From 18ad21bdc88cd45806a3f005d8c1849df972c855 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Fri, 11 Aug 2023 22:27:49 +0400 Subject: [PATCH 01/82] refactor(Haptics): new effects interface [skip ci] --- .clang-format | 2 + lib/arduino/components/serial_plotter.cpp | 2 +- lib/core/types.hpp | 17 +-- lib/core/utility.hpp | 2 +- lib/haptics/haptic_body.cpp | 41 ++++--- lib/haptics/haptic_body.hpp | 27 ++--- lib/haptics/haptic_constants.h | 5 - lib/haptics/haptic_plane.cpp | 127 +++++++++++----------- lib/haptics/haptic_plane.hpp | 127 ++++++++++++++-------- lib/haptics/haptics_interface.hpp | 65 +++++++++++ lib/math/point2.hpp | 56 +++++----- platformio.ini | 2 +- test/test_haptic_body/main.cpp | 69 ------------ test/test_haptics_body/main.cpp | 117 ++++++++++++++++++++ test/test_haptics_plane/main.cpp | 120 +++++++++++--------- test/test_math_point2/main.cpp | 10 ++ 16 files changed, 477 insertions(+), 312 deletions(-) delete mode 100644 lib/haptics/haptic_constants.h create mode 100644 lib/haptics/haptics_interface.hpp delete mode 100644 test/test_haptic_body/main.cpp create mode 100644 test/test_haptics_body/main.cpp diff --git a/.clang-format b/.clang-format index 01908c3b..8972cb76 100644 --- a/.clang-format +++ b/.clang-format @@ -7,6 +7,8 @@ AllowAllConstructorInitializersOnNextLine: 'true' AllowAllParametersOfDeclarationOnNextLine: 'true' AllowShortBlocksOnASingleLine: 'false' AllowShortCaseLabelsOnASingleLine: 'false' +# TODO +# AllowShortFunctionsOnASingleLine: Inline AllowShortFunctionsOnASingleLine: Empty AllowShortIfStatementsOnASingleLine: Never AllowShortLambdasOnASingleLine: Empty diff --git a/lib/arduino/components/serial_plotter.cpp b/lib/arduino/components/serial_plotter.cpp index 4920552e..c3320721 100644 --- a/lib/arduino/components/serial_plotter.cpp +++ b/lib/arduino/components/serial_plotter.cpp @@ -8,7 +8,7 @@ void OH::SerialPlotter_OutputStates<_Tp>::run() oh_output_path_t path = _c.first; OH::HapticPlane* component = _c.second; - for (auto& _s : *component->getOutputStates()) { + for (auto& _s : *component->getActuatorStates()) { oh_output_point_t point = _s.first; oh_output_state_t state = _s.second; diff --git a/lib/core/types.hpp b/lib/core/types.hpp index 60866742..3c51c75f 100644 --- a/lib/core/types.hpp +++ b/lib/core/types.hpp @@ -9,20 +9,5 @@ #define OH_OUTPUT_COORD_MAX UINT8_MAX typedef uint8_t oh_output_path_t; -typedef OH_OUTPUT_COORD_T oh_output_coord_t; +typedef OH_OUTPUT_COORD_T oh_output_coord_t; typedef OH::Point2b oh_output_point_t; - -namespace OH { - struct OutputData { - oh_output_point_t point; - oh_output_intensity_t intensity; - }; - - struct OutputState { - oh_output_intensity_t intensity; - }; -} // namespace OH - -typedef OH::OutputData oh_output_data_t; -typedef OH::OutputState oh_output_state_t; -typedef std::map<oh_output_point_t, OH::AbstractActuator*> oh_output_writers_map_t; diff --git a/lib/core/utility.hpp b/lib/core/utility.hpp index 7a60c5b1..3d40497e 100644 --- a/lib/core/utility.hpp +++ b/lib/core/utility.hpp @@ -30,7 +30,7 @@ namespace OH { }; template<typename _Tp> - inline _Tp accurateMap(_Tp x, _Tp in_min, _Tp in_max, _Tp out_min, _Tp out_max) + constexpr _Tp accurateMap(_Tp x, _Tp in_min, _Tp in_max, _Tp out_min, _Tp out_max) { const _Tp run = in_max - in_min; if (run == 0) { diff --git a/lib/haptics/haptic_body.cpp b/lib/haptics/haptic_body.cpp index 6abee88d..3718ed41 100644 --- a/lib/haptics/haptic_body.cpp +++ b/lib/haptics/haptic_body.cpp @@ -2,24 +2,31 @@ #include <logging.hpp> -void OH::HapticBody::addComponent(const oh_output_path_t path, OH::HapticPlane* c) -{ - this->components[path] = c; -} +namespace SenseShift::Body::Haptics { + void HapticBody::setup() + { + for (auto& [target, plane] : this->vibroTargets) { + plane->setup(); + } + } -std::map<oh_output_path_t, OH::HapticPlane*>* OH::HapticBody::getComponents() -{ - return &this->components; -} + void HapticBody::effect(const EffectRequest_t& effect) + { + if (effect.effect == Effect::Vibro && std::holds_alternative<VibroEffect_t>(effect.data)) { + auto it = this->vibroTargets.find(effect.target); + if (it == this->vibroTargets.end()) { + log_w("No target found for effect: %d", effect.target); + return; + } -void OH::HapticBody::writeOutput(const oh_output_path_t path, const oh_output_data_t& data) -{ - if (this->getComponents()->count(path) == 0) { - // if no requested component exists, skip - log_w("No component found for path %d", path); - return; + it->second->effect(effect.position, std::get<VibroEffect_t>(effect.data)); + } else { + log_w("Non-supported effect type: %d", effect.effect); + } } - auto componentSearch = this->getComponents()->find(path); - (*componentSearch).second->writeOutput(data); -} + void HapticBody::addTarget(const Target_t target, VibroPlane* plane) + { + this->vibroTargets[target] = plane; + } +} // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/haptic_body.hpp b/lib/haptics/haptic_body.hpp index b57b853b..33252535 100644 --- a/lib/haptics/haptic_body.hpp +++ b/lib/haptics/haptic_body.hpp @@ -1,32 +1,27 @@ #pragma once -#include "haptic_constants.h" #include "haptic_plane.hpp" +#include "haptics_interface.hpp" #include <types.hpp> #include <utility.hpp> #include <map> -namespace OH { +namespace SenseShift::Body::Haptics { class HapticBody { - private: - typedef std::map<oh_output_path_t, HapticPlane*> oh_output_components_map_t; - std::map<oh_output_path_t, HapticPlane*> components{}; - public: + typedef std::map<Target_t, VibroPlane*> VibroTargetMap_t; + HapticBody(){}; - void addComponent(const oh_output_path_t, HapticPlane*); - oh_output_components_map_t* getComponents(); + void setup(); - void writeOutput(const oh_output_path_t, const oh_output_data_t&); + void effect(const EffectRequest_t&); - void setup() - { - for (auto& component : this->components) { - component.second->setup(); - } - }; + void addTarget(const Target_t, VibroPlane* plane); + + private: + VibroTargetMap_t vibroTargets{}; }; -} // namespace OH +} // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/haptic_constants.h b/lib/haptics/haptic_constants.h deleted file mode 100644 index 8184df26..00000000 --- a/lib/haptics/haptic_constants.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#define OUTPUT_PATH_CHEST_FRONT 0x00 -#define OUTPUT_PATH_CHEST_BACK 0x01 -#define OUTPUT_PATH_ACCESSORY 0x02 diff --git a/lib/haptics/haptic_plane.cpp b/lib/haptics/haptic_plane.cpp index 95929d94..ddbf0e7b 100644 --- a/lib/haptics/haptic_plane.cpp +++ b/lib/haptics/haptic_plane.cpp @@ -3,79 +3,78 @@ #include <algorithm> #include <logging.hpp> #include <math.h> -#include <utility.hpp> -void OH::HapticPlane::setOutputs(oh_output_writers_map_t& outputs) -{ - this->writers.clear(); - this->writers = outputs; - - this->points.clear(); - for (auto& _p : outputs) { - this->points.push_back(_p.first); - } +#include "haptic_plane.hpp" - this->states.clear(); - for (auto& _p : outputs) { - this->states[_p.first] = {}; +namespace SenseShift::Body::Haptics { + template<typename _Tp> + void ActuativePlane<_Tp>::setActuators(const ActuatorMap_t& 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] = 0; + } } -} -void OH::HapticPlane::setup() -{ - for (const auto& kv : this->writers) { - kv.second->setup(); + template<typename _Tp> + void ActuativePlane<_Tp>::setup() + { + for (const auto& [point, actuator] : this->actuators) { + actuator->setup(); + } } -} -void OH::HapticPlane::writeOutput(const oh_output_data_t& data) -{ - if (this->writers.count(data.point) == 0) { - log_w("No writer for point (%u, %u)", data.point.x, data.point.y); - return; + template<typename _Tp> + void ActuativePlane<_Tp>::effect(const Position_t& pos, const Value_t& val) + { + auto it = this->actuators.find(pos); + if (it == this->actuators.end()) { + log_w("No actuator for point (%u, %u)", pos.x, pos.y); + return; + } + + it->second->writeOutput(val); + this->states[pos] = val; } - auto state = &this->states[data.point]; - state->intensity = data.intensity; - - this->writers.at(data.point)->writeOutput(state->intensity); -} - -oh_output_point_t - OH::HapticPlane_Closest::findClosestPoints(std::list<oh_output_point_t>& pts, const oh_output_point_t& target) -{ - if (contains(pts, target)) { - return target; + template<typename _Tp> + void ActuativePlane_Closest<_Tp>::effect(const Position_t& pos, const Value_t& val) + { + auto& closest = this->findClosestPoint(*this->getAvailablePoints(), pos); + ActuativePlane<_Tp>::effect(closest, val); } - std::multimap<float, oh_output_point_t> mp = {}; - - for (auto& _p : pts) { - float dx = abs(((float) target.x / OH_OUTPUT_COORD_MAX) - ((float) _p.x / OH_OUTPUT_COORD_MAX)), - dy = abs(((float) target.y / OH_OUTPUT_COORD_MAX) - ((float) _p.y / OH_OUTPUT_COORD_MAX)); - - auto dist = (float) sqrt(pow(dx, 2) + pow(dy, 2)); - - mp.insert({ dist, _p }); + template<typename _Tp> + const Position_t& + ActuativePlane_Closest<_Tp>::findClosestPoint(const PositionSet_t& pts, const Position_t& target) const + { + // check if exact point exists + auto it = pts.find(target); + if (it != pts.end()) { + return *it; + } + + // find closest point by square distance + std::multimap<float, Position_t> mp = {}; + for (const auto& _p : pts) { + mp.insert({ (target - _p), _p }); + } + + auto nearest = std::min_element(mp.begin(), mp.end()); + + return nearest->second; } - auto nearest = std::min_element( - mp.begin(), - mp.end(), - [](const std::pair<float, oh_output_point_t>& a, const std::pair<float, oh_output_point_t>& b) { - return a.first < b.first; - } - ); - - return nearest->second; -} - -void OH::HapticPlane_Closest::writeOutput(const oh_output_data_t& data) -{ - auto closestPoint = this->findClosestPoints(this->points, data.point); - - auto state = &this->states[closestPoint]; - state->intensity = data.intensity; - - this->writers.at(closestPoint)->writeOutput(state->intensity); -} + template class ActuativePlane<VibroEffect_t>; + template class ActuativePlane_Closest<VibroEffect_t>; +} // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/haptic_plane.hpp b/lib/haptics/haptic_plane.hpp index 49084195..8f565ef6 100644 --- a/lib/haptics/haptic_plane.hpp +++ b/lib/haptics/haptic_plane.hpp @@ -1,71 +1,96 @@ #pragma once +#include "haptics_interface.hpp" + #include <abstract_actuator.hpp> #include <types.hpp> #include <utility.hpp> #include <list> #include <map> +#include <set> #include <vector> -namespace OH { +namespace SenseShift::Body::Haptics { + typedef std::set<Position_t> PositionSet_t; + /** * Output "plane" (e.g. Chest, Palm, Finger, etc.) + * + * @tparam _Tp The type of the output value. */ - class HapticPlane { - protected: - std::list<oh_output_point_t> points{}; - oh_output_writers_map_t writers{}; - std::map<oh_output_point_t, oh_output_state_t> states{}; - - void setOutputs(oh_output_writers_map_t&); + template<typename _Tp> + class ActuativePlane { + static_assert(std::is_same<_Tp, VibroEffect_t>()); public: - HapticPlane(oh_output_writers_map_t& outputs) + typedef _Tp Value_t; + typedef std::map<Position_t, Value_t> PositionStateMap_t; + + /** + * The type of the actuator. + * @TODO: Make this a template parameter + */ + typedef OH::AbstractActuator Actuator_t; + typedef std::map<Position_t, Actuator_t*> ActuatorMap_t; + + ActuativePlane(const ActuatorMap_t& actuators) { - this->setOutputs(outputs); - }; - std::list<oh_output_point_t>* getOutputPoints(void) + this->setActuators(actuators); + } + + void setup(); + virtual void effect(const Position_t&, const Value_t&); + + [[nodiscard]] const PositionSet_t* getAvailablePoints() const { - return &this->points; - }; - std::map<oh_output_point_t, oh_output_state_t>* getOutputStates(void) + return &points; + } + [[nodiscard]] const PositionStateMap_t* getActuatorStates() const { - return &this->states; - }; - virtual void writeOutput(const oh_output_data_t&); - void setup(); - }; + return &states; + } - class HapticPlane_Closest : public HapticPlane { - protected: - oh_output_point_t findClosestPoints(std::list<oh_output_point_t>& pts, const oh_output_point_t& target); - void setOutputs(oh_output_writers_map_t&); + private: + PositionSet_t points; + ActuatorMap_t actuators{}; + PositionStateMap_t states{}; - public: - HapticPlane_Closest(oh_output_writers_map_t& outputs) : HapticPlane(outputs){}; - void writeOutput(const oh_output_data_t&) override; + void setActuators(const ActuatorMap_t&); }; - class PlaneMapper_Margin { + typedef ActuativePlane<VibroEffect_t> VibroPlane; + + /** + * Output plane, finds the closest actuator for the given point. + * @deprecated We should guarantee on the driver level, that the actuator is always exists + */ + template<typename _Tp> + class ActuativePlane_Closest : public ActuativePlane<_Tp> { public: - /** - * Re-maps a point index to output coordinate. - * @tparam _Tp The type of the point index. - */ - template<typename _Tp> - static inline oh_output_point_t* mapPoint(_Tp x, _Tp y, _Tp x_max, _Tp y_max) - { - const oh_output_coord_t x_coord = simpleMap<_Tp>(x + 1, x_max + 2, OH_OUTPUT_COORD_MAX); - const oh_output_coord_t y_coord = simpleMap<_Tp>(y + 1, y_max + 2, OH_OUTPUT_COORD_MAX); + typedef _Tp Value_t; - return new oh_output_point_t(x_coord, y_coord); + ActuativePlane_Closest(const typename ActuativePlane<_Tp>::ActuatorMap_t& actuators) : + ActuativePlane<_Tp>(actuators) + { } + void effect(const Position_t&, const Value_t&) override; + + private: + [[nodiscard]] const Position_t& findClosestPoint(const PositionSet_t&, const Position_t&) const; + }; + + typedef ActuativePlane_Closest<VibroEffect_t> VibroPlane_Closest; + + // TODO: configurable margin + class PlaneMapper_Margin { + public: template<typename _Tp> - static inline std::map<oh_output_point_t, _Tp*> mapMatrixCoordinates(std::vector<std::vector<_Tp*>> map2d) + [[nodiscard]] static constexpr inline std::map<oh_output_point_t, _Tp*> + mapMatrixCoordinates(std::vector<std::vector<_Tp*>> map2d) { - std::map<oh_output_point_t, _Tp*> points{}; + std::map<Position_t, _Tp*> points{}; size_t y_size = map2d.size(); size_t y_max = y_size - 1; @@ -76,14 +101,28 @@ namespace OH { size_t x_max = x_size - 1; for (size_t x = 0; x < x_size; ++x) { - AbstractActuator* wr = row.at(x); - oh_output_point_t* coord = mapPoint(x, y, x_max, y_max); + auto* wr = row.at(x); + Position_t coord = PlaneMapper_Margin::mapPoint<Position_t::Value_t>(x, y, x_max, y_max); - points[*coord] = wr; + points[coord] = wr; } } return points; } + + /** + * Re-maps a point index to output coordinate. + * @tparam _Tp The type of the point index. + */ + template<typename _Tp> + [[nodiscard]] static constexpr inline OH::Point2<_Tp> mapPoint(_Tp x, _Tp y, _Tp x_max, _Tp y_max) + { + using Point_t = OH::Point2<_Tp>; + return Point_t( + OH::accurateMap<_Tp>(x + 1, 0, x_max + 2, Point_t::MIN, Point_t::MAX), + OH::accurateMap<_Tp>(y + 1, 0, y_max + 2, Point_t::MIN, Point_t::MAX) + ); + } }; -} // namespace OH +} // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/haptics_interface.hpp b/lib/haptics/haptics_interface.hpp new file mode 100644 index 00000000..f6734c76 --- /dev/null +++ b/lib/haptics/haptics_interface.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include <stdint.h> +#include <variant> + +#include <point2.hpp> + +namespace SenseShift::Body::Haptics { + typedef uint8_t EffectIntex_t; + static const EffectIntex_t EFFECT_INVALID = 0xFF; + typedef enum class Effect : EffectIntex_t { + Invalid = EFFECT_INVALID, + Vibro = 0x00, + // TODO: thermal, etc. + // Thermal = 0x01, + } Effect_t; + + typedef uint8_t TargetIndex_t; + static const TargetIndex_t TARGET_INVALID = 0xFF; + typedef enum class Target : TargetIndex_t { + Invalid = TARGET_INVALID, + ChestFront = 0x00, + ChestBack = 0x01, + // Legacy backword compatibility + Accessory [[deprecated]] = 0x02, + + // TODO: arms, legs, etc. + } Target_t; + + typedef uint8_t Coordinate_t; + typedef OH::Point2<Coordinate_t> Position_t; + + // Vibration intensity. + typedef struct VibroEffect { + using Intensity_t = uint16_t; + inline static const Intensity_t INTENSITY_MIN = 0; + inline static const Intensity_t INTENSITY_MAX = 4095; + + Intensity_t intensity = 0; + + inline constexpr VibroEffect() = default; + inline constexpr VibroEffect(Intensity_t intensity) : intensity(intensity) {} + inline constexpr VibroEffect(const VibroEffect& other) = default; + + inline constexpr operator uint16_t() const + { + return intensity; + } + } VibroEffect_t; + + // TODO: thermal, etc. + + typedef std::variant<VibroEffect_t + // TODO: thermal, etc. + // ThermalEffect_t + > + EffectData_t; + + typedef struct EffectRequest { + Effect_t effect = Effect::Invalid; + Target_t target = Target::Invalid; + Position_t position = Position_t(0, 0); + EffectData_t data; + } EffectRequest_t; +} // namespace SenseShift::Body::Haptics diff --git a/lib/math/point2.hpp b/lib/math/point2.hpp index 04db618d..0cf151b8 100644 --- a/lib/math/point2.hpp +++ b/lib/math/point2.hpp @@ -1,19 +1,43 @@ #pragma once +#include <cmath> #include <tuple> namespace OH { template<typename _Tp> struct Point2 { - _Tp x, y; + static_assert(std::is_arithmetic<_Tp>::value, "OH::Point2 only can be used with arithmetic types"); + + typedef _Tp Value_t; - Point2() : x((_Tp) 0), y((_Tp) 0){}; - Point2(_Tp x, _Tp y) : x(x), y(y){}; - Point2(const Point2<_Tp>& v) : x((_Tp) v.x), y((_Tp) v.y){}; + inline static const _Tp MIN = std::numeric_limits<_Tp>::min(); + inline static const _Tp MAX = std::numeric_limits<_Tp>::max(); - bool operator==(const Point2& rhs) const; - bool operator!=(const Point2& rhs) const; - bool operator<(const Point2& rhs) const; + _Tp x, y; + + constexpr Point2() : x((_Tp) 0), y((_Tp) 0){}; + constexpr Point2(_Tp x, _Tp y) : x(x), y(y){}; + constexpr Point2(const Point2<_Tp>& v) : x((_Tp) v.x), y((_Tp) v.y){}; + + constexpr inline bool operator==(const Point2<_Tp>& rhs) const + { + return x == rhs.x && y == rhs.y; + } + + constexpr inline bool operator!=(const Point2<_Tp>& rhs) const + { + return !(*this == rhs); + } + + constexpr bool operator<(const Point2<_Tp>& rhs) const + { + return std::tie(x, y) < std::tie(rhs.x, rhs.y); + } + + constexpr float operator-(const Point2<_Tp>& rhs) const + { + return std::sqrt(std::pow(x - rhs.x, 2) + std::pow(y - rhs.y, 2)); + } }; typedef Point2<unsigned char> Point2b; @@ -22,22 +46,4 @@ namespace OH { typedef Point2<int> Point2i; typedef Point2<short> Point2s; typedef Point2<unsigned short> Point2w; - - template<typename _Tp> - inline bool Point2<_Tp>::operator==(const Point2<_Tp>& rhs) const - { - return x == rhs.x && y == rhs.y; - } - - template<typename _Tp> - inline bool Point2<_Tp>::operator!=(const Point2<_Tp>& rhs) const - { - return !(*this == rhs); - } - - template<typename _Tp> - inline bool Point2<_Tp>::operator<(const Point2<_Tp>& rhs) const - { - return std::tie(x, y) < std::tie(rhs.x, rhs.y); - } }; // namespace OH diff --git a/platformio.ini b/platformio.ini index e6e18eec..f88d3a17 100644 --- a/platformio.ini +++ b/platformio.ini @@ -67,6 +67,6 @@ build_flags = ${common.build_flags} build_src_filter = ${common.build_src_filter} +<mode_configs/test.cpp> lib_deps = ${common.lib_deps} - fabiobatsilva/ArduinoFake@^0.3.1 + fabiobatsilva/ArduinoFake@^0.4 test_ignore = test_embedded diff --git a/test/test_haptic_body/main.cpp b/test/test_haptic_body/main.cpp deleted file mode 100644 index 81bd6492..00000000 --- a/test/test_haptic_body/main.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include <haptic_body.hpp> -#include <unity.h> - -using namespace OH; - -class TestActuator : public AbstractActuator { - public: - bool isSetup = false; - oh_output_intensity_t intensity = 0; - - TestActuator() : AbstractActuator() {} - void setup() override - { - this->isSetup = true; - } - void writeOutput(oh_output_intensity_t intensity) override - { - this->intensity = intensity; - } -}; - -void test_it_sets_up_planes(void) -{ - auto body = new HapticBody(); - - oh_output_writers_map_t outputs = { - { { 0, 0 }, new TestActuator() }, - { { 0, 1 }, new TestActuator() }, - { { 1, 0 }, new TestActuator() }, - { { 1, 1 }, new TestActuator() }, - }; - auto plane = new HapticPlane(outputs); - - body->addComponent(0, plane); - body->setup(); - - for (auto& kv : outputs) { - TEST_ASSERT_TRUE(static_cast<TestActuator*>(kv.second)->isSetup); - } -} - -int process(void) -{ - UNITY_BEGIN(); - - RUN_TEST(test_it_sets_up_planes); - - return UNITY_END(); -} - -#ifdef ARDUINO - -#include <Arduino.h> - -void setup(void) -{ - process(); -} - -void loop(void) {} - -#else - -int main(int argc, char** argv) -{ - return process(); -} - -#endif diff --git a/test/test_haptics_body/main.cpp b/test/test_haptics_body/main.cpp new file mode 100644 index 00000000..d16ed628 --- /dev/null +++ b/test/test_haptics_body/main.cpp @@ -0,0 +1,117 @@ +#include <haptic_body.hpp> +#include <unity.h> + +using namespace SenseShift::Body::Haptics; + +class TestActuator : public OH::AbstractActuator { + public: + bool isSetup = false; + oh_output_intensity_t intensity = 0; + + TestActuator() : AbstractActuator() {} + void setup() override + { + this->isSetup = true; + } + void writeOutput(oh_output_intensity_t intensity) override + { + this->intensity = intensity; + } +}; + +void test_it_sets_up_planes(void) +{ + auto body = new HapticBody(); + + VibroPlane::ActuatorMap_t outputs = { + { { 0, 0 }, new TestActuator() }, + { { 0, 1 }, new TestActuator() }, + { { 1, 0 }, new TestActuator() }, + { { 1, 1 }, new TestActuator() }, + }; + auto plane = new VibroPlane(outputs); + + body->addTarget(Target::ChestFront, plane); + body->setup(); + + for (auto& kv : outputs) { + TEST_ASSERT_TRUE_MESSAGE(static_cast<TestActuator*>(kv.second)->isSetup, "Actuator was not setup"); + } +} + +void test_it_handles_effect__vibro(void) +{ + auto actuator1 = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), + actuator4 = new TestActuator(); + + auto body = new HapticBody(); + + auto plane = new VibroPlane({ + { { 0, 0 }, actuator1 }, + { { 0, 1 }, actuator2 }, + { { 1, 0 }, actuator3 }, + { { 1, 1 }, actuator4 }, + }); + + body->addTarget(Target::ChestFront, plane); + + body->effect({ + .effect = Effect::Vibro, + .target = Target::ChestFront, + .position = { 0, 0 }, + .data = (VibroEffect_t) 64, + }); + body->effect({ + .effect = Effect::Vibro, + .target = Target::ChestFront, + .position = { 0, 1 }, + .data = (VibroEffect_t) 128, + }); + body->effect({ + .effect = Effect::Vibro, + .target = Target::ChestFront, + .position = { 1, 0 }, + .data = (VibroEffect_t) 192, + }); + body->effect({ + .effect = Effect::Vibro, + .target = Target::ChestFront, + .position = { 1, 1 }, + .data = (VibroEffect_t) 255, + }); + + TEST_ASSERT_EQUAL(64, actuator1->intensity); + TEST_ASSERT_EQUAL(128, actuator2->intensity); + TEST_ASSERT_EQUAL(192, actuator3->intensity); + TEST_ASSERT_EQUAL(255, actuator4->intensity); +} + +int process(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_it_sets_up_planes); + RUN_TEST(test_it_handles_effect__vibro); + + return UNITY_END(); +} + +#ifdef ARDUINO + +#include <Arduino.h> + +void setup(void) +{ + process(); +} + +void loop(void) {} + +#else + +int main(int argc, char** argv) +{ + return process(); +} + +#endif diff --git a/test/test_haptics_plane/main.cpp b/test/test_haptics_plane/main.cpp index 6077cf80..ec1af818 100644 --- a/test/test_haptics_plane/main.cpp +++ b/test/test_haptics_plane/main.cpp @@ -1,9 +1,9 @@ #include <haptic_plane.hpp> #include <unity.h> -using namespace OH; +using namespace SenseShift::Body::Haptics; -class TestActuator : public AbstractActuator { +class TestActuator : public OH::AbstractActuator { public: bool isSetup = false; oh_output_intensity_t intensity = 0; @@ -21,18 +21,21 @@ class TestActuator : public AbstractActuator { void test_it_sets_up_actuators(void) { - oh_output_writers_map_t outputs = { + VibroPlane::ActuatorMap_t outputs = { { { 0, 0 }, new TestActuator() }, { { 0, 1 }, new TestActuator() }, { { 1, 0 }, new TestActuator() }, { { 1, 1 }, new TestActuator() }, }; - auto plane = new HapticPlane(outputs); + auto plane = new VibroPlane(outputs); plane->setup(); + TEST_ASSERT_EQUAL(outputs.size(), plane->getAvailablePoints()->size()); for (auto& kv : outputs) { - TEST_ASSERT_TRUE(static_cast<TestActuator*>(kv.second)->isSetup); + TEST_ASSERT_TRUE_MESSAGE(plane->getAvailablePoints()->count(kv.first) > 0, "Expected point was not found"); + TEST_ASSERT_TRUE_MESSAGE(plane->getActuatorStates()->count(kv.first) > 0, "Expected state was not found"); + TEST_ASSERT_TRUE_MESSAGE(static_cast<TestActuator*>(kv.second)->isSetup, "Actuator was not setup"); } } @@ -41,20 +44,19 @@ void test_it_writes_to_correct_output(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - oh_output_writers_map_t outputs = { + VibroPlane::ActuatorMap_t outputs = { { { 0, 0 }, actuator }, { { 0, 1 }, actuator2 }, { { 1, 0 }, actuator3 }, { { 1, 1 }, actuator4 }, }; - auto plane = new HapticPlane(outputs); - plane->setup(); + auto plane = new VibroPlane(outputs); - plane->writeOutput({ { 0, 0 }, 64 }); - plane->writeOutput({ { 0, 1 }, 128 }); - plane->writeOutput({ { 1, 0 }, 192 }); - plane->writeOutput({ { 1, 1 }, 255 }); + plane->effect({ 0, 0 }, 64); + plane->effect({ 0, 1 }, 128); + plane->effect({ 1, 0 }, 192); + plane->effect({ 1, 1 }, 255); TEST_ASSERT_EQUAL_UINT8(64, actuator->intensity); TEST_ASSERT_EQUAL_UINT8(128, actuator2->intensity); @@ -67,25 +69,31 @@ void test_it_updates_state(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - oh_output_writers_map_t outputs = { + VibroPlane::ActuatorMap_t outputs = { { { 0, 0 }, actuator }, { { 0, 1 }, actuator2 }, { { 1, 0 }, actuator3 }, { { 1, 1 }, actuator4 }, }; - auto plane = new HapticPlane(outputs); - plane->setup(); + auto plane = new VibroPlane(outputs); + + plane->effect({ 0, 0 }, 64); + plane->effect({ 0, 1 }, 128); + plane->effect({ 1, 0 }, 192); + plane->effect({ 1, 1 }, 255); + + TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 0, 0 }) > 0); + TEST_ASSERT_EQUAL_UINT8(64, plane->getActuatorStates()->at({ 0, 0 })); - plane->writeOutput({ { 0, 0 }, 64 }); - plane->writeOutput({ { 0, 1 }, 128 }); - plane->writeOutput({ { 1, 0 }, 192 }); - plane->writeOutput({ { 1, 1 }, 255 }); + TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 0, 1 }) > 0); + TEST_ASSERT_EQUAL_UINT8(128, plane->getActuatorStates()->at({ 0, 1 })); - TEST_ASSERT_EQUAL_UINT8(64, plane->getOutputStates()->at({ 0, 0 }).intensity); - TEST_ASSERT_EQUAL_UINT8(128, plane->getOutputStates()->at({ 0, 1 }).intensity); - TEST_ASSERT_EQUAL_UINT8(192, plane->getOutputStates()->at({ 1, 0 }).intensity); - TEST_ASSERT_EQUAL_UINT8(255, plane->getOutputStates()->at({ 1, 1 }).intensity); + TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 1, 0 }) > 0); + TEST_ASSERT_EQUAL_UINT8(192, plane->getActuatorStates()->at({ 1, 0 })); + + TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 1, 1 }) > 0); + TEST_ASSERT_EQUAL_UINT8(255, plane->getActuatorStates()->at({ 1, 1 })); } void test_closest_it_writes_to_correct_if_exact(void) @@ -93,20 +101,19 @@ void test_closest_it_writes_to_correct_if_exact(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - oh_output_writers_map_t outputs = { + VibroPlane_Closest::ActuatorMap_t outputs = { { { 0, 0 }, actuator }, { { 0, 1 }, actuator2 }, { { 1, 0 }, actuator3 }, { { 1, 1 }, actuator4 }, }; - auto plane = new HapticPlane_Closest(outputs); - plane->setup(); + auto plane = new VibroPlane_Closest(outputs); - plane->writeOutput({ { 0, 0 }, 1 }); - plane->writeOutput({ { 0, 1 }, 2 }); - plane->writeOutput({ { 1, 0 }, 3 }); - plane->writeOutput({ { 1, 1 }, 4 }); + plane->effect({ 0, 0 }, 1); + plane->effect({ 0, 1 }, 2); + plane->effect({ 1, 0 }, 3); + plane->effect({ 1, 1 }, 4); TEST_ASSERT_EQUAL(1, actuator->intensity); TEST_ASSERT_EQUAL(2, actuator2->intensity); @@ -119,18 +126,17 @@ void test_closest_it_correctly_finds_closest(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - oh_output_writers_map_t outputs = { + VibroPlane_Closest::ActuatorMap_t outputs = { { { 0, 0 }, actuator }, { { 0, 64 }, actuator2 }, { { 64, 0 }, actuator3 }, { { 64, 64 }, actuator4 }, }; - auto plane = new HapticPlane_Closest(outputs); - plane->setup(); + auto plane = new VibroPlane_Closest(outputs); - plane->writeOutput({ { 16, 16 }, 16 }); - plane->writeOutput({ { 65, 65 }, 65 }); + plane->effect({ 16, 16 }, 16); + plane->effect({ 65, 65 }, 65); TEST_ASSERT_EQUAL(16, actuator->intensity); TEST_ASSERT_EQUAL(0, actuator2->intensity); @@ -143,41 +149,47 @@ void test_closest_it_updates_state(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - oh_output_writers_map_t outputs = { + VibroPlane_Closest::ActuatorMap_t outputs = { { { 0, 0 }, actuator }, { { 0, 64 }, actuator2 }, { { 64, 0 }, actuator3 }, { { 64, 64 }, actuator4 }, }; - auto plane = new HapticPlane_Closest(outputs); - plane->setup(); + auto plane = new VibroPlane_Closest(outputs); + + plane->effect({ 16, 16 }, 16); + plane->effect({ 65, 65 }, 65); + + TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 0, 0 }) > 0); + TEST_ASSERT_EQUAL(16, plane->getActuatorStates()->at({ 0, 0 })); - plane->writeOutput({ { 16, 16 }, 16 }); - plane->writeOutput({ { 65, 65 }, 65 }); + TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 0, 64 }) > 0); + TEST_ASSERT_EQUAL(0, plane->getActuatorStates()->at({ 0, 64 })); - TEST_ASSERT_EQUAL(16, plane->getOutputStates()->at({ 0, 0 }).intensity); - TEST_ASSERT_EQUAL(0, plane->getOutputStates()->at({ 0, 64 }).intensity); - TEST_ASSERT_EQUAL(0, plane->getOutputStates()->at({ 64, 0 }).intensity); - TEST_ASSERT_EQUAL(65, plane->getOutputStates()->at({ 64, 64 }).intensity); + TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 64, 0 }) > 0); + TEST_ASSERT_EQUAL(0, plane->getActuatorStates()->at({ 64, 0 })); + + TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 64, 64 }) > 0); + TEST_ASSERT_EQUAL(65, plane->getActuatorStates()->at({ 64, 64 })); } void test_plain_mapper_margin_map_points(void) { - auto point = PlaneMapper_Margin::mapPoint(0, 0, 0, 0); + auto point = PlaneMapper_Margin::mapPoint<uint8_t>(0, 0, 0, 0); - TEST_ASSERT_EQUAL(127, point->x); - TEST_ASSERT_EQUAL(127, point->y); + TEST_ASSERT_EQUAL(127, point.x); + TEST_ASSERT_EQUAL(127, point.y); - point = PlaneMapper_Margin::mapPoint(0, 0, 1, 1); + point = PlaneMapper_Margin::mapPoint<uint8_t>(0, 0, 1, 1); - TEST_ASSERT_EQUAL(85, point->x); - TEST_ASSERT_EQUAL(85, point->y); + TEST_ASSERT_EQUAL(85, point.x); + TEST_ASSERT_EQUAL(85, point.y); - point = PlaneMapper_Margin::mapPoint(1, 1, 1, 1); + point = PlaneMapper_Margin::mapPoint<uint8_t>(1, 1, 1, 1); - TEST_ASSERT_EQUAL(170, point->x); - TEST_ASSERT_EQUAL(170, point->y); + TEST_ASSERT_EQUAL(170, point.x); + TEST_ASSERT_EQUAL(170, point.y); } int process(void) @@ -187,9 +199,11 @@ int process(void) RUN_TEST(test_it_sets_up_actuators); RUN_TEST(test_it_writes_to_correct_output); RUN_TEST(test_it_updates_state); + RUN_TEST(test_closest_it_writes_to_correct_if_exact); RUN_TEST(test_closest_it_correctly_finds_closest); RUN_TEST(test_closest_it_updates_state); + RUN_TEST(test_plain_mapper_margin_map_points); return UNITY_END(); diff --git a/test/test_math_point2/main.cpp b/test/test_math_point2/main.cpp index 48378b18..8da8b3dd 100644 --- a/test/test_math_point2/main.cpp +++ b/test/test_math_point2/main.cpp @@ -33,6 +33,15 @@ void test_operator_less_than(void) TEST_ASSERT_TRUE(p1 < p3); } +void test_operator_minus(void) +{ + Point2 p1 = { 32, 32 }; + Point2 p2 = { 16, 16 }; + + TEST_ASSERT_EQUAL_FLOAT(p1 - p2, p2 - p1); + TEST_ASSERT_EQUAL_FLOAT(22.6274, p1 - p2); +} + int process(void) { UNITY_BEGIN(); @@ -40,6 +49,7 @@ int process(void) RUN_TEST(test_operator_equal); RUN_TEST(test_operator_not_equal); RUN_TEST(test_operator_less_than); + RUN_TEST(test_operator_minus); return UNITY_END(); } From 2394497e1041e4f0e7ea2d4ed2803a0db5cec098 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sat, 12 Aug 2023 02:22:17 +0400 Subject: [PATCH 02/82] refactor(bHaptics): use new Haptics interfafce --- lib/bhaptics/bh_constants.hpp | 86 ++++++++-------- lib/bhaptics/bh_utils.cpp | 114 ++++++++++----------- lib/bhaptics/bh_utils.hpp | 40 ++++++-- lib/core/types.hpp | 2 +- test/test_bhaptics/main.cpp | 188 ++++++---------------------------- 5 files changed, 164 insertions(+), 266 deletions(-) diff --git a/lib/bhaptics/bh_constants.hpp b/lib/bhaptics/bh_constants.hpp index 92e8ec60..b28f53e3 100644 --- a/lib/bhaptics/bh_constants.hpp +++ b/lib/bhaptics/bh_constants.hpp @@ -1,5 +1,7 @@ #pragma once +#include <haptic_plane.hpp> + #if defined(ESP32) #include <BLEUUID.h> #endif @@ -17,12 +19,12 @@ #define BH_LAYOUT_TACTSUITX16_SIZE_X 4 #define BH_LAYOUT_TACTSUITX16_SIZE_Y 2 -#define BH_LAYOUT_TACTSUITX16_MAKE_POINT(x, y) \ - OH::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX16_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX16_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTSUITX16_MAKE_POINT(x, y) \ + SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + x, \ + y, \ + (oh_output_coord_t) (BH_LAYOUT_TACTSUITX16_SIZE_X - 1), \ + (oh_output_coord_t) (BH_LAYOUT_TACTSUITX16_SIZE_Y - 1) \ ) // X16 suit uses the same packets structure as x40 suit and performs motor grouping in firmware @@ -95,12 +97,12 @@ #define BH_LAYOUT_TACTSUITX40_SIZE_X 4 #define BH_LAYOUT_TACTSUITX40_SIZE_Y 5 -#define BH_LAYOUT_TACTSUITX40_MAKE_POINT(x, y) \ - OH::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTSUITX40_MAKE_POINT(x, y) \ + SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + x, \ + y, \ + (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_X - 1), \ + (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_Y - 1) \ ) // X * Y for front and back @@ -162,12 +164,12 @@ #define BH_LAYOUT_TACTAL_SIZE_X 6 #define BH_LAYOUT_TACTAL_SIZE_Y 1 -#define BH_LAYOUT_TACTAL_MAKE_POINT(x, y) \ - OH::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTAL_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTAL_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTAL_MAKE_POINT(x, y) \ + SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + x, \ + y, \ + (oh_output_coord_t) (BH_LAYOUT_TACTAL_SIZE_X - 1), \ + (oh_output_coord_t) (BH_LAYOUT_TACTAL_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTAL_SIZE (BH_LAYOUT_TACTAL_SIZE_X * BH_LAYOUT_TACTAL_SIZE_Y) @@ -188,12 +190,12 @@ #define BH_LAYOUT_TACTVISOR_SIZE_X 4 #define BH_LAYOUT_TACTVISOR_SIZE_Y 1 -#define BH_LAYOUT_TACTVISOR_MAKE_POINT(x, y) \ - OH::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTVISOR_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTVISOR_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTVISOR_MAKE_POINT(x, y) \ + SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + x, \ + y, \ + (oh_output_coord_t) (BH_LAYOUT_TACTVISOR_SIZE_X - 1), \ + (oh_output_coord_t) (BH_LAYOUT_TACTVISOR_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTVISOR_SIZE (BH_LAYOUT_TACTVISOR_SIZE_X * BH_LAYOUT_TACTVISOR_SIZE_Y) @@ -212,12 +214,12 @@ #define BH_LAYOUT_TACTOSY2_SIZE_X 3 #define BH_LAYOUT_TACTOSY2_SIZE_Y 2 -#define BH_LAYOUT_TACTOSY2_MAKE_POINT(x, y) \ - OH::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSY2_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSY2_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTOSY2_MAKE_POINT(x, y) \ + SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + x, \ + y, \ + (oh_output_coord_t) (BH_LAYOUT_TACTOSY2_SIZE_X - 1), \ + (oh_output_coord_t) (BH_LAYOUT_TACTOSY2_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTOSY2_SIZE (BH_LAYOUT_TACTOSY2_SIZE_X * BH_LAYOUT_TACTOSY2_SIZE_Y) @@ -234,12 +236,12 @@ #define BH_LAYOUT_TACTOSYH_SIZE_X 1 #define BH_LAYOUT_TACTOSYH_SIZE_Y 3 -#define BH_LAYOUT_TACTOSYH_MAKE_POINT(x, y) \ - OH::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSYH_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSYH_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTOSYH_MAKE_POINT(x, y) \ + SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + x, \ + y, \ + (oh_output_coord_t) (BH_LAYOUT_TACTOSYH_SIZE_X - 1), \ + (oh_output_coord_t) (BH_LAYOUT_TACTOSYH_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTOSYH_SIZE (BH_LAYOUT_TACTOSYH_SIZE_X * BH_LAYOUT_TACTOSYH_SIZE_Y) @@ -253,12 +255,12 @@ #define BH_LAYOUT_TACTOSYF_SIZE_X 1 #define BH_LAYOUT_TACTOSYF_SIZE_Y 3 -#define BH_LAYOUT_TACTOSYF_MAKE_POINT(x, y) \ - OH::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSYF_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSYF_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTOSYF_MAKE_POINT(x, y) \ + SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + x, \ + y, \ + (oh_output_coord_t) (BH_LAYOUT_TACTOSYF_SIZE_X - 1), \ + (oh_output_coord_t) (BH_LAYOUT_TACTOSYF_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTOSYF_SIZE (BH_LAYOUT_TACTOSYF_SIZE_X * BH_LAYOUT_TACTOSYF_SIZE_Y) diff --git a/lib/bhaptics/bh_utils.cpp b/lib/bhaptics/bh_utils.cpp index 710e53a5..d1a4654a 100644 --- a/lib/bhaptics/bh_utils.cpp +++ b/lib/bhaptics/bh_utils.cpp @@ -2,60 +2,54 @@ #include <utility.hpp> -void BH::plainOutputTransformer( - OH::HapticBody* output, - std::string& value, - const oh_output_point_t* layout[], - const size_t layoutSize, - const oh_output_path_t path -) -{ - for (size_t i = 0; i < layoutSize; i++) { - uint8_t byte = value[i]; - - oh_output_data_t outputData{ - .point = *layout[i], - // TODO: optimize generic type - .intensity = - static_cast<oh_output_intensity_t>(OH::accurateMap<long>(byte, 0, 100, 0, OH_OUTPUT_INTENSITY_MAX)), - }; - - output->writeOutput(path, outputData); +namespace BH { + template<size_t N = 20> + void vestOutputTransformer( + SenseShift::Body::Haptics::HapticBody* output, const char (&value)[N], const oh_output_point_t (&layout)[N * 2] + ) + { + for (size_t i = 0; i < N; i++) { + uint8_t byte = value[i]; + uint actIndex = i * 2; + const auto target = (actIndex < 10 || actIndex >= 30) ? SenseShift::Body::Haptics::Target::ChestFront + : SenseShift::Body::Haptics::Target::ChestBack; + + output->effect({ + .effect = SenseShift::Body::Haptics::Effect::Vibro, + .target = target, + .position = layout[actIndex], + .data = SenseShift::Body::Haptics::VibroEffect( + OH::simpleMap<SenseShift::Body::Haptics::VibroEffect::Intensity_t>( + ((byte >> 4) & 0xf), + 15, + SenseShift::Body::Haptics::VibroEffect::INTENSITY_MAX + ) + ), + }); + output->effect({ + .effect = SenseShift::Body::Haptics::Effect::Vibro, + .target = target, + .position = layout[actIndex + 1], + .data = SenseShift::Body::Haptics::VibroEffect( + OH::simpleMap<SenseShift::Body::Haptics::VibroEffect::Intensity_t>( + (byte & 0xf), + 15, + SenseShift::Body::Haptics::VibroEffect::INTENSITY_MAX + ) + ), + }); + } } -} - -void BH::vestOutputTransformer( - OH::HapticBody* output, std::string& value, const oh_output_point_t* layout[], const size_t layoutSize -) -{ - for (size_t i = 0; i < layoutSize / 2; i++) { - uint8_t byte = value[i]; - uint actIndex = i * 2; - const auto path = (actIndex < 10 || actIndex >= 30) ? OUTPUT_PATH_CHEST_FRONT : OUTPUT_PATH_CHEST_BACK; - - const oh_output_data_t outputData0{ - .point = *layout[actIndex], - // TODO: optimize generic type - .intensity = - static_cast<oh_output_intensity_t>(OH::simpleMap<long>(((byte >> 4) & 0xf), 15, OH_OUTPUT_INTENSITY_MAX)), - }; - const oh_output_data_t outputData1{ - .point = *layout[actIndex + 1], - // TODO: optimize generic type - .intensity = - static_cast<oh_output_intensity_t>(OH::simpleMap<long>((byte & 0xf), 15, OH_OUTPUT_INTENSITY_MAX)), - }; - - output->writeOutput(path, outputData0); - output->writeOutput(path, outputData1); - } -} + template void vestOutputTransformer<20>( + SenseShift::Body::Haptics::HapticBody* output, const char (&value)[20], const oh_output_point_t (&layout)[40] + ); +} // namespace BH void BH::vestX16OutputTransformer( - OH::HapticBody* output, - std::string& value, - const oh_output_point_t* layout[], + SenseShift::Body::Haptics::HapticBody* output, + const std::string& value, + const oh_output_point_t* layout, const size_t layoutSize, const uint8_t layoutGroups[], const size_t layoutGroupsSize @@ -98,14 +92,16 @@ void BH::vestX16OutputTransformer( continue; } - const auto path = (i < 10 || i >= 30) ? OUTPUT_PATH_CHEST_FRONT : OUTPUT_PATH_CHEST_BACK; - const oh_output_data_t outputData{ - .point = *layout[i], - // TODO: optimize generic type - .intensity = - static_cast<oh_output_intensity_t>(OH::accurateMap<long>(result[i], 0, 15, 0, OH_OUTPUT_INTENSITY_MAX)), - }; - - output->writeOutput(path, outputData); + const auto target = (i < 10 || i >= 30) ? SenseShift::Body::Haptics::Target::ChestFront + : SenseShift::Body::Haptics::Target::ChestBack; + + output->effect({ + .effect = SenseShift::Body::Haptics::Effect::Vibro, + .target = target, + .position = layout[i], + .data = SenseShift::Body::Haptics::VibroEffect( + static_cast<oh_output_intensity_t>(OH::accurateMap<long>(result[i], 0, 15, 0, OH_OUTPUT_INTENSITY_MAX)) + ), + }); } } diff --git a/lib/bhaptics/bh_utils.hpp b/lib/bhaptics/bh_utils.hpp index b1b42fd6..2825aea7 100644 --- a/lib/bhaptics/bh_utils.hpp +++ b/lib/bhaptics/bh_utils.hpp @@ -4,20 +4,40 @@ #include <string> namespace BH { + template<size_t N> void plainOutputTransformer( - OH::HapticBody* output, - std::string& value, - const oh_output_point_t* layout[], - const size_t layoutSize, - const oh_output_path_t path - ); + SenseShift::Body::Haptics::HapticBody* output, + const char (&value)[N], + const oh_output_point_t (&layout)[N], + const SenseShift::Body::Haptics::Target_t target + ) + { + for (size_t i = 0; i < N; i++) { + uint8_t byte = value[i]; + + output->effect({ + .effect = SenseShift::Body::Haptics::Effect::Vibro, + .target = target, + .position = layout[i], + .data = SenseShift::Body::Haptics::VibroEffect( + OH::simpleMap<SenseShift::Body::Haptics::VibroEffect::Intensity_t>( + byte, + 100, + SenseShift::Body::Haptics::VibroEffect::INTENSITY_MAX + ) + ), + }); + } + } + + template<size_t N = 20> void vestOutputTransformer( - OH::HapticBody* output, std::string& value, const oh_output_point_t* layout[], const size_t layoutSize + SenseShift::Body::Haptics::HapticBody* output, const char (&value)[N], const oh_output_point_t (&layout)[N * 2] ); void vestX16OutputTransformer( - OH::HapticBody* output, - std::string& value, - const oh_output_point_t* layout[], + SenseShift::Body::Haptics::HapticBody* output, + const std::string& value, + const oh_output_point_t* layout, const size_t layoutSize, const uint8_t layoutGroups[], const size_t layoutGroupsSize diff --git a/lib/core/types.hpp b/lib/core/types.hpp index 3c51c75f..ed2c7a20 100644 --- a/lib/core/types.hpp +++ b/lib/core/types.hpp @@ -9,5 +9,5 @@ #define OH_OUTPUT_COORD_MAX UINT8_MAX typedef uint8_t oh_output_path_t; -typedef OH_OUTPUT_COORD_T oh_output_coord_t; +typedef OH_OUTPUT_COORD_T oh_output_coord_t; typedef OH::Point2b oh_output_point_t; diff --git a/test/test_bhaptics/main.cpp b/test/test_bhaptics/main.cpp index 1725cca1..1cc22a18 100644 --- a/test/test_bhaptics/main.cpp +++ b/test/test_bhaptics/main.cpp @@ -1,12 +1,13 @@ #include <bh_types.hpp> #include <bh_utils.hpp> -#include <haptic_plane.hpp> + #include <unity.h> +using namespace SenseShift::Body::Haptics; using namespace OH; using namespace BH; -class TestActuator : public AbstractActuator { +class TestActuator : public OH::AbstractActuator { public: bool isSetup = false; oh_output_intensity_t intensity = 0; @@ -25,7 +26,7 @@ class TestActuator : public AbstractActuator { void test_layout_tactsuitx16(void) { static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; - static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX16; + static const oh_output_point_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX16; static const size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; static const uint8_t layoutGroups[layoutGroupsSize] = BH_LAYOUT_TACTSUITX16_GROUPS; @@ -49,7 +50,7 @@ void test_layout_tactsuitx16(void) TestActuator* actuator14 = new TestActuator(); TestActuator* actuator15 = new TestActuator(); - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<OH::AbstractActuator>({ { actuator0, actuator1, actuator2, actuator3 }, { actuator4, actuator5, actuator6, actuator7 }, }); @@ -58,12 +59,12 @@ void test_layout_tactsuitx16(void) { actuator12, actuator13, actuator14, actuator15 }, }); - auto frontPlane = new HapticPlane(frontOutputs); - auto backPlane = new HapticPlane(backOutputs); + auto frontPlane = new VibroPlane(frontOutputs); + auto backPlane = new VibroPlane(backOutputs); - body->addComponent(OUTPUT_PATH_CHEST_FRONT, frontPlane); - body->addComponent(OUTPUT_PATH_CHEST_BACK, backPlane); - body->setup(); + body->addTarget(Target::ChestFront, frontPlane); + body->addTarget(Target::ChestBack, backPlane); + // body->setup(); uint8_t values[] = { 0x01, 0x00, 0x23, 0x00, 0x00, 0x45, 0x00, 0x67, 0x00, 0x00, @@ -94,7 +95,7 @@ void test_layout_tactsuitx16(void) void test_layout_tactsuitx40(void) { static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX40_SIZE; - static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; + static const oh_output_point_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; auto body = new HapticBody(); @@ -116,20 +117,21 @@ void test_layout_tactsuitx40(void) auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>(frontMatrix); auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>(backMatrix); - auto frontPlane = new HapticPlane(frontOutputs); - auto backPlane = new HapticPlane(backOutputs); - - body->addComponent(OUTPUT_PATH_CHEST_FRONT, frontPlane); - body->addComponent(OUTPUT_PATH_CHEST_BACK, backPlane); - body->setup(); - - uint8_t values[] = { - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - std::string value = std::string((char*) values, sizeof(values)); - - vestOutputTransformer(body, value, bhLayout, bhLayoutSize); + auto frontPlane = new VibroPlane(frontOutputs); + auto backPlane = new VibroPlane(backOutputs); + + body->addTarget(Target::ChestFront, frontPlane); + body->addTarget(Target::ChestBack, backPlane); + // body->setup(); + + vestOutputTransformer( + body, + { + 0x01, 0x23, 0x45, 0x67, (char) 0x89, (char) 0xab, (char) 0xcd, (char) 0xef, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + bhLayout + ); TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[0][0])->intensity); TEST_ASSERT_EQUAL_INT(273, static_cast<TestActuator*>(frontMatrix[0][1])->intensity); TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[0][2])->intensity); @@ -176,7 +178,7 @@ void test_layout_tactsuitx40(void) void test_layout_tactal(void) { static const size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; - static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; + static const oh_output_point_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; auto body = new HapticBody(); @@ -190,60 +192,11 @@ void test_layout_tactal(void) auto outputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ { actuator0, actuator1, actuator2, actuator3, actuator4, actuator5 }, }); - auto plane = new HapticPlane(outputs); - - body->addComponent(OUTPUT_PATH_ACCESSORY, plane); - body->setup(); - - uint8_t values[] = { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 }; - std::string value = std::string((char*) values, sizeof(values)); - - plainOutputTransformer(body, value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); - TEST_ASSERT_EQUAL_INT(4095, actuator0->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator1->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator2->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator3->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator4->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator5->intensity); - - value = "\x10\x20\x30\x40\x50\x60"; - - plainOutputTransformer(body, value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); - TEST_ASSERT_EQUAL_INT(655, actuator0->intensity); - TEST_ASSERT_EQUAL_INT(1310, actuator1->intensity); - TEST_ASSERT_EQUAL_INT(1965, actuator2->intensity); - TEST_ASSERT_EQUAL_INT(2620, actuator3->intensity); - TEST_ASSERT_EQUAL_INT(3276, actuator4->intensity); - TEST_ASSERT_EQUAL_INT(3931, actuator5->intensity); -} - -void test_layout_tactosy2(void) -{ - static const size_t bhLayoutSize = BH_LAYOUT_TACTOSY2_SIZE; - static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSY2; - - auto body = new HapticBody(); - - TestActuator* actuator0 = new TestActuator(); - TestActuator* actuator1 = new TestActuator(); - TestActuator* actuator2 = new TestActuator(); - TestActuator* actuator3 = new TestActuator(); - TestActuator* actuator4 = new TestActuator(); - TestActuator* actuator5 = new TestActuator(); - - auto outputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ - { actuator0, actuator1, actuator2 }, - { actuator3, actuator4, actuator5 }, - }); - auto plane = new HapticPlane(outputs); - - body->addComponent(OUTPUT_PATH_ACCESSORY, plane); - body->setup(); + auto plane = new VibroPlane(outputs); - uint8_t values[] = { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 }; - std::string value = std::string((char*) values, sizeof(values)); + body->addTarget(Target::Accessory, plane); - plainOutputTransformer(body, value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); + plainOutputTransformer(body, { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 }, bhLayout, Target::Accessory); TEST_ASSERT_EQUAL_INT(4095, actuator0->intensity); TEST_ASSERT_EQUAL_INT(0, actuator1->intensity); TEST_ASSERT_EQUAL_INT(0, actuator2->intensity); @@ -251,8 +204,7 @@ void test_layout_tactosy2(void) TEST_ASSERT_EQUAL_INT(0, actuator4->intensity); TEST_ASSERT_EQUAL_INT(0, actuator5->intensity); - value = "\x10\x20\x30\x40\x50\x60"; - plainOutputTransformer(body, value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); + plainOutputTransformer(body, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, bhLayout, Target::Accessory); TEST_ASSERT_EQUAL_INT(655, actuator0->intensity); TEST_ASSERT_EQUAL_INT(1310, actuator1->intensity); TEST_ASSERT_EQUAL_INT(1965, actuator2->intensity); @@ -261,78 +213,6 @@ void test_layout_tactosy2(void) TEST_ASSERT_EQUAL_INT(3931, actuator5->intensity); } -void test_layout_tactosyh(void) -{ - static const size_t bhLayoutSize = BH_LAYOUT_TACTOSYH_SIZE; - static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYH; - - auto body = new HapticBody(); - - TestActuator* actuator0 = new TestActuator(); - TestActuator* actuator1 = new TestActuator(); - TestActuator* actuator2 = new TestActuator(); - - auto outputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ - { actuator0 }, - { actuator1 }, - { actuator2 }, - }); - auto plane = new HapticPlane(outputs); - - body->addComponent(OUTPUT_PATH_ACCESSORY, plane); - body->setup(); - - uint8_t values[] = { 0x64, 0x00, 0x00 }; - std::string value = std::string((char*) values, sizeof(values)); - - plainOutputTransformer(body, value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); - TEST_ASSERT_EQUAL_INT(4095, actuator0->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator1->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator2->intensity); - - value = "\x10\x20\x30"; - plainOutputTransformer(body, value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); - TEST_ASSERT_EQUAL_INT(655, actuator0->intensity); - TEST_ASSERT_EQUAL_INT(1310, actuator1->intensity); - TEST_ASSERT_EQUAL_INT(1965, actuator2->intensity); -} - -void test_layout_tactosyf(void) -{ - static const size_t bhLayoutSize = BH_LAYOUT_TACTOSYF_SIZE; - static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYF; - - auto body = new HapticBody(); - - TestActuator* actuator0 = new TestActuator(); - TestActuator* actuator1 = new TestActuator(); - TestActuator* actuator2 = new TestActuator(); - - auto outputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ - { actuator0 }, - { actuator1 }, - { actuator2 }, - }); - auto plane = new HapticPlane(outputs); - - body->addComponent(OUTPUT_PATH_ACCESSORY, plane); - body->setup(); - - uint8_t values[] = { 0x64, 0x00, 0x00 }; - std::string value = std::string((char*) values, sizeof(values)); - - plainOutputTransformer(body, value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); - TEST_ASSERT_EQUAL_INT(4095, actuator0->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator1->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator2->intensity); - - value = "\x10\x20\x30"; - plainOutputTransformer(body, value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); - TEST_ASSERT_EQUAL_INT(655, actuator0->intensity); - TEST_ASSERT_EQUAL_INT(1310, actuator1->intensity); - TEST_ASSERT_EQUAL_INT(1965, actuator2->intensity); -} - int process(void) { UNITY_BEGIN(); @@ -340,9 +220,9 @@ int process(void) RUN_TEST(test_layout_tactsuitx16); RUN_TEST(test_layout_tactsuitx40); RUN_TEST(test_layout_tactal); - RUN_TEST(test_layout_tactosy2); - RUN_TEST(test_layout_tactosyh); - RUN_TEST(test_layout_tactosyf); + // RUN_TEST(test_layout_tactosy2); + // RUN_TEST(test_layout_tactosyh); + // RUN_TEST(test_layout_tactosyf); return UNITY_END(); } From 164f0edd071189f1acbab8b472ea4774894efa0f Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sat, 12 Aug 2023 13:54:05 +0400 Subject: [PATCH 03/82] refactor(bHaptics): update firmwares after refactoring --- firmware/firmware.cpp | 2 +- firmware/mode_configs/bhaptics/tactal.cpp | 16 +++++++----- firmware/senseshift.cpp | 32 ++++++++++++----------- include/senseshift.h | 30 +++++++++++---------- lib/arduino/components/serial_plotter.cpp | 24 ++++++++++------- lib/arduino/components/serial_plotter.hpp | 6 ++--- lib/haptics/haptic_body.cpp | 1 + lib/haptics/haptic_body.hpp | 6 +++++ 8 files changed, 68 insertions(+), 49 deletions(-) diff --git a/firmware/firmware.cpp b/firmware/firmware.cpp index 28aeed08..ae0f0668 100644 --- a/firmware/firmware.cpp +++ b/firmware/firmware.cpp @@ -19,7 +19,7 @@ extern void loopMode(); #if defined(ARDUINO) -SenseShift App; +SenseShift::SenseShift App; void setup() { diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index 25913016..f4430848 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -15,13 +15,15 @@ #endif using namespace OH; +using namespace SenseShift; +using namespace SenseShift::Body::Haptics; using namespace BH; -extern SenseShift App; -SenseShift* app = &App; +extern SenseShift::SenseShift App; +SenseShift::SenseShift* app = &App; static const size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; -static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; +static const oh_output_point_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; void setupMode() { @@ -32,8 +34,8 @@ void setupMode() // clang-format on }); - auto* face = new HapticPlane_Closest(faceOutputs); - app->getHapticBody()->addComponent(OUTPUT_PATH_ACCESSORY, face); + auto* face = new VibroPlane_Closest(faceOutputs); + app->getHapticBody()->addTarget(Target::Accessory, face); app->getHapticBody()->setup(); @@ -46,7 +48,9 @@ void setupMode() auto* bhBleConnection = new ConnectionBHBLE( config, [](std::string& value) -> void { - plainOutputTransformer(app->getHapticBody(), value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); + char buf[6]; + strncpy(buf, value.c_str(), 6); + plainOutputTransformer<6>(app->getHapticBody(), buf, bhLayout, Target::Accessory); }, app ); diff --git a/firmware/senseshift.cpp b/firmware/senseshift.cpp index 683ac376..f54fda9a 100644 --- a/firmware/senseshift.cpp +++ b/firmware/senseshift.cpp @@ -8,23 +8,25 @@ #include <logging.hpp> -SenseShift::SenseShift() -{ - this->pHapticBody = new OH::HapticBody(); -} +namespace SenseShift { + SenseShift::SenseShift() + { + this->pHapticBody = new Body::Haptics::HapticBody(); + } -void SenseShift::postEvent(const OH::IEvent* event) -{ - log_i("Event dispatched at %u: %s (%p)", millis(), event->eventName.c_str(), event); + void SenseShift::postEvent(const OH::IEvent* event) + { + log_i("Event dispatched at %u: %s (%p)", millis(), event->eventName.c_str(), event); - for (auto* listener : this->eventListeners) { - listener->handleEvent(event); - } + for (auto* listener : this->eventListeners) { + listener->handleEvent(event); + } - delete event; -} + delete event; + } -void SenseShift::addEventListener(const OH::IEventListener* listener) -{ - this->eventListeners.push_back(listener); + void SenseShift::addEventListener(const OH::IEventListener* listener) + { + this->eventListeners.push_back(listener); + } } diff --git a/include/senseshift.h b/include/senseshift.h index 1251a9fd..f4346148 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -12,23 +12,25 @@ #include <vector> -class SenseShift final : public OH::IEventDispatcher { - private: - std::vector<const OH::IEventListener*> eventListeners{}; - OH::HapticBody* pHapticBody; +namespace SenseShift { + class SenseShift final : public OH::IEventDispatcher { + private: + std::vector<const OH::IEventListener*> eventListeners{}; + Body::Haptics::HapticBody* pHapticBody; #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true - OH::BatterySensor* battery; + OH::BatterySensor* battery; #endif - public: - SenseShift(); + public: + SenseShift(); - OH::HapticBody* getHapticBody() - { - return this->pHapticBody; - }; + Body::Haptics::HapticBody* getHapticBody() + { + return this->pHapticBody; + }; - void postEvent(const OH::IEvent* event) override; - void addEventListener(const OH::IEventListener* listener) override; -}; + void postEvent(const OH::IEvent* event) override; + void addEventListener(const OH::IEventListener* listener) override; + }; +} diff --git a/lib/arduino/components/serial_plotter.cpp b/lib/arduino/components/serial_plotter.cpp index c3320721..21a1ffb1 100644 --- a/lib/arduino/components/serial_plotter.cpp +++ b/lib/arduino/components/serial_plotter.cpp @@ -1,19 +1,23 @@ #include "components/serial_plotter.hpp" +struct PlaneVisitor { + const SenseShift::Body::Haptics::Target_t target; + HardwareSerial* serial; + + void operator()(const SenseShift::Body::Haptics::VibroPlane* plane) const + { + for (const auto& [position, state] : *(plane->getActuatorStates())) { + this->serial->printf("Output[%u][%ux%u]:%u, ", this->target, position.x, position.y, state.intensity); + } + } +}; + template<typename _Tp> void OH::SerialPlotter_OutputStates<_Tp>::run() { while (true) { - for (auto& _c : *output->getComponents()) { - oh_output_path_t path = _c.first; - OH::HapticPlane* component = _c.second; - - for (auto& _s : *component->getActuatorStates()) { - oh_output_point_t point = _s.first; - oh_output_state_t state = _s.second; - - this->serial->printf("Output[%u][%ux%u]:%u, ", path, point.x, point.y, state.intensity); - } + for (const auto& [target, plane] : *output->getTargets()) { + std::visit(PlaneVisitor{target, this->serial}, plane); } this->serial->println(); diff --git a/lib/arduino/components/serial_plotter.hpp b/lib/arduino/components/serial_plotter.hpp index 70ab445e..e0a9be8a 100644 --- a/lib/arduino/components/serial_plotter.hpp +++ b/lib/arduino/components/serial_plotter.hpp @@ -21,7 +21,7 @@ namespace OH { private: _Tp* serial; - HapticBody* output; + SenseShift::Body::Haptics::HapticBody* output; uint32_t sampleRate; void setup(void){}; @@ -30,12 +30,12 @@ namespace OH { public: SerialPlotter_OutputStates( _Tp& serial, - HapticBody* output, + SenseShift::Body::Haptics::HapticBody* output, uint32_t sampleRate, TaskConfig taskConfig = { "Serial Plotter", 2048, 1, tskNO_AFFINITY } ) : Task<SerialPlotter_OutputStates<_Tp>>(taskConfig), serial(&serial), output(output), sampleRate(sampleRate){}; - SerialPlotter_OutputStates(_Tp& serial, HapticBody* output) : SerialPlotter_OutputStates(serial, output, 100){}; + SerialPlotter_OutputStates(_Tp& serial, SenseShift::Body::Haptics::HapticBody* output) : SerialPlotter_OutputStates(serial, output, 100){}; void begin() override { diff --git a/lib/haptics/haptic_body.cpp b/lib/haptics/haptic_body.cpp index 3718ed41..c90ce2f1 100644 --- a/lib/haptics/haptic_body.cpp +++ b/lib/haptics/haptic_body.cpp @@ -28,5 +28,6 @@ namespace SenseShift::Body::Haptics { void HapticBody::addTarget(const Target_t target, VibroPlane* plane) { this->vibroTargets[target] = plane; + this->allTargets.insert({ target, plane }); } } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/haptic_body.hpp b/lib/haptics/haptic_body.hpp index 33252535..088bad0e 100644 --- a/lib/haptics/haptic_body.hpp +++ b/lib/haptics/haptic_body.hpp @@ -11,6 +11,8 @@ namespace SenseShift::Body::Haptics { class HapticBody { public: + typedef std::variant<VibroPlane*> AuctiativePlane_t; + typedef std::multimap<Target_t, AuctiativePlane_t> PlaneTargetMap_t; typedef std::map<Target_t, VibroPlane*> VibroTargetMap_t; HapticBody(){}; @@ -21,7 +23,11 @@ namespace SenseShift::Body::Haptics { void addTarget(const Target_t, VibroPlane* plane); + const PlaneTargetMap_t* getTargets() const { return &allTargets; } + private: + PlaneTargetMap_t allTargets{}; VibroTargetMap_t vibroTargets{}; + }; } // namespace SenseShift::Body::Haptics From 6f3b63f124a43dbf2bd3d9a478f38a58251593a2 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Wed, 16 Aug 2023 21:08:22 +0400 Subject: [PATCH 04/82] refactor(bHaptics): add Decoder class --- firmware/mode_configs/bhaptics/tactal.cpp | 8 +- lib/bhaptics/bh_encoding.hpp | 202 ++++++++++++++++++ lib/bhaptics/bh_utils.cpp | 107 ---------- lib/bhaptics/bh_utils.hpp | 45 ---- lib/haptics/haptic_body.cpp | 4 +- lib/haptics/haptic_plane.cpp | 4 +- lib/haptics/haptic_plane.hpp | 6 +- lib/haptics/haptics_interface.hpp | 16 +- .../main.cpp | 19 +- test/test_haptics_body/main.cpp | 8 +- 10 files changed, 234 insertions(+), 185 deletions(-) create mode 100644 lib/bhaptics/bh_encoding.hpp delete mode 100644 lib/bhaptics/bh_utils.cpp delete mode 100644 lib/bhaptics/bh_utils.hpp rename test/{test_bhaptics => test_bhaptics_encoding}/main.cpp (93%) diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index f4430848..12bb9063 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -6,7 +6,7 @@ #include "senseshift.h" -#include <bh_utils.hpp> +#include <bh_encoding.hpp> #include <connection_bhble.hpp> #include <output_writers/pwm.hpp> @@ -35,7 +35,7 @@ void setupMode() }); auto* face = new VibroPlane_Closest(faceOutputs); - app->getHapticBody()->addTarget(Target::Accessory, face); + app->getHapticBody()->addTarget(Target::FaceFront, face); app->getHapticBody()->setup(); @@ -48,9 +48,7 @@ void setupMode() auto* bhBleConnection = new ConnectionBHBLE( config, [](std::string& value) -> void { - char buf[6]; - strncpy(buf, value.c_str(), 6); - plainOutputTransformer<6>(app->getHapticBody(), buf, bhLayout, Target::Accessory); + Decoder::applyPlain<6>(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); }, app ); diff --git a/lib/bhaptics/bh_encoding.hpp b/lib/bhaptics/bh_encoding.hpp new file mode 100644 index 00000000..4a4c7508 --- /dev/null +++ b/lib/bhaptics/bh_encoding.hpp @@ -0,0 +1,202 @@ +#pragma once + +#include <haptic_body.hpp> +#include <cstring> + +namespace BH +{ + class Decoder + { + public: + typedef SenseShift::Body::Haptics::VibroEffectData_t VibroEffectData_t; + typedef SenseShift::Body::Haptics::EffectData_t EffectData_t; + typedef SenseShift::Body::Haptics::Effect_t Effect_t; + typedef SenseShift::Body::Haptics::Target_t Target_t; + typedef SenseShift::Body::Haptics::Position_t Position_t; + typedef std::tuple<Effect_t, Target_t, Position_t> OutputLayout_t; + + static const size_t VEST_LAYOUT_SIZE = 40; + static const size_t VEST_PAYLOAD_SIZE = 20; + + /** + * Apply plain-encoded data to the output. + */ + template<size_t N> + static void applyPlain( + SenseShift::Body::Haptics::HapticBody* output, + const uint8_t (&value)[N], + const Position_t (&layout)[N], + const Effect_t effect, + const Target_t target + ) { + for (size_t i = 0; i < N; i++) { + auto position = layout[i]; + uint8_t byte = value[i]; + + output->effect({ + .effect = effect, + .target = target, + .position = position, + .data = effectDataFromByte(effect, byte), + }); + } + } + + template<size_t N> + static void applyPlain( + SenseShift::Body::Haptics::HapticBody* output, + std::string& value, + const Position_t (&layout)[N], + const Effect_t effect, + const Target_t target + ) { + std::uint8_t buf[6]; + std::size_t copyLength = std::min(value.size(), sizeof(buf)); + std::memcpy(buf, value.c_str(), copyLength); + + applyPlain(output, buf, layout, effect, target); + } + + /** + * Apply vest-encoded data to the output. + */ + static void applyVest( + SenseShift::Body::Haptics::HapticBody* output, + const uint8_t (&value)[VEST_PAYLOAD_SIZE], + const Position_t (&layout)[VEST_LAYOUT_SIZE] + ) { + for (size_t i = 0; i < VEST_PAYLOAD_SIZE; i++) { + uint8_t byte = value[i]; + uint actIndex = i * 2; + const auto target = (actIndex < 10 || actIndex >= 30) ? Target_t::ChestFront : Target_t::ChestBack; + + output->effect({ + .effect = Effect_t::Vibro, + .target = target, + .position = layout[actIndex], + .data = effectDataFromByte( + Effect_t::Vibro, + ((byte >> 4) & 0xf), + 15 + ), + }); + output->effect({ + .effect = Effect_t::Vibro, + .target = target, + .position = layout[actIndex + 1], + .data = effectDataFromByte( + Effect_t::Vibro, + (byte & 0xf), + 15 + ), + }); + } + } + + static void applyVest( + SenseShift::Body::Haptics::HapticBody* output, + std::string& value, + const Position_t (&layout)[VEST_LAYOUT_SIZE] + ) { + std::uint8_t buf[VEST_PAYLOAD_SIZE]; + std::size_t copyLength = std::min(value.size(), sizeof(buf)); + std::memcpy(buf, value.c_str(), copyLength); + + applyVest(output, buf, layout); + } + + /** + * Apply grouped vest-encoded data to the output. + */ + template <size_t N> + static void applyVestGrouped( + SenseShift::Body::Haptics::HapticBody* output, + const uint8_t (&value)[VEST_PAYLOAD_SIZE], + const Position_t (&layout)[VEST_LAYOUT_SIZE], + const uint8_t (&layoutGroups)[N] + ) { + uint8_t result[VEST_LAYOUT_SIZE]; + + // Unpack values + for (auto i = 0; i < VEST_PAYLOAD_SIZE; i++) { + uint8_t byte = value[i]; + uint actIndex = i * 2; + + result[actIndex] = (byte >> 4) & 0xf; + result[actIndex + 1] = (byte & 0xf); + } + + // 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 (!OH::contains(layoutGroups, VEST_LAYOUT_SIZE, i)) { + continue; + } + + const auto target = (i < 10 || i >= 30) ? Target_t::ChestFront : Target_t::ChestBack; + + output->effect({ + .effect = Effect_t::Vibro, + .target = target, + .position = layout[i], + .data = effectDataFromByte( + Effect_t::Vibro, + result[i], + 15 + ), + }); + } + } + + template <size_t N> + static void applyVestGrouped( + SenseShift::Body::Haptics::HapticBody* output, + std::string& value, + const Position_t (&layout)[VEST_LAYOUT_SIZE], + const uint8_t (&layoutGroups)[N] + ) { + std::uint8_t buf[VEST_PAYLOAD_SIZE]; + std::size_t copyLength = std::min(value.size(), sizeof(buf)); + std::memcpy(buf, value.c_str(), copyLength); + + applyVestGrouped(output, buf, layout, layoutGroups); + } + + private: + static const EffectData_t effectDataFromByte( + const Effect_t& effect, + const uint8_t byte, + const uint8_t maxValue = 100 + ) { + switch (effect) { + case Effect_t::Vibro: + return VibroEffectData_t( + OH::simpleMap<VibroEffectData_t::Intensity_t>( + byte, maxValue, VibroEffectData_t::INTENSITY_MAX + ) + ); + default: + throw std::runtime_error("Unknown effect"); + } + } + }; +} // namespace BH diff --git a/lib/bhaptics/bh_utils.cpp b/lib/bhaptics/bh_utils.cpp deleted file mode 100644 index d1a4654a..00000000 --- a/lib/bhaptics/bh_utils.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "bh_utils.hpp" - -#include <utility.hpp> - -namespace BH { - template<size_t N = 20> - void vestOutputTransformer( - SenseShift::Body::Haptics::HapticBody* output, const char (&value)[N], const oh_output_point_t (&layout)[N * 2] - ) - { - for (size_t i = 0; i < N; i++) { - uint8_t byte = value[i]; - uint actIndex = i * 2; - const auto target = (actIndex < 10 || actIndex >= 30) ? SenseShift::Body::Haptics::Target::ChestFront - : SenseShift::Body::Haptics::Target::ChestBack; - - output->effect({ - .effect = SenseShift::Body::Haptics::Effect::Vibro, - .target = target, - .position = layout[actIndex], - .data = SenseShift::Body::Haptics::VibroEffect( - OH::simpleMap<SenseShift::Body::Haptics::VibroEffect::Intensity_t>( - ((byte >> 4) & 0xf), - 15, - SenseShift::Body::Haptics::VibroEffect::INTENSITY_MAX - ) - ), - }); - output->effect({ - .effect = SenseShift::Body::Haptics::Effect::Vibro, - .target = target, - .position = layout[actIndex + 1], - .data = SenseShift::Body::Haptics::VibroEffect( - OH::simpleMap<SenseShift::Body::Haptics::VibroEffect::Intensity_t>( - (byte & 0xf), - 15, - SenseShift::Body::Haptics::VibroEffect::INTENSITY_MAX - ) - ), - }); - } - } - - template void vestOutputTransformer<20>( - SenseShift::Body::Haptics::HapticBody* output, const char (&value)[20], const oh_output_point_t (&layout)[40] - ); -} // namespace BH - -void BH::vestX16OutputTransformer( - SenseShift::Body::Haptics::HapticBody* output, - const std::string& value, - const oh_output_point_t* layout, - const size_t layoutSize, - const uint8_t layoutGroups[], - const size_t layoutGroupsSize -) -{ - uint8_t result[layoutSize]; - - // Unpack values - for (auto i = 0; i < layoutSize / 2; i++) { - uint8_t byte = value[i]; - uint actIndex = i * 2; - - result[actIndex] = (byte >> 4) & 0xf; - result[actIndex + 1] = (byte & 0xf); - } - - // Assign max value into each group - for (auto i = 0; i < layoutGroupsSize; 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 < static_cast<uint8_t>(layoutSize); i++) { - // take only meaningful values - if (!OH::contains(layoutGroups, layoutSize, i)) { - continue; - } - - const auto target = (i < 10 || i >= 30) ? SenseShift::Body::Haptics::Target::ChestFront - : SenseShift::Body::Haptics::Target::ChestBack; - - output->effect({ - .effect = SenseShift::Body::Haptics::Effect::Vibro, - .target = target, - .position = layout[i], - .data = SenseShift::Body::Haptics::VibroEffect( - static_cast<oh_output_intensity_t>(OH::accurateMap<long>(result[i], 0, 15, 0, OH_OUTPUT_INTENSITY_MAX)) - ), - }); - } -} diff --git a/lib/bhaptics/bh_utils.hpp b/lib/bhaptics/bh_utils.hpp deleted file mode 100644 index 2825aea7..00000000 --- a/lib/bhaptics/bh_utils.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include <haptic_body.hpp> -#include <string> - -namespace BH { - template<size_t N> - void plainOutputTransformer( - SenseShift::Body::Haptics::HapticBody* output, - const char (&value)[N], - const oh_output_point_t (&layout)[N], - const SenseShift::Body::Haptics::Target_t target - ) - { - for (size_t i = 0; i < N; i++) { - uint8_t byte = value[i]; - - output->effect({ - .effect = SenseShift::Body::Haptics::Effect::Vibro, - .target = target, - .position = layout[i], - .data = SenseShift::Body::Haptics::VibroEffect( - OH::simpleMap<SenseShift::Body::Haptics::VibroEffect::Intensity_t>( - byte, - 100, - SenseShift::Body::Haptics::VibroEffect::INTENSITY_MAX - ) - ), - }); - } - } - - template<size_t N = 20> - void vestOutputTransformer( - SenseShift::Body::Haptics::HapticBody* output, const char (&value)[N], const oh_output_point_t (&layout)[N * 2] - ); - void vestX16OutputTransformer( - SenseShift::Body::Haptics::HapticBody* output, - const std::string& value, - const oh_output_point_t* layout, - const size_t layoutSize, - const uint8_t layoutGroups[], - const size_t layoutGroupsSize - ); -} // namespace BH diff --git a/lib/haptics/haptic_body.cpp b/lib/haptics/haptic_body.cpp index c90ce2f1..fd4cf2cb 100644 --- a/lib/haptics/haptic_body.cpp +++ b/lib/haptics/haptic_body.cpp @@ -12,14 +12,14 @@ namespace SenseShift::Body::Haptics { void HapticBody::effect(const EffectRequest_t& effect) { - if (effect.effect == Effect::Vibro && std::holds_alternative<VibroEffect_t>(effect.data)) { + if (effect.effect == Effect::Vibro && std::holds_alternative<VibroEffectData_t>(effect.data)) { auto it = this->vibroTargets.find(effect.target); if (it == this->vibroTargets.end()) { log_w("No target found for effect: %d", effect.target); return; } - it->second->effect(effect.position, std::get<VibroEffect_t>(effect.data)); + it->second->effect(effect.position, std::get<VibroEffectData_t>(effect.data)); } else { log_w("Non-supported effect type: %d", effect.effect); } diff --git a/lib/haptics/haptic_plane.cpp b/lib/haptics/haptic_plane.cpp index ddbf0e7b..6c10861f 100644 --- a/lib/haptics/haptic_plane.cpp +++ b/lib/haptics/haptic_plane.cpp @@ -75,6 +75,6 @@ namespace SenseShift::Body::Haptics { return nearest->second; } - template class ActuativePlane<VibroEffect_t>; - template class ActuativePlane_Closest<VibroEffect_t>; + template class ActuativePlane<VibroEffectData_t>; + template class ActuativePlane_Closest<VibroEffectData_t>; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/haptic_plane.hpp b/lib/haptics/haptic_plane.hpp index 8f565ef6..66c47818 100644 --- a/lib/haptics/haptic_plane.hpp +++ b/lib/haptics/haptic_plane.hpp @@ -21,7 +21,7 @@ namespace SenseShift::Body::Haptics { */ template<typename _Tp> class ActuativePlane { - static_assert(std::is_same<_Tp, VibroEffect_t>()); + static_assert(std::is_same<_Tp, VibroEffectData_t>()); public: typedef _Tp Value_t; @@ -59,7 +59,7 @@ namespace SenseShift::Body::Haptics { void setActuators(const ActuatorMap_t&); }; - typedef ActuativePlane<VibroEffect_t> VibroPlane; + typedef ActuativePlane<VibroEffectData_t> VibroPlane; /** * Output plane, finds the closest actuator for the given point. @@ -81,7 +81,7 @@ namespace SenseShift::Body::Haptics { [[nodiscard]] const Position_t& findClosestPoint(const PositionSet_t&, const Position_t&) const; }; - typedef ActuativePlane_Closest<VibroEffect_t> VibroPlane_Closest; + typedef ActuativePlane_Closest<VibroEffectData_t> VibroPlane_Closest; // TODO: configurable margin class PlaneMapper_Margin { diff --git a/lib/haptics/haptics_interface.hpp b/lib/haptics/haptics_interface.hpp index f6734c76..26bd2b86 100644 --- a/lib/haptics/haptics_interface.hpp +++ b/lib/haptics/haptics_interface.hpp @@ -24,6 +24,8 @@ namespace SenseShift::Body::Haptics { // Legacy backword compatibility Accessory [[deprecated]] = 0x02, + FaceFront = 0x03, + // TODO: arms, legs, etc. } Target_t; @@ -31,28 +33,28 @@ namespace SenseShift::Body::Haptics { typedef OH::Point2<Coordinate_t> Position_t; // Vibration intensity. - typedef struct VibroEffect { + typedef struct VibroEffectData { using Intensity_t = uint16_t; inline static const Intensity_t INTENSITY_MIN = 0; inline static const Intensity_t INTENSITY_MAX = 4095; Intensity_t intensity = 0; - inline constexpr VibroEffect() = default; - inline constexpr VibroEffect(Intensity_t intensity) : intensity(intensity) {} - inline constexpr VibroEffect(const VibroEffect& other) = default; + inline constexpr VibroEffectData() = default; + inline constexpr VibroEffectData(const Intensity_t intensity) : intensity(intensity) {} + inline constexpr VibroEffectData(const VibroEffectData& other) = default; inline constexpr operator uint16_t() const { return intensity; } - } VibroEffect_t; + } VibroEffectData_t; // TODO: thermal, etc. - typedef std::variant<VibroEffect_t + typedef std::variant<VibroEffectData_t // TODO: thermal, etc. - // ThermalEffect_t + // ThermalEffectData_t > EffectData_t; diff --git a/test/test_bhaptics/main.cpp b/test/test_bhaptics_encoding/main.cpp similarity index 93% rename from test/test_bhaptics/main.cpp rename to test/test_bhaptics_encoding/main.cpp index 1cc22a18..e73993c4 100644 --- a/test/test_bhaptics/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -1,5 +1,5 @@ #include <bh_types.hpp> -#include <bh_utils.hpp> +#include <bh_encoding.hpp> #include <unity.h> @@ -66,13 +66,12 @@ void test_layout_tactsuitx16(void) body->addTarget(Target::ChestBack, backPlane); // body->setup(); - uint8_t values[] = { + const uint8_t values[] = { 0x01, 0x00, 0x23, 0x00, 0x00, 0x45, 0x00, 0x67, 0x00, 0x00, 0x89, 0x00, 0xab, 0x00, 0x00, 0xcd, 0x00, 0xef, 0x00, 0x00, }; - std::string value = std::string((char*) values, sizeof(values)); - vestX16OutputTransformer(body, value, bhLayout, bhLayoutSize, layoutGroups, layoutGroupsSize); + Decoder::applyVestGrouped(body, values, bhLayout, layoutGroups); TEST_ASSERT_EQUAL_INT(0, actuator0->intensity); TEST_ASSERT_EQUAL_INT(273, actuator1->intensity); TEST_ASSERT_EQUAL_INT(3276, actuator2->intensity); @@ -124,11 +123,11 @@ void test_layout_tactsuitx40(void) body->addTarget(Target::ChestBack, backPlane); // body->setup(); - vestOutputTransformer( + Decoder::applyVest( body, { - 0x01, 0x23, 0x45, 0x67, (char) 0x89, (char) 0xab, (char) 0xcd, (char) 0xef, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, bhLayout ); @@ -194,9 +193,9 @@ void test_layout_tactal(void) }); auto plane = new VibroPlane(outputs); - body->addTarget(Target::Accessory, plane); + body->addTarget(Target::FaceFront, plane); - plainOutputTransformer(body, { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 }, bhLayout, Target::Accessory); + Decoder::applyPlain(body, { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 }, bhLayout, Effect::Vibro, Target::FaceFront); TEST_ASSERT_EQUAL_INT(4095, actuator0->intensity); TEST_ASSERT_EQUAL_INT(0, actuator1->intensity); TEST_ASSERT_EQUAL_INT(0, actuator2->intensity); @@ -204,7 +203,7 @@ void test_layout_tactal(void) TEST_ASSERT_EQUAL_INT(0, actuator4->intensity); TEST_ASSERT_EQUAL_INT(0, actuator5->intensity); - plainOutputTransformer(body, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, bhLayout, Target::Accessory); + Decoder::applyPlain(body, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, bhLayout, Effect::Vibro, Target::FaceFront); TEST_ASSERT_EQUAL_INT(655, actuator0->intensity); TEST_ASSERT_EQUAL_INT(1310, actuator1->intensity); TEST_ASSERT_EQUAL_INT(1965, actuator2->intensity); diff --git a/test/test_haptics_body/main.cpp b/test/test_haptics_body/main.cpp index d16ed628..f5ceb76f 100644 --- a/test/test_haptics_body/main.cpp +++ b/test/test_haptics_body/main.cpp @@ -59,25 +59,25 @@ void test_it_handles_effect__vibro(void) .effect = Effect::Vibro, .target = Target::ChestFront, .position = { 0, 0 }, - .data = (VibroEffect_t) 64, + .data = (VibroEffectData_t) 64, }); body->effect({ .effect = Effect::Vibro, .target = Target::ChestFront, .position = { 0, 1 }, - .data = (VibroEffect_t) 128, + .data = (VibroEffectData_t) 128, }); body->effect({ .effect = Effect::Vibro, .target = Target::ChestFront, .position = { 1, 0 }, - .data = (VibroEffect_t) 192, + .data = (VibroEffectData_t) 192, }); body->effect({ .effect = Effect::Vibro, .target = Target::ChestFront, .position = { 1, 1 }, - .data = (VibroEffect_t) 255, + .data = (VibroEffectData_t) 255, }); TEST_ASSERT_EQUAL(64, actuator1->intensity); From 4a6c2a91f30f546a081f16227d59c0e1074131e3 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Wed, 16 Aug 2023 23:41:12 +0400 Subject: [PATCH 05/82] refactor(bHaptics): advanced TactGlove layout --- firmware/mode_configs/bhaptics/tactal.cpp | 2 +- firmware/mode_configs/bhaptics/tactglove.cpp | 72 +++----- include/config/all.h | 1 - include/config/bluetooth.h | 2 +- include/config/output.h | 5 - ini/bhaptics.ini | 2 + lib/bhaptics/bh_constants.hpp | 79 ++------- lib/bhaptics/bh_devices.hpp | 95 ++++++++++ lib/bhaptics/bh_encoding.hpp | 176 +++++++++++-------- lib/hands/hand_interface.hpp | 19 ++ lib/haptics/haptics_interface.hpp | 19 +- platformio.ini | 2 +- test/test_bhaptics_encoding/main.cpp | 48 ++++- 13 files changed, 317 insertions(+), 205 deletions(-) delete mode 100644 include/config/output.h create mode 100644 lib/bhaptics/bh_devices.hpp create mode 100644 lib/hands/hand_interface.hpp diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index 12bb9063..17982748 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -34,7 +34,7 @@ void setupMode() // clang-format on }); - auto* face = new VibroPlane_Closest(faceOutputs); + auto* face = new VibroPlane(faceOutputs); app->getHapticBody()->addTarget(Target::FaceFront, face); app->getHapticBody()->setup(); diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 8466c328..cb4cbea8 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -8,7 +8,8 @@ #include "senseshift.h" -#include <bh_utils.hpp> +#include <bh_encoding.hpp> +#include <bh_devices.hpp> #include <connection_bhble.hpp> #include <output_writers/pwm.hpp> @@ -16,59 +17,36 @@ #include <battery/adc_naive.hpp> #endif +#ifndef BH_LAYOUT +#define BH_LAYOUT BH::TactGloveLeftLayout +#endif + using namespace OH; +using namespace SenseShift; +using namespace SenseShift::Body::Haptics; using namespace BH; -extern SenseShift App; -SenseShift* app = &App; - -#pragma region bHaptics_trash - -// TODO: all of this will need to be re-written to use the new output paths system, when time comes - -static const uint16_t _bh_size_x = 6; -static const uint16_t _bh_size_y = 1; - -inline oh_output_point_t* make_point(oh_output_coord_t x, oh_output_coord_t y) -{ - return PlaneMapper_Margin::mapPoint( - x, - y, - (oh_output_coord_t) (_bh_size_x - 1), - (oh_output_coord_t) (_bh_size_y - 1) - ); -} - -static const uint16_t bhLayoutSize = _bh_size_x * _bh_size_y; -static const oh_output_point_t* bhLayout[bhLayoutSize] = { - // clang-format off - - // Thumb, Index, Middle, Ring, Pinky - make_point(0, 0), make_point(1, 0), make_point(2, 0), make_point(3, 0), make_point(4, 0), - // Wrist - make_point(5, 0) +extern SenseShift::SenseShift App; +SenseShift::SenseShift* app = &App; - // clang-format on -}; - -#pragma endregion bHaptics_trash +const auto& bhLayout = BH_LAYOUT; void setupMode() { // Configure PWM pins to their positions on the glove - auto gloveOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ - // clang-format off - { - // Thumb, Index, Middle, Ring, Pinky - new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26), new PWMOutputWriter(27), - // Wrist - new PWMOutputWriter(14) - }, - // clang-format on - }); - - auto* glove = new HapticPlane_Closest(gloveOutputs); - app->getHapticBody()->addComponent(OUTPUT_PATH_ACCESSORY, glove); + auto* motorThumb = new PWMOutputWriter(33); // Thumb + auto* motorIndex = new PWMOutputWriter(32); // Index + auto* motorMiddle = new PWMOutputWriter(25); // Middle + auto* motorRing = new PWMOutputWriter(26); // Ring + auto* motorLittle = new PWMOutputWriter(27); // Little + auto* motorWrist = new PWMOutputWriter(14); // Wrist + + app->getHapticBody()->addTarget(std::get<0>(bhLayout[0]), new VibroPlane({{ std::get<1>(bhLayout[0]), motorThumb }})); + app->getHapticBody()->addTarget(std::get<0>(bhLayout[1]), new VibroPlane({{ std::get<1>(bhLayout[1]), motorIndex }})); + app->getHapticBody()->addTarget(std::get<0>(bhLayout[2]), new VibroPlane({{ std::get<1>(bhLayout[2]), motorMiddle }})); + app->getHapticBody()->addTarget(std::get<0>(bhLayout[3]), new VibroPlane({{ std::get<1>(bhLayout[3]), motorRing }})); + app->getHapticBody()->addTarget(std::get<0>(bhLayout[4]), new VibroPlane({{ std::get<1>(bhLayout[4]), motorLittle }})); + app->getHapticBody()->addTarget(std::get<0>(bhLayout[5]), new VibroPlane({{ std::get<1>(bhLayout[5]), motorWrist }})); app->getHapticBody()->setup(); @@ -81,7 +59,7 @@ void setupMode() auto* bhBleConnection = new ConnectionBHBLE( config, [](std::string& value) -> void { - plainOutputTransformer(app->getHapticBody(), value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); + Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect_t::Vibro); }, app ); diff --git a/include/config/all.h b/include/config/all.h index 1c74f18c..46c9d0b0 100644 --- a/include/config/all.h +++ b/include/config/all.h @@ -3,7 +3,6 @@ #pragma once #include "config/battery.h" -#include "config/output.h" #include "config/pwm.h" #include "config/bluetooth.h" diff --git a/include/config/bluetooth.h b/include/config/bluetooth.h index 46f31eb6..b12cff34 100644 --- a/include/config/bluetooth.h +++ b/include/config/bluetooth.h @@ -12,5 +12,5 @@ #endif #ifndef BLUETOOTH_USE_NIMBLE -#define BLUETOOTH_USE_NIMBLE false +#define BLUETOOTH_USE_NIMBLE true #endif diff --git a/include/config/output.h b/include/config/output.h deleted file mode 100644 index 8184df26..00000000 --- a/include/config/output.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#define OUTPUT_PATH_CHEST_FRONT 0x00 -#define OUTPUT_PATH_CHEST_BACK 0x01 -#define OUTPUT_PATH_ACCESSORY 0x02 diff --git a/ini/bhaptics.ini b/ini/bhaptics.ini index ee45ae1e..54c5aa1e 100644 --- a/ini/bhaptics.ini +++ b/ini/bhaptics.ini @@ -239,6 +239,7 @@ monitor_speed = ${bhaptics.monitor_speed} build_flags = ${bhaptics.build_flags} -D BH_DEVICE_TACTGLOVE + -D BH_LAYOUT=BH::TactGloveLeftLayout -D BH_BLE_APPEARANCE=508 '-D BLUETOOTH_NAME="TactGlove (L"' '-D BH_SERIAL_NUMBER={ 0xcd, 0x0b, 0x81, 0x45, 0x85, 0xf9, 0x2b, 0x6c, 0xed, 0x5b }' @@ -257,6 +258,7 @@ monitor_speed = ${bhaptics.monitor_speed} build_flags = ${bhaptics.build_flags} -D BH_DEVICE_TACTGLOVE + -D BH_LAYOUT=BH::TactGloveRightLayout -D BH_BLE_APPEARANCE=508 '-D BLUETOOTH_NAME="TactGlove (R"' '-D BH_SERIAL_NUMBER={ 0x12, 0x0b, 0xae, 0xbf, 0xbc, 0x90, 0x3b, 0x0d, 0x84, 0xdd }' diff --git a/lib/bhaptics/bh_constants.hpp b/lib/bhaptics/bh_constants.hpp index b28f53e3..c430911a 100644 --- a/lib/bhaptics/bh_constants.hpp +++ b/lib/bhaptics/bh_constants.hpp @@ -8,8 +8,16 @@ #define BH_SERIAL_NUMBER_LENGTH 10 +#ifndef BH_FIRMWARE_VERSION_MAJOR +#define BH_FIRMWARE_VERSION_MAJOR ((uint8_t) UINT8_MAX) +#endif + +#ifndef BH_FIRMWARE_VERSION_MINOR +#define BH_FIRMWARE_VERSION_MINOR ((uint8_t) UINT8_MAX) +#endif + #ifndef BH_FIRMWARE_VERSION -#define BH_FIRMWARE_VERSION (uint16_t) UINT16_MAX +#define BH_FIRMWARE_VERSION (uint16_t)((BH_FIRMWARE_VERSION_MAJOR << 8) | BH_FIRMWARE_VERSION_MINOR) #endif #define NO_AUDIO_CABLE 0 @@ -93,73 +101,6 @@ #pragma endregion BH_DEVICE_TACTSUITX16 -#pragma region BH_DEVICE_TACTSUITX40 - -#define BH_LAYOUT_TACTSUITX40_SIZE_X 4 -#define BH_LAYOUT_TACTSUITX40_SIZE_Y 5 -#define BH_LAYOUT_TACTSUITX40_MAKE_POINT(x, y) \ - SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_Y - 1) \ - ) - -// X * Y for front and back -#define BH_LAYOUT_TACTSUITX40_SIZE 40 -// clang-format off -#define BH_LAYOUT_TACTSUITX40 { \ - /* Front, left part */ \ - /* 0 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0), \ - /* 1 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0), \ - /* 2 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1), \ - /* 3 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1), \ - /* 4 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2), \ - /* 5 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2), \ - /* 6 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3), \ - /* 7 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3), \ - /* 8 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4), \ - /* 9 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4), \ - \ - /* Back */ \ - /* 11 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0), \ - /* 11 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0), \ - /* 12 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1), \ - /* 13 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1), \ - /* 14 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2), \ - /* 15 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2), \ - /* 16 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3), \ - /* 17 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3), \ - /* 18 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4), \ - /* 19 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4), \ - \ - /* 20 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0), \ - /* 21 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0), \ - /* 22 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1), \ - /* 23 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1), \ - /* 24 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2), \ - /* 25 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2), \ - /* 26 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3), \ - /* 27 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3), \ - /* 28 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4), \ - /* 29 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4), \ - \ - /* Front, again... Now right part */ \ - /* 30 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0), \ - /* 31 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0), \ - /* 32 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1), \ - /* 33 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1), \ - /* 34 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2), \ - /* 35 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2), \ - /* 36 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3), \ - /* 37 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3), \ - /* 38 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4), \ - /* 39 */ BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) \ -} -// clang-format on - -#pragma endregion BH_DEVICE_TACTSUITX40 - #pragma region BH_DEVICE_TACTAL #define BH_LAYOUT_TACTAL_SIZE_X 6 @@ -272,7 +213,7 @@ // All below are weird choices of bHaptics engineers... // Why to use unconventional UUIDs, that are reserved for other purposes? -// You have an unlimited amount of other UUIDs +// You have an unlimited amount of other UUIDs // Main service for communication #define BH_BLE_SERVICE_MOTOR_UUID BLEUUID("6e400001-b5a3-f393-e0a9-e50e24dcca9e") // Nordic UART Service diff --git a/lib/bhaptics/bh_devices.hpp b/lib/bhaptics/bh_devices.hpp new file mode 100644 index 00000000..dd131e20 --- /dev/null +++ b/lib/bhaptics/bh_devices.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include <hand_interface.hpp> + +#pragma region TaxtSuit X16 + +#define BH_LAYOUT_TACTSUITX40_SIZE_X 4 +#define BH_LAYOUT_TACTSUITX40_SIZE_Y 5 +#define BH_LAYOUT_TACTSUITX40_MAKE_POINT(x, y) \ + SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + x, \ + y, \ + (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_X - 1), \ + (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_Y - 1) \ + ) + +// X * Y for front and back +#define BH_LAYOUT_TACTSUITX40_SIZE 40 +// clang-format off +#define BH_LAYOUT_TACTSUITX40 { \ + /* Front, left part */ \ + /* 0 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ + /* 1 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ + /* 2 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ + /* 3 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ + /* 4 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ + /* 5 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ + /* 6 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ + /* 7 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ + /* 8 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ + /* 9 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ + \ + /* Back */ \ + /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ + /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ + /* 12 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ + /* 13 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ + /* 14 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ + /* 15 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ + /* 16 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ + /* 17 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ + /* 18 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ + /* 19 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ + \ + /* 20 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ + /* 21 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ + /* 22 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ + /* 23 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ + /* 24 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ + /* 25 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ + /* 26 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ + /* 27 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ + /* 28 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ + /* 29 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) }, \ + \ + /* Front, again... Now right part */ \ + /* 30 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ + /* 31 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ + /* 32 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ + /* 33 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ + /* 34 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ + /* 35 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ + /* 36 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ + /* 37 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ + /* 38 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ + /* 39 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) } \ +} +// clang-format on + +#pragma endregion BH_DEVICE_TACTSUITX40 + +namespace BH { + using namespace SenseShift::Body::Hands::Haptics; + + typedef SenseShift::Body::Haptics::Effect_t Effect_t; + typedef SenseShift::Body::Haptics::Target_t Target_t; + typedef SenseShift::Body::Haptics::Position_t Position_t; + typedef std::tuple<Target_t, Position_t> OutputLayout_t; + + // TactSuit X40 motor positions + static constexpr const OutputLayout_t TactSuitX40Layout[] = BH_LAYOUT_TACTSUITX40; + + // TactGlove Wrist motor position + static constexpr const Position_t WRIST_MOTOR_POSITION(127, 191); + static constexpr const OutputLayout_t TactGloveLeftLayout[] = { + { Target_t::HandLeftThumb, FINGERTIP_POSITION }, { Target_t::HandLeftIndex, FINGERTIP_POSITION }, + { Target_t::HandLeftMiddle, FINGERTIP_POSITION }, { Target_t::HandLeftRing, FINGERTIP_POSITION }, + { Target_t::HandLeftLittle, FINGERTIP_POSITION }, { Target_t::HandLeftDorsal, WRIST_MOTOR_POSITION }, + }; + static constexpr const OutputLayout_t TactGloveRightLayout[] = { + { Target_t::HandRightThumb, FINGERTIP_POSITION }, { Target_t::HandRightIndex, FINGERTIP_POSITION }, + { Target_t::HandRightMiddle, FINGERTIP_POSITION }, { Target_t::HandRightRing, FINGERTIP_POSITION }, + { Target_t::HandRightLittle, FINGERTIP_POSITION }, { Target_t::HandRightDorsal, WRIST_MOTOR_POSITION }, + }; +} // namespace BH diff --git a/lib/bhaptics/bh_encoding.hpp b/lib/bhaptics/bh_encoding.hpp index 4a4c7508..6a7c5490 100644 --- a/lib/bhaptics/bh_encoding.hpp +++ b/lib/bhaptics/bh_encoding.hpp @@ -1,55 +1,91 @@ #pragma once -#include <haptic_body.hpp> #include <cstring> +#include <haptic_body.hpp> -namespace BH -{ - class Decoder - { +namespace BH { + class Decoder { public: typedef SenseShift::Body::Haptics::VibroEffectData_t VibroEffectData_t; typedef SenseShift::Body::Haptics::EffectData_t EffectData_t; typedef SenseShift::Body::Haptics::Effect_t Effect_t; typedef SenseShift::Body::Haptics::Target_t Target_t; typedef SenseShift::Body::Haptics::Position_t Position_t; - typedef std::tuple<Effect_t, Target_t, Position_t> OutputLayout_t; + typedef std::tuple<Target_t, Position_t> OutputLayout_t; static const size_t VEST_LAYOUT_SIZE = 40; static const size_t VEST_PAYLOAD_SIZE = 20; + template<size_t N> + static void applyPlain( + SenseShift::Body::Haptics::HapticBody* output, + const uint8_t (&value)[N], + const OutputLayout_t (&layout)[N], + const Effect_t effect + ) + { + for (size_t i = 0; i < N; i++) { + const auto [target, position] = layout[i]; + const uint8_t byte = value[i]; + + output->effect({ + .effect = effect, + .target = target, + .position = position, + .data = effectDataFromByte(effect, byte), + }); + } + } + + template<size_t N> + static void applyPlain( + SenseShift::Body::Haptics::HapticBody* output, + std::string& value, + const OutputLayout_t (&layout)[N], + const Effect_t effect + ) + { + std::uint8_t buf[N]; + std::size_t copyLength = std::min(value.size(), sizeof(buf)); + std::memcpy(buf, value.c_str(), copyLength); + + applyPlain(output, buf, layout, effect); + } + /** * Apply plain-encoded data to the output. */ template<size_t N> static void applyPlain( - SenseShift::Body::Haptics::HapticBody* output, - const uint8_t (&value)[N], - const Position_t (&layout)[N], - const Effect_t effect, - const Target_t target - ) { + SenseShift::Body::Haptics::HapticBody* output, + const uint8_t (&value)[N], + const Position_t (&layout)[N], + const Effect_t effect, + const Target_t target + ) + { for (size_t i = 0; i < N; i++) { - auto position = layout[i]; - uint8_t byte = value[i]; + const auto position = layout[i]; + const uint8_t byte = value[i]; output->effect({ - .effect = effect, - .target = target, - .position = position, - .data = effectDataFromByte(effect, byte), + .effect = effect, + .target = target, + .position = position, + .data = effectDataFromByte(effect, byte), }); } } template<size_t N> static void applyPlain( - SenseShift::Body::Haptics::HapticBody* output, - std::string& value, - const Position_t (&layout)[N], - const Effect_t effect, - const Target_t target - ) { + SenseShift::Body::Haptics::HapticBody* output, + std::string& value, + const Position_t (&layout)[N], + const Effect_t effect, + const Target_t target + ) + { std::uint8_t buf[6]; std::size_t copyLength = std::min(value.size(), sizeof(buf)); std::memcpy(buf, value.c_str(), copyLength); @@ -61,43 +97,37 @@ namespace BH * Apply vest-encoded data to the output. */ static void applyVest( - SenseShift::Body::Haptics::HapticBody* output, - const uint8_t (&value)[VEST_PAYLOAD_SIZE], - const Position_t (&layout)[VEST_LAYOUT_SIZE] - ) { + SenseShift::Body::Haptics::HapticBody* output, + const uint8_t (&value)[VEST_PAYLOAD_SIZE], + const Position_t (&layout)[VEST_LAYOUT_SIZE] + ) + { for (size_t i = 0; i < VEST_PAYLOAD_SIZE; i++) { uint8_t byte = value[i]; uint actIndex = i * 2; const auto target = (actIndex < 10 || actIndex >= 30) ? Target_t::ChestFront : Target_t::ChestBack; output->effect({ - .effect = Effect_t::Vibro, - .target = target, - .position = layout[actIndex], - .data = effectDataFromByte( - Effect_t::Vibro, - ((byte >> 4) & 0xf), - 15 - ), + .effect = Effect_t::Vibro, + .target = target, + .position = layout[actIndex], + .data = effectDataFromByte(Effect_t::Vibro, ((byte >> 4) & 0xf), 15), }); output->effect({ - .effect = Effect_t::Vibro, - .target = target, - .position = layout[actIndex + 1], - .data = effectDataFromByte( - Effect_t::Vibro, - (byte & 0xf), - 15 - ), + .effect = Effect_t::Vibro, + .target = target, + .position = layout[actIndex + 1], + .data = effectDataFromByte(Effect_t::Vibro, (byte & 0xf), 15), }); } } static void applyVest( - SenseShift::Body::Haptics::HapticBody* output, - std::string& value, - const Position_t (&layout)[VEST_LAYOUT_SIZE] - ) { + SenseShift::Body::Haptics::HapticBody* output, + std::string& value, + const Position_t (&layout)[VEST_LAYOUT_SIZE] + ) + { std::uint8_t buf[VEST_PAYLOAD_SIZE]; std::size_t copyLength = std::min(value.size(), sizeof(buf)); std::memcpy(buf, value.c_str(), copyLength); @@ -108,13 +138,14 @@ namespace BH /** * Apply grouped vest-encoded data to the output. */ - template <size_t N> + template<size_t N> static void applyVestGrouped( - SenseShift::Body::Haptics::HapticBody* output, - const uint8_t (&value)[VEST_PAYLOAD_SIZE], - const Position_t (&layout)[VEST_LAYOUT_SIZE], - const uint8_t (&layoutGroups)[N] - ) { + SenseShift::Body::Haptics::HapticBody* output, + const uint8_t (&value)[VEST_PAYLOAD_SIZE], + const Position_t (&layout)[VEST_LAYOUT_SIZE], + const uint8_t (&layoutGroups)[N] + ) + { uint8_t result[VEST_LAYOUT_SIZE]; // Unpack values @@ -155,25 +186,22 @@ namespace BH const auto target = (i < 10 || i >= 30) ? Target_t::ChestFront : Target_t::ChestBack; output->effect({ - .effect = Effect_t::Vibro, - .target = target, - .position = layout[i], - .data = effectDataFromByte( - Effect_t::Vibro, - result[i], - 15 - ), + .effect = Effect_t::Vibro, + .target = target, + .position = layout[i], + .data = effectDataFromByte(Effect_t::Vibro, result[i], 15), }); } } - template <size_t N> + template<size_t N> static void applyVestGrouped( - SenseShift::Body::Haptics::HapticBody* output, - std::string& value, - const Position_t (&layout)[VEST_LAYOUT_SIZE], - const uint8_t (&layoutGroups)[N] - ) { + SenseShift::Body::Haptics::HapticBody* output, + std::string& value, + const Position_t (&layout)[VEST_LAYOUT_SIZE], + const uint8_t (&layoutGroups)[N] + ) + { std::uint8_t buf[VEST_PAYLOAD_SIZE]; std::size_t copyLength = std::min(value.size(), sizeof(buf)); std::memcpy(buf, value.c_str(), copyLength); @@ -182,17 +210,13 @@ namespace BH } private: - static const EffectData_t effectDataFromByte( - const Effect_t& effect, - const uint8_t byte, - const uint8_t maxValue = 100 - ) { + static const EffectData_t + effectDataFromByte(const Effect_t effect, const uint8_t byte, const uint8_t maxValue = 100) + { switch (effect) { case Effect_t::Vibro: return VibroEffectData_t( - OH::simpleMap<VibroEffectData_t::Intensity_t>( - byte, maxValue, VibroEffectData_t::INTENSITY_MAX - ) + OH::simpleMap<VibroEffectData_t::Intensity_t>(byte, maxValue, VibroEffectData_t::INTENSITY_MAX) ); default: throw std::runtime_error("Unknown effect"); diff --git a/lib/hands/hand_interface.hpp b/lib/hands/hand_interface.hpp new file mode 100644 index 00000000..34dca343 --- /dev/null +++ b/lib/hands/hand_interface.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include <cstdint> +#include <haptics_interface.hpp> + +namespace SenseShift::Body { + namespace Hands { + typedef std::uint8_t HandPositionIndex_t; + typedef enum class HandPosition : HandPositionIndex_t { Left, Right } HandPosition_t; + + 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_t FINGERTIP_POSITION(127, 16); + } // namespace Haptics + } // namespace Hands +} // namespace SenseShift::Body diff --git a/lib/haptics/haptics_interface.hpp b/lib/haptics/haptics_interface.hpp index 26bd2b86..ca926f21 100644 --- a/lib/haptics/haptics_interface.hpp +++ b/lib/haptics/haptics_interface.hpp @@ -21,10 +21,27 @@ namespace SenseShift::Body::Haptics { Invalid = TARGET_INVALID, ChestFront = 0x00, ChestBack = 0x01, + // Legacy backword compatibility Accessory [[deprecated]] = 0x02, - FaceFront = 0x03, + FaceFront, + + HandLeftThumb, + HandLeftIndex, + HandLeftMiddle, + HandLeftRing, + HandLeftLittle, + HandLeftVolar, // Palm + HandLeftDorsal, // Back + + HandRightThumb, + HandRightIndex, + HandRightMiddle, + HandRightRing, + HandRightLittle, + HandRightVolar, // Palm + HandRightDorsal, // Back // TODO: arms, legs, etc. } Target_t; diff --git a/platformio.ini b/platformio.ini index f88d3a17..c11d81a2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -27,7 +27,7 @@ build_flags = ; -D DEBUG_ESP_PORT=Serial ; -D SERIAL_PLOTTER=true ; -D BATTERY_ENABLED=true -; -D BLUETOOTH_USE_NIMBLE=false + -D BLUETOOTH_USE_NIMBLE=true build_src_filter = +<*> diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index e73993c4..7f153779 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -1,5 +1,6 @@ #include <bh_types.hpp> #include <bh_encoding.hpp> +#include <bh_devices.hpp> #include <unity.h> @@ -212,6 +213,50 @@ void test_layout_tactal(void) TEST_ASSERT_EQUAL_INT(3931, actuator5->intensity); } +void test_layout_tactglove(void) +{ + TestActuator* actuatorThumb = new TestActuator(); + TestActuator* actuatorIndex = new TestActuator(); + TestActuator* actuatorMiddle = new TestActuator(); + TestActuator* actuatorRing = new TestActuator(); + TestActuator* actuatorLittle = new TestActuator(); + TestActuator* actuatorWrist = new TestActuator(); + + const auto& bhLayout = BH::TactGloveLeftLayout; + + auto thumb = new VibroPlane({{ std::get<2>(bhLayout[0]), actuatorThumb }}); + auto index = new VibroPlane({{ std::get<2>(bhLayout[1]), actuatorIndex }}); + auto middle = new VibroPlane({{ std::get<2>(bhLayout[2]), actuatorMiddle }}); + auto ring = new VibroPlane({{ std::get<2>(bhLayout[3]), actuatorRing }}); + auto little = new VibroPlane({{ std::get<2>(bhLayout[4]), actuatorLittle }}); + auto wrist = new VibroPlane({{ std::get<2>(bhLayout[5]), actuatorWrist }}); + + auto body = new HapticBody(); + + body->addTarget(Target::HandLeftThumb, thumb); + body->addTarget(Target::HandLeftIndex, index); + body->addTarget(Target::HandLeftMiddle, middle); + body->addTarget(Target::HandLeftRing, ring); + body->addTarget(Target::HandLeftLittle, little); + body->addTarget(Target::HandLeftDorsal, wrist); + + Decoder::applyPlain(body, { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 }, bhLayout); + TEST_ASSERT_EQUAL_INT(4095, actuatorThumb->intensity); + TEST_ASSERT_EQUAL_INT(0, actuatorIndex->intensity); + TEST_ASSERT_EQUAL_INT(0, actuatorMiddle->intensity); + TEST_ASSERT_EQUAL_INT(0, actuatorRing->intensity); + TEST_ASSERT_EQUAL_INT(0, actuatorLittle->intensity); + TEST_ASSERT_EQUAL_INT(0, actuatorWrist->intensity); + + Decoder::applyPlain(body, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, bhLayout); + TEST_ASSERT_EQUAL_INT(655, actuatorThumb->intensity); + TEST_ASSERT_EQUAL_INT(1310, actuatorIndex->intensity); + TEST_ASSERT_EQUAL_INT(1965, actuatorMiddle->intensity); + TEST_ASSERT_EQUAL_INT(2620, actuatorRing->intensity); + TEST_ASSERT_EQUAL_INT(3276, actuatorLittle->intensity); + TEST_ASSERT_EQUAL_INT(3931, actuatorWrist->intensity); +} + int process(void) { UNITY_BEGIN(); @@ -219,9 +264,6 @@ int process(void) RUN_TEST(test_layout_tactsuitx16); RUN_TEST(test_layout_tactsuitx40); RUN_TEST(test_layout_tactal); - // RUN_TEST(test_layout_tactosy2); - // RUN_TEST(test_layout_tactosyh); - // RUN_TEST(test_layout_tactosyf); return UNITY_END(); } From 27c6650b53c888588a899c6b480a5432fe589069 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 21 Aug 2023 14:45:24 +0400 Subject: [PATCH 06/82] refactor(bHaptics): restructure lib --- firmware/mode_configs/bhaptics/tactal.cpp | 18 +- lib/bhaptics/bh_devices.hpp | 95 ------- lib/bhaptics/bh_types.hpp | 5 - lib/bhaptics/bh_types_c.h | 3 - lib/bhaptics/senseshift/bh/constants.hpp | 17 ++ .../bh/devices.hpp} | 145 ++++++---- .../bh/encoding.hpp} | 36 +-- lib/bhaptics_ble/connection_bhble.cpp | 256 ----------------- .../senseshift/bh/ble/connection.cpp | 260 ++++++++++++++++++ .../bh/ble/connection.hpp} | 68 ++--- .../senseshift/bh/ble/constants.hpp | 59 ++++ test/test_bhaptics_encoding/main.cpp | 16 +- 12 files changed, 501 insertions(+), 477 deletions(-) delete mode 100644 lib/bhaptics/bh_devices.hpp delete mode 100644 lib/bhaptics/bh_types.hpp delete mode 100644 lib/bhaptics/bh_types_c.h create mode 100644 lib/bhaptics/senseshift/bh/constants.hpp rename lib/bhaptics/{bh_constants.hpp => senseshift/bh/devices.hpp} (58%) rename lib/bhaptics/{bh_encoding.hpp => senseshift/bh/encoding.hpp} (88%) delete mode 100644 lib/bhaptics_ble/connection_bhble.cpp create mode 100644 lib/bhaptics_ble/senseshift/bh/ble/connection.cpp rename lib/bhaptics_ble/{connection_bhble.hpp => senseshift/bh/ble/connection.hpp} (67%) create mode 100644 lib/bhaptics_ble/senseshift/bh/ble/constants.hpp diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index 17982748..89b3a620 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -6,8 +6,9 @@ #include "senseshift.h" -#include <bh_encoding.hpp> -#include <connection_bhble.hpp> +#include <senseshift/bh/devices.hpp> +#include <senseshift/bh/encoding.hpp> +#include <senseshift/bh/ble/connection.hpp> #include <output_writers/pwm.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true @@ -17,7 +18,6 @@ using namespace OH; using namespace SenseShift; using namespace SenseShift::Body::Haptics; -using namespace BH; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; @@ -39,16 +39,14 @@ void setupMode() app->getHapticBody()->setup(); - uint8_t serialNumber[BH_SERIAL_NUMBER_LENGTH] = BH_SERIAL_NUMBER; - ConnectionBHBLE_Config config = { + auto* bhBleConnection = new BH::BLE::Connection( + { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, - .serialNumber = serialNumber, - }; - auto* bhBleConnection = new ConnectionBHBLE( - config, + .serialNumber = BH_SERIAL_NUMBER, + }, [](std::string& value) -> void { - Decoder::applyPlain<6>(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); + BH::Decoder::applyPlain<6>(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); }, app ); diff --git a/lib/bhaptics/bh_devices.hpp b/lib/bhaptics/bh_devices.hpp deleted file mode 100644 index dd131e20..00000000 --- a/lib/bhaptics/bh_devices.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once - -#include <hand_interface.hpp> - -#pragma region TaxtSuit X16 - -#define BH_LAYOUT_TACTSUITX40_SIZE_X 4 -#define BH_LAYOUT_TACTSUITX40_SIZE_Y 5 -#define BH_LAYOUT_TACTSUITX40_MAKE_POINT(x, y) \ - SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_Y - 1) \ - ) - -// X * Y for front and back -#define BH_LAYOUT_TACTSUITX40_SIZE 40 -// clang-format off -#define BH_LAYOUT_TACTSUITX40 { \ - /* Front, left part */ \ - /* 0 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ - /* 1 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ - /* 2 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ - /* 3 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ - /* 4 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ - /* 5 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ - /* 6 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ - /* 7 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ - /* 8 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ - /* 9 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ - \ - /* Back */ \ - /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ - /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ - /* 12 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ - /* 13 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ - /* 14 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ - /* 15 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ - /* 16 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ - /* 17 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ - /* 18 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ - /* 19 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ - \ - /* 20 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ - /* 21 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ - /* 22 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ - /* 23 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ - /* 24 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ - /* 25 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ - /* 26 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ - /* 27 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ - /* 28 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ - /* 29 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) }, \ - \ - /* Front, again... Now right part */ \ - /* 30 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ - /* 31 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ - /* 32 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ - /* 33 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ - /* 34 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ - /* 35 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ - /* 36 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ - /* 37 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ - /* 38 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ - /* 39 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) } \ -} -// clang-format on - -#pragma endregion BH_DEVICE_TACTSUITX40 - -namespace BH { - using namespace SenseShift::Body::Hands::Haptics; - - typedef SenseShift::Body::Haptics::Effect_t Effect_t; - typedef SenseShift::Body::Haptics::Target_t Target_t; - typedef SenseShift::Body::Haptics::Position_t Position_t; - typedef std::tuple<Target_t, Position_t> OutputLayout_t; - - // TactSuit X40 motor positions - static constexpr const OutputLayout_t TactSuitX40Layout[] = BH_LAYOUT_TACTSUITX40; - - // TactGlove Wrist motor position - static constexpr const Position_t WRIST_MOTOR_POSITION(127, 191); - static constexpr const OutputLayout_t TactGloveLeftLayout[] = { - { Target_t::HandLeftThumb, FINGERTIP_POSITION }, { Target_t::HandLeftIndex, FINGERTIP_POSITION }, - { Target_t::HandLeftMiddle, FINGERTIP_POSITION }, { Target_t::HandLeftRing, FINGERTIP_POSITION }, - { Target_t::HandLeftLittle, FINGERTIP_POSITION }, { Target_t::HandLeftDorsal, WRIST_MOTOR_POSITION }, - }; - static constexpr const OutputLayout_t TactGloveRightLayout[] = { - { Target_t::HandRightThumb, FINGERTIP_POSITION }, { Target_t::HandRightIndex, FINGERTIP_POSITION }, - { Target_t::HandRightMiddle, FINGERTIP_POSITION }, { Target_t::HandRightRing, FINGERTIP_POSITION }, - { Target_t::HandRightLittle, FINGERTIP_POSITION }, { Target_t::HandRightDorsal, WRIST_MOTOR_POSITION }, - }; -} // namespace BH diff --git a/lib/bhaptics/bh_types.hpp b/lib/bhaptics/bh_types.hpp deleted file mode 100644 index 3cba875f..00000000 --- a/lib/bhaptics/bh_types.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "bh_types_c.h" - -#include "bh_constants.hpp" diff --git a/lib/bhaptics/bh_types_c.h b/lib/bhaptics/bh_types_c.h deleted file mode 100644 index 20bf1928..00000000 --- a/lib/bhaptics/bh_types_c.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#include <stdint.h> diff --git a/lib/bhaptics/senseshift/bh/constants.hpp b/lib/bhaptics/senseshift/bh/constants.hpp new file mode 100644 index 00000000..930a7e3e --- /dev/null +++ b/lib/bhaptics/senseshift/bh/constants.hpp @@ -0,0 +1,17 @@ +#pragma once + +#ifndef BH_FIRMWARE_VERSION_MAJOR +#define BH_FIRMWARE_VERSION_MAJOR ((uint8_t) UINT8_MAX) +#endif + +#ifndef BH_FIRMWARE_VERSION_MINOR +#define BH_FIRMWARE_VERSION_MINOR ((uint8_t) UINT8_MAX) +#endif + +#ifndef BH_FIRMWARE_VERSION +#define BH_FIRMWARE_VERSION (uint16_t)((BH_FIRMWARE_VERSION_MAJOR << 8) | BH_FIRMWARE_VERSION_MINOR) +#endif + +// TODO: use enum +#define NO_AUDIO_CABLE 0 +#define AUDIO_CABLE 1 diff --git a/lib/bhaptics/bh_constants.hpp b/lib/bhaptics/senseshift/bh/devices.hpp similarity index 58% rename from lib/bhaptics/bh_constants.hpp rename to lib/bhaptics/senseshift/bh/devices.hpp index c430911a..e500c09f 100644 --- a/lib/bhaptics/bh_constants.hpp +++ b/lib/bhaptics/senseshift/bh/devices.hpp @@ -1,34 +1,81 @@ #pragma once +#include <hand_interface.hpp> #include <haptic_plane.hpp> -#if defined(ESP32) -#include <BLEUUID.h> -#endif +#pragma region BH_DEVICE_TACTSUITX40 -#define BH_SERIAL_NUMBER_LENGTH 10 - -#ifndef BH_FIRMWARE_VERSION_MAJOR -#define BH_FIRMWARE_VERSION_MAJOR ((uint8_t) UINT8_MAX) -#endif - -#ifndef BH_FIRMWARE_VERSION_MINOR -#define BH_FIRMWARE_VERSION_MINOR ((uint8_t) UINT8_MAX) -#endif +#define BH_LAYOUT_TACTSUITX40_SIZE_X 4 +#define BH_LAYOUT_TACTSUITX40_SIZE_Y 5 +#define BH_LAYOUT_TACTSUITX40_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + x, \ + y, \ + (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_X - 1), \ + (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_Y - 1) \ + ) -#ifndef BH_FIRMWARE_VERSION -#define BH_FIRMWARE_VERSION (uint16_t)((BH_FIRMWARE_VERSION_MAJOR << 8) | BH_FIRMWARE_VERSION_MINOR) -#endif +// X * Y for front and back +#define BH_LAYOUT_TACTSUITX40_SIZE 40 +// clang-format off +#define BH_LAYOUT_TACTSUITX40 { \ + /* Front, left part */ \ + /* 0 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ + /* 1 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ + /* 2 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ + /* 3 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ + /* 4 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ + /* 5 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ + /* 6 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ + /* 7 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ + /* 8 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ + /* 9 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ + \ + /* Back */ \ + /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ + /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ + /* 12 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ + /* 13 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ + /* 14 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ + /* 15 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ + /* 16 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ + /* 17 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ + /* 18 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ + /* 19 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ + \ + /* 20 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ + /* 21 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ + /* 22 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ + /* 23 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ + /* 24 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ + /* 25 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ + /* 26 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ + /* 27 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ + /* 28 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ + /* 29 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) }, \ + \ + /* Front, again... Now right part */ \ + /* 30 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ + /* 31 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ + /* 32 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ + /* 33 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ + /* 34 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ + /* 35 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ + /* 36 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ + /* 37 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ + /* 38 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ + /* 39 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) } \ +} +// clang-format on -#define NO_AUDIO_CABLE 0 -#define AUDIO_CABLE 1 +#pragma endregion BH_DEVICE_TACTSUITX40 #pragma region BH_DEVICE_TACTSUITX16 #define BH_LAYOUT_TACTSUITX16_SIZE_X 4 #define BH_LAYOUT_TACTSUITX16_SIZE_Y 2 #define BH_LAYOUT_TACTSUITX16_MAKE_POINT(x, y) \ - SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ x, \ y, \ (oh_output_coord_t) (BH_LAYOUT_TACTSUITX16_SIZE_X - 1), \ @@ -106,7 +153,7 @@ #define BH_LAYOUT_TACTAL_SIZE_X 6 #define BH_LAYOUT_TACTAL_SIZE_Y 1 #define BH_LAYOUT_TACTAL_MAKE_POINT(x, y) \ - SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ x, \ y, \ (oh_output_coord_t) (BH_LAYOUT_TACTAL_SIZE_X - 1), \ @@ -132,7 +179,7 @@ #define BH_LAYOUT_TACTVISOR_SIZE_X 4 #define BH_LAYOUT_TACTVISOR_SIZE_Y 1 #define BH_LAYOUT_TACTVISOR_MAKE_POINT(x, y) \ - SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ x, \ y, \ (oh_output_coord_t) (BH_LAYOUT_TACTVISOR_SIZE_X - 1), \ @@ -156,7 +203,7 @@ #define BH_LAYOUT_TACTOSY2_SIZE_X 3 #define BH_LAYOUT_TACTOSY2_SIZE_Y 2 #define BH_LAYOUT_TACTOSY2_MAKE_POINT(x, y) \ - SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ x, \ y, \ (oh_output_coord_t) (BH_LAYOUT_TACTOSY2_SIZE_X - 1), \ @@ -178,7 +225,7 @@ #define BH_LAYOUT_TACTOSYH_SIZE_X 1 #define BH_LAYOUT_TACTOSYH_SIZE_Y 3 #define BH_LAYOUT_TACTOSYH_MAKE_POINT(x, y) \ - SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ x, \ y, \ (oh_output_coord_t) (BH_LAYOUT_TACTOSYH_SIZE_X - 1), \ @@ -197,7 +244,7 @@ #define BH_LAYOUT_TACTOSYF_SIZE_X 1 #define BH_LAYOUT_TACTOSYF_SIZE_Y 3 #define BH_LAYOUT_TACTOSYF_MAKE_POINT(x, y) \ - SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ x, \ y, \ (oh_output_coord_t) (BH_LAYOUT_TACTOSYF_SIZE_X - 1), \ @@ -211,30 +258,28 @@ #pragma endregion BH_DEVICE_TACTOSYF -// All below are weird choices of bHaptics engineers... -// Why to use unconventional UUIDs, that are reserved for other purposes? -// You have an unlimited amount of other UUIDs - -// Main service for communication -#define BH_BLE_SERVICE_MOTOR_UUID BLEUUID("6e400001-b5a3-f393-e0a9-e50e24dcca9e") // Nordic UART Service - -// Legacy Characteristic to create haptic feedback -#define BH_BLE_SERVICE_MOTOR_CHAR_MOTOR_UUID BLEUUID("6e400002-b5a3-f393-e0a9-e50e24dcca9e") // Nordic UART RX - -// Characteristic for Device S/N -#define BH_BLE_SERVICE_MOTOR_CHAR_SERIAL_KEY_UUID BLEUUID("6e400003-b5a3-f393-e0a9-e50e24dcca9e") // Nordic UART TX - -// Glow Color -#define BH_BLE_SERVICE_MOTOR_CHAR_CONFIG_UUID BLEUUID("6e400005-b5a3-f393-e0a9-e50e24dcca9e") -#define BH_BLE_SERVICE_MOTOR_CHAR_VERSION_UUID BLEUUID("6e400007-b5a3-f393-e0a9-e50e24dcca9e") -#define BH_BLE_SERVICE_MOTOR_CHAR_BATTERY_UUID BLEUUID("6e400008-b5a3-f393-e0a9-e50e24dcca9e") -#define BH_BLE_SERVICE_MOTOR_CHAR_MOTOR_STABLE_UUID BLEUUID("6e40000a-b5a3-f393-e0a9-e50e24dcca9e") -#define BH_BLE_SERVICE_MOTOR_CHAR_TACTSUIT_MONITOR_UUID BLEUUID("6e40000b-b5a3-f393-e0a9-e50e24dcca9e") -#define BH_BLE_SERVICE_MOTOR_CHAR_ATH_GLOBAL_CONF_UUID \ - BLEUUID("6e40000c-b5a3-f393-e0a9-e50e24dcca9e") // Audio-to-Haptic -#define BH_BLE_SERVICE_MOTOR_CHAR_ATH_THEME_UUID BLEUUID("6e40000d-b5a3-f393-e0a9-e50e24dcca9e") // Audio-to-Haptic -#define BH_BLE_SERVICE_MOTOR_CHAR_MOTTOR_MAPPING_UUID BLEUUID("6e40000e-b5a3-f393-e0a9-e50e24dcca9e") -#define BH_BLE_SERVICE_MOTOR_CHAR_SIGNATURE_PATTERN_UUID BLEUUID("6e40000f-b5a3-f393-e0a9-e50e24dcca9e") - -#define BH_BLE_SERVICE_DFU_UUID BLEUUID("0000fe59-0000-1000-8000-00805f9b34fb") -#define BH_BLE_SERVICE_DFU_CHAR_CONTROL_UUID BLEUUID("8ec90003-f315-4f60-9fb8-838830daea50") +namespace SenseShift::BH { + using namespace ::SenseShift::Body::Hands::Haptics; + + using Effect_t = ::SenseShift::Body::Haptics::Effect_t; + using Target_t = ::SenseShift::Body::Haptics::Target_t; + using Position_t = ::SenseShift::Body::Haptics::Position_t; + + typedef std::tuple<Target_t, Position_t> OutputLayout_t; + + // TactSuit X40 motor positions + static constexpr const OutputLayout_t TactSuitX40Layout[] = BH_LAYOUT_TACTSUITX40; + + // TactGlove Wrist motor position + static constexpr const Position_t WRIST_MOTOR_POSITION(127, 191); + static constexpr const OutputLayout_t TactGloveLeftLayout[] = { + { Target_t::HandLeftThumb, FINGERTIP_POSITION }, { Target_t::HandLeftIndex, FINGERTIP_POSITION }, + { Target_t::HandLeftMiddle, FINGERTIP_POSITION }, { Target_t::HandLeftRing, FINGERTIP_POSITION }, + { Target_t::HandLeftLittle, FINGERTIP_POSITION }, { Target_t::HandLeftDorsal, WRIST_MOTOR_POSITION }, + }; + static constexpr const OutputLayout_t TactGloveRightLayout[] = { + { Target_t::HandRightThumb, FINGERTIP_POSITION }, { Target_t::HandRightIndex, FINGERTIP_POSITION }, + { Target_t::HandRightMiddle, FINGERTIP_POSITION }, { Target_t::HandRightRing, FINGERTIP_POSITION }, + { Target_t::HandRightLittle, FINGERTIP_POSITION }, { Target_t::HandRightDorsal, WRIST_MOTOR_POSITION }, + }; +} // namespace SenseShift::BH diff --git a/lib/bhaptics/bh_encoding.hpp b/lib/bhaptics/senseshift/bh/encoding.hpp similarity index 88% rename from lib/bhaptics/bh_encoding.hpp rename to lib/bhaptics/senseshift/bh/encoding.hpp index 6a7c5490..c6b876e1 100644 --- a/lib/bhaptics/bh_encoding.hpp +++ b/lib/bhaptics/senseshift/bh/encoding.hpp @@ -3,14 +3,18 @@ #include <cstring> #include <haptic_body.hpp> -namespace BH { +namespace SenseShift::BH { class Decoder { public: - typedef SenseShift::Body::Haptics::VibroEffectData_t VibroEffectData_t; - typedef SenseShift::Body::Haptics::EffectData_t EffectData_t; - typedef SenseShift::Body::Haptics::Effect_t Effect_t; - typedef SenseShift::Body::Haptics::Target_t Target_t; - typedef SenseShift::Body::Haptics::Position_t Position_t; + using VibroEffectData_t = ::SenseShift::Body::Haptics::VibroEffectData_t; + using EffectData_t = ::SenseShift::Body::Haptics::EffectData_t; + + using Effect_t = ::SenseShift::Body::Haptics::Effect_t; + using Target_t = ::SenseShift::Body::Haptics::Target_t; + using Position_t = ::SenseShift::Body::Haptics::Position_t; + + using HapticBody_t = ::SenseShift::Body::Haptics::HapticBody; + typedef std::tuple<Target_t, Position_t> OutputLayout_t; static const size_t VEST_LAYOUT_SIZE = 40; @@ -18,7 +22,7 @@ namespace BH { template<size_t N> static void applyPlain( - SenseShift::Body::Haptics::HapticBody* output, + HapticBody_t* output, const uint8_t (&value)[N], const OutputLayout_t (&layout)[N], const Effect_t effect @@ -39,7 +43,7 @@ namespace BH { template<size_t N> static void applyPlain( - SenseShift::Body::Haptics::HapticBody* output, + HapticBody_t* output, std::string& value, const OutputLayout_t (&layout)[N], const Effect_t effect @@ -57,7 +61,7 @@ namespace BH { */ template<size_t N> static void applyPlain( - SenseShift::Body::Haptics::HapticBody* output, + HapticBody_t* output, const uint8_t (&value)[N], const Position_t (&layout)[N], const Effect_t effect, @@ -79,14 +83,14 @@ namespace BH { template<size_t N> static void applyPlain( - SenseShift::Body::Haptics::HapticBody* output, + HapticBody_t* output, std::string& value, const Position_t (&layout)[N], const Effect_t effect, const Target_t target ) { - std::uint8_t buf[6]; + std::uint8_t buf[N]; std::size_t copyLength = std::min(value.size(), sizeof(buf)); std::memcpy(buf, value.c_str(), copyLength); @@ -97,7 +101,7 @@ namespace BH { * Apply vest-encoded data to the output. */ static void applyVest( - SenseShift::Body::Haptics::HapticBody* output, + HapticBody_t* output, const uint8_t (&value)[VEST_PAYLOAD_SIZE], const Position_t (&layout)[VEST_LAYOUT_SIZE] ) @@ -123,7 +127,7 @@ namespace BH { } static void applyVest( - SenseShift::Body::Haptics::HapticBody* output, + HapticBody_t* output, std::string& value, const Position_t (&layout)[VEST_LAYOUT_SIZE] ) @@ -140,7 +144,7 @@ namespace BH { */ template<size_t N> static void applyVestGrouped( - SenseShift::Body::Haptics::HapticBody* output, + HapticBody_t* output, const uint8_t (&value)[VEST_PAYLOAD_SIZE], const Position_t (&layout)[VEST_LAYOUT_SIZE], const uint8_t (&layoutGroups)[N] @@ -196,7 +200,7 @@ namespace BH { template<size_t N> static void applyVestGrouped( - SenseShift::Body::Haptics::HapticBody* output, + HapticBody_t* output, std::string& value, const Position_t (&layout)[VEST_LAYOUT_SIZE], const uint8_t (&layoutGroups)[N] @@ -223,4 +227,4 @@ namespace BH { } } }; -} // namespace BH +} // namespace SenseShift::BH diff --git a/lib/bhaptics_ble/connection_bhble.cpp b/lib/bhaptics_ble/connection_bhble.cpp deleted file mode 100644 index 6367b64d..00000000 --- a/lib/bhaptics_ble/connection_bhble.cpp +++ /dev/null @@ -1,256 +0,0 @@ -#include "connection_bhble.hpp" - -#include <events.hpp> -#include <haptic_body.hpp> - -#include <Arduino.h> - -#if defined(BLUETOOTH_USE_NIMBLE) && BLUETOOTH_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 -#define PROPERTY_WRITE NIMBLE_PROPERTY::WRITE -#define PROPERTY_WRITE_NR NIMBLE_PROPERTY::WRITE_NR -#define PROPERTY_BROADCAST NIMBLE_PROPERTY::BROADCAST -#define PROPERTY_NOTIFY NIMBLE_PROPERTY::NOTIFY -#define PROPERTY_INDICATE NIMBLE_PROPERTY::INDICATE -#else -#include <BLE2902.h> - -#define PROPERTY_READ BLECharacteristic::PROPERTY_READ -#define PROPERTY_WRITE BLECharacteristic::PROPERTY_WRITE -#define PROPERTY_WRITE_NR BLECharacteristic::PROPERTY_WRITE_NR -#define PROPERTY_BROADCAST BLECharacteristic::PROPERTY_BROADCAST -#define PROPERTY_NOTIFY BLECharacteristic::PROPERTY_NOTIFY -#define PROPERTY_INDICATE BLECharacteristic::PROPERTY_INDICATE -#endif - -class BHServerCallbacks final : public BLEServerCallbacks { - private: - OH::IEventDispatcher* dispatcher; - - public: - BHServerCallbacks(OH::IEventDispatcher* eventDispatcher) : dispatcher(eventDispatcher) {} - - void onConnect(BLEServer* pServer) - { - this->dispatcher->postEvent(new OH::IEvent(OH_EVENT_CONNECTED)); - } - - void onDisconnect(BLEServer* pServer) - { - this->dispatcher->postEvent(new OH::IEvent(OH_EVENT_DISCONNECTED)); - pServer->startAdvertising(); - } -}; - -class SerialOutputCharCallbacks : 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 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(BLUETOOTH_USE_NIMBLE) && BLUETOOTH_USE_NIMBLE == true - void onStatus(BLECharacteristic* pCharacteristic, Status s, int code) override -#else - 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() - ); - }; -}; - -class MotorCharCallbacks : public BLECharacteristicCallbacks { - private: - bh_motor_handler_t motorTransformer; - - public: - MotorCharCallbacks(bh_motor_handler_t motorTransformer) : motorTransformer(motorTransformer) {} - - void onWrite(BLECharacteristic* pCharacteristic) override - { - std::string value = pCharacteristic->getValue(); - - this->motorTransformer(value); - }; -}; - -class ConfigCharCallbacks : public BLECharacteristicCallbacks { - void onWrite(BLECharacteristic* pCharacteristic) override - { - auto value = pCharacteristic->getValue(); - - if (value.length() != 3) { - return; - } - - 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 BH::ConnectionBHBLE::begin() -{ - BLEDevice::init(this->config.deviceName); - - this->callbacks->postInit(); - - this->bleServer = BLEDevice::createServer(); - - this->bleServer->setCallbacks(new BHServerCallbacks(this->eventDispatcher)); - - 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); - - // Each characteristic needs 2 handles and descriptor 1 handle. - this->motorService = this->bleServer->createService(BH_BLE_SERVICE_MOTOR_UUID); - - { - 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* 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()); - } - - { - auto* serialNumberChar = this->motorService->createCharacteristic( - BH_BLE_SERVICE_MOTOR_CHAR_SERIAL_KEY_UUID, - PROPERTY_READ | PROPERTY_WRITE - ); - serialNumberChar->setValue(this->config.serialNumber, BH_SERIAL_NUMBER_LENGTH); - serialNumberChar->setCallbacks(new SerialOutputCharCallbacks()); - } - - { - 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(BLUETOOTH_USE_NIMBLE) || BLUETOOTH_USE_NIMBLE != true - batteryChar->addDescriptor(new BLE2902()); -#endif - - // original bHaptics Player require non-null value for battery level, otherwise it crashes -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true - uint16_t defaultLevel = 0; -#else - uint16_t defaultLevel = 100; -#endif - - this->batteryChar->setValue(defaultLevel); - // this->batteryChar->notify(); - } - - { - auto* versionChar = - this->motorService->createCharacteristic(BH_BLE_SERVICE_MOTOR_CHAR_VERSION_UUID, PROPERTY_READ); - versionChar->setCallbacks(new SerialOutputCharCallbacks()); - 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 SerialOutputCharCallbacks()); - -#if !defined(BLUETOOTH_USE_NIMBLE) || BLUETOOTH_USE_NIMBLE != true - monitorChar->addDescriptor(new BLE2902()); -#endif - - uint16_t audioCableState = NO_AUDIO_CABLE; - monitorChar->setValue(audioCableState); - } - - // auto* athGlobalChar = this->motorService->createCharacteristic( - // BH_BLE_SERVICE_MOTOR_CHAR_ATH_GLOBAL_CONF_UUID, - // PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | PROPERTY_WRITE_NR - // ); - // athGlobalChar->setCallbacks(new SerialOutputCharCallbacks()); - - // 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 SerialOutputCharCallbacks()); - - // 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 SerialOutputCharCallbacks()); - - // 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 SerialOutputCharCallbacks()); - - this->motorService->start(); - - { - auto dfuService = this->bleServer->createService(BH_BLE_SERVICE_DFU_UUID); - - auto* dfuControlChar = dfuService->createCharacteristic( - BH_BLE_SERVICE_MOTOR_CHAR_SIGNATURE_PATTERN_UUID, - PROPERTY_READ | PROPERTY_WRITE - ); - dfuService->start(); - } - - this->bleServer->getAdvertising()->start(); -} diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp new file mode 100644 index 00000000..a4f60bbc --- /dev/null +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -0,0 +1,260 @@ +#include "senseshift/bh/ble/connection.hpp" + +#include <senseshift/bh/constants.hpp> + +#include <events.hpp> +#include <haptic_body.hpp> + +#include <Arduino.h> + +#if defined(BLUETOOTH_USE_NIMBLE) && BLUETOOTH_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 +#define PROPERTY_WRITE NIMBLE_PROPERTY::WRITE +#define PROPERTY_WRITE_NR NIMBLE_PROPERTY::WRITE_NR +#define PROPERTY_BROADCAST NIMBLE_PROPERTY::BROADCAST +#define PROPERTY_NOTIFY NIMBLE_PROPERTY::NOTIFY +#define PROPERTY_INDICATE NIMBLE_PROPERTY::INDICATE +#else +#include <BLE2902.h> + +#define PROPERTY_READ BLECharacteristic::PROPERTY_READ +#define PROPERTY_WRITE BLECharacteristic::PROPERTY_WRITE +#define PROPERTY_WRITE_NR BLECharacteristic::PROPERTY_WRITE_NR +#define PROPERTY_BROADCAST BLECharacteristic::PROPERTY_BROADCAST +#define PROPERTY_NOTIFY BLECharacteristic::PROPERTY_NOTIFY +#define PROPERTY_INDICATE BLECharacteristic::PROPERTY_INDICATE +#endif + +namespace SenseShift::BH::BLE { + class BHServerCallbacks final : public BLEServerCallbacks { + private: + OH::IEventDispatcher* dispatcher; + + public: + BHServerCallbacks(OH::IEventDispatcher* eventDispatcher) : dispatcher(eventDispatcher) {} + + void onConnect(BLEServer* pServer) + { + this->dispatcher->postEvent(new OH::IEvent(OH_EVENT_CONNECTED)); + } + + void onDisconnect(BLEServer* pServer) + { + this->dispatcher->postEvent(new OH::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() + ); + }; + + 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() + ); + }; + + #if defined(BLUETOOTH_USE_NIMBLE) && BLUETOOTH_USE_NIMBLE == true + void onStatus(BLECharacteristic* pCharacteristic, Status s, int code) override + #else + 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() + ); + }; + }; + + class MotorCharCallbacks : public BLECharacteristicCallbacks { + private: + Connection::MotorHandler_t motorTransformer; + + public: + MotorCharCallbacks(Connection::MotorHandler_t motorTransformer) : motorTransformer(motorTransformer) {} + + void onWrite(BLECharacteristic* pCharacteristic) override + { + std::string value = pCharacteristic->getValue(); + + this->motorTransformer(value); + }; + }; + + class ConfigCharCallbacks : public BLECharacteristicCallbacks { + void onWrite(BLECharacteristic* pCharacteristic) override + { + auto value = pCharacteristic->getValue(); + + if (value.length() != 3) { + return; + } + + 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() + { + BLEDevice::init(this->config.deviceName); + + this->callbacks->postInit(); + + this->bleServer = BLEDevice::createServer(); + + this->bleServer->setCallbacks(new BHServerCallbacks(this->eventDispatcher)); + + 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); + + // Each characteristic needs 2 handles and descriptor 1 handle. + this->motorService = this->bleServer->createService(BH_BLE_SERVICE_MOTOR_UUID); + + { + 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* 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()); + } + + { + auto* serialNumberChar = this->motorService->createCharacteristic( + BH_BLE_SERVICE_MOTOR_CHAR_SERIAL_KEY_UUID, + PROPERTY_READ | PROPERTY_WRITE + ); + serialNumberChar->setValue(this->config.serialNumber, ConnectionConfig_t::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 + ); + + #if !defined(BLUETOOTH_USE_NIMBLE) || BLUETOOTH_USE_NIMBLE != true + batteryChar->addDescriptor(new BLE2902()); + #endif + + // original bHaptics Player require non-null value for battery level, otherwise it crashes + #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true + uint16_t defaultLevel = 0; + #else + uint16_t defaultLevel = 100; + #endif + + 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* 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(BLUETOOTH_USE_NIMBLE) || BLUETOOTH_USE_NIMBLE != true + monitorChar->addDescriptor(new BLE2902()); + #endif + + uint16_t audioCableState = NO_AUDIO_CABLE; + monitorChar->setValue(audioCableState); + } + + // auto* athGlobalChar = this->motorService->createCharacteristic( + // BH_BLE_SERVICE_MOTOR_CHAR_ATH_GLOBAL_CONF_UUID, + // PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | PROPERTY_WRITE_NR + // ); + // athGlobalChar->setCallbacks(new LogOutputCharCallbacks()); + + // 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_MOTOR_CHAR_SIGNATURE_PATTERN_UUID, + PROPERTY_READ | PROPERTY_WRITE + ); + dfuService->start(); + } + + this->bleServer->getAdvertising()->start(); + } +} diff --git a/lib/bhaptics_ble/connection_bhble.hpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp similarity index 67% rename from lib/bhaptics_ble/connection_bhble.hpp rename to lib/bhaptics_ble/senseshift/bh/ble/connection.hpp index 7645000f..f4d10f19 100644 --- a/lib/bhaptics_ble/connection_bhble.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -3,8 +3,8 @@ #include <abstract_connection.hpp> #include <utility.hpp> -#include <bh_constants.hpp> -#include <bh_types.hpp> +#include <senseshift/bh/constants.hpp> +#include <senseshift/bh/ble/constants.hpp> #include <Arduino.h> #include <esp_wifi.h> @@ -19,45 +19,30 @@ #include <abstract_battery.hpp> #endif -// typedef void (*bh_motor_handler_t)(std::string&); -typedef std::function<void(std::string&)> bh_motor_handler_t; +namespace SenseShift::BH::BLE { + typedef struct ConnectionConfig { + static constexpr size_t SN_LENGTH = 10; -namespace BH { - class BHBLEConnectionCallbacks { + std::string deviceName; + uint16_t appearance; + uint8_t serialNumber[SN_LENGTH]; + } ConnectionConfig_t; + + class ConnectionCallbacks { public: virtual void postInit() { log_v("Default postInit"); }; }; + static ConnectionCallbacks defaultCallback; - static BHBLEConnectionCallbacks defaultCallback; - - struct ConnectionBHBLE_Config { - std::string deviceName; - uint16_t appearance; - uint8_t* serialNumber; - }; - - class ConnectionBHBLE final : public OH::AbstractConnection, public OH::IEventListener { - private: - ConnectionBHBLE_Config config; - bh_motor_handler_t motorHandler; - OH::IEventDispatcher* eventDispatcher; - - BLEServer* bleServer = nullptr; - BLEService* motorService = nullptr; - BLECharacteristic* batteryChar = nullptr; - - BHBLEConnectionCallbacks* callbacks = &defaultCallback; - -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true - void handleBatteryChange(const OH::BatteryLevelEvent* event) const; -#endif - + class Connection final : public OH::AbstractConnection, public OH::IEventListener { public: - ConnectionBHBLE( - ConnectionBHBLE_Config& config, bh_motor_handler_t motorHandler, OH::IEventDispatcher* eventDispatcher + typedef std::function<void(std::string&)> MotorHandler_t; + + Connection( + const ConnectionConfig_t& config, MotorHandler_t motorHandler, OH::IEventDispatcher* eventDispatcher ) : config(config), motorHandler(motorHandler), eventDispatcher(eventDispatcher) { @@ -80,7 +65,7 @@ namespace BH { #endif }; - void setCallbacks(BHBLEConnectionCallbacks* pCallbacks) + void setCallbacks(ConnectionCallbacks* pCallbacks) { if (pCallbacks != nullptr) { this->callbacks = pCallbacks; @@ -88,5 +73,20 @@ namespace BH { this->callbacks = &defaultCallback; } }; + + private: + const ConnectionConfig_t& config; + MotorHandler_t motorHandler; + OH::IEventDispatcher* eventDispatcher; + + BLEServer* bleServer = nullptr; + BLEService* motorService = nullptr; + BLECharacteristic* batteryChar = nullptr; + + ConnectionCallbacks* callbacks = &defaultCallback; + +#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true + void handleBatteryChange(const OH::BatteryLevelEvent* event) const; +#endif }; -} // namespace BH +} // namespace SenseShift::BH::BLE diff --git a/lib/bhaptics_ble/senseshift/bh/ble/constants.hpp b/lib/bhaptics_ble/senseshift/bh/ble/constants.hpp new file mode 100644 index 00000000..64d3ebd4 --- /dev/null +++ b/lib/bhaptics_ble/senseshift/bh/ble/constants.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include <BLEUUID.h> + +// All below are weird choices of bHaptics engineers... +// Why to use unconventional UUIDs, that are reserved for other purposes? +// You have an unlimited amount of other UUIDs + +/** + * Main service for bHaptics BLE devices. + * + * Nordic UART Service (NUS) + * @see https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/libraries/bluetooth_services/services/nus.html + */ +#define BH_BLE_SERVICE_MOTOR_UUID BLEUUID("6e400001-b5a3-f393-e0a9-e50e24dcca9e") + +/** + * Legacy Characteristic for driving haptic feedback. + * + * Nordic UART RX + * @see https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/libraries/bluetooth_services/services/nus.html + */ +#define BH_BLE_SERVICE_MOTOR_CHAR_MOTOR_UUID BLEUUID("6e400002-b5a3-f393-e0a9-e50e24dcca9e") + +/** + * Characteristic for Device S/N. + * + * Nordic UART TX + * @see https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/libraries/bluetooth_services/services/nus.html + */ +#define BH_BLE_SERVICE_MOTOR_CHAR_SERIAL_KEY_UUID BLEUUID("6e400003-b5a3-f393-e0a9-e50e24dcca9e") + +// Glow Color +#define BH_BLE_SERVICE_MOTOR_CHAR_CONFIG_UUID BLEUUID("6e400005-b5a3-f393-e0a9-e50e24dcca9e") +#define BH_BLE_SERVICE_MOTOR_CHAR_VERSION_UUID BLEUUID("6e400007-b5a3-f393-e0a9-e50e24dcca9e") +#define BH_BLE_SERVICE_MOTOR_CHAR_BATTERY_UUID BLEUUID("6e400008-b5a3-f393-e0a9-e50e24dcca9e") + +// Current Characteristic for driving haptic feedback +#define BH_BLE_SERVICE_MOTOR_CHAR_MOTOR_STABLE_UUID BLEUUID("6e40000a-b5a3-f393-e0a9-e50e24dcca9e") +#define BH_BLE_SERVICE_MOTOR_CHAR_TACTSUIT_MONITOR_UUID BLEUUID("6e40000b-b5a3-f393-e0a9-e50e24dcca9e") + +// Audio-to-Haptic +#define BH_BLE_SERVICE_MOTOR_CHAR_ATH_GLOBAL_CONF_UUID BLEUUID("6e40000c-b5a3-f393-e0a9-e50e24dcca9e") +// Audio-to-Haptic +#define BH_BLE_SERVICE_MOTOR_CHAR_ATH_THEME_UUID BLEUUID("6e40000d-b5a3-f393-e0a9-e50e24dcca9e") + +#define BH_BLE_SERVICE_MOTOR_CHAR_MOTTOR_MAPPING_UUID BLEUUID("6e40000e-b5a3-f393-e0a9-e50e24dcca9e") +#define BH_BLE_SERVICE_MOTOR_CHAR_SIGNATURE_PATTERN_UUID BLEUUID("6e40000f-b5a3-f393-e0a9-e50e24dcca9e") + +/** + * Firmware update service + * @see https://infocenter.nordicsemi.com/topic/ug_nrfconnect_ble/UG/nRF_Connect_BLE/nRF_Connect_DFU.html + */ +#define BH_BLE_SERVICE_DFU_UUID BLEUUID("0000fe59-0000-1000-8000-00805f9b34fb") +/** + * Firmware update control characteristic + * @see https://infocenter.nordicsemi.com/topic/ug_nrfconnect_ble/UG/nRF_Connect_BLE/nRF_Connect_DFU.html + */ +#define BH_BLE_SERVICE_DFU_CHAR_CONTROL_UUID BLEUUID("8ec90003-f315-4f60-9fb8-838830daea50") diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index 7f153779..332fb25d 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -1,6 +1,6 @@ -#include <bh_types.hpp> -#include <bh_encoding.hpp> #include <bh_devices.hpp> +#include <bh_encoding.hpp> +#include <bh_types.hpp> #include <unity.h> @@ -224,12 +224,12 @@ void test_layout_tactglove(void) const auto& bhLayout = BH::TactGloveLeftLayout; - auto thumb = new VibroPlane({{ std::get<2>(bhLayout[0]), actuatorThumb }}); - auto index = new VibroPlane({{ std::get<2>(bhLayout[1]), actuatorIndex }}); - auto middle = new VibroPlane({{ std::get<2>(bhLayout[2]), actuatorMiddle }}); - auto ring = new VibroPlane({{ std::get<2>(bhLayout[3]), actuatorRing }}); - auto little = new VibroPlane({{ std::get<2>(bhLayout[4]), actuatorLittle }}); - auto wrist = new VibroPlane({{ std::get<2>(bhLayout[5]), actuatorWrist }}); + auto thumb = new VibroPlane({ { std::get<2>(bhLayout[0]), actuatorThumb } }); + auto index = new VibroPlane({ { std::get<2>(bhLayout[1]), actuatorIndex } }); + auto middle = new VibroPlane({ { std::get<2>(bhLayout[2]), actuatorMiddle } }); + auto ring = new VibroPlane({ { std::get<2>(bhLayout[3]), actuatorRing } }); + auto little = new VibroPlane({ { std::get<2>(bhLayout[4]), actuatorLittle } }); + auto wrist = new VibroPlane({ { std::get<2>(bhLayout[5]), actuatorWrist } }); auto body = new HapticBody(); From 445efe758f3aa0ea063d996b0dd1393098119dd5 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 21 Aug 2023 18:56:30 +0400 Subject: [PATCH 07/82] refactor(bHaptics): use updated haptics core --- .vscode/settings.json | 12 +- examples/bhaptics-ble-bt-serial.cpp | 2 +- firmware/mode_configs/bhaptics/tactal.cpp | 17 +- firmware/mode_configs/bhaptics/tactglove.cpp | 53 ++-- firmware/mode_configs/bhaptics/tactosy2.cpp | 33 ++- firmware/mode_configs/bhaptics/tactosyf.cpp | 29 +- firmware/mode_configs/bhaptics/tactosyh.cpp | 35 ++- .../mode_configs/bhaptics/tactsuit_x16.cpp | 41 ++- .../bhaptics/tactsuit_x16_pca9685.cpp | 41 ++- .../mode_configs/bhaptics/tactsuit_x40.cpp | 53 ++-- firmware/mode_configs/bhaptics/tactvisor.cpp | 31 +-- firmware/senseshift.cpp | 2 +- include/senseshift.h | 6 +- ini/bhaptics.ini | 4 +- lib/arduino/components/serial_plotter.cpp | 2 +- lib/arduino/components/serial_plotter.hpp | 3 +- lib/bhaptics/senseshift/bh/devices.hpp | 262 +++++++++++------- lib/bhaptics/senseshift/bh/encoding.hpp | 41 +-- .../senseshift/bh/ble/connection.cpp | 105 +++---- .../senseshift/bh/ble/connection.hpp | 2 +- lib/core/types.hpp | 7 - lib/hands/hand_interface.hpp | 12 +- lib/haptics/haptic_body.hpp | 6 +- lib/haptics/haptic_plane.hpp | 4 +- lib/haptics/haptics_interface.hpp | 4 +- test/test_bhaptics_encoding/main.cpp | 45 ++- 26 files changed, 451 insertions(+), 401 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 56a04ab3..1af45755 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -59,7 +59,17 @@ "xtree": "cpp", "xhash": "cpp", "xlocnum": "cpp", - "ledc.h": "c" + "ledc.h": "c", + "variant": "cpp", + "bitset": "cpp", + "chrono": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "ratio": "cpp", + "regex": "cpp", + "future": "cpp", + "mutex": "cpp", + "thread": "cpp" }, "files.eol": "\n", "files.insertFinalNewline": true, diff --git a/examples/bhaptics-ble-bt-serial.cpp b/examples/bhaptics-ble-bt-serial.cpp index 4388d41b..d0c42d95 100644 --- a/examples/bhaptics-ble-bt-serial.cpp +++ b/examples/bhaptics-ble-bt-serial.cpp @@ -23,7 +23,7 @@ BluetoothSerial SerialBT; BluetoothSerial* btSerial = &SerialBT; static const size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; -static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; +static const ::SenseShift::Body::Haptics::Position_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; class BLECallbacks : public BHBLEConnectionCallbacks { public: diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index 89b3a620..de7f9560 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -6,10 +6,10 @@ #include "senseshift.h" +#include <output_writers/pwm.hpp> +#include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#include <senseshift/bh/ble/connection.hpp> -#include <output_writers/pwm.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true #include "battery/adc_naive.hpp" @@ -23,19 +23,18 @@ extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; static const size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; -static const oh_output_point_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; +static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; void setupMode() { // Configure PWM pins to their positions on the face - auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + const auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ // clang-format off - {new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26), new PWMOutputWriter(27), new PWMOutputWriter(14)}, + { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26), new PWMOutputWriter(27), new PWMOutputWriter(14) }, // clang-format on }); - auto* face = new VibroPlane(faceOutputs); - app->getHapticBody()->addTarget(Target::FaceFront, face); + app->getHapticBody()->addTarget(Target::FaceFront, new VibroPlane_Closest(faceOutputs)); app->getHapticBody()->setup(); @@ -44,9 +43,9 @@ void setupMode() .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, .serialNumber = BH_SERIAL_NUMBER, - }, + }, [](std::string& value) -> void { - BH::Decoder::applyPlain<6>(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); + BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index cb4cbea8..14acadd8 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -8,58 +8,53 @@ #include "senseshift.h" -#include <bh_encoding.hpp> -#include <bh_devices.hpp> -#include <connection_bhble.hpp> #include <output_writers/pwm.hpp> +#include <senseshift/bh/ble/connection.hpp> +#include <senseshift/bh/devices.hpp> +#include <senseshift/bh/encoding.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true #include <battery/adc_naive.hpp> #endif -#ifndef BH_LAYOUT -#define BH_LAYOUT BH::TactGloveLeftLayout -#endif - using namespace OH; using namespace SenseShift; using namespace SenseShift::Body::Haptics; -using namespace BH; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; -const auto& bhLayout = BH_LAYOUT; +static const Body::Hands::HandSide_t handSide = Body::Hands::HandSide::SENSESHIFT_HAND_SIDE; +static const size_t bhLayoutSize = BH_LAYOUT_TACTGLOVE_SIZE; +// clang-format off +static const BH::OutputLayout_t (&bhLayout)[bhLayoutSize] = handSide == Body::Hands::HandSide::Left ? BH::TactGloveLeftLayout : BH::TactGloveRightLayout; +// clang-format on void setupMode() { // Configure PWM pins to their positions on the glove - auto* motorThumb = new PWMOutputWriter(33); // Thumb - auto* motorIndex = new PWMOutputWriter(32); // Index - auto* motorMiddle = new PWMOutputWriter(25); // Middle - auto* motorRing = new PWMOutputWriter(26); // Ring - auto* motorLittle = new PWMOutputWriter(27); // Little - auto* motorWrist = new PWMOutputWriter(14); // Wrist - - app->getHapticBody()->addTarget(std::get<0>(bhLayout[0]), new VibroPlane({{ std::get<1>(bhLayout[0]), motorThumb }})); - app->getHapticBody()->addTarget(std::get<0>(bhLayout[1]), new VibroPlane({{ std::get<1>(bhLayout[1]), motorIndex }})); - app->getHapticBody()->addTarget(std::get<0>(bhLayout[2]), new VibroPlane({{ std::get<1>(bhLayout[2]), motorMiddle }})); - app->getHapticBody()->addTarget(std::get<0>(bhLayout[3]), new VibroPlane({{ std::get<1>(bhLayout[3]), motorRing }})); - app->getHapticBody()->addTarget(std::get<0>(bhLayout[4]), new VibroPlane({{ std::get<1>(bhLayout[4]), motorLittle }})); - app->getHapticBody()->addTarget(std::get<0>(bhLayout[5]), new VibroPlane({{ std::get<1>(bhLayout[5]), motorWrist }})); + // Replace `new PWMOutputWriter(...)` with `nullptr` to disable a specific actuator + BH::addTactGloveActuators( + app->getHapticBody(), + handSide, + new PWMOutputWriter(32), // Thumb + new PWMOutputWriter(33), // Index + new PWMOutputWriter(25), // Middle + new PWMOutputWriter(26), // Ring + new PWMOutputWriter(27), // Little + new PWMOutputWriter(14) // Wrist + ); app->getHapticBody()->setup(); - uint8_t serialNumber[BH_SERIAL_NUMBER_LENGTH] = BH_SERIAL_NUMBER; - ConnectionBHBLE_Config config = { + auto* bhBleConnection = new BH::BLE::Connection( + { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, - .serialNumber = serialNumber, - }; - auto* bhBleConnection = new ConnectionBHBLE( - config, + .serialNumber = BH_SERIAL_NUMBER, + }, [](std::string& value) -> void { - Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect_t::Vibro); + BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect_t::Vibro); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index e42ea4a9..fb6bd77f 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -6,48 +6,47 @@ #include "senseshift.h" -#include <bh_utils.hpp> -#include <connection_bhble.hpp> #include <output_writers/pwm.hpp> +#include <senseshift/bh/ble/connection.hpp> +#include <senseshift/bh/devices.hpp> +#include <senseshift/bh/encoding.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true #include <battery/adc_naive.hpp> #endif using namespace OH; -using namespace BH; +using namespace SenseShift; +using namespace SenseShift::Body::Haptics; -extern SenseShift App; -SenseShift* app = &App; +extern SenseShift::SenseShift App; +SenseShift::SenseShift* app = &App; static const size_t bhLayoutSize = BH_LAYOUT_TACTOSY2_SIZE; -static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSY2; +static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSY2; void setupMode() { // Configure PWM pins to their positions on the forearm auto forearmOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ // clang-format off - {new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25)}, - {new PWMOutputWriter(26), new PWMOutputWriter(27), new PWMOutputWriter(14)}, + { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25) }, + { new PWMOutputWriter(26), new PWMOutputWriter(27), new PWMOutputWriter(14) }, // clang-format on }); - auto* forearm = new HapticPlane_Closest(forearmOutputs); - app->getHapticBody()->addComponent(OUTPUT_PATH_ACCESSORY, forearm); + app->getHapticBody()->addTarget(Target::Accessory, new VibroPlane_Closest(forearmOutputs)); app->getHapticBody()->setup(); - uint8_t serialNumber[BH_SERIAL_NUMBER_LENGTH] = BH_SERIAL_NUMBER; - ConnectionBHBLE_Config config = { + auto* bhBleConnection = new BH::BLE::Connection( + { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, - .serialNumber = serialNumber, - }; - auto* bhBleConnection = new ConnectionBHBLE( - config, + .serialNumber = BH_SERIAL_NUMBER, + }, [](std::string& value) -> void { - plainOutputTransformer(app->getHapticBody(), value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); + BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index 66629aa9..277377ae 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -6,22 +6,24 @@ #include "senseshift.h" -#include <bh_utils.hpp> -#include <connection_bhble.hpp> #include <output_writers/pwm.hpp> +#include <senseshift/bh/ble/connection.hpp> +#include <senseshift/bh/devices.hpp> +#include <senseshift/bh/encoding.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true #include <battery/adc_naive.hpp> #endif using namespace OH; -using namespace BH; +using namespace SenseShift; +using namespace SenseShift::Body::Haptics; -extern SenseShift App; -SenseShift* app = &App; +extern SenseShift::SenseShift App; +SenseShift::SenseShift* app = &App; static const size_t bhLayoutSize = BH_LAYOUT_TACTOSYF_SIZE; -static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYF; +static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYF; void setupMode() { @@ -34,21 +36,18 @@ void setupMode() // clang-format on }); - auto* foot = new HapticPlane_Closest(footOutputs); - app->getHapticBody()->addComponent(OUTPUT_PATH_ACCESSORY, foot); + app->getHapticBody()->addTarget(Target::Accessory, new VibroPlane_Closest(footOutputs)); app->getHapticBody()->setup(); - uint8_t serialNumber[BH_SERIAL_NUMBER_LENGTH] = BH_SERIAL_NUMBER; - ConnectionBHBLE_Config config = { + auto* bhBleConnection = new BH::BLE::Connection( + { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, - .serialNumber = serialNumber, - }; - auto* bhBleConnection = new ConnectionBHBLE( - config, + .serialNumber = BH_SERIAL_NUMBER, + }, [](std::string& value) -> void { - plainOutputTransformer(app->getHapticBody(), value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); + BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 967b1f84..543f2275 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -6,49 +6,48 @@ #include "senseshift.h" -#include <bh_utils.hpp> -#include <connection_bhble.hpp> #include <output_writers/pwm.hpp> +#include <senseshift/bh/ble/connection.hpp> +#include <senseshift/bh/devices.hpp> +#include <senseshift/bh/encoding.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true #include <battery/adc_naive.hpp> #endif using namespace OH; -using namespace BH; +using namespace SenseShift; +using namespace SenseShift::Body::Haptics; -extern SenseShift App; -SenseShift* app = &App; +extern SenseShift::SenseShift App; +SenseShift::SenseShift* app = &App; static const size_t bhLayoutSize = BH_LAYOUT_TACTOSYH_SIZE; -static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYH; +static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYH; void setupMode() { // Configure PWM pins to their positions on the hands auto handOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ // clang-format off - {new PWMOutputWriter(32)}, - {new PWMOutputWriter(33)}, - {new PWMOutputWriter(25)} + { new PWMOutputWriter(32) }, + { new PWMOutputWriter(33) }, + { new PWMOutputWriter(25) } // clang-format on }); - auto* hand = new HapticPlane_Closest(handOutputs); - app->getHapticBody()->addComponent(OUTPUT_PATH_ACCESSORY, hand); + app->getHapticBody()->addTarget(Target::Accessory, new VibroPlane_Closest(handOutputs)); app->getHapticBody()->setup(); - uint8_t serialNumber[BH_SERIAL_NUMBER_LENGTH] = BH_SERIAL_NUMBER; - ConnectionBHBLE_Config config = { + auto* bhBleConnection = new BH::BLE::Connection( + { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, - .serialNumber = serialNumber, - }; - auto* bhBleConnection = new ConnectionBHBLE( - config, + .serialNumber = BH_SERIAL_NUMBER, + }, [](std::string& value) -> void { - plainOutputTransformer(app->getHapticBody(), value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); + BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index a1a9ba1f..4b4cf7d2 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -6,22 +6,24 @@ #include "senseshift.h" -#include <bh_utils.hpp> -#include <connection_bhble.hpp> #include <output_writers/pwm.hpp> +#include <senseshift/bh/ble/connection.hpp> +#include <senseshift/bh/devices.hpp> +#include <senseshift/bh/encoding.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true #include <battery/adc_naive.hpp> #endif using namespace OH; -using namespace BH; +using namespace SenseShift; +using namespace SenseShift::Body::Haptics; -extern SenseShift App; -SenseShift* app = &App; +extern SenseShift::SenseShift App; +SenseShift::SenseShift* app = &App; -static const oh_output_point_t* bhLayout[] = BH_LAYOUT_TACTSUITX16; static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; +static const BH::OutputLayout_t bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; // Ouput indices, responsible for x40 => x16 grouping static const size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; @@ -32,35 +34,30 @@ void setupMode() // Configure PWM pins to their positions on the vest auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ // clang-format off - {new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26)}, - {new PWMOutputWriter(27), new PWMOutputWriter(14), new PWMOutputWriter(12), new PWMOutputWriter(13)}, + { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26) }, + { new PWMOutputWriter(27), new PWMOutputWriter(14), new PWMOutputWriter(12), new PWMOutputWriter(13) }, // clang-format on }); auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ // clang-format off - {new PWMOutputWriter(19), new PWMOutputWriter(18), new PWMOutputWriter(5), new PWMOutputWriter(17)}, - {new PWMOutputWriter(16), new PWMOutputWriter(4), new PWMOutputWriter(2), new PWMOutputWriter(15)}, + { new PWMOutputWriter(19), new PWMOutputWriter(18), new PWMOutputWriter(5), new PWMOutputWriter(17) }, + { new PWMOutputWriter(16), new PWMOutputWriter(4), new PWMOutputWriter(2), new PWMOutputWriter(15) }, // clang-format on }); - auto* chestFront = new HapticPlane_Closest(frontOutputs); - auto* chestBack = new HapticPlane_Closest(backOutputs); - - app->getHapticBody()->addComponent(OUTPUT_PATH_CHEST_FRONT, chestFront); - app->getHapticBody()->addComponent(OUTPUT_PATH_CHEST_BACK, chestBack); + app->getHapticBody()->addTarget(Target::ChestFront, new VibroPlane_Closest(frontOutputs)); + app->getHapticBody()->addTarget(Target::ChestBack, new VibroPlane_Closest(backOutputs)); app->getHapticBody()->setup(); - uint8_t serialNumber[BH_SERIAL_NUMBER_LENGTH] = BH_SERIAL_NUMBER; - ConnectionBHBLE_Config config = { + auto* bhBleConnection = new BH::BLE::Connection( + { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, - .serialNumber = serialNumber, - }; - auto* bhBleConnection = new ConnectionBHBLE( - config, + .serialNumber = BH_SERIAL_NUMBER, + }, [](std::string& value) -> void { - vestX16OutputTransformer(app->getHapticBody(), value, bhLayout, bhLayoutSize, layoutGroups, layoutGroupsSize); + BH::Decoder::applyVestGrouped(app->getHapticBody(), value, bhLayout, layoutGroups); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index fbe1e567..b9051e9e 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -6,22 +6,24 @@ #include "senseshift.h" -#include <bh_utils.hpp> -#include <connection_bhble.hpp> #include <output_writers/pca9685.hpp> +#include <senseshift/bh/ble/connection.hpp> +#include <senseshift/bh/devices.hpp> +#include <senseshift/bh/encoding.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true #include <battery/adc_naive.hpp> #endif using namespace OH; -using namespace BH; +using namespace SenseShift; +using namespace SenseShift::Body::Haptics; -extern SenseShift App; -SenseShift* app = &App; +extern SenseShift::SenseShift App; +SenseShift::SenseShift* app = &App; -static const oh_output_point_t* bhLayout[] = BH_LAYOUT_TACTSUITX16; static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; +static const BH::OutputLayout_t bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; // Ouput indices, responsible for x40 => x16 grouping static const size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; @@ -37,35 +39,30 @@ void setupMode() // Assign the pins on the configured PCA9685 to positions on the vest auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ // clang-format off - {new PCA9685OutputWriter(pwm, 0), new PCA9685OutputWriter(pwm, 1), new PCA9685OutputWriter(pwm, 2), new PCA9685OutputWriter(pwm, 3)}, - {new PCA9685OutputWriter(pwm, 4), new PCA9685OutputWriter(pwm, 5), new PCA9685OutputWriter(pwm, 6), new PCA9685OutputWriter(pwm, 7)}, + { new PCA9685OutputWriter(pwm, 0), new PCA9685OutputWriter(pwm, 1), new PCA9685OutputWriter(pwm, 2), new PCA9685OutputWriter(pwm, 3) }, + { new PCA9685OutputWriter(pwm, 4), new PCA9685OutputWriter(pwm, 5), new PCA9685OutputWriter(pwm, 6), new PCA9685OutputWriter(pwm, 7) }, // clang-format on }); auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ // clang-format off - {new PCA9685OutputWriter(pwm, 8), new PCA9685OutputWriter(pwm, 9), new PCA9685OutputWriter(pwm, 10), new PCA9685OutputWriter(pwm, 11)}, - {new PCA9685OutputWriter(pwm, 12), new PCA9685OutputWriter(pwm, 13), new PCA9685OutputWriter(pwm, 14), new PCA9685OutputWriter(pwm, 15)}, + { new PCA9685OutputWriter(pwm, 8), new PCA9685OutputWriter(pwm, 9), new PCA9685OutputWriter(pwm, 10), new PCA9685OutputWriter(pwm, 11) }, + { new PCA9685OutputWriter(pwm, 12), new PCA9685OutputWriter(pwm, 13), new PCA9685OutputWriter(pwm, 14), new PCA9685OutputWriter(pwm, 15) }, // clang-format on }); - auto* chestFront = new HapticPlane_Closest(frontOutputs); - auto* chestBack = new HapticPlane_Closest(backOutputs); - - app->getHapticBody()->addComponent(OUTPUT_PATH_CHEST_FRONT, chestFront); - app->getHapticBody()->addComponent(OUTPUT_PATH_CHEST_BACK, chestBack); + app->getHapticBody()->addTarget(Target::ChestFront, new VibroPlane_Closest(frontOutputs)); + app->getHapticBody()->addTarget(Target::ChestBack, new VibroPlane_Closest(backOutputs)); app->getHapticBody()->setup(); - uint8_t serialNumber[BH_SERIAL_NUMBER_LENGTH] = BH_SERIAL_NUMBER; - ConnectionBHBLE_Config config = { + auto* bhBleConnection = new BH::BLE::Connection( + { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, - .serialNumber = serialNumber, - }; - auto* bhBleConnection = new ConnectionBHBLE( - config, + .serialNumber = BH_SERIAL_NUMBER, + }, [](std::string& value) -> void { - vestX16OutputTransformer(app->getHapticBody(), value, bhLayout, bhLayoutSize, layoutGroups, layoutGroupsSize); + BH::Decoder::applyVestGrouped(app->getHapticBody(), value, bhLayout, layoutGroups); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 870a0859..6ec93001 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -6,23 +6,25 @@ #include "senseshift.h" -#include <bh_utils.hpp> -#include <connection_bhble.hpp> #include <output_writers/pca9685.hpp> #include <output_writers/pwm.hpp> +#include <senseshift/bh/ble/connection.hpp> +#include <senseshift/bh/devices.hpp> +#include <senseshift/bh/encoding.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true #include <battery/adc_naive.hpp> #endif using namespace OH; -using namespace BH; +using namespace SenseShift; +using namespace SenseShift::Body::Haptics; -extern SenseShift App; -SenseShift* app = &App; +extern SenseShift::SenseShift App; +SenseShift::SenseShift* app = &App; static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX40_SIZE; -static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; +static const BH::OutputLayout_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; void setupMode() { @@ -39,41 +41,36 @@ void setupMode() // vest auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ // clang-format off - {new PCA9685OutputWriter(pwm0, 0), new PCA9685OutputWriter(pwm0, 1), new PCA9685OutputWriter(pwm0, 2), new PCA9685OutputWriter(pwm0, 3)}, - {new PCA9685OutputWriter(pwm0, 4), new PCA9685OutputWriter(pwm0, 5), new PCA9685OutputWriter(pwm0, 6), new PCA9685OutputWriter(pwm0, 7)}, - {new PCA9685OutputWriter(pwm0, 8), new PCA9685OutputWriter(pwm0, 9), new PCA9685OutputWriter(pwm0, 10), new PCA9685OutputWriter(pwm0, 11)}, - {new PCA9685OutputWriter(pwm0, 12), new PCA9685OutputWriter(pwm0, 13), new PCA9685OutputWriter(pwm0, 14), new PCA9685OutputWriter(pwm0, 15)}, - {new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26)}, + { new PCA9685OutputWriter(pwm0, 0), new PCA9685OutputWriter(pwm0, 1), new PCA9685OutputWriter(pwm0, 2), new PCA9685OutputWriter(pwm0, 3) }, + { new PCA9685OutputWriter(pwm0, 4), new PCA9685OutputWriter(pwm0, 5), new PCA9685OutputWriter(pwm0, 6), new PCA9685OutputWriter(pwm0, 7) }, + { new PCA9685OutputWriter(pwm0, 8), new PCA9685OutputWriter(pwm0, 9), new PCA9685OutputWriter(pwm0, 10), new PCA9685OutputWriter(pwm0, 11) }, + { new PCA9685OutputWriter(pwm0, 12), new PCA9685OutputWriter(pwm0, 13), new PCA9685OutputWriter(pwm0, 14), new PCA9685OutputWriter(pwm0, 15) }, + { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26) }, // clang-format on }); auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ // clang-format off - {new PCA9685OutputWriter(pwm1, 0), new PCA9685OutputWriter(pwm1, 1), new PCA9685OutputWriter(pwm1, 2), new PCA9685OutputWriter(pwm1, 3)}, - {new PCA9685OutputWriter(pwm1, 4), new PCA9685OutputWriter(pwm1, 5), new PCA9685OutputWriter(pwm1, 6), new PCA9685OutputWriter(pwm1, 7)}, - {new PCA9685OutputWriter(pwm1, 8), new PCA9685OutputWriter(pwm1, 9), new PCA9685OutputWriter(pwm1, 10), new PCA9685OutputWriter(pwm1, 11)}, - {new PCA9685OutputWriter(pwm1, 12), new PCA9685OutputWriter(pwm1, 13), new PCA9685OutputWriter(pwm1, 14), new PCA9685OutputWriter(pwm1, 15)}, - {new PWMOutputWriter(27), new PWMOutputWriter(14), new PWMOutputWriter(12), new PWMOutputWriter(13)}, + { new PCA9685OutputWriter(pwm1, 0), new PCA9685OutputWriter(pwm1, 1), new PCA9685OutputWriter(pwm1, 2), new PCA9685OutputWriter(pwm1, 3) }, + { new PCA9685OutputWriter(pwm1, 4), new PCA9685OutputWriter(pwm1, 5), new PCA9685OutputWriter(pwm1, 6), new PCA9685OutputWriter(pwm1, 7) }, + { new PCA9685OutputWriter(pwm1, 8), new PCA9685OutputWriter(pwm1, 9), new PCA9685OutputWriter(pwm1, 10), new PCA9685OutputWriter(pwm1, 11) }, + { new PCA9685OutputWriter(pwm1, 12), new PCA9685OutputWriter(pwm1, 13), new PCA9685OutputWriter(pwm1, 14), new PCA9685OutputWriter(pwm1, 15) }, + { new PWMOutputWriter(27), new PWMOutputWriter(14), new PWMOutputWriter(12), new PWMOutputWriter(13) }, // clang-format on }); - auto* chestFront = new HapticPlane_Closest(frontOutputs); - auto* chestBack = new HapticPlane_Closest(backOutputs); - - app->getHapticBody()->addComponent(OUTPUT_PATH_CHEST_FRONT, chestFront); - app->getHapticBody()->addComponent(OUTPUT_PATH_CHEST_BACK, chestBack); + app->getHapticBody()->addTarget(Target::ChestFront, new VibroPlane_Closest(frontOutputs)); + app->getHapticBody()->addTarget(Target::ChestBack, new VibroPlane_Closest(backOutputs)); app->getHapticBody()->setup(); - uint8_t serialNumber[BH_SERIAL_NUMBER_LENGTH] = BH_SERIAL_NUMBER; - ConnectionBHBLE_Config config = { + auto* bhBleConnection = new BH::BLE::Connection( + { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, - .serialNumber = serialNumber, - }; - auto* bhBleConnection = new ConnectionBHBLE( - config, + .serialNumber = BH_SERIAL_NUMBER, + }, [](std::string& value) -> void { - vestOutputTransformer(app->getHapticBody(), value, bhLayout, bhLayoutSize); + BH::Decoder::applyVest(app->getHapticBody(), value, bhLayout); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index 2cd4692e..9e2bb10d 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -6,47 +6,46 @@ #include "senseshift.h" -#include <bh_utils.hpp> -#include <connection_bhble.hpp> #include <output_writers/pwm.hpp> +#include <senseshift/bh/ble/connection.hpp> +#include <senseshift/bh/devices.hpp> +#include <senseshift/bh/encoding.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true #include "battery/adc_naive.hpp" #endif using namespace OH; -using namespace BH; +using namespace SenseShift; +using namespace SenseShift::Body::Haptics; -extern SenseShift App; -SenseShift* app = &App; +extern SenseShift::SenseShift App; +SenseShift::SenseShift* app = &App; static const size_t bhLayoutSize = BH_LAYOUT_TACTVISOR_SIZE; -static const oh_output_point_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTVISOR; +static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTVISOR; void setupMode() { // Configure PWM pins to their positions on the face auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ // clang-format off - {new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26)}, + { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26) }, // clang-format on }); - auto* face = new HapticPlane_Closest(faceOutputs); - app->getHapticBody()->addComponent(OUTPUT_PATH_ACCESSORY, face); + app->getHapticBody()->addTarget(Target::FaceFront, new VibroPlane_Closest(faceOutputs)); app->getHapticBody()->setup(); - uint8_t serialNumber[BH_SERIAL_NUMBER_LENGTH] = BH_SERIAL_NUMBER; - ConnectionBHBLE_Config config = { + auto* bhBleConnection = new BH::BLE::Connection( + { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, - .serialNumber = serialNumber, - }; - auto* bhBleConnection = new ConnectionBHBLE( - config, + .serialNumber = BH_SERIAL_NUMBER, + }, [](std::string& value) -> void { - plainOutputTransformer(app->getHapticBody(), value, bhLayout, bhLayoutSize, OUTPUT_PATH_ACCESSORY); + BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); }, app ); diff --git a/firmware/senseshift.cpp b/firmware/senseshift.cpp index f54fda9a..2605ce3e 100644 --- a/firmware/senseshift.cpp +++ b/firmware/senseshift.cpp @@ -29,4 +29,4 @@ namespace SenseShift { { this->eventListeners.push_back(listener); } -} +} // namespace SenseShift diff --git a/include/senseshift.h b/include/senseshift.h index f4346148..f973af46 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -14,7 +14,7 @@ namespace SenseShift { class SenseShift final : public OH::IEventDispatcher { - private: + private: std::vector<const OH::IEventListener*> eventListeners{}; Body::Haptics::HapticBody* pHapticBody; @@ -22,7 +22,7 @@ namespace SenseShift { OH::BatterySensor* battery; #endif - public: + public: SenseShift(); Body::Haptics::HapticBody* getHapticBody() @@ -33,4 +33,4 @@ namespace SenseShift { void postEvent(const OH::IEvent* event) override; void addEventListener(const OH::IEventListener* listener) override; }; -} +} // namespace SenseShift diff --git a/ini/bhaptics.ini b/ini/bhaptics.ini index 54c5aa1e..ac624ea8 100644 --- a/ini/bhaptics.ini +++ b/ini/bhaptics.ini @@ -239,7 +239,7 @@ monitor_speed = ${bhaptics.monitor_speed} build_flags = ${bhaptics.build_flags} -D BH_DEVICE_TACTGLOVE - -D BH_LAYOUT=BH::TactGloveLeftLayout + -D SENSESHIFT_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 }' @@ -258,7 +258,7 @@ monitor_speed = ${bhaptics.monitor_speed} build_flags = ${bhaptics.build_flags} -D BH_DEVICE_TACTGLOVE - -D BH_LAYOUT=BH::TactGloveRightLayout + -D SENSESHIFT_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 }' diff --git a/lib/arduino/components/serial_plotter.cpp b/lib/arduino/components/serial_plotter.cpp index 21a1ffb1..d5be860b 100644 --- a/lib/arduino/components/serial_plotter.cpp +++ b/lib/arduino/components/serial_plotter.cpp @@ -17,7 +17,7 @@ void OH::SerialPlotter_OutputStates<_Tp>::run() { while (true) { for (const auto& [target, plane] : *output->getTargets()) { - std::visit(PlaneVisitor{target, this->serial}, plane); + std::visit(PlaneVisitor{ target, this->serial }, plane); } this->serial->println(); diff --git a/lib/arduino/components/serial_plotter.hpp b/lib/arduino/components/serial_plotter.hpp index e0a9be8a..b2b9b085 100644 --- a/lib/arduino/components/serial_plotter.hpp +++ b/lib/arduino/components/serial_plotter.hpp @@ -35,7 +35,8 @@ namespace OH { TaskConfig taskConfig = { "Serial Plotter", 2048, 1, tskNO_AFFINITY } ) : Task<SerialPlotter_OutputStates<_Tp>>(taskConfig), serial(&serial), output(output), sampleRate(sampleRate){}; - SerialPlotter_OutputStates(_Tp& serial, SenseShift::Body::Haptics::HapticBody* output) : SerialPlotter_OutputStates(serial, output, 100){}; + SerialPlotter_OutputStates(_Tp& serial, SenseShift::Body::Haptics::HapticBody* output) : + SerialPlotter_OutputStates(serial, output, 100){}; void begin() override { diff --git a/lib/bhaptics/senseshift/bh/devices.hpp b/lib/bhaptics/senseshift/bh/devices.hpp index e500c09f..7c5531f0 100644 --- a/lib/bhaptics/senseshift/bh/devices.hpp +++ b/lib/bhaptics/senseshift/bh/devices.hpp @@ -1,18 +1,18 @@ #pragma once #include <hand_interface.hpp> -#include <haptic_plane.hpp> +#include <haptic_body.hpp> #pragma region BH_DEVICE_TACTSUITX40 #define BH_LAYOUT_TACTSUITX40_SIZE_X 4 #define BH_LAYOUT_TACTSUITX40_SIZE_Y 5 -#define BH_LAYOUT_TACTSUITX40_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX40_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTSUITX40_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTSUITX40_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTSUITX40_SIZE_Y - 1) \ ) // X * Y for front and back @@ -74,12 +74,12 @@ #define BH_LAYOUT_TACTSUITX16_SIZE_X 4 #define BH_LAYOUT_TACTSUITX16_SIZE_Y 2 -#define BH_LAYOUT_TACTSUITX16_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX16_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTSUITX16_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTSUITX16_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTSUITX16_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTSUITX16_SIZE_Y - 1) \ ) // X16 suit uses the same packets structure as x40 suit and performs motor grouping in firmware @@ -87,55 +87,55 @@ // clang-format off #define BH_LAYOUT_TACTSUITX16 { \ /* Front, left part */ \ - /* 0 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0), /* 0 */ \ - /* 1 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0), /* 1 */ \ - /* 2 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0), /* 4 */ \ - /* 3 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0), /* 5 */ \ + /* 0 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ + /* 1 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ + /* 2 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ + /* 3 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ \ - /* 4 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1), /* 8 */ \ - /* 5 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1), /* 9 */ \ - /* 6 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1), /* 12 */ \ - /* 7 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1), /* 13 */ \ - /* 8 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1), /* 16 */ \ - /* 9 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1), /* 17 */ \ + /* 4 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ + /* 5 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ + /* 6 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ + /* 7 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ + /* 8 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ + /* 9 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ \ /* Back */ \ - /* 10 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0), /* 0 */ \ - /* 11 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0), /* 1 */ \ - /* 12 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0), /* 4 */ \ - /* 13 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0), /* 5 */ \ + /* 10 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ + /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ + /* 12 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ + /* 13 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ \ - /* 14 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1), /* 8 */ \ - /* 15 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1), /* 9 */ \ - /* 16 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1), /* 12 */ \ - /* 17 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1), /* 13 */ \ - /* 18 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1), /* 16 */ \ - /* 19 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1), /* 17 */ \ + /* 14 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ + /* 15 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ + /* 16 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ + /* 17 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ + /* 18 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ + /* 19 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ \ - /* 20 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0), /* 2 */ \ - /* 21 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0), /* 3 */ \ - /* 22 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0), /* 4 */ \ - /* 23 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0), /* 7 */ \ + /* 20 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ + /* 21 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ + /* 22 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ + /* 23 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ \ - /* 24 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1), /* 10 */ \ - /* 25 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1), /* 11 */ \ - /* 26 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1), /* 14 */ \ - /* 27 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1), /* 15 */ \ - /* 28 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1), /* 18 */ \ - /* 29 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1), /* 19 */ \ + /* 24 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ + /* 25 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ + /* 26 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ + /* 27 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 15 */ \ + /* 28 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 18 */ \ + /* 29 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 19 */ \ \ /* Front, again... Now right part */ \ - /* 30 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0), /* 2 */ \ - /* 31 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0), /* 3 */ \ - /* 32 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0), /* 4 */ \ - /* 33 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0), /* 7 */ \ + /* 30 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ + /* 31 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ + /* 32 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ + /* 33 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ \ - /* 34 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1), /* 10 */ \ - /* 35 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1), /* 11 */ \ - /* 36 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1), /* 14 */ \ - /* 37 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1), /* 15 */ \ - /* 38 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1), /* 18 */ \ - /* 39 */ BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1), /* 19 */ \ + /* 34 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ + /* 35 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ + /* 36 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ + /* 37 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 15 */ \ + /* 38 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 18 */ \ + /* 39 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 19 */ \ } // clang-format on @@ -152,12 +152,12 @@ #define BH_LAYOUT_TACTAL_SIZE_X 6 #define BH_LAYOUT_TACTAL_SIZE_Y 1 -#define BH_LAYOUT_TACTAL_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTAL_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTAL_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTAL_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTAL_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTAL_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTAL_SIZE (BH_LAYOUT_TACTAL_SIZE_X * BH_LAYOUT_TACTAL_SIZE_Y) @@ -178,12 +178,12 @@ #define BH_LAYOUT_TACTVISOR_SIZE_X 4 #define BH_LAYOUT_TACTVISOR_SIZE_Y 1 -#define BH_LAYOUT_TACTVISOR_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTVISOR_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTVISOR_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTVISOR_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTVISOR_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTVISOR_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTVISOR_SIZE (BH_LAYOUT_TACTVISOR_SIZE_X * BH_LAYOUT_TACTVISOR_SIZE_Y) @@ -202,12 +202,12 @@ #define BH_LAYOUT_TACTOSY2_SIZE_X 3 #define BH_LAYOUT_TACTOSY2_SIZE_Y 2 -#define BH_LAYOUT_TACTOSY2_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSY2_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSY2_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTOSY2_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSY2_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSY2_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTOSY2_SIZE (BH_LAYOUT_TACTOSY2_SIZE_X * BH_LAYOUT_TACTOSY2_SIZE_Y) @@ -224,12 +224,12 @@ #define BH_LAYOUT_TACTOSYH_SIZE_X 1 #define BH_LAYOUT_TACTOSYH_SIZE_Y 3 -#define BH_LAYOUT_TACTOSYH_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSYH_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSYH_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTOSYH_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSYH_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSYH_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTOSYH_SIZE (BH_LAYOUT_TACTOSYH_SIZE_X * BH_LAYOUT_TACTOSYH_SIZE_Y) @@ -243,12 +243,12 @@ #define BH_LAYOUT_TACTOSYF_SIZE_X 1 #define BH_LAYOUT_TACTOSYF_SIZE_Y 3 -#define BH_LAYOUT_TACTOSYF_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<oh_output_coord_t>( \ - x, \ - y, \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSYF_SIZE_X - 1), \ - (oh_output_coord_t) (BH_LAYOUT_TACTOSYF_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTOSYF_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSYF_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSYF_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTOSYF_SIZE (BH_LAYOUT_TACTOSYF_SIZE_X * BH_LAYOUT_TACTOSYF_SIZE_Y) @@ -258,28 +258,92 @@ #pragma endregion BH_DEVICE_TACTOSYF +#pragma region BH_DEVIDE_TACTGLOVE + +#define BH_LAYOUT_TACTGLOVE_SIZE 6 +// TactGlove (Left) motor positions +#define BH_LAYOUT_TACTGLOVE_LEFT \ + { \ + { Target_t::HandLeftThumb, FINGERTIP_POSITION }, { Target_t::HandLeftIndex, FINGERTIP_POSITION }, \ + { Target_t::HandLeftMiddle, FINGERTIP_POSITION }, { Target_t::HandLeftRing, FINGERTIP_POSITION }, \ + { Target_t::HandLeftLittle, FINGERTIP_POSITION }, { Target_t::HandLeftDorsal, WRIST_MOTOR_POSITION }, \ + } +// TactGlove (Right) motor positions +#define BH_LAYOUT_TACTGLOVE_RIGHT \ + { \ + { Target_t::HandRightThumb, FINGERTIP_POSITION }, { Target_t::HandRightIndex, FINGERTIP_POSITION }, \ + { Target_t::HandRightMiddle, FINGERTIP_POSITION }, { Target_t::HandRightRing, FINGERTIP_POSITION }, \ + { Target_t::HandRightLittle, FINGERTIP_POSITION }, \ + { \ + Target_t::HandRightDorsal, WRIST_MOTOR_POSITION \ + } \ + } + +#pragma endregion BH_DEVIDE_TACTGLOVE + namespace SenseShift::BH { using namespace ::SenseShift::Body::Hands::Haptics; + using namespace ::SenseShift::Body::Haptics; - using Effect_t = ::SenseShift::Body::Haptics::Effect_t; - using Target_t = ::SenseShift::Body::Haptics::Target_t; - using Position_t = ::SenseShift::Body::Haptics::Position_t; + using HandSide_t = ::SenseShift::Body::Hands::HandSide_t; typedef std::tuple<Target_t, Position_t> OutputLayout_t; - // TactSuit X40 motor positions - static constexpr const OutputLayout_t TactSuitX40Layout[] = BH_LAYOUT_TACTSUITX40; - // TactGlove Wrist motor position static constexpr const Position_t WRIST_MOTOR_POSITION(127, 191); - static constexpr const OutputLayout_t TactGloveLeftLayout[] = { - { Target_t::HandLeftThumb, FINGERTIP_POSITION }, { Target_t::HandLeftIndex, FINGERTIP_POSITION }, - { Target_t::HandLeftMiddle, FINGERTIP_POSITION }, { Target_t::HandLeftRing, FINGERTIP_POSITION }, - { Target_t::HandLeftLittle, FINGERTIP_POSITION }, { Target_t::HandLeftDorsal, WRIST_MOTOR_POSITION }, - }; - static constexpr const OutputLayout_t TactGloveRightLayout[] = { - { Target_t::HandRightThumb, FINGERTIP_POSITION }, { Target_t::HandRightIndex, FINGERTIP_POSITION }, - { Target_t::HandRightMiddle, FINGERTIP_POSITION }, { Target_t::HandRightRing, FINGERTIP_POSITION }, - { Target_t::HandRightLittle, FINGERTIP_POSITION }, { Target_t::HandRightDorsal, WRIST_MOTOR_POSITION }, - }; + static constexpr const OutputLayout_t TactGloveLeftLayout[] = BH_LAYOUT_TACTGLOVE_LEFT; + static constexpr const OutputLayout_t TactGloveRightLayout[] = BH_LAYOUT_TACTGLOVE_RIGHT; + + inline void addTactGloveActuators( + HapticBody* hapticBody, + const HandSide_t side, + OH::AbstractActuator* const thumbActuator, + OH::AbstractActuator* const indexActuator, + OH::AbstractActuator* const middleActuator, + OH::AbstractActuator* const ringActuator, + OH::AbstractActuator* const littleActuator, + OH::AbstractActuator* const wristActuator + ) + { + const OutputLayout_t(&layout)[6] = (side == HandSide_t::Left) ? TactGloveLeftLayout : TactGloveRightLayout; + + if (thumbActuator != nullptr) { + hapticBody->addTarget( + std::get<0>(layout[0]), + new VibroPlane({ { std::get<1>(layout[0]), thumbActuator } }) + ); + } + + if (indexActuator != nullptr) { + hapticBody->addTarget( + std::get<0>(layout[1]), + new VibroPlane({ { std::get<1>(layout[1]), indexActuator } }) + ); + } + + if (middleActuator != nullptr) { + hapticBody->addTarget( + std::get<0>(layout[2]), + new VibroPlane({ { std::get<1>(layout[2]), middleActuator } }) + ); + } + + if (ringActuator != nullptr) { + hapticBody->addTarget(std::get<0>(layout[3]), new VibroPlane({ { std::get<1>(layout[3]), ringActuator } })); + } + + if (littleActuator != nullptr) { + hapticBody->addTarget( + std::get<0>(layout[4]), + new VibroPlane({ { std::get<1>(layout[4]), littleActuator } }) + ); + } + + if (wristActuator != nullptr) { + hapticBody->addTarget( + std::get<0>(layout[5]), + new VibroPlane({ { std::get<1>(layout[5]), wristActuator } }) + ); + } + } } // namespace SenseShift::BH diff --git a/lib/bhaptics/senseshift/bh/encoding.hpp b/lib/bhaptics/senseshift/bh/encoding.hpp index c6b876e1..83575f8c 100644 --- a/lib/bhaptics/senseshift/bh/encoding.hpp +++ b/lib/bhaptics/senseshift/bh/encoding.hpp @@ -22,10 +22,7 @@ namespace SenseShift::BH { template<size_t N> static void applyPlain( - HapticBody_t* output, - const uint8_t (&value)[N], - const OutputLayout_t (&layout)[N], - const Effect_t effect + HapticBody_t* output, const uint8_t (&value)[N], const OutputLayout_t (&layout)[N], const Effect_t effect ) { for (size_t i = 0; i < N; i++) { @@ -42,12 +39,8 @@ namespace SenseShift::BH { } template<size_t N> - static void applyPlain( - HapticBody_t* output, - std::string& value, - const OutputLayout_t (&layout)[N], - const Effect_t effect - ) + static void + applyPlain(HapticBody_t* output, std::string& value, const OutputLayout_t (&layout)[N], const Effect_t effect) { std::uint8_t buf[N]; std::size_t copyLength = std::min(value.size(), sizeof(buf)); @@ -103,34 +96,29 @@ namespace SenseShift::BH { static void applyVest( HapticBody_t* output, const uint8_t (&value)[VEST_PAYLOAD_SIZE], - const Position_t (&layout)[VEST_LAYOUT_SIZE] + const OutputLayout_t (&layout)[VEST_LAYOUT_SIZE] ) { for (size_t i = 0; i < VEST_PAYLOAD_SIZE; i++) { uint8_t byte = value[i]; uint actIndex = i * 2; - const auto target = (actIndex < 10 || actIndex >= 30) ? Target_t::ChestFront : Target_t::ChestBack; - output->effect({ .effect = Effect_t::Vibro, - .target = target, - .position = layout[actIndex], + .target = std::get<0>(layout[actIndex]), + .position = std::get<1>(layout[actIndex]), .data = effectDataFromByte(Effect_t::Vibro, ((byte >> 4) & 0xf), 15), }); output->effect({ .effect = Effect_t::Vibro, - .target = target, - .position = layout[actIndex + 1], + .target = std::get<0>(layout[actIndex + 1]), + .position = std::get<1>(layout[actIndex + 1]), .data = effectDataFromByte(Effect_t::Vibro, (byte & 0xf), 15), }); } } - static void applyVest( - HapticBody_t* output, - std::string& value, - const Position_t (&layout)[VEST_LAYOUT_SIZE] - ) + static void + applyVest(HapticBody_t* output, std::string& value, const OutputLayout_t (&layout)[VEST_LAYOUT_SIZE]) { std::uint8_t buf[VEST_PAYLOAD_SIZE]; std::size_t copyLength = std::min(value.size(), sizeof(buf)); @@ -146,7 +134,7 @@ namespace SenseShift::BH { static void applyVestGrouped( HapticBody_t* output, const uint8_t (&value)[VEST_PAYLOAD_SIZE], - const Position_t (&layout)[VEST_LAYOUT_SIZE], + const OutputLayout_t (&layout)[VEST_LAYOUT_SIZE], const uint8_t (&layoutGroups)[N] ) { @@ -187,12 +175,13 @@ namespace SenseShift::BH { continue; } - const auto target = (i < 10 || i >= 30) ? Target_t::ChestFront : Target_t::ChestBack; + const auto target = std::get<0>(layout[i]); + const auto position = std::get<1>(layout[i]); output->effect({ .effect = Effect_t::Vibro, .target = target, - .position = layout[i], + .position = position, .data = effectDataFromByte(Effect_t::Vibro, result[i], 15), }); } @@ -202,7 +191,7 @@ namespace SenseShift::BH { static void applyVestGrouped( HapticBody_t* output, std::string& value, - const Position_t (&layout)[VEST_LAYOUT_SIZE], + const OutputLayout_t (&layout)[VEST_LAYOUT_SIZE], const uint8_t (&layoutGroups)[N] ) { diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp index a4f60bbc..68de48b5 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -29,10 +29,10 @@ namespace SenseShift::BH::BLE { class BHServerCallbacks final : public BLEServerCallbacks { - private: + private: OH::IEventDispatcher* dispatcher; - public: + public: BHServerCallbacks(OH::IEventDispatcher* eventDispatcher) : dispatcher(eventDispatcher) {} void onConnect(BLEServer* pServer) @@ -51,55 +51,55 @@ namespace SenseShift::BH::BLE { 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() + ">>\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() + ">>\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() + ">>\tonNotify (UUID: %s)\n\tvalue: `%s`, len: %u", + pCharacteristic->getUUID().toString().c_str(), + pCharacteristic->getValue().c_str(), + pCharacteristic->getValue().length() ); }; - #if defined(BLUETOOTH_USE_NIMBLE) && BLUETOOTH_USE_NIMBLE == true +#if defined(BLUETOOTH_USE_NIMBLE) && BLUETOOTH_USE_NIMBLE == true void onStatus(BLECharacteristic* pCharacteristic, Status s, int code) override - #else +#else void onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code) override - #endif +#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() + ">>\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: + private: Connection::MotorHandler_t motorTransformer; - public: + public: MotorCharCallbacks(Connection::MotorHandler_t motorTransformer) : motorTransformer(motorTransformer) {} void onWrite(BLECharacteristic* pCharacteristic) override @@ -149,26 +149,26 @@ namespace SenseShift::BH::BLE { MotorCharCallbacks* motorCallbacks = new MotorCharCallbacks(this->motorHandler); auto* motorChar = - this->motorService->createCharacteristic(BH_BLE_SERVICE_MOTOR_CHAR_MOTOR_UUID, PROPERTY_WRITE_NR); + 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); + 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 + BH_BLE_SERVICE_MOTOR_CHAR_CONFIG_UUID, + PROPERTY_READ | PROPERTY_WRITE ); configChar->setCallbacks(new ConfigCharCallbacks()); } { auto* serialNumberChar = this->motorService->createCharacteristic( - BH_BLE_SERVICE_MOTOR_CHAR_SERIAL_KEY_UUID, - PROPERTY_READ | PROPERTY_WRITE + BH_BLE_SERVICE_MOTOR_CHAR_SERIAL_KEY_UUID, + PROPERTY_READ | PROPERTY_WRITE ); serialNumberChar->setValue(this->config.serialNumber, ConnectionConfig_t::SN_LENGTH); serialNumberChar->setCallbacks(new LogOutputCharCallbacks()); @@ -176,21 +176,21 @@ namespace SenseShift::BH::BLE { { this->batteryChar = this->motorService->createCharacteristic( - BH_BLE_SERVICE_MOTOR_CHAR_BATTERY_UUID, - PROPERTY_READ | PROPERTY_WRITE_NR + 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(BLUETOOTH_USE_NIMBLE) || BLUETOOTH_USE_NIMBLE != true +#if !defined(BLUETOOTH_USE_NIMBLE) || BLUETOOTH_USE_NIMBLE != true batteryChar->addDescriptor(new BLE2902()); - #endif +#endif // original bHaptics Player require non-null value for battery level, otherwise it crashes - #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true +#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true uint16_t defaultLevel = 0; - #else +#else uint16_t defaultLevel = 100; - #endif +#endif this->batteryChar->setValue(defaultLevel); // this->batteryChar->notify(); @@ -198,7 +198,7 @@ namespace SenseShift::BH::BLE { { auto* versionChar = - this->motorService->createCharacteristic(BH_BLE_SERVICE_MOTOR_CHAR_VERSION_UUID, PROPERTY_READ); + 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); @@ -206,14 +206,15 @@ namespace SenseShift::BH::BLE { { 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 + 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(BLUETOOTH_USE_NIMBLE) || BLUETOOTH_USE_NIMBLE != true +#if !defined(BLUETOOTH_USE_NIMBLE) || BLUETOOTH_USE_NIMBLE != true monitorChar->addDescriptor(new BLE2902()); - #endif +#endif uint16_t audioCableState = NO_AUDIO_CABLE; monitorChar->setValue(audioCableState); @@ -221,25 +222,29 @@ namespace SenseShift::BH::BLE { // auto* athGlobalChar = this->motorService->createCharacteristic( // BH_BLE_SERVICE_MOTOR_CHAR_ATH_GLOBAL_CONF_UUID, - // PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | PROPERTY_WRITE_NR + // PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | + // PROPERTY_WRITE_NR // ); // athGlobalChar->setCallbacks(new LogOutputCharCallbacks()); // 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 + // 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 + // 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 + // PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | + // PROPERTY_WRITE_NR // ); // signatureMappingChar->setCallbacks(new LogOutputCharCallbacks()); @@ -249,12 +254,12 @@ namespace SenseShift::BH::BLE { auto dfuService = this->bleServer->createService(BH_BLE_SERVICE_DFU_UUID); auto* dfuControlChar = dfuService->createCharacteristic( - BH_BLE_SERVICE_MOTOR_CHAR_SIGNATURE_PATTERN_UUID, - PROPERTY_READ | PROPERTY_WRITE + BH_BLE_SERVICE_MOTOR_CHAR_SIGNATURE_PATTERN_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 f4d10f19..485e0212 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -3,8 +3,8 @@ #include <abstract_connection.hpp> #include <utility.hpp> -#include <senseshift/bh/constants.hpp> #include <senseshift/bh/ble/constants.hpp> +#include <senseshift/bh/constants.hpp> #include <Arduino.h> #include <esp_wifi.h> diff --git a/lib/core/types.hpp b/lib/core/types.hpp index ed2c7a20..49a7c3c3 100644 --- a/lib/core/types.hpp +++ b/lib/core/types.hpp @@ -4,10 +4,3 @@ #include <point2.hpp> #include <map> - -#define OH_OUTPUT_COORD_T uint8_t -#define OH_OUTPUT_COORD_MAX UINT8_MAX - -typedef uint8_t oh_output_path_t; -typedef OH_OUTPUT_COORD_T oh_output_coord_t; -typedef OH::Point2b oh_output_point_t; diff --git a/lib/hands/hand_interface.hpp b/lib/hands/hand_interface.hpp index 34dca343..ee079c5a 100644 --- a/lib/hands/hand_interface.hpp +++ b/lib/hands/hand_interface.hpp @@ -5,8 +5,16 @@ namespace SenseShift::Body { namespace Hands { - typedef std::uint8_t HandPositionIndex_t; - typedef enum class HandPosition : HandPositionIndex_t { Left, Right } HandPosition_t; + typedef std::uint8_t HandSideIndex_t; + typedef enum class HandSide : HandSideIndex_t { Left, Right } HandSide_t; + typedef std::uint8_t FingerIndex_t; + typedef enum class Finger : FingerIndex_t { + Thumb, + Index, + Middle, + Ring, + Little, + } Finger_t; namespace Haptics { /** diff --git a/lib/haptics/haptic_body.hpp b/lib/haptics/haptic_body.hpp index 088bad0e..eb1b06f9 100644 --- a/lib/haptics/haptic_body.hpp +++ b/lib/haptics/haptic_body.hpp @@ -23,11 +23,13 @@ namespace SenseShift::Body::Haptics { void addTarget(const Target_t, VibroPlane* plane); - const PlaneTargetMap_t* getTargets() const { return &allTargets; } + [[nodiscard]] const PlaneTargetMap_t* getTargets() const + { + return &allTargets; + } private: PlaneTargetMap_t allTargets{}; VibroTargetMap_t vibroTargets{}; - }; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/haptic_plane.hpp b/lib/haptics/haptic_plane.hpp index 66c47818..193fb633 100644 --- a/lib/haptics/haptic_plane.hpp +++ b/lib/haptics/haptic_plane.hpp @@ -34,6 +34,8 @@ namespace SenseShift::Body::Haptics { typedef OH::AbstractActuator Actuator_t; typedef std::map<Position_t, Actuator_t*> ActuatorMap_t; + ActuativePlane() = default; + ActuativePlane(const ActuatorMap_t& actuators) { this->setActuators(actuators); @@ -87,7 +89,7 @@ namespace SenseShift::Body::Haptics { class PlaneMapper_Margin { public: template<typename _Tp> - [[nodiscard]] static constexpr inline std::map<oh_output_point_t, _Tp*> + [[nodiscard]] static constexpr inline std::map<Position_t, _Tp*> mapMatrixCoordinates(std::vector<std::vector<_Tp*>> map2d) { std::map<Position_t, _Tp*> points{}; diff --git a/lib/haptics/haptics_interface.hpp b/lib/haptics/haptics_interface.hpp index ca926f21..5afc9ffd 100644 --- a/lib/haptics/haptics_interface.hpp +++ b/lib/haptics/haptics_interface.hpp @@ -32,7 +32,7 @@ namespace SenseShift::Body::Haptics { HandLeftMiddle, HandLeftRing, HandLeftLittle, - HandLeftVolar, // Palm + HandLeftVolar, // Palm HandLeftDorsal, // Back HandRightThumb, @@ -40,7 +40,7 @@ namespace SenseShift::Body::Haptics { HandRightMiddle, HandRightRing, HandRightLittle, - HandRightVolar, // Palm + HandRightVolar, // Palm HandRightDorsal, // Back // TODO: arms, legs, etc. diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index 332fb25d..94457355 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -1,12 +1,10 @@ -#include <bh_devices.hpp> -#include <bh_encoding.hpp> -#include <bh_types.hpp> - +#include <senseshift/bh/devices.hpp> +#include <senseshift/bh/encoding.hpp> #include <unity.h> using namespace SenseShift::Body::Haptics; +using namespace SenseShift::BH; using namespace OH; -using namespace BH; class TestActuator : public OH::AbstractActuator { public: @@ -27,7 +25,7 @@ class TestActuator : public OH::AbstractActuator { void test_layout_tactsuitx16(void) { static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; - static const oh_output_point_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX16; + static const OutputLayout_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX16; static const size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; static const uint8_t layoutGroups[layoutGroupsSize] = BH_LAYOUT_TACTSUITX16_GROUPS; @@ -95,7 +93,7 @@ void test_layout_tactsuitx16(void) void test_layout_tactsuitx40(void) { static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX40_SIZE; - static const oh_output_point_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; + static const OutputLayout_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; auto body = new HapticBody(); @@ -178,7 +176,7 @@ void test_layout_tactsuitx40(void) void test_layout_tactal(void) { static const size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; - static const oh_output_point_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; + static const ::SenseShift::Body::Haptics::Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; auto body = new HapticBody(); @@ -222,25 +220,21 @@ void test_layout_tactglove(void) TestActuator* actuatorLittle = new TestActuator(); TestActuator* actuatorWrist = new TestActuator(); - const auto& bhLayout = BH::TactGloveLeftLayout; - - auto thumb = new VibroPlane({ { std::get<2>(bhLayout[0]), actuatorThumb } }); - auto index = new VibroPlane({ { std::get<2>(bhLayout[1]), actuatorIndex } }); - auto middle = new VibroPlane({ { std::get<2>(bhLayout[2]), actuatorMiddle } }); - auto ring = new VibroPlane({ { std::get<2>(bhLayout[3]), actuatorRing } }); - auto little = new VibroPlane({ { std::get<2>(bhLayout[4]), actuatorLittle } }); - auto wrist = new VibroPlane({ { std::get<2>(bhLayout[5]), actuatorWrist } }); - auto body = new HapticBody(); + const auto& bhLayout = TactGloveLeftLayout; - body->addTarget(Target::HandLeftThumb, thumb); - body->addTarget(Target::HandLeftIndex, index); - body->addTarget(Target::HandLeftMiddle, middle); - body->addTarget(Target::HandLeftRing, ring); - body->addTarget(Target::HandLeftLittle, little); - body->addTarget(Target::HandLeftDorsal, wrist); + addTactGloveActuators( + body, + ::SenseShift::Body::Hands::HandSide::Left, + actuatorThumb, + actuatorIndex, + actuatorMiddle, + actuatorRing, + actuatorLittle, + actuatorWrist + ); - Decoder::applyPlain(body, { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 }, bhLayout); + Decoder::applyPlain(body, { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 }, bhLayout, Effect::Vibro); TEST_ASSERT_EQUAL_INT(4095, actuatorThumb->intensity); TEST_ASSERT_EQUAL_INT(0, actuatorIndex->intensity); TEST_ASSERT_EQUAL_INT(0, actuatorMiddle->intensity); @@ -248,7 +242,7 @@ void test_layout_tactglove(void) TEST_ASSERT_EQUAL_INT(0, actuatorLittle->intensity); TEST_ASSERT_EQUAL_INT(0, actuatorWrist->intensity); - Decoder::applyPlain(body, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, bhLayout); + Decoder::applyPlain(body, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, bhLayout, Effect::Vibro); TEST_ASSERT_EQUAL_INT(655, actuatorThumb->intensity); TEST_ASSERT_EQUAL_INT(1310, actuatorIndex->intensity); TEST_ASSERT_EQUAL_INT(1965, actuatorMiddle->intensity); @@ -264,6 +258,7 @@ int process(void) RUN_TEST(test_layout_tactsuitx16); RUN_TEST(test_layout_tactsuitx40); RUN_TEST(test_layout_tactal); + RUN_TEST(test_layout_tactglove); return UNITY_END(); } From 0b7a1ecfafb2653930d1a394ca6259c8b1b8c4ec Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 21 Aug 2023 21:56:50 +0400 Subject: [PATCH 08/82] refactor(Output): generic actuators --- firmware/mode_configs/bhaptics/tactal.cpp | 10 +++-- firmware/mode_configs/bhaptics/tactglove.cpp | 12 ++--- firmware/mode_configs/bhaptics/tactosy2.cpp | 10 +++-- firmware/mode_configs/bhaptics/tactosyf.cpp | 10 +++-- firmware/mode_configs/bhaptics/tactosyh.cpp | 10 +++-- .../mode_configs/bhaptics/tactsuit_x16.cpp | 16 ++++--- .../bhaptics/tactsuit_x16_pca9685.cpp | 14 +++--- .../mode_configs/bhaptics/tactsuit_x40.cpp | 16 ++++--- firmware/mode_configs/bhaptics/tactvisor.cpp | 10 +++-- .../mode_configs/opengloves/opengloves.cpp | 12 ++--- lib/actuators/senseshift/output/actuator.hpp | 22 ++++++++++ lib/arduino/output_writers/pwm.cpp | 29 ------------ lib/arduino/output_writers/pwm.hpp | 20 --------- lib/arduino/output_writers/servo.hpp | 30 ------------- lib/arduino/senseshift/arduino/output/pwm.hpp | 44 +++++++++++++++++++ .../senseshift/arduino/output/servo.hpp | 32 ++++++++++++++ lib/bhaptics/senseshift/bh/devices.hpp | 12 ++--- lib/core/types.hpp | 6 --- lib/haptics/haptic_body.hpp | 1 - lib/haptics/haptic_plane.cpp | 28 ++++++------ lib/haptics/haptic_plane.hpp | 30 ++++++------- lib/opengloves/og_ffb.hpp | 12 ++--- lib/output/abstract_actuator.hpp | 17 ------- lib/pca9685/output_writers/pca9685.cpp | 7 --- lib/pca9685/output_writers/pca9685.hpp | 20 --------- .../senseshift/arduino/output/pca9685.hpp | 26 +++++++++++ test/test_bhaptics_encoding/main.cpp | 26 +++++------ test/test_haptics_body/main.cpp | 9 ++-- test/test_haptics_plane/main.cpp | 9 ++-- 29 files changed, 257 insertions(+), 243 deletions(-) create mode 100644 lib/actuators/senseshift/output/actuator.hpp delete mode 100644 lib/arduino/output_writers/pwm.cpp delete mode 100644 lib/arduino/output_writers/pwm.hpp delete mode 100644 lib/arduino/output_writers/servo.hpp create mode 100644 lib/arduino/senseshift/arduino/output/pwm.hpp create mode 100644 lib/arduino/senseshift/arduino/output/servo.hpp delete mode 100644 lib/core/types.hpp delete mode 100644 lib/output/abstract_actuator.hpp delete mode 100644 lib/pca9685/output_writers/pca9685.cpp delete mode 100644 lib/pca9685/output_writers/pca9685.hpp create mode 100644 lib/pca9685/senseshift/arduino/output/pca9685.hpp diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index de7f9560..ba2a271e 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -6,7 +6,7 @@ #include "senseshift.h" -#include <output_writers/pwm.hpp> +#include <senseshift/arduino/output/pwm.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -17,6 +17,8 @@ using namespace OH; using namespace SenseShift; +using namespace SenseShift::Arduino::Output; +using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; @@ -28,7 +30,7 @@ static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; void setupMode() { // Configure PWM pins to their positions on the face - const auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + const auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26), new PWMOutputWriter(27), new PWMOutputWriter(14) }, // clang-format on @@ -38,14 +40,14 @@ void setupMode() app->getHapticBody()->setup(); - auto* bhBleConnection = new BH::BLE::Connection( + auto* bhBleConnection = new BLE::Connection( { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); + Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 14acadd8..6ff9d7c4 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -8,7 +8,7 @@ #include "senseshift.h" -#include <output_writers/pwm.hpp> +#include <senseshift/arduino/output/pwm.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -19,6 +19,8 @@ using namespace OH; using namespace SenseShift; +using namespace SenseShift::Arduino::Output; +using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; @@ -27,14 +29,14 @@ SenseShift::SenseShift* app = &App; static const Body::Hands::HandSide_t handSide = Body::Hands::HandSide::SENSESHIFT_HAND_SIDE; static const size_t bhLayoutSize = BH_LAYOUT_TACTGLOVE_SIZE; // clang-format off -static const BH::OutputLayout_t (&bhLayout)[bhLayoutSize] = handSide == Body::Hands::HandSide::Left ? BH::TactGloveLeftLayout : BH::TactGloveRightLayout; +static const OutputLayout_t (&bhLayout)[bhLayoutSize] = handSide == Body::Hands::HandSide::Left ? BH::TactGloveLeftLayout : BH::TactGloveRightLayout; // clang-format on void setupMode() { // Configure PWM pins to their positions on the glove // Replace `new PWMOutputWriter(...)` with `nullptr` to disable a specific actuator - BH::addTactGloveActuators( + addTactGloveActuators( app->getHapticBody(), handSide, new PWMOutputWriter(32), // Thumb @@ -47,14 +49,14 @@ void setupMode() app->getHapticBody()->setup(); - auto* bhBleConnection = new BH::BLE::Connection( + auto* bhBleConnection = new BLE::Connection( { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect_t::Vibro); + Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect_t::Vibro); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index fb6bd77f..6a4af3a6 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -6,7 +6,7 @@ #include "senseshift.h" -#include <output_writers/pwm.hpp> +#include <senseshift/arduino/output/pwm.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -17,6 +17,8 @@ using namespace OH; using namespace SenseShift; +using namespace SenseShift::Arduino::Output; +using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; @@ -28,7 +30,7 @@ static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSY2; void setupMode() { // Configure PWM pins to their positions on the forearm - auto forearmOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto forearmOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25) }, { new PWMOutputWriter(26), new PWMOutputWriter(27), new PWMOutputWriter(14) }, @@ -39,14 +41,14 @@ void setupMode() app->getHapticBody()->setup(); - auto* bhBleConnection = new BH::BLE::Connection( + auto* bhBleConnection = new BLE::Connection( { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); + Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index 277377ae..4595b904 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -6,7 +6,7 @@ #include "senseshift.h" -#include <output_writers/pwm.hpp> +#include <senseshift/arduino/output/pwm.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -17,6 +17,8 @@ using namespace OH; using namespace SenseShift; +using namespace SenseShift::Arduino::Output; +using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; @@ -28,7 +30,7 @@ static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYF; void setupMode() { // Configure PWM pins to their positions on the feet - auto footOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto footOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off { new PWMOutputWriter(32) }, { new PWMOutputWriter(33) }, @@ -40,14 +42,14 @@ void setupMode() app->getHapticBody()->setup(); - auto* bhBleConnection = new BH::BLE::Connection( + auto* bhBleConnection = new BLE::Connection( { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); + Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 543f2275..c2904352 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -6,7 +6,7 @@ #include "senseshift.h" -#include <output_writers/pwm.hpp> +#include <senseshift/arduino/output/pwm.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -17,6 +17,8 @@ using namespace OH; using namespace SenseShift; +using namespace SenseShift::Arduino::Output; +using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; @@ -28,7 +30,7 @@ static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYH; void setupMode() { // Configure PWM pins to their positions on the hands - auto handOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto handOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off { new PWMOutputWriter(32) }, { new PWMOutputWriter(33) }, @@ -40,14 +42,14 @@ void setupMode() app->getHapticBody()->setup(); - auto* bhBleConnection = new BH::BLE::Connection( + auto* bhBleConnection = new BLE::Connection( { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); + Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 4b4cf7d2..0fb4875d 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -6,7 +6,7 @@ #include "senseshift.h" -#include <output_writers/pwm.hpp> +#include <senseshift/arduino/output/pwm.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -17,13 +17,15 @@ using namespace OH; using namespace SenseShift; +using namespace SenseShift::Arduino::Output; +using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; -static const BH::OutputLayout_t bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; +static const OutputLayout_t bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; // Ouput indices, responsible for x40 => x16 grouping static const size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; @@ -32,16 +34,16 @@ static const uint8_t layoutGroups[layoutGroupsSize] = BH_LAYOUT_TACTSUITX16_GROU void setupMode() { // Configure PWM pins to their positions on the vest - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26) }, { new PWMOutputWriter(27), new PWMOutputWriter(14), new PWMOutputWriter(12), new PWMOutputWriter(13) }, // clang-format on }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off { new PWMOutputWriter(19), new PWMOutputWriter(18), new PWMOutputWriter(5), new PWMOutputWriter(17) }, - { new PWMOutputWriter(16), new PWMOutputWriter(4), new PWMOutputWriter(2), new PWMOutputWriter(15) }, + { new PWMOutputWriter(16), new PWMOutputWriter(4), new PWMOutputWriter(2), new PWMOutputWriter(15) }, // clang-format on }); @@ -50,14 +52,14 @@ void setupMode() app->getHapticBody()->setup(); - auto* bhBleConnection = new BH::BLE::Connection( + auto* bhBleConnection = new BLE::Connection( { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - BH::Decoder::applyVestGrouped(app->getHapticBody(), value, bhLayout, layoutGroups); + Decoder::applyVestGrouped(app->getHapticBody(), value, bhLayout, layoutGroups); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index b9051e9e..74df3252 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -6,7 +6,7 @@ #include "senseshift.h" -#include <output_writers/pca9685.hpp> +#include <senseshift/arduino/output/pca9685.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -17,13 +17,15 @@ using namespace OH; using namespace SenseShift; +using namespace SenseShift::Arduino::Output; +using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; -static const BH::OutputLayout_t bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; +static const OutputLayout_t bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; // Ouput indices, responsible for x40 => x16 grouping static const size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; @@ -37,13 +39,13 @@ void setupMode() pwm->setPWMFreq(PWM_FREQUENCY); // Assign the pins on the configured PCA9685 to positions on the vest - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off { new PCA9685OutputWriter(pwm, 0), new PCA9685OutputWriter(pwm, 1), new PCA9685OutputWriter(pwm, 2), new PCA9685OutputWriter(pwm, 3) }, { new PCA9685OutputWriter(pwm, 4), new PCA9685OutputWriter(pwm, 5), new PCA9685OutputWriter(pwm, 6), new PCA9685OutputWriter(pwm, 7) }, // clang-format on }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off { new PCA9685OutputWriter(pwm, 8), new PCA9685OutputWriter(pwm, 9), new PCA9685OutputWriter(pwm, 10), new PCA9685OutputWriter(pwm, 11) }, { new PCA9685OutputWriter(pwm, 12), new PCA9685OutputWriter(pwm, 13), new PCA9685OutputWriter(pwm, 14), new PCA9685OutputWriter(pwm, 15) }, @@ -55,14 +57,14 @@ void setupMode() app->getHapticBody()->setup(); - auto* bhBleConnection = new BH::BLE::Connection( + auto* bhBleConnection = new BLE::Connection( { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - BH::Decoder::applyVestGrouped(app->getHapticBody(), value, bhLayout, layoutGroups); + Decoder::applyVestGrouped(app->getHapticBody(), value, bhLayout, layoutGroups); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 6ec93001..13a0689f 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -6,8 +6,8 @@ #include "senseshift.h" -#include <output_writers/pca9685.hpp> -#include <output_writers/pwm.hpp> +#include <senseshift/arduino/output/pca9685.hpp> +#include <senseshift/arduino/output/pwm.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -18,13 +18,15 @@ using namespace OH; using namespace SenseShift; +using namespace SenseShift::Arduino::Output; +using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX40_SIZE; -static const BH::OutputLayout_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; +static const OutputLayout_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; void setupMode() { @@ -39,7 +41,7 @@ void setupMode() // Assign the pins on the configured PCA9685s and PWM pins to locations on the // vest - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off { new PCA9685OutputWriter(pwm0, 0), new PCA9685OutputWriter(pwm0, 1), new PCA9685OutputWriter(pwm0, 2), new PCA9685OutputWriter(pwm0, 3) }, { new PCA9685OutputWriter(pwm0, 4), new PCA9685OutputWriter(pwm0, 5), new PCA9685OutputWriter(pwm0, 6), new PCA9685OutputWriter(pwm0, 7) }, @@ -48,7 +50,7 @@ void setupMode() { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26) }, // clang-format on }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off { new PCA9685OutputWriter(pwm1, 0), new PCA9685OutputWriter(pwm1, 1), new PCA9685OutputWriter(pwm1, 2), new PCA9685OutputWriter(pwm1, 3) }, { new PCA9685OutputWriter(pwm1, 4), new PCA9685OutputWriter(pwm1, 5), new PCA9685OutputWriter(pwm1, 6), new PCA9685OutputWriter(pwm1, 7) }, @@ -63,14 +65,14 @@ void setupMode() app->getHapticBody()->setup(); - auto* bhBleConnection = new BH::BLE::Connection( + auto* bhBleConnection = new BLE::Connection( { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - BH::Decoder::applyVest(app->getHapticBody(), value, bhLayout); + Decoder::applyVest(app->getHapticBody(), value, bhLayout); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index 9e2bb10d..73c88463 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -6,7 +6,7 @@ #include "senseshift.h" -#include <output_writers/pwm.hpp> +#include <senseshift/arduino/output/pwm.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -17,6 +17,8 @@ using namespace OH; using namespace SenseShift; +using namespace SenseShift::Arduino::Output; +using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; @@ -28,7 +30,7 @@ static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTVISOR; void setupMode() { // Configure PWM pins to their positions on the face - auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26) }, // clang-format on @@ -38,14 +40,14 @@ void setupMode() app->getHapticBody()->setup(); - auto* bhBleConnection = new BH::BLE::Connection( + auto* bhBleConnection = new BLE::Connection( { .deviceName = BLUETOOTH_NAME, .appearance = BH_BLE_APPEARANCE, .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - BH::Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); + Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); }, app ); diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index d575a4cb..b1b78eb1 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -2,7 +2,7 @@ #include <og_constants.hpp> #include <og_serial_communication.hpp> #include <opengloves_task.hpp> -#include <output_writers/servo.hpp> +#include <senseshift/arduino/output/servo.hpp> #include <sensor.hpp> #include <sensor/analog.hpp> #include <sensor/digital.hpp> @@ -285,23 +285,23 @@ OpenGlovesTrackingTask* trackingTask; #if FFB_ENABLED HandActuators handActuators = { #if FFB_THUMB_ENABLED - .thumb = new OH::ServoActuator(PIN_FFB_THUMB), + .thumb = new SenseShift::Arduino::Output::ServoActuator(PIN_FFB_THUMB), #endif #if FFB_INDEX_ENABLED - .index = new OH::ServoActuator(PIN_FFB_INDEX), + .index = new SenseShift::Arduino::Output::ServoActuator(PIN_FFB_INDEX), #endif #if FFB_MIDDLE_ENABLED - .middle = new OH::ServoActuator(PIN_FFB_MIDDLE), + .middle = new SenseShift::Arduino::Output::ServoActuator(PIN_FFB_MIDDLE), #endif #if FFB_RING_ENABLED - .ring = new OH::ServoActuator(PIN_FFB_RING), + .ring = new SenseShift::Arduino::Output::ServoActuator(PIN_FFB_RING), #endif #if FFB_PINKY_ENABLED - .pinky = new OH::ServoActuator(PIN_FFB_PINKY), + .pinky = new SenseShift::Arduino::Output::ServoActuator(PIN_FFB_PINKY), #endif }; OpenGlovesForceFeedbackTask* ffbTask; diff --git a/lib/actuators/senseshift/output/actuator.hpp b/lib/actuators/senseshift/output/actuator.hpp new file mode 100644 index 00000000..5f56db6b --- /dev/null +++ b/lib/actuators/senseshift/output/actuator.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include <cstdint> + +#include <logging.hpp> + +namespace SenseShift::Output { + // Singular output point (e.g. vibration motor) + template<typename T> + class IActuator { + public: + virtual void setup(){}; + virtual void writeOutput(T) = 0; + }; + + template<> + class IActuator<std::uint16_t> { + public: + virtual void setup(){}; + virtual void writeOutput(std::uint16_t) = 0; + }; +} // namespace SenseShift::Output diff --git a/lib/arduino/output_writers/pwm.cpp b/lib/arduino/output_writers/pwm.cpp deleted file mode 100644 index 344cce1f..00000000 --- a/lib/arduino/output_writers/pwm.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include <Arduino.h> - -#include <output_writers/pwm.hpp> -#include <utility.hpp> - -namespace OH { - uint8_t PWMOutputWriter::CHANNELS = 0; - - void PWMOutputWriter::setup() - { - this->chan = PWMOutputWriter::CHANNELS++; - -#if defined(ESP32) - ledcSetup(this->chan, this->freq, this->resolution); - ledcAttachPin(this->pin, this->chan); -#else - pinMode(this->pin, OUTPUT); -#endif - }; - - void PWMOutputWriter::writeOutput(oh_output_intensity_t intensity) - { -#if defined(ESP32) - ledcWrite(chan, simpleMap<uint16_t>(intensity, OH_OUTPUT_INTENSITY_MAX, (1 << this->resolution) - 1)); -#else - analogWrite(this->pin, simpleMap<uint16_t>(intensity, OH_OUTPUT_INTENSITY_MAX, 255)); -#endif - }; -}; // namespace OH diff --git a/lib/arduino/output_writers/pwm.hpp b/lib/arduino/output_writers/pwm.hpp deleted file mode 100644 index eecdccbf..00000000 --- a/lib/arduino/output_writers/pwm.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include <abstract_actuator.hpp> - -namespace OH { - class PWMOutputWriter : public OH::AbstractActuator { - private: - static uint8_t CHANNELS; - uint8_t pin, chan; - double freq; - uint8_t resolution; - - public: - PWMOutputWriter(const uint8_t pin, const double freq = 60, const uint8_t resolution = 12) : - pin(pin), freq(freq), resolution(resolution){}; - - void setup() override; - void writeOutput(oh_output_intensity_t intensity) override; - }; -}; // namespace OH diff --git a/lib/arduino/output_writers/servo.hpp b/lib/arduino/output_writers/servo.hpp deleted file mode 100644 index 6223d265..00000000 --- a/lib/arduino/output_writers/servo.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include <abstract_actuator.hpp> -#include <utility.hpp> - -#include <ESP32Servo.h> - -namespace OH { - class ServoActuator : public AbstractActuator { - public: - ServoActuator(const uint8_t pin, const uint16_t min = 500, const uint16_t max = 2400) : - pin(pin), min(min), max(max){}; - - void setup() override - { - servo.attach(this->pin, this->min, this->max); - this->writeOutput(0); - }; - - void writeOutput(oh_output_intensity_t intensity) override - { - servo.writeMicroseconds(accurateMap<uint16_t>(intensity, 0, OH_OUTPUT_INTENSITY_MAX, this->min, this->max)); - }; - - protected: - Servo servo = Servo(); - uint8_t pin; - uint16_t min, max; - }; -} // namespace OH diff --git a/lib/arduino/senseshift/arduino/output/pwm.hpp b/lib/arduino/senseshift/arduino/output/pwm.hpp new file mode 100644 index 00000000..a8145565 --- /dev/null +++ b/lib/arduino/senseshift/arduino/output/pwm.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include <senseshift/output/actuator.hpp> +#include <utility.hpp> + +#include <Arduino.h> + +namespace SenseShift::Arduino::Output { + class PWMOutputWriter : public ::SenseShift::Output::IActuator<std::uint16_t> { + public: + static inline constexpr const std::uint16_t MAX_INTENSITY = 4095; + + PWMOutputWriter(const std::uint8_t pin, const double freq = 60, const std::uint8_t resolution = 12) : + pin(pin), freq(freq), resolution(resolution){}; + + void setup() override + { + this->chan = CHANNELS++; + +#if defined(ESP32) + ledcSetup(this->chan, this->freq, this->resolution); + ledcAttachPin(this->pin, this->chan); +#else + pinMode(this->pin, OUTPUT); +#endif + } + + void writeOutput(std::uint16_t intensity) override + { +#if defined(ESP32) + ledcWrite(chan, OH::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, (1 << this->resolution) - 1)); +#else + // Arduino only supports 8-bit PWM + analogWrite(this->pin, OH::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, (1 << 8) - 1)); +#endif + } + + private: + static inline std::uint8_t CHANNELS = 0; + std::uint8_t pin, chan; + double freq; + std::uint8_t resolution; + }; +}; // namespace SenseShift::Arduino::Output diff --git a/lib/arduino/senseshift/arduino/output/servo.hpp b/lib/arduino/senseshift/arduino/output/servo.hpp new file mode 100644 index 00000000..88fa6c85 --- /dev/null +++ b/lib/arduino/senseshift/arduino/output/servo.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include <senseshift/output/actuator.hpp> +#include <utility.hpp> + +#include <ESP32Servo.h> + +namespace SenseShift::Arduino::Output { + class ServoActuator : public ::SenseShift::Output::IActuator<std::uint16_t> { + public: + static inline constexpr const std::uint16_t MAX_INTENSITY = 4095; + + ServoActuator(const uint8_t pin, const std::uint16_t min = 500, const std::uint16_t max = 2400) : + pin(pin), min(min), max(max){}; + + void setup() override + { + servo.attach(this->pin, this->min, this->max); + this->writeOutput(0); + }; + + void writeOutput(std::uint16_t intensity) override + { + servo.writeMicroseconds(OH::accurateMap<std::uint16_t>(intensity, 0, MAX_INTENSITY, this->min, this->max)); + }; + + private: + Servo servo = Servo(); + uint8_t pin; + std::uint16_t min, max; + }; +} // namespace SenseShift::Arduino::Output diff --git a/lib/bhaptics/senseshift/bh/devices.hpp b/lib/bhaptics/senseshift/bh/devices.hpp index 7c5531f0..d3c24d1b 100644 --- a/lib/bhaptics/senseshift/bh/devices.hpp +++ b/lib/bhaptics/senseshift/bh/devices.hpp @@ -297,12 +297,12 @@ namespace SenseShift::BH { inline void addTactGloveActuators( HapticBody* hapticBody, const HandSide_t side, - OH::AbstractActuator* const thumbActuator, - OH::AbstractActuator* const indexActuator, - OH::AbstractActuator* const middleActuator, - OH::AbstractActuator* const ringActuator, - OH::AbstractActuator* const littleActuator, - OH::AbstractActuator* const wristActuator + VibroPlane::Actuator_t* const thumbActuator, + VibroPlane::Actuator_t* const indexActuator, + VibroPlane::Actuator_t* const middleActuator, + VibroPlane::Actuator_t* const ringActuator, + VibroPlane::Actuator_t* const littleActuator, + VibroPlane::Actuator_t* const wristActuator ) { const OutputLayout_t(&layout)[6] = (side == HandSide_t::Left) ? TactGloveLeftLayout : TactGloveRightLayout; diff --git a/lib/core/types.hpp b/lib/core/types.hpp deleted file mode 100644 index 49a7c3c3..00000000 --- a/lib/core/types.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include <abstract_actuator.hpp> -#include <point2.hpp> - -#include <map> diff --git a/lib/haptics/haptic_body.hpp b/lib/haptics/haptic_body.hpp index eb1b06f9..351e31eb 100644 --- a/lib/haptics/haptic_body.hpp +++ b/lib/haptics/haptic_body.hpp @@ -3,7 +3,6 @@ #include "haptic_plane.hpp" #include "haptics_interface.hpp" -#include <types.hpp> #include <utility.hpp> #include <map> diff --git a/lib/haptics/haptic_plane.cpp b/lib/haptics/haptic_plane.cpp index 6c10861f..d22c6f55 100644 --- a/lib/haptics/haptic_plane.cpp +++ b/lib/haptics/haptic_plane.cpp @@ -7,8 +7,8 @@ #include "haptic_plane.hpp" namespace SenseShift::Body::Haptics { - template<typename _Tp> - void ActuativePlane<_Tp>::setActuators(const ActuatorMap_t& actuators) + template<typename _Tp, typename _Ta> + void ActuativePlane<_Tp, _Ta>::setActuators(const ActuatorMap_t& actuators) { this->actuators.clear(); for (const auto& [point, actuator] : actuators) { @@ -26,16 +26,16 @@ namespace SenseShift::Body::Haptics { } } - template<typename _Tp> - void ActuativePlane<_Tp>::setup() + template<typename _Tp, typename _Ta> + void ActuativePlane<_Tp, _Ta>::setup() { for (const auto& [point, actuator] : this->actuators) { actuator->setup(); } } - template<typename _Tp> - void ActuativePlane<_Tp>::effect(const Position_t& pos, const Value_t& val) + template<typename _Tp, typename _Ta> + void ActuativePlane<_Tp, _Ta>::effect(const Position_t& pos, const Value_t& val) { auto it = this->actuators.find(pos); if (it == this->actuators.end()) { @@ -47,16 +47,16 @@ namespace SenseShift::Body::Haptics { this->states[pos] = val; } - template<typename _Tp> - void ActuativePlane_Closest<_Tp>::effect(const Position_t& pos, const Value_t& val) + template<typename _Tp, typename _Ta> + void ActuativePlane_Closest<_Tp, _Ta>::effect(const Position_t& pos, const Value_t& val) { auto& closest = this->findClosestPoint(*this->getAvailablePoints(), pos); - ActuativePlane<_Tp>::effect(closest, val); + ActuativePlane<_Tp, _Ta>::effect(closest, val); } - template<typename _Tp> + template<typename _Tp, typename _Ta> const Position_t& - ActuativePlane_Closest<_Tp>::findClosestPoint(const PositionSet_t& pts, const Position_t& target) const + ActuativePlane_Closest<_Tp, _Ta>::findClosestPoint(const PositionSet_t& pts, const Position_t& target) const { // check if exact point exists auto it = pts.find(target); @@ -75,6 +75,8 @@ namespace SenseShift::Body::Haptics { return nearest->second; } - template class ActuativePlane<VibroEffectData_t>; - template class ActuativePlane_Closest<VibroEffectData_t>; + template class ActuativePlane<VibroEffectData_t, ::SenseShift::Output::IActuator<VibroEffectData_t::Intensity_t>>; + template class ActuativePlane_Closest< + VibroEffectData_t, + ::SenseShift::Output::IActuator<VibroEffectData_t::Intensity_t>>; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/haptic_plane.hpp b/lib/haptics/haptic_plane.hpp index 193fb633..97aac1c9 100644 --- a/lib/haptics/haptic_plane.hpp +++ b/lib/haptics/haptic_plane.hpp @@ -2,8 +2,8 @@ #include "haptics_interface.hpp" -#include <abstract_actuator.hpp> -#include <types.hpp> +#include <senseshift/output/actuator.hpp> + #include <utility.hpp> #include <list> @@ -19,20 +19,16 @@ namespace SenseShift::Body::Haptics { * * @tparam _Tp The type of the output value. */ - template<typename _Tp> + template<typename _Tp, typename _Ta> class ActuativePlane { static_assert(std::is_same<_Tp, VibroEffectData_t>()); public: - typedef _Tp Value_t; - typedef std::map<Position_t, Value_t> PositionStateMap_t; + using Value_t = _Tp; + using Actuator_t = _Ta; - /** - * The type of the actuator. - * @TODO: Make this a template parameter - */ - typedef OH::AbstractActuator Actuator_t; typedef std::map<Position_t, Actuator_t*> ActuatorMap_t; + typedef std::map<Position_t, Value_t> PositionStateMap_t; ActuativePlane() = default; @@ -61,19 +57,20 @@ namespace SenseShift::Body::Haptics { void setActuators(const ActuatorMap_t&); }; - typedef ActuativePlane<VibroEffectData_t> VibroPlane; + typedef ActuativePlane<VibroEffectData_t, ::SenseShift::Output::IActuator<VibroEffectData_t::Intensity_t>> + VibroPlane; /** * Output plane, finds the closest actuator for the given point. * @deprecated We should guarantee on the driver level, that the actuator is always exists */ - template<typename _Tp> - class ActuativePlane_Closest : public ActuativePlane<_Tp> { + template<typename _Tp, typename _Ta> + class ActuativePlane_Closest : public ActuativePlane<_Tp, _Ta> { public: typedef _Tp Value_t; - ActuativePlane_Closest(const typename ActuativePlane<_Tp>::ActuatorMap_t& actuators) : - ActuativePlane<_Tp>(actuators) + ActuativePlane_Closest(const typename ActuativePlane<_Tp, _Ta>::ActuatorMap_t& actuators) : + ActuativePlane<_Tp, _Ta>(actuators) { } @@ -83,7 +80,8 @@ namespace SenseShift::Body::Haptics { [[nodiscard]] const Position_t& findClosestPoint(const PositionSet_t&, const Position_t&) const; }; - typedef ActuativePlane_Closest<VibroEffectData_t> VibroPlane_Closest; + typedef ActuativePlane_Closest<VibroEffectData_t, ::SenseShift::Output::IActuator<VibroEffectData_t::Intensity_t>> + VibroPlane_Closest; // TODO: configurable margin class PlaneMapper_Margin { diff --git a/lib/opengloves/og_ffb.hpp b/lib/opengloves/og_ffb.hpp index c1a8b42a..ca2c5b9d 100644 --- a/lib/opengloves/og_ffb.hpp +++ b/lib/opengloves/og_ffb.hpp @@ -1,15 +1,15 @@ #pragma once -#include <abstract_actuator.hpp> +#include <senseshift/output/actuator.hpp> #include <optional> namespace OpenGloves { struct HandActuators { - std::optional<OH::AbstractActuator*> thumb = std::nullopt; - std::optional<OH::AbstractActuator*> index = std::nullopt; - std::optional<OH::AbstractActuator*> middle = std::nullopt; - std::optional<OH::AbstractActuator*> ring = std::nullopt; - std::optional<OH::AbstractActuator*> pinky = std::nullopt; + std::optional<::SenseShift::Output::IActuator<uint16_t>*> thumb = std::nullopt; + std::optional<::SenseShift::Output::IActuator<uint16_t>*> index = std::nullopt; + std::optional<::SenseShift::Output::IActuator<uint16_t>*> middle = std::nullopt; + std::optional<::SenseShift::Output::IActuator<uint16_t>*> ring = std::nullopt; + std::optional<::SenseShift::Output::IActuator<uint16_t>*> pinky = std::nullopt; }; } // namespace OpenGloves diff --git a/lib/output/abstract_actuator.hpp b/lib/output/abstract_actuator.hpp deleted file mode 100644 index 50df1752..00000000 --- a/lib/output/abstract_actuator.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include <stdint.h> - -#define OH_OUTPUT_INTENSITY_T uint16_t -#define OH_OUTPUT_INTENSITY_MAX 4095 - -typedef OH_OUTPUT_INTENSITY_T oh_output_intensity_t; - -namespace OH { - //! Singular output point (e.g. vibration motor) - class AbstractActuator { - public: - virtual void setup(){}; - virtual void writeOutput(oh_output_intensity_t intensity) = 0; - }; -} // namespace OH diff --git a/lib/pca9685/output_writers/pca9685.cpp b/lib/pca9685/output_writers/pca9685.cpp deleted file mode 100644 index 4e20d609..00000000 --- a/lib/pca9685/output_writers/pca9685.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "output_writers/pca9685.hpp" -#include <utility.hpp> - -void OH::PCA9685OutputWriter::writeOutput(oh_output_intensity_t intensity) -{ - this->driver->setPin(this->num, simpleMap<uint16_t>(intensity, OH_OUTPUT_INTENSITY_MAX, 4095)); -} diff --git a/lib/pca9685/output_writers/pca9685.hpp b/lib/pca9685/output_writers/pca9685.hpp deleted file mode 100644 index 69db3fcf..00000000 --- a/lib/pca9685/output_writers/pca9685.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include <Adafruit_PWMServoDriver.h> -#include <Arduino.h> -#include <Wire.h> - -#include <abstract_actuator.hpp> - -namespace OH { - class PCA9685OutputWriter : public OH::AbstractActuator { - private: - Adafruit_PWMServoDriver* driver; - uint8_t num; - - public: - PCA9685OutputWriter(Adafruit_PWMServoDriver* driver, const uint8_t num) : driver(driver), num(num){}; - - void writeOutput(oh_output_intensity_t intensity) override; - }; -} // namespace OH diff --git a/lib/pca9685/senseshift/arduino/output/pca9685.hpp b/lib/pca9685/senseshift/arduino/output/pca9685.hpp new file mode 100644 index 00000000..a6529521 --- /dev/null +++ b/lib/pca9685/senseshift/arduino/output/pca9685.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include <senseshift/output/actuator.hpp> +#include <utility.hpp> + +#include <Adafruit_PWMServoDriver.h> +#include <Arduino.h> +#include <Wire.h> + +namespace SenseShift::Arduino::Output { + class PCA9685OutputWriter : public ::SenseShift::Output::IActuator<std::uint16_t> { + public: + static inline constexpr const std::uint16_t MAX_INTENSITY = 4095; + + PCA9685OutputWriter(Adafruit_PWMServoDriver* driver, const std::uint8_t num) : driver(driver), num(num){}; + + void writeOutput(std::uint16_t intensity) override + { + this->driver->setPin(this->num, OH::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, 4095)); + } + + private: + Adafruit_PWMServoDriver* driver; + std::uint8_t num; + }; +} // namespace SenseShift::Arduino::Output diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index 94457355..2de6e52e 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -2,21 +2,21 @@ #include <senseshift/bh/encoding.hpp> #include <unity.h> -using namespace SenseShift::Body::Haptics; using namespace SenseShift::BH; -using namespace OH; +using namespace SenseShift::Body::Haptics; +using namespace SenseShift::Output; -class TestActuator : public OH::AbstractActuator { +class TestActuator : public IActuator<uint16_t> { public: bool isSetup = false; - oh_output_intensity_t intensity = 0; + uint16_t intensity = 0; - TestActuator() : AbstractActuator() {} + TestActuator() : IActuator<uint16_t>() {} void setup() override { this->isSetup = true; } - void writeOutput(oh_output_intensity_t intensity) override + void writeOutput(uint16_t intensity) override { this->intensity = intensity; } @@ -49,11 +49,11 @@ void test_layout_tactsuitx16(void) TestActuator* actuator14 = new TestActuator(); TestActuator* actuator15 = new TestActuator(); - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<OH::AbstractActuator>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ { actuator0, actuator1, actuator2, actuator3 }, { actuator4, actuator5, actuator6, actuator7 }, }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ { actuator8, actuator9, actuator10, actuator11 }, { actuator12, actuator13, actuator14, actuator15 }, }); @@ -97,14 +97,14 @@ void test_layout_tactsuitx40(void) auto body = new HapticBody(); - std::vector<std::vector<AbstractActuator*>> frontMatrix = { + std::vector<std::vector<VibroPlane::Actuator_t*>> frontMatrix = { { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, }; - std::vector<std::vector<AbstractActuator*>> backMatrix = { + std::vector<std::vector<VibroPlane::Actuator_t*>> backMatrix = { { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, @@ -112,8 +112,8 @@ void test_layout_tactsuitx40(void) { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, }; - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>(frontMatrix); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>(backMatrix); + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>(frontMatrix); + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>(backMatrix); auto frontPlane = new VibroPlane(frontOutputs); auto backPlane = new VibroPlane(backOutputs); @@ -187,7 +187,7 @@ void test_layout_tactal(void) TestActuator* actuator4 = new TestActuator(); TestActuator* actuator5 = new TestActuator(); - auto outputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ + auto outputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ { actuator0, actuator1, actuator2, actuator3, actuator4, actuator5 }, }); auto plane = new VibroPlane(outputs); diff --git a/test/test_haptics_body/main.cpp b/test/test_haptics_body/main.cpp index f5ceb76f..27b8b56e 100644 --- a/test/test_haptics_body/main.cpp +++ b/test/test_haptics_body/main.cpp @@ -2,18 +2,19 @@ #include <unity.h> using namespace SenseShift::Body::Haptics; +using namespace SenseShift::Output; -class TestActuator : public OH::AbstractActuator { +class TestActuator : public IActuator<uint16_t> { public: bool isSetup = false; - oh_output_intensity_t intensity = 0; + uint16_t intensity = 0; - TestActuator() : AbstractActuator() {} + TestActuator() : IActuator<uint16_t>() {} void setup() override { this->isSetup = true; } - void writeOutput(oh_output_intensity_t intensity) override + void writeOutput(uint16_t intensity) override { this->intensity = intensity; } diff --git a/test/test_haptics_plane/main.cpp b/test/test_haptics_plane/main.cpp index ec1af818..38e4594b 100644 --- a/test/test_haptics_plane/main.cpp +++ b/test/test_haptics_plane/main.cpp @@ -2,18 +2,19 @@ #include <unity.h> using namespace SenseShift::Body::Haptics; +using namespace SenseShift::Output; -class TestActuator : public OH::AbstractActuator { +class TestActuator : public IActuator<uint16_t> { public: bool isSetup = false; - oh_output_intensity_t intensity = 0; + uint16_t intensity = 0; - TestActuator() : AbstractActuator() {} + TestActuator() : IActuator<uint16_t>() {} void setup() override { this->isSetup = true; } - void writeOutput(oh_output_intensity_t intensity) override + void writeOutput(uint16_t intensity) override { this->intensity = intensity; } From 4977fd0e3be1560aaaff1459ec9baebe0ae543db Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 21 Aug 2023 22:50:45 +0400 Subject: [PATCH 09/82] refactor(Core): move to `SenseShift` namespace and directory --- firmware/mode_configs/bhaptics/tactglove.cpp | 3 +- .../mode_configs/opengloves/opengloves.cpp | 2 +- firmware/senseshift.cpp | 6 ++-- include/senseshift.h | 11 ++++---- lib/actuators/senseshift/output/actuator.hpp | 2 +- lib/arduino/battery/adc_naive.cpp | 4 +-- lib/arduino/senseshift/arduino/output/pwm.hpp | 9 ++++-- .../senseshift/arduino/output/servo.hpp | 6 ++-- lib/battery/abstract_battery.hpp | 13 +++++---- lib/bhaptics/senseshift/bh/encoding.hpp | 10 ++++--- .../senseshift/bh/ble/connection.cpp | 13 ++++----- .../senseshift/bh/ble/connection.hpp | 20 +++++++------ lib/calibration/calibration.hpp | 28 +++++++++++++------ lib/core/abstract_connection.hpp | 9 ------ lib/core/{ => senseshift}/events.hpp | 4 +-- lib/core/{ => senseshift}/logging.hpp | 4 +++ lib/core/{ => senseshift}/utility.hpp | 6 ++-- lib/freertos/task.hpp | 2 +- lib/haptics/haptic_body.cpp | 2 +- lib/haptics/haptic_body.hpp | 2 +- lib/haptics/haptic_plane.cpp | 4 +-- lib/haptics/haptic_plane.hpp | 7 ++--- lib/opengloves/og_alpha_encoding.hpp | 5 ++-- lib/opengloves_task/opengloves_task.hpp | 2 +- .../senseshift/arduino/output/pca9685.hpp | 4 +-- lib/sensor/sensor.hpp | 2 +- test/test_core_utility/main.cpp | 4 +-- 27 files changed, 100 insertions(+), 84 deletions(-) delete mode 100644 lib/core/abstract_connection.hpp rename lib/core/{ => senseshift}/events.hpp (92%) rename lib/core/{ => senseshift}/logging.hpp (99%) rename lib/core/{ => senseshift}/utility.hpp (94%) diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 6ff9d7c4..8f663e62 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -4,14 +4,13 @@ #include <Arduino.h> #include <Wire.h> -#include <utility.hpp> - #include "senseshift.h" #include <senseshift/arduino/output/pwm.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> +#include <senseshift/utility.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true #include <battery/adc_naive.hpp> diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index b1b78eb1..6fadafdc 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -3,13 +3,13 @@ #include <og_serial_communication.hpp> #include <opengloves_task.hpp> #include <senseshift/arduino/output/servo.hpp> +#include <senseshift/utility.hpp> #include <sensor.hpp> #include <sensor/analog.hpp> #include <sensor/digital.hpp> #include <sensor/joystick.hpp> #include <sensor/og_finger.hpp> #include <sensor/og_gesture.hpp> -#include <utility.hpp> #pragma region Communication diff --git a/firmware/senseshift.cpp b/firmware/senseshift.cpp index 2605ce3e..3ba2b1f7 100644 --- a/firmware/senseshift.cpp +++ b/firmware/senseshift.cpp @@ -6,7 +6,7 @@ #include <Arduino.h> #endif -#include <logging.hpp> +#include <senseshift/logging.hpp> namespace SenseShift { SenseShift::SenseShift() @@ -14,7 +14,7 @@ namespace SenseShift { this->pHapticBody = new Body::Haptics::HapticBody(); } - void SenseShift::postEvent(const OH::IEvent* event) + void SenseShift::postEvent(const IEvent* event) { log_i("Event dispatched at %u: %s (%p)", millis(), event->eventName.c_str(), event); @@ -25,7 +25,7 @@ namespace SenseShift { delete event; } - void SenseShift::addEventListener(const OH::IEventListener* listener) + void SenseShift::addEventListener(const IEventListener* listener) { this->eventListeners.push_back(listener); } diff --git a/include/senseshift.h b/include/senseshift.h index f973af46..f2c94937 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -2,9 +2,8 @@ #include "config/all.h" -#include <abstract_connection.hpp> -#include <events.hpp> #include <haptic_body.hpp> +#include <senseshift/events.hpp> #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true #include <abstract_battery.hpp> @@ -13,9 +12,9 @@ #include <vector> namespace SenseShift { - class SenseShift final : public OH::IEventDispatcher { + class SenseShift final : public IEventDispatcher { private: - std::vector<const OH::IEventListener*> eventListeners{}; + std::vector<const IEventListener*> eventListeners{}; Body::Haptics::HapticBody* pHapticBody; #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true @@ -30,7 +29,7 @@ namespace SenseShift { return this->pHapticBody; }; - void postEvent(const OH::IEvent* event) override; - void addEventListener(const OH::IEventListener* listener) override; + void postEvent(const IEvent* event) override; + void addEventListener(const IEventListener* listener) override; }; } // namespace SenseShift diff --git a/lib/actuators/senseshift/output/actuator.hpp b/lib/actuators/senseshift/output/actuator.hpp index 5f56db6b..3938c65f 100644 --- a/lib/actuators/senseshift/output/actuator.hpp +++ b/lib/actuators/senseshift/output/actuator.hpp @@ -2,7 +2,7 @@ #include <cstdint> -#include <logging.hpp> +#include <senseshift/logging.hpp> namespace SenseShift::Output { // Singular output point (e.g. vibration motor) diff --git a/lib/arduino/battery/adc_naive.cpp b/lib/arduino/battery/adc_naive.cpp index 6ee9487f..d9991715 100644 --- a/lib/arduino/battery/adc_naive.cpp +++ b/lib/arduino/battery/adc_naive.cpp @@ -1,7 +1,7 @@ #include "battery/adc_naive.hpp" #include <Arduino.h> -#include <utility.hpp> +#include <senseshift/utility.hpp> namespace OH { void ADCNaiveBattery::setup() @@ -11,6 +11,6 @@ namespace OH { BatteryState ADCNaiveBattery::getValue() { - return { .level = static_cast<uint8_t>(simpleMap<uint16_t>(analogRead(this->pin), 4095, 255)) }; + return { .level = static_cast<uint8_t>(::SenseShift::simpleMap<uint16_t>(analogRead(this->pin), 4095, 255)) }; } } // namespace OH diff --git a/lib/arduino/senseshift/arduino/output/pwm.hpp b/lib/arduino/senseshift/arduino/output/pwm.hpp index a8145565..50605e5b 100644 --- a/lib/arduino/senseshift/arduino/output/pwm.hpp +++ b/lib/arduino/senseshift/arduino/output/pwm.hpp @@ -1,7 +1,7 @@ #pragma once #include <senseshift/output/actuator.hpp> -#include <utility.hpp> +#include <senseshift/utility.hpp> #include <Arduino.h> @@ -28,10 +28,13 @@ namespace SenseShift::Arduino::Output { void writeOutput(std::uint16_t intensity) override { #if defined(ESP32) - ledcWrite(chan, OH::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, (1 << this->resolution) - 1)); + ledcWrite( + chan, + ::SenseShift::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, (1 << this->resolution) - 1) + ); #else // Arduino only supports 8-bit PWM - analogWrite(this->pin, OH::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, (1 << 8) - 1)); + analogWrite(this->pin, ::SenseShift::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, (1 << 8) - 1)); #endif } diff --git a/lib/arduino/senseshift/arduino/output/servo.hpp b/lib/arduino/senseshift/arduino/output/servo.hpp index 88fa6c85..027c0b05 100644 --- a/lib/arduino/senseshift/arduino/output/servo.hpp +++ b/lib/arduino/senseshift/arduino/output/servo.hpp @@ -1,7 +1,7 @@ #pragma once #include <senseshift/output/actuator.hpp> -#include <utility.hpp> +#include <senseshift/utility.hpp> #include <ESP32Servo.h> @@ -21,7 +21,9 @@ namespace SenseShift::Arduino::Output { void writeOutput(std::uint16_t intensity) override { - servo.writeMicroseconds(OH::accurateMap<std::uint16_t>(intensity, 0, MAX_INTENSITY, this->min, this->max)); + servo.writeMicroseconds( + ::SenseShift::accurateMap<std::uint16_t>(intensity, 0, MAX_INTENSITY, this->min, this->max) + ); }; private: diff --git a/lib/battery/abstract_battery.hpp b/lib/battery/abstract_battery.hpp index 94c6c71f..feb3cdb1 100644 --- a/lib/battery/abstract_battery.hpp +++ b/lib/battery/abstract_battery.hpp @@ -1,6 +1,6 @@ #pragma once -#include <events.hpp> +#include <senseshift/events.hpp> #include <sensor.hpp> #include <task.hpp> @@ -45,10 +45,10 @@ namespace OH { uint8_t level; }; - class BatteryLevelEvent : public IEvent { + class BatteryLevelEvent : public ::SenseShift::IEvent { public: const BatteryState state; - BatteryLevelEvent(const BatteryState state) : IEvent(OH_EVENT_BATTERY_LEVEL), state(state){}; + BatteryLevelEvent(const BatteryState state) : ::SenseShift::IEvent(OH_EVENT_BATTERY_LEVEL), state(state){}; }; struct BatteryConfig { @@ -65,11 +65,14 @@ namespace OH { friend class TaskedSensor<BatteryState>; private: - IEventDispatcher* eventDispatcher; + ::SenseShift::IEventDispatcher* eventDispatcher; public: BatterySensor( - IBatterySensor* sensor, IEventDispatcher* eventDispatcher, BatteryConfig config, TaskConfig taskConfig + IBatterySensor* sensor, + ::SenseShift::IEventDispatcher* eventDispatcher, + BatteryConfig config, + TaskConfig taskConfig ) : TaskedSensor<BatteryState>(sensor, taskConfig, config.sampleRate), eventDispatcher(eventDispatcher){}; diff --git a/lib/bhaptics/senseshift/bh/encoding.hpp b/lib/bhaptics/senseshift/bh/encoding.hpp index 83575f8c..e2500cd9 100644 --- a/lib/bhaptics/senseshift/bh/encoding.hpp +++ b/lib/bhaptics/senseshift/bh/encoding.hpp @@ -171,7 +171,7 @@ namespace SenseShift::BH { for (uint8_t i = 0; i < VEST_LAYOUT_SIZE; i++) { // take only meaningful values - if (!OH::contains(layoutGroups, VEST_LAYOUT_SIZE, i)) { + if (!::SenseShift::contains(layoutGroups, VEST_LAYOUT_SIZE, i)) { continue; } @@ -208,9 +208,11 @@ namespace SenseShift::BH { { switch (effect) { case Effect_t::Vibro: - return VibroEffectData_t( - OH::simpleMap<VibroEffectData_t::Intensity_t>(byte, maxValue, VibroEffectData_t::INTENSITY_MAX) - ); + return VibroEffectData_t(::SenseShift::simpleMap<VibroEffectData_t::Intensity_t>( + byte, + maxValue, + VibroEffectData_t::INTENSITY_MAX + )); default: throw std::runtime_error("Unknown effect"); } diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp index 68de48b5..7e54500e 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -1,9 +1,8 @@ #include "senseshift/bh/ble/connection.hpp" -#include <senseshift/bh/constants.hpp> - -#include <events.hpp> #include <haptic_body.hpp> +#include <senseshift/bh/constants.hpp> +#include <senseshift/events.hpp> #include <Arduino.h> @@ -30,19 +29,19 @@ namespace SenseShift::BH::BLE { class BHServerCallbacks final : public BLEServerCallbacks { private: - OH::IEventDispatcher* dispatcher; + ::SenseShift::IEventDispatcher* dispatcher; public: - BHServerCallbacks(OH::IEventDispatcher* eventDispatcher) : dispatcher(eventDispatcher) {} + BHServerCallbacks(::SenseShift::IEventDispatcher* eventDispatcher) : dispatcher(eventDispatcher) {} void onConnect(BLEServer* pServer) { - this->dispatcher->postEvent(new OH::IEvent(OH_EVENT_CONNECTED)); + this->dispatcher->postEvent(new ::SenseShift::IEvent(OH_EVENT_CONNECTED)); } void onDisconnect(BLEServer* pServer) { - this->dispatcher->postEvent(new OH::IEvent(OH_EVENT_DISCONNECTED)); + this->dispatcher->postEvent(new ::SenseShift::IEvent(OH_EVENT_DISCONNECTED)); pServer->startAdvertising(); } }; diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp index 485e0212..90247d74 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -1,10 +1,9 @@ #pragma once -#include <abstract_connection.hpp> -#include <utility.hpp> - #include <senseshift/bh/ble/constants.hpp> #include <senseshift/bh/constants.hpp> +#include <senseshift/events.hpp> +#include <senseshift/utility.hpp> #include <Arduino.h> #include <esp_wifi.h> @@ -37,12 +36,12 @@ namespace SenseShift::BH::BLE { }; static ConnectionCallbacks defaultCallback; - class Connection final : public OH::AbstractConnection, public OH::IEventListener { + class Connection final : public ::SenseShift::IEventListener { public: typedef std::function<void(std::string&)> MotorHandler_t; Connection( - const ConnectionConfig_t& config, MotorHandler_t motorHandler, OH::IEventDispatcher* eventDispatcher + const ConnectionConfig_t& config, MotorHandler_t motorHandler, ::SenseShift::IEventDispatcher* eventDispatcher ) : config(config), motorHandler(motorHandler), eventDispatcher(eventDispatcher) { @@ -50,12 +49,15 @@ namespace SenseShift::BH::BLE { }; void begin(void); - void handleEvent(const OH::IEvent* event) const override + void handleEvent(const ::SenseShift::IEvent* event) const override { #if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true if (event->eventName == OH_EVENT_BATTERY_LEVEL) { - uint16_t level = - OH::simpleMap<uint8_t>(static_cast<const OH::BatteryLevelEvent*>(event)->state.level, 255, 100); + uint16_t level = ::SenseShift::simpleMap<uint8_t>( + static_cast<const OH::BatteryLevelEvent*>(event)->state.level, + 255, + 100 + ); this->batteryChar->setValue(level); this->batteryChar->notify(); @@ -77,7 +79,7 @@ namespace SenseShift::BH::BLE { private: const ConnectionConfig_t& config; MotorHandler_t motorHandler; - OH::IEventDispatcher* eventDispatcher; + ::SenseShift::IEventDispatcher* eventDispatcher; BLEServer* bleServer = nullptr; BLEService* motorService = nullptr; diff --git a/lib/calibration/calibration.hpp b/lib/calibration/calibration.hpp index 9654a1ce..fa5faa86 100644 --- a/lib/calibration/calibration.hpp +++ b/lib/calibration/calibration.hpp @@ -5,7 +5,7 @@ #pragma once -#include <utility.hpp> +#include <senseshift/utility.hpp> namespace OH { struct ICalibrated { @@ -76,7 +76,7 @@ namespace OH { } // Map the input range to the output range. - _Tp output = accurateMap<_Tp>(input, value_min, value_max, output_min, output_max); + _Tp output = ::SenseShift::accurateMap<_Tp>(input, value_min, value_max, output_min, output_max); // Lock the range to the output. return std::clamp(output, output_min, output_max); @@ -105,9 +105,9 @@ namespace OH { { // Update the min and the max. if (input < range_min) - range_min = accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); + range_min = ::SenseShift::accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); if (input > range_max) - range_max = accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); + range_max = ::SenseShift::accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); } _Tp calibrate(_Tp input) const @@ -116,13 +116,19 @@ namespace OH { _Tp center = (range_min + range_max) / 2.0f; // Map the input to the sensor range of motion. - int output = accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); + int output = ::SenseShift::accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); // Find the deviation from the center and clamp it to the maximum that the driver supports. output = std::clamp<int>(output - center, -driver_max_deviation, driver_max_deviation); // Finally map the deviation from the center back to the output range. - return (_Tp) accurateMap<int>(output, -driver_max_deviation, driver_max_deviation, output_min, output_max); + return (_Tp)::SenseShift::accurateMap<int>( + output, + -driver_max_deviation, + driver_max_deviation, + output_min, + output_max + ); } private: @@ -142,13 +148,19 @@ namespace OH { _Tp center = sensor_max / 2.0f; // Map the input to the sensor range of motion. - int output = accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); + int output = ::SenseShift::accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); // Find the deviation from the center and clamp it to the maximum that the driver supports. output = std::clamp<int>(output - center, -driver_max_deviation, driver_max_deviation); // Finally map the deviation from the center back to the output range. - return (_Tp) accurateMap<int>(output, -driver_max_deviation, driver_max_deviation, output_min, output_max); + return (_Tp)::SenseShift::accurateMap<int>( + output, + -driver_max_deviation, + driver_max_deviation, + output_min, + output_max + ); } }; } // namespace OH diff --git a/lib/core/abstract_connection.hpp b/lib/core/abstract_connection.hpp deleted file mode 100644 index 07a0523e..00000000 --- a/lib/core/abstract_connection.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "events.hpp" -namespace OH { - class AbstractConnection { - public: - virtual void begin(void){}; - }; -} // namespace OH diff --git a/lib/core/events.hpp b/lib/core/senseshift/events.hpp similarity index 92% rename from lib/core/events.hpp rename to lib/core/senseshift/events.hpp index 0740dc6d..bf09ec22 100644 --- a/lib/core/events.hpp +++ b/lib/core/senseshift/events.hpp @@ -6,7 +6,7 @@ #define OH_EVENT_CONNECTED "connected" #define OH_EVENT_DISCONNECTED "disconnected" -namespace OH { +namespace SenseShift { enum Event { }; @@ -27,4 +27,4 @@ namespace OH { virtual void postEvent(const IEvent* event) = 0; virtual void addEventListener(const IEventListener* handler) = 0; }; -} // namespace OH +} // namespace SenseShift diff --git a/lib/core/logging.hpp b/lib/core/senseshift/logging.hpp similarity index 99% rename from lib/core/logging.hpp rename to lib/core/senseshift/logging.hpp index 8af17aa8..d3cbc94b 100644 --- a/lib/core/logging.hpp +++ b/lib/core/senseshift/logging.hpp @@ -1,6 +1,7 @@ #pragma once #if defined(ESP32) + #include <esp32-hal-log.h> #elif defined(UNITY_INCLUDE_PRINT_FORMATTED) #define log_e(...) TEST_PRINTF(__VA_ARGS__) @@ -8,10 +9,13 @@ #define log_i(...) TEST_PRINTF(__VA_ARGS__) #define log_d(...) TEST_PRINTF(__VA_ARGS__) #define log_t(...) TEST_PRINTF(__VA_ARGS__) + #else + #define log_e(...) #define log_w(...) #define log_i(...) #define log_d(...) #define log_t(...) + #endif diff --git a/lib/core/utility.hpp b/lib/core/senseshift/utility.hpp similarity index 94% rename from lib/core/utility.hpp rename to lib/core/senseshift/utility.hpp index 3d40497e..227748f4 100644 --- a/lib/core/utility.hpp +++ b/lib/core/senseshift/utility.hpp @@ -2,9 +2,9 @@ #include <algorithm> #include <iterator> -#include <logging.hpp> +#include <senseshift/logging.hpp> -namespace OH { +namespace SenseShift { /** * Checks if a container contains a value. * @@ -48,4 +48,4 @@ namespace OH { { return x * out_max / in_max; } -} // namespace OH +} // namespace SenseShift diff --git a/lib/freertos/task.hpp b/lib/freertos/task.hpp index e31fb0d0..6a40f33a 100644 --- a/lib/freertos/task.hpp +++ b/lib/freertos/task.hpp @@ -1,6 +1,6 @@ #pragma once -#include "logging.hpp" +#include <senseshift/logging.hpp> extern "C" void delay(uint32_t ms); diff --git a/lib/haptics/haptic_body.cpp b/lib/haptics/haptic_body.cpp index fd4cf2cb..ddde0702 100644 --- a/lib/haptics/haptic_body.cpp +++ b/lib/haptics/haptic_body.cpp @@ -1,6 +1,6 @@ #include "haptic_body.hpp" -#include <logging.hpp> +#include <senseshift/logging.hpp> namespace SenseShift::Body::Haptics { void HapticBody::setup() diff --git a/lib/haptics/haptic_body.hpp b/lib/haptics/haptic_body.hpp index 351e31eb..ff05a1e4 100644 --- a/lib/haptics/haptic_body.hpp +++ b/lib/haptics/haptic_body.hpp @@ -3,7 +3,7 @@ #include "haptic_plane.hpp" #include "haptics_interface.hpp" -#include <utility.hpp> +#include <senseshift/utility.hpp> #include <map> diff --git a/lib/haptics/haptic_plane.cpp b/lib/haptics/haptic_plane.cpp index d22c6f55..47af5ae6 100644 --- a/lib/haptics/haptic_plane.cpp +++ b/lib/haptics/haptic_plane.cpp @@ -1,8 +1,8 @@ #include "haptic_plane.hpp" #include <algorithm> -#include <logging.hpp> -#include <math.h> +#include <cmath> +#include <senseshift/logging.hpp> #include "haptic_plane.hpp" diff --git a/lib/haptics/haptic_plane.hpp b/lib/haptics/haptic_plane.hpp index 97aac1c9..88227f4f 100644 --- a/lib/haptics/haptic_plane.hpp +++ b/lib/haptics/haptic_plane.hpp @@ -3,8 +3,7 @@ #include "haptics_interface.hpp" #include <senseshift/output/actuator.hpp> - -#include <utility.hpp> +#include <senseshift/utility.hpp> #include <list> #include <map> @@ -120,8 +119,8 @@ namespace SenseShift::Body::Haptics { { using Point_t = OH::Point2<_Tp>; return Point_t( - OH::accurateMap<_Tp>(x + 1, 0, x_max + 2, Point_t::MIN, Point_t::MAX), - OH::accurateMap<_Tp>(y + 1, 0, y_max + 2, Point_t::MIN, Point_t::MAX) + ::SenseShift::accurateMap<_Tp>(x + 1, 0, x_max + 2, Point_t::MIN, Point_t::MAX), + ::SenseShift::accurateMap<_Tp>(y + 1, 0, y_max + 2, Point_t::MIN, Point_t::MAX) ); } }; diff --git a/lib/opengloves/og_alpha_encoding.hpp b/lib/opengloves/og_alpha_encoding.hpp index acc3744f..8ca21f07 100644 --- a/lib/opengloves/og_alpha_encoding.hpp +++ b/lib/opengloves/og_alpha_encoding.hpp @@ -1,18 +1,19 @@ #pragma once +#include <cstdint> #include <functional> #include <map> -#include <stdint.h> #include <string> #include <vector> -#include <logging.hpp> #include <og_protocol.hpp> +#include <senseshift/logging.hpp> namespace OpenGloves { class AlphaEncodingService { public: inline static const std::string valueSymbols = "0123456789"; + // TODO: use Frozen library to save memory inline static const std::map<std::string, Command> commandMap = { // clang-format off { "A", Command::ThumbCurl }, diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index d52f5cd4..89eb9805 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -8,6 +8,7 @@ #include <og_alpha_encoding.hpp> #include <og_ffb.hpp> #include <og_serial_communication.hpp> +#include <senseshift/utility.hpp> #include <sensor.hpp> #include <sensor/analog.hpp> #include <sensor/digital.hpp> @@ -15,7 +16,6 @@ #include <sensor/og_finger.hpp> #include <sensor/og_gesture.hpp> #include <task.hpp> -#include <utility.hpp> namespace OpenGloves { struct OpenGlovesTrackingTaskConfig { diff --git a/lib/pca9685/senseshift/arduino/output/pca9685.hpp b/lib/pca9685/senseshift/arduino/output/pca9685.hpp index a6529521..aa8b4ce2 100644 --- a/lib/pca9685/senseshift/arduino/output/pca9685.hpp +++ b/lib/pca9685/senseshift/arduino/output/pca9685.hpp @@ -1,7 +1,7 @@ #pragma once #include <senseshift/output/actuator.hpp> -#include <utility.hpp> +#include <senseshift/utility.hpp> #include <Adafruit_PWMServoDriver.h> #include <Arduino.h> @@ -16,7 +16,7 @@ namespace SenseShift::Arduino::Output { void writeOutput(std::uint16_t intensity) override { - this->driver->setPin(this->num, OH::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, 4095)); + this->driver->setPin(this->num, ::SenseShift::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, 4095)); } private: diff --git a/lib/sensor/sensor.hpp b/lib/sensor/sensor.hpp index 714a0a09..8f95ef5a 100644 --- a/lib/sensor/sensor.hpp +++ b/lib/sensor/sensor.hpp @@ -3,7 +3,7 @@ #include <type_traits> #include <calibration.hpp> -#include <logging.hpp> +#include <senseshift/logging.hpp> #if defined(__AVR__) #define ANALOG_MAX 1023 diff --git a/test/test_core_utility/main.cpp b/test/test_core_utility/main.cpp index e4539512..a468a49a 100644 --- a/test/test_core_utility/main.cpp +++ b/test/test_core_utility/main.cpp @@ -1,7 +1,7 @@ +#include <senseshift/utility.hpp> #include <unity.h> -#include <utility.hpp> -using namespace OH; +using namespace SenseShift; void test_contains_container(void) { From 169f50e0c6430ea988c572237dcfe815da3fa049 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 21 Aug 2023 23:49:54 +0400 Subject: [PATCH 10/82] refactor(Input): move to `SenseShift` namespace and directory --- .../mode_configs/opengloves/opengloves.cpp | 49 ++++++++++++------- .../arduino/input}/sensor/analog.hpp | 8 +-- .../arduino/input}/sensor/digital.hpp | 9 ++-- lib/battery/abstract_battery.cpp | 1 - lib/battery/abstract_battery.hpp | 10 ++-- lib/opengloves/sensor/og_finger.hpp | 26 +++++----- lib/opengloves/sensor/og_gesture.hpp | 2 +- lib/opengloves/sensor/og_sensor.hpp | 10 ++-- lib/opengloves_task/opengloves_task.hpp | 8 +-- lib/sensor/{ => senseshift/input}/sensor.hpp | 11 +++-- .../senseshift/input}/sensor/joystick.hpp | 8 ++- test/test_opengloves/main.cpp | 6 +-- test/test_opengloves_finger/main.cpp | 10 ++-- test/test_sensor/main.cpp | 3 +- 14 files changed, 90 insertions(+), 71 deletions(-) rename lib/arduino/{ => senseshift/arduino/input}/sensor/analog.hpp (73%) rename lib/arduino/{ => senseshift/arduino/input}/sensor/digital.hpp (76%) delete mode 100644 lib/battery/abstract_battery.cpp rename lib/sensor/{ => senseshift/input}/sensor.hpp (90%) rename lib/{arduino => sensor/senseshift/input}/sensor/joystick.hpp (90%) diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 6fadafdc..2ac3d7d0 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -2,12 +2,12 @@ #include <og_constants.hpp> #include <og_serial_communication.hpp> #include <opengloves_task.hpp> +#include <senseshift/arduino/input/sensor/analog.hpp> +#include <senseshift/arduino/input/sensor/digital.hpp> #include <senseshift/arduino/output/servo.hpp> +#include <senseshift/input/sensor.hpp> +#include <senseshift/input/sensor/joystick.hpp> #include <senseshift/utility.hpp> -#include <sensor.hpp> -#include <sensor/analog.hpp> -#include <sensor/digital.hpp> -#include <sensor/joystick.hpp> #include <sensor/og_finger.hpp> #include <sensor/og_gesture.hpp> @@ -53,10 +53,13 @@ #define FINGER_MIDDLE_ENABLED (defined(PIN_FINGER_MIDDLE) && (PIN_FINGER_MIDDLE != -1)) #define FINGER_RING_ENABLED (defined(PIN_FINGER_RING) && (PIN_FINGER_RING != -1)) #define FINGER_PINKY_ENABLED (defined(PIN_FINGER_PINKY) && (PIN_FINGER_PINKY != -1)) -#define FINGER_CLASS(type, curl_pin, curl_invert, curl_calib) \ - FingerSensor( \ - new OH::CalibratedSensor<uint16_t>(new OH::AnalogSensor<curl_invert>(curl_pin), new curl_calib()), \ - type \ +#define FINGER_CLASS(type, curl_pin, curl_invert, curl_calib) \ + FingerSensor( \ + new ::SenseShift::Input::CalibratedSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ + new curl_calib() \ + ), \ + type \ ) #define FINGER_THUMB_SPLAY (FINGER_THUMB_ENABLED && defined(PIN_FINGER_THUMB_SPLAY) && (PIN_FINGER_THUMB_SPLAY != -1)) #define FINGER_INDEX_SPLAY (FINGER_INDEX_ENABLED && defined(PIN_FINGER_INDEX_SPLAY) && (PIN_FINGER_INDEX_SPLAY != -1)) @@ -64,11 +67,17 @@ (FINGER_MIDDLE_ENABLED && defined(PIN_FINGER_MIDDLE_SPLAY) && (PIN_FINGER_MIDDLE_SPLAY != -1)) #define FINGER_RING_SPLAY (FINGER_RING_ENABLED && defined(PIN_FINGER_RING_SPLAY) && (PIN_FINGER_RING_SPLAY != -1)) #define FINGER_PINKY_SPLAY (FINGER_PINKY_ENABLED && defined(PIN_FINGER_PINKY_SPLAY) && (PIN_FINGER_PINKY_SPLAY != -1)) -#define FINGER_SPLAY_CLASS(type, curl_pin, curl_invert, curl_calib, splay_pin, splay_invert, splay_calib) \ - FingerSensor( \ - new OH::CalibratedSensor<uint16_t>(new OH::AnalogSensor<curl_invert>(curl_pin), new curl_calib()), \ - new OH::CalibratedSensor<uint16_t>(new OH::AnalogSensor<splay_invert>(splay_pin), new splay_calib()), \ - type \ +#define FINGER_SPLAY_CLASS(type, curl_pin, curl_invert, curl_calib, splay_pin, splay_invert, splay_calib) \ + FingerSensor( \ + new ::SenseShift::Input::CalibratedSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ + new curl_calib() \ + ), \ + new ::SenseShift::Input::CalibratedSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<splay_invert>(splay_pin), \ + new splay_calib() \ + ), \ + type \ ) #pragma endregion @@ -78,10 +87,13 @@ #define JOYSTICK_ENABLED \ (defined(PIN_JOYSTICK_X) && defined(PIN_JOYSTICK_Y) && (PIN_JOYSTICK_X != -1) && (PIN_JOYSTICK_Y != -1)) -#define JOYSTICK_CLASS(type, pin, invert, deadzone) \ - StringEncodedMemoizedSensor<uint16_t>( \ - new OH::JoystickAxisSensor<uint16_t>(new OH::AnalogSensor<invert>(pin), deadzone), \ - type \ +#define JOYSTICK_CLASS(type, pin, invert, deadzone) \ + StringEncodedMemoizedSensor<uint16_t>( \ + new ::SenseShift::Input::JoystickAxisSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<invert>(pin), \ + deadzone \ + ), \ + type \ ) #pragma endregion @@ -97,7 +109,8 @@ #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)) -#define BUTTON_CLASS(type, pin, invert) StringEncodedMemoizedSensor<bool>(new OH::DigitalSensor<invert>(pin), type) +#define BUTTON_CLASS(type, pin, invert) \ + StringEncodedMemoizedSensor<bool>(new ::SenseShift::Arduino::Input::DigitalSensor<invert>(pin), type) #pragma endregion diff --git a/lib/arduino/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp similarity index 73% rename from lib/arduino/sensor/analog.hpp rename to lib/arduino/senseshift/arduino/input/sensor/analog.hpp index 9f8a33a7..d55fc37e 100644 --- a/lib/arduino/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -1,12 +1,12 @@ #pragma once -#include <sensor.hpp> +#include <senseshift/input/sensor.hpp> #include <Arduino.h> -namespace OH { +namespace SenseShift::Arduino::Input { template<bool invert = false> - class AnalogSensor : public ISensor<uint16_t> { + class AnalogSensor : public ::SenseShift::Input::ISensor<uint16_t> { private: uint8_t pin; @@ -32,4 +32,4 @@ namespace OH { { return ANALOG_MAX - analogRead(this->pin); } -} // namespace OH +} // namespace SenseShift::Arduino::Input diff --git a/lib/arduino/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp similarity index 76% rename from lib/arduino/sensor/digital.hpp rename to lib/arduino/senseshift/arduino/input/sensor/digital.hpp index 90b517c1..5a9c2f63 100644 --- a/lib/arduino/sensor/digital.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -1,10 +1,11 @@ #pragma once +#include <senseshift/input/sensor.hpp> + #include <Arduino.h> -#include <sensor.hpp> -namespace OH { - typedef ISensor<bool> IDigitalSensor; +namespace SenseShift::Arduino::Input { + typedef ::SenseShift::Input::ISensor<bool> IDigitalSensor; template<bool invert = false> class DigitalSensor : public IDigitalSensor { @@ -33,4 +34,4 @@ namespace OH { { return digitalRead(this->pin) == HIGH; } -} // namespace OH +} // namespace SenseShift::Arduino::Input diff --git a/lib/battery/abstract_battery.cpp b/lib/battery/abstract_battery.cpp deleted file mode 100644 index 326b3507..00000000 --- a/lib/battery/abstract_battery.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "abstract_battery.hpp" diff --git a/lib/battery/abstract_battery.hpp b/lib/battery/abstract_battery.hpp index feb3cdb1..0e64c2ad 100644 --- a/lib/battery/abstract_battery.hpp +++ b/lib/battery/abstract_battery.hpp @@ -1,7 +1,7 @@ #pragma once #include <senseshift/events.hpp> -#include <sensor.hpp> +#include <senseshift/input/sensor.hpp> #include <task.hpp> #include <stdint.h> @@ -15,7 +15,7 @@ namespace OH { * Tasked sensor decorator */ template<typename _Tp> - class TaskedSensor : public Task<TaskedSensor<_Tp>>, public MemoizedSensor<_Tp> { + class TaskedSensor : public Task<TaskedSensor<_Tp>>, public ::SenseShift::Input::MemoizedSensor<_Tp> { friend class Task<TaskedSensor<_Tp>>; private: @@ -31,8 +31,8 @@ namespace OH { uint32_t rate; public: - TaskedSensor(ISensor<_Tp>* sensor, TaskConfig taskConfig, uint32_t rate) : - MemoizedSensor<_Tp>(sensor), Task<TaskedSensor<_Tp>>(taskConfig), rate(rate){}; + TaskedSensor(::SenseShift::Input::ISensor<_Tp>* sensor, TaskConfig taskConfig, uint32_t rate) : + ::SenseShift::Input::MemoizedSensor<_Tp>(sensor), Task<TaskedSensor<_Tp>>(taskConfig), rate(rate){}; void begin() override { @@ -58,7 +58,7 @@ namespace OH { /** * Abstract battery sensor */ - typedef ISensor<BatteryState> IBatterySensor; + typedef ::SenseShift::Input::ISensor<BatteryState> IBatterySensor; class BatterySensor : public TaskedSensor<BatteryState> { friend class Task<TaskedSensor<BatteryState>>; diff --git a/lib/opengloves/sensor/og_finger.hpp b/lib/opengloves/sensor/og_finger.hpp index 1b335718..1b5de1a9 100644 --- a/lib/opengloves/sensor/og_finger.hpp +++ b/lib/opengloves/sensor/og_finger.hpp @@ -6,17 +6,19 @@ namespace OpenGloves { struct FingerSensors { - std::vector<OH::CalibratedSensor<uint16_t>*> curl = std::vector<OH::CalibratedSensor<uint16_t>*>(); - std::optional<OH::CalibratedSensor<uint16_t>*> splay = std::nullopt; + std::vector<SenseShift::Input::CalibratedSensor<uint16_t>*> curl = + std::vector<SenseShift::Input::CalibratedSensor<uint16_t>*>(); + std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay = std::nullopt; FingerSensors( - std::vector<OH::CalibratedSensor<uint16_t>*> curl, - std::optional<OH::CalibratedSensor<uint16_t>*> splay = std::nullopt + std::vector<SenseShift::Input::CalibratedSensor<uint16_t>*> curl, + std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay = std::nullopt ) : curl(curl), splay(splay){}; FingerSensors( - OH::CalibratedSensor<uint16_t>* curl1, std::optional<OH::CalibratedSensor<uint16_t>*> splay = std::nullopt + SenseShift::Input::CalibratedSensor<uint16_t>* curl1, + std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay = std::nullopt ) : curl({ curl1 }), splay(splay){}; }; @@ -29,14 +31,15 @@ namespace OpenGloves { virtual uint16_t getCurl() = 0; }; - typedef OH::ISensor<FingerValue> IFingerSensor; + typedef SenseShift::Input::ISensor<FingerValue> IFingerSensor; class SimpleFingerSensor : public IFingerSensor, public ICurl { public: SimpleFingerSensor(FingerSensors sensors) : sensors(sensors){}; SimpleFingerSensor( - OH::CalibratedSensor<uint16_t>* curl1, std::optional<OH::CalibratedSensor<uint16_t>*> splay = std::nullopt + SenseShift::Input::CalibratedSensor<uint16_t>* curl1, + std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay = std::nullopt ) : sensors(curl1, splay){}; @@ -82,7 +85,8 @@ namespace OpenGloves { CalibratedFingerSensor(FingerSensors sensors) : SimpleFingerSensor(sensors){}; CalibratedFingerSensor( - OH::CalibratedSensor<uint16_t>* curl1, std::optional<OH::CalibratedSensor<uint16_t>*> splay = std::nullopt + SenseShift::Input::CalibratedSensor<uint16_t>* curl1, + std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay = std::nullopt ) : SimpleFingerSensor(curl1, splay){}; @@ -123,13 +127,13 @@ namespace OpenGloves { StringEncodedMemoizedSensor<FingerValue>(sensor, type){}; FingerSensor( - OH::CalibratedSensor<uint16_t>* curl1, - std::optional<OH::CalibratedSensor<uint16_t>*> splay, + SenseShift::Input::CalibratedSensor<uint16_t>* curl1, + std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay, IEncodedInput::Type type ) : StringEncodedMemoizedSensor<FingerValue>(new CalibratedFingerSensor(curl1, splay), type){}; - FingerSensor(OH::CalibratedSensor<uint16_t>* curl1, IEncodedInput::Type type) : + FingerSensor(SenseShift::Input::CalibratedSensor<uint16_t>* curl1, IEncodedInput::Type type) : StringEncodedMemoizedSensor<FingerValue>(new CalibratedFingerSensor(curl1, std::nullopt), type){}; void resetCalibration() override diff --git a/lib/opengloves/sensor/og_gesture.hpp b/lib/opengloves/sensor/og_gesture.hpp index 9a35aa8d..3c7e0944 100644 --- a/lib/opengloves/sensor/og_gesture.hpp +++ b/lib/opengloves/sensor/og_gesture.hpp @@ -3,7 +3,7 @@ #include <sensor/og_finger.hpp> namespace OpenGloves { - class Gesture : public OH::ISensor<bool> {}; + class Gesture : public SenseShift::Input::ISensor<bool> {}; class GrabGesture : public Gesture { private: diff --git a/lib/opengloves/sensor/og_sensor.hpp b/lib/opengloves/sensor/og_sensor.hpp index 1ab097c9..60e099d7 100644 --- a/lib/opengloves/sensor/og_sensor.hpp +++ b/lib/opengloves/sensor/og_sensor.hpp @@ -2,7 +2,7 @@ #include <calibration.hpp> #include <og_protocol.hpp> -#include <sensor.hpp> +#include <senseshift/input/sensor.hpp> #include <optional> #include <vector> @@ -27,10 +27,12 @@ namespace OpenGloves { }; template<typename _Tp> - class StringEncodedMemoizedSensor : public IStringEncodedMemoizedSensor, public OH::MemoizedSensor<_Tp> { + class StringEncodedMemoizedSensor : + public IStringEncodedMemoizedSensor, + public SenseShift::Input::MemoizedSensor<_Tp> { public: - StringEncodedMemoizedSensor(OH::ISensor<_Tp>* sensor, IEncodedInput::Type type) : - IStringEncodedMemoizedSensor(type), OH::MemoizedSensor<_Tp>(sensor){}; + StringEncodedMemoizedSensor(SenseShift::Input::ISensor<_Tp>* sensor, IEncodedInput::Type type) : + IStringEncodedMemoizedSensor(type), SenseShift::Input::MemoizedSensor<_Tp>(sensor){}; void setup() override { diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index 89eb9805..a5dd8b3b 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -8,11 +8,11 @@ #include <og_alpha_encoding.hpp> #include <og_ffb.hpp> #include <og_serial_communication.hpp> +#include <senseshift/arduino/input/sensor/analog.hpp> +#include <senseshift/arduino/input/sensor/digital.hpp> +#include <senseshift/input/sensor.hpp> +#include <senseshift/input/sensor/joystick.hpp> #include <senseshift/utility.hpp> -#include <sensor.hpp> -#include <sensor/analog.hpp> -#include <sensor/digital.hpp> -#include <sensor/joystick.hpp> #include <sensor/og_finger.hpp> #include <sensor/og_gesture.hpp> #include <task.hpp> diff --git a/lib/sensor/sensor.hpp b/lib/sensor/senseshift/input/sensor.hpp similarity index 90% rename from lib/sensor/sensor.hpp rename to lib/sensor/senseshift/input/sensor.hpp index 8f95ef5a..1b08ec60 100644 --- a/lib/sensor/sensor.hpp +++ b/lib/sensor/senseshift/input/sensor.hpp @@ -16,7 +16,7 @@ // #define ANALOG_MAX 4095 #endif -namespace OH { +namespace SenseShift::Input { /** * Abstract hardware sensor (e.g. potentiometer, flex sensor, etc.) * @tparam _Tp Type of the sensor value @@ -90,10 +90,10 @@ namespace OH { * @tparam _Tp Type of the sensor value */ template<typename _Tp> - class CalibratedSensor : public ISensor<_Tp>, public Calibrated { + class CalibratedSensor : public ISensor<_Tp>, public OH::Calibrated { protected: ISensor<_Tp>* sensor; - ICalibrator<_Tp>* calibrator; + OH::ICalibrator<_Tp>* calibrator; _Tp getCalibratedValue() { @@ -111,7 +111,8 @@ namespace OH { * @param sensor Sensor to be decorated * @param calibrator ICalibrator algorithm to be used */ - CalibratedSensor(ISensor<_Tp>* sensor, ICalibrator<_Tp>* calibrator) : sensor(sensor), calibrator(calibrator){}; + CalibratedSensor(ISensor<_Tp>* sensor, OH::ICalibrator<_Tp>* calibrator) : + sensor(sensor), calibrator(calibrator){}; void setup() override { @@ -128,4 +129,4 @@ namespace OH { this->calibrator->reset(); }; }; -} // namespace OH +} // namespace SenseShift::Input diff --git a/lib/arduino/sensor/joystick.hpp b/lib/sensor/senseshift/input/sensor/joystick.hpp similarity index 90% rename from lib/arduino/sensor/joystick.hpp rename to lib/sensor/senseshift/input/sensor/joystick.hpp index 858f36cd..307d49ea 100644 --- a/lib/arduino/sensor/joystick.hpp +++ b/lib/sensor/senseshift/input/sensor/joystick.hpp @@ -1,10 +1,8 @@ #pragma once -#include <sensor.hpp> +#include "senseshift/input/sensor.hpp" -#include <Arduino.h> - -namespace OH { +namespace SenseShift::Input { /** * Joystick axis sensor decorator */ @@ -38,4 +36,4 @@ namespace OH { return value; } }; -}; // namespace OH +}; // namespace SenseShift::Input diff --git a/test/test_opengloves/main.cpp b/test/test_opengloves/main.cpp index 704515b8..646a9785 100644 --- a/test/test_opengloves/main.cpp +++ b/test/test_opengloves/main.cpp @@ -3,7 +3,7 @@ using namespace OpenGloves; -class TestAnalogSensor : public OH::ISensor<uint16_t> { +class TestAnalogSensor : public SenseShift::Input::ISensor<uint16_t> { private: uint16_t count = 0; @@ -21,7 +21,7 @@ class TestAnalogSensor : public OH::ISensor<uint16_t> { }; }; -class TestBinarySensor : public OH::ISensor<bool> { +class TestBinarySensor : public SenseShift::Input::ISensor<bool> { public: bool value = false; int setupCounter = 0; @@ -37,7 +37,7 @@ class TestBinarySensor : public OH::ISensor<bool> { }; }; -class TestFingerSensor : public OH::ISensor<FingerValue> { +class TestFingerSensor : public SenseShift::Input::ISensor<FingerValue> { public: FingerValue value; int setupCounter = 0; diff --git a/test/test_opengloves_finger/main.cpp b/test/test_opengloves_finger/main.cpp index 4dd5a74e..0a3a9978 100644 --- a/test/test_opengloves_finger/main.cpp +++ b/test/test_opengloves_finger/main.cpp @@ -3,7 +3,7 @@ using namespace OpenGloves; -class TestAnalogSensor : public OH::ISensor<uint16_t> { +class TestAnalogSensor : public SenseShift::Input::ISensor<uint16_t> { private: uint16_t count = 0; @@ -45,7 +45,7 @@ void test_simple_finger_sensor_curl(void) { auto* inner = new TestAnalogSensor(); auto* calibrator = new DummyCalibrator(); - auto* calibrated = new OH::CalibratedSensor<uint16_t>(inner, calibrator); + auto* calibrated = new SenseShift::Input::CalibratedSensor<uint16_t>(inner, calibrator); auto* sensor = new SimpleFingerSensor(calibrated); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); @@ -71,11 +71,11 @@ void test_simple_finger_sensor_curl_flex(void) { auto* inner_curl = new TestAnalogSensor(); auto* calibrator_curl = new DummyCalibrator(); - auto* calibrated_curl = new OH::CalibratedSensor<uint16_t>(inner_curl, calibrator_curl); + auto* calibrated_curl = new SenseShift::Input::CalibratedSensor<uint16_t>(inner_curl, calibrator_curl); auto* inner_flex = new TestAnalogSensor(); auto* calibrator_flex = new DummyCalibrator(); - auto* calibrated_flex = new OH::CalibratedSensor<uint16_t>(inner_flex, calibrator_flex); + auto* calibrated_flex = new SenseShift::Input::CalibratedSensor<uint16_t>(inner_flex, calibrator_flex); auto* sensor = new SimpleFingerSensor(calibrated_curl, calibrated_flex); @@ -111,7 +111,7 @@ void test_finger_sensor_curl(void) { auto* inner = new TestAnalogSensor(); auto* calibrator = new DummyCalibrator(); - auto* calibrated = new OH::CalibratedSensor<uint16_t>(inner, calibrator); + auto* calibrated = new SenseShift::Input::CalibratedSensor<uint16_t>(inner, calibrator); auto* sensor = new FingerSensor(calibrated, IEncodedInput::Type::INDEX); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); diff --git a/test/test_sensor/main.cpp b/test/test_sensor/main.cpp index d026d2a7..7309e65c 100644 --- a/test/test_sensor/main.cpp +++ b/test/test_sensor/main.cpp @@ -1,6 +1,7 @@ -#include <sensor.hpp> +#include <senseshift/input/sensor.hpp> #include <unity.h> +using namespace SenseShift::Input; using namespace OH; class TestAnalogSensor : public ISensor<int> { From b9c791ec12e7463f7a2c75d4364f806a7eb6c89e Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 22 Aug 2023 01:20:57 +0400 Subject: [PATCH 11/82] refactor(Battery): use `SenseShift` lib namespace and dir --- .github/scripts/get_firmware_name.sh | 2 +- .github/workflows/ci.yml | 8 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/release.yml | 2 +- firmware/mode_configs/bhaptics/tactal.cpp | 16 ++-- firmware/mode_configs/bhaptics/tactglove.cpp | 16 ++-- firmware/mode_configs/bhaptics/tactosy2.cpp | 16 ++-- firmware/mode_configs/bhaptics/tactosyf.cpp | 16 ++-- firmware/mode_configs/bhaptics/tactosyh.cpp | 16 ++-- .../mode_configs/bhaptics/tactsuit_x16.cpp | 16 ++-- .../bhaptics/tactsuit_x16_pca9685.cpp | 16 ++-- .../mode_configs/bhaptics/tactsuit_x40.cpp | 16 ++-- firmware/mode_configs/bhaptics/tactvisor.cpp | 16 ++-- include/config/battery.h | 16 ++-- include/senseshift.h | 10 +- lib/arduino/battery/adc_naive.cpp | 16 ---- lib/arduino/battery/adc_naive.hpp | 16 ---- lib/battery/senseshift/battery.hpp | 17 ++++ .../battery/sensor.hpp} | 92 ++++++++++--------- .../senseshift/bh/ble/connection.cpp | 4 - .../senseshift/bh/ble/connection.hpp | 23 ++--- lib/ina219/battery/ina219.cpp | 25 ----- lib/ina219/battery/ina219.hpp | 19 ---- .../senseshift/arduino/battery/ina219.hpp | 35 +++++++ lib/max17048/battery/max17048.cpp | 32 ------- lib/max17048/battery/max17048.hpp | 20 ---- .../senseshift/arduino/battery/max17048.hpp | 45 +++++++++ platformio.ini | 2 +- 28 files changed, 243 insertions(+), 287 deletions(-) delete mode 100644 lib/arduino/battery/adc_naive.cpp delete mode 100644 lib/arduino/battery/adc_naive.hpp create mode 100644 lib/battery/senseshift/battery.hpp rename lib/battery/{abstract_battery.hpp => senseshift/battery/sensor.hpp} (50%) delete mode 100644 lib/ina219/battery/ina219.cpp delete mode 100644 lib/ina219/battery/ina219.hpp create mode 100644 lib/ina219/senseshift/arduino/battery/ina219.hpp delete mode 100644 lib/max17048/battery/max17048.cpp delete mode 100644 lib/max17048/battery/max17048.hpp create mode 100644 lib/max17048/senseshift/arduino/battery/max17048.hpp diff --git a/.github/scripts/get_firmware_name.sh b/.github/scripts/get_firmware_name.sh index 199e38aa..cd7a2b6d 100755 --- a/.github/scripts/get_firmware_name.sh +++ b/.github/scripts/get_firmware_name.sh @@ -13,7 +13,7 @@ getBhapticsName() { target="$target+nimble" fi - if [[ $flags =~ BATTERY_ENABLED=true ]]; then + if [[ $flags =~ SENSESHIFT_BATTERY_ENABLED=true ]]; then echo "::debug::Battery is enabled, appending +battery to the target" target="$target+battery" fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa9c5153..fefeed9d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: - bhaptics_tactal - bhaptics_tactvisor - bhaptics_tactglove_right - battery_flag: [ BATTERY_ENABLED=true ] + battery_flag: [ SENSESHIFT_BATTERY_ENABLED=true ] serial_plotter_flag: [ SERIAL_PLOTTER=false ] nimble_flag: [ BLUETOOTH_USE_NIMBLE=false ] coverage: [ false ] @@ -42,19 +42,19 @@ jobs: - target: bhaptics_tactsuit_x40 os: ubuntu-latest coverage: true - battery_flag: BATTERY_ENABLED=true + battery_flag: SENSESHIFT_BATTERY_ENABLED=true serial_plotter_flag: SERIAL_PLOTTER=true nimble_flag: BLUETOOTH_USE_NIMBLE=true # - target: bhaptics_tactsuit_x40 # os: ubuntu-latest # coverage: true - # battery_flag: BATTERY_ENABLED=true + # battery_flag: SENSESHIFT_BATTERY_ENABLED=true # serial_plotter_flag: SERIAL_PLOTTER=true # nimble_flag: BLUETOOTH_USE_NIMBLE=false - target: bhaptics_tactsuit_x40 os: ubuntu-latest coverage: false - battery_flag: BATTERY_ENABLED=true + battery_flag: SENSESHIFT_BATTERY_ENABLED=true serial_plotter_flag: SERIAL_PLOTTER=false nimble_flag: BLUETOOTH_USE_NIMBLE=true diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7e624290..6f82bad4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -31,7 +31,7 @@ jobs: # Enabling all flags to test build for every feature battery_flag: - - BATTERY_ENABLED=true + - SENSESHIFT_BATTERY_ENABLED=true serial_plotter_flag: - SERIAL_PLOTTER=true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 65ceb54b..9b11b4a5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,7 +33,7 @@ jobs: - bhaptics_tactglove_left - bhaptics_tactglove_right battery_flag: - - BATTERY_ENABLED=true + - SENSESHIFT_BATTERY_ENABLED=true nimble_flag: - BLUETOOTH_USE_NIMBLE=true diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index ba2a271e..991fdce5 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -6,18 +6,18 @@ #include "senseshift.h" +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true -#include "battery/adc_naive.hpp" -#endif - using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; +using namespace SenseShift::Arduino::Input; +using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -53,12 +53,12 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true +#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* battery = new BatterySensor( - new ADCNaiveBattery(36), + new NaiveBatterySensor(new AnalogSensor(36)), &App, - { .sampleRate = BATTERY_SAMPLE_RATE }, - { "ADC Battery", 4096, BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); #endif diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 8f663e62..c7fd1924 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -6,19 +6,19 @@ #include "senseshift.h" +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> #include <senseshift/utility.hpp> -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true -#include <battery/adc_naive.hpp> -#endif - using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; +using namespace SenseShift::Arduino::Input; +using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -61,12 +61,12 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true +#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* battery = new BatterySensor( - new ADCNaiveBattery(36), + new NaiveBatterySensor(new AnalogSensor(36)), &App, - { .sampleRate = BATTERY_SAMPLE_RATE }, - { "ADC Battery", 4096, BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); #endif diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index 6a4af3a6..26937edb 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -6,18 +6,18 @@ #include "senseshift.h" +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true -#include <battery/adc_naive.hpp> -#endif - using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; +using namespace SenseShift::Arduino::Input; +using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -54,12 +54,12 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true +#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* battery = new BatterySensor( - new ADCNaiveBattery(36), + new NaiveBatterySensor(new AnalogSensor(36)), &App, - { .sampleRate = BATTERY_SAMPLE_RATE }, - { "ADC Battery", 4096, BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); #endif diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index 4595b904..33aea620 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -6,18 +6,18 @@ #include "senseshift.h" +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true -#include <battery/adc_naive.hpp> -#endif - using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; +using namespace SenseShift::Arduino::Input; +using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -55,12 +55,12 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true +#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* battery = new BatterySensor( - new ADCNaiveBattery(36), + new NaiveBatterySensor(new AnalogSensor(36)), &App, - { .sampleRate = BATTERY_SAMPLE_RATE }, - { "ADC Battery", 4096, BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); #endif diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index c2904352..068add9e 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -6,18 +6,18 @@ #include "senseshift.h" +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true -#include <battery/adc_naive.hpp> -#endif - using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; +using namespace SenseShift::Arduino::Input; +using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -55,12 +55,12 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true +#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* battery = new BatterySensor( - new ADCNaiveBattery(36), + new NaiveBatterySensor(new AnalogSensor(36)), &App, - { .sampleRate = BATTERY_SAMPLE_RATE }, - { "ADC Battery", 4096, BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); #endif diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 0fb4875d..300d9535 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -6,18 +6,18 @@ #include "senseshift.h" +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true -#include <battery/adc_naive.hpp> -#endif - using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; +using namespace SenseShift::Arduino::Input; +using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -65,12 +65,12 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true +#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* battery = new BatterySensor( - new ADCNaiveBattery(36), + new NaiveBatterySensor(new AnalogSensor(36)), &App, - { .sampleRate = BATTERY_SAMPLE_RATE }, - { "ADC Battery", 4096, BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); #endif diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index 74df3252..39bb6835 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -6,18 +6,18 @@ #include "senseshift.h" +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pca9685.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true -#include <battery/adc_naive.hpp> -#endif - using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; +using namespace SenseShift::Arduino::Input; +using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -70,12 +70,12 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true +#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* battery = new BatterySensor( - new ADCNaiveBattery(36), + new NaiveBatterySensor(new AnalogSensor(36)), &App, - { .sampleRate = BATTERY_SAMPLE_RATE }, - { "ADC Battery", 4096, BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); #endif diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 13a0689f..6fe41fc7 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -6,19 +6,19 @@ #include "senseshift.h" +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pca9685.hpp> #include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true -#include <battery/adc_naive.hpp> -#endif - using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; +using namespace SenseShift::Arduino::Input; +using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -78,12 +78,12 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true +#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* battery = new BatterySensor( - new ADCNaiveBattery(36), + new NaiveBatterySensor(new AnalogSensor(36)), &App, - { .sampleRate = BATTERY_SAMPLE_RATE }, - { "ADC Battery", 4096, BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); #endif diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index 73c88463..f6e063e0 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -6,18 +6,18 @@ #include "senseshift.h" +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true -#include "battery/adc_naive.hpp" -#endif - using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; +using namespace SenseShift::Arduino::Input; +using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -53,12 +53,12 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true +#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* battery = new BatterySensor( - new ADCNaiveBattery(36), + new NaiveBatterySensor(new AnalogSensor(36)), &App, - { .sampleRate = BATTERY_SAMPLE_RATE }, - { "ADC Battery", 4096, BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); #endif diff --git a/include/config/battery.h b/include/config/battery.h index 9c34c5e8..67747fa3 100644 --- a/include/config/battery.h +++ b/include/config/battery.h @@ -1,17 +1,17 @@ #pragma once -#ifndef BATTERY_ENABLED -#define BATTERY_ENABLED false +#ifndef SENSESHIFT_BATTERY_ENABLED +#define SENSESHIFT_BATTERY_ENABLED false #endif -#ifndef BATTERY_SAMPLE_RATE -#define BATTERY_SAMPLE_RATE 10000 +#ifndef SENSESHIFT_BATTERY_SAMPLE_RATE +#define SENSESHIFT_BATTERY_SAMPLE_RATE 10000 #endif -#ifndef BATTERY_THRESHOLD_PERCENTAGE -#define BATTERY_THRESHOLD_PERCENTAGE 20 +#ifndef SENSESHIFT_BATTERY_THRESHOLD_PERCENTAGE +#define SENSESHIFT_BATTERY_THRESHOLD_PERCENTAGE 20 #endif -#ifndef BATTERY_TASK_PRIORITY -#define BATTERY_TASK_PRIORITY 1 +#ifndef SENSESHIFT_BATTERY_TASK_PRIORITY +#define SENSESHIFT_BATTERY_TASK_PRIORITY 1 #endif diff --git a/include/senseshift.h b/include/senseshift.h index f2c94937..d48c99bb 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -3,12 +3,9 @@ #include "config/all.h" #include <haptic_body.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/events.hpp> -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true -#include <abstract_battery.hpp> -#endif - #include <vector> namespace SenseShift { @@ -16,10 +13,7 @@ namespace SenseShift { private: std::vector<const IEventListener*> eventListeners{}; Body::Haptics::HapticBody* pHapticBody; - -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true - OH::BatterySensor* battery; -#endif + Battery::BatterySensor* battery; public: SenseShift(); diff --git a/lib/arduino/battery/adc_naive.cpp b/lib/arduino/battery/adc_naive.cpp deleted file mode 100644 index d9991715..00000000 --- a/lib/arduino/battery/adc_naive.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "battery/adc_naive.hpp" - -#include <Arduino.h> -#include <senseshift/utility.hpp> - -namespace OH { - void ADCNaiveBattery::setup() - { - pinMode(this->pin, INPUT); - } - - BatteryState ADCNaiveBattery::getValue() - { - return { .level = static_cast<uint8_t>(::SenseShift::simpleMap<uint16_t>(analogRead(this->pin), 4095, 255)) }; - } -} // namespace OH diff --git a/lib/arduino/battery/adc_naive.hpp b/lib/arduino/battery/adc_naive.hpp deleted file mode 100644 index c54ced7b..00000000 --- a/lib/arduino/battery/adc_naive.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include <abstract_battery.hpp> - -namespace OH { - class ADCNaiveBattery : public OH::IBatterySensor { - private: - uint8_t pin; - - public: - ADCNaiveBattery(const uint8_t pin) : pin(pin){}; - - BatteryState getValue() override; - void setup(); - }; -} // namespace OH diff --git a/lib/battery/senseshift/battery.hpp b/lib/battery/senseshift/battery.hpp new file mode 100644 index 00000000..10e51896 --- /dev/null +++ b/lib/battery/senseshift/battery.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include <senseshift/events.hpp> + +#include <cstdint> + +namespace SenseShift::Battery { + typedef struct BatteryState { + uint8_t level; + } BatteryState_t; + + class BatteryLevelEvent : public IEvent { + public: + const BatteryState_t& state; + BatteryLevelEvent(const BatteryState_t& state) : IEvent(OH_EVENT_BATTERY_LEVEL), state(state){}; + }; +} // namespace SenseShift::Battery diff --git a/lib/battery/abstract_battery.hpp b/lib/battery/senseshift/battery/sensor.hpp similarity index 50% rename from lib/battery/abstract_battery.hpp rename to lib/battery/senseshift/battery/sensor.hpp index 0e64c2ad..bd9106d7 100644 --- a/lib/battery/abstract_battery.hpp +++ b/lib/battery/senseshift/battery/sensor.hpp @@ -1,58 +1,48 @@ #pragma once -#include <senseshift/events.hpp> +#include "senseshift/battery.hpp" + #include <senseshift/input/sensor.hpp> +#include <senseshift/utility.hpp> #include <task.hpp> -#include <stdint.h> - -#ifndef BATTERY_TASK_PRIORITY -#define BATTERY_TASK_PRIORITY 1 +#ifndef SENSESHIFT_BATTERY_TASK_PRIORITY +#define SENSESHIFT_BATTERY_TASK_PRIORITY 1 #endif -namespace OH { +namespace SenseShift::Battery { + typedef struct BatteryConfig { + uint sampleRate; + } BatteryConfig_t; + /** * Tasked sensor decorator */ template<typename _Tp> - class TaskedSensor : public Task<TaskedSensor<_Tp>>, public ::SenseShift::Input::MemoizedSensor<_Tp> { - friend class Task<TaskedSensor<_Tp>>; - - private: - virtual void run(void) - { - while (true) { - this->updateValue(); - delay(this->rate); - } - }; - - protected: - uint32_t rate; + class TaskedSensor : public OH::Task<TaskedSensor<_Tp>>, public ::SenseShift::Input::MemoizedSensor<_Tp> { + friend class OH::Task<TaskedSensor<_Tp>>; public: - TaskedSensor(::SenseShift::Input::ISensor<_Tp>* sensor, TaskConfig taskConfig, uint32_t rate) : - ::SenseShift::Input::MemoizedSensor<_Tp>(sensor), Task<TaskedSensor<_Tp>>(taskConfig), rate(rate){}; + TaskedSensor(::SenseShift::Input::ISensor<_Tp>* sensor, OH::TaskConfig taskConfig, const uint32_t rate) : + ::SenseShift::Input::MemoizedSensor<_Tp>(sensor), OH::Task<TaskedSensor<_Tp>>(taskConfig), rate(rate){}; void begin() override { this->setup(); - this->Task<TaskedSensor<_Tp>>::begin(); + this->OH::Task<TaskedSensor<_Tp>>::begin(); }; - }; - - struct BatteryState { - uint8_t level; - }; - class BatteryLevelEvent : public ::SenseShift::IEvent { - public: - const BatteryState state; - BatteryLevelEvent(const BatteryState state) : ::SenseShift::IEvent(OH_EVENT_BATTERY_LEVEL), state(state){}; - }; + protected: + const uint32_t rate; - struct BatteryConfig { - uint sampleRate; + private: + virtual void run(void) + { + while (true) { + this->updateValue(); + delay(this->rate); + } + }; }; /** @@ -61,18 +51,15 @@ namespace OH { typedef ::SenseShift::Input::ISensor<BatteryState> IBatterySensor; class BatterySensor : public TaskedSensor<BatteryState> { - friend class Task<TaskedSensor<BatteryState>>; + friend class OH::Task<TaskedSensor<BatteryState>>; friend class TaskedSensor<BatteryState>; - private: - ::SenseShift::IEventDispatcher* eventDispatcher; - public: BatterySensor( IBatterySensor* sensor, ::SenseShift::IEventDispatcher* eventDispatcher, - BatteryConfig config, - TaskConfig taskConfig + const BatteryConfig_t& config, + OH::TaskConfig taskConfig ) : TaskedSensor<BatteryState>(sensor, taskConfig, config.sampleRate), eventDispatcher(eventDispatcher){}; @@ -84,5 +71,26 @@ namespace OH { delay(this->rate); } } + + private: + ::SenseShift::IEventDispatcher* eventDispatcher; + }; + + class NaiveBatterySensor : public IBatterySensor { + public: + NaiveBatterySensor(::SenseShift::Input::ISensor<uint16_t>* sensor) : sensor(sensor){}; + + BatteryState getValue() override + { + return { .level = + static_cast<uint8_t>(::SenseShift::simpleMap<uint16_t>(this->sensor->getValue(), 4095, 255)) }; + }; + void setup() + { + this->sensor->setup(); + } + + private: + ::SenseShift::Input::ISensor<uint16_t>* sensor; }; -} // namespace OH +} // namespace SenseShift::Battery diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp index 7e54500e..fd16ec75 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -185,11 +185,7 @@ namespace SenseShift::BH::BLE { #endif // original bHaptics Player require non-null value for battery level, otherwise it crashes -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true uint16_t defaultLevel = 0; -#else - uint16_t defaultLevel = 100; -#endif this->batteryChar->setValue(defaultLevel); // this->batteryChar->notify(); diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp index 90247d74..49068f52 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -1,5 +1,6 @@ #pragma once +#include <senseshift/battery.hpp> #include <senseshift/bh/ble/constants.hpp> #include <senseshift/bh/constants.hpp> #include <senseshift/events.hpp> @@ -14,10 +15,6 @@ #include <BLEDevice.h> #endif -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true -#include <abstract_battery.hpp> -#endif - namespace SenseShift::BH::BLE { typedef struct ConnectionConfig { static constexpr size_t SN_LENGTH = 10; @@ -36,25 +33,22 @@ namespace SenseShift::BH::BLE { }; static ConnectionCallbacks defaultCallback; - class Connection final : public ::SenseShift::IEventListener { + class Connection final : public IEventListener { public: typedef std::function<void(std::string&)> MotorHandler_t; - Connection( - const ConnectionConfig_t& config, MotorHandler_t motorHandler, ::SenseShift::IEventDispatcher* eventDispatcher - ) : + Connection(const ConnectionConfig_t& config, MotorHandler_t motorHandler, IEventDispatcher* eventDispatcher) : config(config), motorHandler(motorHandler), eventDispatcher(eventDispatcher) { this->eventDispatcher->addEventListener(this); }; void begin(void); - void handleEvent(const ::SenseShift::IEvent* event) const override + void handleEvent(const IEvent* event) const override { -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true if (event->eventName == OH_EVENT_BATTERY_LEVEL) { - uint16_t level = ::SenseShift::simpleMap<uint8_t>( - static_cast<const OH::BatteryLevelEvent*>(event)->state.level, + uint16_t level = simpleMap<uint8_t>( + static_cast<const ::SenseShift::Battery::BatteryLevelEvent*>(event)->state.level, 255, 100 ); @@ -64,7 +58,6 @@ namespace SenseShift::BH::BLE { return; } -#endif }; void setCallbacks(ConnectionCallbacks* pCallbacks) @@ -86,9 +79,5 @@ namespace SenseShift::BH::BLE { BLECharacteristic* batteryChar = nullptr; ConnectionCallbacks* callbacks = &defaultCallback; - -#if defined(BATTERY_ENABLED) && BATTERY_ENABLED == true - void handleBatteryChange(const OH::BatteryLevelEvent* event) const; -#endif }; } // namespace SenseShift::BH::BLE diff --git a/lib/ina219/battery/ina219.cpp b/lib/ina219/battery/ina219.cpp deleted file mode 100644 index 06ac6fb1..00000000 --- a/lib/ina219/battery/ina219.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "battery/ina219.hpp" -#include <utility.hpp> - -namespace OH { - void OH::INA219_Battery::setup() - { - this->active = this->sensor->begin(); - } - - BatteryState OH::INA219_Battery::getValue() - { - if (!this->active) { - return { 0 }; - } - - auto batteryVoltage = this->sensor->getBusVoltage_V(); - // TODO: change this linear transformation to smth more useful - auto batteryPercentage = (batteryVoltage - 3.0) / 0.96; - - return - { - simpleMap<float>(batteryPercentage, 1.0f, 255.0f); - }; - } -} // namespace OH diff --git a/lib/ina219/battery/ina219.hpp b/lib/ina219/battery/ina219.hpp deleted file mode 100644 index 109400de..00000000 --- a/lib/ina219/battery/ina219.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include <abstract_battery.hpp> - -#include <Adafruit_INA219.h> - -namespace OH { - class INA219_Battery : public OH::IBatterySensor { - private: - bool active = false; - Adafruit_INA219* sensor; - - public: - INA219_Battery(Adafruit_INA219* sensor) : sensor(sensor){}; - - void setup() override; - BatteryState getValue() override; - }; -} // namespace OH diff --git a/lib/ina219/senseshift/arduino/battery/ina219.hpp b/lib/ina219/senseshift/arduino/battery/ina219.hpp new file mode 100644 index 00000000..0d3487bf --- /dev/null +++ b/lib/ina219/senseshift/arduino/battery/ina219.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include <senseshift/battery/sensor.hpp> + +#include <Adafruit_INA219.h> + +namespace SenseShift::Arduino::Battery { + class INA219_Battery : public ::SenseShift::Battery::IBatterySensor { + private: + bool active = false; + Adafruit_INA219* sensor; + + public: + INA219_Battery(Adafruit_INA219* sensor) : sensor(sensor){}; + + void setup() override + { + this->active = this->sensor->begin(); + } + ::SenseShift::Battery::BatteryState getValue() override + { + if (!this->active) { + return { 0 }; + } + + auto batteryVoltage = this->sensor->getBusVoltage_V(); + // TODO: change this linear transformation to smth more useful + auto batteryPercentage = (batteryVoltage - 3.0) / 0.96; + + return { + simpleMap<float>(batteryPercentage, 1.0f, 255.0f), + }; + } + }; +} // namespace SenseShift::Arduino::Battery diff --git a/lib/max17048/battery/max17048.cpp b/lib/max17048/battery/max17048.cpp deleted file mode 100644 index d8d89383..00000000 --- a/lib/max17048/battery/max17048.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "battery/max17048.hpp" - -namespace OH { - /** - * @see - * https://github.com/sparkfun/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/blob/main/examples/Example1_Simple/Example1_Simple.ino - */ - void MAX1704_Battery::setup() - { - // Set up the MAX17043 LiPo fuel gauge: - this->active = this->gauge->begin(); - - if (this->active) { - // Quick start restarts the MAX17043 in hopes of getting a more accurate - // guess for the SOC. - this->gauge->quickStart(); - - // We can set an interrupt to alert when the battery SoC gets too low. - // We can alert at anywhere between 1% - 32%: - // this->gauge->setThreshold(BATTERY_THRESHOLD_PERCENTAGE); - } - } - - BatteryState MAX1704_Battery::getValue() - { - if (!this->active) { - return { 0 }; - } - - return { .level = this->gauge->getSOC() }; - } -} // namespace OH diff --git a/lib/max17048/battery/max17048.hpp b/lib/max17048/battery/max17048.hpp deleted file mode 100644 index 3c43fbcc..00000000 --- a/lib/max17048/battery/max17048.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include <abstract_battery.hpp> - -#include <SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.h> - -namespace OH { - class MAX1704_Battery : public OH::IBatterySensor { - private: - bool active = false; - SFE_MAX1704X* gauge; - - protected: - public: - MAX1704_Battery(SFE_MAX1704X* gauge) : gauge(gauge){}; - - void setup() override; - BatteryState getValue() override; - }; -} // namespace OH diff --git a/lib/max17048/senseshift/arduino/battery/max17048.hpp b/lib/max17048/senseshift/arduino/battery/max17048.hpp new file mode 100644 index 00000000..c95c8e86 --- /dev/null +++ b/lib/max17048/senseshift/arduino/battery/max17048.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include <senseshift/battery/sensor.hpp> + +#include <SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.h> + +namespace SenseShift::Arduino::Battery { + class MAX1704_Battery : public ::SenseShift::Battery::IBatterySensor { + public: + MAX1704_Battery(SFE_MAX1704X* gauge) : gauge(gauge){}; + + /** + * @see + * https://github.com/sparkfun/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/blob/main/examples/Example1_Simple/Example1_Simple.ino + */ + void setup() override + { + // Set up the MAX17043 LiPo fuel gauge: + this->active = this->gauge->begin(); + + if (this->active) { + // Quick start restarts the MAX17043 in hopes of getting a more accurate + // guess for the SOC. + this->gauge->quickStart(); + + // We can set an interrupt to alert when the battery SoC gets too low. + // We can alert at anywhere between 1% - 32%: + // this->gauge->setThreshold(SENSESHIFT_BATTERY_THRESHOLD_PERCENTAGE); + } + } + + ::SenseShift::Battery::BatteryState getValue() override + { + if (!this->active) { + return { 0 }; + } + + return { .level = this->gauge->getSOC() }; + } + + private: + bool active = false; + SFE_MAX1704X* gauge; + }; +} // namespace SenseShift::Arduino::Battery diff --git a/platformio.ini b/platformio.ini index c11d81a2..6d9b15a4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -26,7 +26,7 @@ build_flags = ; -D DEBUG_MODE=0 ; -D DEBUG_ESP_PORT=Serial ; -D SERIAL_PLOTTER=true -; -D BATTERY_ENABLED=true +; -D SENSESHIFT_BATTERY_ENABLED=true -D BLUETOOTH_USE_NIMBLE=true build_src_filter = From bfb53df79de2e0d18f41263db9cf77b6b12ffcf1 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 22 Aug 2023 01:42:45 +0400 Subject: [PATCH 12/82] refactor(Core): use `SenseShift` namespace and dir for math --- lib/haptics/haptic_plane.hpp | 6 ++++-- lib/haptics/haptics_interface.hpp | 4 ++-- lib/math/{ => senseshift/math}/point2.hpp | 8 +++++--- test/test_math_point2/main.cpp | 4 ++-- 4 files changed, 13 insertions(+), 9 deletions(-) rename lib/math/{ => senseshift/math}/point2.hpp (86%) diff --git a/lib/haptics/haptic_plane.hpp b/lib/haptics/haptic_plane.hpp index 88227f4f..4441b03a 100644 --- a/lib/haptics/haptic_plane.hpp +++ b/lib/haptics/haptic_plane.hpp @@ -115,9 +115,11 @@ namespace SenseShift::Body::Haptics { * @tparam _Tp The type of the point index. */ template<typename _Tp> - [[nodiscard]] static constexpr inline OH::Point2<_Tp> mapPoint(_Tp x, _Tp y, _Tp x_max, _Tp y_max) + [[nodiscard]] static constexpr inline ::SenseShift::Math::Point2<_Tp> + mapPoint(_Tp x, _Tp y, _Tp x_max, _Tp y_max) { - using Point_t = OH::Point2<_Tp>; + using Point_t = ::SenseShift::Math::Point2<_Tp>; + return Point_t( ::SenseShift::accurateMap<_Tp>(x + 1, 0, x_max + 2, Point_t::MIN, Point_t::MAX), ::SenseShift::accurateMap<_Tp>(y + 1, 0, y_max + 2, Point_t::MIN, Point_t::MAX) diff --git a/lib/haptics/haptics_interface.hpp b/lib/haptics/haptics_interface.hpp index 5afc9ffd..5b5a13bf 100644 --- a/lib/haptics/haptics_interface.hpp +++ b/lib/haptics/haptics_interface.hpp @@ -3,7 +3,7 @@ #include <stdint.h> #include <variant> -#include <point2.hpp> +#include <senseshift/math/point2.hpp> namespace SenseShift::Body::Haptics { typedef uint8_t EffectIntex_t; @@ -47,7 +47,7 @@ namespace SenseShift::Body::Haptics { } Target_t; typedef uint8_t Coordinate_t; - typedef OH::Point2<Coordinate_t> Position_t; + typedef ::SenseShift::Math::Point2<Coordinate_t> Position_t; // Vibration intensity. typedef struct VibroEffectData { diff --git a/lib/math/point2.hpp b/lib/math/senseshift/math/point2.hpp similarity index 86% rename from lib/math/point2.hpp rename to lib/math/senseshift/math/point2.hpp index 0cf151b8..6f8131d5 100644 --- a/lib/math/point2.hpp +++ b/lib/math/senseshift/math/point2.hpp @@ -3,10 +3,12 @@ #include <cmath> #include <tuple> -namespace OH { +namespace SenseShift::Math { template<typename _Tp> struct Point2 { - static_assert(std::is_arithmetic<_Tp>::value, "OH::Point2 only can be used with arithmetic types"); + static_assert( + std::is_arithmetic<_Tp>::value, "::SenseShift::Math::Point2 only can be used with arithmetic types" + ); typedef _Tp Value_t; @@ -46,4 +48,4 @@ namespace OH { typedef Point2<int> Point2i; typedef Point2<short> Point2s; typedef Point2<unsigned short> Point2w; -}; // namespace OH +}; // namespace SenseShift::Math diff --git a/test/test_math_point2/main.cpp b/test/test_math_point2/main.cpp index 8da8b3dd..a4fa7baf 100644 --- a/test/test_math_point2/main.cpp +++ b/test/test_math_point2/main.cpp @@ -1,7 +1,7 @@ -#include <point2.hpp> +#include <senseshift/math/point2.hpp> #include <unity.h> -using namespace OH; +using namespace SenseShift::Math; void test_operator_equal(void) { From ccf35e75f31b895296040fe3ec58a59f95c67d72 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 22 Aug 2023 01:55:30 +0400 Subject: [PATCH 13/82] refactor(Core): use `SenseShift` namespace and dir for calibration --- .github/scripts/get_firmware_name.sh | 6 +++--- firmware/mode_configs/opengloves/opengloves.cpp | 6 +++--- lib/calibration/{ => senseshift}/calibration.hpp | 6 ++++-- lib/opengloves/sensor/og_finger.hpp | 7 +++++-- lib/opengloves/sensor/og_sensor.hpp | 1 - lib/opengloves_task/opengloves_task.hpp | 5 +++-- lib/sensor/senseshift/input/sensor.hpp | 8 ++++---- test/test_calibration/main.cpp | 2 +- 8 files changed, 23 insertions(+), 18 deletions(-) rename lib/calibration/{ => senseshift}/calibration.hpp (96%) diff --git a/.github/scripts/get_firmware_name.sh b/.github/scripts/get_firmware_name.sh index cd7a2b6d..988e2d6c 100755 --- a/.github/scripts/get_firmware_name.sh +++ b/.github/scripts/get_firmware_name.sh @@ -50,17 +50,17 @@ getOpenGlovesName() { target="$target+bluetooth" fi - if [[ $flags =~ CALIBRATION_CURL=OH::MinMaxCalibrator ]]; then + if [[ $flags =~ CALIBRATION_CURL=::SenseShift::Calibration::MinMaxCalibrator ]]; then echo "::debug::MinMaxCalibrator is enabled, appending +curl_minmax to the target" target="$target+curl_minmaxcalib" fi - if [[ $flags =~ CALIBRATION_CURL=OH::CenterPointDeviationCalibrator ]]; then + if [[ $flags =~ CALIBRATION_CURL=::SenseShift::Calibration::CenterPointDeviationCalibrator ]]; then echo "::debug::CenterPointDeviationCalibrator is enabled, appending +curl_cpcalib to the target" target="$target+curl_cpcalib" fi - if [[ $flags =~ CALIBRATION_CURL=OH::FixedCenterPointDeviationCalibrator ]]; then + if [[ $flags =~ CALIBRATION_CURL=::SenseShift::Calibration::FixedCenterPointDeviationCalibrator ]]; then echo "::debug::FixedCenterPointDeviationCalibrator is enabled, appending +curl_fcpcalib to the target" target="$target+curl_fcpcalib" fi diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 2ac3d7d0..47d8e289 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -1,10 +1,10 @@ -#include <calibration.hpp> #include <og_constants.hpp> #include <og_serial_communication.hpp> #include <opengloves_task.hpp> #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/input/sensor/digital.hpp> #include <senseshift/arduino/output/servo.hpp> +#include <senseshift/calibration.hpp> #include <senseshift/input/sensor.hpp> #include <senseshift/input/sensor/joystick.hpp> #include <senseshift/utility.hpp> @@ -34,10 +34,10 @@ #pragma region Calibration #ifndef CALIBRATION_CURL -#define CALIBRATION_CURL OH::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX> +#define CALIBRATION_CURL ::SenseShift::Calibration::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX> #endif #ifndef CALIBRATION_SPLAY -#define CALIBRATION_SPLAY OH::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX> +#define CALIBRATION_SPLAY ::SenseShift::Calibration::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX> #endif #ifndef CALIBRATION_DURATION diff --git a/lib/calibration/calibration.hpp b/lib/calibration/senseshift/calibration.hpp similarity index 96% rename from lib/calibration/calibration.hpp rename to lib/calibration/senseshift/calibration.hpp index fa5faa86..fb48f060 100644 --- a/lib/calibration/calibration.hpp +++ b/lib/calibration/senseshift/calibration.hpp @@ -7,7 +7,7 @@ #include <senseshift/utility.hpp> -namespace OH { +namespace SenseShift::Calibration { struct ICalibrated { virtual void resetCalibration() = 0; virtual void enableCalibration() = 0; @@ -34,6 +34,8 @@ namespace OH { template<typename _Tp> struct ICalibrator { + static_assert(std::is_arithmetic<_Tp>::value, "ICalibrator only can be used with arithmetic types"); + virtual void reset() = 0; virtual void update(_Tp input) = 0; virtual _Tp calibrate(_Tp input) const = 0; @@ -163,4 +165,4 @@ namespace OH { ); } }; -} // namespace OH +} // namespace SenseShift::Calibration diff --git a/lib/opengloves/sensor/og_finger.hpp b/lib/opengloves/sensor/og_finger.hpp index 1b5de1a9..62f4b244 100644 --- a/lib/opengloves/sensor/og_finger.hpp +++ b/lib/opengloves/sensor/og_finger.hpp @@ -80,7 +80,7 @@ namespace OpenGloves { /** * Simple finger sensor that only provides calibration. */ - class CalibratedFingerSensor : public SimpleFingerSensor, public OH::ICalibrated { + class CalibratedFingerSensor : public SimpleFingerSensor, public SenseShift::Calibration::ICalibrated { public: CalibratedFingerSensor(FingerSensors sensors) : SimpleFingerSensor(sensors){}; @@ -121,7 +121,10 @@ namespace OpenGloves { } }; - class FingerSensor : public StringEncodedMemoizedSensor<FingerValue>, public OH::ICalibrated, public ICurl { + class FingerSensor : + public StringEncodedMemoizedSensor<FingerValue>, + public SenseShift::Calibration::ICalibrated, + public ICurl { public: FingerSensor(CalibratedFingerSensor* sensor, IEncodedInput::Type type) : StringEncodedMemoizedSensor<FingerValue>(sensor, type){}; diff --git a/lib/opengloves/sensor/og_sensor.hpp b/lib/opengloves/sensor/og_sensor.hpp index 60e099d7..71c4c439 100644 --- a/lib/opengloves/sensor/og_sensor.hpp +++ b/lib/opengloves/sensor/og_sensor.hpp @@ -1,6 +1,5 @@ #pragma once -#include <calibration.hpp> #include <og_protocol.hpp> #include <senseshift/input/sensor.hpp> diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index a5dd8b3b..9d1f115a 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -4,12 +4,12 @@ #include <optional> -#include <calibration.hpp> #include <og_alpha_encoding.hpp> #include <og_ffb.hpp> #include <og_serial_communication.hpp> #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/input/sensor/digital.hpp> +#include <senseshift/calibration.hpp> #include <senseshift/input/sensor.hpp> #include <senseshift/input/sensor/joystick.hpp> #include <senseshift/utility.hpp> @@ -141,7 +141,8 @@ namespace OpenGloves { std::vector<IStringEncodedMemoizedSensor*> allSensors; std::optional<StringEncodedMemoizedSensor<bool>>& calibrationButton; - std::vector<OH::ICalibrated*> calibrated = std::vector<OH::ICalibrated*>(); + std::vector<SenseShift::Calibration::ICalibrated*> calibrated = + std::vector<SenseShift::Calibration::ICalibrated*>(); unsigned long long calibrationStarted = 0; void startCalibration() diff --git a/lib/sensor/senseshift/input/sensor.hpp b/lib/sensor/senseshift/input/sensor.hpp index 1b08ec60..d721257e 100644 --- a/lib/sensor/senseshift/input/sensor.hpp +++ b/lib/sensor/senseshift/input/sensor.hpp @@ -2,7 +2,7 @@ #include <type_traits> -#include <calibration.hpp> +#include <senseshift/calibration.hpp> #include <senseshift/logging.hpp> #if defined(__AVR__) @@ -90,10 +90,10 @@ namespace SenseShift::Input { * @tparam _Tp Type of the sensor value */ template<typename _Tp> - class CalibratedSensor : public ISensor<_Tp>, public OH::Calibrated { + class CalibratedSensor : public ISensor<_Tp>, public ::SenseShift::Calibration::Calibrated { protected: ISensor<_Tp>* sensor; - OH::ICalibrator<_Tp>* calibrator; + ::SenseShift::Calibration::ICalibrator<_Tp>* calibrator; _Tp getCalibratedValue() { @@ -111,7 +111,7 @@ namespace SenseShift::Input { * @param sensor Sensor to be decorated * @param calibrator ICalibrator algorithm to be used */ - CalibratedSensor(ISensor<_Tp>* sensor, OH::ICalibrator<_Tp>* calibrator) : + CalibratedSensor(ISensor<_Tp>* sensor, ::SenseShift::Calibration::ICalibrator<_Tp>* calibrator) : sensor(sensor), calibrator(calibrator){}; void setup() override diff --git a/test/test_calibration/main.cpp b/test/test_calibration/main.cpp index 52452a67..3455463c 100644 --- a/test/test_calibration/main.cpp +++ b/test/test_calibration/main.cpp @@ -1,4 +1,4 @@ -#include <calibration.hpp> +#include <senseshift/calibration.hpp> #include <unity.h> using namespace OH; From 87e8a2bfbc5ca984aba56572cc92b99edff80301 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 22 Aug 2023 02:07:28 +0400 Subject: [PATCH 14/82] refactor: move serial plotter to `SenseShift` namespace/dir --- .github/scripts/get_firmware_name.sh | 2 +- .github/workflows/ci.yml | 14 +++++----- .github/workflows/codeql-analysis.yml | 2 +- firmware/firmware.cpp | 22 ++++++++------- lib/arduino/components/serial_plotter.cpp | 26 ----------------- .../arduino/components/serial_plotter.cpp | 28 +++++++++++++++++++ .../arduino}/components/serial_plotter.hpp | 25 +++++++++++------ lib/opengloves/og_protocol.hpp | 4 +++ platformio.ini | 2 +- test/test_calibration/main.cpp | 2 +- test/test_opengloves_finger/main.cpp | 3 +- test/test_sensor/main.cpp | 2 +- 12 files changed, 74 insertions(+), 58 deletions(-) delete mode 100644 lib/arduino/components/serial_plotter.cpp create mode 100644 lib/arduino/senseshift/arduino/components/serial_plotter.cpp rename lib/arduino/{ => senseshift/arduino}/components/serial_plotter.hpp (56%) diff --git a/.github/scripts/get_firmware_name.sh b/.github/scripts/get_firmware_name.sh index 988e2d6c..75546a23 100755 --- a/.github/scripts/get_firmware_name.sh +++ b/.github/scripts/get_firmware_name.sh @@ -18,7 +18,7 @@ getBhapticsName() { target="$target+battery" fi - if [[ $flags =~ SERIAL_PLOTTER=true ]]; then + if [[ $flags =~ SENSESHIFT_SERIAL_PLOTTER=true ]]; then echo "::debug::Serial Plotter is enabled, appending +serialplotter to the target" target="$target+serialplotter" fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fefeed9d..66ab3dbd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: - bhaptics_tactvisor - bhaptics_tactglove_right battery_flag: [ SENSESHIFT_BATTERY_ENABLED=true ] - serial_plotter_flag: [ SERIAL_PLOTTER=false ] + serial_plotter_flag: [ SENSESHIFT_SERIAL_PLOTTER=false ] nimble_flag: [ BLUETOOTH_USE_NIMBLE=false ] coverage: [ false ] @@ -43,19 +43,19 @@ jobs: os: ubuntu-latest coverage: true battery_flag: SENSESHIFT_BATTERY_ENABLED=true - serial_plotter_flag: SERIAL_PLOTTER=true + serial_plotter_flag: SENSESHIFT_SERIAL_PLOTTER=true nimble_flag: BLUETOOTH_USE_NIMBLE=true # - target: bhaptics_tactsuit_x40 # os: ubuntu-latest # coverage: true # battery_flag: SENSESHIFT_BATTERY_ENABLED=true - # serial_plotter_flag: SERIAL_PLOTTER=true + # serial_plotter_flag: SENSESHIFT_SERIAL_PLOTTER=true # nimble_flag: BLUETOOTH_USE_NIMBLE=false - target: bhaptics_tactsuit_x40 os: ubuntu-latest coverage: false battery_flag: SENSESHIFT_BATTERY_ENABLED=true - serial_plotter_flag: SERIAL_PLOTTER=false + serial_plotter_flag: SENSESHIFT_SERIAL_PLOTTER=false nimble_flag: BLUETOOTH_USE_NIMBLE=true steps: @@ -177,15 +177,15 @@ jobs: include: - os: ubuntu-latest target: lucidgloves-prototype4-ffb - curl_calibration_flag: CALIBRATION_CURL="OH::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX>" + curl_calibration_flag: CALIBRATION_CURL="::SenseShift::Calibration::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX>" coverage: true - os: ubuntu-latest target: lucidgloves-prototype4-ffb - curl_calibration_flag: CALIBRATION_CURL="OH::CenterPointDeviationCalibrator<uint16_t, 20, 270, 0, ANALOG_MAX>" + curl_calibration_flag: CALIBRATION_CURL="::SenseShift::Calibration::CenterPointDeviationCalibrator<uint16_t, 20, 270, 0, ANALOG_MAX>" coverage: true - os: ubuntu-latest target: lucidgloves-prototype4-ffb - curl_calibration_flag: CALIBRATION_CURL="OH::FixedCenterPointDeviationCalibrator<uint16_t, 20, 270, 0, ANALOG_MAX>" + curl_calibration_flag: CALIBRATION_CURL="::SenseShift::Calibration::FixedCenterPointDeviationCalibrator<uint16_t, 20, 270, 0, ANALOG_MAX>" coverage: true - os: ubuntu-latest target: indexer-csf diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6f82bad4..74b3dd8d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -33,7 +33,7 @@ jobs: battery_flag: - SENSESHIFT_BATTERY_ENABLED=true serial_plotter_flag: - - SERIAL_PLOTTER=true + - SENSESHIFT_SERIAL_PLOTTER=true steps: - name: Checkout repository diff --git a/firmware/firmware.cpp b/firmware/firmware.cpp index ae0f0668..c30147c3 100644 --- a/firmware/firmware.cpp +++ b/firmware/firmware.cpp @@ -4,13 +4,13 @@ #include <Arduino.h> #endif // ARDUINO -#if defined(SERIAL_PLOTTER) && SERIAL_PLOTTER == true -#include <components/serial_plotter.hpp> -#endif // SERIAL_PLOTTER +#if defined(SENSESHIFT_SERIAL_PLOTTER) && SENSESHIFT_SERIAL_PLOTTER == true +#include <senseshift/arduino/components/serial_plotter.hpp> +#endif // SENSESHIFT_SERIAL_PLOTTER -#ifndef SERIAL_PLOTTER_PORT -#define SERIAL_PLOTTER_PORT Serial -#endif // SERIAL_PLOTTER_PORT +#ifndef SENSESHIFT_SERIAL_PLOTTER_PORT +#define SENSESHIFT_SERIAL_PLOTTER_PORT Serial +#endif // SENSESHIFT_SERIAL_PLOTTER_PORT #ifndef PIO_UNIT_TESTING @@ -25,11 +25,13 @@ void setup() { setupMode(); -#if defined(SERIAL_PLOTTER) && SERIAL_PLOTTER == true - auto* serialOutputState = - new OH::SerialPlotter_OutputStates<HardwareSerial>(SERIAL_PLOTTER_PORT, App.getHapticBody()); +#if defined(SENSESHIFT_SERIAL_PLOTTER) && SENSESHIFT_SERIAL_PLOTTER == true + auto* serialOutputState = new ::SenseShift::Arduino::SerialPlotter_OutputStates<HardwareSerial>( + SENSESHIFT_SERIAL_PLOTTER_PORT, + App.getHapticBody() + ); serialOutputState->begin(); -#endif // SERIAL_PLOTTER +#endif // SENSESHIFT_SERIAL_PLOTTER } void loop() diff --git a/lib/arduino/components/serial_plotter.cpp b/lib/arduino/components/serial_plotter.cpp deleted file mode 100644 index d5be860b..00000000 --- a/lib/arduino/components/serial_plotter.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "components/serial_plotter.hpp" - -struct PlaneVisitor { - const SenseShift::Body::Haptics::Target_t target; - HardwareSerial* serial; - - void operator()(const SenseShift::Body::Haptics::VibroPlane* plane) const - { - for (const auto& [position, state] : *(plane->getActuatorStates())) { - this->serial->printf("Output[%u][%ux%u]:%u, ", this->target, position.x, position.y, state.intensity); - } - } -}; - -template<typename _Tp> -void OH::SerialPlotter_OutputStates<_Tp>::run() -{ - while (true) { - for (const auto& [target, plane] : *output->getTargets()) { - std::visit(PlaneVisitor{ target, this->serial }, plane); - } - this->serial->println(); - - delay(this->sampleRate); - } -} diff --git a/lib/arduino/senseshift/arduino/components/serial_plotter.cpp b/lib/arduino/senseshift/arduino/components/serial_plotter.cpp new file mode 100644 index 00000000..bdd1fb38 --- /dev/null +++ b/lib/arduino/senseshift/arduino/components/serial_plotter.cpp @@ -0,0 +1,28 @@ +#include "senseshift/arduino/components/serial_plotter.hpp" + +namespace SenseShift::Arduino { + struct PlaneVisitor { + const SenseShift::Body::Haptics::Target_t target; + HardwareSerial* serial; + + void operator()(const SenseShift::Body::Haptics::VibroPlane* plane) const + { + for (const auto& [position, state] : *(plane->getActuatorStates())) { + this->serial->printf("Output[%u][%ux%u]:%u, ", this->target, position.x, position.y, state.intensity); + } + } + }; + + template<typename _Tp> + void SerialPlotter_OutputStates<_Tp>::run() + { + while (true) { + for (const auto& [target, plane] : *output->getTargets()) { + std::visit(PlaneVisitor{ target, this->serial }, plane); + } + this->serial->println(); + + delay(this->sampleRate); + } + } +} // namespace SenseShift::Arduino diff --git a/lib/arduino/components/serial_plotter.hpp b/lib/arduino/senseshift/arduino/components/serial_plotter.hpp similarity index 56% rename from lib/arduino/components/serial_plotter.hpp rename to lib/arduino/senseshift/arduino/components/serial_plotter.hpp index b2b9b085..02e21b36 100644 --- a/lib/arduino/components/serial_plotter.hpp +++ b/lib/arduino/senseshift/arduino/components/serial_plotter.hpp @@ -9,19 +9,23 @@ #define SERIAL_PLOTTER_BAUD 115200 #endif // SERIAL_PLOTTER_BAUD -namespace OH { +namespace SenseShift::Arduino { /** * Component, that prints the current state of the output to the serial port in Arduino's Serial Plotter format * * @tparam _Tp the type of the serial port */ template<class _Tp> - class SerialPlotter_OutputStates : public Task<SerialPlotter_OutputStates<_Tp>> { - friend class Task<SerialPlotter_OutputStates<_Tp>>; + class SerialPlotter_OutputStates : public OH::Task<SerialPlotter_OutputStates<_Tp>> { + static_assert( + std::is_base_of<Print, _Tp>::value, + "SerialPlotter_OutputStates only can be used with types, that inherit from Print" + ); + friend class OH::Task<SerialPlotter_OutputStates<_Tp>>; private: _Tp* serial; - SenseShift::Body::Haptics::HapticBody* output; + ::SenseShift::Body::Haptics::HapticBody* output; uint32_t sampleRate; void setup(void){}; @@ -30,12 +34,15 @@ namespace OH { public: SerialPlotter_OutputStates( _Tp& serial, - SenseShift::Body::Haptics::HapticBody* output, + ::SenseShift::Body::Haptics::HapticBody* output, uint32_t sampleRate, - TaskConfig taskConfig = { "Serial Plotter", 2048, 1, tskNO_AFFINITY } + OH::TaskConfig taskConfig = { "Serial Plotter", 2048, 1, tskNO_AFFINITY } ) : - Task<SerialPlotter_OutputStates<_Tp>>(taskConfig), serial(&serial), output(output), sampleRate(sampleRate){}; - SerialPlotter_OutputStates(_Tp& serial, SenseShift::Body::Haptics::HapticBody* output) : + OH::Task<SerialPlotter_OutputStates<_Tp>>(taskConfig), + serial(&serial), + output(output), + sampleRate(sampleRate){}; + SerialPlotter_OutputStates(_Tp& serial, ::SenseShift::Body::Haptics::HapticBody* output) : SerialPlotter_OutputStates(serial, output, 100){}; void begin() override @@ -55,4 +62,4 @@ namespace OH { } template class SerialPlotter_OutputStates<HardwareSerial>; -} // namespace OH +} // namespace SenseShift::Arduino diff --git a/lib/opengloves/og_protocol.hpp b/lib/opengloves/og_protocol.hpp index 3d601656..05e28174 100644 --- a/lib/opengloves/og_protocol.hpp +++ b/lib/opengloves/og_protocol.hpp @@ -1,5 +1,9 @@ #pragma once +#include <cstdint> +#include <functional> +#include <vector> + namespace OpenGloves { struct IEncodedInput { public: diff --git a/platformio.ini b/platformio.ini index 6d9b15a4..e626fcaa 100644 --- a/platformio.ini +++ b/platformio.ini @@ -25,7 +25,7 @@ build_flags = -D CORE_DEBUG_LEVEL=3 ; -D DEBUG_MODE=0 ; -D DEBUG_ESP_PORT=Serial -; -D SERIAL_PLOTTER=true +; -D SENSESHIFT_SERIAL_PLOTTER=true ; -D SENSESHIFT_BATTERY_ENABLED=true -D BLUETOOTH_USE_NIMBLE=true diff --git a/test/test_calibration/main.cpp b/test/test_calibration/main.cpp index 3455463c..a79a8bc6 100644 --- a/test/test_calibration/main.cpp +++ b/test/test_calibration/main.cpp @@ -1,7 +1,7 @@ #include <senseshift/calibration.hpp> #include <unity.h> -using namespace OH; +using namespace SenseShift::Calibration; void test_minmax_calibrator(void) { diff --git a/test/test_opengloves_finger/main.cpp b/test/test_opengloves_finger/main.cpp index 0a3a9978..019d8b5c 100644 --- a/test/test_opengloves_finger/main.cpp +++ b/test/test_opengloves_finger/main.cpp @@ -2,6 +2,7 @@ #include <unity.h> using namespace OpenGloves; +using namespace SenseShift::Calibration; class TestAnalogSensor : public SenseShift::Input::ISensor<uint16_t> { private: @@ -21,7 +22,7 @@ class TestAnalogSensor : public SenseShift::Input::ISensor<uint16_t> { }; }; -class DummyCalibrator : public OH::ICalibrator<uint16_t> { +class DummyCalibrator : public ICalibrator<uint16_t> { public: uint8_t resetCounter = 0; std::optional<uint16_t> calibrated = std::nullopt; diff --git a/test/test_sensor/main.cpp b/test/test_sensor/main.cpp index 7309e65c..02fe6e86 100644 --- a/test/test_sensor/main.cpp +++ b/test/test_sensor/main.cpp @@ -2,7 +2,7 @@ #include <unity.h> using namespace SenseShift::Input; -using namespace OH; +using namespace SenseShift::Calibration; class TestAnalogSensor : public ISensor<int> { private: From 4f818909f6da6a6e0cb21227440018d58bf46525 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 22 Aug 2023 10:17:49 +0400 Subject: [PATCH 15/82] refactor(BLE): rename global NimBLE flag --- .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 | 8 ++++---- lib/bhaptics_ble/senseshift/bh/ble/connection.hpp | 2 +- platformio.ini | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/scripts/get_firmware_name.sh b/.github/scripts/get_firmware_name.sh index 75546a23..d7c15d7a 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 =~ BLUETOOTH_USE_NIMBLE=true ]]; then + if [[ $flags =~ SENSESHIFT_BLE_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 66ab3dbd..5a0bf078 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: - bhaptics_tactglove_right battery_flag: [ SENSESHIFT_BATTERY_ENABLED=true ] serial_plotter_flag: [ SENSESHIFT_SERIAL_PLOTTER=false ] - nimble_flag: [ BLUETOOTH_USE_NIMBLE=false ] + nimble_flag: [ SENSESHIFT_BLE_USE_NIMBLE=false ] coverage: [ false ] include: @@ -44,19 +44,19 @@ jobs: coverage: true battery_flag: SENSESHIFT_BATTERY_ENABLED=true serial_plotter_flag: SENSESHIFT_SERIAL_PLOTTER=true - nimble_flag: BLUETOOTH_USE_NIMBLE=true + nimble_flag: SENSESHIFT_BLE_USE_NIMBLE=true # - target: bhaptics_tactsuit_x40 # os: ubuntu-latest # coverage: true # battery_flag: SENSESHIFT_BATTERY_ENABLED=true # serial_plotter_flag: SENSESHIFT_SERIAL_PLOTTER=true - # nimble_flag: BLUETOOTH_USE_NIMBLE=false + # nimble_flag: SENSESHIFT_BLE_USE_NIMBLE=false - target: bhaptics_tactsuit_x40 os: ubuntu-latest coverage: false battery_flag: SENSESHIFT_BATTERY_ENABLED=true serial_plotter_flag: SENSESHIFT_SERIAL_PLOTTER=false - nimble_flag: BLUETOOTH_USE_NIMBLE=true + nimble_flag: SENSESHIFT_BLE_USE_NIMBLE=true steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9b11b4a5..e4e216ef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,7 @@ jobs: battery_flag: - SENSESHIFT_BATTERY_ENABLED=true nimble_flag: - - BLUETOOTH_USE_NIMBLE=true + - SENSESHIFT_BLE_USE_NIMBLE=true steps: - uses: actions/checkout@v3 diff --git a/include/config/bluetooth.h b/include/config/bluetooth.h index b12cff34..3de034d4 100644 --- a/include/config/bluetooth.h +++ b/include/config/bluetooth.h @@ -11,6 +11,6 @@ } #endif -#ifndef BLUETOOTH_USE_NIMBLE -#define BLUETOOTH_USE_NIMBLE true +#ifndef SENSESHIFT_BLE_USE_NIMBLE +#define SENSESHIFT_BLE_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 fd16ec75..7d200d5d 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -6,7 +6,7 @@ #include <Arduino.h> -#if defined(BLUETOOTH_USE_NIMBLE) && BLUETOOTH_USE_NIMBLE == true +#if defined(SENSESHIFT_BLE_USE_NIMBLE) && SENSESHIFT_BLE_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(BLUETOOTH_USE_NIMBLE) && BLUETOOTH_USE_NIMBLE == true +#if defined(SENSESHIFT_BLE_USE_NIMBLE) && SENSESHIFT_BLE_USE_NIMBLE == true void onStatus(BLECharacteristic* pCharacteristic, Status s, int code) override #else void onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code) override @@ -180,7 +180,7 @@ namespace SenseShift::BH::BLE { | PROPERTY_NOTIFY // for whatever reason, it have to be writable, otherwise Desktop app crashes ); -#if !defined(BLUETOOTH_USE_NIMBLE) || BLUETOOTH_USE_NIMBLE != true +#if !defined(SENSESHIFT_BLE_USE_NIMBLE) || SENSESHIFT_BLE_USE_NIMBLE != true batteryChar->addDescriptor(new BLE2902()); #endif @@ -207,7 +207,7 @@ namespace SenseShift::BH::BLE { ); monitorChar->setCallbacks(new LogOutputCharCallbacks()); -#if !defined(BLUETOOTH_USE_NIMBLE) || BLUETOOTH_USE_NIMBLE != true +#if !defined(SENSESHIFT_BLE_USE_NIMBLE) || SENSESHIFT_BLE_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 49068f52..10dd4643 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -9,7 +9,7 @@ #include <Arduino.h> #include <esp_wifi.h> -#if defined(BLUETOOTH_USE_NIMBLE) && BLUETOOTH_USE_NIMBLE == true +#if defined(SENSESHIFT_BLE_USE_NIMBLE) && SENSESHIFT_BLE_USE_NIMBLE == true #include <NimBLEDevice.h> #else #include <BLEDevice.h> diff --git a/platformio.ini b/platformio.ini index e626fcaa..1a6bb8c3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -27,7 +27,7 @@ build_flags = ; -D DEBUG_ESP_PORT=Serial ; -D SENSESHIFT_SERIAL_PLOTTER=true ; -D SENSESHIFT_BATTERY_ENABLED=true - -D BLUETOOTH_USE_NIMBLE=true +; -D SENSESHIFT_BLE_USE_NIMBLE=true build_src_filter = +<*> From 1e635bc033850aaea778f76d0282be76ad31cdab Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 22 Aug 2023 10:30:55 +0400 Subject: [PATCH 16/82] format(clang): inline short functions --- .clang-format | 4 +- examples/bhaptics-ble-bt-serial.cpp | 5 +- firmware/mode_configs/test.cpp | 5 +- include/senseshift.h | 5 +- .../arduino/input/sensor/analog.hpp | 5 +- .../arduino/input/sensor/digital.hpp | 5 +- lib/battery/senseshift/battery/sensor.hpp | 5 +- lib/bhaptics/senseshift/bh/devices.hpp | 189 +++++++++--------- .../senseshift/bh/ble/connection.hpp | 5 +- lib/calibration/senseshift/calibration.hpp | 10 +- lib/freertos/task.hpp | 5 +- lib/haptics/haptic_body.hpp | 5 +- lib/haptics/haptic_plane.hpp | 15 +- lib/haptics/haptics_interface.hpp | 5 +- .../senseshift/arduino/battery/ina219.hpp | 5 +- lib/math/senseshift/math/point2.hpp | 15 +- lib/opengloves/og_protocol.hpp | 5 +- lib/opengloves/sensor/og_finger.hpp | 25 +-- lib/opengloves/sensor/og_gesture.hpp | 5 +- lib/opengloves/sensor/og_sensor.hpp | 10 +- .../og_serial_communication.hpp | 5 +- lib/sensor/senseshift/input/sensor.hpp | 30 +-- .../senseshift/input/sensor/joystick.hpp | 5 +- test/test_bhaptics_encoding/main.cpp | 10 +- test/test_haptics_body/main.cpp | 10 +- test/test_haptics_plane/main.cpp | 10 +- test/test_opengloves/main.cpp | 32 +-- test/test_opengloves_finger/main.cpp | 20 +- test/test_opengloves_gesture/main.cpp | 5 +- test/test_sensor/main.cpp | 20 +- 30 files changed, 155 insertions(+), 325 deletions(-) diff --git a/.clang-format b/.clang-format index 8972cb76..f1213235 100644 --- a/.clang-format +++ b/.clang-format @@ -7,9 +7,7 @@ AllowAllConstructorInitializersOnNextLine: 'true' AllowAllParametersOfDeclarationOnNextLine: 'true' AllowShortBlocksOnASingleLine: 'false' AllowShortCaseLabelsOnASingleLine: 'false' -# TODO -# AllowShortFunctionsOnASingleLine: Inline -AllowShortFunctionsOnASingleLine: Empty +AllowShortFunctionsOnASingleLine: Inline AllowShortIfStatementsOnASingleLine: Never AllowShortLambdasOnASingleLine: Empty AllowShortLoopsOnASingleLine: 'false' diff --git a/examples/bhaptics-ble-bt-serial.cpp b/examples/bhaptics-ble-bt-serial.cpp index d0c42d95..8adb23d3 100644 --- a/examples/bhaptics-ble-bt-serial.cpp +++ b/examples/bhaptics-ble-bt-serial.cpp @@ -27,10 +27,7 @@ static const ::SenseShift::Body::Haptics::Position_t* bhLayout[bhLayoutSize] = B class BLECallbacks : public BHBLEConnectionCallbacks { public: - void postInit() - { - btSerial->begin("SenseShift Serial"); - } + void postInit() { btSerial->begin("SenseShift Serial"); } }; void setupMode() diff --git a/firmware/mode_configs/test.cpp b/firmware/mode_configs/test.cpp index b6592e1b..943a38a2 100644 --- a/firmware/mode_configs/test.cpp +++ b/firmware/mode_configs/test.cpp @@ -22,10 +22,7 @@ class TestOutput : public OH::AbstractActuator { public: TestOutput(uint8_t channel) : channel(channel){}; - uint8_t getChannel() - { - return channel; - }; + uint8_t getChannel() { return channel; }; void writeOutput(oh_output_intensity_t intensity){}; }; diff --git a/include/senseshift.h b/include/senseshift.h index d48c99bb..27a3c3e9 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -18,10 +18,7 @@ namespace SenseShift { public: SenseShift(); - Body::Haptics::HapticBody* getHapticBody() - { - return this->pHapticBody; - }; + Body::Haptics::HapticBody* getHapticBody() { return this->pHapticBody; }; 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 d55fc37e..4d1d5705 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -13,10 +13,7 @@ namespace SenseShift::Arduino::Input { public: AnalogSensor(uint8_t pin) : pin(pin) {} - void setup(void) - { - pinMode(this->pin, INPUT); - }; + void setup(void) { pinMode(this->pin, INPUT); }; uint16_t getValue(void) override; }; diff --git a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp index 5a9c2f63..16de1b6c 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -15,10 +15,7 @@ namespace SenseShift::Arduino::Input { public: DigitalSensor(uint8_t pin) : pin(pin) {} - void setup(void) - { - pinMode(this->pin, INPUT_PULLUP); - }; + void setup(void) { pinMode(this->pin, INPUT_PULLUP); }; bool getValue(void) override; }; diff --git a/lib/battery/senseshift/battery/sensor.hpp b/lib/battery/senseshift/battery/sensor.hpp index bd9106d7..06a5f5b6 100644 --- a/lib/battery/senseshift/battery/sensor.hpp +++ b/lib/battery/senseshift/battery/sensor.hpp @@ -85,10 +85,7 @@ namespace SenseShift::Battery { return { .level = static_cast<uint8_t>(::SenseShift::simpleMap<uint16_t>(this->sensor->getValue(), 4095, 255)) }; }; - void setup() - { - this->sensor->setup(); - } + void setup() { this->sensor->setup(); } private: ::SenseShift::Input::ISensor<uint16_t>* sensor; diff --git a/lib/bhaptics/senseshift/bh/devices.hpp b/lib/bhaptics/senseshift/bh/devices.hpp index d3c24d1b..60cac07c 100644 --- a/lib/bhaptics/senseshift/bh/devices.hpp +++ b/lib/bhaptics/senseshift/bh/devices.hpp @@ -18,20 +18,20 @@ // X * Y for front and back #define BH_LAYOUT_TACTSUITX40_SIZE 40 // clang-format off -#define BH_LAYOUT_TACTSUITX40 { \ - /* Front, left part */ \ - /* 0 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ - /* 1 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ - /* 2 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ - /* 3 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ - /* 4 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ - /* 5 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ - /* 6 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ - /* 7 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ - /* 8 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ - /* 9 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ - \ - /* Back */ \ +#define BH_LAYOUT_TACTSUITX40 { \ + /* Front, left part */ \ + /* 0 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ + /* 1 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ + /* 2 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ + /* 3 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ + /* 4 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ + /* 5 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ + /* 6 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ + /* 7 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ + /* 8 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ + /* 9 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ + \ + /* Back */ \ /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ /* 12 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ @@ -42,7 +42,7 @@ /* 17 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ /* 18 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ /* 19 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ - \ + \ /* 20 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ /* 21 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ /* 22 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ @@ -53,18 +53,18 @@ /* 27 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ /* 28 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ /* 29 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) }, \ - \ - /* Front, again... Now right part */ \ - /* 30 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ - /* 31 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ - /* 32 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ - /* 33 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ - /* 34 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ - /* 35 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ - /* 36 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ - /* 37 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ - /* 38 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ - /* 39 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) } \ + \ + /* Front, again... Now right part */ \ + /* 30 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ + /* 31 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ + /* 32 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ + /* 33 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ + /* 34 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ + /* 35 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ + /* 36 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ + /* 37 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ + /* 38 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ + /* 39 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) } \ } // clang-format on @@ -85,57 +85,57 @@ // X16 suit uses the same packets structure as x40 suit and performs motor grouping in firmware #define BH_LAYOUT_TACTSUITX16_SIZE 40 // clang-format off -#define BH_LAYOUT_TACTSUITX16 { \ - /* Front, left part */ \ - /* 0 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ - /* 1 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ - /* 2 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ - /* 3 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ - \ - /* 4 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ - /* 5 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ - /* 6 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ - /* 7 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ - /* 8 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ - /* 9 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ - \ - /* Back */ \ - /* 10 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ - /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ - /* 12 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ - /* 13 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ - \ - /* 14 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ - /* 15 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ - /* 16 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ - /* 17 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ - /* 18 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ - /* 19 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ - \ - /* 20 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ - /* 21 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ - /* 22 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ - /* 23 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ - \ - /* 24 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ - /* 25 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ - /* 26 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ - /* 27 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 15 */ \ - /* 28 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 18 */ \ - /* 29 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 19 */ \ - \ - /* Front, again... Now right part */ \ - /* 30 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ - /* 31 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ - /* 32 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ - /* 33 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ - \ - /* 34 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ - /* 35 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ - /* 36 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ - /* 37 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 15 */ \ - /* 38 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 18 */ \ - /* 39 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 19 */ \ +#define BH_LAYOUT_TACTSUITX16 { \ + /* Front, left part */ \ + /* 0 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ + /* 1 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ + /* 2 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ + /* 3 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ + \ + /* 4 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ + /* 5 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ + /* 6 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ + /* 7 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ + /* 8 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ + /* 9 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ + \ + /* Back */ \ + /* 10 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ + /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ + /* 12 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ + /* 13 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ + \ + /* 14 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ + /* 15 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ + /* 16 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ + /* 17 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ + /* 18 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ + /* 19 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ + \ + /* 20 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ + /* 21 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ + /* 22 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ + /* 23 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ + \ + /* 24 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ + /* 25 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ + /* 26 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ + /* 27 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 15 */ \ + /* 28 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 18 */ \ + /* 29 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 19 */ \ + \ + /* Front, again... Now right part */ \ + /* 30 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ + /* 31 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ + /* 32 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ + /* 33 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ + \ + /* 34 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ + /* 35 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ + /* 36 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ + /* 37 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 15 */ \ + /* 38 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 18 */ \ + /* 39 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 19 */ \ } // clang-format on @@ -260,24 +260,27 @@ #pragma region BH_DEVIDE_TACTGLOVE +// clang-format off #define BH_LAYOUT_TACTGLOVE_SIZE 6 // TactGlove (Left) motor positions -#define BH_LAYOUT_TACTGLOVE_LEFT \ - { \ - { Target_t::HandLeftThumb, FINGERTIP_POSITION }, { Target_t::HandLeftIndex, FINGERTIP_POSITION }, \ - { Target_t::HandLeftMiddle, FINGERTIP_POSITION }, { Target_t::HandLeftRing, FINGERTIP_POSITION }, \ - { Target_t::HandLeftLittle, FINGERTIP_POSITION }, { Target_t::HandLeftDorsal, WRIST_MOTOR_POSITION }, \ - } +#define BH_LAYOUT_TACTGLOVE_LEFT { \ + { Target_t::HandLeftThumb, FINGERTIP_POSITION }, \ + { Target_t::HandLeftIndex, FINGERTIP_POSITION }, \ + { Target_t::HandLeftMiddle, FINGERTIP_POSITION }, \ + { Target_t::HandLeftRing, FINGERTIP_POSITION }, \ + { Target_t::HandLeftLittle, FINGERTIP_POSITION }, \ + { Target_t::HandLeftDorsal, WRIST_MOTOR_POSITION }, \ +} // TactGlove (Right) motor positions -#define BH_LAYOUT_TACTGLOVE_RIGHT \ - { \ - { Target_t::HandRightThumb, FINGERTIP_POSITION }, { Target_t::HandRightIndex, FINGERTIP_POSITION }, \ - { Target_t::HandRightMiddle, FINGERTIP_POSITION }, { Target_t::HandRightRing, FINGERTIP_POSITION }, \ - { Target_t::HandRightLittle, FINGERTIP_POSITION }, \ - { \ - Target_t::HandRightDorsal, WRIST_MOTOR_POSITION \ - } \ - } +#define BH_LAYOUT_TACTGLOVE_RIGHT { \ + { Target_t::HandRightThumb, FINGERTIP_POSITION }, \ + { Target_t::HandRightIndex, FINGERTIP_POSITION }, \ + { Target_t::HandRightMiddle, FINGERTIP_POSITION }, \ + { Target_t::HandRightRing, FINGERTIP_POSITION }, \ + { Target_t::HandRightLittle, FINGERTIP_POSITION }, \ + { Target_t::HandRightDorsal, WRIST_MOTOR_POSITION } \ +} +// clang-format on #pragma endregion BH_DEVIDE_TACTGLOVE diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp index 10dd4643..ea5b1ae6 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -26,10 +26,7 @@ namespace SenseShift::BH::BLE { class ConnectionCallbacks { public: - virtual void postInit() - { - log_v("Default postInit"); - }; + virtual void postInit() { log_v("Default postInit"); }; }; static ConnectionCallbacks defaultCallback; diff --git a/lib/calibration/senseshift/calibration.hpp b/lib/calibration/senseshift/calibration.hpp index fb48f060..58c190c0 100644 --- a/lib/calibration/senseshift/calibration.hpp +++ b/lib/calibration/senseshift/calibration.hpp @@ -21,15 +21,9 @@ namespace SenseShift::Calibration { public: virtual void resetCalibration() = 0; - void enableCalibration() override - { - calibrate = true; - } + void enableCalibration() override { calibrate = true; } - void disableCalibration() override - { - calibrate = false; - } + void disableCalibration() override { calibrate = false; } }; template<typename _Tp> diff --git a/lib/freertos/task.hpp b/lib/freertos/task.hpp index 6a40f33a..e77c7ec4 100644 --- a/lib/freertos/task.hpp +++ b/lib/freertos/task.hpp @@ -58,10 +58,7 @@ namespace OH { Task(TaskConfig config) : taskConfig(config){}; virtual ~Task(){}; - TaskHandle_t getHandle() const - { - return taskHandle; - }; + TaskHandle_t getHandle() const { return taskHandle; }; virtual void begin() { diff --git a/lib/haptics/haptic_body.hpp b/lib/haptics/haptic_body.hpp index ff05a1e4..d0e536cd 100644 --- a/lib/haptics/haptic_body.hpp +++ b/lib/haptics/haptic_body.hpp @@ -22,10 +22,7 @@ namespace SenseShift::Body::Haptics { void addTarget(const Target_t, VibroPlane* plane); - [[nodiscard]] const PlaneTargetMap_t* getTargets() const - { - return &allTargets; - } + [[nodiscard]] const PlaneTargetMap_t* getTargets() const { return &allTargets; } private: PlaneTargetMap_t allTargets{}; diff --git a/lib/haptics/haptic_plane.hpp b/lib/haptics/haptic_plane.hpp index 4441b03a..e382e01a 100644 --- a/lib/haptics/haptic_plane.hpp +++ b/lib/haptics/haptic_plane.hpp @@ -31,22 +31,13 @@ namespace SenseShift::Body::Haptics { ActuativePlane() = default; - ActuativePlane(const ActuatorMap_t& actuators) - { - this->setActuators(actuators); - } + ActuativePlane(const ActuatorMap_t& actuators) { this->setActuators(actuators); } void setup(); virtual void effect(const Position_t&, const Value_t&); - [[nodiscard]] const PositionSet_t* getAvailablePoints() const - { - return &points; - } - [[nodiscard]] const PositionStateMap_t* getActuatorStates() const - { - return &states; - } + [[nodiscard]] const PositionSet_t* getAvailablePoints() const { return &points; } + [[nodiscard]] const PositionStateMap_t* getActuatorStates() const { return &states; } private: PositionSet_t points; diff --git a/lib/haptics/haptics_interface.hpp b/lib/haptics/haptics_interface.hpp index 5b5a13bf..506f0928 100644 --- a/lib/haptics/haptics_interface.hpp +++ b/lib/haptics/haptics_interface.hpp @@ -61,10 +61,7 @@ namespace SenseShift::Body::Haptics { inline constexpr VibroEffectData(const Intensity_t intensity) : intensity(intensity) {} inline constexpr VibroEffectData(const VibroEffectData& other) = default; - inline constexpr operator uint16_t() const - { - return intensity; - } + inline constexpr operator uint16_t() const { return intensity; } } VibroEffectData_t; // TODO: thermal, etc. diff --git a/lib/ina219/senseshift/arduino/battery/ina219.hpp b/lib/ina219/senseshift/arduino/battery/ina219.hpp index 0d3487bf..ec2dea00 100644 --- a/lib/ina219/senseshift/arduino/battery/ina219.hpp +++ b/lib/ina219/senseshift/arduino/battery/ina219.hpp @@ -13,10 +13,7 @@ namespace SenseShift::Arduino::Battery { public: INA219_Battery(Adafruit_INA219* sensor) : sensor(sensor){}; - void setup() override - { - this->active = this->sensor->begin(); - } + void setup() override { this->active = this->sensor->begin(); } ::SenseShift::Battery::BatteryState getValue() override { if (!this->active) { diff --git a/lib/math/senseshift/math/point2.hpp b/lib/math/senseshift/math/point2.hpp index 6f8131d5..001d16bf 100644 --- a/lib/math/senseshift/math/point2.hpp +++ b/lib/math/senseshift/math/point2.hpp @@ -21,20 +21,11 @@ namespace SenseShift::Math { constexpr Point2(_Tp x, _Tp y) : x(x), y(y){}; constexpr Point2(const Point2<_Tp>& v) : x((_Tp) v.x), y((_Tp) v.y){}; - constexpr inline bool operator==(const Point2<_Tp>& rhs) const - { - return x == rhs.x && y == rhs.y; - } + constexpr inline bool operator==(const Point2<_Tp>& rhs) const { return x == rhs.x && y == rhs.y; } - constexpr inline bool operator!=(const Point2<_Tp>& rhs) const - { - return !(*this == rhs); - } + constexpr inline bool operator!=(const Point2<_Tp>& rhs) const { return !(*this == rhs); } - constexpr bool operator<(const Point2<_Tp>& rhs) const - { - return std::tie(x, y) < std::tie(rhs.x, rhs.y); - } + constexpr bool operator<(const Point2<_Tp>& rhs) const { return std::tie(x, y) < std::tie(rhs.x, rhs.y); } constexpr float operator-(const Point2<_Tp>& rhs) const { diff --git a/lib/opengloves/og_protocol.hpp b/lib/opengloves/og_protocol.hpp index 05e28174..9c92e98f 100644 --- a/lib/opengloves/og_protocol.hpp +++ b/lib/opengloves/og_protocol.hpp @@ -27,10 +27,7 @@ namespace OpenGloves { IEncodedInput(Type type) : type(type){}; - constexpr Type getType() const - { - return this->type; - } + constexpr Type getType() const { return this->type; } protected: Type type; diff --git a/lib/opengloves/sensor/og_finger.hpp b/lib/opengloves/sensor/og_finger.hpp index 62f4b244..9b5193d3 100644 --- a/lib/opengloves/sensor/og_finger.hpp +++ b/lib/opengloves/sensor/og_finger.hpp @@ -68,10 +68,7 @@ namespace OpenGloves { return value; } - uint16_t getCurl() override - { - return this->getValue().getTotalCurl(); - } + uint16_t getCurl() override { return this->getValue().getTotalCurl(); } protected: FingerSensors sensors; @@ -139,25 +136,13 @@ namespace OpenGloves { FingerSensor(SenseShift::Input::CalibratedSensor<uint16_t>* curl1, IEncodedInput::Type type) : StringEncodedMemoizedSensor<FingerValue>(new CalibratedFingerSensor(curl1, std::nullopt), type){}; - void resetCalibration() override - { - static_cast<CalibratedFingerSensor*>(this->sensor)->resetCalibration(); - } + void resetCalibration() override { static_cast<CalibratedFingerSensor*>(this->sensor)->resetCalibration(); } - void enableCalibration() override - { - static_cast<CalibratedFingerSensor*>(this->sensor)->enableCalibration(); - } + void enableCalibration() override { static_cast<CalibratedFingerSensor*>(this->sensor)->enableCalibration(); } - void disableCalibration() override - { - static_cast<CalibratedFingerSensor*>(this->sensor)->disableCalibration(); - } + void disableCalibration() override { static_cast<CalibratedFingerSensor*>(this->sensor)->disableCalibration(); } - uint16_t getCurl() override - { - return this->getValue().getTotalCurl(); - } + uint16_t getCurl() override { return this->getValue().getTotalCurl(); } }; struct HandSensors { diff --git a/lib/opengloves/sensor/og_gesture.hpp b/lib/opengloves/sensor/og_gesture.hpp index 3c7e0944..324cdb30 100644 --- a/lib/opengloves/sensor/og_gesture.hpp +++ b/lib/opengloves/sensor/og_gesture.hpp @@ -36,10 +36,7 @@ namespace OpenGloves { void setup() override{}; - bool getValue() override - { - return this->index.getCurl() > this->threshold; - } + bool getValue() override { return this->index.getCurl() > this->threshold; } }; class PinchGesture : public Gesture { diff --git a/lib/opengloves/sensor/og_sensor.hpp b/lib/opengloves/sensor/og_sensor.hpp index 71c4c439..9fdd4a71 100644 --- a/lib/opengloves/sensor/og_sensor.hpp +++ b/lib/opengloves/sensor/og_sensor.hpp @@ -33,15 +33,9 @@ namespace OpenGloves { StringEncodedMemoizedSensor(SenseShift::Input::ISensor<_Tp>* sensor, IEncodedInput::Type type) : IStringEncodedMemoizedSensor(type), SenseShift::Input::MemoizedSensor<_Tp>(sensor){}; - void setup() override - { - this->sensor->setup(); - } + void setup() override { this->sensor->setup(); } - void updateValue() override - { - this->value = this->sensor->getValue(); - } + void updateValue() override { this->value = this->sensor->getValue(); } size_t getEncodedLength() const override; diff --git a/lib/opengloves_serial/og_serial_communication.hpp b/lib/opengloves_serial/og_serial_communication.hpp index 45d89a52..800b70e0 100644 --- a/lib/opengloves_serial/og_serial_communication.hpp +++ b/lib/opengloves_serial/og_serial_communication.hpp @@ -70,10 +70,7 @@ namespace OpenGloves { this->ready = true; } - bool isReady() override - { - return this->ready; - } + bool isReady() override { return this->ready; } bool hasData() override { diff --git a/lib/sensor/senseshift/input/sensor.hpp b/lib/sensor/senseshift/input/sensor.hpp index d721257e..8de2a7bb 100644 --- a/lib/sensor/senseshift/input/sensor.hpp +++ b/lib/sensor/senseshift/input/sensor.hpp @@ -62,26 +62,17 @@ namespace SenseShift::Input { /** * Setup the sensor hardware */ - void setup() override - { - this->sensor->setup(); - }; + void setup() override { this->sensor->setup(); }; /** * Get the current memoized value */ - _Tp getValue() override - { - return this->value; - }; + _Tp getValue() override { return this->value; }; /** * Read actual value from the hardware and memoize it */ - void updateValue() - { - this->value = this->sensor->getValue(); - }; + void updateValue() { this->value = this->sensor->getValue(); }; }; /** @@ -114,19 +105,10 @@ namespace SenseShift::Input { CalibratedSensor(ISensor<_Tp>* sensor, ::SenseShift::Calibration::ICalibrator<_Tp>* calibrator) : sensor(sensor), calibrator(calibrator){}; - void setup() override - { - this->sensor->setup(); - }; + void setup() override { this->sensor->setup(); }; - _Tp getValue() override - { - return this->getCalibratedValue(); - }; + _Tp getValue() override { return this->getCalibratedValue(); }; - void resetCalibration() override - { - this->calibrator->reset(); - }; + void resetCalibration() override { this->calibrator->reset(); }; }; } // namespace SenseShift::Input diff --git a/lib/sensor/senseshift/input/sensor/joystick.hpp b/lib/sensor/senseshift/input/sensor/joystick.hpp index 307d49ea..b9d28519 100644 --- a/lib/sensor/senseshift/input/sensor/joystick.hpp +++ b/lib/sensor/senseshift/input/sensor/joystick.hpp @@ -24,10 +24,7 @@ namespace SenseShift::Input { public: JoystickAxisSensor(ISensor<_Tp>* sensor, float dead_zone) : sensor(sensor), dead_zone(dead_zone){}; - void setup(void) - { - this->sensor->setup(); - }; + void setup(void) { this->sensor->setup(); }; uint16_t getValue(void) override { diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index 2de6e52e..03a560be 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -12,14 +12,8 @@ class TestActuator : public IActuator<uint16_t> { uint16_t intensity = 0; TestActuator() : IActuator<uint16_t>() {} - void setup() override - { - this->isSetup = true; - } - void writeOutput(uint16_t intensity) override - { - this->intensity = intensity; - } + void setup() override { this->isSetup = true; } + void writeOutput(uint16_t intensity) override { this->intensity = intensity; } }; void test_layout_tactsuitx16(void) diff --git a/test/test_haptics_body/main.cpp b/test/test_haptics_body/main.cpp index 27b8b56e..19c8c866 100644 --- a/test/test_haptics_body/main.cpp +++ b/test/test_haptics_body/main.cpp @@ -10,14 +10,8 @@ class TestActuator : public IActuator<uint16_t> { uint16_t intensity = 0; TestActuator() : IActuator<uint16_t>() {} - void setup() override - { - this->isSetup = true; - } - void writeOutput(uint16_t intensity) override - { - this->intensity = intensity; - } + void setup() override { this->isSetup = true; } + void writeOutput(uint16_t intensity) override { this->intensity = intensity; } }; void test_it_sets_up_planes(void) diff --git a/test/test_haptics_plane/main.cpp b/test/test_haptics_plane/main.cpp index 38e4594b..091ba1c3 100644 --- a/test/test_haptics_plane/main.cpp +++ b/test/test_haptics_plane/main.cpp @@ -10,14 +10,8 @@ class TestActuator : public IActuator<uint16_t> { uint16_t intensity = 0; TestActuator() : IActuator<uint16_t>() {} - void setup() override - { - this->isSetup = true; - } - void writeOutput(uint16_t intensity) override - { - this->intensity = intensity; - } + void setup() override { this->isSetup = true; } + void writeOutput(uint16_t intensity) override { this->intensity = intensity; } }; void test_it_sets_up_actuators(void) diff --git a/test/test_opengloves/main.cpp b/test/test_opengloves/main.cpp index 646a9785..c711cdc1 100644 --- a/test/test_opengloves/main.cpp +++ b/test/test_opengloves/main.cpp @@ -10,15 +10,9 @@ class TestAnalogSensor : public SenseShift::Input::ISensor<uint16_t> { public: int setupCounter = 0; - void setup() override - { - this->setupCounter++; - }; - - uint16_t getValue() override - { - return ++this->count; - }; + void setup() override { this->setupCounter++; }; + + uint16_t getValue() override { return ++this->count; }; }; class TestBinarySensor : public SenseShift::Input::ISensor<bool> { @@ -26,15 +20,9 @@ class TestBinarySensor : public SenseShift::Input::ISensor<bool> { bool value = false; int setupCounter = 0; - void setup() override - { - this->setupCounter++; - }; + void setup() override { this->setupCounter++; }; - bool getValue() override - { - return this->value; - }; + bool getValue() override { return this->value; }; }; class TestFingerSensor : public SenseShift::Input::ISensor<FingerValue> { @@ -42,15 +30,9 @@ class TestFingerSensor : public SenseShift::Input::ISensor<FingerValue> { FingerValue value; int setupCounter = 0; - void setup() override - { - this->setupCounter++; - }; + void setup() override { this->setupCounter++; }; - FingerValue getValue() override - { - return this->value; - }; + FingerValue getValue() override { return this->value; }; }; void test_string_encoded_sensor_uint16(void) diff --git a/test/test_opengloves_finger/main.cpp b/test/test_opengloves_finger/main.cpp index 019d8b5c..ee063582 100644 --- a/test/test_opengloves_finger/main.cpp +++ b/test/test_opengloves_finger/main.cpp @@ -11,15 +11,9 @@ class TestAnalogSensor : public SenseShift::Input::ISensor<uint16_t> { public: int setupCounter = 0; - void setup() override - { - this->setupCounter++; - }; + void setup() override { this->setupCounter++; }; - uint16_t getValue() override - { - return this->count++; - }; + uint16_t getValue() override { return this->count++; }; }; class DummyCalibrator : public ICalibrator<uint16_t> { @@ -32,14 +26,8 @@ class DummyCalibrator : public ICalibrator<uint16_t> { this->resetCounter++; this->calibrated = std::nullopt; }; - void update(uint16_t input) override - { - this->calibrated = input; - }; - uint16_t calibrate(uint16_t input) const override - { - return this->calibrated.value_or(input); - }; + void update(uint16_t input) override { this->calibrated = input; }; + uint16_t calibrate(uint16_t input) const override { return this->calibrated.value_or(input); }; }; void test_simple_finger_sensor_curl(void) diff --git a/test/test_opengloves_gesture/main.cpp b/test/test_opengloves_gesture/main.cpp index 6ee8b066..0d89a11a 100644 --- a/test/test_opengloves_gesture/main.cpp +++ b/test/test_opengloves_gesture/main.cpp @@ -9,10 +9,7 @@ class TestCurlFinger : public ICurl { TestCurlFinger(uint16_t initialValue = 0) : value(initialValue){}; - uint16_t getCurl() override - { - return this->value; - } + uint16_t getCurl() override { return this->value; } }; void test_gesture_grab(void) diff --git a/test/test_sensor/main.cpp b/test/test_sensor/main.cpp index 02fe6e86..f9cbcea0 100644 --- a/test/test_sensor/main.cpp +++ b/test/test_sensor/main.cpp @@ -11,15 +11,9 @@ class TestAnalogSensor : public ISensor<int> { public: int setupCounter = 0; - void setup() override - { - this->setupCounter++; - }; + void setup() override { this->setupCounter++; }; - int getValue() override - { - return ++this->count; - }; + int getValue() override { return ++this->count; }; }; void test_memoized_sensor(void) @@ -50,14 +44,8 @@ class DummyCalibrator : public ICalibrator<int> { this->resetCounter++; this->calibrated = 0; }; - void update(int input) override - { - this->calibrated = input; - }; - int calibrate(int input) const override - { - return calibrated; - }; + void update(int input) override { this->calibrated = input; }; + int calibrate(int input) const override { return calibrated; }; }; void test_calibrated_sensor(void) From e3c16396516395ebf5e9d50ee8e1669166b15962 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 22 Aug 2023 10:48:43 +0400 Subject: [PATCH 17/82] fix(BLE): non-NimBLE S/N char --- lib/bhaptics_ble/senseshift/bh/ble/connection.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp index 7d200d5d..66c91204 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -169,7 +169,9 @@ namespace SenseShift::BH::BLE { BH_BLE_SERVICE_MOTOR_CHAR_SERIAL_KEY_UUID, PROPERTY_READ | PROPERTY_WRITE ); - serialNumberChar->setValue(this->config.serialNumber, ConnectionConfig_t::SN_LENGTH); + uint8_t serialNumber[ConnectionConfig_t::SN_LENGTH]; + memcpy(serialNumber, this->config.serialNumber, ConnectionConfig_t::SN_LENGTH); + serialNumberChar->setValue(serialNumber, ConnectionConfig_t::SN_LENGTH); serialNumberChar->setCallbacks(new LogOutputCharCallbacks()); } From 8a1e2b5c086b7ba2c69ce41dc3d28e3476be89f7 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 22 Aug 2023 18:45:07 +0400 Subject: [PATCH 18/82] refactor(FreeRTOS): move to `SenseShift` namespace/dir --- examples/bhaptics-ble-bt-serial.cpp | 1 - firmware/mode_configs/bhaptics/tactal.cpp | 1 - firmware/mode_configs/bhaptics/tactglove.cpp | 1 - firmware/mode_configs/bhaptics/tactosy2.cpp | 1 - firmware/mode_configs/bhaptics/tactosyf.cpp | 1 - firmware/mode_configs/bhaptics/tactosyh.cpp | 1 - .../mode_configs/bhaptics/tactsuit_x16.cpp | 1 - .../bhaptics/tactsuit_x16_pca9685.cpp | 1 - .../mode_configs/bhaptics/tactsuit_x40.cpp | 1 - firmware/mode_configs/bhaptics/tactvisor.cpp | 1 - firmware/mode_configs/test.cpp | 42 ------------------- .../arduino/components/serial_plotter.hpp | 12 +++--- lib/battery/senseshift/battery/sensor.hpp | 22 ++++++---- .../{ => senseshift/freertos}/task.hpp | 4 +- lib/opengloves_task/opengloves_task.hpp | 27 +++++++----- 15 files changed, 38 insertions(+), 79 deletions(-) delete mode 100644 firmware/mode_configs/test.cpp rename lib/freertos/{ => senseshift/freertos}/task.hpp (97%) diff --git a/examples/bhaptics-ble-bt-serial.cpp b/examples/bhaptics-ble-bt-serial.cpp index 8adb23d3..68dd1482 100644 --- a/examples/bhaptics-ble-bt-serial.cpp +++ b/examples/bhaptics-ble-bt-serial.cpp @@ -13,7 +13,6 @@ #include <BluetoothSerial.h> #include <HardwareSerial.h> -using namespace OH; using namespace BH; extern SenseShift App; diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index 991fdce5..d1886357 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -13,7 +13,6 @@ #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index c7fd1924..f3bfc5f4 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -14,7 +14,6 @@ #include <senseshift/bh/encoding.hpp> #include <senseshift/utility.hpp> -using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index 26937edb..3063cc98 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -13,7 +13,6 @@ #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index 33aea620..ceae8983 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -13,7 +13,6 @@ #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 068add9e..0f8beef4 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -13,7 +13,6 @@ #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 300d9535..8897b400 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -13,7 +13,6 @@ #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index 39bb6835..e147a845 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -13,7 +13,6 @@ #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 6fe41fc7..5d990130 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -14,7 +14,6 @@ #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index f6e063e0..4c9fa3d0 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -13,7 +13,6 @@ #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -using namespace OH; using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; diff --git a/firmware/mode_configs/test.cpp b/firmware/mode_configs/test.cpp deleted file mode 100644 index 943a38a2..00000000 --- a/firmware/mode_configs/test.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Override you configs in this file (Ctrl+Click) -#include "config/all.h" - -#ifdef UNIT_TEST -#include "ArduinoFake.h" -#else -#include "Arduino.h" -#endif - -#include "senseshift.h" - -#include <haptic_body.hpp> - -using namespace OH; - -extern SenseShift App; -SenseShift* app = &App; - -class TestOutput : public OH::AbstractActuator { - private: - uint8_t channel; - - public: - TestOutput(uint8_t channel) : channel(channel){}; - uint8_t getChannel() { return channel; }; - void writeOutput(oh_output_intensity_t intensity){}; -}; - -void setupMode() -{ - auto testOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ - { new TestOutput(0), new TestOutput(1) }, - { new TestOutput(2), new TestOutput(3) }, - { new TestOutput(4), new TestOutput(5) }, - { new TestOutput(6), new TestOutput(7) }, - }); - - auto test = new HapticPlane_Closest(testOutputs); - App.getHapticBody()->addComponent(OUTPUT_PATH_ACCESSORY, test); -} - -void loopMode() {} diff --git a/lib/arduino/senseshift/arduino/components/serial_plotter.hpp b/lib/arduino/senseshift/arduino/components/serial_plotter.hpp index 02e21b36..708111b6 100644 --- a/lib/arduino/senseshift/arduino/components/serial_plotter.hpp +++ b/lib/arduino/senseshift/arduino/components/serial_plotter.hpp @@ -1,7 +1,7 @@ #pragma once #include <haptic_body.hpp> -#include <task.hpp> +#include <senseshift/freertos/task.hpp> #include <HardwareSerial.h> @@ -16,12 +16,12 @@ namespace SenseShift::Arduino { * @tparam _Tp the type of the serial port */ template<class _Tp> - class SerialPlotter_OutputStates : public OH::Task<SerialPlotter_OutputStates<_Tp>> { + class SerialPlotter_OutputStates : public ::SenseShift::FreeRTOS::Task<SerialPlotter_OutputStates<_Tp>> { static_assert( std::is_base_of<Print, _Tp>::value, "SerialPlotter_OutputStates only can be used with types, that inherit from Print" ); - friend class OH::Task<SerialPlotter_OutputStates<_Tp>>; + friend class ::SenseShift::FreeRTOS::Task<SerialPlotter_OutputStates<_Tp>>; private: _Tp* serial; @@ -36,9 +36,9 @@ namespace SenseShift::Arduino { _Tp& serial, ::SenseShift::Body::Haptics::HapticBody* output, uint32_t sampleRate, - OH::TaskConfig taskConfig = { "Serial Plotter", 2048, 1, tskNO_AFFINITY } + ::SenseShift::FreeRTOS::TaskConfig taskConfig = { "Serial Plotter", 2048, 1, tskNO_AFFINITY } ) : - OH::Task<SerialPlotter_OutputStates<_Tp>>(taskConfig), + ::SenseShift::FreeRTOS::Task<SerialPlotter_OutputStates<_Tp>>(taskConfig), serial(&serial), output(output), sampleRate(sampleRate){}; @@ -48,7 +48,7 @@ namespace SenseShift::Arduino { void begin() override { this->setup(); - OH::Task<SerialPlotter_OutputStates<_Tp>>::begin(); + ::SenseShift::FreeRTOS::Task<SerialPlotter_OutputStates<_Tp>>::begin(); }; }; diff --git a/lib/battery/senseshift/battery/sensor.hpp b/lib/battery/senseshift/battery/sensor.hpp index 06a5f5b6..b5dea89d 100644 --- a/lib/battery/senseshift/battery/sensor.hpp +++ b/lib/battery/senseshift/battery/sensor.hpp @@ -2,9 +2,9 @@ #include "senseshift/battery.hpp" +#include <senseshift/freertos/task.hpp> #include <senseshift/input/sensor.hpp> #include <senseshift/utility.hpp> -#include <task.hpp> #ifndef SENSESHIFT_BATTERY_TASK_PRIORITY #define SENSESHIFT_BATTERY_TASK_PRIORITY 1 @@ -19,17 +19,23 @@ namespace SenseShift::Battery { * Tasked sensor decorator */ template<typename _Tp> - class TaskedSensor : public OH::Task<TaskedSensor<_Tp>>, public ::SenseShift::Input::MemoizedSensor<_Tp> { - friend class OH::Task<TaskedSensor<_Tp>>; + class TaskedSensor : + public ::SenseShift::FreeRTOS::Task<TaskedSensor<_Tp>>, + public ::SenseShift::Input::MemoizedSensor<_Tp> { + friend class ::SenseShift::FreeRTOS::Task<TaskedSensor<_Tp>>; public: - TaskedSensor(::SenseShift::Input::ISensor<_Tp>* sensor, OH::TaskConfig taskConfig, const uint32_t rate) : - ::SenseShift::Input::MemoizedSensor<_Tp>(sensor), OH::Task<TaskedSensor<_Tp>>(taskConfig), rate(rate){}; + TaskedSensor( + ::SenseShift::Input::ISensor<_Tp>* sensor, ::SenseShift::FreeRTOS::TaskConfig taskConfig, const uint32_t rate + ) : + ::SenseShift::Input::MemoizedSensor<_Tp>(sensor), + ::SenseShift::FreeRTOS::Task<TaskedSensor<_Tp>>(taskConfig), + rate(rate){}; void begin() override { this->setup(); - this->OH::Task<TaskedSensor<_Tp>>::begin(); + this->::SenseShift::FreeRTOS::Task<TaskedSensor<_Tp>>::begin(); }; protected: @@ -51,7 +57,7 @@ namespace SenseShift::Battery { typedef ::SenseShift::Input::ISensor<BatteryState> IBatterySensor; class BatterySensor : public TaskedSensor<BatteryState> { - friend class OH::Task<TaskedSensor<BatteryState>>; + friend class ::SenseShift::FreeRTOS::Task<TaskedSensor<BatteryState>>; friend class TaskedSensor<BatteryState>; public: @@ -59,7 +65,7 @@ namespace SenseShift::Battery { IBatterySensor* sensor, ::SenseShift::IEventDispatcher* eventDispatcher, const BatteryConfig_t& config, - OH::TaskConfig taskConfig + ::SenseShift::FreeRTOS::TaskConfig taskConfig ) : TaskedSensor<BatteryState>(sensor, taskConfig, config.sampleRate), eventDispatcher(eventDispatcher){}; diff --git a/lib/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp similarity index 97% rename from lib/freertos/task.hpp rename to lib/freertos/senseshift/freertos/task.hpp index e77c7ec4..d06aada4 100644 --- a/lib/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -21,7 +21,7 @@ BaseType_t xTaskCreateUniversal( } #endif -namespace OH { +namespace SenseShift::FreeRTOS { struct TaskConfig { const char* name; uint32_t stackDepth; @@ -78,4 +78,4 @@ namespace OH { } }; }; -} // namespace OH +} // namespace SenseShift::FreeRTOS diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index 9d1f115a..8fab0ec0 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -10,12 +10,12 @@ #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/input/sensor/digital.hpp> #include <senseshift/calibration.hpp> +#include <senseshift/freertos/task.hpp> #include <senseshift/input/sensor.hpp> #include <senseshift/input/sensor/joystick.hpp> #include <senseshift/utility.hpp> #include <sensor/og_finger.hpp> #include <sensor/og_gesture.hpp> -#include <task.hpp> namespace OpenGloves { struct OpenGlovesTrackingTaskConfig { @@ -36,8 +36,8 @@ namespace OpenGloves { } }; - class OpenGlovesTrackingTask : public OH::Task<OpenGlovesTrackingTask> { - friend class OH::Task<OpenGlovesTrackingTask>; + class OpenGlovesTrackingTask : public SenseShift::FreeRTOS::Task<OpenGlovesTrackingTask> { + friend class SenseShift::FreeRTOS::Task<OpenGlovesTrackingTask>; public: /** @@ -58,7 +58,7 @@ namespace OpenGloves { std::vector<StringEncodedMemoizedSensor<uint16_t>*>& joysticks, std::vector<IStringEncodedMemoizedSensor*>& otherSensors, std::optional<StringEncodedMemoizedSensor<bool>>& calibrationButton, - OH::TaskConfig taskConfig + SenseShift::FreeRTOS::TaskConfig taskConfig ) : config(config), communication(communication), @@ -68,7 +68,7 @@ namespace OpenGloves { otherSensors(otherSensors), calibrationButton(calibrationButton), allSensors(std::vector<IStringEncodedMemoizedSensor*>()), - OH::Task<OpenGlovesTrackingTask>(taskConfig) + SenseShift::FreeRTOS::Task<OpenGlovesTrackingTask>(taskConfig) { if (fingers.thumb.has_value()) { auto* thumb = &fingers.thumb.value(); @@ -126,7 +126,7 @@ namespace OpenGloves { { log_d("Starting OpenGloves tracking task: %p", this); this->setup(); - this->OH::Task<OpenGlovesTrackingTask>::begin(); + this->SenseShift::FreeRTOS::Task<OpenGlovesTrackingTask>::begin(); }; private: @@ -215,14 +215,19 @@ namespace OpenGloves { }; }; - class OpenGlovesForceFeedbackTask : public OH::Task<OpenGlovesForceFeedbackTask> { - friend class OH::Task<OpenGlovesForceFeedbackTask>; + class OpenGlovesForceFeedbackTask : public SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask> { + friend class SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>; public: OpenGlovesForceFeedbackTask( - ICommunication& communication, HandActuators& actuators, size_t updateRate, OH::TaskConfig taskConfig + ICommunication& communication, + HandActuators& actuators, + size_t updateRate, + SenseShift::FreeRTOS::TaskConfig taskConfig ) : - communication(communication), actuators(actuators), OH::Task<OpenGlovesForceFeedbackTask>(taskConfig) + communication(communication), + actuators(actuators), + SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>(taskConfig) { this->updateIntervalMs = 1000 / updateRate; }; @@ -231,7 +236,7 @@ namespace OpenGloves { { log_d("Starting OpenGloves force feedback task: %p", this); this->setup(); - this->OH::Task<OpenGlovesForceFeedbackTask>::begin(); + this->SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>::begin(); }; private: From 46743e918485c6b3ddf0153a4a23e1cab36986e6 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 24 Aug 2023 13:32:33 +0400 Subject: [PATCH 19/82] refactor(Battery): decouple battery API and impl --- firmware/mode_configs/bhaptics/tactal.cpp | 10 +-- firmware/mode_configs/bhaptics/tactglove.cpp | 10 +-- firmware/mode_configs/bhaptics/tactosy2.cpp | 10 +-- firmware/mode_configs/bhaptics/tactosyf.cpp | 10 +-- firmware/mode_configs/bhaptics/tactosyh.cpp | 10 +-- .../mode_configs/bhaptics/tactsuit_x16.cpp | 10 +-- .../bhaptics/tactsuit_x16_pca9685.cpp | 10 +-- .../mode_configs/bhaptics/tactsuit_x40.cpp | 10 +-- firmware/mode_configs/bhaptics/tactvisor.cpp | 10 +-- include/senseshift.h | 2 +- lib/battery/senseshift/battery/sensor.hpp | 66 ------------------- .../senseshift/freertos/battery.hpp | 22 +++++++ .../senseshift/freertos/input/sensor.hpp | 59 +++++++++++++++++ lib/freertos/senseshift/freertos/task.hpp | 33 +++++----- 14 files changed, 154 insertions(+), 118 deletions(-) create mode 100644 lib/battery_task/senseshift/freertos/battery.hpp create mode 100644 lib/freertos/senseshift/freertos/input/sensor.hpp diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index d1886357..f19d9e7d 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -12,10 +12,13 @@ #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> +#include <senseshift/freertos/battery.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; +using namespace SenseShift::FreeRTOS::Battery; +using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -53,10 +56,9 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new BatterySensor( - new NaiveBatterySensor(new AnalogSensor(36)), - &App, - { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + auto* battery = new TaskedSensor<BatteryState>( + new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), + SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index f3bfc5f4..8b123ef4 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -12,11 +12,14 @@ #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> +#include <senseshift/freertos/battery.hpp> #include <senseshift/utility.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; +using namespace SenseShift::FreeRTOS::Battery; +using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -61,10 +64,9 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new BatterySensor( - new NaiveBatterySensor(new AnalogSensor(36)), - &App, - { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + auto* battery = new TaskedSensor<BatteryState>( + new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), + SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index 3063cc98..682a349b 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -12,10 +12,13 @@ #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> +#include <senseshift/freertos/battery.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; +using namespace SenseShift::FreeRTOS::Battery; +using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -54,10 +57,9 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new BatterySensor( - new NaiveBatterySensor(new AnalogSensor(36)), - &App, - { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + auto* battery = new TaskedSensor<BatteryState>( + new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), + SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index ceae8983..99b792fd 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -12,10 +12,13 @@ #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> +#include <senseshift/freertos/battery.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; +using namespace SenseShift::FreeRTOS::Battery; +using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -55,10 +58,9 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new BatterySensor( - new NaiveBatterySensor(new AnalogSensor(36)), - &App, - { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + auto* battery = new TaskedSensor<BatteryState>( + new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), + SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 0f8beef4..0e3cc417 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -12,10 +12,13 @@ #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> +#include <senseshift/freertos/battery.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; +using namespace SenseShift::FreeRTOS::Battery; +using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -55,10 +58,9 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new BatterySensor( - new NaiveBatterySensor(new AnalogSensor(36)), - &App, - { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + auto* battery = new TaskedSensor<BatteryState>( + new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), + SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 8897b400..8bc88899 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -12,10 +12,13 @@ #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> +#include <senseshift/freertos/battery.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; +using namespace SenseShift::FreeRTOS::Battery; +using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -65,10 +68,9 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new BatterySensor( - new NaiveBatterySensor(new AnalogSensor(36)), - &App, - { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + auto* battery = new TaskedSensor<BatteryState>( + new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), + SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index e147a845..f7a9b099 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -12,10 +12,13 @@ #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> +#include <senseshift/freertos/battery.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; +using namespace SenseShift::FreeRTOS::Battery; +using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -70,10 +73,9 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new BatterySensor( - new NaiveBatterySensor(new AnalogSensor(36)), - &App, - { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + auto* battery = new TaskedSensor<BatteryState>( + new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), + SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 5d990130..e8668bcf 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -13,10 +13,13 @@ #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> +#include <senseshift/freertos/battery.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; +using namespace SenseShift::FreeRTOS::Battery; +using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -78,10 +81,9 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new BatterySensor( - new NaiveBatterySensor(new AnalogSensor(36)), - &App, - { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + auto* battery = new TaskedSensor<BatteryState>( + new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), + SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index 4c9fa3d0..68cd1188 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -12,10 +12,13 @@ #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> +#include <senseshift/freertos/battery.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; +using namespace SenseShift::FreeRTOS::Battery; +using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; @@ -53,10 +56,9 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new BatterySensor( - new NaiveBatterySensor(new AnalogSensor(36)), - &App, - { .sampleRate = SENSESHIFT_BATTERY_SAMPLE_RATE }, + auto* battery = new TaskedSensor<BatteryState>( + new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), + SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); battery->begin(); diff --git a/include/senseshift.h b/include/senseshift.h index 27a3c3e9..c63f5659 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -13,7 +13,7 @@ namespace SenseShift { private: std::vector<const IEventListener*> eventListeners{}; Body::Haptics::HapticBody* pHapticBody; - Battery::BatterySensor* battery; + ::SenseShift::Battery::IBatterySensor* battery; public: SenseShift(); diff --git a/lib/battery/senseshift/battery/sensor.hpp b/lib/battery/senseshift/battery/sensor.hpp index b5dea89d..0ae63ba3 100644 --- a/lib/battery/senseshift/battery/sensor.hpp +++ b/lib/battery/senseshift/battery/sensor.hpp @@ -11,77 +11,11 @@ #endif namespace SenseShift::Battery { - typedef struct BatteryConfig { - uint sampleRate; - } BatteryConfig_t; - - /** - * Tasked sensor decorator - */ - template<typename _Tp> - class TaskedSensor : - public ::SenseShift::FreeRTOS::Task<TaskedSensor<_Tp>>, - public ::SenseShift::Input::MemoizedSensor<_Tp> { - friend class ::SenseShift::FreeRTOS::Task<TaskedSensor<_Tp>>; - - public: - TaskedSensor( - ::SenseShift::Input::ISensor<_Tp>* sensor, ::SenseShift::FreeRTOS::TaskConfig taskConfig, const uint32_t rate - ) : - ::SenseShift::Input::MemoizedSensor<_Tp>(sensor), - ::SenseShift::FreeRTOS::Task<TaskedSensor<_Tp>>(taskConfig), - rate(rate){}; - - void begin() override - { - this->setup(); - this->::SenseShift::FreeRTOS::Task<TaskedSensor<_Tp>>::begin(); - }; - - protected: - const uint32_t rate; - - private: - virtual void run(void) - { - while (true) { - this->updateValue(); - delay(this->rate); - } - }; - }; - /** * Abstract battery sensor */ typedef ::SenseShift::Input::ISensor<BatteryState> IBatterySensor; - class BatterySensor : public TaskedSensor<BatteryState> { - friend class ::SenseShift::FreeRTOS::Task<TaskedSensor<BatteryState>>; - friend class TaskedSensor<BatteryState>; - - public: - BatterySensor( - IBatterySensor* sensor, - ::SenseShift::IEventDispatcher* eventDispatcher, - const BatteryConfig_t& config, - ::SenseShift::FreeRTOS::TaskConfig taskConfig - ) : - TaskedSensor<BatteryState>(sensor, taskConfig, config.sampleRate), eventDispatcher(eventDispatcher){}; - - void run() override - { - while (true) { - this->updateValue(); - this->eventDispatcher->postEvent(new BatteryLevelEvent(this->value)); - delay(this->rate); - } - } - - private: - ::SenseShift::IEventDispatcher* eventDispatcher; - }; - class NaiveBatterySensor : public IBatterySensor { public: NaiveBatterySensor(::SenseShift::Input::ISensor<uint16_t>* sensor) : sensor(sensor){}; diff --git a/lib/battery_task/senseshift/freertos/battery.hpp b/lib/battery_task/senseshift/freertos/battery.hpp new file mode 100644 index 00000000..688459a2 --- /dev/null +++ b/lib/battery_task/senseshift/freertos/battery.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include <senseshift/battery/sensor.hpp> +#include <senseshift/freertos/input/sensor.hpp> + +namespace SenseShift::FreeRTOS::Battery { + class BatterySensor : public ::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState> { + public: + BatterySensor(::SenseShift::Battery::IBatterySensor* sensor, ::SenseShift::IEventDispatcher* eventDispatcher) : + ::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>(sensor), + eventDispatcher(eventDispatcher){}; + + void updateValue() override + { + this->::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>::updateValue(); + this->eventDispatcher->postEvent(new ::SenseShift::Battery::BatteryLevelEvent(this->value)); + } + + private: + ::SenseShift::IEventDispatcher* eventDispatcher; + }; +} // namespace SenseShift::FreeRTOS::Battery diff --git a/lib/freertos/senseshift/freertos/input/sensor.hpp b/lib/freertos/senseshift/freertos/input/sensor.hpp new file mode 100644 index 00000000..b4b273b8 --- /dev/null +++ b/lib/freertos/senseshift/freertos/input/sensor.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include <senseshift/freertos/task.hpp> +#include <senseshift/input/sensor.hpp> + +#include <cstdint> + +namespace SenseShift::FreeRTOS::Input { + /** + * Sensor update task + */ + class SensorUpdateTask : public Task<SensorUpdateTask> { + friend class Task<SensorUpdateTask>; + + private: + using Sensor_t = ::SenseShift::Input::IMemoizedSensor; + + public: + SensorUpdateTask(Sensor_t* sensor, std::uint32_t updateDelay, TaskConfig taskConfig) : + Task<SensorUpdateTask>(taskConfig), updateDelay(updateDelay){}; + + protected: + Sensor_t* sensor; + std::uint32_t updateDelay; + + void run() + { + while (true) { + this->sensor->updateValue(); + ::delay(this->updateDelay); + } + } + }; + + template<typename _Tp> + class TaskedSensor : public SensorUpdateTask, public ::SenseShift::Input::ISensor<_Tp> { + friend class SensorUpdateTask; + + private: + using Sensor_t = ::SenseShift::Input::MemoizedSensor<_Tp>; + + public: + TaskedSensor(Sensor_t* sensor, std::uint32_t updateDelay, TaskConfig taskConfig) : + SensorUpdateTask(sensor, updateDelay, taskConfig), sensor(sensor){}; + + void begin() override + { + this->setup(); + SensorUpdateTask::begin(); + }; + + void setup() override { this->sensor->setup(); }; + + _Tp getValue() override { return this->sensor->getValue(); }; + + private: + Sensor_t* sensor; + }; +} // namespace SenseShift::FreeRTOS::Input diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index d06aada4..d41355ec 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -38,25 +38,18 @@ namespace SenseShift::FreeRTOS { template<typename> friend class Task; - private: - TaskConfig taskConfig; - TaskHandle_t taskHandle = nullptr; - - static void taskFunction(void* params) - { - _Tp* task = static_cast<_Tp*>(params); - task->run(); - } - public: Task(const char* name, uint32_t stackDepth, UBaseType_t priority, const BaseType_t coreId = tskNO_AFFINITY) { - TaskConfig config = { name, stackDepth, priority, coreId }; - - this->taskConfig = config; + this->taskConfig = { name, stackDepth, priority, coreId }; + }; + Task(TaskConfig& config) : taskConfig(config){}; + virtual ~Task() + { + if (taskHandle) { + vTaskDelete(taskHandle); + } }; - Task(TaskConfig config) : taskConfig(config){}; - virtual ~Task(){}; TaskHandle_t getHandle() const { return taskHandle; }; @@ -77,5 +70,15 @@ namespace SenseShift::FreeRTOS { log_e("Failed to create task %s", this->taskConfig.name); } }; + + private: + const TaskConfig& taskConfig; + TaskHandle_t taskHandle = nullptr; + + static void taskFunction(void* params) + { + _Tp* task = static_cast<_Tp*>(params); + task->run(); + } }; } // namespace SenseShift::FreeRTOS From bb73823f8a6d562888e9a12f9d9637a26a793d21 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 24 Aug 2023 14:52:58 +0400 Subject: [PATCH 20/82] ci(GitHub): easier build flag handling --- .github/scripts/get_firmware_name.sh | 45 +++++++++++++++++----------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/.github/scripts/get_firmware_name.sh b/.github/scripts/get_firmware_name.sh index d7c15d7a..63b0b610 100755 --- a/.github/scripts/get_firmware_name.sh +++ b/.github/scripts/get_firmware_name.sh @@ -32,6 +32,22 @@ getBhapticsName() { 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 @@ -43,27 +59,20 @@ getOpenGlovesName() { if [[ $flags =~ OPENGLOVES_COMM_SERIAL ]]; then echo "::debug::Serial is enabled, appending +serial to the target" target="$target+serial" - fi - - if [[ $flags =~ OPENGLOVES_COMM_BTSERIAL ]]; then + elif [[ $flags =~ OPENGLOVES_COMM_BTSERIAL ]]; then echo "::debug::Bluetooth Serial is enabled, appending +bluetooth to the target" target="$target+bluetooth" fi - if [[ $flags =~ CALIBRATION_CURL=::SenseShift::Calibration::MinMaxCalibrator ]]; then - echo "::debug::MinMaxCalibrator is enabled, appending +curl_minmax to the target" - target="$target+curl_minmaxcalib" - fi - - if [[ $flags =~ CALIBRATION_CURL=::SenseShift::Calibration::CenterPointDeviationCalibrator ]]; then - echo "::debug::CenterPointDeviationCalibrator is enabled, appending +curl_cpcalib to the target" - target="$target+curl_cpcalib" - fi + for flag in "${@:2}"; do + if [[ $flag =~ CALIBRATION_CURL ]]; then + target=$(handleCalibrationFlag "$target" "$flag" "curl_calib") + fi - if [[ $flags =~ CALIBRATION_CURL=::SenseShift::Calibration::FixedCenterPointDeviationCalibrator ]]; then - echo "::debug::FixedCenterPointDeviationCalibrator is enabled, appending +curl_fcpcalib to the target" - target="$target+curl_fcpcalib" - fi + if [[ $flag =~ CALIBRATION_SPLAY ]]; then + target=$(handleCalibrationFlag "$target" "$flag" "splay_calib") + fi + done echo "firmware=$target" if [[ -n "$GITHUB_ACTIONS" ]]; then @@ -77,9 +86,9 @@ getOpenGlovesName() { target=$1 echo "::debug::Target is $target" if [[ $target =~ ^(bhaptics) ]]; then - getBhapticsName $@ + getBhapticsName "${@}" elif [[ $target =~ ^(opengloves|lucidgloves|indexer) ]]; then - getOpenGlovesName $@ + getOpenGlovesName "${@}" else echo "::error::Unknown target $target" exit 1 From 854f5c532dba357f85170b2cdc2e03610a7d6338 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 29 Aug 2023 01:24:25 +0400 Subject: [PATCH 21/82] refactor(Input): use memoized sensor by default --- .../mode_configs/opengloves/opengloves.cpp | 6 +- .../arduino/input/sensor/analog.hpp | 10 +-- .../arduino/input/sensor/digital.hpp | 10 +-- lib/battery/senseshift/battery/sensor.hpp | 8 +- .../senseshift/freertos/battery.hpp | 4 +- lib/calibration/senseshift/calibration.hpp | 2 - lib/core/senseshift/interface.hpp | 11 +++ .../senseshift/freertos/input/sensor.hpp | 10 +-- lib/opengloves/og_protocol.hpp | 2 +- lib/opengloves/sensor/og_finger.hpp | 36 ++++----- lib/opengloves/sensor/og_gesture.hpp | 8 +- lib/opengloves/sensor/og_sensor.hpp | 4 +- lib/opengloves_task/opengloves_task.hpp | 2 +- lib/sensor/senseshift/input/sensor.hpp | 77 +++++++++---------- .../senseshift/input/sensor/joystick.hpp | 8 +- test/test_opengloves/main.cpp | 18 ++--- test/test_opengloves_finger/main.cpp | 18 ++--- test/test_sensor/main.cpp | 12 +-- 18 files changed, 126 insertions(+), 120 deletions(-) create mode 100644 lib/core/senseshift/interface.hpp diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 47d8e289..5af9b961 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -55,7 +55,7 @@ #define FINGER_PINKY_ENABLED (defined(PIN_FINGER_PINKY) && (PIN_FINGER_PINKY != -1)) #define FINGER_CLASS(type, curl_pin, curl_invert, curl_calib) \ FingerSensor( \ - new ::SenseShift::Input::CalibratedSensor<uint16_t>( \ + new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ new curl_calib() \ ), \ @@ -69,11 +69,11 @@ #define FINGER_PINKY_SPLAY (FINGER_PINKY_ENABLED && defined(PIN_FINGER_PINKY_SPLAY) && (PIN_FINGER_PINKY_SPLAY != -1)) #define FINGER_SPLAY_CLASS(type, curl_pin, curl_invert, curl_calib, splay_pin, splay_invert, splay_calib) \ FingerSensor( \ - new ::SenseShift::Input::CalibratedSensor<uint16_t>( \ + new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ new curl_calib() \ ), \ - new ::SenseShift::Input::CalibratedSensor<uint16_t>( \ + new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ new ::SenseShift::Arduino::Input::AnalogSensor<splay_invert>(splay_pin), \ new splay_calib() \ ), \ diff --git a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp index 4d1d5705..4dabd41b 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -6,26 +6,26 @@ namespace SenseShift::Arduino::Input { template<bool invert = false> - class AnalogSensor : public ::SenseShift::Input::ISensor<uint16_t> { + class AnalogSensor : public ::SenseShift::Input::ISimpleSensor<uint16_t> { private: uint8_t pin; public: AnalogSensor(uint8_t pin) : pin(pin) {} - void setup(void) { pinMode(this->pin, INPUT); }; + void init() override { pinMode(this->pin, INPUT); }; - uint16_t getValue(void) override; + uint16_t getValue() override; }; template<> - uint16_t AnalogSensor<false>::getValue(void) + uint16_t AnalogSensor<false>::getValue() { return analogRead(this->pin); } template<> - uint16_t AnalogSensor<true>::getValue(void) + uint16_t AnalogSensor<true>::getValue() { return ANALOG_MAX - analogRead(this->pin); } diff --git a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp index 16de1b6c..31b77bbf 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -5,7 +5,7 @@ #include <Arduino.h> namespace SenseShift::Arduino::Input { - typedef ::SenseShift::Input::ISensor<bool> IDigitalSensor; + typedef ::SenseShift::Input::ISimpleSensor<bool> IDigitalSensor; template<bool invert = false> class DigitalSensor : public IDigitalSensor { @@ -15,19 +15,19 @@ namespace SenseShift::Arduino::Input { public: DigitalSensor(uint8_t pin) : pin(pin) {} - void setup(void) { pinMode(this->pin, INPUT_PULLUP); }; + void init() override { pinMode(this->pin, INPUT_PULLUP); }; - bool getValue(void) override; + bool getValue() override; }; template<> - bool DigitalSensor<false>::getValue(void) + bool DigitalSensor<false>::getValue() { return digitalRead(this->pin) == LOW; } template<> - bool DigitalSensor<true>::getValue(void) + bool DigitalSensor<true>::getValue() { return digitalRead(this->pin) == HIGH; } diff --git a/lib/battery/senseshift/battery/sensor.hpp b/lib/battery/senseshift/battery/sensor.hpp index 0ae63ba3..5897564e 100644 --- a/lib/battery/senseshift/battery/sensor.hpp +++ b/lib/battery/senseshift/battery/sensor.hpp @@ -14,20 +14,20 @@ namespace SenseShift::Battery { /** * Abstract battery sensor */ - typedef ::SenseShift::Input::ISensor<BatteryState> IBatterySensor; + typedef ::SenseShift::Input::ISimpleSensor<BatteryState> IBatterySensor; class NaiveBatterySensor : public IBatterySensor { public: - NaiveBatterySensor(::SenseShift::Input::ISensor<uint16_t>* sensor) : sensor(sensor){}; + NaiveBatterySensor(::SenseShift::Input::ISimpleSensor<uint16_t>* sensor) : sensor(sensor){}; BatteryState getValue() override { return { .level = static_cast<uint8_t>(::SenseShift::simpleMap<uint16_t>(this->sensor->getValue(), 4095, 255)) }; }; - void setup() { this->sensor->setup(); } + void init() override { this->sensor->init(); } private: - ::SenseShift::Input::ISensor<uint16_t>* sensor; + ::SenseShift::Input::ISimpleSensor<uint16_t>* sensor; }; } // namespace SenseShift::Battery diff --git a/lib/battery_task/senseshift/freertos/battery.hpp b/lib/battery_task/senseshift/freertos/battery.hpp index 688459a2..8a1199fe 100644 --- a/lib/battery_task/senseshift/freertos/battery.hpp +++ b/lib/battery_task/senseshift/freertos/battery.hpp @@ -10,9 +10,9 @@ namespace SenseShift::FreeRTOS::Battery { ::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>(sensor), eventDispatcher(eventDispatcher){}; - void updateValue() override + void tick() override { - this->::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>::updateValue(); + this->::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>::tick(); this->eventDispatcher->postEvent(new ::SenseShift::Battery::BatteryLevelEvent(this->value)); } diff --git a/lib/calibration/senseshift/calibration.hpp b/lib/calibration/senseshift/calibration.hpp index 58c190c0..13a9834b 100644 --- a/lib/calibration/senseshift/calibration.hpp +++ b/lib/calibration/senseshift/calibration.hpp @@ -20,9 +20,7 @@ namespace SenseShift::Calibration { public: virtual void resetCalibration() = 0; - void enableCalibration() override { calibrate = true; } - void disableCalibration() override { calibrate = false; } }; diff --git a/lib/core/senseshift/interface.hpp b/lib/core/senseshift/interface.hpp new file mode 100644 index 00000000..af428cc6 --- /dev/null +++ b/lib/core/senseshift/interface.hpp @@ -0,0 +1,11 @@ +#pragma once + +namespace SenseShift { + struct IInitializable { + virtual void init() = 0; + }; + + struct ITickable { + virtual void tick() = 0; + }; +} // namespace SenseShift diff --git a/lib/freertos/senseshift/freertos/input/sensor.hpp b/lib/freertos/senseshift/freertos/input/sensor.hpp index b4b273b8..cf7a1f45 100644 --- a/lib/freertos/senseshift/freertos/input/sensor.hpp +++ b/lib/freertos/senseshift/freertos/input/sensor.hpp @@ -13,7 +13,7 @@ namespace SenseShift::FreeRTOS::Input { friend class Task<SensorUpdateTask>; private: - using Sensor_t = ::SenseShift::Input::IMemoizedSensor; + using Sensor_t = ::SenseShift::ITickable; public: SensorUpdateTask(Sensor_t* sensor, std::uint32_t updateDelay, TaskConfig taskConfig) : @@ -26,14 +26,14 @@ namespace SenseShift::FreeRTOS::Input { void run() { while (true) { - this->sensor->updateValue(); + this->sensor->tick(); ::delay(this->updateDelay); } } }; template<typename _Tp> - class TaskedSensor : public SensorUpdateTask, public ::SenseShift::Input::ISensor<_Tp> { + class TaskedSensor : public SensorUpdateTask, public ::SenseShift::Input::ISimpleSensor<_Tp> { friend class SensorUpdateTask; private: @@ -45,11 +45,11 @@ namespace SenseShift::FreeRTOS::Input { void begin() override { - this->setup(); + this->init(); SensorUpdateTask::begin(); }; - void setup() override { this->sensor->setup(); }; + void init() override { this->sensor->init(); }; _Tp getValue() override { return this->sensor->getValue(); }; diff --git a/lib/opengloves/og_protocol.hpp b/lib/opengloves/og_protocol.hpp index 9c92e98f..0e863109 100644 --- a/lib/opengloves/og_protocol.hpp +++ b/lib/opengloves/og_protocol.hpp @@ -45,7 +45,7 @@ namespace OpenGloves { public: IStringEncodedMemoizedSensor(Type type) : IStringEncoded(type){}; - virtual void setup() = 0; + virtual void init() = 0; virtual void updateValue() = 0; }; diff --git a/lib/opengloves/sensor/og_finger.hpp b/lib/opengloves/sensor/og_finger.hpp index 9b5193d3..1be50ec0 100644 --- a/lib/opengloves/sensor/og_finger.hpp +++ b/lib/opengloves/sensor/og_finger.hpp @@ -6,19 +6,19 @@ namespace OpenGloves { struct FingerSensors { - std::vector<SenseShift::Input::CalibratedSensor<uint16_t>*> curl = - std::vector<SenseShift::Input::CalibratedSensor<uint16_t>*>(); - std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay = std::nullopt; + std::vector<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> curl = + std::vector<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*>(); + std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay = std::nullopt; FingerSensors( - std::vector<SenseShift::Input::CalibratedSensor<uint16_t>*> curl, - std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay = std::nullopt + std::vector<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> curl, + std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay = std::nullopt ) : curl(curl), splay(splay){}; FingerSensors( - SenseShift::Input::CalibratedSensor<uint16_t>* curl1, - std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay = std::nullopt + SenseShift::Input::CalibratedSimpleSensor<uint16_t>* curl1, + std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay = std::nullopt ) : curl({ curl1 }), splay(splay){}; }; @@ -31,25 +31,25 @@ namespace OpenGloves { virtual uint16_t getCurl() = 0; }; - typedef SenseShift::Input::ISensor<FingerValue> IFingerSensor; + typedef SenseShift::Input::ISimpleSensor<FingerValue> IFingerSensor; class SimpleFingerSensor : public IFingerSensor, public ICurl { public: SimpleFingerSensor(FingerSensors sensors) : sensors(sensors){}; SimpleFingerSensor( - SenseShift::Input::CalibratedSensor<uint16_t>* curl1, - std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay = std::nullopt + SenseShift::Input::CalibratedSimpleSensor<uint16_t>* curl1, + std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay = std::nullopt ) : sensors(curl1, splay){}; - void setup() override + void init() override { for (auto sensor : sensors.curl) { - sensor->setup(); + sensor->init(); } if (sensors.splay.has_value()) { - sensors.splay.value()->setup(); + sensors.splay.value()->init(); } } @@ -82,8 +82,8 @@ namespace OpenGloves { CalibratedFingerSensor(FingerSensors sensors) : SimpleFingerSensor(sensors){}; CalibratedFingerSensor( - SenseShift::Input::CalibratedSensor<uint16_t>* curl1, - std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay = std::nullopt + SenseShift::Input::CalibratedSimpleSensor<uint16_t>* curl1, + std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay = std::nullopt ) : SimpleFingerSensor(curl1, splay){}; @@ -127,13 +127,13 @@ namespace OpenGloves { StringEncodedMemoizedSensor<FingerValue>(sensor, type){}; FingerSensor( - SenseShift::Input::CalibratedSensor<uint16_t>* curl1, - std::optional<SenseShift::Input::CalibratedSensor<uint16_t>*> splay, + SenseShift::Input::CalibratedSimpleSensor<uint16_t>* curl1, + std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay, IEncodedInput::Type type ) : StringEncodedMemoizedSensor<FingerValue>(new CalibratedFingerSensor(curl1, splay), type){}; - FingerSensor(SenseShift::Input::CalibratedSensor<uint16_t>* curl1, IEncodedInput::Type type) : + FingerSensor(SenseShift::Input::CalibratedSimpleSensor<uint16_t>* curl1, IEncodedInput::Type type) : StringEncodedMemoizedSensor<FingerValue>(new CalibratedFingerSensor(curl1, std::nullopt), type){}; void resetCalibration() override { static_cast<CalibratedFingerSensor*>(this->sensor)->resetCalibration(); } diff --git a/lib/opengloves/sensor/og_gesture.hpp b/lib/opengloves/sensor/og_gesture.hpp index 324cdb30..9bb0e375 100644 --- a/lib/opengloves/sensor/og_gesture.hpp +++ b/lib/opengloves/sensor/og_gesture.hpp @@ -3,7 +3,7 @@ #include <sensor/og_finger.hpp> namespace OpenGloves { - class Gesture : public SenseShift::Input::ISensor<bool> {}; + class Gesture : public SenseShift::Input::ISimpleSensor<bool> {}; class GrabGesture : public Gesture { private: @@ -17,7 +17,7 @@ namespace OpenGloves { GrabGesture(ICurl& index, ICurl& middle, ICurl& ring, ICurl& pinky, uint16_t threshold) : index(index), middle(middle), ring(ring), pinky(pinky), threshold(threshold){}; - void setup() override{}; + void init() override{}; bool getValue() override { @@ -34,7 +34,7 @@ namespace OpenGloves { public: TriggerGesture(ICurl& index, uint16_t threshold) : index(index), threshold(threshold){}; - void setup() override{}; + void init() override{}; bool getValue() override { return this->index.getCurl() > this->threshold; } }; @@ -49,7 +49,7 @@ namespace OpenGloves { PinchGesture(ICurl& index, ICurl& thumb, uint16_t threshold) : index(index), thumb(thumb), threshold(threshold){}; - void setup() override{}; + void init() override{}; bool getValue() override { diff --git a/lib/opengloves/sensor/og_sensor.hpp b/lib/opengloves/sensor/og_sensor.hpp index 9fdd4a71..42c722de 100644 --- a/lib/opengloves/sensor/og_sensor.hpp +++ b/lib/opengloves/sensor/og_sensor.hpp @@ -30,10 +30,10 @@ namespace OpenGloves { public IStringEncodedMemoizedSensor, public SenseShift::Input::MemoizedSensor<_Tp> { public: - StringEncodedMemoizedSensor(SenseShift::Input::ISensor<_Tp>* sensor, IEncodedInput::Type type) : + StringEncodedMemoizedSensor(SenseShift::Input::ISimpleSensor<_Tp>* sensor, IEncodedInput::Type type) : IStringEncodedMemoizedSensor(type), SenseShift::Input::MemoizedSensor<_Tp>(sensor){}; - void setup() override { this->sensor->setup(); } + void init() override { this->sensor->init(); } void updateValue() override { this->value = this->sensor->getValue(); } diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index 8fab0ec0..630d6d8a 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -160,7 +160,7 @@ namespace OpenGloves { log_d("There is a total of %d sensors", this->allSensors.size()); for (auto* input : this->allSensors) { log_d("Setting up sensor: %c", input->getType()); - input->setup(); + input->init(); } // Start calibration if no calibration button is present or if configured to always calibrate. diff --git a/lib/sensor/senseshift/input/sensor.hpp b/lib/sensor/senseshift/input/sensor.hpp index 8de2a7bb..a4f5e160 100644 --- a/lib/sensor/senseshift/input/sensor.hpp +++ b/lib/sensor/senseshift/input/sensor.hpp @@ -3,6 +3,7 @@ #include <type_traits> #include <senseshift/calibration.hpp> +#include <senseshift/interface.hpp> #include <senseshift/logging.hpp> #if defined(__AVR__) @@ -22,93 +23,89 @@ namespace SenseShift::Input { * @tparam _Tp Type of the sensor value */ template<typename _Tp> - class ISensor { - public: - /** - * Setup the sensor hardware - */ - virtual void setup() = 0; + struct ISimpleSensor : public virtual IInitializable { + using ValueType = _Tp; /** * Get the current sensor value */ - virtual _Tp getValue() = 0; + virtual ValueType getValue() = 0; }; - class IMemoizedSensor { - public: - /** - * Update the memoized value - */ - virtual void updateValue() = 0; - }; + template<typename _Tp> + struct ISensor : public virtual ISimpleSensor<_Tp>, ITickable {}; /** * Memoized sensor decorator * @tparam _Tp Type of the sensor value */ template<typename _Tp> - class MemoizedSensor : public ISensor<_Tp>, public virtual IMemoizedSensor { + class MemoizedSensor : public ISensor<_Tp> { protected: - ISensor<_Tp>* sensor; + ISimpleSensor<_Tp>* sensor; _Tp value; public: /** * @param sensor Sensor to be decorated */ - MemoizedSensor(ISensor<_Tp>* sensor) : sensor(sensor){}; + MemoizedSensor(ISimpleSensor<_Tp>* sensor) : sensor(sensor){}; /** * Setup the sensor hardware */ - void setup() override { this->sensor->setup(); }; + void init() override { this->sensor->init(); }; /** - * Get the current memoized value + * Read actual value from the hardware and memoize it */ - _Tp getValue() override { return this->value; }; + void tick() override { this->value = this->sensor->getValue(); }; /** - * Read actual value from the hardware and memoize it + * Get the current memoized value */ - void updateValue() { this->value = this->sensor->getValue(); }; + _Tp getValue() override { return this->value; }; }; + template<typename _Tp> + class ICalibratedSimpleSensor : public ISimpleSensor<_Tp>, public Calibration::ICalibrated {}; + /** * Calibrated sensor decorator * * @tparam _Tp Type of the sensor value */ template<typename _Tp> - class CalibratedSensor : public ISensor<_Tp>, public ::SenseShift::Calibration::Calibrated { + class CalibratedSimpleSensor : public ICalibratedSimpleSensor<_Tp> { + public: + /** + * @param sensor Sensor to be decorated + * @param calibrator ICalibrator algorithm to be used + */ + CalibratedSimpleSensor(ISimpleSensor<_Tp>* sensor, Calibration::ICalibrator<_Tp>* calibrator) : + sensor(sensor), calibrator(calibrator){}; + + void init() override { this->sensor->init(); }; + _Tp getValue() override { return this->getCalibratedValue(); }; + + void resetCalibration() override { this->calibrator->reset(); }; + void enableCalibration() override { calibrating = true; } + void disableCalibration() override { calibrating = false; } + protected: - ISensor<_Tp>* sensor; - ::SenseShift::Calibration::ICalibrator<_Tp>* calibrator; + ISimpleSensor<_Tp>* sensor; + Calibration::ICalibrator<_Tp>* calibrator; + bool calibrating = false; _Tp getCalibratedValue() { auto value = this->sensor->getValue(); - if (this->calibrate) { + if (this->calibrating) { this->calibrator->update(value); } return this->calibrator->calibrate(value); } - - public: - /** - * @param sensor Sensor to be decorated - * @param calibrator ICalibrator algorithm to be used - */ - CalibratedSensor(ISensor<_Tp>* sensor, ::SenseShift::Calibration::ICalibrator<_Tp>* calibrator) : - sensor(sensor), calibrator(calibrator){}; - - void setup() override { this->sensor->setup(); }; - - _Tp getValue() override { return this->getCalibratedValue(); }; - - void resetCalibration() override { this->calibrator->reset(); }; }; } // namespace SenseShift::Input diff --git a/lib/sensor/senseshift/input/sensor/joystick.hpp b/lib/sensor/senseshift/input/sensor/joystick.hpp index b9d28519..a03af6f7 100644 --- a/lib/sensor/senseshift/input/sensor/joystick.hpp +++ b/lib/sensor/senseshift/input/sensor/joystick.hpp @@ -7,9 +7,9 @@ namespace SenseShift::Input { * Joystick axis sensor decorator */ template<typename _Tp> - class JoystickAxisSensor : public ISensor<_Tp> { + class JoystickAxisSensor : public ISimpleSensor<_Tp> { private: - ISensor<_Tp>* sensor; + ISimpleSensor<_Tp>* sensor; float dead_zone; int filterDeadZone(int in) @@ -22,9 +22,9 @@ namespace SenseShift::Input { } public: - JoystickAxisSensor(ISensor<_Tp>* sensor, float dead_zone) : sensor(sensor), dead_zone(dead_zone){}; + JoystickAxisSensor(ISimpleSensor<_Tp>* sensor, float dead_zone) : sensor(sensor), dead_zone(dead_zone){}; - void setup(void) { this->sensor->setup(); }; + void init() override { this->sensor->init(); }; uint16_t getValue(void) override { diff --git a/test/test_opengloves/main.cpp b/test/test_opengloves/main.cpp index c711cdc1..7f607d6f 100644 --- a/test/test_opengloves/main.cpp +++ b/test/test_opengloves/main.cpp @@ -3,34 +3,34 @@ using namespace OpenGloves; -class TestAnalogSensor : public SenseShift::Input::ISensor<uint16_t> { +class TestAnalogSensor : public SenseShift::Input::ISimpleSensor<uint16_t> { private: uint16_t count = 0; public: int setupCounter = 0; - void setup() override { this->setupCounter++; }; + void init() override { this->setupCounter++; }; uint16_t getValue() override { return ++this->count; }; }; -class TestBinarySensor : public SenseShift::Input::ISensor<bool> { +class TestBinarySensor : public SenseShift::Input::ISimpleSensor<bool> { public: bool value = false; int setupCounter = 0; - void setup() override { this->setupCounter++; }; + void init() override { this->setupCounter++; }; bool getValue() override { return this->value; }; }; -class TestFingerSensor : public SenseShift::Input::ISensor<FingerValue> { +class TestFingerSensor : public SenseShift::Input::ISimpleSensor<FingerValue> { public: FingerValue value; int setupCounter = 0; - void setup() override { this->setupCounter++; }; + void init() override { this->setupCounter++; }; FingerValue getValue() override { return this->value; }; }; @@ -41,7 +41,7 @@ void test_string_encoded_sensor_uint16(void) auto sensor = new StringEncodedMemoizedSensor<uint16_t>(inner, IEncodedInput::Type::INDEX); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->setup(); + sensor->init(); TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); TEST_ASSERT_EQUAL_INT(0, sensor->getValue()); @@ -63,7 +63,7 @@ void test_string_encoded_sensor_bool(void) auto sensor = new StringEncodedMemoizedSensor<bool>(inner, IEncodedInput::Type::A_BTN); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->setup(); + sensor->init(); TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); TEST_ASSERT_FALSE(sensor->getValue()); @@ -94,7 +94,7 @@ void test_string_encoded_sensor_fingervalue(void) auto sensor = new StringEncodedMemoizedSensor<FingerValue>(inner, IEncodedInput::Type::THUMB); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->setup(); + sensor->init(); TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); // curl-only diff --git a/test/test_opengloves_finger/main.cpp b/test/test_opengloves_finger/main.cpp index ee063582..569bcda8 100644 --- a/test/test_opengloves_finger/main.cpp +++ b/test/test_opengloves_finger/main.cpp @@ -4,14 +4,14 @@ using namespace OpenGloves; using namespace SenseShift::Calibration; -class TestAnalogSensor : public SenseShift::Input::ISensor<uint16_t> { +class TestAnalogSensor : public SenseShift::Input::ISimpleSensor<uint16_t> { private: uint16_t count = 0; public: int setupCounter = 0; - void setup() override { this->setupCounter++; }; + void init() override { this->setupCounter++; }; uint16_t getValue() override { return this->count++; }; }; @@ -34,11 +34,11 @@ void test_simple_finger_sensor_curl(void) { auto* inner = new TestAnalogSensor(); auto* calibrator = new DummyCalibrator(); - auto* calibrated = new SenseShift::Input::CalibratedSensor<uint16_t>(inner, calibrator); + auto* calibrated = new SenseShift::Input::CalibratedSimpleSensor<uint16_t>(inner, calibrator); auto* sensor = new SimpleFingerSensor(calibrated); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->setup(); + sensor->init(); TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); // since the sensor is not memoized, the value is updated on every call @@ -60,17 +60,17 @@ void test_simple_finger_sensor_curl_flex(void) { auto* inner_curl = new TestAnalogSensor(); auto* calibrator_curl = new DummyCalibrator(); - auto* calibrated_curl = new SenseShift::Input::CalibratedSensor<uint16_t>(inner_curl, calibrator_curl); + auto* calibrated_curl = new SenseShift::Input::CalibratedSimpleSensor<uint16_t>(inner_curl, calibrator_curl); auto* inner_flex = new TestAnalogSensor(); auto* calibrator_flex = new DummyCalibrator(); - auto* calibrated_flex = new SenseShift::Input::CalibratedSensor<uint16_t>(inner_flex, calibrator_flex); + auto* calibrated_flex = new SenseShift::Input::CalibratedSimpleSensor<uint16_t>(inner_flex, calibrator_flex); auto* sensor = new SimpleFingerSensor(calibrated_curl, calibrated_flex); TEST_ASSERT_EQUAL_INT(0, inner_curl->setupCounter); TEST_ASSERT_EQUAL_INT(0, inner_flex->setupCounter); - sensor->setup(); + sensor->init(); TEST_ASSERT_EQUAL_INT(1, inner_curl->setupCounter); TEST_ASSERT_EQUAL_INT(1, inner_flex->setupCounter); @@ -100,11 +100,11 @@ void test_finger_sensor_curl(void) { auto* inner = new TestAnalogSensor(); auto* calibrator = new DummyCalibrator(); - auto* calibrated = new SenseShift::Input::CalibratedSensor<uint16_t>(inner, calibrator); + auto* calibrated = new SenseShift::Input::CalibratedSimpleSensor<uint16_t>(inner, calibrator); auto* sensor = new FingerSensor(calibrated, IEncodedInput::Type::INDEX); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->setup(); + sensor->init(); TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); TEST_ASSERT_EQUAL_INT(0, sensor->getValue().curl[0]); diff --git a/test/test_sensor/main.cpp b/test/test_sensor/main.cpp index f9cbcea0..c0b75acb 100644 --- a/test/test_sensor/main.cpp +++ b/test/test_sensor/main.cpp @@ -4,14 +4,14 @@ using namespace SenseShift::Input; using namespace SenseShift::Calibration; -class TestAnalogSensor : public ISensor<int> { +class TestAnalogSensor : public ISimpleSensor<int> { private: int count = 0; public: int setupCounter = 0; - void setup() override { this->setupCounter++; }; + void init() override { this->setupCounter++; }; int getValue() override { return ++this->count; }; }; @@ -22,13 +22,13 @@ void test_memoized_sensor(void) auto sensor = new MemoizedSensor<int>(inner); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->setup(); + sensor->init(); TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); TEST_ASSERT_EQUAL_INT(0, sensor->getValue()); TEST_ASSERT_EQUAL_INT(0, sensor->getValue()); - sensor->updateValue(); + sensor->tick(); TEST_ASSERT_EQUAL_INT(1, sensor->getValue()); TEST_ASSERT_EQUAL_INT(1, sensor->getValue()); @@ -52,10 +52,10 @@ void test_calibrated_sensor(void) { auto inner = new TestAnalogSensor(); auto calibrator = new DummyCalibrator(); - auto sensor = new CalibratedSensor<int>(inner, calibrator); + auto sensor = new CalibratedSimpleSensor<int>(inner, calibrator); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->setup(); + sensor->init(); TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); calibrator->update(-1); From 985e4c01f69a4ef8f65815de7f770205c0132465 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Wed, 30 Aug 2023 19:42:26 +0400 Subject: [PATCH 22/82] refactor: use advanced PlatformIO LDF --- examples/bhaptics-ble-bt-serial.cpp | 2 +- firmware/mode_configs/bhaptics/tactal.cpp | 7 ++-- firmware/mode_configs/bhaptics/tactglove.cpp | 17 +++++----- firmware/mode_configs/bhaptics/tactosy2.cpp | 9 +++--- firmware/mode_configs/bhaptics/tactosyf.cpp | 11 +++---- firmware/mode_configs/bhaptics/tactosyh.cpp | 11 +++---- .../mode_configs/bhaptics/tactsuit_x16.cpp | 13 ++++---- .../bhaptics/tactsuit_x16_pca9685.cpp | 13 ++++---- .../mode_configs/bhaptics/tactsuit_x40.cpp | 27 ++++++++-------- firmware/mode_configs/bhaptics/tactvisor.cpp | 7 ++-- .../mode_configs/opengloves/opengloves.cpp | 12 +++---- lib/arduino/library.json | 13 ++++++++ .../senseshift/arduino/battery/ina219.hpp | 3 +- .../senseshift/arduino/battery/max17048.hpp | 4 +-- .../arduino/output/actuator}/pca9685.hpp | 4 +-- .../arduino/output/{ => actuator}/pwm.hpp | 4 +-- .../arduino/output/{ => actuator}/servo.hpp | 4 +-- lib/battery/senseshift/battery/sensor.hpp | 16 ++++++++++ .../senseshift/freertos/battery.hpp | 22 ------------- lib/bhaptics_ble/library.json | 10 ++++++ lib/core/senseshift/events.hpp | 4 +++ lib/core/senseshift/logging.hpp | 2 ++ .../senseshift/input/sensor.hpp | 0 .../senseshift/input/sensor/joystick.hpp | 0 .../senseshift/output/actuator.hpp | 0 .../senseshift/calibration.hpp | 0 .../senseshift/container.hpp} | 32 +++++++------------ lib/util/senseshift/range.hpp | 30 +++++++++++++++++ lib/util/senseshift/utility.hpp | 8 +++++ platformio.ini | 13 +------- test/{test_sensor => test_io_sensor}/main.cpp | 0 .../{test_core_utility => test_util}/main.cpp | 1 + .../main.cpp | 0 33 files changed, 166 insertions(+), 133 deletions(-) create mode 100644 lib/arduino/library.json rename lib/{ina219 => arduino}/senseshift/arduino/battery/ina219.hpp (92%) rename lib/{max17048 => arduino}/senseshift/arduino/battery/max17048.hpp (92%) rename lib/{pca9685/senseshift/arduino/output => arduino/senseshift/arduino/output/actuator}/pca9685.hpp (75%) rename lib/arduino/senseshift/arduino/output/{ => actuator}/pwm.hpp (86%) rename lib/arduino/senseshift/arduino/output/{ => actuator}/servo.hpp (87%) delete mode 100644 lib/battery_task/senseshift/freertos/battery.hpp create mode 100644 lib/bhaptics_ble/library.json rename lib/{sensor => io}/senseshift/input/sensor.hpp (100%) rename lib/{sensor => io}/senseshift/input/sensor/joystick.hpp (100%) rename lib/{actuators => io}/senseshift/output/actuator.hpp (100%) rename lib/{calibration => util}/senseshift/calibration.hpp (100%) rename lib/{core/senseshift/utility.hpp => util/senseshift/container.hpp} (54%) create mode 100644 lib/util/senseshift/range.hpp create mode 100644 lib/util/senseshift/utility.hpp rename test/{test_sensor => test_io_sensor}/main.cpp (100%) rename test/{test_core_utility => test_util}/main.cpp (99%) rename test/{test_calibration => test_util_calibration}/main.cpp (100%) diff --git a/examples/bhaptics-ble-bt-serial.cpp b/examples/bhaptics-ble-bt-serial.cpp index 68dd1482..3a532691 100644 --- a/examples/bhaptics-ble-bt-serial.cpp +++ b/examples/bhaptics-ble-bt-serial.cpp @@ -34,7 +34,7 @@ void setupMode() // Configure PWM pins to their positions on the face auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<AbstractActuator>({ // clang-format off - {new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26), new PWMOutputWriter(27), new PWMOutputWriter(14)}, + {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 f19d9e7d..2c99a8fc 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -7,17 +7,16 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/arduino/output/actuator/pwm.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#include <senseshift/freertos/battery.hpp> +#include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Battery; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; @@ -34,7 +33,7 @@ void setupMode() // Configure PWM pins to their positions on the face const auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off - { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26), new PWMOutputWriter(27), new PWMOutputWriter(14) }, + { 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/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 8b123ef4..8d2138f6 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -7,18 +7,17 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/arduino/output/actuator/pwm.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#include <senseshift/freertos/battery.hpp> +#include <senseshift/freertos/input/sensor.hpp> #include <senseshift/utility.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Battery; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; @@ -40,12 +39,12 @@ void setupMode() addTactGloveActuators( app->getHapticBody(), handSide, - new PWMOutputWriter(32), // Thumb - new PWMOutputWriter(33), // Index - new PWMOutputWriter(25), // Middle - new PWMOutputWriter(26), // Ring - new PWMOutputWriter(27), // Little - new PWMOutputWriter(14) // Wrist + new ActuatorPWM(32), // Thumb + new ActuatorPWM(33), // Index + new ActuatorPWM(25), // Middle + new ActuatorPWM(26), // Ring + new ActuatorPWM(27), // Little + new ActuatorPWM(14) // Wrist ); app->getHapticBody()->setup(); diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index 682a349b..38743a78 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -7,17 +7,16 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/arduino/output/actuator/pwm.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#include <senseshift/freertos/battery.hpp> +#include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Battery; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; @@ -34,8 +33,8 @@ void setupMode() // Configure PWM pins to their positions on the forearm auto forearmOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off - { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25) }, - { new PWMOutputWriter(26), new PWMOutputWriter(27), new PWMOutputWriter(14) }, + { 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/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index 99b792fd..0dd2733f 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -7,17 +7,16 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/arduino/output/actuator/pwm.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#include <senseshift/freertos/battery.hpp> +#include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Battery; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; @@ -34,9 +33,9 @@ void setupMode() // Configure PWM pins to their positions on the feet auto footOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off - { new PWMOutputWriter(32) }, - { new PWMOutputWriter(33) }, - { new PWMOutputWriter(25) }, + { new ActuatorPWM(32) }, + { new ActuatorPWM(33) }, + { new ActuatorPWM(25) }, // clang-format on }); diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 0e3cc417..ae3de9da 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -7,17 +7,16 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/arduino/output/actuator/pwm.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#include <senseshift/freertos/battery.hpp> +#include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Battery; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; @@ -34,9 +33,9 @@ void setupMode() // Configure PWM pins to their positions on the hands auto handOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off - { new PWMOutputWriter(32) }, - { new PWMOutputWriter(33) }, - { new PWMOutputWriter(25) } + { new ActuatorPWM(32) }, + { new ActuatorPWM(33) }, + { new ActuatorPWM(25) } // clang-format on }); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 8bc88899..88b46536 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -7,17 +7,16 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/arduino/output/actuator/pwm.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#include <senseshift/freertos/battery.hpp> +#include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Battery; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; @@ -38,14 +37,14 @@ void setupMode() // Configure PWM pins to their positions on the vest auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off - { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26) }, - { new PWMOutputWriter(27), new PWMOutputWriter(14), new PWMOutputWriter(12), new PWMOutputWriter(13) }, + { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25), new ActuatorPWM(26) }, + { new ActuatorPWM(27), new ActuatorPWM(14), new ActuatorPWM(12), new ActuatorPWM(13) }, // clang-format on }); auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off - { new PWMOutputWriter(19), new PWMOutputWriter(18), new PWMOutputWriter(5), new PWMOutputWriter(17) }, - { new PWMOutputWriter(16), new PWMOutputWriter(4), new PWMOutputWriter(2), new PWMOutputWriter(15) }, + { new ActuatorPWM(19), new ActuatorPWM(18), new ActuatorPWM(5), new ActuatorPWM(17) }, + { new ActuatorPWM(16), new ActuatorPWM(4), new ActuatorPWM(2), new ActuatorPWM(15) }, // clang-format on }); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index f7a9b099..6782ecee 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -7,17 +7,16 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/pca9685.hpp> +#include <senseshift/arduino/output/actuator/pca9685.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#include <senseshift/freertos/battery.hpp> +#include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Battery; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; @@ -43,14 +42,14 @@ void setupMode() // Assign the pins on the configured PCA9685 to positions on the vest auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off - { new PCA9685OutputWriter(pwm, 0), new PCA9685OutputWriter(pwm, 1), new PCA9685OutputWriter(pwm, 2), new PCA9685OutputWriter(pwm, 3) }, - { new PCA9685OutputWriter(pwm, 4), new PCA9685OutputWriter(pwm, 5), new PCA9685OutputWriter(pwm, 6), new PCA9685OutputWriter(pwm, 7) }, + { new ActuatorPCA9685(pwm, 0), new ActuatorPCA9685(pwm, 1), new ActuatorPCA9685(pwm, 2), new ActuatorPCA9685(pwm, 3) }, + { new ActuatorPCA9685(pwm, 4), new ActuatorPCA9685(pwm, 5), new ActuatorPCA9685(pwm, 6), new ActuatorPCA9685(pwm, 7) }, // clang-format on }); auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off - { new PCA9685OutputWriter(pwm, 8), new PCA9685OutputWriter(pwm, 9), new PCA9685OutputWriter(pwm, 10), new PCA9685OutputWriter(pwm, 11) }, - { new PCA9685OutputWriter(pwm, 12), new PCA9685OutputWriter(pwm, 13), new PCA9685OutputWriter(pwm, 14), new PCA9685OutputWriter(pwm, 15) }, + { new ActuatorPCA9685(pwm, 8), new ActuatorPCA9685(pwm, 9), new ActuatorPCA9685(pwm, 10), new ActuatorPCA9685(pwm, 11) }, + { new ActuatorPCA9685(pwm, 12), new ActuatorPCA9685(pwm, 13), new ActuatorPCA9685(pwm, 14), new ActuatorPCA9685(pwm, 15) }, // clang-format on }); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index e8668bcf..318e6ef6 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -7,18 +7,17 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/pca9685.hpp> -#include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/arduino/output/actuator/pca9685.hpp> +#include <senseshift/arduino/output/actuator/pwm.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#include <senseshift/freertos/battery.hpp> +#include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Battery; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; @@ -45,20 +44,20 @@ void setupMode() // vest auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off - { new PCA9685OutputWriter(pwm0, 0), new PCA9685OutputWriter(pwm0, 1), new PCA9685OutputWriter(pwm0, 2), new PCA9685OutputWriter(pwm0, 3) }, - { new PCA9685OutputWriter(pwm0, 4), new PCA9685OutputWriter(pwm0, 5), new PCA9685OutputWriter(pwm0, 6), new PCA9685OutputWriter(pwm0, 7) }, - { new PCA9685OutputWriter(pwm0, 8), new PCA9685OutputWriter(pwm0, 9), new PCA9685OutputWriter(pwm0, 10), new PCA9685OutputWriter(pwm0, 11) }, - { new PCA9685OutputWriter(pwm0, 12), new PCA9685OutputWriter(pwm0, 13), new PCA9685OutputWriter(pwm0, 14), new PCA9685OutputWriter(pwm0, 15) }, - { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26) }, + { new ActuatorPCA9685(pwm0, 0), new ActuatorPCA9685(pwm0, 1), new ActuatorPCA9685(pwm0, 2), new ActuatorPCA9685(pwm0, 3) }, + { new ActuatorPCA9685(pwm0, 4), new ActuatorPCA9685(pwm0, 5), new ActuatorPCA9685(pwm0, 6), new ActuatorPCA9685(pwm0, 7) }, + { new ActuatorPCA9685(pwm0, 8), new ActuatorPCA9685(pwm0, 9), new ActuatorPCA9685(pwm0, 10), new ActuatorPCA9685(pwm0, 11) }, + { new ActuatorPCA9685(pwm0, 12), new ActuatorPCA9685(pwm0, 13), new ActuatorPCA9685(pwm0, 14), new ActuatorPCA9685(pwm0, 15) }, + { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25), new ActuatorPWM(26) }, // clang-format on }); auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off - { new PCA9685OutputWriter(pwm1, 0), new PCA9685OutputWriter(pwm1, 1), new PCA9685OutputWriter(pwm1, 2), new PCA9685OutputWriter(pwm1, 3) }, - { new PCA9685OutputWriter(pwm1, 4), new PCA9685OutputWriter(pwm1, 5), new PCA9685OutputWriter(pwm1, 6), new PCA9685OutputWriter(pwm1, 7) }, - { new PCA9685OutputWriter(pwm1, 8), new PCA9685OutputWriter(pwm1, 9), new PCA9685OutputWriter(pwm1, 10), new PCA9685OutputWriter(pwm1, 11) }, - { new PCA9685OutputWriter(pwm1, 12), new PCA9685OutputWriter(pwm1, 13), new PCA9685OutputWriter(pwm1, 14), new PCA9685OutputWriter(pwm1, 15) }, - { new PWMOutputWriter(27), new PWMOutputWriter(14), new PWMOutputWriter(12), new PWMOutputWriter(13) }, + { new ActuatorPCA9685(pwm1, 0), new ActuatorPCA9685(pwm1, 1), new ActuatorPCA9685(pwm1, 2), new ActuatorPCA9685(pwm1, 3) }, + { new ActuatorPCA9685(pwm1, 4), new ActuatorPCA9685(pwm1, 5), new ActuatorPCA9685(pwm1, 6), new ActuatorPCA9685(pwm1, 7) }, + { new ActuatorPCA9685(pwm1, 8), new ActuatorPCA9685(pwm1, 9), new ActuatorPCA9685(pwm1, 10), new ActuatorPCA9685(pwm1, 11) }, + { new ActuatorPCA9685(pwm1, 12), new ActuatorPCA9685(pwm1, 13), new ActuatorPCA9685(pwm1, 14), new ActuatorPCA9685(pwm1, 15) }, + { new ActuatorPWM(27), new ActuatorPWM(14), new ActuatorPWM(12), new ActuatorPWM(13) }, // clang-format on }); diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index 68cd1188..758ab9aa 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -7,17 +7,16 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/pwm.hpp> +#include <senseshift/arduino/output/actuator/pwm.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> -#include <senseshift/freertos/battery.hpp> +#include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Battery; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::BH; @@ -34,7 +33,7 @@ void setupMode() // Configure PWM pins to their positions on the face auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ // clang-format off - { new PWMOutputWriter(32), new PWMOutputWriter(33), new PWMOutputWriter(25), new PWMOutputWriter(26) }, + { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25), new ActuatorPWM(26) }, // clang-format on }); diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 5af9b961..c58e221c 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -3,7 +3,7 @@ #include <opengloves_task.hpp> #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/input/sensor/digital.hpp> -#include <senseshift/arduino/output/servo.hpp> +#include <senseshift/arduino/output/actuator/servo.hpp> #include <senseshift/calibration.hpp> #include <senseshift/input/sensor.hpp> #include <senseshift/input/sensor/joystick.hpp> @@ -298,23 +298,23 @@ OpenGlovesTrackingTask* trackingTask; #if FFB_ENABLED HandActuators handActuators = { #if FFB_THUMB_ENABLED - .thumb = new SenseShift::Arduino::Output::ServoActuator(PIN_FFB_THUMB), + .thumb = new SenseShift::Arduino::Output::ActuatorServo(PIN_FFB_THUMB), #endif #if FFB_INDEX_ENABLED - .index = new SenseShift::Arduino::Output::ServoActuator(PIN_FFB_INDEX), + .index = new SenseShift::Arduino::Output::ActuatorServo(PIN_FFB_INDEX), #endif #if FFB_MIDDLE_ENABLED - .middle = new SenseShift::Arduino::Output::ServoActuator(PIN_FFB_MIDDLE), + .middle = new SenseShift::Arduino::Output::ActuatorServo(PIN_FFB_MIDDLE), #endif #if FFB_RING_ENABLED - .ring = new SenseShift::Arduino::Output::ServoActuator(PIN_FFB_RING), + .ring = new SenseShift::Arduino::Output::ActuatorServo(PIN_FFB_RING), #endif #if FFB_PINKY_ENABLED - .pinky = new SenseShift::Arduino::Output::ServoActuator(PIN_FFB_PINKY), + .pinky = new SenseShift::Arduino::Output::ActuatorServo(PIN_FFB_PINKY), #endif }; OpenGlovesForceFeedbackTask* ffbTask; diff --git a/lib/arduino/library.json b/lib/arduino/library.json new file mode 100644 index 00000000..8601c003 --- /dev/null +++ b/lib/arduino/library.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", + "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": "^0.13.0" + } +} diff --git a/lib/ina219/senseshift/arduino/battery/ina219.hpp b/lib/arduino/senseshift/arduino/battery/ina219.hpp similarity index 92% rename from lib/ina219/senseshift/arduino/battery/ina219.hpp rename to lib/arduino/senseshift/arduino/battery/ina219.hpp index ec2dea00..a343488d 100644 --- a/lib/ina219/senseshift/arduino/battery/ina219.hpp +++ b/lib/arduino/senseshift/arduino/battery/ina219.hpp @@ -13,7 +13,8 @@ namespace SenseShift::Arduino::Battery { public: INA219_Battery(Adafruit_INA219* sensor) : sensor(sensor){}; - void setup() override { this->active = this->sensor->begin(); } + void init() override { this->active = this->sensor->begin(); } + ::SenseShift::Battery::BatteryState getValue() override { if (!this->active) { diff --git a/lib/max17048/senseshift/arduino/battery/max17048.hpp b/lib/arduino/senseshift/arduino/battery/max17048.hpp similarity index 92% rename from lib/max17048/senseshift/arduino/battery/max17048.hpp rename to lib/arduino/senseshift/arduino/battery/max17048.hpp index c95c8e86..dc886cc2 100644 --- a/lib/max17048/senseshift/arduino/battery/max17048.hpp +++ b/lib/arduino/senseshift/arduino/battery/max17048.hpp @@ -13,7 +13,7 @@ namespace SenseShift::Arduino::Battery { * @see * https://github.com/sparkfun/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/blob/main/examples/Example1_Simple/Example1_Simple.ino */ - void setup() override + void init() override { // Set up the MAX17043 LiPo fuel gauge: this->active = this->gauge->begin(); @@ -35,7 +35,7 @@ namespace SenseShift::Arduino::Battery { return { 0 }; } - return { .level = this->gauge->getSOC() }; + return { .level = simpleMap(this->gauge->getSOC(), 1.0f, 255.0f) }; } private: diff --git a/lib/pca9685/senseshift/arduino/output/pca9685.hpp b/lib/arduino/senseshift/arduino/output/actuator/pca9685.hpp similarity index 75% rename from lib/pca9685/senseshift/arduino/output/pca9685.hpp rename to lib/arduino/senseshift/arduino/output/actuator/pca9685.hpp index aa8b4ce2..4d28f92d 100644 --- a/lib/pca9685/senseshift/arduino/output/pca9685.hpp +++ b/lib/arduino/senseshift/arduino/output/actuator/pca9685.hpp @@ -8,11 +8,11 @@ #include <Wire.h> namespace SenseShift::Arduino::Output { - class PCA9685OutputWriter : public ::SenseShift::Output::IActuator<std::uint16_t> { + class ActuatorPCA9685 : public ::SenseShift::Output::IActuator<std::uint16_t> { public: static inline constexpr const std::uint16_t MAX_INTENSITY = 4095; - PCA9685OutputWriter(Adafruit_PWMServoDriver* driver, const std::uint8_t num) : driver(driver), num(num){}; + ActuatorPCA9685(Adafruit_PWMServoDriver* driver, const std::uint8_t num) : driver(driver), num(num){}; void writeOutput(std::uint16_t intensity) override { diff --git a/lib/arduino/senseshift/arduino/output/pwm.hpp b/lib/arduino/senseshift/arduino/output/actuator/pwm.hpp similarity index 86% rename from lib/arduino/senseshift/arduino/output/pwm.hpp rename to lib/arduino/senseshift/arduino/output/actuator/pwm.hpp index 50605e5b..5f2a595e 100644 --- a/lib/arduino/senseshift/arduino/output/pwm.hpp +++ b/lib/arduino/senseshift/arduino/output/actuator/pwm.hpp @@ -6,11 +6,11 @@ #include <Arduino.h> namespace SenseShift::Arduino::Output { - class PWMOutputWriter : public ::SenseShift::Output::IActuator<std::uint16_t> { + class ActuatorPWM : public ::SenseShift::Output::IActuator<std::uint16_t> { public: static inline constexpr const std::uint16_t MAX_INTENSITY = 4095; - PWMOutputWriter(const std::uint8_t pin, const double freq = 60, const std::uint8_t resolution = 12) : + ActuatorPWM(const std::uint8_t pin, const double freq = 60, const std::uint8_t resolution = 12) : pin(pin), freq(freq), resolution(resolution){}; void setup() override diff --git a/lib/arduino/senseshift/arduino/output/servo.hpp b/lib/arduino/senseshift/arduino/output/actuator/servo.hpp similarity index 87% rename from lib/arduino/senseshift/arduino/output/servo.hpp rename to lib/arduino/senseshift/arduino/output/actuator/servo.hpp index 027c0b05..29bfa5e1 100644 --- a/lib/arduino/senseshift/arduino/output/servo.hpp +++ b/lib/arduino/senseshift/arduino/output/actuator/servo.hpp @@ -6,11 +6,11 @@ #include <ESP32Servo.h> namespace SenseShift::Arduino::Output { - class ServoActuator : public ::SenseShift::Output::IActuator<std::uint16_t> { + class ActuatorServo : public ::SenseShift::Output::IActuator<std::uint16_t> { public: static inline constexpr const std::uint16_t MAX_INTENSITY = 4095; - ServoActuator(const uint8_t pin, const std::uint16_t min = 500, const std::uint16_t max = 2400) : + ActuatorServo(const uint8_t pin, const std::uint16_t min = 500, const std::uint16_t max = 2400) : pin(pin), min(min), max(max){}; void setup() override diff --git a/lib/battery/senseshift/battery/sensor.hpp b/lib/battery/senseshift/battery/sensor.hpp index 5897564e..f2c2968a 100644 --- a/lib/battery/senseshift/battery/sensor.hpp +++ b/lib/battery/senseshift/battery/sensor.hpp @@ -30,4 +30,20 @@ namespace SenseShift::Battery { private: ::SenseShift::Input::ISimpleSensor<uint16_t>* sensor; }; + + class BatterySensor : public ::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState> { + public: + BatterySensor(::SenseShift::Battery::IBatterySensor* sensor, ::SenseShift::IEventDispatcher* eventDispatcher) : + ::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>(sensor), + eventDispatcher(eventDispatcher){}; + + void tick() override + { + this->::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>::tick(); + this->eventDispatcher->postEvent(new ::SenseShift::Battery::BatteryLevelEvent(this->value)); + } + + private: + ::SenseShift::IEventDispatcher* eventDispatcher; + }; } // namespace SenseShift::Battery diff --git a/lib/battery_task/senseshift/freertos/battery.hpp b/lib/battery_task/senseshift/freertos/battery.hpp deleted file mode 100644 index 8a1199fe..00000000 --- a/lib/battery_task/senseshift/freertos/battery.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include <senseshift/battery/sensor.hpp> -#include <senseshift/freertos/input/sensor.hpp> - -namespace SenseShift::FreeRTOS::Battery { - class BatterySensor : public ::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState> { - public: - BatterySensor(::SenseShift::Battery::IBatterySensor* sensor, ::SenseShift::IEventDispatcher* eventDispatcher) : - ::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>(sensor), - eventDispatcher(eventDispatcher){}; - - void tick() override - { - this->::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>::tick(); - this->eventDispatcher->postEvent(new ::SenseShift::Battery::BatteryLevelEvent(this->value)); - } - - private: - ::SenseShift::IEventDispatcher* eventDispatcher; - }; -} // namespace SenseShift::FreeRTOS::Battery diff --git a/lib/bhaptics_ble/library.json b/lib/bhaptics_ble/library.json new file mode 100644 index 00000000..7ab73cce --- /dev/null +++ b/lib/bhaptics_ble/library.json @@ -0,0 +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" + } +} diff --git a/lib/core/senseshift/events.hpp b/lib/core/senseshift/events.hpp index bf09ec22..f9f404f2 100644 --- a/lib/core/senseshift/events.hpp +++ b/lib/core/senseshift/events.hpp @@ -6,6 +6,10 @@ #define OH_EVENT_CONNECTED "connected" #define OH_EVENT_DISCONNECTED "disconnected" +// TODO: Use ETL +// https://www.etlcpp.com/observer.html +// https://www.etlcpp.com/messages.html + namespace SenseShift { enum Event { diff --git a/lib/core/senseshift/logging.hpp b/lib/core/senseshift/logging.hpp index d3cbc94b..9cf54f37 100644 --- a/lib/core/senseshift/logging.hpp +++ b/lib/core/senseshift/logging.hpp @@ -3,7 +3,9 @@ #if defined(ESP32) #include <esp32-hal-log.h> + #elif defined(UNITY_INCLUDE_PRINT_FORMATTED) + #define log_e(...) TEST_PRINTF(__VA_ARGS__) #define log_w(...) TEST_PRINTF(__VA_ARGS__) #define log_i(...) TEST_PRINTF(__VA_ARGS__) diff --git a/lib/sensor/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp similarity index 100% rename from lib/sensor/senseshift/input/sensor.hpp rename to lib/io/senseshift/input/sensor.hpp diff --git a/lib/sensor/senseshift/input/sensor/joystick.hpp b/lib/io/senseshift/input/sensor/joystick.hpp similarity index 100% rename from lib/sensor/senseshift/input/sensor/joystick.hpp rename to lib/io/senseshift/input/sensor/joystick.hpp diff --git a/lib/actuators/senseshift/output/actuator.hpp b/lib/io/senseshift/output/actuator.hpp similarity index 100% rename from lib/actuators/senseshift/output/actuator.hpp rename to lib/io/senseshift/output/actuator.hpp diff --git a/lib/calibration/senseshift/calibration.hpp b/lib/util/senseshift/calibration.hpp similarity index 100% rename from lib/calibration/senseshift/calibration.hpp rename to lib/util/senseshift/calibration.hpp diff --git a/lib/core/senseshift/utility.hpp b/lib/util/senseshift/container.hpp similarity index 54% rename from lib/core/senseshift/utility.hpp rename to lib/util/senseshift/container.hpp index 227748f4..7f0ab894 100644 --- a/lib/core/senseshift/utility.hpp +++ b/lib/util/senseshift/container.hpp @@ -2,7 +2,7 @@ #include <algorithm> #include <iterator> -#include <senseshift/logging.hpp> +#include <type_traits> namespace SenseShift { /** @@ -17,6 +17,12 @@ namespace SenseShift { return std::find(std::begin(c), std::end(c), val) != std::end(c); }; + template<> + inline bool contains<std::string&, char>(std::string& s, char val) + { + return s.find(val) != std::string::npos; + }; + template<typename _Tp> inline bool contains(_Tp* begin, _Tp* end, const _Tp& val) { @@ -26,26 +32,10 @@ namespace SenseShift { template<typename _Tp> constexpr inline bool contains(const _Tp* arr, const std::size_t size, const _Tp& val) { + static_assert( + std::is_same<_Tp, typename std::iterator_traits<_Tp*>::value_type>::value, + "Container and value must be of the same type" + ); return std::find(arr, arr + size, val) != arr + size; }; - - template<typename _Tp> - constexpr _Tp accurateMap(_Tp x, _Tp in_min, _Tp in_max, _Tp out_min, _Tp out_max) - { - const _Tp run = in_max - in_min; - if (run == 0) { - log_e("map(): Invalid input range, min == max"); - return (out_min + out_max) / 2; - } - const _Tp rise = out_max - out_min; - const _Tp delta = x - in_min; - return (delta * rise) / run + out_min; - } - - // Same as the above, but both mins are 0. - template<typename _Tp> - constexpr inline _Tp simpleMap(_Tp x, _Tp in_max, _Tp out_max) - { - return x * out_max / in_max; - } } // namespace SenseShift diff --git a/lib/util/senseshift/range.hpp b/lib/util/senseshift/range.hpp new file mode 100644 index 00000000..ea563482 --- /dev/null +++ b/lib/util/senseshift/range.hpp @@ -0,0 +1,30 @@ +#include <cstdint> +#include <type_traits> + +#include <senseshift/logging.hpp> + +namespace SenseShift { + template<typename _Tp> + constexpr _Tp accurateMap(_Tp x, _Tp in_min, _Tp in_max, _Tp out_min, _Tp out_max) + { + static_assert(std::is_arithmetic<_Tp>::value, "Type must be arithmetic"); + + const _Tp run = in_max - in_min; + if (run == 0) { + log_e("map(): Invalid input range, min == max"); + return (out_min + out_max) / 2; + } + const _Tp rise = out_max - out_min; + const _Tp delta = x - in_min; + return (delta * rise) / run + out_min; + } + + // Same as the above, but both mins are 0. + template<typename _Tp> + constexpr inline _Tp simpleMap(_Tp x, _Tp in_max, _Tp out_max) + { + static_assert(std::is_arithmetic<_Tp>::value, "Type must be arithmetic"); + + return x * out_max / in_max; + } +} // namespace SenseShift diff --git a/lib/util/senseshift/utility.hpp b/lib/util/senseshift/utility.hpp new file mode 100644 index 00000000..5c95fd01 --- /dev/null +++ b/lib/util/senseshift/utility.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include <algorithm> +#include <iterator> +#include <type_traits> + +#include "senseshift/container.hpp" +#include "senseshift/range.hpp" diff --git a/platformio.ini b/platformio.ini index 1a6bb8c3..d2a48669 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,28 +34,17 @@ build_src_filter = -<mode_configs> lib_deps = - Wire - SPI - adafruit/Adafruit BusIO@^1.14.1 - 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 - h2zero/NimBLE-Arduino@^1.4.0 - madhephaestus/ESP32Servo @ ^0.13.0 [env] 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_flags = clangtidy: --config-file=./.clang-tidy --fix -check_src_filters = - +<firmware> - +<include> - +<lib> [env:native] platform = native diff --git a/test/test_sensor/main.cpp b/test/test_io_sensor/main.cpp similarity index 100% rename from test/test_sensor/main.cpp rename to test/test_io_sensor/main.cpp diff --git a/test/test_core_utility/main.cpp b/test/test_util/main.cpp similarity index 99% rename from test/test_core_utility/main.cpp rename to test/test_util/main.cpp index a468a49a..4be719ba 100644 --- a/test/test_core_utility/main.cpp +++ b/test/test_util/main.cpp @@ -76,6 +76,7 @@ int process(void) RUN_TEST(test_contains_container); RUN_TEST(test_contains_iterator); RUN_TEST(test_contains_string); + RUN_TEST(test_accurate_map); RUN_TEST(test_simple_map); diff --git a/test/test_calibration/main.cpp b/test/test_util_calibration/main.cpp similarity index 100% rename from test/test_calibration/main.cpp rename to test/test_util_calibration/main.cpp From f1dd8cca1e73b02cbd5d17db0ea5d573c707463e Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 24 Aug 2023 17:24:20 +0400 Subject: [PATCH 23/82] refactor(Haptics): move into `SenseShift` dir/namespace --- include/senseshift.h | 2 +- .../senseshift/arduino/components/serial_plotter.hpp | 2 +- lib/bhaptics/senseshift/bh/devices.hpp | 2 +- lib/bhaptics/senseshift/bh/encoding.hpp | 2 +- lib/bhaptics_ble/senseshift/bh/ble/connection.cpp | 2 +- lib/hands/hand_interface.hpp | 2 +- .../body/haptics/body.cpp} | 2 +- .../body/haptics/body.hpp} | 4 ++-- .../body/haptics/interface.hpp} | 12 ++++++------ .../body/haptics/plane.cpp} | 4 +--- .../body/haptics/plane.hpp} | 2 +- test/test_haptics_body/main.cpp | 2 +- test/test_haptics_plane/main.cpp | 2 +- 13 files changed, 19 insertions(+), 21 deletions(-) rename lib/haptics/{haptic_body.cpp => senseshift/body/haptics/body.cpp} (95%) rename lib/haptics/{haptic_body.hpp => senseshift/body/haptics/body.hpp} (88%) rename lib/haptics/{haptics_interface.hpp => senseshift/body/haptics/interface.hpp} (88%) rename lib/haptics/{haptic_plane.cpp => senseshift/body/haptics/plane.cpp} (97%) rename lib/haptics/{haptic_plane.hpp => senseshift/body/haptics/plane.hpp} (98%) diff --git a/include/senseshift.h b/include/senseshift.h index c63f5659..95c5603e 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -2,8 +2,8 @@ #include "config/all.h" -#include <haptic_body.hpp> #include <senseshift/battery/sensor.hpp> +#include <senseshift/body/haptics/body.hpp> #include <senseshift/events.hpp> #include <vector> diff --git a/lib/arduino/senseshift/arduino/components/serial_plotter.hpp b/lib/arduino/senseshift/arduino/components/serial_plotter.hpp index 708111b6..2cc04d92 100644 --- a/lib/arduino/senseshift/arduino/components/serial_plotter.hpp +++ b/lib/arduino/senseshift/arduino/components/serial_plotter.hpp @@ -1,6 +1,6 @@ #pragma once -#include <haptic_body.hpp> +#include <senseshift/body/haptics/body.hpp> #include <senseshift/freertos/task.hpp> #include <HardwareSerial.h> diff --git a/lib/bhaptics/senseshift/bh/devices.hpp b/lib/bhaptics/senseshift/bh/devices.hpp index 60cac07c..b78bbb9f 100644 --- a/lib/bhaptics/senseshift/bh/devices.hpp +++ b/lib/bhaptics/senseshift/bh/devices.hpp @@ -1,7 +1,7 @@ #pragma once #include <hand_interface.hpp> -#include <haptic_body.hpp> +#include <senseshift/body/haptics/body.hpp> #pragma region BH_DEVICE_TACTSUITX40 diff --git a/lib/bhaptics/senseshift/bh/encoding.hpp b/lib/bhaptics/senseshift/bh/encoding.hpp index e2500cd9..3b75f8f0 100644 --- a/lib/bhaptics/senseshift/bh/encoding.hpp +++ b/lib/bhaptics/senseshift/bh/encoding.hpp @@ -1,7 +1,7 @@ #pragma once #include <cstring> -#include <haptic_body.hpp> +#include <senseshift/body/haptics/body.hpp> namespace SenseShift::BH { class Decoder { diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp index 66c91204..48e11876 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -1,7 +1,7 @@ #include "senseshift/bh/ble/connection.hpp" -#include <haptic_body.hpp> #include <senseshift/bh/constants.hpp> +#include <senseshift/body/haptics/body.hpp> #include <senseshift/events.hpp> #include <Arduino.h> diff --git a/lib/hands/hand_interface.hpp b/lib/hands/hand_interface.hpp index ee079c5a..71249f0c 100644 --- a/lib/hands/hand_interface.hpp +++ b/lib/hands/hand_interface.hpp @@ -1,7 +1,7 @@ #pragma once #include <cstdint> -#include <haptics_interface.hpp> +#include <senseshift/body/haptics/interface.hpp> namespace SenseShift::Body { namespace Hands { diff --git a/lib/haptics/haptic_body.cpp b/lib/haptics/senseshift/body/haptics/body.cpp similarity index 95% rename from lib/haptics/haptic_body.cpp rename to lib/haptics/senseshift/body/haptics/body.cpp index ddde0702..ed97efd4 100644 --- a/lib/haptics/haptic_body.cpp +++ b/lib/haptics/senseshift/body/haptics/body.cpp @@ -1,4 +1,4 @@ -#include "haptic_body.hpp" +#include "senseshift/body/haptics/body.hpp" #include <senseshift/logging.hpp> diff --git a/lib/haptics/haptic_body.hpp b/lib/haptics/senseshift/body/haptics/body.hpp similarity index 88% rename from lib/haptics/haptic_body.hpp rename to lib/haptics/senseshift/body/haptics/body.hpp index d0e536cd..2b049c83 100644 --- a/lib/haptics/haptic_body.hpp +++ b/lib/haptics/senseshift/body/haptics/body.hpp @@ -1,7 +1,7 @@ #pragma once -#include "haptic_plane.hpp" -#include "haptics_interface.hpp" +#include "senseshift/body/haptics/interface.hpp" +#include "senseshift/body/haptics/plane.hpp" #include <senseshift/utility.hpp> diff --git a/lib/haptics/haptics_interface.hpp b/lib/haptics/senseshift/body/haptics/interface.hpp similarity index 88% rename from lib/haptics/haptics_interface.hpp rename to lib/haptics/senseshift/body/haptics/interface.hpp index 506f0928..4ab0df0e 100644 --- a/lib/haptics/haptics_interface.hpp +++ b/lib/haptics/senseshift/body/haptics/interface.hpp @@ -1,12 +1,12 @@ #pragma once -#include <stdint.h> +#include <cstdint> #include <variant> #include <senseshift/math/point2.hpp> namespace SenseShift::Body::Haptics { - typedef uint8_t EffectIntex_t; + typedef std::uint8_t EffectIntex_t; static const EffectIntex_t EFFECT_INVALID = 0xFF; typedef enum class Effect : EffectIntex_t { Invalid = EFFECT_INVALID, @@ -15,7 +15,7 @@ namespace SenseShift::Body::Haptics { // Thermal = 0x01, } Effect_t; - typedef uint8_t TargetIndex_t; + typedef std::uint8_t TargetIndex_t; static const TargetIndex_t TARGET_INVALID = 0xFF; typedef enum class Target : TargetIndex_t { Invalid = TARGET_INVALID, @@ -46,12 +46,12 @@ namespace SenseShift::Body::Haptics { // TODO: arms, legs, etc. } Target_t; - typedef uint8_t Coordinate_t; + typedef std::uint8_t Coordinate_t; typedef ::SenseShift::Math::Point2<Coordinate_t> Position_t; // Vibration intensity. typedef struct VibroEffectData { - using Intensity_t = uint16_t; + using Intensity_t = std::uint16_t; inline static const Intensity_t INTENSITY_MIN = 0; inline static const Intensity_t INTENSITY_MAX = 4095; @@ -61,7 +61,7 @@ namespace SenseShift::Body::Haptics { inline constexpr VibroEffectData(const Intensity_t intensity) : intensity(intensity) {} inline constexpr VibroEffectData(const VibroEffectData& other) = default; - inline constexpr operator uint16_t() const { return intensity; } + inline constexpr operator std::uint16_t() const { return intensity; } } VibroEffectData_t; // TODO: thermal, etc. diff --git a/lib/haptics/haptic_plane.cpp b/lib/haptics/senseshift/body/haptics/plane.cpp similarity index 97% rename from lib/haptics/haptic_plane.cpp rename to lib/haptics/senseshift/body/haptics/plane.cpp index 47af5ae6..21614dcc 100644 --- a/lib/haptics/haptic_plane.cpp +++ b/lib/haptics/senseshift/body/haptics/plane.cpp @@ -1,11 +1,9 @@ -#include "haptic_plane.hpp" +#include "senseshift/body/haptics/plane.hpp" #include <algorithm> #include <cmath> #include <senseshift/logging.hpp> -#include "haptic_plane.hpp" - namespace SenseShift::Body::Haptics { template<typename _Tp, typename _Ta> void ActuativePlane<_Tp, _Ta>::setActuators(const ActuatorMap_t& actuators) diff --git a/lib/haptics/haptic_plane.hpp b/lib/haptics/senseshift/body/haptics/plane.hpp similarity index 98% rename from lib/haptics/haptic_plane.hpp rename to lib/haptics/senseshift/body/haptics/plane.hpp index e382e01a..5c2cf7be 100644 --- a/lib/haptics/haptic_plane.hpp +++ b/lib/haptics/senseshift/body/haptics/plane.hpp @@ -1,6 +1,6 @@ #pragma once -#include "haptics_interface.hpp" +#include "senseshift/body/haptics/interface.hpp" #include <senseshift/output/actuator.hpp> #include <senseshift/utility.hpp> diff --git a/test/test_haptics_body/main.cpp b/test/test_haptics_body/main.cpp index 19c8c866..5abefa7d 100644 --- a/test/test_haptics_body/main.cpp +++ b/test/test_haptics_body/main.cpp @@ -1,4 +1,4 @@ -#include <haptic_body.hpp> +#include <senseshift/body/haptics/body.hpp> #include <unity.h> using namespace SenseShift::Body::Haptics; diff --git a/test/test_haptics_plane/main.cpp b/test/test_haptics_plane/main.cpp index 091ba1c3..0be53a48 100644 --- a/test/test_haptics_plane/main.cpp +++ b/test/test_haptics_plane/main.cpp @@ -1,4 +1,4 @@ -#include <haptic_plane.hpp> +#include <senseshift/body/haptics/plane.hpp> #include <unity.h> using namespace SenseShift::Body::Haptics; From ae5355e776251862ad98303ea154f8539ebd694e Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 27 Aug 2023 14:17:44 +0400 Subject: [PATCH 24/82] feat(OpenGloves): use Frozen for command mapping --- .github/workflows/ci.yml | 8 +++++++- .github/workflows/codeql-analysis.yml | 1 + .github/workflows/release.yml | 4 ++++ .gitmodules | 3 +++ docs/DEVELOPMENT.md | 7 +++++++ lib/frozen | 1 + lib/opengloves/og_alpha_encoding.cpp | 2 +- lib/opengloves/og_alpha_encoding.hpp | 16 ++++++++++------ lib/opengloves/og_protocol.hpp | 3 ++- 9 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 .gitmodules create mode 100644 docs/DEVELOPMENT.md create mode 160000 lib/frozen diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a0bf078..4ecc2720 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,6 +60,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: 'recursive' - name: Get firmware name id: firmware_name @@ -194,6 +196,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: 'recursive' - name: Get firmware name id: firmware_name @@ -298,6 +302,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: 'recursive' - name: Speedup package installation uses: abbbi/github-actions-tune@v1 @@ -382,7 +388,7 @@ jobs: ls -lahR ./build/lcov/ 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/*' -o ./build/lcov/lcov.info.cleaned + lcov --remove ./build/lcov/lcov.info '/usr/include/*' '*.platformio/*' '*/.pio/*' '*/tool-unity/*' '*/test/*' '*/MockArduino/*' '*/lib/frozen/*' -o ./build/lcov/lcov.info.cleaned - name: Generate HTML report run: genhtml -p $PWD -o ./build/coverage/ --demangle-cpp ./build/lcov/lcov.info.cleaned diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 74b3dd8d..ed8f6731 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -42,6 +42,7 @@ jobs: # 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. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e4e216ef..6eb7910a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,6 +39,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: 'recursive' - name: Get firmware name id: firmware_name @@ -134,6 +136,8 @@ jobs: - OPENGLOVES_COMMUNCATION=OPENGLOVES_COMM_BTSERIAL steps: - uses: actions/checkout@v3 + with: + submodules: 'recursive' - name: Get firmware name id: firmware_name diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..cd1f2794 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/frozen"] + path = lib/frozen + url = git@github.com:senseshift/frozen.git diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md new file mode 100644 index 00000000..e7d53aef --- /dev/null +++ b/docs/DEVELOPMENT.md @@ -0,0 +1,7 @@ +## Useful Scripts + +### 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 {} \; +``` diff --git a/lib/frozen b/lib/frozen new file mode 160000 index 00000000..eb113465 --- /dev/null +++ b/lib/frozen @@ -0,0 +1 @@ +Subproject commit eb113465791905f29384a9deac6650fc323f4d53 diff --git a/lib/opengloves/og_alpha_encoding.cpp b/lib/opengloves/og_alpha_encoding.cpp index ed30cbf4..da70fbe7 100644 --- a/lib/opengloves/og_alpha_encoding.cpp +++ b/lib/opengloves/og_alpha_encoding.cpp @@ -33,7 +33,7 @@ namespace OpenGloves { } // Split the command into prefix and number - size_t split_index = current_command.find_last_not_of(valueSymbols) + 1; + size_t split_index = current_command.find_last_not_of(valueSymbols.data()) + 1; if (split_index >= current_command.size()) { log_w("Invalid command: %s", current_command.c_str()); diff --git a/lib/opengloves/og_alpha_encoding.hpp b/lib/opengloves/og_alpha_encoding.hpp index 8ca21f07..f2ad57d1 100644 --- a/lib/opengloves/og_alpha_encoding.hpp +++ b/lib/opengloves/og_alpha_encoding.hpp @@ -1,21 +1,25 @@ #pragma once +#include <algorithm> #include <cstdint> #include <functional> #include <map> #include <string> #include <vector> +#include <frozen/map.h> +#include <frozen/string.h> +#include <frozen/unordered_map.h> + #include <og_protocol.hpp> #include <senseshift/logging.hpp> namespace OpenGloves { class AlphaEncodingService { public: - inline static const std::string valueSymbols = "0123456789"; - // TODO: use Frozen library to save memory - inline static const std::map<std::string, Command> commandMap = { - // clang-format off + inline static constexpr frozen::string valueSymbols = "0123456789"; + inline static const auto commandMap = frozen::make_map<std::string, Command>({ + // clang-format off { "A", Command::ThumbCurl }, { "(AB)", Command::ThumbSplay }, { "B", Command::IndexCurl }, @@ -26,8 +30,8 @@ namespace OpenGloves { { "(DB)", Command::RingSplay }, { "E", Command::PinkyCurl }, { "(EB)", Command::PinkySplay }, - // clang-format on - }; + // clang-format on + }); AlphaEncodingService() = default; diff --git a/lib/opengloves/og_protocol.hpp b/lib/opengloves/og_protocol.hpp index 0e863109..3b8dcccc 100644 --- a/lib/opengloves/og_protocol.hpp +++ b/lib/opengloves/og_protocol.hpp @@ -57,7 +57,8 @@ namespace OpenGloves { virtual size_t readCommand(char* buffer, size_t length) = 0; }; - typedef enum Command { + typedef uint16_t CommandIndex_t; + typedef enum Command : CommandIndex_t { ThumbCurl, ThumbSplay, From 6629ccdfecb0a348d0e7519cf4ddecb0b5e1bb26 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 5 Sep 2023 07:28:21 +0000 Subject: [PATCH 25/82] chore: add devcontainer codespace --- .devcontainer/Dockerfile | 48 +++++++++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 34 +++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..238133e3 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,48 @@ +FROM mcr.microsoft.com/vscode/devcontainers/base:ubuntu + +ARG CLANG_VERSION=16 + +RUN apt-get update \ + && apt-get -qqy install \ + lsb-release \ + wget \ + software-properties-common \ + gnupg \ + bc \ + sudo \ + build-essential \ + ca-certificates \ + clang \ + curl \ + gcc \ + git \ + python3 \ + python3-dev \ + python3-pip \ + python3-venv \ + python3-distutils \ + python3-setuptools \ + srecord \ + udev \ + xz-utils \ + && wget --quiet https://apt.llvm.org/llvm.sh \ + && chmod +x llvm.sh \ + && ./llvm.sh $CLANG_VERSION && rm -rf llvm.sh \ + && apt-get --no-install-recommends -y install clang-format-$CLANG_VERSION clang-tidy-$CLANG_VERSION \ + && ln -s /usr/bin/clang-format-$CLANG_VERSION /usr/bin/clang-format \ + && ln -s /usr/bin/clang-tidy-$CLANG_VERSION /usr/bin/clang-tidy \ + && ln -s /usr/bin/python3 /usr/bin/python \ + && apt-get autoremove -y \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* + +RUN curl -fLo /etc/udev/rules.d/99-platformio-udev.rules --create-dirs https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/system/99-platformio-udev.rules + +USER $USERNAME + +# RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -O get-platformio.py \ +# && python3 get-platformio.py \ +# && rm -rf get-platformio.py + +RUN python -m pip install --upgrade pip \ + && pip install --upgrade platformio diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..01be1c44 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,34 @@ +{ + // "name": "SenseShift", + "dockerFile": "Dockerfile", + "runArgs": [ + "--privileged" + ], + "forwardPorts": [ + 8008 + ], + "mounts": [ + "source=/dev/,target=/dev/,type=bind,consistency=consistent" + ], + "postAttachCommand": "sudo service udev restart", + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.defaultProfile.linux": "zsh", + "editor.formatOnSave": true, + "platformio-ide.useBuiltinPIOCore": false, + "platformio-ide.useBuiltinPython": false, + "platformio-ide.disablePIOHomeStartup": true, + "platformio-ide.pioHomeServerHttpPort": 8008 + }, + "extensions": [ + "ms-vscode.cpptools", + "platformio.platformio-ide", + "xaver.clang-format", + "GitHub.copilot", + "GitHub.copilot-labs", + "GitHub.copilot-chat" + ] + } + } +} From ba92af52b32cc527bbe65d1f1e61e1ea61da4fad Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Wed, 6 Sep 2023 13:31:29 +0000 Subject: [PATCH 26/82] ci(GitHub): add Wokwi testing --- .devcontainer/Dockerfile | 3 + .devcontainer/devcontainer.json | 6 +- .github/workflows/ci.yml | 80 ++++- .gitmodules | 2 +- .../diagram.json | 314 ++++++++++++++++++ .../lucidgloves-prototype3+serial/test.yaml | 76 +++++ .../lucidgloves-prototype3+serial/wokwi.toml | 4 + 7 files changed, 465 insertions(+), 20 deletions(-) create mode 100644 .wokwi/lucidgloves-prototype3+serial/diagram.json create mode 100644 .wokwi/lucidgloves-prototype3+serial/test.yaml create mode 100644 .wokwi/lucidgloves-prototype3+serial/wokwi.toml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 238133e3..eac4101c 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -46,3 +46,6 @@ USER $USERNAME RUN python -m pip install --upgrade pip \ && pip install --upgrade platformio + +RUN sudo wget -O /usr/local/bin/wokwi-cli https://github.com/wokwi/wokwi-cli/releases/latest/download/wokwi-cli-linuxstatic-x64 \ + && sudo chmod +x /usr/local/bin/wokwi-cli diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 01be1c44..4ec06d5d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -10,7 +10,10 @@ "mounts": [ "source=/dev/,target=/dev/,type=bind,consistency=consistent" ], - "postAttachCommand": "sudo service udev restart", + "postAttachCommand": { + "submodules": ["git", "submodule", "update", "--recursive", "--init"], + "udev": ["sudo", "service", "udev", "restart"] + }, "customizations": { "vscode": { "settings": { @@ -24,6 +27,7 @@ "extensions": [ "ms-vscode.cpptools", "platformio.platformio-ide", + "Wokwi.wokwi-vscode", "xaver.clang-format", "GitHub.copilot", "GitHub.copilot-labs", diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ecc2720..1119c892 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,13 +6,13 @@ on: - master - develop paths-ignore: - - '**/*.md' + - "**/*.md" push: branches: - master - develop paths-ignore: - - '**/*.md' + - "**/*.md" jobs: build-bhaptics: @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ ubuntu-latest ] + os: [ubuntu-latest] target: - bhaptics_tactsuit_x16 - bhaptics_tactsuit_x16_pca9685 @@ -32,10 +32,10 @@ jobs: - bhaptics_tactal - bhaptics_tactvisor - bhaptics_tactglove_right - battery_flag: [ SENSESHIFT_BATTERY_ENABLED=true ] - serial_plotter_flag: [ SENSESHIFT_SERIAL_PLOTTER=false ] - nimble_flag: [ SENSESHIFT_BLE_USE_NIMBLE=false ] - coverage: [ false ] + battery_flag: [SENSESHIFT_BATTERY_ENABLED=true] + serial_plotter_flag: [SENSESHIFT_SERIAL_PLOTTER=false] + nimble_flag: [SENSESHIFT_BLE_USE_NIMBLE=false] + coverage: [false] include: # Extra tests for x40, as it uses the most features @@ -61,7 +61,7 @@ jobs: steps: - uses: actions/checkout@v3 with: - submodules: 'recursive' + submodules: "recursive" - name: Get firmware name id: firmware_name @@ -120,7 +120,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: "3.9" - name: Install PlatformIO run: | @@ -156,14 +156,14 @@ jobs: with: name: lcov.info.${{ steps.firmware_name.outputs.firmware }} path: ./build/lcov/lcov.info.${{ steps.firmware_name.outputs.firmware }} - retention-days: 5 + retention-days: 1 build-opengloves: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ ubuntu-latest ] + os: [ubuntu-latest] target: - lucidgloves-prototype3 - lucidgloves-prototype4 @@ -174,7 +174,7 @@ jobs: comm_flag: - COMMUNICATION_PROTOCOL=OPENGLOVES_COMM_SERIAL - COMMUNICATION_PROTOCOL=OPENGLOVES_COMM_BTSERIAL - coverage: [ false ] + coverage: [false] include: - os: ubuntu-latest @@ -197,7 +197,7 @@ jobs: steps: - uses: actions/checkout@v3 with: - submodules: 'recursive' + submodules: "recursive" - name: Get firmware name id: firmware_name @@ -234,7 +234,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: "3.9" - name: Enable coverage (non-macOS) if: runner.os != 'macOS' && matrix.coverage @@ -278,6 +278,17 @@ jobs: echo "::endgroup::" pio run --environment ${{matrix.target}} + - name: Upload firmware Artifact + if: matrix.coverage == false + uses: actions/upload-artifact@v3 + with: + name: ${{ steps.firmware_name.outputs.firmware }} + path: | + ./.pio/build/${{matrix.target}}/firmware.bin + ./.pio/build/${{matrix.target}}/firmware.elf + retention-days: 1 + if-no-files-found: error + - name: Collect initial coverage if: matrix.coverage run: | @@ -290,7 +301,8 @@ jobs: with: name: lcov.info.${{ steps.firmware_name.outputs.firmware }} path: ./build/lcov/lcov.info.${{ steps.firmware_name.outputs.firmware }} - retention-days: 5 + retention-days: 1 + if-no-files-found: error test: runs-on: ubuntu-latest @@ -303,7 +315,7 @@ jobs: steps: - uses: actions/checkout@v3 with: - submodules: 'recursive' + submodules: "recursive" - name: Speedup package installation uses: abbbi/github-actions-tune@v1 @@ -333,7 +345,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: "3.9" - name: Install PlatformIO run: | @@ -398,7 +410,6 @@ jobs: with: name: coverage-report path: | - ./build/lcov/ ./build/coverage/ retention-days: 5 @@ -406,3 +417,36 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} lcov-file: ./build/lcov/lcov.info.cleaned + + wokwi: + needs: + - build-opengloves + - test + runs-on: ubuntu-latest + + strategy: + matrix: + variant: + - lucidgloves-prototype3+serial + + steps: + - uses: actions/checkout@v3 + + - name: Extract target + id: target_name + run: | + target=$(echo ${{ matrix.variant }} | cut -d'+' -f1) + echo "target=$target" >> $GITHUB_OUTPUT + + - name: Download firmware artifact + uses: actions/download-artifact@v3 + with: + name: ${{ matrix.variant }} + path: ./.pio/build/${{ steps.target_name.outputs.target }} + + - name: Run Wokwi scenario + uses: wokwi/wokwi-ci-action@v1 + with: + token: ${{ secrets.WOKWI_CLI_TOKEN }} + path: ./.wokwi/${{ matrix.variant }} + scenario: "test.yaml" diff --git a/.gitmodules b/.gitmodules index cd1f2794..fb9d97bc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "lib/frozen"] path = lib/frozen - url = git@github.com:senseshift/frozen.git + url = https://github.com/senseshift/frozen.git diff --git a/.wokwi/lucidgloves-prototype3+serial/diagram.json b/.wokwi/lucidgloves-prototype3+serial/diagram.json new file mode 100644 index 00000000..e20e4916 --- /dev/null +++ b/.wokwi/lucidgloves-prototype3+serial/diagram.json @@ -0,0 +1,314 @@ +{ + "version": 1, + "author": "Leonid Meleshin", + "editor": "wokwi", + "parts": [ + { + "type": "wokwi-esp32-devkit-v1", + "id": "esp", + "top": 110.3, + "left": 523, + "attrs": {} + }, + { + "type": "wokwi-potentiometer", + "id": "pot-thumb", + "top": -87.7, + "left": -278.6, + "attrs": {} + }, + { + "type": "wokwi-potentiometer", + "id": "pot-index", + "top": -87.7, + "left": -192.2, + "attrs": {} + }, + { + "type": "wokwi-potentiometer", + "id": "pot-middle", + "top": -87.7, + "left": -105.8, + "attrs": {} + }, + { + "type": "wokwi-potentiometer", + "id": "pot-ring", + "top": -87.7, + "left": -19.4, + "attrs": {} + }, + { + "type": "wokwi-potentiometer", + "id": "pot-pinky", + "top": -87.7, + "left": 67, + "attrs": {} + }, + { + "type": "wokwi-analog-joystick", + "id": "joystick1", + "top": -135, + "left": 149.4, + "attrs": {} + }, + { + "type": "wokwi-pushbutton", + "id": "btn1", + "top": 6.2, + "left": 268.8, + "attrs": { + "color": "green", + "key": "a", + "bounce": "1", + "label": "A" + } + }, + { + "type": "wokwi-pushbutton", + "id": "btn2", + "top": 6.2, + "left": 355.2, + "attrs": { + "color": "green", + "key": "b", + "bounce": "1", + "label": "B" + } + }, + { + "type": "wokwi-gnd", + "id": "gnd1", + "top": 307.2, + "left": 729, + "attrs": {} + } + ], + "connections": [ + [ + "esp:TX0", + "$serialMonitor:RX", + "", + [] + ], + [ + "esp:RX0", + "$serialMonitor:TX", + "", + [] + ], + [ + "pot-thumb:VCC", + "pot-index:VCC", + "red", + [ + "v28.8", + "h76.8" + ] + ], + [ + "pot-index:VCC", + "pot-middle:VCC", + "red", + [ + "v28.8", + "h76.8" + ] + ], + [ + "pot-middle:VCC", + "pot-ring:VCC", + "red", + [ + "v28.8", + "h76.8" + ] + ], + [ + "pot-thumb:GND", + "pot-index:GND", + "black", + [ + "v38.4", + "h76.8" + ] + ], + [ + "pot-index:GND", + "pot-middle:GND", + "black", + [ + "v38.4", + "h76.8" + ] + ], + [ + "pot-middle:GND", + "pot-ring:GND", + "black", + [ + "v38.4", + "h76.8" + ] + ], + [ + "pot-ring:GND", + "pot-pinky:GND", + "black", + [ + "v38.4", + "h76.8" + ] + ], + [ + "esp:VP", + "pot-pinky:SIG", + "green", + [ + "h0" + ] + ], + [ + "esp:VN", + "pot-ring:SIG", + "green", + [ + "h0" + ] + ], + [ + "esp:D34", + "pot-middle:SIG", + "green", + [ + "h0" + ] + ], + [ + "esp:D35", + "pot-index:SIG", + "green", + [ + "h0" + ] + ], + [ + "esp:D32", + "pot-thumb:SIG", + "green", + [ + "h0" + ] + ], + [ + "joystick1:GND", + "pot-pinky:GND", + "black", + [ + "v38.4", + "h-124.8" + ] + ], + [ + "esp:D33", + "joystick1:HORZ", + "green", + [ + "h0" + ] + ], + [ + "esp:D25", + "joystick1:VERT", + "green", + [ + "h0" + ] + ], + [ + "esp:D26", + "joystick1:SEL", + "green", + [ + "h0" + ] + ], + [ + "esp:GND.2", + "joystick1:GND", + "black", + [ + "h0" + ] + ], + [ + "esp:VIN", + "joystick1:VCC", + "red", + [ + "h0" + ] + ], + [ + "pot-ring:VCC", + "pot-pinky:VCC", + "red", + [ + "v28.8", + "h37.6" + ] + ], + [ + "joystick1:VCC", + "pot-pinky:VCC", + "red", + [ + "v28.8", + "h-38.4" + ] + ], + [ + "btn1:2.r", + "esp:D27", + "green", + [ + "h0.2", + "v249.8" + ] + ], + [ + "btn2:2.r", + "esp:D14", + "green", + [ + "h0.2", + "v259.4" + ] + ], + [ + "btn1:1.r", + "btn2:1.l", + "black", + [ + "v0" + ] + ], + [ + "joystick1:GND", + "btn1:1.l", + "black", + [ + "v0" + ] + ], + [ + "esp:GND.1", + "gnd1:GND", + "black", + [ + "h0" + ] + ] + ], + "dependencies": {} +} diff --git a/.wokwi/lucidgloves-prototype3+serial/test.yaml b/.wokwi/lucidgloves-prototype3+serial/test.yaml new file mode 100644 index 00000000..0639c5cc --- /dev/null +++ b/.wokwi/lucidgloves-prototype3+serial/test.yaml @@ -0,0 +1,76 @@ +name: Test LucidGloves Prototype 3 +version: 1 +author: Leonid Meleshin + +steps: + - 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: 'A4095B4095C0D0E0F2047G2047IM' # M is for Pinch gesture + + # Curl Middle finger + - set-control: + part-id: pot-middle + control: position + value: 1 + - wait-serial: 'A4095B4095C4095D0E0F2047G2047IM' + + # Curl Ring finger + - set-control: + part-id: pot-ring + control: position + value: 1 + - wait-serial: 'A4095B4095C4095D4095E0F2047G2047IM' + + # Curl Pinky finger + - set-control: + part-id: pot-pinky + control: position + value: 1 + - wait-serial: 'A4095B4095C4095D4095E4095F2047G2047ILM' # L is for the Grab gesture + + # Release Thumb finger + - set-control: + part-id: pot-thumb + control: position + value: 0 + - wait-serial: 'A0B4095C4095D4095E4095F2047G2047IL' diff --git a/.wokwi/lucidgloves-prototype3+serial/wokwi.toml b/.wokwi/lucidgloves-prototype3+serial/wokwi.toml new file mode 100644 index 00000000..54e28de8 --- /dev/null +++ b/.wokwi/lucidgloves-prototype3+serial/wokwi.toml @@ -0,0 +1,4 @@ +[wokwi] +version = 1 +firmware = "../../.pio/build/lucidgloves-prototype3/firmware.bin" +elf = "../../.pio/build/lucidgloves-prototype3/firmware.elf" From e7db5fbe43f70e9a0bd7190660ae37304f0c8b78 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 3 Sep 2023 13:19:03 +0400 Subject: [PATCH 27/82] refactor(OpenGloves): decouple transport and serialization --- .../mode_configs/opengloves/opengloves.cpp | 8 +- .../opengloves/encoding/alpha.cpp} | 31 +++- .../opengloves/encoding/alpha.hpp} | 18 ++- .../senseshift/opengloves/interface.hpp | 21 +++ lib/opengloves/sensor/og_sensor.hpp | 1 - .../opengloves/transport/stream.hpp | 121 ++++++++++++++++ .../og_serial_communication.hpp | 137 ------------------ lib/opengloves_task/opengloves_task.hpp | 24 +-- test/test_opengloves_alpha_encoding/main.cpp | 7 +- 9 files changed, 206 insertions(+), 162 deletions(-) rename lib/opengloves/{og_alpha_encoding.cpp => senseshift/opengloves/encoding/alpha.cpp} (65%) rename lib/opengloves/{og_alpha_encoding.hpp => senseshift/opengloves/encoding/alpha.hpp} (67%) create mode 100644 lib/opengloves/senseshift/opengloves/interface.hpp create mode 100644 lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp delete mode 100644 lib/opengloves_serial/og_serial_communication.hpp diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index c58e221c..95c5f9c0 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -1,5 +1,4 @@ #include <og_constants.hpp> -#include <og_serial_communication.hpp> #include <opengloves_task.hpp> #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/input/sensor/digital.hpp> @@ -7,6 +6,7 @@ #include <senseshift/calibration.hpp> #include <senseshift/input/sensor.hpp> #include <senseshift/input/sensor/joystick.hpp> +#include <senseshift/opengloves/transport/stream.hpp> #include <senseshift/utility.hpp> #include <sensor/og_finger.hpp> #include <sensor/og_gesture.hpp> @@ -146,6 +146,7 @@ (FFB_THUMB_ENABLED || FFB_INDEX_ENABLED || FFB_MIDDLE_ENABLED || FFB_RING_ENABLED || FFB_PINKY_ENABLED) using namespace OpenGloves; +using namespace SenseShift::OpenGloves; HandSensors handSensors = { #if FINGER_THUMB_SPLAY @@ -323,15 +324,16 @@ OpenGlovesForceFeedbackTask* ffbTask; void setupMode() { #if OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_SERIAL - auto* communication = new SerialCommunication(SERIAL_PORT, SERIAL_BAUDRATE); + SERIAL_PORT.begin(SERIAL_BAUDRATE); + auto* communication = new StreamTransport(SERIAL_PORT); #elif OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL #ifdef BTSERIAL_NAME std::string name = BTSERIAL_NAME; #else char suffix[4]; sprintf(suffix, "%04X", (uint16_t) (ESP.getEfuseMac() >> 32)); - log_i("Generated Bluetooth suffix: %s", suffix); std::string name = BTSERIAL_PREFIX + std::string(suffix); + log_i("Generated Bluetooth name: %s", name.c_str()); #endif BluetoothSerial* bt_serial = new BluetoothSerial(); auto* communication = new BTSerialCommunication(*bt_serial, name); diff --git a/lib/opengloves/og_alpha_encoding.cpp b/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp similarity index 65% rename from lib/opengloves/og_alpha_encoding.cpp rename to lib/opengloves/senseshift/opengloves/encoding/alpha.cpp index da70fbe7..702a157c 100644 --- a/lib/opengloves/og_alpha_encoding.cpp +++ b/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp @@ -1,7 +1,10 @@ -#include "og_alpha_encoding.hpp" +#include "senseshift/opengloves/encoding/alpha.hpp" -namespace OpenGloves { - std::map<Command, uint16_t> AlphaEncodingService::splitCommands(std::string input_string) +#include <string.h> + +namespace SenseShift::OpenGloves { + const std::map<AlphaEncodingService::Command, uint16_t> AlphaEncodingService::deserialize(const std::string& input_string + ) const { std::map<Command, uint16_t> commands; @@ -54,4 +57,24 @@ namespace OpenGloves { Command command = it->second; commands[command] = number; } -} // namespace OpenGloves + + const std::string AlphaEncodingService::serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors + ) + { + memset(this->writeBuffer, 0, 256); + this->writeBuffer[0] = '\0'; + + size_t offset = 0; + + for (size_t i = 0; i < sensors.size(); i++) { + // The offset is the total charecters already added to the string. + offset += sensors[i]->encodeString(this->writeBuffer + offset); + } + + // Add a newline and terminator to the end of the encoded string. + this->writeBuffer[offset++] = '\n'; + this->writeBuffer[offset] = '\0'; + + return std::string(this->writeBuffer, offset); + } +} // namespace SenseShift::OpenGloves diff --git a/lib/opengloves/og_alpha_encoding.hpp b/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp similarity index 67% rename from lib/opengloves/og_alpha_encoding.hpp rename to lib/opengloves/senseshift/opengloves/encoding/alpha.hpp index f2ad57d1..59830803 100644 --- a/lib/opengloves/og_alpha_encoding.hpp +++ b/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp @@ -13,9 +13,12 @@ #include <og_protocol.hpp> #include <senseshift/logging.hpp> +#include <senseshift/opengloves/interface.hpp> + +namespace SenseShift::OpenGloves { + class AlphaEncodingService : public IEncoding { + using Command = ::OpenGloves::Command; -namespace OpenGloves { - class AlphaEncodingService { public: inline static constexpr frozen::string valueSymbols = "0123456789"; inline static const auto commandMap = frozen::make_map<std::string, Command>({ @@ -33,15 +36,18 @@ namespace OpenGloves { // clang-format on }); - AlphaEncodingService() = default; + AlphaEncodingService() : writeBuffer(new char[256]){}; + + virtual const std::map<Command, uint16_t> deserialize(const std::string& buffer) const override; - static std::map<Command, uint16_t> splitCommands(std::string input_string); + virtual const std::string serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors + ) override; private: - CommandCallback callback = nullptr; + char* writeBuffer; static void splitCommand( const std::string& input_string, size_t start, size_t end, std::map<Command, uint16_t>& commands ); }; -} // namespace OpenGloves +} // namespace SenseShift::OpenGloves diff --git a/lib/opengloves/senseshift/opengloves/interface.hpp b/lib/opengloves/senseshift/opengloves/interface.hpp new file mode 100644 index 00000000..17815845 --- /dev/null +++ b/lib/opengloves/senseshift/opengloves/interface.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include <cstddef> +#include <cstdint> + +#include "og_protocol.hpp" + +namespace SenseShift::OpenGloves { + struct ITransport { + virtual void setup(){}; + virtual size_t send(const char* buffer, size_t length) = 0; + virtual bool hasData() = 0; + virtual size_t read(char* buffer, size_t length) = 0; + }; + + struct IEncoding { + virtual const std::string serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors + ) = 0; + virtual const std::map<::OpenGloves::Command, uint16_t> deserialize(const std::string& buffer) const = 0; + }; +} // namespace SenseShift::OpenGloves diff --git a/lib/opengloves/sensor/og_sensor.hpp b/lib/opengloves/sensor/og_sensor.hpp index 42c722de..caa4a9c8 100644 --- a/lib/opengloves/sensor/og_sensor.hpp +++ b/lib/opengloves/sensor/og_sensor.hpp @@ -82,7 +82,6 @@ namespace OpenGloves { size_t StringEncodedMemoizedSensor<FingerValue>::encodeString(char* buffer) const { size_t offset = 0; - offset += snprintf(buffer + offset, 6, "%c%d", this->type, this->value.getTotalCurl()); if (this->value.curl.size() > 1) { diff --git a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp new file mode 100644 index 00000000..b198aac5 --- /dev/null +++ b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp @@ -0,0 +1,121 @@ +#pragma once + +#include <BluetoothSerial.h> +#include <HardwareSerial.h> +#include <Print.h> +#include <WiFi.h> + +#include <og_protocol.hpp> +#include <senseshift/opengloves/interface.hpp> + +namespace SenseShift::OpenGloves { + class IStreamTransport : public ITransport { + using IStringEncodedMemoizedSensor = ::OpenGloves::IStringEncodedMemoizedSensor; + + protected: + Stream* channel; + char* buffer = new char[256]; + + public: + IStreamTransport(Stream* channel) : channel(channel){}; + + size_t send(const char* buffer, size_t length) override + { + if (!this->isReady()) { + return 0; + } + + const auto written = this->channel->write(buffer); + this->channel->flush(); + + return written; + } + + virtual bool isReady() = 0; + + virtual bool hasData() override + { + return this->isReady() && this->channel != nullptr && this->channel->available() > 0; + } + + virtual size_t read(char* buffer, size_t length) + { + if (!this->hasData()) { + return false; + } + + size_t bytesRead = this->channel->readBytesUntil('\n', buffer, length); + buffer[bytesRead] = '\0'; + + return bytesRead; + } + }; + + class StreamTransport : public IStreamTransport { + public: + StreamTransport(Stream& channel) : IStreamTransport(&channel){}; + StreamTransport(Stream* channel) : IStreamTransport(channel){}; + + void setup() override { this->mReady = true; } + + bool isReady() override { return this->channel != nullptr && this->mReady; } + + private: + bool mReady = false; + }; + + class BluetoothSerialTransport : public IStreamTransport { + private: + std::string name; + + public: + BluetoothSerialTransport(BluetoothSerial& channel, std::string name) : IStreamTransport(&channel), name(name){}; + + void setup() override + { + auto* serial = static_cast<BluetoothSerial*>(this->channel); + if (serial->isReady()) { + return; + } + + serial->begin(name.c_str()); + } + + bool isReady() override + { + auto* serial = static_cast<BluetoothSerial*>(this->channel); + return serial->isReady() && serial->hasClient(); + } + }; + + class WiFiSerialTransport : public IStreamTransport { + public: + WiFiSerialTransport(WiFiServer& server) : IStreamTransport(nullptr), m_server(server){}; + + void setup() override + { + auto* client = static_cast<WiFiClient*>(this->channel); + if (client != nullptr) { + if (client->connected()) { + return; + } + } + + this->m_server.begin(); + this->channel = new WiFiClient(this->m_server.available()); + } + + bool isReady() override + { + if (this->channel == nullptr) { + return false; + } + + auto* client = static_cast<WiFiClient*>(this->channel); + return client->connected(); + } + + private: + WiFiServer& m_server; + }; +} // namespace SenseShift::OpenGloves diff --git a/lib/opengloves_serial/og_serial_communication.hpp b/lib/opengloves_serial/og_serial_communication.hpp deleted file mode 100644 index 800b70e0..00000000 --- a/lib/opengloves_serial/og_serial_communication.hpp +++ /dev/null @@ -1,137 +0,0 @@ -#pragma once - -#include <BluetoothSerial.h> -#include <HardwareSerial.h> -#include <Print.h> -#include <WiFi.h> - -#include <og_protocol.hpp> - -namespace OpenGloves { - class ISerialCommunication : public ICommunication { - protected: - Print& channel; - char* buffer = new char[256]; - - public: - ISerialCommunication(Print& channel) : channel(channel){}; - - void send(std::vector<IStringEncodedMemoizedSensor*>& sensors) override - { - if (!this->isReady()) { - return; - } - - // Encode all of the sensors into a single string. - size_t length = encodeAll(buffer, sensors); - // Send the encoded string over serial. - this->channel.print(buffer); - this->channel.flush(); - } - - virtual bool isReady() = 0; - - static size_t encodeAll(char* buffer, std::vector<IStringEncodedMemoizedSensor*>& sensors) - { - size_t offset = 0; - // Loop over all of the encoders and encode them to the output string. - for (size_t i = 0; i < sensors.size(); i++) { - // The offset is the total charecters already added to the string. - offset += sensors[i]->encodeString(buffer + offset); - } - - // Add a new line to the end of the encoded string. - buffer[offset++] = '\n'; - buffer[offset] = '\0'; - - return offset; - } - - virtual bool hasData() = 0; - - virtual size_t readCommand(char* buffer, size_t length) = 0; - }; - - class SerialCommunication : public ISerialCommunication { - private: - unsigned long baud; - bool ready = false; - - public: - SerialCommunication(HardwareSerial& channel, unsigned long baud) : baud(baud), ISerialCommunication(channel){}; - - void setup() override - { - if (this->ready) { - return; - } - - static_cast<HardwareSerial&>(this->channel).begin(this->baud); - this->ready = true; - } - - bool isReady() override { return this->ready; } - - bool hasData() override - { - return this->isReady() && static_cast<HardwareSerial&>(this->channel).available() > 0; - } - - size_t readCommand(char* buffer, size_t length) override - { - if (!this->hasData()) { - return false; - } - - size_t bytesRead = static_cast<HardwareSerial&>(this->channel).readBytesUntil('\n', buffer, length); - buffer[bytesRead] = '\0'; - - return bytesRead; - } - }; - - class BTSerialCommunication : public ISerialCommunication { - private: - std::string name; - - public: - BTSerialCommunication(BluetoothSerial& channel, std::string name) : ISerialCommunication(channel), name(name){}; - - void setup() override - { - auto& serial = static_cast<BluetoothSerial&>(this->channel); - if (serial.isReady()) { - return; - } - - // serial.register_callback([](esp_spp_cb_event_t event, esp_spp_cb_param_t *param) { - // log_i("Bluetooth event: %d", event); - // }); - // serial.setTimeout(4); - serial.begin(name.c_str()); - } - - bool isReady() override - { - auto& serial = static_cast<BluetoothSerial&>(this->channel); - return serial.isReady() && serial.hasClient(); - } - - bool hasData() override - { - return this->isReady() && static_cast<BluetoothSerial&>(this->channel).available() > 0; - } - - size_t readCommand(char* buffer, size_t length) override - { - if (!this->hasData()) { - return false; - } - - size_t bytesRead = static_cast<BluetoothSerial&>(this->channel).readBytesUntil('\n', buffer, length); - buffer[bytesRead] = '\0'; - - return bytesRead; - } - }; -} // namespace OpenGloves diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index 630d6d8a..5d4b90db 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -4,15 +4,15 @@ #include <optional> -#include <og_alpha_encoding.hpp> #include <og_ffb.hpp> -#include <og_serial_communication.hpp> #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/input/sensor/digital.hpp> #include <senseshift/calibration.hpp> #include <senseshift/freertos/task.hpp> #include <senseshift/input/sensor.hpp> #include <senseshift/input/sensor/joystick.hpp> +#include <senseshift/opengloves/encoding/alpha.hpp> +#include <senseshift/opengloves/interface.hpp> #include <senseshift/utility.hpp> #include <sensor/og_finger.hpp> #include <sensor/og_gesture.hpp> @@ -52,7 +52,7 @@ namespace OpenGloves { */ OpenGlovesTrackingTask( OpenGlovesTrackingTaskConfig& config, - ICommunication& communication, + ::SenseShift::OpenGloves::ITransport& communication, HandSensors& fingers, std::vector<StringEncodedMemoizedSensor<bool>*>& buttons, std::vector<StringEncodedMemoizedSensor<uint16_t>*>& joysticks, @@ -133,7 +133,10 @@ namespace OpenGloves { OpenGlovesTrackingTaskConfig& config; HandSensors& fingers; - ICommunication& communication; + ::SenseShift::OpenGloves::ITransport& communication; + ::SenseShift::OpenGloves::AlphaEncodingService encodingService = + ::SenseShift::OpenGloves::AlphaEncodingService(); + std::vector<StringEncodedMemoizedSensor<bool>*>& buttons; std::vector<StringEncodedMemoizedSensor<uint16_t>*>& joysticks; std::vector<IStringEncodedMemoizedSensor*>& otherSensors; @@ -194,7 +197,8 @@ namespace OpenGloves { } // Send the sensor values. - this->communication.send(this->allSensors); + auto command = this->encodingService.serialize(this->allSensors); + this->communication.send(command.c_str(), command.size()); // Check if the calibration has finished. if (!(this->config.alwaysCalibrate) && calibrationStarted > 0 && (now - calibrationStarted) > CALIBRATION_DURATION) { @@ -220,7 +224,7 @@ namespace OpenGloves { public: OpenGlovesForceFeedbackTask( - ICommunication& communication, + ::SenseShift::OpenGloves::ITransport& communication, HandActuators& actuators, size_t updateRate, SenseShift::FreeRTOS::TaskConfig taskConfig @@ -240,9 +244,11 @@ namespace OpenGloves { }; private: - ICommunication& communication; + ::SenseShift::OpenGloves::ITransport& communication; HandActuators& actuators; size_t updateIntervalMs; + ::SenseShift::OpenGloves::AlphaEncodingService encodingService = + ::SenseShift::OpenGloves::AlphaEncodingService(); void setup() { @@ -278,14 +284,14 @@ namespace OpenGloves { auto now = millis(); if (this->communication.hasData()) { - auto bytesRead = this->communication.readCommand(commandBuffer, sizeof(commandBuffer)); + auto bytesRead = this->communication.read(commandBuffer, sizeof(commandBuffer)); if (bytesRead == 0) { continue; } command.assign(commandBuffer, bytesRead); - auto commands = AlphaEncodingService::splitCommands(command); + auto commands = this->encodingService.deserialize(command); for (auto& [command, value] : commands) { this->handleCommand(command, value); diff --git a/test/test_opengloves_alpha_encoding/main.cpp b/test/test_opengloves_alpha_encoding/main.cpp index 7f5f7200..1f71136c 100644 --- a/test/test_opengloves_alpha_encoding/main.cpp +++ b/test/test_opengloves_alpha_encoding/main.cpp @@ -1,7 +1,8 @@ -#include <og_alpha_encoding.hpp> +#include <senseshift/opengloves/encoding/alpha.hpp> #include <unity.h> using namespace OpenGloves; +using namespace SenseShift::OpenGloves; void testSplitCommands(void) { @@ -90,8 +91,10 @@ void testSplitCommands(void) }, }; + auto encoding_service = AlphaEncodingService(); + for (auto& [input_string, expected_commands] : input_strings) { - std::map<Command, uint16_t> commands = AlphaEncodingService::splitCommands(input_string); + std::map<Command, uint16_t> commands = encoding_service.deserialize(input_string); TEST_ASSERT_EQUAL_size_t_MESSAGE( expected_commands.size(), From efae0e039051dd806d45ac6f4ca18cbcdcaccca9 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <lm@devolt.one> Date: Sun, 3 Sep 2023 23:40:49 +0400 Subject: [PATCH 28/82] feat(Input): add averaged sensor --- .../mode_configs/opengloves/opengloves.cpp | 32 +++++++++++++------ lib/io/senseshift/input/sensor.hpp | 26 +++++++++++++++ 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 95c5f9c0..706e3b57 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -53,13 +53,16 @@ #define FINGER_MIDDLE_ENABLED (defined(PIN_FINGER_MIDDLE) && (PIN_FINGER_MIDDLE != -1)) #define FINGER_RING_ENABLED (defined(PIN_FINGER_RING) && (PIN_FINGER_RING != -1)) #define FINGER_PINKY_ENABLED (defined(PIN_FINGER_PINKY) && (PIN_FINGER_PINKY != -1)) -#define FINGER_CLASS(type, curl_pin, curl_invert, curl_calib) \ - FingerSensor( \ - new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ - new curl_calib() \ - ), \ - type \ +#define FINGER_CLASS(type, curl_pin, curl_invert, curl_calib) \ + FingerSensor( \ + new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ + new ::SenseShift::Input::AverageSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ + 5 \ + ), \ + new curl_calib() \ + ), \ + type \ ) #define FINGER_THUMB_SPLAY (FINGER_THUMB_ENABLED && defined(PIN_FINGER_THUMB_SPLAY) && (PIN_FINGER_THUMB_SPLAY != -1)) #define FINGER_INDEX_SPLAY (FINGER_INDEX_ENABLED && defined(PIN_FINGER_INDEX_SPLAY) && (PIN_FINGER_INDEX_SPLAY != -1)) @@ -70,11 +73,17 @@ #define FINGER_SPLAY_CLASS(type, curl_pin, curl_invert, curl_calib, splay_pin, splay_invert, splay_calib) \ FingerSensor( \ new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ + new ::SenseShift::Input::AverageSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ + 5 \ + ), \ new curl_calib() \ ), \ new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<splay_invert>(splay_pin), \ + new ::SenseShift::Input::AverageSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<splay_invert>(splay_pin), \ + 5 \ + ), \ new splay_calib() \ ), \ type \ @@ -90,7 +99,10 @@ #define JOYSTICK_CLASS(type, pin, invert, deadzone) \ StringEncodedMemoizedSensor<uint16_t>( \ new ::SenseShift::Input::JoystickAxisSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<invert>(pin), \ + new ::SenseShift::Input::AverageSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<invert>(pin), \ + 5 \ + ), \ deadzone \ ), \ type \ diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index a4f5e160..c3ce962c 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -108,4 +108,30 @@ namespace SenseShift::Input { return this->calibrator->calibrate(value); } }; + + template <typename _Tp> + class AverageSensor : public ISimpleSensor<_Tp> + { + static_assert(std::is_arithmetic<_Tp>::value, "AverageSensor only supports arithmetic types"); + + public: + AverageSensor(ISimpleSensor<_Tp>* sensor, size_t samples) : sensor(sensor), samples(samples){ } + + void init() override { this->sensor->init(); }; + + _Tp getValue() override + { + // TODO: another type for sum? + double sum = 0; + for (size_t i = 0; i < this->samples; i++) { + sum += this->sensor->getValue(); + } + + return sum / this->samples; + } + + private: + ISimpleSensor<_Tp>* sensor; + size_t samples; + }; } // namespace SenseShift::Input From e28d5dfa45e84c1f403cbbce70d7c2b81f77d0a6 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <lm@devolt.one> Date: Sun, 3 Sep 2023 23:56:08 +0400 Subject: [PATCH 29/82] refactor(OpenGloves): auto-configure transport --- .../mode_configs/opengloves/opengloves.cpp | 163 +-------------- .../senseshift/opengloves/autoconfig.hpp | 185 ++++++++++++++++++ .../opengloves/transport/stream.hpp | 7 +- 3 files changed, 188 insertions(+), 167 deletions(-) create mode 100644 lib/opengloves/senseshift/opengloves/autoconfig.hpp diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 706e3b57..ff39cdff 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -6,157 +6,12 @@ #include <senseshift/calibration.hpp> #include <senseshift/input/sensor.hpp> #include <senseshift/input/sensor/joystick.hpp> +#include <senseshift/opengloves/autoconfig.hpp> #include <senseshift/opengloves/transport/stream.hpp> #include <senseshift/utility.hpp> #include <sensor/og_finger.hpp> #include <sensor/og_gesture.hpp> -#pragma region Communication - -#ifndef OPENGLOVES_COMMUNCATION -#define OPENGLOVES_COMMUNCATION OPENGLOVES_COMM_SERIAL -#endif - -#ifndef SERIAL_PORT -#define SERIAL_PORT Serial -#endif - -#ifndef SERIAL_BAUDRATE -#define SERIAL_BAUDRATE 115200 -#endif - -#ifndef BTSERIAL_PREFIX -#define BTSERIAL_PREFIX "SenseShift_OG" -#endif - -#pragma endregion - -#pragma region Calibration - -#ifndef CALIBRATION_CURL -#define CALIBRATION_CURL ::SenseShift::Calibration::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX> -#endif -#ifndef CALIBRATION_SPLAY -#define CALIBRATION_SPLAY ::SenseShift::Calibration::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX> -#endif - -#ifndef CALIBRATION_DURATION -#define CALIBRATION_DURATION 2000 // duration in milliseconds -#endif - -#pragma endregion - -#pragma region Fingers - -#define FINGER_THUMB_ENABLED (defined(PIN_FINGER_THUMB) && (PIN_FINGER_THUMB != -1)) -#define FINGER_INDEX_ENABLED (defined(PIN_FINGER_INDEX) && (PIN_FINGER_INDEX != -1)) -#define FINGER_MIDDLE_ENABLED (defined(PIN_FINGER_MIDDLE) && (PIN_FINGER_MIDDLE != -1)) -#define FINGER_RING_ENABLED (defined(PIN_FINGER_RING) && (PIN_FINGER_RING != -1)) -#define FINGER_PINKY_ENABLED (defined(PIN_FINGER_PINKY) && (PIN_FINGER_PINKY != -1)) -#define FINGER_CLASS(type, curl_pin, curl_invert, curl_calib) \ - FingerSensor( \ - new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Input::AverageSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ - 5 \ - ), \ - new curl_calib() \ - ), \ - type \ - ) -#define FINGER_THUMB_SPLAY (FINGER_THUMB_ENABLED && defined(PIN_FINGER_THUMB_SPLAY) && (PIN_FINGER_THUMB_SPLAY != -1)) -#define FINGER_INDEX_SPLAY (FINGER_INDEX_ENABLED && defined(PIN_FINGER_INDEX_SPLAY) && (PIN_FINGER_INDEX_SPLAY != -1)) -#define FINGER_MIDDLE_SPLAY \ - (FINGER_MIDDLE_ENABLED && defined(PIN_FINGER_MIDDLE_SPLAY) && (PIN_FINGER_MIDDLE_SPLAY != -1)) -#define FINGER_RING_SPLAY (FINGER_RING_ENABLED && defined(PIN_FINGER_RING_SPLAY) && (PIN_FINGER_RING_SPLAY != -1)) -#define FINGER_PINKY_SPLAY (FINGER_PINKY_ENABLED && defined(PIN_FINGER_PINKY_SPLAY) && (PIN_FINGER_PINKY_SPLAY != -1)) -#define FINGER_SPLAY_CLASS(type, curl_pin, curl_invert, curl_calib, splay_pin, splay_invert, splay_calib) \ - FingerSensor( \ - new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Input::AverageSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ - 5 \ - ), \ - new curl_calib() \ - ), \ - new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Input::AverageSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<splay_invert>(splay_pin), \ - 5 \ - ), \ - new splay_calib() \ - ), \ - type \ - ) - -#pragma endregion - -#pragma region Joysticks - -#define JOYSTICK_ENABLED \ - (defined(PIN_JOYSTICK_X) && defined(PIN_JOYSTICK_Y) && (PIN_JOYSTICK_X != -1) && (PIN_JOYSTICK_Y != -1)) - -#define JOYSTICK_CLASS(type, pin, invert, deadzone) \ - StringEncodedMemoizedSensor<uint16_t>( \ - new ::SenseShift::Input::JoystickAxisSensor<uint16_t>( \ - new ::SenseShift::Input::AverageSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<invert>(pin), \ - 5 \ - ), \ - deadzone \ - ), \ - type \ - ) - -#pragma endregion - -#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)) - -#define BUTTON_CLASS(type, pin, invert) \ - StringEncodedMemoizedSensor<bool>(new ::SenseShift::Arduino::Input::DigitalSensor<invert>(pin), type) - -#pragma endregion - -#pragma region Gestures - -#ifndef GESTURE_TRIGGER_THRESHOLD -#define GESTURE_TRIGGER_THRESHOLD (ANALOG_MAX / 2) -#endif - -#ifndef GESTURE_GRAB_THRESHOLD -#define GESTURE_GRAB_THRESHOLD (ANALOG_MAX / 2) -#endif - -#ifndef GESTURE_PINCH_THRESHOLD -#define GESTURE_PINCH_THRESHOLD (ANALOG_MAX / 2) -#endif - -#define GESTURE_CLASS(type, sensor) StringEncodedMemoizedSensor<bool>(sensor, type) - -#pragma endregion - -#ifndef UPDATE_RATE -#define UPDATE_RATE 90 -#endif - -#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)) - -#define FFB_ENABLED \ - (FFB_THUMB_ENABLED || FFB_INDEX_ENABLED || FFB_MIDDLE_ENABLED || FFB_RING_ENABLED || FFB_PINKY_ENABLED) - using namespace OpenGloves; using namespace SenseShift::OpenGloves; @@ -335,21 +190,7 @@ OpenGlovesForceFeedbackTask* ffbTask; void setupMode() { -#if OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_SERIAL - SERIAL_PORT.begin(SERIAL_BAUDRATE); - auto* communication = new StreamTransport(SERIAL_PORT); -#elif OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL -#ifdef BTSERIAL_NAME - std::string name = BTSERIAL_NAME; -#else - char suffix[4]; - sprintf(suffix, "%04X", (uint16_t) (ESP.getEfuseMac() >> 32)); - std::string name = BTSERIAL_PREFIX + std::string(suffix); - log_i("Generated Bluetooth name: %s", name.c_str()); -#endif - BluetoothSerial* bt_serial = new BluetoothSerial(); - auto* communication = new BTSerialCommunication(*bt_serial, name); -#endif + auto* communication = AutoConfig::setupTransport(); trackingTask = new OpenGlovesTrackingTask( config, diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp new file mode 100644 index 00000000..ed585ef4 --- /dev/null +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -0,0 +1,185 @@ +#pragma once + +#include <senseshift/opengloves/interface.hpp> + +#ifdef ARDUINO +#include <senseshift/opengloves/transport/stream.hpp> +#endif + +#pragma region Communication + +#ifndef OPENGLOVES_COMMUNCATION +#define OPENGLOVES_COMMUNCATION OPENGLOVES_COMM_SERIAL +#endif + +#ifndef SERIAL_PORT +#define SERIAL_PORT Serial +#endif + +#ifndef SERIAL_BAUDRATE +#define SERIAL_BAUDRATE 115200 +#endif + +#ifndef BTSERIAL_PREFIX +#define BTSERIAL_PREFIX "SenseShift_OG" +#endif + +#pragma endregion + +#pragma region Calibration + +#ifndef CALIBRATION_CURL +#define CALIBRATION_CURL ::SenseShift::Calibration::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX> +#endif +#ifndef CALIBRATION_SPLAY +#define CALIBRATION_SPLAY ::SenseShift::Calibration::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX> +#endif + +#ifndef CALIBRATION_DURATION +#define CALIBRATION_DURATION 2000 // duration in milliseconds +#endif + +#pragma endregion + +#pragma region Fingers + +#define FINGER_THUMB_ENABLED (defined(PIN_FINGER_THUMB) && (PIN_FINGER_THUMB != -1)) +#define FINGER_INDEX_ENABLED (defined(PIN_FINGER_INDEX) && (PIN_FINGER_INDEX != -1)) +#define FINGER_MIDDLE_ENABLED (defined(PIN_FINGER_MIDDLE) && (PIN_FINGER_MIDDLE != -1)) +#define FINGER_RING_ENABLED (defined(PIN_FINGER_RING) && (PIN_FINGER_RING != -1)) +#define FINGER_PINKY_ENABLED (defined(PIN_FINGER_PINKY) && (PIN_FINGER_PINKY != -1)) +#define FINGER_CLASS(type, curl_pin, curl_invert, curl_calib) \ + FingerSensor( \ + new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ + new ::SenseShift::Input::AverageSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ + 5 \ + ), \ + new curl_calib() \ + ), \ + type \ + ) +#define FINGER_THUMB_SPLAY (FINGER_THUMB_ENABLED && defined(PIN_FINGER_THUMB_SPLAY) && (PIN_FINGER_THUMB_SPLAY != -1)) +#define FINGER_INDEX_SPLAY (FINGER_INDEX_ENABLED && defined(PIN_FINGER_INDEX_SPLAY) && (PIN_FINGER_INDEX_SPLAY != -1)) +#define FINGER_MIDDLE_SPLAY \ + (FINGER_MIDDLE_ENABLED && defined(PIN_FINGER_MIDDLE_SPLAY) && (PIN_FINGER_MIDDLE_SPLAY != -1)) +#define FINGER_RING_SPLAY (FINGER_RING_ENABLED && defined(PIN_FINGER_RING_SPLAY) && (PIN_FINGER_RING_SPLAY != -1)) +#define FINGER_PINKY_SPLAY (FINGER_PINKY_ENABLED && defined(PIN_FINGER_PINKY_SPLAY) && (PIN_FINGER_PINKY_SPLAY != -1)) +#define FINGER_SPLAY_CLASS(type, curl_pin, curl_invert, curl_calib, splay_pin, splay_invert, splay_calib) \ + FingerSensor( \ + new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ + new ::SenseShift::Input::AverageSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ + 5 \ + ), \ + new curl_calib() \ + ), \ + new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ + new ::SenseShift::Input::AverageSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<splay_invert>(splay_pin), \ + 5 \ + ), \ + new splay_calib() \ + ), \ + type \ + ) + +#pragma endregion + +#pragma region Joysticks + +#define JOYSTICK_ENABLED \ + (defined(PIN_JOYSTICK_X) && defined(PIN_JOYSTICK_Y) && (PIN_JOYSTICK_X != -1) && (PIN_JOYSTICK_Y != -1)) + +#define JOYSTICK_CLASS(type, pin, invert, deadzone) \ + StringEncodedMemoizedSensor<uint16_t>( \ + new ::SenseShift::Input::JoystickAxisSensor<uint16_t>( \ + new ::SenseShift::Input::AverageSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<invert>(pin), \ + 5 \ + ), \ + deadzone \ + ), \ + type \ + ) + +#pragma endregion + +#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)) + +#define BUTTON_CLASS(_type, _pin, _invert) \ + StringEncodedMemoizedSensor<bool>(new ::SenseShift::Arduino::Input::DigitalSensor<_invert>(_pin), _type) + +#pragma endregion + +#pragma region Gestures + +#ifndef GESTURE_TRIGGER_THRESHOLD +#define GESTURE_TRIGGER_THRESHOLD (ANALOG_MAX / 2) +#endif + +#ifndef GESTURE_GRAB_THRESHOLD +#define GESTURE_GRAB_THRESHOLD (ANALOG_MAX / 2) +#endif + +#ifndef GESTURE_PINCH_THRESHOLD +#define GESTURE_PINCH_THRESHOLD (ANALOG_MAX / 2) +#endif + +#define GESTURE_CLASS(_type, _sensor) StringEncodedMemoizedSensor<bool>(_sensor, _type) + +#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)) + +#define FFB_ENABLED \ + (FFB_THUMB_ENABLED || FFB_INDEX_ENABLED || FFB_MIDDLE_ENABLED || FFB_RING_ENABLED || FFB_PINKY_ENABLED) + +#ifndef UPDATE_RATE +#define UPDATE_RATE 90 +#endif + +namespace SenseShift::OpenGloves::AutoConfig { + + /** + * Setup the transport for the OpenGloves interface. + */ + [[nodiscard]] ITransport* setupTransport(void) + { +#if OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_SERIAL // Serial + auto* pSerial = &SERIAL_PORT; + pSerial->begin(SERIAL_BAUDRATE); + return new StreamTransport(pSerial); +#elif OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL // Bluetooth Serial + std::string name; +#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()); +#endif + BluetoothSerial* pBtSerial = new BluetoothSerial(); + pBtSerial->begin(name.c_str()); + return new BluetoothSerialTransport(*pBtSerial); +#else // Fallback +#error "Unsupported communication type" + return nullptr; +#endif + } +} // namespace SenseShift::OpenGloves::AutoConfig diff --git a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp index b198aac5..f0cb609a 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp @@ -65,11 +65,8 @@ namespace SenseShift::OpenGloves { }; class BluetoothSerialTransport : public IStreamTransport { - private: - std::string name; - public: - BluetoothSerialTransport(BluetoothSerial& channel, std::string name) : IStreamTransport(&channel), name(name){}; + BluetoothSerialTransport(BluetoothSerial& channel) : IStreamTransport(&channel){}; void setup() override { @@ -77,8 +74,6 @@ namespace SenseShift::OpenGloves { if (serial->isReady()) { return; } - - serial->begin(name.c_str()); } bool isReady() override From 83e95fea73ca8c8d4920ee5878e1d88037e5ea4a Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <lm@devolt.one> Date: Sun, 3 Sep 2023 23:56:24 +0400 Subject: [PATCH 30/82] feat(OpenGloves): debug performance --- ini/opengloves.ini | 4 ++-- lib/opengloves_task/opengloves_task.hpp | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ini/opengloves.ini b/ini/opengloves.ini index 15732211..f4526043 100644 --- a/ini/opengloves.ini +++ b/ini/opengloves.ini @@ -5,7 +5,7 @@ platform_packages = framework = arduino board = esp32doit-devkit-v1 upload_speed = 921600 -monitor_speed = 115200 +monitor_speed = 921600 build_flags = ${common.build_flags} -D OPENGLOVES @@ -13,7 +13,7 @@ build_flags = ${common.build_flags} ; Communication ; -D OPENGLOVES_COMMUNCATION=OPENGLOVES_COMM_SERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL ; Serial - -D SERIAL_BAUDRATE=115200 + -D SERIAL_BAUDRATE=921600 -D SERIAL_PORT=Serial ; Serial, Serial1, Serial2, Serial3 ; BTSerial '-D BTSERIAL_PREFIX="SenseShift_OG"' diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index 5d4b90db..87afffca 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -212,6 +212,9 @@ namespace OpenGloves { // Delay until the next update. auto elapsed = millis() - now; + + log_d("Update took %d ms, theoretical max rate is %dHz (target is %dHz)", elapsed, 1000 / elapsed, 1000 / this->config.updateIntervalMs); + if (elapsed < this->config.updateIntervalMs) { delay(this->config.updateIntervalMs - elapsed); } From 1f21404aa2d09dfd20717c562b9249f59d1739b0 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <lm@devolt.one> Date: Mon, 4 Sep 2023 00:25:52 +0400 Subject: [PATCH 31/82] feat(OpenGloves): add BLE stream --- .github/scripts/get_firmware_name.sh | 3 + .../mode_configs/opengloves/opengloves.cpp | 29 ++- ini/opengloves.ini | 6 +- lib/ble_serial/BLESerial.hpp | 224 ++++++++++++++++++ lib/ble_serial/library.json | 7 + lib/opengloves/og_constants.hpp | 1 + .../senseshift/opengloves/autoconfig.hpp | 9 +- .../opengloves/transport/stream.hpp | 28 ++- lib/opengloves_task/opengloves_task.hpp | 2 +- 9 files changed, 282 insertions(+), 27 deletions(-) create mode 100644 lib/ble_serial/BLESerial.hpp create mode 100644 lib/ble_serial/library.json diff --git a/.github/scripts/get_firmware_name.sh b/.github/scripts/get_firmware_name.sh index 63b0b610..36b1bfb9 100755 --- a/.github/scripts/get_firmware_name.sh +++ b/.github/scripts/get_firmware_name.sh @@ -62,6 +62,9 @@ getOpenGlovesName() { 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 diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index ff39cdff..76706b73 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -206,22 +206,21 @@ void setupMode() .priority = OPENGLOVES_FINGERS_TASK_PRIORITY, } ); - -#if FFB_ENABLED - ffbTask = new OpenGlovesForceFeedbackTask( - *communication, - handActuators, - UPDATE_RATE, - { - .name = "OpenGlovesForceFeedbackTask", - .stackDepth = 8192, - .priority = OPENGLOVES_FINGERS_TASK_PRIORITY, - } - ); - ffbTask->begin(); -#endif - trackingTask->begin(); + +// #if FFB_ENABLED +// ffbTask = new OpenGlovesForceFeedbackTask( +// *communication, +// handActuators, +// UPDATE_RATE, +// { +// .name = "OpenGlovesForceFeedbackTask", +// .stackDepth = 8192, +// .priority = OPENGLOVES_FINGERS_TASK_PRIORITY, +// } +// ); +// ffbTask->begin(); +// #endif } void loopMode() diff --git a/ini/opengloves.ini b/ini/opengloves.ini index f4526043..0160ae8d 100644 --- a/ini/opengloves.ini +++ b/ini/opengloves.ini @@ -5,15 +5,15 @@ platform_packages = framework = arduino board = esp32doit-devkit-v1 upload_speed = 921600 -monitor_speed = 921600 +monitor_speed = 115200 build_flags = ${common.build_flags} -D OPENGLOVES ; Communication - ; -D OPENGLOVES_COMMUNCATION=OPENGLOVES_COMM_SERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL + ; -D OPENGLOVES_COMMUNCATION=OPENGLOVES_COMM_SERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL, OPENGLOVES_COMM_BLESERIAL ; Serial - -D SERIAL_BAUDRATE=921600 + -D SERIAL_BAUDRATE=115200 -D SERIAL_PORT=Serial ; Serial, Serial1, Serial2, Serial3 ; BTSerial '-D BTSERIAL_PREFIX="SenseShift_OG"' diff --git a/lib/ble_serial/BLESerial.hpp b/lib/ble_serial/BLESerial.hpp new file mode 100644 index 00000000..89572837 --- /dev/null +++ b/lib/ble_serial/BLESerial.hpp @@ -0,0 +1,224 @@ +#pragma once +#ifndef BLESERIAL_H +#define BLESERIAL_H + +#include <Arduino.h> +#include <BLEDevice.h> +#include <BLEUtils.h> +#include <BLEServer.h> +#include <BLE2902.h> + +#define BLESERIAL_ATTRIBUTE_MAX_VALUE_LENGTH 20 +#define BLESERIAL_RECEIVE_BUFFER_SIZE 256 + +template<typename _Tp, size_t N> +class ByteRingBuffer { + public: + using ValueType = _Tp; + + void add(ValueType value) { + ringBuffer[newestIndex] = value; + newestIndex = (newestIndex + 1) % N; + length = min(length + 1, N); + } + + int pop() { // pops the oldest value off the ring buffer + if (length == 0) { + return -1; + } + ValueType result = ringBuffer[(N + newestIndex - length) % N]; + length -= 1; + return result; + } + + void clear() { + newestIndex = 0; + length = 0; + } + + int get(size_t index) { // this.get(0) is the oldest value, this.get(this.getLength() - 1) is the newest value + if (index < 0 || index >= length) { + return -1; + } + return ringBuffer[(N + newestIndex - length + index) % N]; + } + + size_t getLength() { return length; } + + private: + ValueType ringBuffer[N]; + size_t newestIndex = 0; + size_t length = 0; +}; + +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<uint8_t *>(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); + } + + void begin(const char *deviceName, const char *serviceUuid = SERVICE_UUID, const char *rxUuid = RX_UUID, const char *txUuid = TX_UUID) + { + // Create the BLE Device + log_d("Creating BLE device with name '%s'", deviceName); + BLEDevice::init(deviceName); + + BLEServer *pServer = BLEDevice::createServer(); + + this->begin(pServer, serviceUuid, rxUuid, txUuid); + } + + void begin(BLEServer* pServer, const char *serviceUuid = SERVICE_UUID, const char *rxUuid = RX_UUID, const char *txUuid = TX_UUID) + { + log_d("Creating BLE service with UUID '%s'", serviceUuid); + BLEService *pService = pServer->getServiceByUUID(serviceUuid); + if (pService == nullptr) { + pService = pServer->createService(serviceUuid); + } + + log_d("Creating BLE characteristics with UUIDs '%s' (RX) and '%s' (TX)", rxUuid, txUuid); + auto pRxCharacteristic = pService->createCharacteristic(rxUuid, BLECharacteristic::PROPERTY_WRITE); + auto pTxCharacteristic = pService->createCharacteristic(txUuid, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY); + + this->begin(pServer, pRxCharacteristic, pTxCharacteristic); + + pService->start(); + log_d("Started BLE service"); + + BLEAdvertising *pAdvertising = pServer->getAdvertising(); + pAdvertising->start(); + log_d("Started BLE advertising"); + } + + void begin(BLEServer* pServer, BLECharacteristic *pRxCharacteristic, BLECharacteristic *pTxCharacteristic); + + bool connected() + { + return m_pServer != nullptr && m_pServer->getConnectedCount() > 0; + } + + private: + BLESerial(BLESerial const &other) = delete; // disable copy constructor + void operator=(BLESerial const &other) = delete; // disable assign constructor + + ByteRingBuffer<uint8_t, BLESERIAL_RECEIVE_BUFFER_SIZE> m_receiveBuffer; + + BLEServer *m_pServer; + BLECharacteristic *m_pRxCharacteristic; + BLECharacteristic *m_pTxCharacteristic; +}; + +class BLESerialServerCallbacks : public BLEServerCallbacks +{ + void onConnect(BLEServer *pServer) override + { + + } + + void onDisconnect(BLEServer *pServer) override + { + auto* pAdvertising = pServer->getAdvertising(); + if (pAdvertising == nullptr) + { + return; + } + pAdvertising->start(); + } +}; + +class BLESerialCharacteristicCallbacks : public BLECharacteristicCallbacks +{ + public: + BLESerialCharacteristicCallbacks(BLESerial *bleSerial) : bleSerial(bleSerial) {} + + void onWrite(BLECharacteristic *pCharacteristic) + { + if (pCharacteristic != bleSerial->m_pRxCharacteristic) + { + return; + } + + std::string rxValue = pCharacteristic->getValue(); + for (int i = 0; i < rxValue.length(); i++) + { + bleSerial->m_receiveBuffer.add(rxValue[i]); + } + } + + private: + BLESerial *bleSerial; +}; + +void BLESerial::begin(BLEServer* pServer, BLECharacteristic *pRxCharacteristic, BLECharacteristic *pTxCharacteristic) +{ + this->m_pServer = pServer; + 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/ble_serial/library.json b/lib/ble_serial/library.json new file mode 100644 index 00000000..e237d1ef --- /dev/null +++ b/lib/ble_serial/library.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", + "frameworks": "arduino", + "platforms": [ + "espressif32" + ] +} diff --git a/lib/opengloves/og_constants.hpp b/lib/opengloves/og_constants.hpp index 6d612517..df163940 100644 --- a/lib/opengloves/og_constants.hpp +++ b/lib/opengloves/og_constants.hpp @@ -4,3 +4,4 @@ #define OPENGLOVES_COMM_SERIAL 0x1 #define OPENGLOVES_COMM_BTSERIAL 0x2 +#define OPENGLOVES_COMM_BLESERIAL 0x3 diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index ed585ef4..0fbe65fa 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -163,7 +163,7 @@ namespace SenseShift::OpenGloves::AutoConfig { auto* pSerial = &SERIAL_PORT; pSerial->begin(SERIAL_BAUDRATE); return new StreamTransport(pSerial); -#elif OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL // Bluetooth Serial +#elif (OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL) || (OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BLESERIAL) // Bluetooth Serial std::string name; #ifdef BTSERIAL_NAME name = BTSERIAL_NAME; @@ -174,9 +174,16 @@ namespace SenseShift::OpenGloves::AutoConfig { log_i("Generated Bluetooth name: %s", name.c_str()); #endif + +#if OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL // Bluetooth Classic BluetoothSerial* pBtSerial = new BluetoothSerial(); pBtSerial->begin(name.c_str()); return new BluetoothSerialTransport(*pBtSerial); +#elif OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BLESERIAL // Bluetooth Low Energy + BLESerial* pBleSerial = new BLESerial(); + pBleSerial->begin(name.c_str()); + return new BLESerialTransport(*pBleSerial); +#endif #else // Fallback #error "Unsupported communication type" return nullptr; diff --git a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp index f0cb609a..72c94048 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp @@ -1,6 +1,7 @@ #pragma once #include <BluetoothSerial.h> +#include <BLESerial.hpp> #include <HardwareSerial.h> #include <Print.h> #include <WiFi.h> @@ -25,7 +26,7 @@ namespace SenseShift::OpenGloves { return 0; } - const auto written = this->channel->write(buffer); + const auto written = this->channel->write(buffer, length); this->channel->flush(); return written; @@ -68,18 +69,31 @@ namespace SenseShift::OpenGloves { public: BluetoothSerialTransport(BluetoothSerial& channel) : IStreamTransport(&channel){}; - void setup() override + bool isReady() override { auto* serial = static_cast<BluetoothSerial*>(this->channel); - if (serial->isReady()) { - return; - } + return serial->isReady() && serial->hasClient(); } + virtual size_t send(const char* buffer, size_t length) override + { + auto written = this->channel->write(buffer, length); + + // TODO: This is a hack to ensure the data is sent + delay(2); + + return written; + } + }; + + class BLESerialTransport : public IStreamTransport { + public: + BLESerialTransport(BLESerial& channel) : IStreamTransport(&channel){}; + bool isReady() override { - auto* serial = static_cast<BluetoothSerial*>(this->channel); - return serial->isReady() && serial->hasClient(); + auto* serial = static_cast<BLESerial*>(this->channel); + return serial->connected(); } }; diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index 87afffca..c45ea604 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -213,7 +213,7 @@ namespace OpenGloves { // Delay until the next update. auto elapsed = millis() - now; - log_d("Update took %d ms, theoretical max rate is %dHz (target is %dHz)", elapsed, 1000 / elapsed, 1000 / this->config.updateIntervalMs); + log_i("Update took %d ms, theoretical max rate is %dHz (target is %dHz)", elapsed, 1000 / elapsed, 1000 / this->config.updateIntervalMs); if (elapsed < this->config.updateIntervalMs) { delay(this->config.updateIntervalMs - elapsed); From f8a9deb3ffb985082e4adcbdec547430b21cf763 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 4 Sep 2023 01:09:19 +0400 Subject: [PATCH 32/82] style(clang-format): fix formatting --- .../mode_configs/opengloves/opengloves.cpp | 26 +-- lib/ble_serial/BLESerial.hpp | 155 ++++++++---------- lib/io/senseshift/input/sensor.hpp | 7 +- .../senseshift/opengloves/autoconfig.hpp | 33 ++-- .../senseshift/opengloves/encoding/alpha.cpp | 8 +- .../opengloves/transport/stream.hpp | 2 +- lib/opengloves_task/opengloves_task.hpp | 7 +- 7 files changed, 116 insertions(+), 122 deletions(-) diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 76706b73..3ebfca56 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -208,19 +208,19 @@ void setupMode() ); trackingTask->begin(); -// #if FFB_ENABLED -// ffbTask = new OpenGlovesForceFeedbackTask( -// *communication, -// handActuators, -// UPDATE_RATE, -// { -// .name = "OpenGlovesForceFeedbackTask", -// .stackDepth = 8192, -// .priority = OPENGLOVES_FINGERS_TASK_PRIORITY, -// } -// ); -// ffbTask->begin(); -// #endif +#if FFB_ENABLED + ffbTask = new OpenGlovesForceFeedbackTask( + *communication, + handActuators, + UPDATE_RATE, + { + .name = "OpenGlovesForceFeedbackTask", + .stackDepth = 8192, + .priority = OPENGLOVES_FINGERS_TASK_PRIORITY, + } + ); + ffbTask->begin(); +#endif } void loopMode() diff --git a/lib/ble_serial/BLESerial.hpp b/lib/ble_serial/BLESerial.hpp index 89572837..781e3840 100644 --- a/lib/ble_serial/BLESerial.hpp +++ b/lib/ble_serial/BLESerial.hpp @@ -3,10 +3,10 @@ #define BLESERIAL_H #include <Arduino.h> +#include <BLE2902.h> #include <BLEDevice.h> -#include <BLEUtils.h> #include <BLEServer.h> -#include <BLE2902.h> +#include <BLEUtils.h> #define BLESERIAL_ATTRIBUTE_MAX_VALUE_LENGTH 20 #define BLESERIAL_RECEIVE_BUFFER_SIZE 256 @@ -16,31 +16,35 @@ class ByteRingBuffer { public: using ValueType = _Tp; - void add(ValueType value) { - ringBuffer[newestIndex] = value; - newestIndex = (newestIndex + 1) % N; - length = min(length + 1, N); + void add(ValueType value) + { + ringBuffer[newestIndex] = value; + newestIndex = (newestIndex + 1) % N; + length = min(length + 1, N); } - int pop() { // pops the oldest value off the ring buffer - if (length == 0) { - return -1; - } - ValueType result = ringBuffer[(N + newestIndex - length) % N]; - length -= 1; - return result; + int pop() + { // pops the oldest value off the ring buffer + if (length == 0) { + return -1; + } + ValueType result = ringBuffer[(N + newestIndex - length) % N]; + length -= 1; + return result; } - void clear() { - newestIndex = 0; - length = 0; + void clear() + { + newestIndex = 0; + length = 0; } - int get(size_t index) { // this.get(0) is the oldest value, this.get(this.getLength() - 1) is the newest value - if (index < 0 || index >= length) { - return -1; - } - return ringBuffer[(N + newestIndex - length + index) % N]; + int get(size_t index) + { // this.get(0) is the oldest value, this.get(this.getLength() - 1) is the newest value + if (index < 0 || index >= length) { + return -1; + } + return ringBuffer[(N + newestIndex - length + index) % N]; } size_t getLength() { return length; } @@ -54,41 +58,30 @@ class ByteRingBuffer { class BLESerialCharacteristicCallbacks; class BLESerialServerCallbacks; -class BLESerial : public Stream -{ +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"; + 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 available() override { return m_receiveBuffer.getLength(); } - virtual int peek() override - { - return m_receiveBuffer.get(0); - } + virtual int peek() override { return m_receiveBuffer.get(0); } - virtual int read() override - { - return m_receiveBuffer.pop(); - } + virtual int read() override { return m_receiveBuffer.pop(); } - virtual size_t write(const uint8_t *buffer, size_t bufferSize) override + virtual size_t write(const uint8_t* buffer, size_t bufferSize) override { - if (this->m_pTxCharacteristic == nullptr || !this->connected()) - { + if (this->m_pTxCharacteristic == nullptr || !this->connected()) { return 0; } - this->m_pTxCharacteristic->setValue(const_cast<uint8_t *>(buffer), bufferSize); + this->m_pTxCharacteristic->setValue(const_cast<uint8_t*>(buffer), bufferSize); this->flush(); return bufferSize; @@ -96,8 +89,7 @@ class BLESerial : public Stream virtual size_t write(uint8_t byte) override { - if (this->m_pTxCharacteristic == nullptr || !this->connected()) - { + if (this->m_pTxCharacteristic == nullptr || !this->connected()) { return 0; } @@ -107,104 +99,101 @@ class BLESerial : public Stream return 1; } - virtual void flush(void) override - { - this->m_pTxCharacteristic->notify(true); - } + virtual void flush(void) override { this->m_pTxCharacteristic->notify(true); } - void begin(const char *deviceName, const char *serviceUuid = SERVICE_UUID, const char *rxUuid = RX_UUID, const char *txUuid = TX_UUID) + void begin( + const char* deviceName, + const char* serviceUuid = SERVICE_UUID, + const char* rxUuid = RX_UUID, + const char* txUuid = TX_UUID + ) { // Create the BLE Device log_d("Creating BLE device with name '%s'", deviceName); BLEDevice::init(deviceName); - BLEServer *pServer = BLEDevice::createServer(); + BLEServer* pServer = BLEDevice::createServer(); this->begin(pServer, serviceUuid, rxUuid, txUuid); } - void begin(BLEServer* pServer, const char *serviceUuid = SERVICE_UUID, const char *rxUuid = RX_UUID, const char *txUuid = TX_UUID) + void begin( + BLEServer* pServer, + const char* serviceUuid = SERVICE_UUID, + const char* rxUuid = RX_UUID, + const char* txUuid = TX_UUID + ) { log_d("Creating BLE service with UUID '%s'", serviceUuid); - BLEService *pService = pServer->getServiceByUUID(serviceUuid); + BLEService* pService = pServer->getServiceByUUID(serviceUuid); if (pService == nullptr) { pService = pServer->createService(serviceUuid); } log_d("Creating BLE characteristics with UUIDs '%s' (RX) and '%s' (TX)", rxUuid, txUuid); auto pRxCharacteristic = pService->createCharacteristic(rxUuid, BLECharacteristic::PROPERTY_WRITE); - auto pTxCharacteristic = pService->createCharacteristic(txUuid, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY); + auto pTxCharacteristic = + pService->createCharacteristic(txUuid, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY); this->begin(pServer, pRxCharacteristic, pTxCharacteristic); pService->start(); log_d("Started BLE service"); - BLEAdvertising *pAdvertising = pServer->getAdvertising(); + BLEAdvertising* pAdvertising = pServer->getAdvertising(); pAdvertising->start(); log_d("Started BLE advertising"); } - void begin(BLEServer* pServer, BLECharacteristic *pRxCharacteristic, BLECharacteristic *pTxCharacteristic); + void begin(BLEServer* pServer, BLECharacteristic* pRxCharacteristic, BLECharacteristic* pTxCharacteristic); - bool connected() - { - return m_pServer != nullptr && m_pServer->getConnectedCount() > 0; - } + bool connected() { return m_pServer != nullptr && m_pServer->getConnectedCount() > 0; } private: - BLESerial(BLESerial const &other) = delete; // disable copy constructor - void operator=(BLESerial const &other) = delete; // disable assign constructor + BLESerial(BLESerial const& other) = delete; // disable copy constructor + void operator=(BLESerial const& other) = delete; // disable assign constructor ByteRingBuffer<uint8_t, BLESERIAL_RECEIVE_BUFFER_SIZE> m_receiveBuffer; - BLEServer *m_pServer; - BLECharacteristic *m_pRxCharacteristic; - BLECharacteristic *m_pTxCharacteristic; + BLEServer* m_pServer; + BLECharacteristic* m_pRxCharacteristic; + BLECharacteristic* m_pTxCharacteristic; }; -class BLESerialServerCallbacks : public BLEServerCallbacks -{ - void onConnect(BLEServer *pServer) override - { - - } +class BLESerialServerCallbacks : public BLEServerCallbacks { + void onConnect(BLEServer* pServer) override {} - void onDisconnect(BLEServer *pServer) override + void onDisconnect(BLEServer* pServer) override { auto* pAdvertising = pServer->getAdvertising(); - if (pAdvertising == nullptr) - { + if (pAdvertising == nullptr) { return; } pAdvertising->start(); } }; -class BLESerialCharacteristicCallbacks : public BLECharacteristicCallbacks -{ +class BLESerialCharacteristicCallbacks : public BLECharacteristicCallbacks { public: - BLESerialCharacteristicCallbacks(BLESerial *bleSerial) : bleSerial(bleSerial) {} + BLESerialCharacteristicCallbacks(BLESerial* bleSerial) : bleSerial(bleSerial) {} - void onWrite(BLECharacteristic *pCharacteristic) + void onWrite(BLECharacteristic* pCharacteristic) { - if (pCharacteristic != bleSerial->m_pRxCharacteristic) - { + if (pCharacteristic != bleSerial->m_pRxCharacteristic) { return; } std::string rxValue = pCharacteristic->getValue(); - for (int i = 0; i < rxValue.length(); i++) - { + for (int i = 0; i < rxValue.length(); i++) { bleSerial->m_receiveBuffer.add(rxValue[i]); } } private: - BLESerial *bleSerial; + BLESerial* bleSerial; }; -void BLESerial::begin(BLEServer* pServer, BLECharacteristic *pRxCharacteristic, BLECharacteristic *pTxCharacteristic) +void BLESerial::begin(BLEServer* pServer, BLECharacteristic* pRxCharacteristic, BLECharacteristic* pTxCharacteristic) { this->m_pServer = pServer; this->m_pRxCharacteristic = pRxCharacteristic; diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index c3ce962c..d1fe8b51 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -109,13 +109,12 @@ namespace SenseShift::Input { } }; - template <typename _Tp> - class AverageSensor : public ISimpleSensor<_Tp> - { + template<typename _Tp> + class AverageSensor : public ISimpleSensor<_Tp> { static_assert(std::is_arithmetic<_Tp>::value, "AverageSensor only supports arithmetic types"); public: - AverageSensor(ISimpleSensor<_Tp>* sensor, size_t samples) : sensor(sensor), samples(samples){ } + AverageSensor(ISimpleSensor<_Tp>* sensor, size_t samples) : sensor(sensor), samples(samples) {} void init() override { this->sensor->init(); }; diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index 0fbe65fa..cebdefe2 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -75,10 +75,10 @@ new curl_calib() \ ), \ new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Input::AverageSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<splay_invert>(splay_pin), \ - 5 \ - ), \ + new ::SenseShift::Input::AverageSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<splay_invert>(splay_pin), \ + 5 \ + ), \ new splay_calib() \ ), \ type \ @@ -91,16 +91,16 @@ #define JOYSTICK_ENABLED \ (defined(PIN_JOYSTICK_X) && defined(PIN_JOYSTICK_Y) && (PIN_JOYSTICK_X != -1) && (PIN_JOYSTICK_Y != -1)) -#define JOYSTICK_CLASS(type, pin, invert, deadzone) \ - StringEncodedMemoizedSensor<uint16_t>( \ - new ::SenseShift::Input::JoystickAxisSensor<uint16_t>( \ - new ::SenseShift::Input::AverageSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<invert>(pin), \ - 5 \ - ), \ - deadzone \ - ), \ - type \ +#define JOYSTICK_CLASS(type, pin, invert, deadzone) \ + StringEncodedMemoizedSensor<uint16_t>( \ + new ::SenseShift::Input::JoystickAxisSensor<uint16_t>( \ + new ::SenseShift::Input::AverageSensor<uint16_t>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<invert>(pin), \ + 5 \ + ), \ + deadzone \ + ), \ + type \ ) #pragma endregion @@ -163,7 +163,8 @@ namespace SenseShift::OpenGloves::AutoConfig { auto* pSerial = &SERIAL_PORT; pSerial->begin(SERIAL_BAUDRATE); return new StreamTransport(pSerial); -#elif (OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL) || (OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BLESERIAL) // Bluetooth Serial +#elif (OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL) \ + || (OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BLESERIAL) // Bluetooth Serial std::string name; #ifdef BTSERIAL_NAME name = BTSERIAL_NAME; @@ -175,7 +176,7 @@ namespace SenseShift::OpenGloves::AutoConfig { log_i("Generated Bluetooth name: %s", name.c_str()); #endif -#if OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL // Bluetooth Classic +#if OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL // Bluetooth Classic BluetoothSerial* pBtSerial = new BluetoothSerial(); pBtSerial->begin(name.c_str()); return new BluetoothSerialTransport(*pBtSerial); diff --git a/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp b/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp index 702a157c..ad1f4a1e 100644 --- a/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp +++ b/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp @@ -3,8 +3,8 @@ #include <string.h> namespace SenseShift::OpenGloves { - const std::map<AlphaEncodingService::Command, uint16_t> AlphaEncodingService::deserialize(const std::string& input_string - ) const + const std::map<AlphaEncodingService::Command, uint16_t> + AlphaEncodingService::deserialize(const std::string& input_string) const { std::map<Command, uint16_t> commands; @@ -58,8 +58,8 @@ namespace SenseShift::OpenGloves { commands[command] = number; } - const std::string AlphaEncodingService::serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors - ) + const std::string + AlphaEncodingService::serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors) { memset(this->writeBuffer, 0, 256); this->writeBuffer[0] = '\0'; diff --git a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp index 72c94048..f249f954 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp @@ -1,7 +1,7 @@ #pragma once -#include <BluetoothSerial.h> #include <BLESerial.hpp> +#include <BluetoothSerial.h> #include <HardwareSerial.h> #include <Print.h> #include <WiFi.h> diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index c45ea604..80f2cd9e 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -213,7 +213,12 @@ namespace OpenGloves { // Delay until the next update. auto elapsed = millis() - now; - log_i("Update took %d ms, theoretical max rate is %dHz (target is %dHz)", elapsed, 1000 / elapsed, 1000 / this->config.updateIntervalMs); + log_i( + "Update took %d ms, theoretical max rate is %dHz (target is %dHz)", + elapsed, + 1000 / elapsed, + 1000 / this->config.updateIntervalMs + ); if (elapsed < this->config.updateIntervalMs) { delay(this->config.updateIntervalMs - elapsed); From b3ef92ad7c2e0e42b4dd4bf40d46167a4592705a Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 4 Sep 2023 01:09:50 +0400 Subject: [PATCH 33/82] ci(GitHub): cover BLE transport --- .github/workflows/ci.yml | 22 +++++++++++++++++++--- ini/opengloves.ini | 2 +- lib/opengloves_task/opengloves_task.hpp | 2 +- platformio.ini | 2 ++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1119c892..fbba23fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ on: jobs: build-bhaptics: - name: Build ${{ matrix.target }} on ${{ matrix.os }} ${{ matrix.coverage && 'with coverage' || 'without coverage' }}, -D ${{ matrix.battery_flag }} -D ${{ matrix.serial_plotter_flag }} -D ${{ matrix.nimble_flag }} + name: Build ${{ matrix.target }} ${{ matrix.coverage && 'with coverage' || 'without coverage' }}, -D ${{ matrix.battery_flag }} -D ${{ matrix.serial_plotter_flag }} -D ${{ matrix.nimble_flag }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -135,7 +135,8 @@ jobs: - name: Change memory segments if: matrix.coverage run: | - sed -i "s/len\s=\s0x2c200\s-\s0xdb5c/len = 289888/" ~/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/memory.ld + sed -i "s/len\s=\s0x2c200\s-\s0xdb5c/len = 2898880/" ~/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/memory.ld + sed -i "/\[env\]/p; s/\[env\]/board_build.partitions = huge_app.csv/" platformio.ini - name: Build run: | @@ -159,6 +160,7 @@ jobs: retention-days: 1 build-opengloves: + name: Build ${{ matrix.target }} ${{ matrix.coverage && 'with coverage' || 'without coverage' }}, -D ${{ matrix.comm_flag }} -D ${{ matrix.curl_calibration_flag }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -193,6 +195,10 @@ jobs: target: indexer-csf comm_flag: COMMUNICATION_PROTOCOL=OPENGLOVES_COMM_BTSERIAL coverage: true + - os: ubuntu-latest + target: indexer-csf + comm_flag: COMMUNICATION_PROTOCOL=OPENGLOVES_COMM_BLESERIAL + coverage: true steps: - uses: actions/checkout@v3 @@ -269,14 +275,23 @@ jobs: - name: Change memory segments if: matrix.coverage run: | - sed -i "s/len\s=\s0x2c200\s-\s0xdb5c/len = 289888/" ~/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/memory.ld + sed -i "s/len\s=\s0x2c200\s-\s0xdb5c/len = 2898880/" ~/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/memory.ld + sed -i "/\[env\]/p; s/\[env\]/board_build.partitions = huge_app.csv/" platformio.ini - name: Build + if: matrix.coverage == false run: | echo "::group::platformio.ini" cat platformio.ini echo "::endgroup::" pio run --environment ${{matrix.target}} + - name: Build (debug) + if: matrix.coverage + run: | + echo "::group::platformio.ini" + cat platformio.ini + echo "::endgroup::" + pio debug --environment ${{matrix.target}} - name: Upload firmware Artifact if: matrix.coverage == false @@ -420,6 +435,7 @@ jobs: wokwi: needs: + - build-bhaptics - build-opengloves - test runs-on: ubuntu-latest diff --git a/ini/opengloves.ini b/ini/opengloves.ini index 0160ae8d..15e91d29 100644 --- a/ini/opengloves.ini +++ b/ini/opengloves.ini @@ -11,7 +11,7 @@ build_flags = ${common.build_flags} -D OPENGLOVES ; Communication - ; -D OPENGLOVES_COMMUNCATION=OPENGLOVES_COMM_SERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL, OPENGLOVES_COMM_BLESERIAL + -D OPENGLOVES_COMMUNCATION=OPENGLOVES_COMM_BLESERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL, OPENGLOVES_COMM_BLESERIAL ; Serial -D SERIAL_BAUDRATE=115200 -D SERIAL_PORT=Serial ; Serial, Serial1, Serial2, Serial3 diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index 80f2cd9e..a04c2f11 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -213,7 +213,7 @@ namespace OpenGloves { // Delay until the next update. auto elapsed = millis() - now; - log_i( + log_d( "Update took %d ms, theoretical max rate is %dHz (target is %dHz)", elapsed, 1000 / elapsed, diff --git a/platformio.ini b/platformio.ini index d2a48669..6787808b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -46,6 +46,8 @@ check_tool = clangtidy check_flags = clangtidy: --config-file=./.clang-tidy --fix +debug_build_flags = -Os + [env:native] platform = native From 1b91c221309e83a9f7b94967781772c5277af34a Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 4 Sep 2023 09:22:16 +0400 Subject: [PATCH 34/82] feat(IO): add Median Filter sensor --- lib/io/senseshift/input/sensor.hpp | 26 ++++++++++ .../senseshift/opengloves/autoconfig.hpp | 48 +++++++++---------- test/test_io_sensor/main.cpp | 44 +++++++++++++++-- 3 files changed, 89 insertions(+), 29 deletions(-) diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index d1fe8b51..2520cd76 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -133,4 +133,30 @@ namespace SenseShift::Input { ISimpleSensor<_Tp>* sensor; size_t samples; }; + + template<typename _Tp, size_t _Samples> + class StaticMedianSensor : public ISimpleSensor<_Tp> { + static_assert(std::is_arithmetic<_Tp>::value, "StaticMedianSensor only supports arithmetic types"); + static_assert(_Samples % 2 == 1, "StaticMedianSensor only supports odd sample sizes"); + + public: + StaticMedianSensor(ISimpleSensor<_Tp>* sensor) : sensor(sensor) {} + + void init() override { this->sensor->init(); }; + + _Tp getValue() override + { + for (size_t i = 0; i < _Samples; i++) { + this->values[i] = this->sensor->getValue(); + } + + std::sort(this->values, this->values + _Samples); + + return this->values[_Samples / 2]; + } + + private: + _Tp values[_Samples]; + ISimpleSensor<_Tp>* sensor; + }; } // namespace SenseShift::Input diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index cebdefe2..191a8c06 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -48,16 +48,15 @@ #define FINGER_MIDDLE_ENABLED (defined(PIN_FINGER_MIDDLE) && (PIN_FINGER_MIDDLE != -1)) #define FINGER_RING_ENABLED (defined(PIN_FINGER_RING) && (PIN_FINGER_RING != -1)) #define FINGER_PINKY_ENABLED (defined(PIN_FINGER_PINKY) && (PIN_FINGER_PINKY != -1)) -#define FINGER_CLASS(type, curl_pin, curl_invert, curl_calib) \ - FingerSensor( \ - new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Input::AverageSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ - 5 \ - ), \ - new curl_calib() \ - ), \ - type \ +#define FINGER_CLASS(type, curl_pin, curl_invert, curl_calib) \ + FingerSensor( \ + new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ + new ::SenseShift::Input::StaticMedianSensor<uint16_t, 5>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin) \ + ), \ + new curl_calib() \ + ), \ + type \ ) #define FINGER_THUMB_SPLAY (FINGER_THUMB_ENABLED && defined(PIN_FINGER_THUMB_SPLAY) && (PIN_FINGER_THUMB_SPLAY != -1)) #define FINGER_INDEX_SPLAY (FINGER_INDEX_ENABLED && defined(PIN_FINGER_INDEX_SPLAY) && (PIN_FINGER_INDEX_SPLAY != -1)) @@ -68,16 +67,14 @@ #define FINGER_SPLAY_CLASS(type, curl_pin, curl_invert, curl_calib, splay_pin, splay_invert, splay_calib) \ FingerSensor( \ new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Input::AverageSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin), \ - 5 \ + new ::SenseShift::Input::StaticMedianSensor<uint16_t, 5>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin) \ ), \ new curl_calib() \ ), \ new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Input::AverageSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<splay_invert>(splay_pin), \ - 5 \ + new ::SenseShift::Input::StaticMedianSensor<uint16_t, 5>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<splay_invert>(splay_pin) \ ), \ new splay_calib() \ ), \ @@ -91,16 +88,15 @@ #define JOYSTICK_ENABLED \ (defined(PIN_JOYSTICK_X) && defined(PIN_JOYSTICK_Y) && (PIN_JOYSTICK_X != -1) && (PIN_JOYSTICK_Y != -1)) -#define JOYSTICK_CLASS(type, pin, invert, deadzone) \ - StringEncodedMemoizedSensor<uint16_t>( \ - new ::SenseShift::Input::JoystickAxisSensor<uint16_t>( \ - new ::SenseShift::Input::AverageSensor<uint16_t>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<invert>(pin), \ - 5 \ - ), \ - deadzone \ - ), \ - type \ +#define JOYSTICK_CLASS(type, pin, invert, deadzone) \ + StringEncodedMemoizedSensor<uint16_t>( \ + new ::SenseShift::Input::JoystickAxisSensor<uint16_t>( \ + new ::SenseShift::Input::StaticMedianSensor<uint16_t, 5>( \ + new ::SenseShift::Arduino::Input::AnalogSensor<invert>(pin) \ + ), \ + deadzone \ + ), \ + type \ ) #pragma endregion diff --git a/test/test_io_sensor/main.cpp b/test/test_io_sensor/main.cpp index c0b75acb..74b4ace3 100644 --- a/test/test_io_sensor/main.cpp +++ b/test/test_io_sensor/main.cpp @@ -5,10 +5,8 @@ using namespace SenseShift::Input; using namespace SenseShift::Calibration; class TestAnalogSensor : public ISimpleSensor<int> { - private: - int count = 0; - public: + int count = 0; int setupCounter = 0; void init() override { this->setupCounter++; }; @@ -72,12 +70,52 @@ void test_calibrated_sensor(void) TEST_ASSERT_EQUAL_INT(1, calibrator->resetCounter); } +void test_average_sensor(void) +{ + auto inner = new TestAnalogSensor(); + auto sensor = new AverageSensor<int>(inner, 3); + + TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); + sensor->init(); + TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); + + // TODO: mock inner sensor, to return more interesting values + TEST_ASSERT_EQUAL_INT(2, sensor->getValue()); // (1 + 2 + 3) / 3 = 2 + TEST_ASSERT_EQUAL_INT(5, sensor->getValue()); // (4 + 5 + 6) / 3 = 5 + TEST_ASSERT_EQUAL_INT(8, sensor->getValue()); // (7 + 8 + 9) / 3 = 8 + TEST_ASSERT_EQUAL_INT(11, sensor->getValue()); // (10 + 11 + 12) / 3 = 11 + + inner->count = 0; + sensor = new AverageSensor<int>(inner, 10); + + TEST_ASSERT_EQUAL_INT(5, sensor->getValue()); // (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10) / 10 = 5 +} + +void test_static_median_sensor(void) +{ + auto inner = new TestAnalogSensor(); + auto sensor = new StaticMedianSensor<int, 3>(inner); + + TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); + sensor->init(); + TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); + + // lmao, literally the same as average sensor + // TODO: mock inner sensor, to return more interesting values + TEST_ASSERT_EQUAL_INT(2, sensor->getValue()); // (1, 2, 3) = 2 + TEST_ASSERT_EQUAL_INT(5, sensor->getValue()); // (4, 5, 6) = 5 + TEST_ASSERT_EQUAL_INT(8, sensor->getValue()); // (7, 8, 9) = 8 + TEST_ASSERT_EQUAL_INT(11, sensor->getValue()); // (10, 11, 12) = 11 +} + int process(void) { UNITY_BEGIN(); RUN_TEST(test_memoized_sensor); RUN_TEST(test_calibrated_sensor); + RUN_TEST(test_average_sensor); + RUN_TEST(test_static_median_sensor); return UNITY_END(); } From 3161613f18985f04751fb0bfb4a36367797b6915 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 4 Sep 2023 19:54:36 +0400 Subject: [PATCH 35/82] refactor: decouple buffer from BLE Serial --- ini/opengloves.ini | 2 +- lib/ble_serial/BLESerial.hpp | 66 ++++--------- lib/util/senseshift/buffer.hpp | 123 ++++++++++++++++++++++++ test/test_util_buffer/main.cpp | 169 +++++++++++++++++++++++++++++++++ 4 files changed, 313 insertions(+), 47 deletions(-) create mode 100644 lib/util/senseshift/buffer.hpp create mode 100644 test/test_util_buffer/main.cpp diff --git a/ini/opengloves.ini b/ini/opengloves.ini index 15e91d29..0160ae8d 100644 --- a/ini/opengloves.ini +++ b/ini/opengloves.ini @@ -11,7 +11,7 @@ build_flags = ${common.build_flags} -D OPENGLOVES ; Communication - -D OPENGLOVES_COMMUNCATION=OPENGLOVES_COMM_BLESERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL, OPENGLOVES_COMM_BLESERIAL + ; -D OPENGLOVES_COMMUNCATION=OPENGLOVES_COMM_SERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL, OPENGLOVES_COMM_BLESERIAL ; Serial -D SERIAL_BAUDRATE=115200 -D SERIAL_PORT=Serial ; Serial, Serial1, Serial2, Serial3 diff --git a/lib/ble_serial/BLESerial.hpp b/lib/ble_serial/BLESerial.hpp index 781e3840..8e4cd4bc 100644 --- a/lib/ble_serial/BLESerial.hpp +++ b/lib/ble_serial/BLESerial.hpp @@ -8,52 +8,12 @@ #include <BLEServer.h> #include <BLEUtils.h> -#define BLESERIAL_ATTRIBUTE_MAX_VALUE_LENGTH 20 -#define BLESERIAL_RECEIVE_BUFFER_SIZE 256 - -template<typename _Tp, size_t N> -class ByteRingBuffer { - public: - using ValueType = _Tp; - - void add(ValueType value) - { - ringBuffer[newestIndex] = value; - newestIndex = (newestIndex + 1) % N; - length = min(length + 1, N); - } - - int pop() - { // pops the oldest value off the ring buffer - if (length == 0) { - return -1; - } - ValueType result = ringBuffer[(N + newestIndex - length) % N]; - length -= 1; - return result; - } - - void clear() - { - newestIndex = 0; - length = 0; - } - - int get(size_t index) - { // this.get(0) is the oldest value, this.get(this.getLength() - 1) is the newest value - if (index < 0 || index >= length) { - return -1; - } - return ringBuffer[(N + newestIndex - length + index) % N]; - } +#include <algorithm> - size_t getLength() { return length; } +#include <senseshift/buffer.hpp> - private: - ValueType ringBuffer[N]; - size_t newestIndex = 0; - size_t length = 0; -}; +#define BLESERIAL_ATTRIBUTE_MAX_VALUE_LENGTH 20 +#define BLESERIAL_RECEIVE_BUFFER_SIZE 256 class BLESerialCharacteristicCallbacks; class BLESerialServerCallbacks; @@ -80,6 +40,20 @@ class BLESerial : public Stream { if (this->m_pTxCharacteristic == nullptr || !this->connected()) { return 0; } + // uint16_t mtu = BLEDevice::getMTU(); + // uint16_t packetSize = mtu > 3 ? mtu - 3 : 20; + + // chunk the buffer into packets + // for (size_t i = 0; i < bufferSize; i += packetSize) { + // auto chunkSize = static_cast<uint16_t>(std::min(static_cast<size_t>(packetSize), bufferSize - i)); + // this->m_pTxCharacteristic->setValue(const_cast<uint8_t*>(buffer + i), chunkSize); + // this->flush(); + + // // delay if not last packet + // if (i + chunkSize < bufferSize) { + // delay(10); + // } + // } this->m_pTxCharacteristic->setValue(const_cast<uint8_t*>(buffer), bufferSize); this->flush(); @@ -131,7 +105,7 @@ class BLESerial : public Stream { } log_d("Creating BLE characteristics with UUIDs '%s' (RX) and '%s' (TX)", rxUuid, txUuid); - auto pRxCharacteristic = pService->createCharacteristic(rxUuid, BLECharacteristic::PROPERTY_WRITE); + auto pRxCharacteristic = pService->createCharacteristic(rxUuid, BLECharacteristic::PROPERTY_WRITE_NR); auto pTxCharacteristic = pService->createCharacteristic(txUuid, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY); @@ -153,7 +127,7 @@ class BLESerial : public Stream { BLESerial(BLESerial const& other) = delete; // disable copy constructor void operator=(BLESerial const& other) = delete; // disable assign constructor - ByteRingBuffer<uint8_t, BLESERIAL_RECEIVE_BUFFER_SIZE> m_receiveBuffer; + SenseShift::RingBuffer<uint8_t, BLESERIAL_RECEIVE_BUFFER_SIZE> m_receiveBuffer; BLEServer* m_pServer; BLECharacteristic* m_pRxCharacteristic; diff --git a/lib/util/senseshift/buffer.hpp b/lib/util/senseshift/buffer.hpp new file mode 100644 index 00000000..4b21a1cd --- /dev/null +++ b/lib/util/senseshift/buffer.hpp @@ -0,0 +1,123 @@ +#pragma once + +#include <algorithm> +#include <stddef.h> + +namespace SenseShift { + template<typename _Tp> + struct IBuffer { + using ValueType = _Tp; + + virtual void add(ValueType value) = 0; + virtual void clear() = 0; + virtual ValueType pop() = 0; + virtual ValueType get(size_t index) = 0; + virtual size_t getLength() = 0; + }; + + template<typename _Tp, size_t N> + class RingBuffer : public IBuffer<_Tp> { + public: + using ValueType = _Tp; + + void add(ValueType value) override + { + this->mRingBuffer[this->mNewestIndex] = value; + this->mNewestIndex = (this->mNewestIndex + 1) % N; + this->mLength = std::min(this->mLength + 1, N); + } + + 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. + * + * `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value + */ + ValueType get(size_t index) override + { + if (index < 0 || index >= this->mLength) { + return -1; + } + return this->mRingBuffer[(N + this->mNewestIndex - this->mLength + index) % N]; + } + + size_t getLength() override { return this->mLength; } + + private: + ValueType mRingBuffer[N]; + size_t mNewestIndex = 0; + size_t mLength = 0; + }; + + template<typename _Tp, size_t N> + class FlatBuffer : public IBuffer<_Tp> { + public: + using ValueType = _Tp; + + void add(ValueType value) override + { + if (this->mLength == N) { + return; + } + this->mBuffer[this->mLength] = value; + this->mLength += 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; + } + + /** + * @brief Get the value at the given index. + * + * `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value + */ + ValueType get(size_t index) override + { + if (index < 0 || index >= this->mLength) { + return -1; + } + return this->mBuffer[index]; + } + + size_t getLength() override { return this->mLength; } + + private: + ValueType mBuffer[N]; + size_t mLength = 0; + }; +} // namespace SenseShift diff --git a/test/test_util_buffer/main.cpp b/test/test_util_buffer/main.cpp new file mode 100644 index 00000000..595c6184 --- /dev/null +++ b/test/test_util_buffer/main.cpp @@ -0,0 +1,169 @@ +#include <senseshift/utility.hpp> +#include <unity.h> + +#include <senseshift/buffer.hpp> + +using namespace SenseShift; + +void test_ring_buffer(void) +{ + auto buffer = RingBuffer<char, 5>(); + + TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); + + buffer.add('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.add('a'); // [] => [a] + buffer.add('b'); // [a] => [a, b] + buffer.add('c'); // [a, b] => [a, b, c] + buffer.add('d'); // [a, b, c] => [a, b, c, d] + buffer.add('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.add('c'); // [] => [c] + buffer.add('d'); // [c] => [c, d] + buffer.add('e'); // [c, d] => [c, d, e] + buffer.add('f'); // [c, d, e] => [c, d, e, f] + buffer.add('g'); // [c, d, e, f] => [c, d, e, f, g] + buffer.add('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 = FlatBuffer<char, 5>(); + + TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); + + buffer.add('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.add('a'); // [] => [a] + buffer.add('b'); // [a] => [a, b] + buffer.add('c'); // [a, b] => [a, b, c] + buffer.add('d'); // [a, b, c] => [a, b, c, d] + buffer.add('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.add('c'); // [] => [c] + buffer.add('d'); // [c] => [c, d] + buffer.add('e'); // [c, d] => [c, d, e] + buffer.add('f'); // [c, d, e] => [c, d, e, f] + buffer.add('g'); // [c, d, e, f] => [c, d, e, f, g] + buffer.add('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 <Arduino.h> + +void setup(void) +{ + process(); +} + +void loop(void) {} + +#else + +int main(int argc, char** argv) +{ + return process(); +} + +#endif From 295ecc50790115b95137c91576fcd2b892895c54 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <leon.03.99@gmail.com> Date: Wed, 6 Sep 2023 16:20:37 +0400 Subject: [PATCH 36/82] refactor(BLE): optimize Serial lib --- lib/ble_serial/BLESerial.hpp | 182 +++++++++++++++++++++++++++-------- lib/ble_serial/library.json | 2 + 2 files changed, 143 insertions(+), 41 deletions(-) diff --git a/lib/ble_serial/BLESerial.hpp b/lib/ble_serial/BLESerial.hpp index 8e4cd4bc..6b0fbe54 100644 --- a/lib/ble_serial/BLESerial.hpp +++ b/lib/ble_serial/BLESerial.hpp @@ -40,20 +40,6 @@ class BLESerial : public Stream { if (this->m_pTxCharacteristic == nullptr || !this->connected()) { return 0; } - // uint16_t mtu = BLEDevice::getMTU(); - // uint16_t packetSize = mtu > 3 ? mtu - 3 : 20; - - // chunk the buffer into packets - // for (size_t i = 0; i < bufferSize; i += packetSize) { - // auto chunkSize = static_cast<uint16_t>(std::min(static_cast<size_t>(packetSize), bufferSize - i)); - // this->m_pTxCharacteristic->setValue(const_cast<uint8_t*>(buffer + i), chunkSize); - // this->flush(); - - // // delay if not last packet - // if (i + chunkSize < bufferSize) { - // delay(10); - // } - // } this->m_pTxCharacteristic->setValue(const_cast<uint8_t*>(buffer), bufferSize); this->flush(); @@ -75,22 +61,35 @@ class BLESerial : public Stream { 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 - ) - { - // Create the BLE Device - log_d("Creating BLE device with name '%s'", deviceName); - BLEDevice::init(deviceName); - - BLEServer* pServer = BLEDevice::createServer(); - - this->begin(pServer, serviceUuid, rxUuid, txUuid); - } - + ); + + /** + * 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, @@ -98,46 +97,124 @@ class BLESerial : public Stream { const char* txUuid = TX_UUID ) { - log_d("Creating BLE service with UUID '%s'", serviceUuid); 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); } - log_d("Creating BLE characteristics with UUIDs '%s' (RX) and '%s' (TX)", rxUuid, txUuid); - auto pRxCharacteristic = pService->createCharacteristic(rxUuid, BLECharacteristic::PROPERTY_WRITE_NR); - auto pTxCharacteristic = - pService->createCharacteristic(txUuid, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY); + // Store the service so we know if we're managing it + this->m_pService = pService; - this->begin(pServer, pRxCharacteristic, pTxCharacteristic); + this->begin(pService, rxUuid, txUuid); pService->start(); log_d("Started BLE service"); + } - BLEAdvertising* pAdvertising = pServer->getAdvertising(); - pAdvertising->start(); - log_d("Started BLE advertising"); + /** + * 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); } - void begin(BLEServer* pServer, BLECharacteristic* pRxCharacteristic, BLECharacteristic* 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<uint8_t, BLESERIAL_RECEIVE_BUFFER_SIZE> m_receiveBuffer; - BLEServer* m_pServer; - BLECharacteristic* m_pRxCharacteristic; - BLECharacteristic* m_pTxCharacteristic; + /** + * 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 { - void onConnect(BLEServer* pServer) override {} + public: + BLESerialServerCallbacks(BLESerial* bleSerial) : bleSerial(bleSerial) {} - void onDisconnect(BLEServer* pServer) override + 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) { @@ -145,6 +222,9 @@ class BLESerialServerCallbacks : public BLEServerCallbacks { } pAdvertising->start(); } + + private: + BLESerial* bleSerial; }; class BLESerialCharacteristicCallbacks : public BLECharacteristicCallbacks { @@ -167,9 +247,29 @@ class BLESerialCharacteristicCallbacks : public BLECharacteristicCallbacks { BLESerial* bleSerial; }; -void BLESerial::begin(BLEServer* pServer, BLECharacteristic* pRxCharacteristic, BLECharacteristic* pTxCharacteristic) +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; diff --git a/lib/ble_serial/library.json b/lib/ble_serial/library.json index e237d1ef..7c2d9618 100644 --- a/lib/ble_serial/library.json +++ b/lib/ble_serial/library.json @@ -1,5 +1,7 @@ { "$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" From 82d996cc1e126785eea14e6a73e66dde7acb306c Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Wed, 6 Sep 2023 22:48:55 +0400 Subject: [PATCH 37/82] docs: add Wokwi debug guide --- .devcontainer/Dockerfile | 1 + .devcontainer/devcontainer.json | 22 +++++++++++++-- .../lucidgloves-prototype3+serial/test.yaml | 6 ++-- .../lucidgloves-prototype3+serial/wokwi.toml | 2 ++ docs/DEVELOPMENT.md | 28 +++++++++++++++++++ 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index eac4101c..01f13c27 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -22,6 +22,7 @@ RUN apt-get update \ python3-venv \ python3-distutils \ python3-setuptools \ + libpython2.7-dev \ srecord \ udev \ xz-utils \ diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4ec06d5d..c629151a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,8 @@ { // "name": "SenseShift", - "dockerFile": "Dockerfile", + "build": { + "dockerfile": "Dockerfile" + }, "runArgs": [ "--privileged" ], @@ -18,17 +20,33 @@ "vscode": { "settings": { "terminal.integrated.defaultProfile.linux": "zsh", + "editor.formatOnPaste": false, "editor.formatOnSave": true, + "editor.formatOnType": true, "platformio-ide.useBuiltinPIOCore": false, "platformio-ide.useBuiltinPython": false, "platformio-ide.disablePIOHomeStartup": true, - "platformio-ide.pioHomeServerHttpPort": 8008 + "platformio-ide.pioHomeServerHttpPort": 8008, + "platformio-ide.autoOpenPlatformIOIniFile": false, + "files.exclude": { + "**/.git": true, + "**/.DS_Store": true + }, + "files.associations": { + "**/.vscode/*.json": "jsonc" + }, + "C_Cpp.clang_format_path": "clang-format" }, "extensions": [ "ms-vscode.cpptools", + "redhat.vscode-yaml", + "platformio.platformio-ide", "Wokwi.wokwi-vscode", + "xaver.clang-format", + "editorconfig.editorconfig", + "GitHub.copilot", "GitHub.copilot-labs", "GitHub.copilot-chat" diff --git a/.wokwi/lucidgloves-prototype3+serial/test.yaml b/.wokwi/lucidgloves-prototype3+serial/test.yaml index 0639c5cc..4cd7043b 100644 --- a/.wokwi/lucidgloves-prototype3+serial/test.yaml +++ b/.wokwi/lucidgloves-prototype3+serial/test.yaml @@ -68,9 +68,9 @@ steps: value: 1 - wait-serial: 'A4095B4095C4095D4095E4095F2047G2047ILM' # L is for the Grab gesture - # Release Thumb finger + # Partially Release Thumb finger - set-control: part-id: pot-thumb control: position - value: 0 - - wait-serial: 'A0B4095C4095D4095E4095F2047G2047IL' + value: 0.25 + - wait-serial: 'A1024B4095C4095D4095E4095F2047G2047IL' diff --git a/.wokwi/lucidgloves-prototype3+serial/wokwi.toml b/.wokwi/lucidgloves-prototype3+serial/wokwi.toml index 54e28de8..5878bf60 100644 --- a/.wokwi/lucidgloves-prototype3+serial/wokwi.toml +++ b/.wokwi/lucidgloves-prototype3+serial/wokwi.toml @@ -2,3 +2,5 @@ version = 1 firmware = "../../.pio/build/lucidgloves-prototype3/firmware.bin" elf = "../../.pio/build/lucidgloves-prototype3/firmware.elf" + +gdbServerPort=3333 diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index e7d53aef..dafd8ccf 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -1,3 +1,31 @@ +# Debugging + +## Debugging in Wokwi + +Run and debug firmware in Wokwi Simulator + +1. Run this command: + ```shell + pio debug -e lucidgloves-prototype3 + ``` +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)): + ```json + ... + + { + "name": "Wokwi GDB - lucidgloves-prototype3", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/.pio/build/lucidgloves-prototype3/firmware.elf", + "cwd": "${workspaceFolder}", + "MIMode": "gdb", + "miDebuggerPath": "${userHome}/.platformio/packages/toolchain-xtensa-esp32/bin/xtensa-esp32-elf-gdb", + "miDebuggerServerAddress": "localhost:3333", + }, + ... + ``` + ## Useful Scripts ### Fix `clang-format` From d8e45a0318215fc13ee01d8972ac16fb2fcc989d Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 7 Sep 2023 01:01:40 +0400 Subject: [PATCH 38/82] refactor(OpenGloves): optimize encoding --- lib/ble_serial/BLESerial.hpp | 2 +- .../senseshift/opengloves/encoding/alpha.cpp | 51 +++++++-------- .../senseshift/opengloves/encoding/alpha.hpp | 14 ++-- .../senseshift/opengloves/interface.hpp | 11 +++- lib/opengloves_task/opengloves_task.hpp | 10 +-- lib/util/senseshift/buffer.hpp | 65 +++++++++++++++---- lib/util/senseshift/range.hpp | 4 +- test/test_opengloves_alpha_encoding/main.cpp | 3 +- test/test_util_buffer/main.cpp | 50 +++++++------- 9 files changed, 129 insertions(+), 81 deletions(-) diff --git a/lib/ble_serial/BLESerial.hpp b/lib/ble_serial/BLESerial.hpp index 6b0fbe54..b239eec2 100644 --- a/lib/ble_serial/BLESerial.hpp +++ b/lib/ble_serial/BLESerial.hpp @@ -239,7 +239,7 @@ class BLESerialCharacteristicCallbacks : public BLECharacteristicCallbacks { std::string rxValue = pCharacteristic->getValue(); for (int i = 0; i < rxValue.length(); i++) { - bleSerial->m_receiveBuffer.add(rxValue[i]); + bleSerial->m_receiveBuffer.push(rxValue[i]); } } diff --git a/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp b/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp index ad1f4a1e..c9dc738d 100644 --- a/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp +++ b/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp @@ -3,14 +3,33 @@ #include <string.h> namespace SenseShift::OpenGloves { - const std::map<AlphaEncodingService::Command, uint16_t> - AlphaEncodingService::deserialize(const std::string& input_string) const + size_t AlphaEncodingService::serialize( + const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors, char* buffer + ) const { - std::map<Command, uint16_t> commands; + buffer[0] = '\0'; + size_t offset = 0; + + for (size_t i = 0; i < sensors.size(); i++) { + auto* sensor = sensors[i]; + offset += sensor->encodeString(buffer + offset); + } + + buffer[offset++] = '\n'; + buffer[offset] = '\0'; + + return offset; + } + + bool AlphaEncodingService::deserialize( + const char* buffer, const size_t length, std::map<::OpenGloves::Command, uint16_t>& commands + ) const + { + std::string input_string(buffer, length); size_t start = 0; // Start of the current command - for (size_t i = 0; i < input_string.size(); i++) { - char ch = input_string[i]; + for (size_t i = 0; i < input_string.length(); i++) { + const char ch = input_string[i]; // Start a new command if the character is non-numeric or an opening parenthesis // and previous character is a numeric character @@ -22,7 +41,7 @@ namespace SenseShift::OpenGloves { AlphaEncodingService::splitCommand(input_string, start, input_string.size(), commands); - return commands; + return true; } void AlphaEncodingService::splitCommand( @@ -57,24 +76,4 @@ namespace SenseShift::OpenGloves { Command command = it->second; commands[command] = number; } - - const std::string - AlphaEncodingService::serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors) - { - memset(this->writeBuffer, 0, 256); - this->writeBuffer[0] = '\0'; - - size_t offset = 0; - - for (size_t i = 0; i < sensors.size(); i++) { - // The offset is the total charecters already added to the string. - offset += sensors[i]->encodeString(this->writeBuffer + offset); - } - - // Add a newline and terminator to the end of the encoded string. - this->writeBuffer[offset++] = '\n'; - this->writeBuffer[offset] = '\0'; - - return std::string(this->writeBuffer, offset); - } } // namespace SenseShift::OpenGloves diff --git a/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp b/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp index 59830803..49d223cf 100644 --- a/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp +++ b/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp @@ -15,6 +15,8 @@ #include <senseshift/logging.hpp> #include <senseshift/opengloves/interface.hpp> +#define SENSESHIFT_OPENGLOVES_ALPHA_ENCODING_BUFFER_SIZE 256 + namespace SenseShift::OpenGloves { class AlphaEncodingService : public IEncoding { using Command = ::OpenGloves::Command; @@ -36,16 +38,16 @@ namespace SenseShift::OpenGloves { // clang-format on }); - AlphaEncodingService() : writeBuffer(new char[256]){}; + AlphaEncodingService(){}; - virtual const std::map<Command, uint16_t> deserialize(const std::string& buffer) const override; + virtual size_t serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors, char* buffer) + const override; - virtual const std::string serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors - ) override; + virtual bool deserialize( + const char* buffer, const size_t length, std::map<::OpenGloves::Command, uint16_t>& commands + ) const override; private: - char* writeBuffer; - static void splitCommand( const std::string& input_string, size_t start, size_t end, std::map<Command, uint16_t>& commands ); diff --git a/lib/opengloves/senseshift/opengloves/interface.hpp b/lib/opengloves/senseshift/opengloves/interface.hpp index 17815845..5e94b1e9 100644 --- a/lib/opengloves/senseshift/opengloves/interface.hpp +++ b/lib/opengloves/senseshift/opengloves/interface.hpp @@ -3,6 +3,8 @@ #include <cstddef> #include <cstdint> +#include <senseshift/buffer.hpp> + #include "og_protocol.hpp" namespace SenseShift::OpenGloves { @@ -14,8 +16,11 @@ namespace SenseShift::OpenGloves { }; struct IEncoding { - virtual const std::string serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors - ) = 0; - virtual const std::map<::OpenGloves::Command, uint16_t> deserialize(const std::string& buffer) const = 0; + virtual size_t + serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors, char* buffer) const = 0; + + virtual bool deserialize( + const char* buffer, const size_t length, std::map<::OpenGloves::Command, uint16_t>& commands + ) const = 0; }; } // namespace SenseShift::OpenGloves diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index a04c2f11..2f7bc581 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -197,8 +197,9 @@ namespace OpenGloves { } // Send the sensor values. - auto command = this->encodingService.serialize(this->allSensors); - this->communication.send(command.c_str(), command.size()); + char command[256]; + size_t length = this->encodingService.serialize(this->allSensors, command); + this->communication.send(command, length); // Check if the calibration has finished. if (!(this->config.alwaysCalibrate) && calibrationStarted > 0 && (now - calibrationStarted) > CALIBRATION_DURATION) { @@ -297,9 +298,8 @@ namespace OpenGloves { continue; } - command.assign(commandBuffer, bytesRead); - - auto commands = this->encodingService.deserialize(command); + std::map<::OpenGloves::Command, uint16_t> commands = {}; + this->encodingService.deserialize(commandBuffer, bytesRead, commands); for (auto& [command, value] : commands) { this->handleCommand(command, value); diff --git a/lib/util/senseshift/buffer.hpp b/lib/util/senseshift/buffer.hpp index 4b21a1cd..0dd1c85d 100644 --- a/lib/util/senseshift/buffer.hpp +++ b/lib/util/senseshift/buffer.hpp @@ -2,17 +2,24 @@ #include <algorithm> #include <stddef.h> +#include <string.h> namespace SenseShift { template<typename _Tp> struct IBuffer { using ValueType = _Tp; - virtual void add(ValueType value) = 0; + 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) = 0; - virtual size_t getLength() = 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<typename _Tp, size_t N> @@ -20,11 +27,26 @@ namespace SenseShift { public: using ValueType = _Tp; - void add(ValueType value) override + 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 @@ -52,7 +74,7 @@ namespace SenseShift { * * `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value */ - ValueType get(size_t index) override + ValueType get(size_t index) const override { if (index < 0 || index >= this->mLength) { return -1; @@ -60,7 +82,7 @@ namespace SenseShift { return this->mRingBuffer[(N + this->mNewestIndex - this->mLength + index) % N]; } - size_t getLength() override { return this->mLength; } + size_t getLength() const override { return this->mLength; } private: ValueType mRingBuffer[N]; @@ -69,17 +91,34 @@ namespace SenseShift { }; template<typename _Tp, size_t N> - class FlatBuffer : public IBuffer<_Tp> { + class FixedSizeBuffer : public IBuffer<_Tp> { public: using ValueType = _Tp; - void add(ValueType value) override + FixedSizeBuffer() = default; + virtual ~FixedSizeBuffer() = default; + + bool push(const ValueType value) override { if (this->mLength == N) { - return; + 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; } @@ -106,7 +145,7 @@ namespace SenseShift { * * `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value */ - ValueType get(size_t index) override + ValueType get(size_t index) const override { if (index < 0 || index >= this->mLength) { return -1; @@ -114,10 +153,12 @@ namespace SenseShift { return this->mBuffer[index]; } - size_t getLength() override { return this->mLength; } + ValueType* getData() { return this->mBuffer.data(); } + + size_t getLength() const override { return this->mLength; } private: - ValueType mBuffer[N]; + std::array<ValueType, N> mBuffer; size_t mLength = 0; }; } // namespace SenseShift diff --git a/lib/util/senseshift/range.hpp b/lib/util/senseshift/range.hpp index ea563482..6dac8598 100644 --- a/lib/util/senseshift/range.hpp +++ b/lib/util/senseshift/range.hpp @@ -5,7 +5,7 @@ namespace SenseShift { template<typename _Tp> - constexpr _Tp accurateMap(_Tp x, _Tp in_min, _Tp in_max, _Tp out_min, _Tp out_max) + constexpr _Tp accurateMap(_Tp x, _Tp in_min, _Tp in_max, _Tp out_min, _Tp out_max) noexcept { static_assert(std::is_arithmetic<_Tp>::value, "Type must be arithmetic"); @@ -21,7 +21,7 @@ namespace SenseShift { // Same as the above, but both mins are 0. template<typename _Tp> - constexpr inline _Tp simpleMap(_Tp x, _Tp in_max, _Tp out_max) + constexpr inline _Tp simpleMap(_Tp x, _Tp in_max, _Tp out_max) noexcept { static_assert(std::is_arithmetic<_Tp>::value, "Type must be arithmetic"); diff --git a/test/test_opengloves_alpha_encoding/main.cpp b/test/test_opengloves_alpha_encoding/main.cpp index 1f71136c..68be53cd 100644 --- a/test/test_opengloves_alpha_encoding/main.cpp +++ b/test/test_opengloves_alpha_encoding/main.cpp @@ -94,7 +94,8 @@ void testSplitCommands(void) auto encoding_service = AlphaEncodingService(); for (auto& [input_string, expected_commands] : input_strings) { - std::map<Command, uint16_t> commands = encoding_service.deserialize(input_string); + std::map<Command, uint16_t> commands = {}; + encoding_service.deserialize(input_string.c_str(), input_string.length(), commands); TEST_ASSERT_EQUAL_size_t_MESSAGE( expected_commands.size(), diff --git a/test/test_util_buffer/main.cpp b/test/test_util_buffer/main.cpp index 595c6184..40f1221c 100644 --- a/test/test_util_buffer/main.cpp +++ b/test/test_util_buffer/main.cpp @@ -11,7 +11,7 @@ void test_ring_buffer(void) TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); - buffer.add('a'); // [] => [a] + 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)); @@ -22,11 +22,11 @@ void test_ring_buffer(void) TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); // add 5 values and check length - buffer.add('a'); // [] => [a] - buffer.add('b'); // [a] => [a, b] - buffer.add('c'); // [a, b] => [a, b, c] - buffer.add('d'); // [a, b, c] => [a, b, c, d] - buffer.add('e'); // [a, b, c, d] => [a, b, c, d, e] + 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 @@ -53,12 +53,12 @@ void test_ring_buffer(void) TEST_ASSERT_EQUAL_INT8(-1, buffer.get(3)); // check overflow - buffer.add('c'); // [] => [c] - buffer.add('d'); // [c] => [c, d] - buffer.add('e'); // [c, d] => [c, d, e] - buffer.add('f'); // [c, d, e] => [c, d, e, f] - buffer.add('g'); // [c, d, e, f] => [c, d, e, f, g] - buffer.add('h'); // [c, d, e, f, g] => [d, e, f, g, h] + 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)); @@ -77,11 +77,11 @@ void test_ring_buffer(void) void test_flat_buffer(void) { - auto buffer = FlatBuffer<char, 5>(); + auto buffer = FixedSizeBuffer<char, 5>(); TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); - buffer.add('a'); // [] => [a] + 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)); @@ -92,11 +92,11 @@ void test_flat_buffer(void) TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); // add 5 values and check length - buffer.add('a'); // [] => [a] - buffer.add('b'); // [a] => [a, b] - buffer.add('c'); // [a, b] => [a, b, c] - buffer.add('d'); // [a, b, c] => [a, b, c, d] - buffer.add('e'); // [a, b, c, d] => [a, b, c, d, e] + 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 @@ -123,12 +123,12 @@ void test_flat_buffer(void) TEST_ASSERT_EQUAL_INT8(-1, buffer.get(2)); // check overflow - buffer.add('c'); // [] => [c] - buffer.add('d'); // [c] => [c, d] - buffer.add('e'); // [c, d] => [c, d, e] - buffer.add('f'); // [c, d, e] => [c, d, e, f] - buffer.add('g'); // [c, d, e, f] => [c, d, e, f, g] - buffer.add('h'); // [c, d, e, f, g] => [c, d, e, f, g] + 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)); From 9acd9a3fd5deda6249edaae75f2200a37b0dfbfd Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Fri, 8 Sep 2023 20:02:20 +0400 Subject: [PATCH 39/82] test(Calibration): cover center point deviation --- lib/util/senseshift/buffer.hpp | 4 ++-- lib/util/senseshift/calibration.hpp | 5 +---- test/test_util_calibration/main.cpp | 21 +++++++++++++++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/util/senseshift/buffer.hpp b/lib/util/senseshift/buffer.hpp index 0dd1c85d..a6756cb8 100644 --- a/lib/util/senseshift/buffer.hpp +++ b/lib/util/senseshift/buffer.hpp @@ -72,7 +72,7 @@ namespace SenseShift { /** * @brief Get the value at the given index. * - * `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value + * @example `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value */ ValueType get(size_t index) const override { @@ -143,7 +143,7 @@ namespace SenseShift { /** * @brief Get the value at the given index. * - * `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value + * @example `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value */ ValueType get(size_t index) const override { diff --git a/lib/util/senseshift/calibration.hpp b/lib/util/senseshift/calibration.hpp index 13a9834b..53411728 100644 --- a/lib/util/senseshift/calibration.hpp +++ b/lib/util/senseshift/calibration.hpp @@ -84,10 +84,7 @@ namespace SenseShift::Calibration { template<typename _Tp, _Tp sensor_max, _Tp driver_max_deviation, _Tp output_min, _Tp output_max> class CenterPointDeviationCalibrator : public ICalibrator<_Tp> { public: - CenterPointDeviationCalibrator() : range_min(sensor_max), range_max(0) - { -#warning "CenterPointDeviationCalibrator is untested and may not work as expected." - } + CenterPointDeviationCalibrator() : range_min(sensor_max), range_max(0) {} void reset() { diff --git a/test/test_util_calibration/main.cpp b/test/test_util_calibration/main.cpp index a79a8bc6..1fa42a23 100644 --- a/test/test_util_calibration/main.cpp +++ b/test/test_util_calibration/main.cpp @@ -35,6 +35,26 @@ void test_minmax_calibrator(void) TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(4096)); } +void test_center_point_deviation_calibrator(void) +{ + CenterPointDeviationCalibrator<int, 100, 10, 0, 255> calibrator; + + // Test reset function + calibrator.reset(); + + // Test update function + calibrator.update(50); + calibrator.update(75); + calibrator.update(25); + + // Test calibrate function + TEST_ASSERT_EQUAL_INT(255, calibrator.calibrate(100)); + TEST_ASSERT_EQUAL_INT(191, calibrator.calibrate(75)); + TEST_ASSERT_EQUAL_INT(63, calibrator.calibrate(50)); + TEST_ASSERT_EQUAL_INT(0, calibrator.calibrate(25)); + TEST_ASSERT_EQUAL_INT(0, calibrator.calibrate(0)); +} + void test_fixed_center_point_deviation_calibrator(void) { auto calibrator = new FixedCenterPointDeviationCalibrator<uint16_t, 512, 64, 0, 4096>(); @@ -91,6 +111,7 @@ int process(void) UNITY_BEGIN(); RUN_TEST(test_minmax_calibrator); + RUN_TEST(test_center_point_deviation_calibrator); RUN_TEST(test_fixed_center_point_deviation_calibrator); return UNITY_END(); From 14a2b5b68716bd133e1cc39c745c557c75e9d779 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Fri, 8 Sep 2023 18:34:45 +0000 Subject: [PATCH 40/82] ci(GitHub): add Wokwi for lucidglove proto 4 --- .github/workflows/ci.yml | 1 + .../lucidgloves-prototype3+serial/test.yaml | 122 ++--- .../diagram.json | 485 ++++++++++++++++++ .../lucidgloves-prototype4+serial/test.yaml | 76 +++ .../lucidgloves-prototype4+serial/wokwi.toml | 6 + 5 files changed, 629 insertions(+), 61 deletions(-) create mode 100644 .wokwi/lucidgloves-prototype4+serial/diagram.json create mode 100644 .wokwi/lucidgloves-prototype4+serial/test.yaml create mode 100644 .wokwi/lucidgloves-prototype4+serial/wokwi.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1119c892..9c373108 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -428,6 +428,7 @@ jobs: matrix: variant: - lucidgloves-prototype3+serial + - lucidgloves-prototype4+serial steps: - uses: actions/checkout@v3 diff --git a/.wokwi/lucidgloves-prototype3+serial/test.yaml b/.wokwi/lucidgloves-prototype3+serial/test.yaml index 0639c5cc..db653793 100644 --- a/.wokwi/lucidgloves-prototype3+serial/test.yaml +++ b/.wokwi/lucidgloves-prototype3+serial/test.yaml @@ -3,74 +3,74 @@ version: 1 author: Leonid Meleshin steps: - - wait-serial: "A0B0C0D0E0F2047G2047" + - wait-serial: "A0B0C0D0E0F2047G2047" - # Press the 'A' button - - set-control: - part-id: btn1 - control: pressed - value: 1 - - wait-serial: 'A0B0C0D0E0F2047G2047J' + # 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' + # 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 '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' + # 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 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: 'A4095B4095C0D0E0F2047G2047IM' # M is for Pinch gesture + # Curl Thumb finger + - set-control: + part-id: pot-thumb + control: position + value: 1 + - wait-serial: "A4095B4095C0D0E0F2047G2047IM" # M is for Pinch gesture - # Curl Middle finger - - set-control: - part-id: pot-middle - control: position - value: 1 - - wait-serial: 'A4095B4095C4095D0E0F2047G2047IM' + # Curl Middle finger + - set-control: + part-id: pot-middle + control: position + value: 1 + - wait-serial: "A4095B4095C4095D0E0F2047G2047IM" - # Curl Ring finger - - set-control: - part-id: pot-ring - control: position - value: 1 - - wait-serial: 'A4095B4095C4095D4095E0F2047G2047IM' + # Curl Ring finger + - set-control: + part-id: pot-ring + control: position + value: 1 + - wait-serial: "A4095B4095C4095D4095E0F2047G2047IM" - # Curl Pinky finger - - set-control: - part-id: pot-pinky - control: position - value: 1 - - wait-serial: 'A4095B4095C4095D4095E4095F2047G2047ILM' # L is for the Grab gesture + # Curl Pinky finger + - set-control: + part-id: pot-pinky + control: position + value: 1 + - wait-serial: "A4095B4095C4095D4095E4095F2047G2047ILM" # L is for the Grab gesture - # Release Thumb finger - - set-control: - part-id: pot-thumb - control: position - value: 0 - - wait-serial: 'A0B4095C4095D4095E4095F2047G2047IL' + # Release Thumb finger + - set-control: + part-id: pot-thumb + control: position + value: 0 + - wait-serial: "A0B4095C4095D4095E4095F2047G2047IL" diff --git a/.wokwi/lucidgloves-prototype4+serial/diagram.json b/.wokwi/lucidgloves-prototype4+serial/diagram.json new file mode 100644 index 00000000..70ab1ebc --- /dev/null +++ b/.wokwi/lucidgloves-prototype4+serial/diagram.json @@ -0,0 +1,485 @@ +{ + "version": 1, + "author": "Leonid Meleshin", + "editor": "wokwi", + "parts": [ + { + "type": "wokwi-esp32-devkit-v1", + "id": "esp", + "top": 110.3, + "left": 599.8, + "attrs": {} + }, + { + "type": "wokwi-potentiometer", + "id": "pot-thumb", + "top": -87.7, + "left": -278.6, + "attrs": {} + }, + { + "type": "wokwi-potentiometer", + "id": "pot-index", + "top": -87.7, + "left": -192.2, + "attrs": {} + }, + { + "type": "wokwi-potentiometer", + "id": "pot-middle", + "top": -87.7, + "left": -105.8, + "attrs": {} + }, + { + "type": "wokwi-potentiometer", + "id": "pot-ring", + "top": -87.7, + "left": -19.4, + "attrs": {} + }, + { + "type": "wokwi-potentiometer", + "id": "pot-pinky", + "top": -87.7, + "left": 67, + "attrs": {} + }, + { + "type": "wokwi-analog-joystick", + "id": "joystick1", + "top": -135, + "left": 149.4, + "attrs": {} + }, + { + "type": "wokwi-pushbutton", + "id": "btn1", + "top": 6.2, + "left": 268.8, + "attrs": { + "color": "green", + "key": "a", + "bounce": "1", + "label": "A" + } + }, + { + "type": "wokwi-pushbutton", + "id": "btn2", + "top": 6.2, + "left": 355.2, + "attrs": { + "color": "green", + "key": "b", + "bounce": "1", + "label": "B" + } + }, + { + "type": "wokwi-pushbutton", + "id": "btn3", + "top": 6.2, + "left": 451.2, + "attrs": { + "color": "green" + } + }, + { + "type": "wokwi-servo", + "id": "servo1", + "top": -30.8, + "left": 912, + "attrs": {} + }, + { + "type": "wokwi-servo", + "id": "servo2", + "top": 103.6, + "left": 912, + "attrs": {} + }, + { + "type": "wokwi-servo", + "id": "servo3", + "top": 238, + "left": 912, + "attrs": {} + }, + { + "type": "wokwi-servo", + "id": "servo4", + "top": 372.4, + "left": 912, + "attrs": {} + }, + { + "type": "wokwi-servo", + "id": "servo5", + "top": -165.2, + "left": 912, + "attrs": {} + } + ], + "connections": [ + [ + "esp:TX0", + "$serialMonitor:RX", + "", + [] + ], + [ + "esp:RX0", + "$serialMonitor:TX", + "", + [] + ], + [ + "pot-thumb:VCC", + "pot-index:VCC", + "red", + [ + "v28.8", + "h76.8" + ] + ], + [ + "pot-index:VCC", + "pot-middle:VCC", + "red", + [ + "v28.8", + "h76.8" + ] + ], + [ + "pot-middle:VCC", + "pot-ring:VCC", + "red", + [ + "v28.8", + "h76.8" + ] + ], + [ + "pot-thumb:GND", + "pot-index:GND", + "black", + [ + "v38.4", + "h76.8" + ] + ], + [ + "pot-index:GND", + "pot-middle:GND", + "black", + [ + "v38.4", + "h76.8" + ] + ], + [ + "pot-middle:GND", + "pot-ring:GND", + "black", + [ + "v38.4", + "h76.8" + ] + ], + [ + "pot-ring:GND", + "pot-pinky:GND", + "black", + [ + "v38.4", + "h76.8" + ] + ], + [ + "esp:VP", + "pot-pinky:SIG", + "green", + [ + "h0" + ] + ], + [ + "esp:VN", + "pot-ring:SIG", + "green", + [ + "h0" + ] + ], + [ + "esp:D34", + "pot-middle:SIG", + "green", + [ + "h0" + ] + ], + [ + "esp:D35", + "pot-index:SIG", + "green", + [ + "h0" + ] + ], + [ + "esp:D32", + "pot-thumb:SIG", + "green", + [ + "h0" + ] + ], + [ + "joystick1:GND", + "pot-pinky:GND", + "black", + [ + "v38.4", + "h-124.8" + ] + ], + [ + "esp:D33", + "joystick1:HORZ", + "green", + [ + "h0" + ] + ], + [ + "esp:D25", + "joystick1:VERT", + "green", + [ + "h0" + ] + ], + [ + "esp:D26", + "joystick1:SEL", + "green", + [ + "h0" + ] + ], + [ + "esp:GND.2", + "joystick1:GND", + "black", + [ + "h0" + ] + ], + [ + "esp:VIN", + "joystick1:VCC", + "red", + [ + "h0" + ] + ], + [ + "pot-ring:VCC", + "pot-pinky:VCC", + "red", + [ + "v28.8", + "h37.6" + ] + ], + [ + "joystick1:VCC", + "pot-pinky:VCC", + "red", + [ + "v28.8", + "h-38.4" + ] + ], + [ + "btn1:2.r", + "esp:D27", + "green", + [ + "h0.2", + "v249.8" + ] + ], + [ + "btn2:2.r", + "esp:D14", + "green", + [ + "h0.2", + "v259.4" + ] + ], + [ + "btn3:2.r", + "esp:D12", + "green", + [ + "h0.2", + "v211.4" + ] + ], + [ + "servo2:GND", + "servo3:GND", + "black", + [ + "h-19.2", + "v134.4" + ] + ], + [ + "servo3:GND", + "servo4:GND", + "black", + [ + "h-19.2", + "v115.2" + ] + ], + [ + "joystick1:GND", + "btn1:1.l", + "black", + [ + "v0" + ] + ], + [ + "btn1:1.r", + "btn2:1.l", + "black", + [ + "v0" + ] + ], + [ + "btn2:1.r", + "btn3:1.l", + "black", + [ + "v0" + ] + ], + [ + "servo1:GND", + "servo2:GND", + "black", + [ + "h-19.2", + "v96" + ] + ], + [ + "servo1:GND", + "btn3:1.r", + "black", + [ + "h0" + ] + ], + [ + "servo1:V+", + "servo2:V+", + "red", + [ + "h-28.8", + "v96.1" + ] + ], + [ + "servo2:V+", + "servo3:V+", + "red", + [ + "h-28.8", + "v86.5" + ] + ], + [ + "servo3:V+", + "servo4:V+", + "red", + [ + "h-28.8", + "v134.4" + ] + ], + [ + "esp:D5", + "servo4:PWM", + "green", + [ + "h38.1", + "v239.8" + ] + ], + [ + "esp:D18", + "servo3:PWM", + "green", + [ + "h57.3", + "v115" + ] + ], + [ + "esp:D21", + "servo1:PWM", + "green", + [ + "h38.1", + "v-135" + ] + ], + [ + "esp:D19", + "servo2:PWM", + "green", + [ + "h57.3", + "v-9.9" + ] + ], + [ + "servo1:V+", + "servo5:V+", + "red", + [ + "h-28.8", + "v-134.3" + ] + ], + [ + "servo1:GND", + "servo5:GND", + "black", + [ + "h-19.2", + "v-134.4" + ] + ], + [ + "esp:TX2", + "servo5:PWM", + "green", + [ + "h18.9", + "v-307.3" + ] + ] + ], + "dependencies": {} +} diff --git a/.wokwi/lucidgloves-prototype4+serial/test.yaml b/.wokwi/lucidgloves-prototype4+serial/test.yaml new file mode 100644 index 00000000..f89d70f4 --- /dev/null +++ b/.wokwi/lucidgloves-prototype4+serial/test.yaml @@ -0,0 +1,76 @@ +name: Test LucidGloves Prototype 4 +version: 1 +author: Leonid Meleshin + +steps: + - 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: "A4095B4095C0D0E0F2047G2047IM" # M is for Pinch gesture + + # Curl Middle finger + - set-control: + part-id: pot-middle + control: position + value: 1 + - wait-serial: "A4095B4095C4095D0E0F2047G2047IM" + + # Curl Ring finger + - set-control: + part-id: pot-ring + control: position + value: 1 + - wait-serial: "A4095B4095C4095D4095E0F2047G2047IM" + + # Curl Pinky finger + - set-control: + part-id: pot-pinky + control: position + value: 1 + - wait-serial: "A4095B4095C4095D4095E4095F2047G2047ILM" # L is for the Grab gesture + + # Partially Release Thumb finger + - set-control: + part-id: pot-thumb + control: position + value: 0.25 + - wait-serial: "A1024B4095C4095D4095E4095F2047G2047IL" diff --git a/.wokwi/lucidgloves-prototype4+serial/wokwi.toml b/.wokwi/lucidgloves-prototype4+serial/wokwi.toml new file mode 100644 index 00000000..316b68c7 --- /dev/null +++ b/.wokwi/lucidgloves-prototype4+serial/wokwi.toml @@ -0,0 +1,6 @@ +[wokwi] +version = 1 +firmware = "../../.pio/build/lucidgloves-prototype4/firmware.bin" +elf = "../../.pio/build/lucidgloves-prototype4/firmware.elf" + +gdbServerPort=3333 From 3a2b887b788c51f9bba60dbf90caabec16227724 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 10 Sep 2023 13:35:32 +0400 Subject: [PATCH 41/82] fix(Wokwi): test scenario indentation --- .wokwi/lucidgloves-prototype3+serial/test.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.wokwi/lucidgloves-prototype3+serial/test.yaml b/.wokwi/lucidgloves-prototype3+serial/test.yaml index b5c030bc..95f55e39 100644 --- a/.wokwi/lucidgloves-prototype3+serial/test.yaml +++ b/.wokwi/lucidgloves-prototype3+serial/test.yaml @@ -68,9 +68,9 @@ steps: value: 1 - wait-serial: "A4095B4095C4095D4095E4095F2047G2047ILM" # L is for the Grab gesture - # Partially Release Thumb finger - - set-control: - part-id: pot-thumb - control: position - value: 0.25 - - wait-serial: 'A1024B4095C4095D4095E4095F2047G2047IL' + # Partially Release Thumb finger + - set-control: + part-id: pot-thumb + control: position + value: 0.25 + - wait-serial: 'A1024B4095C4095D4095E4095F2047G2047IL' From a373ccdce2a0f2fb786a32c66b325079a7dc5ab8 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 28 Sep 2023 20:41:17 +0400 Subject: [PATCH 42/82] chore: add Wakatime to devcontainer --- .devcontainer/devcontainer.json | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c629151a..1fee0e22 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -12,10 +12,16 @@ "mounts": [ "source=/dev/,target=/dev/,type=bind,consistency=consistent" ], - "postAttachCommand": { - "submodules": ["git", "submodule", "update", "--recursive", "--init"], - "udev": ["sudo", "service", "udev", "restart"] + "updateContentCommand": { + "submodule": "git submodule update --init --recursive", + "pio": "pio pkg install" }, + "postAttachCommand": [ + "sudo", + "service", + "udev", + "restart" + ], "customizations": { "vscode": { "settings": { @@ -29,27 +35,25 @@ "platformio-ide.pioHomeServerHttpPort": 8008, "platformio-ide.autoOpenPlatformIOIniFile": false, "files.exclude": { - "**/.git": true, - "**/.DS_Store": true + "**/.git": true, + "**/.DS_Store": true }, "files.associations": { - "**/.vscode/*.json": "jsonc" + "**/.vscode/*.json": "jsonc" }, "C_Cpp.clang_format_path": "clang-format" }, "extensions": [ "ms-vscode.cpptools", "redhat.vscode-yaml", - "platformio.platformio-ide", "Wokwi.wokwi-vscode", - "xaver.clang-format", "editorconfig.editorconfig", - "GitHub.copilot", "GitHub.copilot-labs", - "GitHub.copilot-chat" + "GitHub.copilot-chat", + "wakatime.vscode-wakatime" ] } } From af9df068fa0c02e9ab7fb20002859ce281049f7f Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Fri, 29 Sep 2023 13:56:06 +0400 Subject: [PATCH 43/82] refactor: remove C-styled `_t` typedefs --- examples/bhaptics-ble-bt-serial.cpp | 4 +- firmware/mode_configs/bhaptics/tactal.cpp | 6 +- firmware/mode_configs/bhaptics/tactglove.cpp | 8 +- firmware/mode_configs/bhaptics/tactosy2.cpp | 6 +- firmware/mode_configs/bhaptics/tactosyf.cpp | 6 +- firmware/mode_configs/bhaptics/tactosyh.cpp | 6 +- .../mode_configs/bhaptics/tactsuit_x16.cpp | 10 +- .../bhaptics/tactsuit_x16_pca9685.cpp | 10 +- .../mode_configs/bhaptics/tactsuit_x40.cpp | 8 +- firmware/mode_configs/bhaptics/tactvisor.cpp | 6 +- .../arduino/components/serial_plotter.cpp | 2 +- .../arduino/input/sensor/digital.hpp | 2 +- lib/battery/senseshift/battery.hpp | 8 +- lib/battery/senseshift/battery/sensor.hpp | 2 +- lib/bhaptics/senseshift/bh/devices.hpp | 294 +++++++++--------- lib/bhaptics/senseshift/bh/encoding.hpp | 73 ++--- .../senseshift/bh/ble/connection.cpp | 10 +- .../senseshift/bh/ble/connection.hpp | 12 +- .../senseshift/freertos/input/sensor.hpp | 12 +- lib/hands/hand_interface.hpp | 12 +- lib/haptics/senseshift/body/haptics/body.cpp | 8 +- lib/haptics/senseshift/body/haptics/body.hpp | 16 +- .../senseshift/body/haptics/interface.hpp | 54 ++-- lib/haptics/senseshift/body/haptics/plane.cpp | 18 +- lib/haptics/senseshift/body/haptics/plane.hpp | 57 ++-- lib/math/senseshift/math/point2.hpp | 18 +- lib/opengloves/og_protocol.hpp | 8 +- lib/opengloves/sensor/og_finger.hpp | 2 +- test/test_bhaptics_encoding/main.cpp | 28 +- test/test_haptics_body/main.cpp | 10 +- test/test_haptics_plane/main.cpp | 12 +- 31 files changed, 357 insertions(+), 371 deletions(-) diff --git a/examples/bhaptics-ble-bt-serial.cpp b/examples/bhaptics-ble-bt-serial.cpp index 3a532691..9f1f9820 100644 --- a/examples/bhaptics-ble-bt-serial.cpp +++ b/examples/bhaptics-ble-bt-serial.cpp @@ -21,8 +21,8 @@ SenseShift* app = &App; BluetoothSerial SerialBT; BluetoothSerial* btSerial = &SerialBT; -static const size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; -static const ::SenseShift::Body::Haptics::Position_t* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; +static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; +static const ::SenseShift::Body::Haptics::Position* bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; class BLECallbacks : public BHBLEConnectionCallbacks { public: diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index 2c99a8fc..54bd226f 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -25,13 +25,13 @@ using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; -static const size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; -static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; +static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; +static const Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; void setupMode() { // Configure PWM pins to their positions on the face - const auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + const auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ // 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/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 8d2138f6..3091a5d6 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -26,10 +26,10 @@ using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; -static const Body::Hands::HandSide_t handSide = Body::Hands::HandSide::SENSESHIFT_HAND_SIDE; -static const size_t bhLayoutSize = BH_LAYOUT_TACTGLOVE_SIZE; +static constexpr Body::Hands::HandSide handSide = Body::Hands::HandSide::SENSESHIFT_HAND_SIDE; +static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTGLOVE_SIZE; // clang-format off -static const OutputLayout_t (&bhLayout)[bhLayoutSize] = handSide == Body::Hands::HandSide::Left ? BH::TactGloveLeftLayout : BH::TactGloveRightLayout; +static const OutputLayout (&bhLayout)[bhLayoutSize] = handSide == Body::Hands::HandSide::Left ? BH::TactGloveLeftLayout : BH::TactGloveRightLayout; // clang-format on void setupMode() @@ -56,7 +56,7 @@ void setupMode() .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect_t::Vibro); + Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index 38743a78..20751691 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -25,13 +25,13 @@ using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; -static const size_t bhLayoutSize = BH_LAYOUT_TACTOSY2_SIZE; -static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSY2; +static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTOSY2_SIZE; +static const Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSY2; void setupMode() { // Configure PWM pins to their positions on the forearm - auto forearmOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto forearmOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ // clang-format off { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25) }, { new ActuatorPWM(26), new ActuatorPWM(27), new ActuatorPWM(14) }, diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index 0dd2733f..b7667f0f 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -25,13 +25,13 @@ using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; -static const size_t bhLayoutSize = BH_LAYOUT_TACTOSYF_SIZE; -static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYF; +static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTOSYF_SIZE; +static const Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYF; void setupMode() { // Configure PWM pins to their positions on the feet - auto footOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto footOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ // clang-format off { new ActuatorPWM(32) }, { new ActuatorPWM(33) }, diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index ae3de9da..50b46ec9 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -25,13 +25,13 @@ using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; -static const size_t bhLayoutSize = BH_LAYOUT_TACTOSYH_SIZE; -static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYH; +static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTOSYH_SIZE; +static const Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYH; void setupMode() { // Configure PWM pins to their positions on the hands - auto handOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto handOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ // clang-format off { new ActuatorPWM(32) }, { new ActuatorPWM(33) }, diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 88b46536..62fc1e45 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -25,23 +25,23 @@ using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; -static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; -static const OutputLayout_t bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; +static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; +static const OutputLayout bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; // Ouput indices, responsible for x40 => x16 grouping -static const size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; +static constexpr size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; static const uint8_t layoutGroups[layoutGroupsSize] = BH_LAYOUT_TACTSUITX16_GROUPS; void setupMode() { // Configure PWM pins to their positions on the vest - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ // clang-format off { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25), new ActuatorPWM(26) }, { new ActuatorPWM(27), new ActuatorPWM(14), new ActuatorPWM(12), new ActuatorPWM(13) }, // clang-format on }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ // clang-format off { new ActuatorPWM(19), new ActuatorPWM(18), new ActuatorPWM(5), new ActuatorPWM(17) }, { new ActuatorPWM(16), new ActuatorPWM(4), new ActuatorPWM(2), new ActuatorPWM(15) }, diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index 6782ecee..8d3383e8 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -25,11 +25,11 @@ using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; -static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; -static const OutputLayout_t bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; +static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; +static const OutputLayout bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; // Ouput indices, responsible for x40 => x16 grouping -static const size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; +static constexpr size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; static const uint8_t layoutGroups[layoutGroupsSize] = BH_LAYOUT_TACTSUITX16_GROUPS; void setupMode() @@ -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<VibroPlane::Actuator_t>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ // clang-format off { new ActuatorPCA9685(pwm, 0), new ActuatorPCA9685(pwm, 1), new ActuatorPCA9685(pwm, 2), new ActuatorPCA9685(pwm, 3) }, { new ActuatorPCA9685(pwm, 4), new ActuatorPCA9685(pwm, 5), new ActuatorPCA9685(pwm, 6), new ActuatorPCA9685(pwm, 7) }, // clang-format on }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ // clang-format off { new ActuatorPCA9685(pwm, 8), new ActuatorPCA9685(pwm, 9), new ActuatorPCA9685(pwm, 10), new ActuatorPCA9685(pwm, 11) }, { new ActuatorPCA9685(pwm, 12), new ActuatorPCA9685(pwm, 13), new ActuatorPCA9685(pwm, 14), new ActuatorPCA9685(pwm, 15) }, diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 318e6ef6..13fce314 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -26,8 +26,8 @@ using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; -static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX40_SIZE; -static const OutputLayout_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; +static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTSUITX40_SIZE; +static const OutputLayout bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; void setupMode() { @@ -42,7 +42,7 @@ void setupMode() // Assign the pins on the configured PCA9685s and PWM pins to locations on the // vest - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ // clang-format off { new ActuatorPCA9685(pwm0, 0), new ActuatorPCA9685(pwm0, 1), new ActuatorPCA9685(pwm0, 2), new ActuatorPCA9685(pwm0, 3) }, { new ActuatorPCA9685(pwm0, 4), new ActuatorPCA9685(pwm0, 5), new ActuatorPCA9685(pwm0, 6), new ActuatorPCA9685(pwm0, 7) }, @@ -51,7 +51,7 @@ void setupMode() { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25), new ActuatorPWM(26) }, // clang-format on }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ // clang-format off { new ActuatorPCA9685(pwm1, 0), new ActuatorPCA9685(pwm1, 1), new ActuatorPCA9685(pwm1, 2), new ActuatorPCA9685(pwm1, 3) }, { new ActuatorPCA9685(pwm1, 4), new ActuatorPCA9685(pwm1, 5), new ActuatorPCA9685(pwm1, 6), new ActuatorPCA9685(pwm1, 7) }, diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index 758ab9aa..f7e7ab44 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -25,13 +25,13 @@ using namespace SenseShift::Body::Haptics; extern SenseShift::SenseShift App; SenseShift::SenseShift* app = &App; -static const size_t bhLayoutSize = BH_LAYOUT_TACTVISOR_SIZE; -static const Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTVISOR; +static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTVISOR_SIZE; +static const Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTVISOR; void setupMode() { // Configure PWM pins to their positions on the face - auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ // clang-format off { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25), new ActuatorPWM(26) }, // clang-format on diff --git a/lib/arduino/senseshift/arduino/components/serial_plotter.cpp b/lib/arduino/senseshift/arduino/components/serial_plotter.cpp index bdd1fb38..8cd48978 100644 --- a/lib/arduino/senseshift/arduino/components/serial_plotter.cpp +++ b/lib/arduino/senseshift/arduino/components/serial_plotter.cpp @@ -2,7 +2,7 @@ namespace SenseShift::Arduino { struct PlaneVisitor { - const SenseShift::Body::Haptics::Target_t target; + const SenseShift::Body::Haptics::Target target; HardwareSerial* serial; void operator()(const SenseShift::Body::Haptics::VibroPlane* plane) const diff --git a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp index 31b77bbf..3cb68b3f 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -5,7 +5,7 @@ #include <Arduino.h> namespace SenseShift::Arduino::Input { - typedef ::SenseShift::Input::ISimpleSensor<bool> IDigitalSensor; + using IDigitalSensor = ::SenseShift::Input::ISimpleSensor<bool>; template<bool invert = false> class DigitalSensor : public IDigitalSensor { diff --git a/lib/battery/senseshift/battery.hpp b/lib/battery/senseshift/battery.hpp index 10e51896..a89455fb 100644 --- a/lib/battery/senseshift/battery.hpp +++ b/lib/battery/senseshift/battery.hpp @@ -5,13 +5,13 @@ #include <cstdint> namespace SenseShift::Battery { - typedef struct BatteryState { + struct BatteryState { uint8_t level; - } BatteryState_t; + }; class BatteryLevelEvent : public IEvent { public: - const BatteryState_t& state; - BatteryLevelEvent(const BatteryState_t& state) : IEvent(OH_EVENT_BATTERY_LEVEL), state(state){}; + const BatteryState& state; + BatteryLevelEvent(const BatteryState& state) : IEvent(OH_EVENT_BATTERY_LEVEL), state(state){}; }; } // namespace SenseShift::Battery diff --git a/lib/battery/senseshift/battery/sensor.hpp b/lib/battery/senseshift/battery/sensor.hpp index f2c2968a..01b1ae96 100644 --- a/lib/battery/senseshift/battery/sensor.hpp +++ b/lib/battery/senseshift/battery/sensor.hpp @@ -14,7 +14,7 @@ namespace SenseShift::Battery { /** * Abstract battery sensor */ - typedef ::SenseShift::Input::ISimpleSensor<BatteryState> IBatterySensor; + using IBatterySensor = ::SenseShift::Input::ISimpleSensor<BatteryState>; class NaiveBatterySensor : public IBatterySensor { public: diff --git a/lib/bhaptics/senseshift/bh/devices.hpp b/lib/bhaptics/senseshift/bh/devices.hpp index b78bbb9f..f4c168de 100644 --- a/lib/bhaptics/senseshift/bh/devices.hpp +++ b/lib/bhaptics/senseshift/bh/devices.hpp @@ -7,12 +7,12 @@ #define BH_LAYOUT_TACTSUITX40_SIZE_X 4 #define BH_LAYOUT_TACTSUITX40_SIZE_Y 5 -#define BH_LAYOUT_TACTSUITX40_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ - x, \ - y, \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTSUITX40_SIZE_X - 1), \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTSUITX40_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTSUITX40_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTSUITX40_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTSUITX40_SIZE_Y - 1) \ ) // X * Y for front and back @@ -20,51 +20,51 @@ // clang-format off #define BH_LAYOUT_TACTSUITX40 { \ /* Front, left part */ \ - /* 0 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ - /* 1 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ - /* 2 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ - /* 3 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ - /* 4 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ - /* 5 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ - /* 6 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ - /* 7 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ - /* 8 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ - /* 9 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ + /* 0 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ + /* 1 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ + /* 2 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ + /* 3 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ + /* 4 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ + /* 5 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ + /* 6 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ + /* 7 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ + /* 8 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ + /* 9 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ \ /* Back */ \ - /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ - /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ - /* 12 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ - /* 13 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ - /* 14 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ - /* 15 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ - /* 16 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ - /* 17 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ - /* 18 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ - /* 19 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ + /* 11 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ + /* 11 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ + /* 12 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ + /* 13 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 1) }, \ + /* 14 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 2) }, \ + /* 15 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 2) }, \ + /* 16 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 3) }, \ + /* 17 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ + /* 18 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ + /* 19 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ \ - /* 20 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ - /* 21 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ - /* 22 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ - /* 23 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ - /* 24 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ - /* 25 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ - /* 26 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ - /* 27 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ - /* 28 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ - /* 29 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) }, \ + /* 20 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ + /* 21 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ + /* 22 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ + /* 23 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ + /* 24 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ + /* 25 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ + /* 26 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ + /* 27 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ + /* 28 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ + /* 29 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) }, \ \ /* Front, again... Now right part */ \ - /* 30 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ - /* 31 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ - /* 32 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ - /* 33 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ - /* 34 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ - /* 35 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ - /* 36 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ - /* 37 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ - /* 38 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ - /* 39 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) } \ + /* 30 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ + /* 31 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ + /* 32 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ + /* 33 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 1) }, \ + /* 34 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 2) }, \ + /* 35 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 2) }, \ + /* 36 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 3) }, \ + /* 37 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ + /* 38 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ + /* 39 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) } \ } // clang-format on @@ -74,12 +74,12 @@ #define BH_LAYOUT_TACTSUITX16_SIZE_X 4 #define BH_LAYOUT_TACTSUITX16_SIZE_Y 2 -#define BH_LAYOUT_TACTSUITX16_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ - x, \ - y, \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTSUITX16_SIZE_X - 1), \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTSUITX16_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTSUITX16_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTSUITX16_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTSUITX16_SIZE_Y - 1) \ ) // X16 suit uses the same packets structure as x40 suit and performs motor grouping in firmware @@ -87,55 +87,55 @@ // clang-format off #define BH_LAYOUT_TACTSUITX16 { \ /* Front, left part */ \ - /* 0 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ - /* 1 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ - /* 2 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ - /* 3 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ + /* 0 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ + /* 1 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ + /* 2 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ + /* 3 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ \ - /* 4 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ - /* 5 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ - /* 6 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ - /* 7 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ - /* 8 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ - /* 9 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ + /* 4 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ + /* 5 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ + /* 6 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ + /* 7 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ + /* 8 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ + /* 9 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ \ /* Back */ \ - /* 10 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ - /* 11 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ - /* 12 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ - /* 13 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ + /* 10 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ + /* 11 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ + /* 12 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ + /* 13 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ \ - /* 14 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ - /* 15 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ - /* 16 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ - /* 17 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ - /* 18 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ - /* 19 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ + /* 14 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ + /* 15 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ + /* 16 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ + /* 17 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ + /* 18 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ + /* 19 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ \ - /* 20 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ - /* 21 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ - /* 22 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ - /* 23 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ + /* 20 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ + /* 21 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ + /* 22 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ + /* 23 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ \ - /* 24 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ - /* 25 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ - /* 26 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ - /* 27 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 15 */ \ - /* 28 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 18 */ \ - /* 29 */ { Target_t::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 19 */ \ + /* 24 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ + /* 25 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ + /* 26 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ + /* 27 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 15 */ \ + /* 28 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 18 */ \ + /* 29 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 19 */ \ \ /* Front, again... Now right part */ \ - /* 30 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ - /* 31 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ - /* 32 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ - /* 33 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ + /* 30 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ + /* 31 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ + /* 32 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ + /* 33 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ \ - /* 34 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ - /* 35 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ - /* 36 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ - /* 37 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 15 */ \ - /* 38 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 18 */ \ - /* 39 */ { Target_t::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 19 */ \ + /* 34 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ + /* 35 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ + /* 36 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ + /* 37 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 15 */ \ + /* 38 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 18 */ \ + /* 39 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 19 */ \ } // clang-format on @@ -152,12 +152,12 @@ #define BH_LAYOUT_TACTAL_SIZE_X 6 #define BH_LAYOUT_TACTAL_SIZE_Y 1 -#define BH_LAYOUT_TACTAL_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ - x, \ - y, \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTAL_SIZE_X - 1), \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTAL_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTAL_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTAL_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTAL_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTAL_SIZE (BH_LAYOUT_TACTAL_SIZE_X * BH_LAYOUT_TACTAL_SIZE_Y) @@ -178,12 +178,12 @@ #define BH_LAYOUT_TACTVISOR_SIZE_X 4 #define BH_LAYOUT_TACTVISOR_SIZE_Y 1 -#define BH_LAYOUT_TACTVISOR_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ - x, \ - y, \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTVISOR_SIZE_X - 1), \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTVISOR_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTVISOR_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTVISOR_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTVISOR_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTVISOR_SIZE (BH_LAYOUT_TACTVISOR_SIZE_X * BH_LAYOUT_TACTVISOR_SIZE_Y) @@ -202,12 +202,12 @@ #define BH_LAYOUT_TACTOSY2_SIZE_X 3 #define BH_LAYOUT_TACTOSY2_SIZE_Y 2 -#define BH_LAYOUT_TACTOSY2_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ - x, \ - y, \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSY2_SIZE_X - 1), \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSY2_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTOSY2_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTOSY2_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTOSY2_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTOSY2_SIZE (BH_LAYOUT_TACTOSY2_SIZE_X * BH_LAYOUT_TACTOSY2_SIZE_Y) @@ -224,12 +224,12 @@ #define BH_LAYOUT_TACTOSYH_SIZE_X 1 #define BH_LAYOUT_TACTOSYH_SIZE_Y 3 -#define BH_LAYOUT_TACTOSYH_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ - x, \ - y, \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSYH_SIZE_X - 1), \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSYH_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTOSYH_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTOSYH_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTOSYH_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTOSYH_SIZE (BH_LAYOUT_TACTOSYH_SIZE_X * BH_LAYOUT_TACTOSYH_SIZE_Y) @@ -243,12 +243,12 @@ #define BH_LAYOUT_TACTOSYF_SIZE_X 1 #define BH_LAYOUT_TACTOSYF_SIZE_Y 3 -#define BH_LAYOUT_TACTOSYF_MAKE_POINT(x, y) \ - ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate_t>( \ - x, \ - y, \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSYF_SIZE_X - 1), \ - (::SenseShift::Body::Haptics::Coordinate_t)(BH_LAYOUT_TACTOSYF_SIZE_Y - 1) \ +#define BH_LAYOUT_TACTOSYF_MAKE_POINT(x, y) \ + ::SenseShift::Body::Haptics::PlaneMapper_Margin::mapPoint<::SenseShift::Body::Haptics::Coordinate>( \ + x, \ + y, \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTOSYF_SIZE_X - 1), \ + (::SenseShift::Body::Haptics::Coordinate)(BH_LAYOUT_TACTOSYF_SIZE_Y - 1) \ ) #define BH_LAYOUT_TACTOSYF_SIZE (BH_LAYOUT_TACTOSYF_SIZE_X * BH_LAYOUT_TACTOSYF_SIZE_Y) @@ -264,21 +264,21 @@ #define BH_LAYOUT_TACTGLOVE_SIZE 6 // TactGlove (Left) motor positions #define BH_LAYOUT_TACTGLOVE_LEFT { \ - { Target_t::HandLeftThumb, FINGERTIP_POSITION }, \ - { Target_t::HandLeftIndex, FINGERTIP_POSITION }, \ - { Target_t::HandLeftMiddle, FINGERTIP_POSITION }, \ - { Target_t::HandLeftRing, FINGERTIP_POSITION }, \ - { Target_t::HandLeftLittle, FINGERTIP_POSITION }, \ - { Target_t::HandLeftDorsal, WRIST_MOTOR_POSITION }, \ + { Target::HandLeftThumb, FINGERTIP_POSITION }, \ + { Target::HandLeftIndex, FINGERTIP_POSITION }, \ + { Target::HandLeftMiddle, FINGERTIP_POSITION }, \ + { Target::HandLeftRing, FINGERTIP_POSITION }, \ + { Target::HandLeftLittle, FINGERTIP_POSITION }, \ + { Target::HandLeftDorsal, WRIST_MOTOR_POSITION }, \ } // TactGlove (Right) motor positions #define BH_LAYOUT_TACTGLOVE_RIGHT { \ - { Target_t::HandRightThumb, FINGERTIP_POSITION }, \ - { Target_t::HandRightIndex, FINGERTIP_POSITION }, \ - { Target_t::HandRightMiddle, FINGERTIP_POSITION }, \ - { Target_t::HandRightRing, FINGERTIP_POSITION }, \ - { Target_t::HandRightLittle, FINGERTIP_POSITION }, \ - { Target_t::HandRightDorsal, WRIST_MOTOR_POSITION } \ + { Target::HandRightThumb, FINGERTIP_POSITION }, \ + { Target::HandRightIndex, FINGERTIP_POSITION }, \ + { Target::HandRightMiddle, FINGERTIP_POSITION }, \ + { Target::HandRightRing, FINGERTIP_POSITION }, \ + { Target::HandRightLittle, FINGERTIP_POSITION }, \ + { Target::HandRightDorsal, WRIST_MOTOR_POSITION } \ } // clang-format on @@ -288,27 +288,27 @@ namespace SenseShift::BH { using namespace ::SenseShift::Body::Hands::Haptics; using namespace ::SenseShift::Body::Haptics; - using HandSide_t = ::SenseShift::Body::Hands::HandSide_t; + using HandSide = ::SenseShift::Body::Hands::HandSide; - typedef std::tuple<Target_t, Position_t> OutputLayout_t; + using OutputLayout = std::tuple<Target, Position>; // TactGlove Wrist motor position - static constexpr const Position_t WRIST_MOTOR_POSITION(127, 191); - static constexpr const OutputLayout_t TactGloveLeftLayout[] = BH_LAYOUT_TACTGLOVE_LEFT; - static constexpr const OutputLayout_t TactGloveRightLayout[] = BH_LAYOUT_TACTGLOVE_RIGHT; + static constexpr const Position WRIST_MOTOR_POSITION(127, 191); + static constexpr const OutputLayout TactGloveLeftLayout[] = BH_LAYOUT_TACTGLOVE_LEFT; + static constexpr const OutputLayout TactGloveRightLayout[] = BH_LAYOUT_TACTGLOVE_RIGHT; inline void addTactGloveActuators( HapticBody* hapticBody, - const HandSide_t side, - VibroPlane::Actuator_t* const thumbActuator, - VibroPlane::Actuator_t* const indexActuator, - VibroPlane::Actuator_t* const middleActuator, - VibroPlane::Actuator_t* const ringActuator, - VibroPlane::Actuator_t* const littleActuator, - VibroPlane::Actuator_t* const wristActuator + const HandSide side, + VibroPlane::Actuator* const thumbActuator, + VibroPlane::Actuator* const indexActuator, + VibroPlane::Actuator* const middleActuator, + VibroPlane::Actuator* const ringActuator, + VibroPlane::Actuator* const littleActuator, + VibroPlane::Actuator* const wristActuator ) { - const OutputLayout_t(&layout)[6] = (side == HandSide_t::Left) ? TactGloveLeftLayout : TactGloveRightLayout; + const OutputLayout(&layout)[6] = (side == HandSide::Left) ? TactGloveLeftLayout : TactGloveRightLayout; if (thumbActuator != nullptr) { hapticBody->addTarget( diff --git a/lib/bhaptics/senseshift/bh/encoding.hpp b/lib/bhaptics/senseshift/bh/encoding.hpp index 3b75f8f0..273b98c7 100644 --- a/lib/bhaptics/senseshift/bh/encoding.hpp +++ b/lib/bhaptics/senseshift/bh/encoding.hpp @@ -6,23 +6,23 @@ namespace SenseShift::BH { class Decoder { public: - using VibroEffectData_t = ::SenseShift::Body::Haptics::VibroEffectData_t; - using EffectData_t = ::SenseShift::Body::Haptics::EffectData_t; + using VibroEffectData = ::SenseShift::Body::Haptics::VibroEffectData; + using EffectData = ::SenseShift::Body::Haptics::EffectData; - using Effect_t = ::SenseShift::Body::Haptics::Effect_t; - using Target_t = ::SenseShift::Body::Haptics::Target_t; - using Position_t = ::SenseShift::Body::Haptics::Position_t; + using Effect = ::SenseShift::Body::Haptics::Effect; + using Target = ::SenseShift::Body::Haptics::Target; + using Position = ::SenseShift::Body::Haptics::Position; - using HapticBody_t = ::SenseShift::Body::Haptics::HapticBody; + using HapticBody = ::SenseShift::Body::Haptics::HapticBody; - typedef std::tuple<Target_t, Position_t> OutputLayout_t; + using OutputLayout = std::tuple<Target, Position>; - static const size_t VEST_LAYOUT_SIZE = 40; - static const size_t VEST_PAYLOAD_SIZE = 20; + static constexpr size_t VEST_LAYOUT_SIZE = 40; + static constexpr size_t VEST_PAYLOAD_SIZE = 20; template<size_t N> static void applyPlain( - HapticBody_t* output, const uint8_t (&value)[N], const OutputLayout_t (&layout)[N], const Effect_t effect + HapticBody* output, const uint8_t (&value)[N], const OutputLayout (&layout)[N], const Effect effect ) { for (size_t i = 0; i < N; i++) { @@ -40,7 +40,7 @@ namespace SenseShift::BH { template<size_t N> static void - applyPlain(HapticBody_t* output, std::string& value, const OutputLayout_t (&layout)[N], const Effect_t effect) + applyPlain(HapticBody* output, std::string& value, const OutputLayout (&layout)[N], const Effect effect) { std::uint8_t buf[N]; std::size_t copyLength = std::min(value.size(), sizeof(buf)); @@ -54,11 +54,11 @@ namespace SenseShift::BH { */ template<size_t N> static void applyPlain( - HapticBody_t* output, + HapticBody* output, const uint8_t (&value)[N], - const Position_t (&layout)[N], - const Effect_t effect, - const Target_t target + const Position (&layout)[N], + const Effect effect, + const Target target ) { for (size_t i = 0; i < N; i++) { @@ -76,11 +76,7 @@ namespace SenseShift::BH { template<size_t N> static void applyPlain( - HapticBody_t* output, - std::string& value, - const Position_t (&layout)[N], - const Effect_t effect, - const Target_t target + HapticBody* output, std::string& value, const Position (&layout)[N], const Effect effect, const Target target ) { std::uint8_t buf[N]; @@ -94,31 +90,28 @@ namespace SenseShift::BH { * Apply vest-encoded data to the output. */ static void applyVest( - HapticBody_t* output, - const uint8_t (&value)[VEST_PAYLOAD_SIZE], - const OutputLayout_t (&layout)[VEST_LAYOUT_SIZE] + HapticBody* output, const uint8_t (&value)[VEST_PAYLOAD_SIZE], const OutputLayout (&layout)[VEST_LAYOUT_SIZE] ) { for (size_t i = 0; i < VEST_PAYLOAD_SIZE; i++) { uint8_t byte = value[i]; uint actIndex = i * 2; output->effect({ - .effect = Effect_t::Vibro, + .effect = Effect::Vibro, .target = std::get<0>(layout[actIndex]), .position = std::get<1>(layout[actIndex]), - .data = effectDataFromByte(Effect_t::Vibro, ((byte >> 4) & 0xf), 15), + .data = effectDataFromByte(Effect::Vibro, ((byte >> 4) & 0xf), 15), }); output->effect({ - .effect = Effect_t::Vibro, + .effect = Effect::Vibro, .target = std::get<0>(layout[actIndex + 1]), .position = std::get<1>(layout[actIndex + 1]), - .data = effectDataFromByte(Effect_t::Vibro, (byte & 0xf), 15), + .data = effectDataFromByte(Effect::Vibro, (byte & 0xf), 15), }); } } - static void - applyVest(HapticBody_t* output, std::string& value, const OutputLayout_t (&layout)[VEST_LAYOUT_SIZE]) + static void applyVest(HapticBody* output, std::string& value, const OutputLayout (&layout)[VEST_LAYOUT_SIZE]) { std::uint8_t buf[VEST_PAYLOAD_SIZE]; std::size_t copyLength = std::min(value.size(), sizeof(buf)); @@ -132,9 +125,9 @@ namespace SenseShift::BH { */ template<size_t N> static void applyVestGrouped( - HapticBody_t* output, + HapticBody* output, const uint8_t (&value)[VEST_PAYLOAD_SIZE], - const OutputLayout_t (&layout)[VEST_LAYOUT_SIZE], + const OutputLayout (&layout)[VEST_LAYOUT_SIZE], const uint8_t (&layoutGroups)[N] ) { @@ -179,19 +172,19 @@ namespace SenseShift::BH { const auto position = std::get<1>(layout[i]); output->effect({ - .effect = Effect_t::Vibro, + .effect = Effect::Vibro, .target = target, .position = position, - .data = effectDataFromByte(Effect_t::Vibro, result[i], 15), + .data = effectDataFromByte(Effect::Vibro, result[i], 15), }); } } template<size_t N> static void applyVestGrouped( - HapticBody_t* output, + HapticBody* output, std::string& value, - const OutputLayout_t (&layout)[VEST_LAYOUT_SIZE], + const OutputLayout (&layout)[VEST_LAYOUT_SIZE], const uint8_t (&layoutGroups)[N] ) { @@ -203,15 +196,15 @@ namespace SenseShift::BH { } private: - static const EffectData_t - effectDataFromByte(const Effect_t effect, const uint8_t byte, const uint8_t maxValue = 100) + static const EffectData + effectDataFromByte(const Effect effect, const uint8_t byte, const uint8_t maxValue = 100) { switch (effect) { - case Effect_t::Vibro: - return VibroEffectData_t(::SenseShift::simpleMap<VibroEffectData_t::Intensity_t>( + case Effect::Vibro: + return VibroEffectData(::SenseShift::simpleMap<VibroEffectData::Intensity>( byte, maxValue, - VibroEffectData_t::INTENSITY_MAX + VibroEffectData::INTENSITY_MAX )); default: throw std::runtime_error("Unknown effect"); diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp index 48e11876..db642a43 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -96,10 +96,10 @@ namespace SenseShift::BH::BLE { class MotorCharCallbacks : public BLECharacteristicCallbacks { private: - Connection::MotorHandler_t motorTransformer; + Connection::MotorHandler motorTransformer; public: - MotorCharCallbacks(Connection::MotorHandler_t motorTransformer) : motorTransformer(motorTransformer) {} + MotorCharCallbacks(Connection::MotorHandler motorTransformer) : motorTransformer(motorTransformer) {} void onWrite(BLECharacteristic* pCharacteristic) override { @@ -169,9 +169,9 @@ namespace SenseShift::BH::BLE { BH_BLE_SERVICE_MOTOR_CHAR_SERIAL_KEY_UUID, PROPERTY_READ | PROPERTY_WRITE ); - uint8_t serialNumber[ConnectionConfig_t::SN_LENGTH]; - memcpy(serialNumber, this->config.serialNumber, ConnectionConfig_t::SN_LENGTH); - serialNumberChar->setValue(serialNumber, ConnectionConfig_t::SN_LENGTH); + uint8_t serialNumber[ConnectionConfig::SN_LENGTH]; + memcpy(serialNumber, this->config.serialNumber, ConnectionConfig::SN_LENGTH); + serialNumberChar->setValue(serialNumber, ConnectionConfig::SN_LENGTH); serialNumberChar->setCallbacks(new LogOutputCharCallbacks()); } diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp index ea5b1ae6..a0265f74 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -16,13 +16,13 @@ #endif namespace SenseShift::BH::BLE { - typedef struct ConnectionConfig { + struct ConnectionConfig { static constexpr size_t SN_LENGTH = 10; std::string deviceName; uint16_t appearance; uint8_t serialNumber[SN_LENGTH]; - } ConnectionConfig_t; + }; class ConnectionCallbacks { public: @@ -32,9 +32,9 @@ namespace SenseShift::BH::BLE { class Connection final : public IEventListener { public: - typedef std::function<void(std::string&)> MotorHandler_t; + using MotorHandler = std::function<void(std::string&)>; - Connection(const ConnectionConfig_t& config, MotorHandler_t motorHandler, IEventDispatcher* eventDispatcher) : + Connection(const ConnectionConfig& config, MotorHandler motorHandler, IEventDispatcher* eventDispatcher) : config(config), motorHandler(motorHandler), eventDispatcher(eventDispatcher) { this->eventDispatcher->addEventListener(this); @@ -67,8 +67,8 @@ namespace SenseShift::BH::BLE { }; private: - const ConnectionConfig_t& config; - MotorHandler_t motorHandler; + const ConnectionConfig& config; + MotorHandler motorHandler; ::SenseShift::IEventDispatcher* eventDispatcher; BLEServer* bleServer = nullptr; diff --git a/lib/freertos/senseshift/freertos/input/sensor.hpp b/lib/freertos/senseshift/freertos/input/sensor.hpp index cf7a1f45..8209aa3f 100644 --- a/lib/freertos/senseshift/freertos/input/sensor.hpp +++ b/lib/freertos/senseshift/freertos/input/sensor.hpp @@ -13,14 +13,14 @@ namespace SenseShift::FreeRTOS::Input { friend class Task<SensorUpdateTask>; private: - using Sensor_t = ::SenseShift::ITickable; + using Sensor = ::SenseShift::ITickable; public: - SensorUpdateTask(Sensor_t* sensor, std::uint32_t updateDelay, TaskConfig taskConfig) : + SensorUpdateTask(Sensor* sensor, std::uint32_t updateDelay, TaskConfig taskConfig) : Task<SensorUpdateTask>(taskConfig), updateDelay(updateDelay){}; protected: - Sensor_t* sensor; + Sensor* sensor; std::uint32_t updateDelay; void run() @@ -37,10 +37,10 @@ namespace SenseShift::FreeRTOS::Input { friend class SensorUpdateTask; private: - using Sensor_t = ::SenseShift::Input::MemoizedSensor<_Tp>; + using Sensor = ::SenseShift::Input::MemoizedSensor<_Tp>; public: - TaskedSensor(Sensor_t* sensor, std::uint32_t updateDelay, TaskConfig taskConfig) : + TaskedSensor(Sensor* sensor, std::uint32_t updateDelay, TaskConfig taskConfig) : SensorUpdateTask(sensor, updateDelay, taskConfig), sensor(sensor){}; void begin() override @@ -54,6 +54,6 @@ namespace SenseShift::FreeRTOS::Input { _Tp getValue() override { return this->sensor->getValue(); }; private: - Sensor_t* sensor; + Sensor* sensor; }; } // namespace SenseShift::FreeRTOS::Input diff --git a/lib/hands/hand_interface.hpp b/lib/hands/hand_interface.hpp index 71249f0c..907a553b 100644 --- a/lib/hands/hand_interface.hpp +++ b/lib/hands/hand_interface.hpp @@ -5,23 +5,23 @@ namespace SenseShift::Body { namespace Hands { - typedef std::uint8_t HandSideIndex_t; - typedef enum class HandSide : HandSideIndex_t { Left, Right } HandSide_t; - typedef std::uint8_t FingerIndex_t; - typedef enum class Finger : FingerIndex_t { + using HandSideIndex = std::uint8_t; + enum class HandSide : HandSideIndex { Left, Right }; + using FingerIndex = std::uint8_t; + enum class Finger : FingerIndex { Thumb, Index, Middle, Ring, Little, - } Finger_t; + }; 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_t FINGERTIP_POSITION(127, 16); + static constexpr const ::SenseShift::Body::Haptics::Position FINGERTIP_POSITION(127, 16); } // namespace Haptics } // namespace Hands } // namespace SenseShift::Body diff --git a/lib/haptics/senseshift/body/haptics/body.cpp b/lib/haptics/senseshift/body/haptics/body.cpp index ed97efd4..edd3ee6e 100644 --- a/lib/haptics/senseshift/body/haptics/body.cpp +++ b/lib/haptics/senseshift/body/haptics/body.cpp @@ -10,22 +10,22 @@ namespace SenseShift::Body::Haptics { } } - void HapticBody::effect(const EffectRequest_t& effect) + void HapticBody::effect(const EffectRequest& effect) { - if (effect.effect == Effect::Vibro && std::holds_alternative<VibroEffectData_t>(effect.data)) { + if (effect.effect == Effect::Vibro && std::holds_alternative<VibroEffectData>(effect.data)) { auto it = this->vibroTargets.find(effect.target); if (it == this->vibroTargets.end()) { log_w("No target found for effect: %d", effect.target); return; } - it->second->effect(effect.position, std::get<VibroEffectData_t>(effect.data)); + it->second->effect(effect.position, std::get<VibroEffectData>(effect.data)); } else { log_w("Non-supported effect type: %d", effect.effect); } } - void HapticBody::addTarget(const Target_t target, VibroPlane* plane) + void HapticBody::addTarget(const Target target, VibroPlane* plane) { this->vibroTargets[target] = plane; this->allTargets.insert({ target, plane }); diff --git a/lib/haptics/senseshift/body/haptics/body.hpp b/lib/haptics/senseshift/body/haptics/body.hpp index 2b049c83..b0c9068e 100644 --- a/lib/haptics/senseshift/body/haptics/body.hpp +++ b/lib/haptics/senseshift/body/haptics/body.hpp @@ -10,22 +10,22 @@ namespace SenseShift::Body::Haptics { class HapticBody { public: - typedef std::variant<VibroPlane*> AuctiativePlane_t; - typedef std::multimap<Target_t, AuctiativePlane_t> PlaneTargetMap_t; - typedef std::map<Target_t, VibroPlane*> VibroTargetMap_t; + using AuctiativePlane = std::variant<VibroPlane*>; + using PlaneTargetMap = std::multimap<Target, AuctiativePlane>; + using VibroTargetMap = std::map<Target, VibroPlane*>; HapticBody(){}; void setup(); - void effect(const EffectRequest_t&); + void effect(const EffectRequest&); - void addTarget(const Target_t, VibroPlane* plane); + void addTarget(const Target, VibroPlane* plane); - [[nodiscard]] const PlaneTargetMap_t* getTargets() const { return &allTargets; } + [[nodiscard]] const PlaneTargetMap* getTargets() const { return &allTargets; } private: - PlaneTargetMap_t allTargets{}; - VibroTargetMap_t vibroTargets{}; + PlaneTargetMap allTargets{}; + VibroTargetMap vibroTargets{}; }; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/interface.hpp b/lib/haptics/senseshift/body/haptics/interface.hpp index 4ab0df0e..c4084531 100644 --- a/lib/haptics/senseshift/body/haptics/interface.hpp +++ b/lib/haptics/senseshift/body/haptics/interface.hpp @@ -6,18 +6,18 @@ #include <senseshift/math/point2.hpp> namespace SenseShift::Body::Haptics { - typedef std::uint8_t EffectIntex_t; - static const EffectIntex_t EFFECT_INVALID = 0xFF; - typedef enum class Effect : EffectIntex_t { + using EffectIntex = std::uint8_t; + static constexpr EffectIntex EFFECT_INVALID = 0xFF; + enum class Effect : EffectIntex { Invalid = EFFECT_INVALID, Vibro = 0x00, // TODO: thermal, etc. // Thermal = 0x01, - } Effect_t; + }; - typedef std::uint8_t TargetIndex_t; - static const TargetIndex_t TARGET_INVALID = 0xFF; - typedef enum class Target : TargetIndex_t { + using TargetIndex = std::uint8_t; + static constexpr TargetIndex TARGET_INVALID = 0xFF; + enum class Target : TargetIndex { Invalid = TARGET_INVALID, ChestFront = 0x00, ChestBack = 0x01, @@ -44,38 +44,34 @@ namespace SenseShift::Body::Haptics { HandRightDorsal, // Back // TODO: arms, legs, etc. - } Target_t; + }; - typedef std::uint8_t Coordinate_t; - typedef ::SenseShift::Math::Point2<Coordinate_t> Position_t; + using Coordinate = std::uint8_t; + using Position = ::SenseShift::Math::Point2<Coordinate>; // Vibration intensity. - typedef struct VibroEffectData { - using Intensity_t = std::uint16_t; - inline static const Intensity_t INTENSITY_MIN = 0; - inline static const Intensity_t INTENSITY_MAX = 4095; + struct VibroEffectData { + using Intensity = std::uint16_t; + static constexpr Intensity INTENSITY_MIN = 0; + static constexpr Intensity INTENSITY_MAX = 4095; - Intensity_t intensity = 0; + Intensity intensity = 0; inline constexpr VibroEffectData() = default; - inline constexpr VibroEffectData(const Intensity_t intensity) : intensity(intensity) {} + inline constexpr VibroEffectData(const Intensity intensity) : intensity(intensity) {} inline constexpr VibroEffectData(const VibroEffectData& other) = default; inline constexpr operator std::uint16_t() const { return intensity; } - } VibroEffectData_t; + }; // TODO: thermal, etc. - typedef std::variant<VibroEffectData_t - // TODO: thermal, etc. - // ThermalEffectData_t - > - EffectData_t; - - typedef struct EffectRequest { - Effect_t effect = Effect::Invalid; - Target_t target = Target::Invalid; - Position_t position = Position_t(0, 0); - EffectData_t data; - } EffectRequest_t; + using EffectData = std::variant<VibroEffectData>; + + struct EffectRequest { + Effect effect = Effect::Invalid; + Target target = Target::Invalid; + Position position = Position(0, 0); + 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 21614dcc..ab11c81b 100644 --- a/lib/haptics/senseshift/body/haptics/plane.cpp +++ b/lib/haptics/senseshift/body/haptics/plane.cpp @@ -6,7 +6,7 @@ namespace SenseShift::Body::Haptics { template<typename _Tp, typename _Ta> - void ActuativePlane<_Tp, _Ta>::setActuators(const ActuatorMap_t& actuators) + void ActuativePlane<_Tp, _Ta>::setActuators(const ActuatorMap& actuators) { this->actuators.clear(); for (const auto& [point, actuator] : actuators) { @@ -33,7 +33,7 @@ namespace SenseShift::Body::Haptics { } template<typename _Tp, typename _Ta> - void ActuativePlane<_Tp, _Ta>::effect(const Position_t& pos, const Value_t& val) + void ActuativePlane<_Tp, _Ta>::effect(const Position& pos, const Value& val) { auto it = this->actuators.find(pos); if (it == this->actuators.end()) { @@ -46,15 +46,15 @@ namespace SenseShift::Body::Haptics { } template<typename _Tp, typename _Ta> - void ActuativePlane_Closest<_Tp, _Ta>::effect(const Position_t& pos, const Value_t& val) + void ActuativePlane_Closest<_Tp, _Ta>::effect(const Position& pos, const Value& val) { auto& closest = this->findClosestPoint(*this->getAvailablePoints(), pos); ActuativePlane<_Tp, _Ta>::effect(closest, val); } template<typename _Tp, typename _Ta> - const Position_t& - ActuativePlane_Closest<_Tp, _Ta>::findClosestPoint(const PositionSet_t& pts, const Position_t& target) const + const Position& + ActuativePlane_Closest<_Tp, _Ta>::findClosestPoint(const PositionSet& pts, const Position& target) const { // check if exact point exists auto it = pts.find(target); @@ -63,7 +63,7 @@ namespace SenseShift::Body::Haptics { } // find closest point by square distance - std::multimap<float, Position_t> mp = {}; + std::multimap<float, Position> mp = {}; for (const auto& _p : pts) { mp.insert({ (target - _p), _p }); } @@ -73,8 +73,6 @@ namespace SenseShift::Body::Haptics { return nearest->second; } - template class ActuativePlane<VibroEffectData_t, ::SenseShift::Output::IActuator<VibroEffectData_t::Intensity_t>>; - template class ActuativePlane_Closest< - VibroEffectData_t, - ::SenseShift::Output::IActuator<VibroEffectData_t::Intensity_t>>; + template class ActuativePlane<VibroEffectData, ::SenseShift::Output::IActuator<VibroEffectData::Intensity>>; + template class ActuativePlane_Closest<VibroEffectData, ::SenseShift::Output::IActuator<VibroEffectData::Intensity>>; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/plane.hpp b/lib/haptics/senseshift/body/haptics/plane.hpp index 5c2cf7be..b8ac0727 100644 --- a/lib/haptics/senseshift/body/haptics/plane.hpp +++ b/lib/haptics/senseshift/body/haptics/plane.hpp @@ -11,7 +11,7 @@ #include <vector> namespace SenseShift::Body::Haptics { - typedef std::set<Position_t> PositionSet_t; + using PositionSet = std::set<Position>; /** * Output "plane" (e.g. Chest, Palm, Finger, etc.) @@ -20,35 +20,34 @@ namespace SenseShift::Body::Haptics { */ template<typename _Tp, typename _Ta> class ActuativePlane { - static_assert(std::is_same<_Tp, VibroEffectData_t>()); + static_assert(std::is_same<_Tp, VibroEffectData>()); public: - using Value_t = _Tp; - using Actuator_t = _Ta; + using Value = _Tp; + using Actuator = _Ta; - typedef std::map<Position_t, Actuator_t*> ActuatorMap_t; - typedef std::map<Position_t, Value_t> PositionStateMap_t; + using ActuatorMap = std::map<Position, Actuator*>; + using PositionStateMap = std::map<Position, Value>; ActuativePlane() = default; - ActuativePlane(const ActuatorMap_t& actuators) { this->setActuators(actuators); } + ActuativePlane(const ActuatorMap& actuators) { this->setActuators(actuators); } void setup(); - virtual void effect(const Position_t&, const Value_t&); + virtual void effect(const Position&, const Value&); - [[nodiscard]] const PositionSet_t* getAvailablePoints() const { return &points; } - [[nodiscard]] const PositionStateMap_t* getActuatorStates() const { return &states; } + [[nodiscard]] const PositionSet* getAvailablePoints() const { return &points; } + [[nodiscard]] const PositionStateMap* getActuatorStates() const { return &states; } private: - PositionSet_t points; - ActuatorMap_t actuators{}; - PositionStateMap_t states{}; + PositionSet points; + ActuatorMap actuators{}; + PositionStateMap states{}; - void setActuators(const ActuatorMap_t&); + void setActuators(const ActuatorMap&); }; - typedef ActuativePlane<VibroEffectData_t, ::SenseShift::Output::IActuator<VibroEffectData_t::Intensity_t>> - VibroPlane; + using VibroPlane = ActuativePlane<VibroEffectData, ::SenseShift::Output::IActuator<VibroEffectData::Intensity>>; /** * Output plane, finds the closest actuator for the given point. @@ -57,30 +56,30 @@ namespace SenseShift::Body::Haptics { template<typename _Tp, typename _Ta> class ActuativePlane_Closest : public ActuativePlane<_Tp, _Ta> { public: - typedef _Tp Value_t; + using Value = _Tp; - ActuativePlane_Closest(const typename ActuativePlane<_Tp, _Ta>::ActuatorMap_t& actuators) : + ActuativePlane_Closest(const typename ActuativePlane<_Tp, _Ta>::ActuatorMap& actuators) : ActuativePlane<_Tp, _Ta>(actuators) { } - void effect(const Position_t&, const Value_t&) override; + void effect(const Position&, const Value&) override; private: - [[nodiscard]] const Position_t& findClosestPoint(const PositionSet_t&, const Position_t&) const; + [[nodiscard]] const Position& findClosestPoint(const PositionSet&, const Position&) const; }; - typedef ActuativePlane_Closest<VibroEffectData_t, ::SenseShift::Output::IActuator<VibroEffectData_t::Intensity_t>> - VibroPlane_Closest; + using VibroPlane_Closest = + ActuativePlane_Closest<VibroEffectData, ::SenseShift::Output::IActuator<VibroEffectData::Intensity>>; // TODO: configurable margin class PlaneMapper_Margin { public: template<typename _Tp> - [[nodiscard]] static constexpr inline std::map<Position_t, _Tp*> + [[nodiscard]] static constexpr inline std::map<Position, _Tp*> mapMatrixCoordinates(std::vector<std::vector<_Tp*>> map2d) { - std::map<Position_t, _Tp*> points{}; + std::map<Position, _Tp*> points{}; size_t y_size = map2d.size(); size_t y_max = y_size - 1; @@ -92,7 +91,7 @@ namespace SenseShift::Body::Haptics { for (size_t x = 0; x < x_size; ++x) { auto* wr = row.at(x); - Position_t coord = PlaneMapper_Margin::mapPoint<Position_t::Value_t>(x, y, x_max, y_max); + Position coord = PlaneMapper_Margin::mapPoint<Position::Value>(x, y, x_max, y_max); points[coord] = wr; } @@ -109,11 +108,11 @@ namespace SenseShift::Body::Haptics { [[nodiscard]] static constexpr inline ::SenseShift::Math::Point2<_Tp> mapPoint(_Tp x, _Tp y, _Tp x_max, _Tp y_max) { - using Point_t = ::SenseShift::Math::Point2<_Tp>; + using Point = ::SenseShift::Math::Point2<_Tp>; - return Point_t( - ::SenseShift::accurateMap<_Tp>(x + 1, 0, x_max + 2, Point_t::MIN, Point_t::MAX), - ::SenseShift::accurateMap<_Tp>(y + 1, 0, y_max + 2, Point_t::MIN, Point_t::MAX) + return Point( + ::SenseShift::accurateMap<_Tp>(x + 1, 0, x_max + 2, Point::MIN, Point::MAX), + ::SenseShift::accurateMap<_Tp>(y + 1, 0, y_max + 2, Point::MIN, Point::MAX) ); } }; diff --git a/lib/math/senseshift/math/point2.hpp b/lib/math/senseshift/math/point2.hpp index 001d16bf..b91b096b 100644 --- a/lib/math/senseshift/math/point2.hpp +++ b/lib/math/senseshift/math/point2.hpp @@ -10,10 +10,10 @@ namespace SenseShift::Math { std::is_arithmetic<_Tp>::value, "::SenseShift::Math::Point2 only can be used with arithmetic types" ); - typedef _Tp Value_t; + using Value = _Tp; - inline static const _Tp MIN = std::numeric_limits<_Tp>::min(); - inline static const _Tp MAX = std::numeric_limits<_Tp>::max(); + static constexpr _Tp MIN = std::numeric_limits<_Tp>::min(); + static constexpr _Tp MAX = std::numeric_limits<_Tp>::max(); _Tp x, y; @@ -33,10 +33,10 @@ namespace SenseShift::Math { } }; - typedef Point2<unsigned char> Point2b; - typedef Point2<double> Point2d; - typedef Point2<float> Point2f; - typedef Point2<int> Point2i; - typedef Point2<short> Point2s; - typedef Point2<unsigned short> Point2w; + using Point2b = Point2<unsigned char>; + using Point2d = Point2<double>; + using Point2f = Point2<float>; + using Point2i = Point2<int>; + using Point2s = Point2<short>; + using Point2w = Point2<unsigned short>; }; // namespace SenseShift::Math diff --git a/lib/opengloves/og_protocol.hpp b/lib/opengloves/og_protocol.hpp index 3b8dcccc..a8f19e2e 100644 --- a/lib/opengloves/og_protocol.hpp +++ b/lib/opengloves/og_protocol.hpp @@ -57,8 +57,8 @@ namespace OpenGloves { virtual size_t readCommand(char* buffer, size_t length) = 0; }; - typedef uint16_t CommandIndex_t; - typedef enum Command : CommandIndex_t { + using CommandIndex = uint16_t; + enum Command : CommandIndex { ThumbCurl, ThumbSplay, @@ -73,7 +73,7 @@ namespace OpenGloves { PinkyCurl, PinkySplay, - } Command; + }; - typedef std::function<void(Command, uint16_t)> CommandCallback; + using CommandCallback = std::function<void(Command, uint16_t)>; } // namespace OpenGloves diff --git a/lib/opengloves/sensor/og_finger.hpp b/lib/opengloves/sensor/og_finger.hpp index 1be50ec0..542d981e 100644 --- a/lib/opengloves/sensor/og_finger.hpp +++ b/lib/opengloves/sensor/og_finger.hpp @@ -31,7 +31,7 @@ namespace OpenGloves { virtual uint16_t getCurl() = 0; }; - typedef SenseShift::Input::ISimpleSensor<FingerValue> IFingerSensor; + using IFingerSensor = SenseShift::Input::ISimpleSensor<FingerValue>; class SimpleFingerSensor : public IFingerSensor, public ICurl { public: diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index 03a560be..0ff45557 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -18,10 +18,10 @@ class TestActuator : public IActuator<uint16_t> { void test_layout_tactsuitx16(void) { - static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; - static const OutputLayout_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX16; + static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; + static const OutputLayout bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX16; - static const size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; + static constexpr size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; static const uint8_t layoutGroups[layoutGroupsSize] = BH_LAYOUT_TACTSUITX16_GROUPS; auto body = new HapticBody(); @@ -43,11 +43,11 @@ void test_layout_tactsuitx16(void) TestActuator* actuator14 = new TestActuator(); TestActuator* actuator15 = new TestActuator(); - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ { actuator0, actuator1, actuator2, actuator3 }, { actuator4, actuator5, actuator6, actuator7 }, }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ { actuator8, actuator9, actuator10, actuator11 }, { actuator12, actuator13, actuator14, actuator15 }, }); @@ -86,19 +86,19 @@ void test_layout_tactsuitx16(void) void test_layout_tactsuitx40(void) { - static const size_t bhLayoutSize = BH_LAYOUT_TACTSUITX40_SIZE; - static const OutputLayout_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; + static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTSUITX40_SIZE; + static const OutputLayout bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; auto body = new HapticBody(); - std::vector<std::vector<VibroPlane::Actuator_t*>> frontMatrix = { + std::vector<std::vector<VibroPlane::Actuator*>> frontMatrix = { { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, }; - std::vector<std::vector<VibroPlane::Actuator_t*>> backMatrix = { + std::vector<std::vector<VibroPlane::Actuator*>> backMatrix = { { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, @@ -106,8 +106,8 @@ void test_layout_tactsuitx40(void) { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, }; - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>(frontMatrix); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>(backMatrix); + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>(frontMatrix); + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>(backMatrix); auto frontPlane = new VibroPlane(frontOutputs); auto backPlane = new VibroPlane(backOutputs); @@ -169,8 +169,8 @@ void test_layout_tactsuitx40(void) void test_layout_tactal(void) { - static const size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; - static const ::SenseShift::Body::Haptics::Position_t bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; + static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; + static const ::SenseShift::Body::Haptics::Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; auto body = new HapticBody(); @@ -181,7 +181,7 @@ void test_layout_tactal(void) TestActuator* actuator4 = new TestActuator(); TestActuator* actuator5 = new TestActuator(); - auto outputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator_t>({ + auto outputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ { actuator0, actuator1, actuator2, actuator3, actuator4, actuator5 }, }); auto plane = new VibroPlane(outputs); diff --git a/test/test_haptics_body/main.cpp b/test/test_haptics_body/main.cpp index 5abefa7d..7f00d150 100644 --- a/test/test_haptics_body/main.cpp +++ b/test/test_haptics_body/main.cpp @@ -18,7 +18,7 @@ void test_it_sets_up_planes(void) { auto body = new HapticBody(); - VibroPlane::ActuatorMap_t outputs = { + VibroPlane::ActuatorMap outputs = { { { 0, 0 }, new TestActuator() }, { { 0, 1 }, new TestActuator() }, { { 1, 0 }, new TestActuator() }, @@ -54,25 +54,25 @@ void test_it_handles_effect__vibro(void) .effect = Effect::Vibro, .target = Target::ChestFront, .position = { 0, 0 }, - .data = (VibroEffectData_t) 64, + .data = (VibroEffectData) 64, }); body->effect({ .effect = Effect::Vibro, .target = Target::ChestFront, .position = { 0, 1 }, - .data = (VibroEffectData_t) 128, + .data = (VibroEffectData) 128, }); body->effect({ .effect = Effect::Vibro, .target = Target::ChestFront, .position = { 1, 0 }, - .data = (VibroEffectData_t) 192, + .data = (VibroEffectData) 192, }); body->effect({ .effect = Effect::Vibro, .target = Target::ChestFront, .position = { 1, 1 }, - .data = (VibroEffectData_t) 255, + .data = (VibroEffectData) 255, }); TEST_ASSERT_EQUAL(64, actuator1->intensity); diff --git a/test/test_haptics_plane/main.cpp b/test/test_haptics_plane/main.cpp index 0be53a48..7c8890cc 100644 --- a/test/test_haptics_plane/main.cpp +++ b/test/test_haptics_plane/main.cpp @@ -16,7 +16,7 @@ class TestActuator : public IActuator<uint16_t> { void test_it_sets_up_actuators(void) { - VibroPlane::ActuatorMap_t outputs = { + VibroPlane::ActuatorMap outputs = { { { 0, 0 }, new TestActuator() }, { { 0, 1 }, new TestActuator() }, { { 1, 0 }, new TestActuator() }, @@ -39,7 +39,7 @@ void test_it_writes_to_correct_output(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - VibroPlane::ActuatorMap_t outputs = { + VibroPlane::ActuatorMap outputs = { { { 0, 0 }, actuator }, { { 0, 1 }, actuator2 }, { { 1, 0 }, actuator3 }, @@ -64,7 +64,7 @@ void test_it_updates_state(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - VibroPlane::ActuatorMap_t outputs = { + VibroPlane::ActuatorMap outputs = { { { 0, 0 }, actuator }, { { 0, 1 }, actuator2 }, { { 1, 0 }, actuator3 }, @@ -96,7 +96,7 @@ void test_closest_it_writes_to_correct_if_exact(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - VibroPlane_Closest::ActuatorMap_t outputs = { + VibroPlane_Closest::ActuatorMap outputs = { { { 0, 0 }, actuator }, { { 0, 1 }, actuator2 }, { { 1, 0 }, actuator3 }, @@ -121,7 +121,7 @@ void test_closest_it_correctly_finds_closest(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - VibroPlane_Closest::ActuatorMap_t outputs = { + VibroPlane_Closest::ActuatorMap outputs = { { { 0, 0 }, actuator }, { { 0, 64 }, actuator2 }, { { 64, 0 }, actuator3 }, @@ -144,7 +144,7 @@ void test_closest_it_updates_state(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - VibroPlane_Closest::ActuatorMap_t outputs = { + VibroPlane_Closest::ActuatorMap outputs = { { { 0, 0 }, actuator }, { { 0, 64 }, actuator2 }, { { 64, 0 }, actuator3 }, From fc0fc5522b6a27e2fe7828fad93ba425981dc499 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Fri, 13 Oct 2023 10:58:59 +0400 Subject: [PATCH 44/82] chore: add VSCode extensions recommends --- .vscode/extensions.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..8e806412 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,11 @@ +{ + "recommendations": [ + "ms-vscode.cpptools", + "redhat.vscode-yaml", + "platformio.platformio-ide", + "Wokwi.wokwi-vscode", + "xaver.clang-format", + "editorconfig.editorconfig", + "wakatime.vscode-wakatime" + ] +} From 2d125a4e6a9a66bef90a4c7d3f72e4924c8af4a2 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 24 Oct 2023 02:15:59 +0400 Subject: [PATCH 45/82] ci: change lcov reporter --- .github/workflows/ci.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb9197de..bade01aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -428,10 +428,13 @@ jobs: ./build/coverage/ retention-days: 5 - - uses: manarbenkraouda/lcov-reporter-action@v0.3.5.3 + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 with: - github-token: ${{ secrets.GITHUB_TOKEN }} - lcov-file: ./build/lcov/lcov.info.cleaned + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true + files: ./build/lcov/lcov.info.cleaned + flags: unittests wokwi: needs: From 25356a4f28aa4e327293577244f65ad260c8717d Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 24 Oct 2023 10:43:07 +0000 Subject: [PATCH 46/82] ci: configure codecov --- README.md | 1 + codecov.yml | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 codecov.yml diff --git a/README.md b/README.md index dc172271..4a655a94 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Build your own DIY haptic vest, haptic gloves, and more! [](https://twitter.com/leon0399) [](https://github.com/senseshift/senseshift-firmware/actions/workflows/ci.yml) +[](https://codecov.io/gh/senseshift/senseshift-firmware) [](https://github.com/senseshift/senseshift-firmware/issues?q=is%3Aissue+is%3Aopen+label%3Abug) [](/LICENSE) diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..ccc8e521 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,3 @@ +comment: + layout: "header, diff, flags, components" # show component info in the PR comment + From 99d96f0fcd8b23d49f798eae079f00ea25ec8f5e Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 5 Nov 2023 13:55:02 +0400 Subject: [PATCH 47/82] feat(deps): update frozen submodule --- lib/frozen | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/frozen b/lib/frozen index eb113465..3a4f00cb 160000 --- a/lib/frozen +++ b/lib/frozen @@ -1 +1 @@ -Subproject commit eb113465791905f29384a9deac6650fc323f4d53 +Subproject commit 3a4f00cb83d580880b8a79864a479e1a14eb8c74 From 92c5d13dbc7a25f17736c5b8b02b25bc3ba73345 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sat, 30 Dec 2023 18:31:07 +0400 Subject: [PATCH 48/82] chore(PlatformIO): separate configs --- .vscode/extensions.json | 15 +- ini/opengloves-indexer.ini | 175 ++++++++++++++++++++ ini/opengloves-lucidgloves.ini | 116 +++++++++++++ ini/opengloves.ini | 293 --------------------------------- platformio.ini | 3 + 5 files changed, 304 insertions(+), 298 deletions(-) create mode 100644 ini/opengloves-indexer.ini create mode 100644 ini/opengloves-lucidgloves.ini diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 8e806412..7e2b2d8e 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,11 +1,16 @@ { + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format "recommendations": [ - "ms-vscode.cpptools", - "redhat.vscode-yaml", - "platformio.platformio-ide", "Wokwi.wokwi-vscode", - "xaver.clang-format", "editorconfig.editorconfig", - "wakatime.vscode-wakatime" + "ms-vscode.cpptools", + "platformio.platformio-ide", + "redhat.vscode-yaml", + "wakatime.vscode-wakatime", + "xaver.clang-format" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" ] } diff --git a/ini/opengloves-indexer.ini b/ini/opengloves-indexer.ini new file mode 100644 index 00000000..7d5cd163 --- /dev/null +++ b/ini/opengloves-indexer.ini @@ -0,0 +1,175 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 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} + ; 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} + +<mode_configs/opengloves/opengloves.cpp> +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} + ; 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} + +<mode_configs/opengloves/opengloves.cpp> +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} + +<mode_configs/opengloves/opengloves.cpp> +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} + +<mode_configs/opengloves/opengloves.cpp> +lib_deps = ${opengloves.lib_deps} diff --git a/ini/opengloves-lucidgloves.ini b/ini/opengloves-lucidgloves.ini new file mode 100644 index 00000000..f4047f55 --- /dev/null +++ b/ini/opengloves-lucidgloves.ini @@ -0,0 +1,116 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 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} + ; 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 + +build_unflags = ${opengloves.build_unflags} +build_src_filter = ${opengloves.build_src_filter} + +<mode_configs/opengloves/opengloves.cpp> +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} + ; 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 + + ; todo: add servo pins + +build_unflags = ${opengloves.build_unflags} +build_src_filter = ${opengloves.build_src_filter} + +<mode_configs/opengloves/opengloves.cpp> +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} + ; 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} + +<mode_configs/opengloves/opengloves.cpp> +lib_deps = ${opengloves.lib_deps} diff --git a/ini/opengloves.ini b/ini/opengloves.ini index 0160ae8d..b7bb70cc 100644 --- a/ini/opengloves.ini +++ b/ini/opengloves.ini @@ -58,296 +58,3 @@ build_flags = ${common.build_flags} build_unflags = ${common.build_unflags} build_src_filter = ${common.build_src_filter} lib_deps = ${common.lib_deps} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; 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} - ; 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 - -build_unflags = ${opengloves.build_unflags} -build_src_filter = ${opengloves.build_src_filter} - +<mode_configs/opengloves/opengloves.cpp> -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} - ; 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 - - ; todo: add servo pins - -build_unflags = ${opengloves.build_unflags} -build_src_filter = ${opengloves.build_src_filter} - +<mode_configs/opengloves/opengloves.cpp> -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} - ; 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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; 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} - ; 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} - +<mode_configs/opengloves/opengloves.cpp> -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} - ; 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} - +<mode_configs/opengloves/opengloves.cpp> -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} - +<mode_configs/opengloves/opengloves.cpp> -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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} diff --git a/platformio.ini b/platformio.ini index 6787808b..4815cf7a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,6 +15,9 @@ 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 [common] build_unflags = From 9e33f0bfd8e18d4b94470e930813b01dcf4e67c6 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Fri, 26 Jan 2024 20:58:19 +0400 Subject: [PATCH 49/82] refactor: simplyfy overall setup and structure --- docs/DEVELOPMENT.md | 32 ++- firmware/firmware.cpp | 2 +- firmware/mode_configs/bhaptics/tactal.cpp | 19 +- firmware/mode_configs/bhaptics/tactglove.cpp | 27 ++- firmware/mode_configs/bhaptics/tactosy2.cpp | 21 +- firmware/mode_configs/bhaptics/tactosyf.cpp | 23 ++- firmware/mode_configs/bhaptics/tactosyh.cpp | 23 ++- .../mode_configs/bhaptics/tactsuit_x16.cpp | 35 ++-- .../bhaptics/tactsuit_x16_pca9685.cpp | 37 ++-- .../mode_configs/bhaptics/tactsuit_x40.cpp | 46 ++--- firmware/mode_configs/bhaptics/tactvisor.cpp | 19 +- .../mode_configs/opengloves/opengloves.cpp | 2 +- firmware/senseshift.cpp | 18 +- include/senseshift.h | 16 +- lib/arduino/library.json | 3 +- .../arduino/components/serial_plotter.cpp | 28 --- .../arduino/components/serial_plotter.hpp | 65 ------- .../arduino/input/sensor/analog.hpp | 23 +-- .../arduino/input/sensor/binary.hpp | 29 +++ .../arduino/input/sensor/digital.hpp | 34 ---- .../arduino/output/actuator/pca9685.hpp | 26 --- .../arduino/output/actuator/pwm.hpp | 47 ----- .../senseshift/arduino/output/analog.hpp | 29 +++ .../senseshift/arduino/output/pca9685.hpp | 35 ++++ .../senseshift/arduino/output/ledc.hpp | 57 ++++++ lib/battery/senseshift/battery.hpp | 58 +++++- lib/battery/senseshift/battery/sensor.hpp | 6 +- lib/bhaptics/senseshift/bh/devices.hpp | 95 ++++----- lib/bhaptics/senseshift/bh/encoding.hpp | 183 +++++++++--------- lib/core/senseshift/core/component.hpp | 33 ++++ lib/core/senseshift/core/helpers.hpp | 59 ++++++ lib/core/senseshift/core/logging.hpp | 40 ++++ lib/core/senseshift/core/macros.hpp | 4 + lib/core/senseshift/interface.hpp | 11 -- lib/core/senseshift/logging.hpp | 23 --- lib/freertos/senseshift/freertos/task.hpp | 2 +- lib/haptics/senseshift/body/haptics/body.cpp | 36 ++-- lib/haptics/senseshift/body/haptics/body.hpp | 39 ++-- .../senseshift/body/haptics/interface.hpp | 35 ++-- lib/haptics/senseshift/body/haptics/plane.cpp | 78 ++++---- lib/haptics/senseshift/body/haptics/plane.hpp | 128 ++++++------ lib/io/senseshift/input/sensor.hpp | 178 +++++++++-------- lib/io/senseshift/input/sensor/joystick.hpp | 32 +-- lib/io/senseshift/output/actuator.hpp | 22 --- lib/io/senseshift/output/binary_output.hpp | 10 + lib/io/senseshift/output/output.hpp | 15 ++ lib/math/senseshift/math/point2.hpp | 30 +-- lib/opengloves/og_protocol.hpp | 2 +- .../senseshift/opengloves/autoconfig.hpp | 2 +- .../senseshift/opengloves/encoding/alpha.hpp | 2 +- lib/opengloves/sensor/og_finger.hpp | 10 +- lib/opengloves/sensor/og_gesture.hpp | 8 +- lib/opengloves/sensor/og_sensor.hpp | 36 ++-- lib/opengloves_task/opengloves_task.hpp | 2 +- lib/util/senseshift/calibration.hpp | 116 +++++------ lib/util/senseshift/container.hpp | 2 +- lib/util/senseshift/range.hpp | 27 +-- 57 files changed, 1074 insertions(+), 946 deletions(-) delete mode 100644 lib/arduino/senseshift/arduino/components/serial_plotter.cpp delete mode 100644 lib/arduino/senseshift/arduino/components/serial_plotter.hpp create mode 100644 lib/arduino/senseshift/arduino/input/sensor/binary.hpp delete mode 100644 lib/arduino/senseshift/arduino/input/sensor/digital.hpp delete mode 100644 lib/arduino/senseshift/arduino/output/actuator/pca9685.hpp delete mode 100644 lib/arduino/senseshift/arduino/output/actuator/pwm.hpp create mode 100644 lib/arduino/senseshift/arduino/output/analog.hpp create mode 100644 lib/arduino/senseshift/arduino/output/pca9685.hpp create mode 100644 lib/arduino_esp32/senseshift/arduino/output/ledc.hpp create mode 100644 lib/core/senseshift/core/component.hpp create mode 100644 lib/core/senseshift/core/helpers.hpp create mode 100644 lib/core/senseshift/core/logging.hpp create mode 100644 lib/core/senseshift/core/macros.hpp delete mode 100644 lib/core/senseshift/interface.hpp delete mode 100644 lib/core/senseshift/logging.hpp delete mode 100644 lib/io/senseshift/output/actuator.hpp create mode 100644 lib/io/senseshift/output/binary_output.hpp create mode 100644 lib/io/senseshift/output/output.hpp diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index dafd8ccf..1a6e5409 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -1,3 +1,23 @@ +# Code Style + +## Member naming + +Local variable: `snake_case` +Global variable: `snake_case` + +Class: `UpperCamelCase` +Class member: `snake_case_` (**with trailing underscore**) +ClassFunction: `camelCase` +Function argument: `snake_case` + +## Useful Scripts + +### 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 {} \; +``` + # Debugging ## Debugging in Wokwi @@ -9,7 +29,7 @@ Run and debug firmware in Wokwi Simulator pio debug -e lucidgloves-prototype3 ``` 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)): +3. Add launch option (this step is required until PlatformIO fixes this issue: [#3824](https://github.com/platformio/platformio-core/issues/3824)): ```json ... @@ -24,12 +44,4 @@ Run and debug firmware in Wokwi Simulator "miDebuggerServerAddress": "localhost:3333", }, ... - ``` - -## Useful Scripts - -### 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 {} \; -``` + ``` \ No newline at end of file diff --git a/firmware/firmware.cpp b/firmware/firmware.cpp index c30147c3..213a1fbd 100644 --- a/firmware/firmware.cpp +++ b/firmware/firmware.cpp @@ -19,7 +19,7 @@ extern void loopMode(); #if defined(ARDUINO) -SenseShift::SenseShift App; +SenseShift::Application App; void setup() { diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index 54bd226f..08f35d38 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -7,7 +7,7 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/actuator/pwm.hpp> +#include <senseshift/arduino/output/ledc.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> @@ -22,24 +22,23 @@ using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern SenseShift::SenseShift App; -SenseShift::SenseShift* app = &App; +extern Application App; +Application* app = &App; -static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; -static const Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; +static const std::array<Position, BH_LAYOUT_TACTAL_SIZE> bhLayout = { BH_LAYOUT_TACTAL }; void setupMode() { // Configure PWM pins to their positions on the face - const auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ + const auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ // clang-format off - { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25), new ActuatorPWM(26), new ActuatorPWM(27), new ActuatorPWM(14) }, + { new LedcOutput(32), new LedcOutput(33), new LedcOutput(25), new LedcOutput(26), new LedcOutput(27), new LedcOutput(14) }, // clang-format on }); - app->getHapticBody()->addTarget(Target::FaceFront, new VibroPlane_Closest(faceOutputs)); + app->getVibroBody()->addTarget(Target::FaceFront, new FloatPlane_Closest(faceOutputs)); - app->getHapticBody()->setup(); + app->getVibroBody()->setup(); auto* bhBleConnection = new BLE::Connection( { @@ -48,7 +47,7 @@ void setupMode() .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); + Decoder::applyPlain(app->getVibroBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 3091a5d6..7463c1b9 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -7,7 +7,7 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/actuator/pwm.hpp> +#include <senseshift/arduino/output/ledc.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> @@ -23,13 +23,12 @@ using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern SenseShift::SenseShift App; -SenseShift::SenseShift* app = &App; +extern Application App; +Application* app = &App; static constexpr Body::Hands::HandSide handSide = Body::Hands::HandSide::SENSESHIFT_HAND_SIDE; -static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTGLOVE_SIZE; // clang-format off -static const OutputLayout (&bhLayout)[bhLayoutSize] = handSide == Body::Hands::HandSide::Left ? BH::TactGloveLeftLayout : BH::TactGloveRightLayout; +static const auto& bhLayout = handSide == Body::Hands::HandSide::Left ? BH::TactGloveLeftLayout : BH::TactGloveRightLayout; // clang-format on void setupMode() @@ -37,17 +36,17 @@ void setupMode() // Configure PWM pins to their positions on the glove // Replace `new PWMOutputWriter(...)` with `nullptr` to disable a specific actuator addTactGloveActuators( - app->getHapticBody(), + app->getVibroBody(), handSide, - new ActuatorPWM(32), // Thumb - new ActuatorPWM(33), // Index - new ActuatorPWM(25), // Middle - new ActuatorPWM(26), // Ring - new ActuatorPWM(27), // Little - new ActuatorPWM(14) // Wrist + new LedcOutput(32), // Thumb + new LedcOutput(33), // Index + new LedcOutput(25), // Middle + new LedcOutput(26), // Ring + new LedcOutput(27), // Little + new LedcOutput(14) // Wrist ); - app->getHapticBody()->setup(); + app->getVibroBody()->setup(); auto* bhBleConnection = new BLE::Connection( { @@ -56,7 +55,7 @@ void setupMode() .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro); + Decoder::applyPlain(app->getVibroBody(), value, bhLayout, Effect::Vibro); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index 20751691..74cbcdfd 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -7,7 +7,7 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/actuator/pwm.hpp> +#include <senseshift/arduino/output/ledc.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> @@ -22,25 +22,24 @@ using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern SenseShift::SenseShift App; -SenseShift::SenseShift* app = &App; +extern Application App; +Application* app = &App; -static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTOSY2_SIZE; -static const Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSY2; +static const std::array<Position, BH_LAYOUT_TACTOSY2_SIZE> bhLayout = { BH_LAYOUT_TACTOSY2 }; void setupMode() { // Configure PWM pins to their positions on the forearm - auto forearmOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ + auto forearmOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ // clang-format off - { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25) }, - { new ActuatorPWM(26), new ActuatorPWM(27), new ActuatorPWM(14) }, + { new LedcOutput(32), new LedcOutput(33), new LedcOutput(25) }, + { new LedcOutput(26), new LedcOutput(27), new LedcOutput(14) }, // clang-format on }); - app->getHapticBody()->addTarget(Target::Accessory, new VibroPlane_Closest(forearmOutputs)); + app->getVibroBody()->addTarget(Target::Accessory, new FloatPlane_Closest(forearmOutputs)); - app->getHapticBody()->setup(); + app->getVibroBody()->setup(); auto* bhBleConnection = new BLE::Connection( { @@ -49,7 +48,7 @@ void setupMode() .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); + Decoder::applyPlain(app->getVibroBody(), value, bhLayout, Effect::Vibro, Target::Accessory); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index b7667f0f..c8352ee8 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -7,7 +7,7 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/actuator/pwm.hpp> +#include <senseshift/arduino/output/ledc.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> @@ -22,26 +22,25 @@ using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern SenseShift::SenseShift App; -SenseShift::SenseShift* app = &App; +extern Application App; +Application* app = &App; -static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTOSYF_SIZE; -static const Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYF; +static const std::array<Position, BH_LAYOUT_TACTOSYF_SIZE> bhLayout = { BH_LAYOUT_TACTOSYF }; void setupMode() { // Configure PWM pins to their positions on the feet - auto footOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ + auto footOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ // clang-format off - { new ActuatorPWM(32) }, - { new ActuatorPWM(33) }, - { new ActuatorPWM(25) }, + { new LedcOutput(32) }, + { new LedcOutput(33) }, + { new LedcOutput(25) }, // clang-format on }); - app->getHapticBody()->addTarget(Target::Accessory, new VibroPlane_Closest(footOutputs)); + app->getVibroBody()->addTarget(Target::Accessory, new FloatPlane_Closest(footOutputs)); - app->getHapticBody()->setup(); + app->getVibroBody()->setup(); auto* bhBleConnection = new BLE::Connection( { @@ -50,7 +49,7 @@ void setupMode() .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); + Decoder::applyPlain(app->getVibroBody(), value, bhLayout, Effect::Vibro, Target::Accessory); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 50b46ec9..a4b8574f 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -7,7 +7,7 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/actuator/pwm.hpp> +#include <senseshift/arduino/output/ledc.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> @@ -22,26 +22,25 @@ using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern SenseShift::SenseShift App; -SenseShift::SenseShift* app = &App; +extern Application App; +Application* app = &App; -static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTOSYH_SIZE; -static const Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTOSYH; +static const std::array<Position, BH_LAYOUT_TACTOSYH_SIZE> bhLayout = { BH_LAYOUT_TACTOSYH }; void setupMode() { // Configure PWM pins to their positions on the hands - auto handOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ + auto handOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ // clang-format off - { new ActuatorPWM(32) }, - { new ActuatorPWM(33) }, - { new ActuatorPWM(25) } + { new LedcOutput(32) }, + { new LedcOutput(33) }, + { new LedcOutput(25) } // clang-format on }); - app->getHapticBody()->addTarget(Target::Accessory, new VibroPlane_Closest(handOutputs)); + app->getVibroBody()->addTarget(Target::Accessory, new FloatPlane_Closest(handOutputs)); - app->getHapticBody()->setup(); + app->getVibroBody()->setup(); auto* bhBleConnection = new BLE::Connection( { @@ -50,7 +49,7 @@ void setupMode() .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::Accessory); + Decoder::applyPlain(app->getVibroBody(), value, bhLayout, Effect::Vibro, Target::Accessory); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 62fc1e45..f5c566c3 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -5,10 +5,7 @@ #include <Wire.h> #include "senseshift.h" - -#include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/actuator/pwm.hpp> -#include <senseshift/battery/sensor.hpp> +#include <senseshift/arduino/output/ledc.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -22,36 +19,34 @@ using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern SenseShift::SenseShift App; -SenseShift::SenseShift* app = &App; +extern Application App; +Application* app = &App; -static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; -static const OutputLayout bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; +static const std::array<OutputLayout, BH_LAYOUT_TACTSUITX16_SIZE> bhLayout = { BH_LAYOUT_TACTSUITX16 }; // Ouput indices, responsible for x40 => x16 grouping -static constexpr size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; -static const uint8_t layoutGroups[layoutGroupsSize] = BH_LAYOUT_TACTSUITX16_GROUPS; +static const std::array<std::uint8_t,BH_LAYOUT_TACTSUITX16_GROUPS_SIZE> layoutGroups = BH_LAYOUT_TACTSUITX16_GROUPS; void setupMode() { // Configure PWM pins to their positions on the vest - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ // clang-format off - { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25), new ActuatorPWM(26) }, - { new ActuatorPWM(27), new ActuatorPWM(14), new ActuatorPWM(12), new ActuatorPWM(13) }, + { 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<VibroPlane::Actuator>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ // clang-format off - { new ActuatorPWM(19), new ActuatorPWM(18), new ActuatorPWM(5), new ActuatorPWM(17) }, - { new ActuatorPWM(16), new ActuatorPWM(4), new ActuatorPWM(2), new ActuatorPWM(15) }, + { new LedcOutput(19), new LedcOutput(18), new LedcOutput(5), new LedcOutput(17) }, + { new LedcOutput(16), new LedcOutput(4), new LedcOutput(2), new LedcOutput(15) }, // clang-format on }); - app->getHapticBody()->addTarget(Target::ChestFront, new VibroPlane_Closest(frontOutputs)); - app->getHapticBody()->addTarget(Target::ChestBack, new VibroPlane_Closest(backOutputs)); + app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane_Closest(frontOutputs)); + app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane_Closest(backOutputs)); - app->getHapticBody()->setup(); + app->getVibroBody()->setup(); auto* bhBleConnection = new BLE::Connection( { @@ -60,7 +55,7 @@ void setupMode() .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - Decoder::applyVestGrouped(app->getHapticBody(), value, bhLayout, layoutGroups); + Decoder::applyVestGrouped(app->getVibroBody(), value, bhLayout, layoutGroups); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index 8d3383e8..128dcd22 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -5,10 +5,7 @@ #include <Wire.h> #include "senseshift.h" - -#include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/actuator/pca9685.hpp> -#include <senseshift/battery/sensor.hpp> +#include <senseshift/arduino/output/pca9685.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -22,41 +19,39 @@ using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern SenseShift::SenseShift App; -SenseShift::SenseShift* app = &App; +extern Application App; +Application* app = &App; -static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; -static const OutputLayout bhLayout[BH_LAYOUT_TACTSUITX16_SIZE] = BH_LAYOUT_TACTSUITX16; +static const std::array<OutputLayout, BH_LAYOUT_TACTSUITX16_SIZE> bhLayout = { BH_LAYOUT_TACTSUITX16 }; // Ouput indices, responsible for x40 => x16 grouping -static constexpr size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; -static const uint8_t layoutGroups[layoutGroupsSize] = BH_LAYOUT_TACTSUITX16_GROUPS; +static const std::array<std::uint8_t,BH_LAYOUT_TACTSUITX16_GROUPS_SIZE> layoutGroups = BH_LAYOUT_TACTSUITX16_GROUPS; void setupMode() { // Configure the PCA9685 - auto pwm = new Adafruit_PWMServoDriver(0x40); + auto* pwm = new Adafruit_PWMServoDriver(0x40); pwm->begin(); pwm->setPWMFreq(PWM_FREQUENCY); // Assign the pins on the configured PCA9685 to positions on the vest - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ // clang-format off - { new ActuatorPCA9685(pwm, 0), new ActuatorPCA9685(pwm, 1), new ActuatorPCA9685(pwm, 2), new ActuatorPCA9685(pwm, 3) }, - { new ActuatorPCA9685(pwm, 4), new ActuatorPCA9685(pwm, 5), new ActuatorPCA9685(pwm, 6), new ActuatorPCA9685(pwm, 7) }, + { 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<VibroPlane::Actuator>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ // clang-format off - { new ActuatorPCA9685(pwm, 8), new ActuatorPCA9685(pwm, 9), new ActuatorPCA9685(pwm, 10), new ActuatorPCA9685(pwm, 11) }, - { new ActuatorPCA9685(pwm, 12), new ActuatorPCA9685(pwm, 13), new ActuatorPCA9685(pwm, 14), new ActuatorPCA9685(pwm, 15) }, + { 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) }, // clang-format on }); - app->getHapticBody()->addTarget(Target::ChestFront, new VibroPlane_Closest(frontOutputs)); - app->getHapticBody()->addTarget(Target::ChestBack, new VibroPlane_Closest(backOutputs)); + app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane_Closest(frontOutputs)); + app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane_Closest(backOutputs)); - app->getHapticBody()->setup(); + app->getVibroBody()->setup(); auto* bhBleConnection = new BLE::Connection( { @@ -65,7 +60,7 @@ void setupMode() .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - Decoder::applyVestGrouped(app->getHapticBody(), value, bhLayout, layoutGroups); + Decoder::applyVestGrouped(app->getVibroBody(), value, bhLayout, layoutGroups); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 13fce314..23983157 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -5,11 +5,8 @@ #include <Wire.h> #include "senseshift.h" - -#include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/actuator/pca9685.hpp> -#include <senseshift/arduino/output/actuator/pwm.hpp> -#include <senseshift/battery/sensor.hpp> +#include <senseshift/arduino/output/ledc.hpp> +#include <senseshift/arduino/output/pca9685.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -23,11 +20,10 @@ using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern SenseShift::SenseShift App; -SenseShift::SenseShift* app = &App; +extern Application App; +Application* app = &App; -static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTSUITX40_SIZE; -static const OutputLayout bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; +static const std::array<OutputLayout, BH_LAYOUT_TACTSUITX40_SIZE> bhLayout = { BH_LAYOUT_TACTSUITX40 }; void setupMode() { @@ -42,29 +38,29 @@ void setupMode() // Assign the pins on the configured PCA9685s and PWM pins to locations on the // vest - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ // clang-format off - { new ActuatorPCA9685(pwm0, 0), new ActuatorPCA9685(pwm0, 1), new ActuatorPCA9685(pwm0, 2), new ActuatorPCA9685(pwm0, 3) }, - { new ActuatorPCA9685(pwm0, 4), new ActuatorPCA9685(pwm0, 5), new ActuatorPCA9685(pwm0, 6), new ActuatorPCA9685(pwm0, 7) }, - { new ActuatorPCA9685(pwm0, 8), new ActuatorPCA9685(pwm0, 9), new ActuatorPCA9685(pwm0, 10), new ActuatorPCA9685(pwm0, 11) }, - { new ActuatorPCA9685(pwm0, 12), new ActuatorPCA9685(pwm0, 13), new ActuatorPCA9685(pwm0, 14), new ActuatorPCA9685(pwm0, 15) }, - { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25), new ActuatorPWM(26) }, + { 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<VibroPlane::Actuator>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ // clang-format off - { new ActuatorPCA9685(pwm1, 0), new ActuatorPCA9685(pwm1, 1), new ActuatorPCA9685(pwm1, 2), new ActuatorPCA9685(pwm1, 3) }, - { new ActuatorPCA9685(pwm1, 4), new ActuatorPCA9685(pwm1, 5), new ActuatorPCA9685(pwm1, 6), new ActuatorPCA9685(pwm1, 7) }, - { new ActuatorPCA9685(pwm1, 8), new ActuatorPCA9685(pwm1, 9), new ActuatorPCA9685(pwm1, 10), new ActuatorPCA9685(pwm1, 11) }, - { new ActuatorPCA9685(pwm1, 12), new ActuatorPCA9685(pwm1, 13), new ActuatorPCA9685(pwm1, 14), new ActuatorPCA9685(pwm1, 15) }, - { new ActuatorPWM(27), new ActuatorPWM(14), new ActuatorPWM(12), new ActuatorPWM(13) }, + { 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->getHapticBody()->addTarget(Target::ChestFront, new VibroPlane_Closest(frontOutputs)); - app->getHapticBody()->addTarget(Target::ChestBack, new VibroPlane_Closest(backOutputs)); + app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane_Closest(frontOutputs)); + app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane_Closest(backOutputs)); - app->getHapticBody()->setup(); + app->getVibroBody()->setup(); auto* bhBleConnection = new BLE::Connection( { @@ -73,7 +69,7 @@ void setupMode() .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - Decoder::applyVest(app->getHapticBody(), value, bhLayout); + Decoder::applyVest(app->getVibroBody(), value, bhLayout); }, app ); diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index f7e7ab44..1c3f02cb 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -7,7 +7,7 @@ #include "senseshift.h" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/output/actuator/pwm.hpp> +#include <senseshift/arduino/output/ledc.hpp> #include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> @@ -22,24 +22,23 @@ using namespace SenseShift::Battery; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern SenseShift::SenseShift App; -SenseShift::SenseShift* app = &App; +extern Application App; +Application* app = &App; -static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTVISOR_SIZE; -static const Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTVISOR; +static const std::array<Position, BH_LAYOUT_TACTVISOR_SIZE> bhLayout = { BH_LAYOUT_TACTVISOR }; void setupMode() { // Configure PWM pins to their positions on the face - auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ + auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ // clang-format off - { new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25), new ActuatorPWM(26) }, + { new LedcOutput(32), new LedcOutput(33), new LedcOutput(25), new LedcOutput(26) }, // clang-format on }); - app->getHapticBody()->addTarget(Target::FaceFront, new VibroPlane_Closest(faceOutputs)); + app->getVibroBody()->addTarget(Target::FaceFront, new FloatPlane_Closest(faceOutputs)); - app->getHapticBody()->setup(); + app->getVibroBody()->setup(); auto* bhBleConnection = new BLE::Connection( { @@ -48,7 +47,7 @@ void setupMode() .serialNumber = BH_SERIAL_NUMBER, }, [](std::string& value) -> void { - Decoder::applyPlain(app->getHapticBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); + Decoder::applyPlain(app->getVibroBody(), value, bhLayout, Effect::Vibro, Target::FaceFront); }, app ); diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 3ebfca56..bded27d3 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -1,7 +1,7 @@ #include <og_constants.hpp> #include <opengloves_task.hpp> #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/input/sensor/digital.hpp> +#include <senseshift/arduino/input/sensor/binary.hpp> #include <senseshift/arduino/output/actuator/servo.hpp> #include <senseshift/calibration.hpp> #include <senseshift/input/sensor.hpp> diff --git a/firmware/senseshift.cpp b/firmware/senseshift.cpp index 3ba2b1f7..d6445325 100644 --- a/firmware/senseshift.cpp +++ b/firmware/senseshift.cpp @@ -6,27 +6,29 @@ #include <Arduino.h> #endif -#include <senseshift/logging.hpp> +#include <senseshift/core/logging.hpp> namespace SenseShift { - SenseShift::SenseShift() + static const char *const TAG = "application"; + + Application::Application() { - this->pHapticBody = new Body::Haptics::HapticBody(); + this->vibro_body_ = new Body::Haptics::FloatBody (); } - void SenseShift::postEvent(const IEvent* event) + void Application::postEvent(const IEvent* event) { - log_i("Event dispatched at %u: %s (%p)", millis(), event->eventName.c_str(), event); + LOG_I(TAG, "Event dispatched at %u: %s (%p)", millis(), event->eventName.c_str(), event); - for (auto* listener : this->eventListeners) { + for (const auto* listener : this->event_listeners_) { listener->handleEvent(event); } delete event; } - void SenseShift::addEventListener(const IEventListener* listener) + void Application::addEventListener(const IEventListener* listener) { - this->eventListeners.push_back(listener); + this->event_listeners_.push_back(listener); } } // namespace SenseShift diff --git a/include/senseshift.h b/include/senseshift.h index 95c5603e..ec98103d 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -9,18 +9,18 @@ #include <vector> namespace SenseShift { - class SenseShift final : public IEventDispatcher { - private: - std::vector<const IEventListener*> eventListeners{}; - Body::Haptics::HapticBody* pHapticBody; - ::SenseShift::Battery::IBatterySensor* battery; - + class Application final : public IEventDispatcher { public: - SenseShift(); + Application(); - Body::Haptics::HapticBody* getHapticBody() { return this->pHapticBody; }; + [[nodiscard]] auto getVibroBody() const -> Body::Haptics::FloatBody* { return this->vibro_body_; }; void postEvent(const IEvent* event) override; void addEventListener(const IEventListener* listener) override; + + private: + std::vector<const IEventListener*> event_listeners_{}; + Body::Haptics::FloatBody* vibro_body_; + Battery::IBatterySensor* battery_ = nullptr; }; } // namespace SenseShift diff --git a/lib/arduino/library.json b/lib/arduino/library.json index 8601c003..8434426d 100644 --- a/lib/arduino/library.json +++ b/lib/arduino/library.json @@ -7,7 +7,6 @@ "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": "^0.13.0" + "sparkfun/SparkFun MAX1704x Fuel Gauge Arduino Library": "^1.0.4" } } diff --git a/lib/arduino/senseshift/arduino/components/serial_plotter.cpp b/lib/arduino/senseshift/arduino/components/serial_plotter.cpp deleted file mode 100644 index 8cd48978..00000000 --- a/lib/arduino/senseshift/arduino/components/serial_plotter.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "senseshift/arduino/components/serial_plotter.hpp" - -namespace SenseShift::Arduino { - struct PlaneVisitor { - const SenseShift::Body::Haptics::Target target; - HardwareSerial* serial; - - void operator()(const SenseShift::Body::Haptics::VibroPlane* plane) const - { - for (const auto& [position, state] : *(plane->getActuatorStates())) { - this->serial->printf("Output[%u][%ux%u]:%u, ", this->target, position.x, position.y, state.intensity); - } - } - }; - - template<typename _Tp> - void SerialPlotter_OutputStates<_Tp>::run() - { - while (true) { - for (const auto& [target, plane] : *output->getTargets()) { - std::visit(PlaneVisitor{ target, this->serial }, plane); - } - this->serial->println(); - - delay(this->sampleRate); - } - } -} // namespace SenseShift::Arduino diff --git a/lib/arduino/senseshift/arduino/components/serial_plotter.hpp b/lib/arduino/senseshift/arduino/components/serial_plotter.hpp deleted file mode 100644 index 2cc04d92..00000000 --- a/lib/arduino/senseshift/arduino/components/serial_plotter.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include <senseshift/body/haptics/body.hpp> -#include <senseshift/freertos/task.hpp> - -#include <HardwareSerial.h> - -#ifndef SERIAL_PLOTTER_BAUD -#define SERIAL_PLOTTER_BAUD 115200 -#endif // SERIAL_PLOTTER_BAUD - -namespace SenseShift::Arduino { - /** - * Component, that prints the current state of the output to the serial port in Arduino's Serial Plotter format - * - * @tparam _Tp the type of the serial port - */ - template<class _Tp> - class SerialPlotter_OutputStates : public ::SenseShift::FreeRTOS::Task<SerialPlotter_OutputStates<_Tp>> { - static_assert( - std::is_base_of<Print, _Tp>::value, - "SerialPlotter_OutputStates only can be used with types, that inherit from Print" - ); - friend class ::SenseShift::FreeRTOS::Task<SerialPlotter_OutputStates<_Tp>>; - - private: - _Tp* serial; - ::SenseShift::Body::Haptics::HapticBody* output; - uint32_t sampleRate; - - void setup(void){}; - void run(void); - - public: - SerialPlotter_OutputStates( - _Tp& serial, - ::SenseShift::Body::Haptics::HapticBody* output, - uint32_t sampleRate, - ::SenseShift::FreeRTOS::TaskConfig taskConfig = { "Serial Plotter", 2048, 1, tskNO_AFFINITY } - ) : - ::SenseShift::FreeRTOS::Task<SerialPlotter_OutputStates<_Tp>>(taskConfig), - serial(&serial), - output(output), - sampleRate(sampleRate){}; - SerialPlotter_OutputStates(_Tp& serial, ::SenseShift::Body::Haptics::HapticBody* output) : - SerialPlotter_OutputStates(serial, output, 100){}; - - void begin() override - { - this->setup(); - ::SenseShift::FreeRTOS::Task<SerialPlotter_OutputStates<_Tp>>::begin(); - }; - }; - - /** - * Specialized setup for HardwareSerial - */ - template<> - inline void SerialPlotter_OutputStates<HardwareSerial>::setup() - { - this->serial->begin(SERIAL_PLOTTER_BAUD); - } - - template class SerialPlotter_OutputStates<HardwareSerial>; -} // namespace SenseShift::Arduino diff --git a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp index 4dabd41b..122b1906 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -5,28 +5,29 @@ #include <Arduino.h> namespace SenseShift::Arduino::Input { - template<bool invert = false> - class AnalogSensor : public ::SenseShift::Input::ISimpleSensor<uint16_t> { - private: - uint8_t pin; + using IAnalogSensor = ::SenseShift::Input::ISimpleSensor<uint16_t>; + + template<bool Invert = false> + class AnalogSensor : public IAnalogSensor { + uint8_t pin_; public: - AnalogSensor(uint8_t pin) : pin(pin) {} + AnalogSensor(const uint8_t pin) : pin_(pin) {} - void init() override { pinMode(this->pin, INPUT); }; + void init() override { pinMode(this->pin_, INPUT); }; - uint16_t getValue() override; + [[nodiscard]] auto getValue() -> uint16_t override; }; template<> - uint16_t AnalogSensor<false>::getValue() + [[nodiscard]] inline auto AnalogSensor<false>::getValue() -> uint16_t { - return analogRead(this->pin); + return analogRead(this->pin_); } template<> - uint16_t AnalogSensor<true>::getValue() + [[nodiscard]] inline auto AnalogSensor<true>::getValue() -> uint16_t { - return ANALOG_MAX - analogRead(this->pin); + return ANALOG_MAX - analogRead(this->pin_); } } // namespace SenseShift::Arduino::Input diff --git a/lib/arduino/senseshift/arduino/input/sensor/binary.hpp b/lib/arduino/senseshift/arduino/input/sensor/binary.hpp new file mode 100644 index 00000000..44783b98 --- /dev/null +++ b/lib/arduino/senseshift/arduino/input/sensor/binary.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include <senseshift/input/sensor.hpp> + +#include <Arduino.h> + +namespace SenseShift::Arduino::Input { + template<bool Invert = false> + class BinarySensor : public IBinarySensor { + uint8_t pin_; + + public: + BinarySensor(const uint8_t pin) : pin_(pin) {} + + void init() override { pinMode(this->pin_, INPUT_PULLUP); }; + + [[nodiscard]] auto getValue() -> bool override; + }; + + template<> + [[nodiscard]] inline auto BinarySensor<false>::getValue() -> bool { + return digitalRead(this->pin_) == LOW; + } + + template<> + [[nodiscard]] inline auto BinarySensor<true>::getValue() -> bool { + return digitalRead(this->pin_) == HIGH; + } +} // namespace SenseShift::Arduino::Input diff --git a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp deleted file mode 100644 index 3cb68b3f..00000000 --- a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include <senseshift/input/sensor.hpp> - -#include <Arduino.h> - -namespace SenseShift::Arduino::Input { - using IDigitalSensor = ::SenseShift::Input::ISimpleSensor<bool>; - - template<bool invert = false> - class DigitalSensor : public IDigitalSensor { - private: - uint8_t pin; - - public: - DigitalSensor(uint8_t pin) : pin(pin) {} - - void init() override { pinMode(this->pin, INPUT_PULLUP); }; - - bool getValue() override; - }; - - template<> - bool DigitalSensor<false>::getValue() - { - return digitalRead(this->pin) == LOW; - } - - template<> - bool DigitalSensor<true>::getValue() - { - return digitalRead(this->pin) == HIGH; - } -} // namespace SenseShift::Arduino::Input diff --git a/lib/arduino/senseshift/arduino/output/actuator/pca9685.hpp b/lib/arduino/senseshift/arduino/output/actuator/pca9685.hpp deleted file mode 100644 index 4d28f92d..00000000 --- a/lib/arduino/senseshift/arduino/output/actuator/pca9685.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include <senseshift/output/actuator.hpp> -#include <senseshift/utility.hpp> - -#include <Adafruit_PWMServoDriver.h> -#include <Arduino.h> -#include <Wire.h> - -namespace SenseShift::Arduino::Output { - class ActuatorPCA9685 : public ::SenseShift::Output::IActuator<std::uint16_t> { - public: - static inline constexpr const std::uint16_t MAX_INTENSITY = 4095; - - ActuatorPCA9685(Adafruit_PWMServoDriver* driver, const std::uint8_t num) : driver(driver), num(num){}; - - void writeOutput(std::uint16_t intensity) override - { - this->driver->setPin(this->num, ::SenseShift::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, 4095)); - } - - private: - Adafruit_PWMServoDriver* driver; - std::uint8_t num; - }; -} // namespace SenseShift::Arduino::Output diff --git a/lib/arduino/senseshift/arduino/output/actuator/pwm.hpp b/lib/arduino/senseshift/arduino/output/actuator/pwm.hpp deleted file mode 100644 index 5f2a595e..00000000 --- a/lib/arduino/senseshift/arduino/output/actuator/pwm.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include <senseshift/output/actuator.hpp> -#include <senseshift/utility.hpp> - -#include <Arduino.h> - -namespace SenseShift::Arduino::Output { - class ActuatorPWM : public ::SenseShift::Output::IActuator<std::uint16_t> { - public: - static inline constexpr const std::uint16_t MAX_INTENSITY = 4095; - - ActuatorPWM(const std::uint8_t pin, const double freq = 60, const std::uint8_t resolution = 12) : - pin(pin), freq(freq), resolution(resolution){}; - - void setup() override - { - this->chan = CHANNELS++; - -#if defined(ESP32) - ledcSetup(this->chan, this->freq, this->resolution); - ledcAttachPin(this->pin, this->chan); -#else - pinMode(this->pin, OUTPUT); -#endif - } - - void writeOutput(std::uint16_t intensity) override - { -#if defined(ESP32) - ledcWrite( - chan, - ::SenseShift::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, (1 << this->resolution) - 1) - ); -#else - // Arduino only supports 8-bit PWM - analogWrite(this->pin, ::SenseShift::simpleMap<std::uint16_t>(intensity, MAX_INTENSITY, (1 << 8) - 1)); -#endif - } - - private: - static inline std::uint8_t CHANNELS = 0; - std::uint8_t pin, chan; - double freq; - std::uint8_t resolution; - }; -}; // namespace SenseShift::Arduino::Output diff --git a/lib/arduino/senseshift/arduino/output/analog.hpp b/lib/arduino/senseshift/arduino/output/analog.hpp new file mode 100644 index 00000000..bcefae41 --- /dev/null +++ b/lib/arduino/senseshift/arduino/output/analog.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include <cstdint> + +#include <Arduino.h> + +#include <senseshift/output/output.hpp> + +namespace SenseShift::Arduino::Output { + /// Arduino analog output + class AnalogOutput : public ::SenseShift::Output::FloatOutput { + 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 { + analogWrite(this->pin_, value * MAX_INTENSITY); + } + + 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 new file mode 100644 index 00000000..66798efd --- /dev/null +++ b/lib/arduino/senseshift/arduino/output/pca9685.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include <cstdint> + +#include <senseshift/output/output.hpp> +#include <senseshift/utility.hpp> + +#include <Adafruit_PWMServoDriver.h> +#include <Arduino.h> +#include <Wire.h> + +namespace SenseShift::Arduino::Output { + class PCA9685Output : public ::SenseShift::Output::FloatOutput { + 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 intensity) override + { + this->driver_->setPin( + this->channel_, + intensity * MAX_INTENSITY + ); + } + + private: + Adafruit_PWMServoDriver* driver_; + std::uint8_t channel_; + }; +} // namespace SenseShift::Arduino::Output diff --git a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp new file mode 100644 index 00000000..a74eba96 --- /dev/null +++ b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include <cstdint> + +#include <esp32-hal-ledc.h> + +#include <senseshift/output/output.hpp> +#include <senseshift/core/logging.hpp> + +namespace SenseShift::Arduino::Output { + static const char *const TAG = "output.ledc"; + + /// Arduino analog output + class LedcOutput : public ::SenseShift::Output::FloatOutput { + 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) {} + + 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){ + LOG_E(TAG, "setup failed (freq = %u, resolution = %u). Try setting different resolution or frequency", this->analog_frequency_, this->analog_resolution_); + return; + } + ledcAttachPin(this->pin_, this->channel_); + } + + [[nodiscard]] auto getMaxValue() const -> std::uint32_t { + return (1 << analog_resolution_) - 1; + } + + void writeState(const float value) override { + const auto duty = static_cast<std::uint32_t>(value * this->getMaxValue()); + LOG_V(TAG, "GPIO %d - Writing %d to Channel %d", this->pin_, duty, this->channel_); + ledcWrite(this->channel_, 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_; + }; +} // namespace SenseShift::Arduino::Output diff --git a/lib/battery/senseshift/battery.hpp b/lib/battery/senseshift/battery.hpp index a89455fb..4de3c867 100644 --- a/lib/battery/senseshift/battery.hpp +++ b/lib/battery/senseshift/battery.hpp @@ -1,10 +1,64 @@ #pragma once -#include <senseshift/events.hpp> - #include <cstdint> +#include <frozen/map.h> + +#include <senseshift/events.hpp> + namespace SenseShift::Battery { + // Source: https://blog.ampow.com/lipo-voltage-chart/ + inline static const auto voltageToPercents_1s = frozen::make_map<float, float>({ + // clang-format off + { 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 }, + // clang-format on + }); + inline static const auto voltageToPercents_2s = frozen::make_map<float, float>({ + // clang-format off + { 8.4, 1.0 }, + { 8.3, 0.95 }, + { 8.22, 0.9 }, + { 8.16, 0.85 }, + { 8.05, 0.8 }, + { 7.97, 0.75 }, + { 7.91, 0.7 }, + { 7.83, 0.65 }, + { 7.75, 0.6 }, + { 7.71, 0.55 }, + { 7.67, 0.5 }, + { 7.63, 0.45 }, + { 7.59, 0.4 }, + { 7.57, 0.35 }, + { 7.53, 0.3 }, + { 7.49, 0.25 }, + { 7.45, 0.2 }, + { 7.41, 0.15 }, + { 7.37, 0.1 }, + { 7.22, 0.05 }, + { 6.55, 0.0 }, + // clang-format on + }); + struct BatteryState { uint8_t level; }; diff --git a/lib/battery/senseshift/battery/sensor.hpp b/lib/battery/senseshift/battery/sensor.hpp index 01b1ae96..ff05f5af 100644 --- a/lib/battery/senseshift/battery/sensor.hpp +++ b/lib/battery/senseshift/battery/sensor.hpp @@ -20,7 +20,7 @@ namespace SenseShift::Battery { public: NaiveBatterySensor(::SenseShift::Input::ISimpleSensor<uint16_t>* sensor) : sensor(sensor){}; - BatteryState getValue() override + [[nodiscard]] auto getValue() -> BatteryState override { return { .level = static_cast<uint8_t>(::SenseShift::simpleMap<uint16_t>(this->sensor->getValue(), 4095, 255)) }; @@ -28,7 +28,7 @@ namespace SenseShift::Battery { void init() override { this->sensor->init(); } private: - ::SenseShift::Input::ISimpleSensor<uint16_t>* sensor; + ISimpleSensor<uint16_t> * sensor; }; class BatterySensor : public ::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState> { @@ -40,7 +40,7 @@ namespace SenseShift::Battery { void tick() override { this->::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>::tick(); - this->eventDispatcher->postEvent(new ::SenseShift::Battery::BatteryLevelEvent(this->value)); + this->eventDispatcher->postEvent(new ::SenseShift::Battery::BatteryLevelEvent(this->getValue())); } private: diff --git a/lib/bhaptics/senseshift/bh/devices.hpp b/lib/bhaptics/senseshift/bh/devices.hpp index f4c168de..7b051c85 100644 --- a/lib/bhaptics/senseshift/bh/devices.hpp +++ b/lib/bhaptics/senseshift/bh/devices.hpp @@ -1,6 +1,11 @@ #pragma once +#include <array> +#include <tuple> + #include <hand_interface.hpp> + +#include <senseshift/body/haptics/plane.hpp> #include <senseshift/body/haptics/body.hpp> #pragma region BH_DEVICE_TACTSUITX40 @@ -18,8 +23,8 @@ // X * Y for front and back #define BH_LAYOUT_TACTSUITX40_SIZE 40 // clang-format off -#define BH_LAYOUT_TACTSUITX40 { \ - /* Front, left part */ \ +#define BH_LAYOUT_TACTSUITX40 { \ + /* Front, left part */ \ /* 0 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ /* 1 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ /* 2 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ @@ -30,8 +35,8 @@ /* 7 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ /* 8 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ /* 9 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ - \ - /* Back */ \ + \ + /* Back */ \ /* 11 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 0) }, \ /* 11 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 0) }, \ /* 12 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 1) }, \ @@ -42,7 +47,7 @@ /* 17 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 3) }, \ /* 18 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(0, 4) }, \ /* 19 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(1, 4) }, \ - \ + \ /* 20 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ /* 21 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ /* 22 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ @@ -53,8 +58,8 @@ /* 27 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 3) }, \ /* 28 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 4) }, \ /* 29 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 4) }, \ - \ - /* Front, again... Now right part */ \ + \ + /* Front, again... Now right part */ \ /* 30 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 0) }, \ /* 31 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(3, 0) }, \ /* 32 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX40_MAKE_POINT(2, 1) }, \ @@ -85,51 +90,51 @@ // X16 suit uses the same packets structure as x40 suit and performs motor grouping in firmware #define BH_LAYOUT_TACTSUITX16_SIZE 40 // clang-format off -#define BH_LAYOUT_TACTSUITX16 { \ - /* Front, left part */ \ +#define BH_LAYOUT_TACTSUITX16 { \ + /* Front, left part */ \ /* 0 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ /* 1 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ /* 2 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ /* 3 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ - \ + \ /* 4 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ /* 5 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ /* 6 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ /* 7 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ /* 8 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ /* 9 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ - \ - /* Back */ \ + \ + /* Back */ \ /* 10 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 0 */ \ /* 11 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 1 */ \ /* 12 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 0) }, /* 4 */ \ /* 13 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 0) }, /* 5 */ \ - \ + \ /* 14 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 8 */ \ /* 15 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 9 */ \ /* 16 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 12 */ \ /* 17 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 13 */ \ /* 18 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(0, 1) }, /* 16 */ \ /* 19 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(1, 1) }, /* 17 */ \ - \ + \ /* 20 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ /* 21 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ /* 22 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ /* 23 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ - \ + \ /* 24 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ /* 25 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ /* 26 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ /* 27 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 15 */ \ /* 28 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 18 */ \ /* 29 */ { Target::ChestBack, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 19 */ \ - \ - /* Front, again... Now right part */ \ + \ + /* Front, again... Now right part */ \ /* 30 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 2 */ \ /* 31 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 3 */ \ /* 32 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 0) }, /* 4 */ \ /* 33 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 0) }, /* 7 */ \ - \ + \ /* 34 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 10 */ \ /* 35 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(3, 1) }, /* 11 */ \ /* 36 */ { Target::ChestFront, BH_LAYOUT_TACTSUITX16_MAKE_POINT(2, 1) }, /* 14 */ \ @@ -290,62 +295,64 @@ namespace SenseShift::BH { using HandSide = ::SenseShift::Body::Hands::HandSide; - using OutputLayout = std::tuple<Target, Position>; + 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 OutputLayout TactGloveLeftLayout[] = BH_LAYOUT_TACTGLOVE_LEFT; - static constexpr const OutputLayout TactGloveRightLayout[] = BH_LAYOUT_TACTGLOVE_RIGHT; + static constexpr const std::array<OutputLayout, BH_LAYOUT_TACTGLOVE_SIZE> TactGloveLeftLayout = { BH_LAYOUT_TACTGLOVE_LEFT }; + static constexpr const std::array<OutputLayout, BH_LAYOUT_TACTGLOVE_SIZE> TactGloveRightLayout = { BH_LAYOUT_TACTGLOVE_RIGHT }; inline void addTactGloveActuators( - HapticBody* hapticBody, + FloatBody* hapticBody, const HandSide side, - VibroPlane::Actuator* const thumbActuator, - VibroPlane::Actuator* const indexActuator, - VibroPlane::Actuator* const middleActuator, - VibroPlane::Actuator* const ringActuator, - VibroPlane::Actuator* const littleActuator, - VibroPlane::Actuator* const wristActuator - ) - { - const OutputLayout(&layout)[6] = (side == HandSide::Left) ? TactGloveLeftLayout : TactGloveRightLayout; - - if (thumbActuator != nullptr) { + 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 VibroPlane({ { std::get<1>(layout[0]), thumbActuator } }) + new FloatPlane({ {std::get<1>(layout[0]), thumb } }) ); } - if (indexActuator != nullptr) { + if (index != nullptr) { hapticBody->addTarget( std::get<0>(layout[1]), - new VibroPlane({ { std::get<1>(layout[1]), indexActuator } }) + new FloatPlane({ {std::get<1>(layout[1]), index } }) ); } - if (middleActuator != nullptr) { + if (middle != nullptr) { hapticBody->addTarget( std::get<0>(layout[2]), - new VibroPlane({ { std::get<1>(layout[2]), middleActuator } }) + new FloatPlane({ {std::get<1>(layout[2]), middle } }) ); } - if (ringActuator != nullptr) { - hapticBody->addTarget(std::get<0>(layout[3]), new VibroPlane({ { std::get<1>(layout[3]), ringActuator } })); + if (ring != nullptr) { + hapticBody->addTarget( + std::get<0>(layout[3]), + new FloatPlane({ {std::get<1>(layout[3]), ring } }) + ); } - if (littleActuator != nullptr) { + if (little != nullptr) { hapticBody->addTarget( std::get<0>(layout[4]), - new VibroPlane({ { std::get<1>(layout[4]), littleActuator } }) + new FloatPlane({ {std::get<1>(layout[4]), little } }) ); } - if (wristActuator != nullptr) { + if (wrist != nullptr) { hapticBody->addTarget( std::get<0>(layout[5]), - new VibroPlane({ { std::get<1>(layout[5]), wristActuator } }) + new FloatPlane({ {std::get<1>(layout[5]), wrist } }) ); } } diff --git a/lib/bhaptics/senseshift/bh/encoding.hpp b/lib/bhaptics/senseshift/bh/encoding.hpp index 273b98c7..3b05a54f 100644 --- a/lib/bhaptics/senseshift/bh/encoding.hpp +++ b/lib/bhaptics/senseshift/bh/encoding.hpp @@ -1,20 +1,24 @@ #pragma once +#include <algorithm> +#include <array> +#include <cstdint> #include <cstring> +#include <string> +#include <tuple> + +#include <senseshift/body/haptics/interface.hpp> #include <senseshift/body/haptics/body.hpp> namespace SenseShift::BH { class Decoder { public: using VibroEffectData = ::SenseShift::Body::Haptics::VibroEffectData; - using EffectData = ::SenseShift::Body::Haptics::EffectData; using Effect = ::SenseShift::Body::Haptics::Effect; using Target = ::SenseShift::Body::Haptics::Target; using Position = ::SenseShift::Body::Haptics::Position; - using HapticBody = ::SenseShift::Body::Haptics::HapticBody; - using OutputLayout = std::tuple<Target, Position>; static constexpr size_t VEST_LAYOUT_SIZE = 40; @@ -22,29 +26,33 @@ namespace SenseShift::BH { template<size_t N> static void applyPlain( - HapticBody* output, const uint8_t (&value)[N], const OutputLayout (&layout)[N], const Effect effect - ) - { + FloatBody* output, + const std::array<std::uint8_t, N>& value, + const std::array<OutputLayout, N>& layout, + const Effect effect + ) { for (size_t i = 0; i < N; i++) { const auto [target, position] = layout[i]; - const uint8_t byte = value[i]; + const std::uint8_t byte = value[i]; - output->effect({ - .effect = effect, - .target = target, - .position = position, - .data = effectDataFromByte(effect, byte), - }); + output->effect( + target, + position, + static_cast<FloatBody::Plane::Value>(effectDataFromByte(byte)) + ); } } template<size_t N> - static void - applyPlain(HapticBody* output, std::string& value, const OutputLayout (&layout)[N], const Effect effect) - { - std::uint8_t buf[N]; + static void applyPlain( + FloatBody* output, + std::string& value, + const std::array<OutputLayout, N>& layout, + const Effect effect + ) { + std::array<std::uint8_t, N> buf{}; std::size_t copyLength = std::min(value.size(), sizeof(buf)); - std::memcpy(buf, value.c_str(), copyLength); + std::memcpy(buf.data(), value.c_str(), copyLength); applyPlain(output, buf, layout, effect); } @@ -54,34 +62,35 @@ namespace SenseShift::BH { */ template<size_t N> static void applyPlain( - HapticBody* output, - const uint8_t (&value)[N], - const Position (&layout)[N], + FloatBody* output, + const std::array<std::uint8_t, N>& value, + const std::array<Position, N>& 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({ - .effect = effect, - .target = target, - .position = position, - .data = effectDataFromByte(effect, byte), - }); + output->effect( + target, + position, + static_cast<FloatBody::Plane::Value>(effectDataFromByte(byte)) + ); } } template<size_t N> static void applyPlain( - HapticBody* output, std::string& value, const Position (&layout)[N], const Effect effect, const Target target - ) - { - std::uint8_t buf[N]; + FloatBody* output, + std::string& value, + const std::array<Position, N>& layout, + const Effect effect, + const Target target + ) { + std::array<std::uint8_t, N> buf{}; std::size_t copyLength = std::min(value.size(), sizeof(buf)); - std::memcpy(buf, value.c_str(), copyLength); + std::memcpy(buf.data(), value.c_str(), copyLength); applyPlain(output, buf, layout, effect, target); } @@ -90,32 +99,35 @@ namespace SenseShift::BH { * Apply vest-encoded data to the output. */ static void applyVest( - HapticBody* output, const uint8_t (&value)[VEST_PAYLOAD_SIZE], const OutputLayout (&layout)[VEST_LAYOUT_SIZE] - ) - { + FloatBody* output, + const std::array<uint8_t, VEST_PAYLOAD_SIZE>& value, + const std::array<OutputLayout, VEST_LAYOUT_SIZE>& layout + ) { for (size_t i = 0; i < VEST_PAYLOAD_SIZE; i++) { - uint8_t byte = value[i]; - uint actIndex = i * 2; - output->effect({ - .effect = Effect::Vibro, - .target = std::get<0>(layout[actIndex]), - .position = std::get<1>(layout[actIndex]), - .data = effectDataFromByte(Effect::Vibro, ((byte >> 4) & 0xf), 15), - }); - output->effect({ - .effect = Effect::Vibro, - .target = std::get<0>(layout[actIndex + 1]), - .position = std::get<1>(layout[actIndex + 1]), - .data = effectDataFromByte(Effect::Vibro, (byte & 0xf), 15), - }); + 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<FloatBody::Plane::Value>(effectDataFromByte(((byte >> 4) & 0xf), 15)) + ); + output->effect( + std::get<0>(layout[actIndex + 1]), + std::get<1>(layout[actIndex + 1]), + static_cast<FloatBody::Plane::Value>(effectDataFromByte((byte & 0xf), 15).getIntensity()) + ); } } - static void applyVest(HapticBody* output, std::string& value, const OutputLayout (&layout)[VEST_LAYOUT_SIZE]) - { - std::uint8_t buf[VEST_PAYLOAD_SIZE]; - std::size_t copyLength = std::min(value.size(), sizeof(buf)); - std::memcpy(buf, value.c_str(), copyLength); + static void applyVest( + FloatBody* output, + std::string& value, + const std::array<OutputLayout, VEST_LAYOUT_SIZE>& layout + ) { + std::array<std::uint8_t, VEST_PAYLOAD_SIZE> buf{}; + const size_t copyLength = std::min(value.size(), sizeof(buf)); + std::memcpy(buf.data(), value.c_str(), copyLength); applyVest(output, buf, layout); } @@ -125,18 +137,17 @@ namespace SenseShift::BH { */ template<size_t N> static void applyVestGrouped( - HapticBody* output, - const uint8_t (&value)[VEST_PAYLOAD_SIZE], - const OutputLayout (&layout)[VEST_LAYOUT_SIZE], - const uint8_t (&layoutGroups)[N] - ) - { - uint8_t result[VEST_LAYOUT_SIZE]; + FloatBody* output, + const std::array<std::uint8_t, VEST_PAYLOAD_SIZE>& value, + const std::array<OutputLayout, VEST_LAYOUT_SIZE>& layout, + const std::array<std::uint8_t, N>& layoutGroups + ) { + std::array<std::uint8_t, VEST_LAYOUT_SIZE> result{}; // Unpack values for (auto i = 0; i < VEST_PAYLOAD_SIZE; i++) { - uint8_t byte = value[i]; - uint actIndex = i * 2; + const std::uint8_t byte = value[i]; + const size_t actIndex = i * 2; result[actIndex] = (byte >> 4) & 0xf; result[actIndex + 1] = (byte & 0xf); @@ -164,51 +175,39 @@ namespace SenseShift::BH { for (uint8_t i = 0; i < VEST_LAYOUT_SIZE; i++) { // take only meaningful values - if (!::SenseShift::contains(layoutGroups, VEST_LAYOUT_SIZE, i)) { + 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({ - .effect = Effect::Vibro, - .target = target, - .position = position, - .data = effectDataFromByte(Effect::Vibro, result[i], 15), - }); + output->effect( + target, + position, + static_cast<FloatBody::Plane::Value>(effectDataFromByte(result[i], 15)) + ); } } template<size_t N> static void applyVestGrouped( - HapticBody* output, + FloatBody* output, std::string& value, - const OutputLayout (&layout)[VEST_LAYOUT_SIZE], - const uint8_t (&layoutGroups)[N] - ) - { - std::uint8_t buf[VEST_PAYLOAD_SIZE]; - std::size_t copyLength = std::min(value.size(), sizeof(buf)); - std::memcpy(buf, value.c_str(), copyLength); + const std::array<OutputLayout, VEST_LAYOUT_SIZE>& layout, + const std::array<std::uint8_t, N>& layoutGroups + ) { + std::array<std::uint8_t, VEST_PAYLOAD_SIZE> 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 const EffectData - effectDataFromByte(const Effect effect, const uint8_t byte, const uint8_t maxValue = 100) + static auto effectDataFromByte(const uint8_t byte, const uint8_t maxValue = 100) -> VibroEffectData { - switch (effect) { - case Effect::Vibro: - return VibroEffectData(::SenseShift::simpleMap<VibroEffectData::Intensity>( - byte, - maxValue, - VibroEffectData::INTENSITY_MAX - )); - default: - throw std::runtime_error("Unknown effect"); - } + return VibroEffectData(byte / maxValue); } }; } // namespace SenseShift::BH diff --git a/lib/core/senseshift/core/component.hpp b/lib/core/senseshift/core/component.hpp new file mode 100644 index 00000000..8fae06dd --- /dev/null +++ b/lib/core/senseshift/core/component.hpp @@ -0,0 +1,33 @@ +#pragma once + +namespace SenseShift { + class IInitializable { + public: + virtual void init() = 0; + }; + + class ITickable { + public: + virtual void tick() = 0; + }; + + class Component : public IInitializable, public 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/core/senseshift/core/helpers.hpp b/lib/core/senseshift/core/helpers.hpp new file mode 100644 index 00000000..8a68a2fb --- /dev/null +++ b/lib/core/senseshift/core/helpers.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include <type_traits> + +namespace SenseShift { + /// @name Mathematics + /// @{ + + /// Linearly interpolate between \p start and \p end by \p completion (between 0 and 1). + constexpr auto lerp(const float completion, const float start, const float end) -> float + { + 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<typename Tp, typename Up> + constexpr auto remap(Up value, Up min, Up max, Tp min_out, Tp max_out) -> Tp + { + static_assert(std::is_arithmetic_v<Up>, "Type must be arithmetic"); + static_assert(std::is_arithmetic_v<Tp>, "Type must be arithmetic"); + + 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<typename Tp, typename Up> + constexpr auto remap_simple(Up value, Up max, Tp max_out) noexcept -> Tp + { + static_assert(std::is_arithmetic_v<Up>, "Type must be arithmetic"); + static_assert(std::is_arithmetic_v<Tp>, "Type must be arithmetic"); + + return value * max_out / max; + } + + /// @} +} // namespace SenseShift \ No newline at end of file diff --git a/lib/core/senseshift/core/logging.hpp b/lib/core/senseshift/core/logging.hpp new file mode 100644 index 00000000..647965ef --- /dev/null +++ b/lib/core/senseshift/core/logging.hpp @@ -0,0 +1,40 @@ +#pragma once + +#if defined(ESP32) + +#include <esp32-hal-log.h> +#define LOG_E(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__) +#define LOG_W(tag, format, ...) ESP_LOGW(tag, format, ##__VA_ARGS__) +#define LOG_I(tag, format, ...) ESP_LOGI(tag, format, ##__VA_ARGS__) +#define LOG_D(tag, format, ...) ESP_LOGD(tag, format, ##__VA_ARGS__) +#define LOG_V(tag, format, ...) ESP_LOGV(tag, format, ##__VA_ARGS__) + +#elif defined(UNITY_INCLUDE_PRINT_FORMATTED) + +#define log_e(...) TEST_PRINTF(__VA_ARGS__) +#define log_w(...) TEST_PRINTF(__VA_ARGS__) +#define log_i(...) TEST_PRINTF(__VA_ARGS__) +#define log_d(...) TEST_PRINTF(__VA_ARGS__) +#define log_v(...) TEST_PRINTF(__VA_ARGS__) + +#define LOG_E(tag, format, ...) log_e("[%s] " format, tag, ##__VA_ARGS__) +#define LOG_W(tag, format, ...) log_w("[%s] " format, tag, ##__VA_ARGS__) +#define LOG_I(tag, format, ...) log_i("[%s] " format, tag, ##__VA_ARGS__) +#define LOG_D(tag, format, ...) log_d("[%s] " format, tag, ##__VA_ARGS__) +#define LOG_V(tag, format, ...) log_v("[%s] " format, tag, ##__VA_ARGS__) + +#else + +#define log_e(...) +#define log_w(...) +#define log_i(...) +#define log_d(...) +#define log_v(...) + +#define LOG_E(tag, format, ...) +#define LOG_W(tag, format, ...) +#define LOG_I(tag, format, ...) +#define LOG_D(tag, format, ...) +#define LOG_V(tag, format, ...) + +#endif diff --git a/lib/core/senseshift/core/macros.hpp b/lib/core/senseshift/core/macros.hpp new file mode 100644 index 00000000..1087e76f --- /dev/null +++ b/lib/core/senseshift/core/macros.hpp @@ -0,0 +1,4 @@ +#pragma once + +// Helper macro to define a version code, whose value can be compared against other version codes. +#define VERSION_CODE(major, minor, patch) ((major) << 16 | (minor) << 8 | (patch)) \ No newline at end of file diff --git a/lib/core/senseshift/interface.hpp b/lib/core/senseshift/interface.hpp deleted file mode 100644 index af428cc6..00000000 --- a/lib/core/senseshift/interface.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -namespace SenseShift { - struct IInitializable { - virtual void init() = 0; - }; - - struct ITickable { - virtual void tick() = 0; - }; -} // namespace SenseShift diff --git a/lib/core/senseshift/logging.hpp b/lib/core/senseshift/logging.hpp deleted file mode 100644 index 9cf54f37..00000000 --- a/lib/core/senseshift/logging.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#if defined(ESP32) - -#include <esp32-hal-log.h> - -#elif defined(UNITY_INCLUDE_PRINT_FORMATTED) - -#define log_e(...) TEST_PRINTF(__VA_ARGS__) -#define log_w(...) TEST_PRINTF(__VA_ARGS__) -#define log_i(...) TEST_PRINTF(__VA_ARGS__) -#define log_d(...) TEST_PRINTF(__VA_ARGS__) -#define log_t(...) TEST_PRINTF(__VA_ARGS__) - -#else - -#define log_e(...) -#define log_w(...) -#define log_i(...) -#define log_d(...) -#define log_t(...) - -#endif diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index d41355ec..d06415ea 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -1,6 +1,6 @@ #pragma once -#include <senseshift/logging.hpp> +#include <senseshift/core/logging.hpp> extern "C" void delay(uint32_t ms); diff --git a/lib/haptics/senseshift/body/haptics/body.cpp b/lib/haptics/senseshift/body/haptics/body.cpp index edd3ee6e..e60eb210 100644 --- a/lib/haptics/senseshift/body/haptics/body.cpp +++ b/lib/haptics/senseshift/body/haptics/body.cpp @@ -1,33 +1,23 @@ #include "senseshift/body/haptics/body.hpp" +#include "senseshift/body/haptics/interface.hpp" -#include <senseshift/logging.hpp> +#include <senseshift/output/output.hpp> +#include <senseshift/core/logging.hpp> namespace SenseShift::Body::Haptics { - void HapticBody::setup() - { - for (auto& [target, plane] : this->vibroTargets) { - plane->setup(); - } - } + static const char *const TAG = "haptic.body"; - void HapticBody::effect(const EffectRequest& effect) + template<typename Tp, typename Ta> + void OutputBody<Tp, Ta>::effect(const Target& target, const Position& pos, const typename Plane::Value& val) { - if (effect.effect == Effect::Vibro && std::holds_alternative<VibroEffectData>(effect.data)) { - auto it = this->vibroTargets.find(effect.target); - if (it == this->vibroTargets.end()) { - log_w("No target found for effect: %d", effect.target); - return; - } - - it->second->effect(effect.position, std::get<VibroEffectData>(effect.data)); - } else { - log_w("Non-supported effect type: %d", effect.effect); + auto find = this->targets_.find(target); + if (find == this->targets_.end()) { + LOG_W(TAG, "No target found for effect: %d", target); + return; } - } - void HapticBody::addTarget(const Target target, VibroPlane* plane) - { - this->vibroTargets[target] = plane; - this->allTargets.insert({ target, plane }); + find->second->effect(pos, val); } + + template class OutputBody<Position::Value, Output::FloatOutput::ValueType>; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/body.hpp b/lib/haptics/senseshift/body/haptics/body.hpp index b0c9068e..386866a4 100644 --- a/lib/haptics/senseshift/body/haptics/body.hpp +++ b/lib/haptics/senseshift/body/haptics/body.hpp @@ -3,29 +3,42 @@ #include "senseshift/body/haptics/interface.hpp" #include "senseshift/body/haptics/plane.hpp" -#include <senseshift/utility.hpp> - #include <map> +#include <senseshift/output/output.hpp> + namespace SenseShift::Body::Haptics { - class HapticBody { + /// Output body, contains all the output planes. + /// + /// \tparam Tc The type of the coordinate. + /// \tparam To The type of the output value. + template<typename Tc, typename To> + class OutputBody { public: - using AuctiativePlane = std::variant<VibroPlane*>; - using PlaneTargetMap = std::multimap<Target, AuctiativePlane>; - using VibroTargetMap = std::map<Target, VibroPlane*>; + /// The type of the output plane for the given target. + using Plane = OutputPlane<Tc, To>; + /// The type of the target to output plane map (e.g. Chest -> OutputPlane). + using TargetPlaneMap = std::map<Target, Plane*>; - HapticBody(){}; + OutputBody() = default; - void setup(); + void setup() { + for (auto& [target, plane] : this->targets_) { + plane->setup(); + } + } - void effect(const EffectRequest&); + void addTarget(Target target, Plane* plane) { + this->targets_[target] = plane; + } - void addTarget(const Target, VibroPlane* plane); + void effect(const Target& target, const Position& pos, const typename Plane::Value& val); - [[nodiscard]] const PlaneTargetMap* getTargets() const { return &allTargets; } + [[nodiscard]] auto getTargets() const -> const TargetPlaneMap* { return &targets_; } private: - PlaneTargetMap allTargets{}; - VibroTargetMap vibroTargets{}; + TargetPlaneMap targets_{}; }; + + using FloatBody = OutputBody<Position::Value, Output::FloatOutput::ValueType>; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/interface.hpp b/lib/haptics/senseshift/body/haptics/interface.hpp index c4084531..89f14cff 100644 --- a/lib/haptics/senseshift/body/haptics/interface.hpp +++ b/lib/haptics/senseshift/body/haptics/interface.hpp @@ -6,9 +6,9 @@ #include <senseshift/math/point2.hpp> namespace SenseShift::Body::Haptics { - using EffectIntex = std::uint8_t; - static constexpr EffectIntex EFFECT_INVALID = 0xFF; - enum class Effect : EffectIntex { + using EffectIndex = std::uint8_t; + static constexpr EffectIndex EFFECT_INVALID = 0xFF; + enum class Effect : EffectIndex { Invalid = EFFECT_INVALID, Vibro = 0x00, // TODO: thermal, etc. @@ -47,31 +47,36 @@ namespace SenseShift::Body::Haptics { }; using Coordinate = std::uint8_t; - using Position = ::SenseShift::Math::Point2<Coordinate>; + using Position = Math::Point2<Coordinate>; - // Vibration intensity. - struct VibroEffectData { - using Intensity = std::uint16_t; - static constexpr Intensity INTENSITY_MIN = 0; - static constexpr Intensity INTENSITY_MAX = 4095; + // Vibration intensity_. + class VibroEffectData { + public: + using Intensity = float; - Intensity intensity = 0; + static constexpr Intensity INTENSITY_MIN = 0.0F; + static constexpr Intensity INTENSITY_MAX = 1.0F; - inline constexpr VibroEffectData() = default; - inline constexpr VibroEffectData(const Intensity intensity) : intensity(intensity) {} - inline constexpr VibroEffectData(const VibroEffectData& other) = default; + constexpr VibroEffectData() = default; + constexpr explicit VibroEffectData(const Intensity intensity) : intensity_(intensity) {} + constexpr VibroEffectData(const VibroEffectData& other) = default; - inline constexpr operator std::uint16_t() const { return intensity; } + constexpr inline explicit operator float() const { return this->intensity_; } + + [[nodiscard]] constexpr inline auto getIntensity() const -> Intensity { return intensity_; }; + + private: + Intensity intensity_ = 0; }; // TODO: thermal, etc. - using EffectData = std::variant<VibroEffectData>; struct EffectRequest { Effect effect = Effect::Invalid; Target target = Target::Invalid; Position position = Position(0, 0); + 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 ab11c81b..bfbd4f33 100644 --- a/lib/haptics/senseshift/body/haptics/plane.cpp +++ b/lib/haptics/senseshift/body/haptics/plane.cpp @@ -1,78 +1,82 @@ #include "senseshift/body/haptics/plane.hpp" +#include "senseshift/body/haptics/interface.hpp" #include <algorithm> -#include <cmath> -#include <senseshift/logging.hpp> +#include <map> + +#include <senseshift/output/output.hpp> +#include <senseshift/core/logging.hpp> namespace SenseShift::Body::Haptics { - template<typename _Tp, typename _Ta> - void ActuativePlane<_Tp, _Ta>::setActuators(const ActuatorMap& actuators) + static const char *const TAG = "haptic.plane"; + + template<typename Tc, typename To> + void OutputPlane<Tc, To>::setActuators(const ActuatorMap& actuators) { - this->actuators.clear(); + this->actuators_.clear(); for (const auto& [point, actuator] : actuators) { - this->actuators[point] = actuator; + this->actuators_[point] = actuator; } - this->points.clear(); + this->points_.clear(); for (const auto& [point, _] : actuators) { - this->points.insert(point); + this->points_.insert(point); } - this->states.clear(); + this->states_.clear(); for (const auto& [point, _] : actuators) { - this->states[point] = 0; + this->states_[point] = static_cast<Value>(0); } } - template<typename _Tp, typename _Ta> - void ActuativePlane<_Tp, _Ta>::setup() + template<typename Tc, typename To> + void OutputPlane<Tc, To>::setup() { - for (const auto& [point, actuator] : this->actuators) { - actuator->setup(); + for (const auto& [point, actuator] : this->actuators_) { + actuator->init(); } } - template<typename _Tp, typename _Ta> - void ActuativePlane<_Tp, _Ta>::effect(const Position& pos, const Value& val) + template<typename Tc, typename To> + void OutputPlane<Tc, To>::effect(const Position& pos, const Value& val) { - auto it = this->actuators.find(pos); - if (it == this->actuators.end()) { - log_w("No actuator for point (%u, %u)", pos.x, pos.y); + 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; } - it->second->writeOutput(val); - this->states[pos] = val; + find->second->writeState(val); + this->states_[pos] = val; } - template<typename _Tp, typename _Ta> - void ActuativePlane_Closest<_Tp, _Ta>::effect(const Position& pos, const Value& val) + template<typename Tc, typename To> + void OutputPlane_Closest<Tc, To>::effect(const Position& pos, const Value& val) { auto& closest = this->findClosestPoint(*this->getAvailablePoints(), pos); - ActuativePlane<_Tp, _Ta>::effect(closest, val); + OutputPlane<Tc, To>::effect(closest, val); } - template<typename _Tp, typename _Ta> - const Position& - ActuativePlane_Closest<_Tp, _Ta>::findClosestPoint(const PositionSet& pts, const Position& target) const + template<typename Tc, typename To> + [[nodiscard]] auto OutputPlane_Closest<Tc, To>::findClosestPoint(const PositionSet& pts, const Position& target) -> const Position& { // check if exact point exists - auto it = pts.find(target); - if (it != pts.end()) { - return *it; + const auto find = pts.find(target); + if (find != pts.end()) { + return *find; } - // find closest point by square distance - std::multimap<float, Position> mp = {}; - for (const auto& _p : pts) { - mp.insert({ (target - _p), _p }); + // find the closest point by square distance + std::multimap<float, Position> distance_map = {}; + for (const auto& point : pts) { + distance_map.insert({(target - point), point }); } - auto nearest = std::min_element(mp.begin(), mp.end()); + const auto nearest = std::min_element(distance_map.begin(), distance_map.end()); return nearest->second; } - template class ActuativePlane<VibroEffectData, ::SenseShift::Output::IActuator<VibroEffectData::Intensity>>; - template class ActuativePlane_Closest<VibroEffectData, ::SenseShift::Output::IActuator<VibroEffectData::Intensity>>; + template class OutputPlane<Position::Value, Output::FloatOutput::ValueType>; + template class OutputPlane_Closest<Position::Value, Output::FloatOutput::ValueType>; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/plane.hpp b/lib/haptics/senseshift/body/haptics/plane.hpp index b8ac0727..eeea313b 100644 --- a/lib/haptics/senseshift/body/haptics/plane.hpp +++ b/lib/haptics/senseshift/body/haptics/plane.hpp @@ -2,96 +2,101 @@ #include "senseshift/body/haptics/interface.hpp" -#include <senseshift/output/actuator.hpp> -#include <senseshift/utility.hpp> - -#include <list> +#include <cstddef> #include <map> #include <set> #include <vector> -namespace SenseShift::Body::Haptics { - using PositionSet = std::set<Position>; - - /** - * Output "plane" (e.g. Chest, Palm, Finger, etc.) - * - * @tparam _Tp The type of the output value. - */ - template<typename _Tp, typename _Ta> - class ActuativePlane { - static_assert(std::is_same<_Tp, VibroEffectData>()); +#include <senseshift/output/output.hpp> +#include <senseshift/utility.hpp> +#include <senseshift/math/point2.hpp> +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<typename Tc, typename To> + class OutputPlane { public: - using Value = _Tp; - using Actuator = _Ta; + /// The type of the coordinate (e.g. std::uint8_t) for the plane. + using Coordinate = Tc; + /// The type of the position (e.g. Point2<std::uint8_t>) for the plane. + using Position = Math::Point2<Coordinate>; + using PositionSet = std::set<Position>; + + /// 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::Output<Value>; using ActuatorMap = std::map<Position, Actuator*>; using PositionStateMap = std::map<Position, Value>; - ActuativePlane() = default; + OutputPlane() = default; - ActuativePlane(const ActuatorMap& actuators) { this->setActuators(actuators); } + explicit OutputPlane(const ActuatorMap& actuators) { this->setActuators(actuators); } void setup(); virtual void effect(const Position&, const Value&); - [[nodiscard]] const PositionSet* getAvailablePoints() const { return &points; } - [[nodiscard]] const PositionStateMap* getActuatorStates() const { return &states; } + [[nodiscard]] auto getAvailablePoints() const -> const PositionSet* { return &points_; } + [[nodiscard]] auto getActuatorStates() const -> const PositionStateMap* { return &states_; } - private: - PositionSet points; - ActuatorMap actuators{}; - PositionStateMap states{}; + protected: + void setActuators(const ActuatorMap& actuators); - void setActuators(const ActuatorMap&); + private: + PositionSet points_; + ActuatorMap actuators_{}; + PositionStateMap states_{}; }; - using VibroPlane = ActuativePlane<VibroEffectData, ::SenseShift::Output::IActuator<VibroEffectData::Intensity>>; - - /** - * Output plane, finds the closest actuator for the given point. - * @deprecated We should guarantee on the driver level, that the actuator is always exists - */ - template<typename _Tp, typename _Ta> - class ActuativePlane_Closest : public ActuativePlane<_Tp, _Ta> { - public: - using Value = _Tp; - - ActuativePlane_Closest(const typename ActuativePlane<_Tp, _Ta>::ActuatorMap& actuators) : - ActuativePlane<_Tp, _Ta>(actuators) + /// 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<typename Tc, typename To> + class OutputPlane_Closest : public OutputPlane<Tc, To> { + public: + using Value = To; + using PositionSet = typename OutputPlane<Tc, To>::PositionSet; + + explicit OutputPlane_Closest(const typename OutputPlane<Tc, To>::ActuatorMap& actuators) : OutputPlane<Tc, To>(actuators) { } void effect(const Position&, const Value&) override; - private: - [[nodiscard]] const Position& findClosestPoint(const PositionSet&, const Position&) const; + private: + [[nodiscard]] static auto findClosestPoint(const PositionSet&, const Position&) -> const Position&; }; - using VibroPlane_Closest = - ActuativePlane_Closest<VibroEffectData, ::SenseShift::Output::IActuator<VibroEffectData::Intensity>>; + using FloatPlane = OutputPlane<Position::Value, Output::FloatOutput::ValueType>; + using FloatPlane_Closest = OutputPlane_Closest<Position::Value, Output::FloatOutput::ValueType>; // TODO: configurable margin class PlaneMapper_Margin { public: - template<typename _Tp> - [[nodiscard]] static constexpr inline std::map<Position, _Tp*> - mapMatrixCoordinates(std::vector<std::vector<_Tp*>> map2d) + + /// Maps a 2D matrix into a 1D (coord, object) map. + template<typename Tp> + [[nodiscard]] static constexpr auto mapMatrixCoordinates(std::vector<std::vector<Tp*>> map2d) -> std::map<Position, Tp*> { - std::map<Position, _Tp*> points{}; + std::map<Position, Tp*> points{}; - size_t y_size = map2d.size(); - size_t y_max = y_size - 1; + 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 x_size = row.size(); - size_t x_max = x_size - 1; + 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 = PlaneMapper_Margin::mapPoint<Position::Value>(x, y, x_max, y_max); + Position coord = mapPoint<Position::Value>(x, y, x_max, y_max); points[coord] = wr; } @@ -100,19 +105,16 @@ namespace SenseShift::Body::Haptics { return points; } - /** - * Re-maps a point index to output coordinate. - * @tparam _Tp The type of the point index. - */ - template<typename _Tp> - [[nodiscard]] static constexpr inline ::SenseShift::Math::Point2<_Tp> - mapPoint(_Tp x, _Tp y, _Tp x_max, _Tp y_max) + /// Re-maps a point index to output coordinate. + /// \tparam Tp The type of the point index. + template<typename Tp> + [[nodiscard]] static constexpr auto mapPoint(Tp x, Tp y, Tp x_max, Tp y_max) -> Math::Point2<Tp> { - using Point = ::SenseShift::Math::Point2<_Tp>; + using LocalPointType = Math::Point2<Tp>; - return Point( - ::SenseShift::accurateMap<_Tp>(x + 1, 0, x_max + 2, Point::MIN, Point::MAX), - ::SenseShift::accurateMap<_Tp>(y + 1, 0, y_max + 2, Point::MIN, Point::MAX) + return LocalPointType( + ::SenseShift::remap<Tp, Tp>(x + 1, 0, x_max + 2, LocalPointType::MIN, LocalPointType::MAX), + ::SenseShift::remap<Tp, Tp>(y + 1, 0, y_max + 2, LocalPointType::MIN, LocalPointType::MAX) ); } }; diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index 2520cd76..22b8a116 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -3,8 +3,7 @@ #include <type_traits> #include <senseshift/calibration.hpp> -#include <senseshift/interface.hpp> -#include <senseshift/logging.hpp> +#include <senseshift/core/component.hpp> #if defined(__AVR__) #define ANALOG_MAX 1023 @@ -18,145 +17,154 @@ #endif namespace SenseShift::Input { - /** - * Abstract hardware sensor (e.g. potentiometer, flex sensor, etc.) - * @tparam _Tp Type of the sensor value - */ - template<typename _Tp> - struct ISimpleSensor : public virtual IInitializable { - using ValueType = _Tp; - - /** - * Get the current sensor value - */ - virtual ValueType getValue() = 0; + /// Abstract hardware sensor (e.g. potentiometer, flex sensor, etc.) + /// \tparam Tp Type of the sensor value + template<typename Tp> + class ISimpleSensor : virtual public IInitializable { + public: + using ValueType = Tp; + + /// Get the current sensor value + [[nodiscard]] virtual auto getValue() -> ValueType = 0; }; - template<typename _Tp> - struct ISensor : public virtual ISimpleSensor<_Tp>, ITickable {}; + using IBinarySensor = ISimpleSensor<bool>; - /** - * Memoized sensor decorator - * @tparam _Tp Type of the sensor value - */ - template<typename _Tp> - class MemoizedSensor : public ISensor<_Tp> { - protected: - ISimpleSensor<_Tp>* sensor; - _Tp value; + template<typename Tp> + class ISensor : virtual ISimpleSensor<Tp>, ITickable {}; + /// Memoized sensor decorator. Stores the last read value and returns it on subsequent calls + /// \tparam Tp Type of the sensor value + template<typename Tp> + class MemoizedSensor : public ISensor<Tp> { public: - /** - * @param sensor Sensor to be decorated - */ - MemoizedSensor(ISimpleSensor<_Tp>* sensor) : sensor(sensor){}; + using ValueType = Tp; + + /// \param sensor Sensor to be decorated + explicit MemoizedSensor(ISimpleSensor<ValueType>* sensor) : sensor_(sensor){} /** * Setup the sensor hardware */ - void init() override { this->sensor->init(); }; + void init() override { this->sensor_->init(); } /** * Read actual value from the hardware and memoize it */ - void tick() override { this->value = this->sensor->getValue(); }; + void tick() override { this->value_ = this->sensor_->getValue(); } /** * Get the current memoized value */ - _Tp getValue() override { return this->value; }; + [[nodiscard]] auto getValue() -> ValueType override { return this->value_; } + + private: + ISimpleSensor<ValueType>* sensor_; + ValueType value_; }; - template<typename _Tp> - class ICalibratedSimpleSensor : public ISimpleSensor<_Tp>, public Calibration::ICalibrated {}; + template<typename Tp> + class ICalibratedSimpleSensor : public ISimpleSensor<Tp>, public Calibration::ICalibrated {}; - /** - * Calibrated sensor decorator - * - * @tparam _Tp Type of the sensor value - */ - template<typename _Tp> - class CalibratedSimpleSensor : public ICalibratedSimpleSensor<_Tp> { + /// Calibrated sensor decorator + /// \tparam Tp Type of the sensor value + template<typename Tp> + class CalibratedSimpleSensor : public ICalibratedSimpleSensor<Tp> { public: - /** - * @param sensor Sensor to be decorated - * @param calibrator ICalibrator algorithm to be used - */ - CalibratedSimpleSensor(ISimpleSensor<_Tp>* sensor, Calibration::ICalibrator<_Tp>* calibrator) : - sensor(sensor), calibrator(calibrator){}; + using ValueType = Tp; - void init() override { this->sensor->init(); }; - _Tp getValue() override { return this->getCalibratedValue(); }; + /// \param sensor Sensor to be decorated + /// \param calibrator ICalibrator algorithm to be used + CalibratedSimpleSensor(ISimpleSensor<ValueType>* sensor, Calibration::ICalibrator<ValueType>* calibrator) : + sensor_(sensor), calibrator_(calibrator){}; - void resetCalibration() override { this->calibrator->reset(); }; - void enableCalibration() override { calibrating = true; } - void disableCalibration() override { calibrating = false; } + void init() override { this->sensor_->init(); }; + [[nodiscard]] auto getValue() -> ValueType override { return this->getCalibratedValue(); }; - protected: - ISimpleSensor<_Tp>* sensor; - Calibration::ICalibrator<_Tp>* calibrator; - bool calibrating = false; + void resetCalibration() override { this->calibrator_->reset(); }; + void enableCalibration() override { is_calibrating_ = true; } + void disableCalibration() override { is_calibrating_ = false; } - _Tp getCalibratedValue() + protected: + [[nodiscard]] auto getCalibratedValue() -> ValueType { - auto value = this->sensor->getValue(); + auto value = this->sensor_->getValue(); - if (this->calibrating) { - this->calibrator->update(value); + if (this->is_calibrating_) { + this->calibrator_->update(value); } - return this->calibrator->calibrate(value); + return this->calibrator_->calibrate(value); } + + private: + ISimpleSensor<ValueType>* sensor_; + Calibration::ICalibrator<ValueType>* calibrator_; + bool is_calibrating_ = false; }; - template<typename _Tp> - class AverageSensor : public ISimpleSensor<_Tp> { - static_assert(std::is_arithmetic<_Tp>::value, "AverageSensor only supports arithmetic types"); + /// A sensor that returns the average value of N samples. + /// \tparam Tp Type of the sensor value + template<typename Tp> + class AverageSensor : public ISimpleSensor<Tp> { + static_assert(std::is_arithmetic_v<Tp>, "AverageSensor only supports arithmetic types"); public: - AverageSensor(ISimpleSensor<_Tp>* sensor, size_t samples) : sensor(sensor), samples(samples) {} + using ValueType = Tp; + + /// \param sensor Sensor to be decorated + /// \param samples Number of samples to be used + AverageSensor(ISimpleSensor<ValueType>* sensor, const size_t samples) : sensor_(sensor), samples_(samples) {} - void init() override { this->sensor->init(); }; + void init() override { this->sensor_->init(); }; - _Tp getValue() override + [[nodiscard]] auto getValue() const -> ValueType override { // TODO: another type for sum? double sum = 0; - for (size_t i = 0; i < this->samples; i++) { - sum += this->sensor->getValue(); + for (size_t i = 0; i < this->samples_; i++) { + sum += this->sensor_->getValue(); } - return sum / this->samples; + return sum / this->samples_; } private: - ISimpleSensor<_Tp>* sensor; - size_t samples; + ISimpleSensor<ValueType>* sensor_; + size_t samples_; }; - template<typename _Tp, size_t _Samples> - class StaticMedianSensor : public ISimpleSensor<_Tp> { - static_assert(std::is_arithmetic<_Tp>::value, "StaticMedianSensor only supports arithmetic types"); - static_assert(_Samples % 2 == 1, "StaticMedianSensor only supports odd sample sizes"); + /// A sensor that returns the median value of N samples. + /// \tparam Tp Type of the sensor value + /// \tparam NumSamples Number of samples to be used + template<typename Tp, size_t NumSamples> + class StaticMedianSensor : public ISimpleSensor<Tp> { + static_assert(std::is_arithmetic_v<Tp>, "StaticMedianSensor only supports arithmetic types"); + static_assert(NumSamples % 2 == 1, "StaticMedianSensor only supports odd sample sizes"); public: - StaticMedianSensor(ISimpleSensor<_Tp>* sensor) : sensor(sensor) {} + using ValueType = Tp; - void init() override { this->sensor->init(); }; + explicit StaticMedianSensor(ISimpleSensor<ValueType>* sensor) : sensor_(sensor) {} - _Tp getValue() override + void init() override { this->sensor_->init(); }; + + [[nodiscard]] auto getValue() -> ValueType override { - for (size_t i = 0; i < _Samples; i++) { - this->values[i] = this->sensor->getValue(); + for (size_t i = 0; i < NumSamples; i++) { + this->values_[i] = this->sensor_->getValue(); } - std::sort(this->values, this->values + _Samples); + std::sort(this->values_.begin(), this->values_.end()); - return this->values[_Samples / 2]; + return this->values_[NumSamples / 2]; } private: - _Tp values[_Samples]; - ISimpleSensor<_Tp>* sensor; + /// Buffer to store the last N samples. + /// We are using a static array to avoid dynamic allocation + std::array<ValueType, NumSamples> values_; + + ISimpleSensor<Tp>* sensor_; }; } // namespace SenseShift::Input diff --git a/lib/io/senseshift/input/sensor/joystick.hpp b/lib/io/senseshift/input/sensor/joystick.hpp index a03af6f7..0dd95dfe 100644 --- a/lib/io/senseshift/input/sensor/joystick.hpp +++ b/lib/io/senseshift/input/sensor/joystick.hpp @@ -6,29 +6,31 @@ namespace SenseShift::Input { /** * Joystick axis sensor decorator */ - template<typename _Tp> - class JoystickAxisSensor : public ISimpleSensor<_Tp> { + template<typename Tp> + class JoystickAxisSensor : public ISimpleSensor<Tp> { + public: + using ValueType = Tp; + private: - ISimpleSensor<_Tp>* sensor; - float dead_zone; + ISimpleSensor<ValueType>* sensor_; + float dead_zone_; - int filterDeadZone(int in) - { - // This function clamps the input to the center of the range if - // the value is within the threshold. This is to eliminate at-rest - // noise of the joystick. - int center = ANALOG_MAX / 2; - return abs(center - in) < dead_zone * ANALOG_MAX ? center : in; + /// This function clamps the input to the center of the range if + /// the value is within the threshold. This is to eliminate at-rest + /// noise of the joystick. + [[nodiscard]] auto filterDeadZone(const int value_in) const -> ValueType { + constexpr ValueType center = ANALOG_MAX / 2; + return abs(center - value_in) < dead_zone_ * ANALOG_MAX ? center : value_in; } public: - JoystickAxisSensor(ISimpleSensor<_Tp>* sensor, float dead_zone) : sensor(sensor), dead_zone(dead_zone){}; + JoystickAxisSensor(ISimpleSensor<Tp>* sensor, const float dead_zone) : sensor_(sensor), dead_zone_(dead_zone){}; - void init() override { this->sensor->init(); }; + void init() override { this->sensor_->init(); }; - uint16_t getValue(void) override + [[nodiscard]] auto getValue() -> uint16_t override { - auto value = this->sensor->getValue(); + auto value = this->sensor_->getValue(); value = this->filterDeadZone(value); return value; } diff --git a/lib/io/senseshift/output/actuator.hpp b/lib/io/senseshift/output/actuator.hpp deleted file mode 100644 index 3938c65f..00000000 --- a/lib/io/senseshift/output/actuator.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include <cstdint> - -#include <senseshift/logging.hpp> - -namespace SenseShift::Output { - // Singular output point (e.g. vibration motor) - template<typename T> - class IActuator { - public: - virtual void setup(){}; - virtual void writeOutput(T) = 0; - }; - - template<> - class IActuator<std::uint16_t> { - public: - virtual void setup(){}; - virtual void writeOutput(std::uint16_t) = 0; - }; -} // namespace SenseShift::Output diff --git a/lib/io/senseshift/output/binary_output.hpp b/lib/io/senseshift/output/binary_output.hpp new file mode 100644 index 00000000..c9200a08 --- /dev/null +++ b/lib/io/senseshift/output/binary_output.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "senseshift/output/output.hpp" + +namespace SenseShift::Output { + class BinaryOutput : public ::SenseShift::Output::Output<bool> { + public: + virtual void writeOutput(bool) = 0; + }; +} // namespace SenseShift::Output \ No newline at end of file diff --git a/lib/io/senseshift/output/output.hpp b/lib/io/senseshift/output/output.hpp new file mode 100644 index 00000000..c02bfaf7 --- /dev/null +++ b/lib/io/senseshift/output/output.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include <senseshift/core/component.hpp> + +namespace SenseShift::Output { + template<typename Tp> + class Output : public IInitializable { + public: + using ValueType = Tp; + + virtual void writeState(ValueType value) = 0; + }; + + using FloatOutput = Output<float>; +} // namespace SenseShift::Output \ No newline at end of file diff --git a/lib/math/senseshift/math/point2.hpp b/lib/math/senseshift/math/point2.hpp index b91b096b..faa2f475 100644 --- a/lib/math/senseshift/math/point2.hpp +++ b/lib/math/senseshift/math/point2.hpp @@ -1,33 +1,33 @@ #pragma once #include <cmath> +#include <limits> #include <tuple> +#include <type_traits> namespace SenseShift::Math { - template<typename _Tp> + template<typename Tp> struct Point2 { - static_assert( - std::is_arithmetic<_Tp>::value, "::SenseShift::Math::Point2 only can be used with arithmetic types" - ); + static_assert(std::is_arithmetic_v<Tp>, "Point2 only can be used with arithmetic types"); - using Value = _Tp; + using Value = Tp; - static constexpr _Tp MIN = std::numeric_limits<_Tp>::min(); - static constexpr _Tp MAX = std::numeric_limits<_Tp>::max(); + static constexpr Tp MIN = std::numeric_limits<Tp>::min(); + static constexpr Tp MAX = std::numeric_limits<Tp>::max(); - _Tp x, y; + Tp x, y; - constexpr Point2() : x((_Tp) 0), y((_Tp) 0){}; - constexpr Point2(_Tp x, _Tp y) : x(x), y(y){}; - constexpr Point2(const Point2<_Tp>& v) : x((_Tp) v.x), y((_Tp) v.y){}; + constexpr Point2() : x(static_cast<Tp>(0)), y(static_cast<Tp>(0)){}; + constexpr Point2(Tp x, Tp y) : x(x), y(y){}; + constexpr Point2(const Point2<Tp>& v) : x((Tp) v.x), y((Tp) v.y){}; - constexpr inline bool operator==(const Point2<_Tp>& rhs) const { return x == rhs.x && y == rhs.y; } + constexpr inline auto operator==(const Point2<Tp>& rhs) const -> bool { return x == rhs.x && y == rhs.y; } - constexpr inline bool operator!=(const Point2<_Tp>& rhs) const { return !(*this == rhs); } + constexpr inline auto operator!=(const Point2<Tp>& rhs) const -> bool { return !(*this == rhs); } - constexpr bool operator<(const Point2<_Tp>& rhs) const { return std::tie(x, y) < std::tie(rhs.x, rhs.y); } + constexpr auto operator<(const Point2<Tp>& rhs) const -> bool { return std::tie(x, y) < std::tie(rhs.x, rhs.y); } - constexpr float operator-(const Point2<_Tp>& rhs) const + constexpr auto operator-(const Point2<Tp>& rhs) const -> float { return std::sqrt(std::pow(x - rhs.x, 2) + std::pow(y - rhs.y, 2)); } diff --git a/lib/opengloves/og_protocol.hpp b/lib/opengloves/og_protocol.hpp index a8f19e2e..f1849a3b 100644 --- a/lib/opengloves/og_protocol.hpp +++ b/lib/opengloves/og_protocol.hpp @@ -38,7 +38,7 @@ namespace OpenGloves { IStringEncoded(Type type) : IEncodedInput(type){}; virtual size_t getEncodedLength() const = 0; - virtual size_t encodeString(char* buffer) const = 0; + virtual size_t encodeString(char* buffer) = 0; }; class IStringEncodedMemoizedSensor : public IStringEncoded { diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index 191a8c06..35419d72 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -113,7 +113,7 @@ #define BUTTON_PINCH_ENABLED (!GESTURE_PINCH_ENABLED && defined(PIN_BUTTON_PINCH) && (PIN_BUTTON_PINCH != -1)) #define BUTTON_CLASS(_type, _pin, _invert) \ - StringEncodedMemoizedSensor<bool>(new ::SenseShift::Arduino::Input::DigitalSensor<_invert>(_pin), _type) + StringEncodedMemoizedSensor<bool>(new ::SenseShift::Arduino::Input::BinarySensor<_invert>(_pin), _type) #pragma endregion diff --git a/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp b/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp index 49d223cf..a8f81f7a 100644 --- a/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp +++ b/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp @@ -12,7 +12,7 @@ #include <frozen/unordered_map.h> #include <og_protocol.hpp> -#include <senseshift/logging.hpp> +#include <senseshift/core/logging.hpp> #include <senseshift/opengloves/interface.hpp> #define SENSESHIFT_OPENGLOVES_ALPHA_ENCODING_BUFFER_SIZE 256 diff --git a/lib/opengloves/sensor/og_finger.hpp b/lib/opengloves/sensor/og_finger.hpp index 542d981e..95760b7a 100644 --- a/lib/opengloves/sensor/og_finger.hpp +++ b/lib/opengloves/sensor/og_finger.hpp @@ -53,7 +53,7 @@ namespace OpenGloves { } } - FingerValue getValue() override + [[nodiscard]] auto getValue() -> FingerValue override { FingerValue value{ .curl = std::vector<uint16_t>(), @@ -68,7 +68,7 @@ namespace OpenGloves { return value; } - uint16_t getCurl() override { return this->getValue().getTotalCurl(); } + [[nodiscard]] auto getCurl() -> uint16_t override { return this->getValue().getTotalCurl(); } protected: FingerSensors sensors; @@ -136,11 +136,11 @@ namespace OpenGloves { FingerSensor(SenseShift::Input::CalibratedSimpleSensor<uint16_t>* curl1, IEncodedInput::Type type) : StringEncodedMemoizedSensor<FingerValue>(new CalibratedFingerSensor(curl1, std::nullopt), type){}; - void resetCalibration() override { static_cast<CalibratedFingerSensor*>(this->sensor)->resetCalibration(); } + void resetCalibration() override { static_cast<CalibratedFingerSensor*>(this->getSensor())->resetCalibration(); } - void enableCalibration() override { static_cast<CalibratedFingerSensor*>(this->sensor)->enableCalibration(); } + void enableCalibration() override { static_cast<CalibratedFingerSensor*>(this->getSensor())->enableCalibration(); } - void disableCalibration() override { static_cast<CalibratedFingerSensor*>(this->sensor)->disableCalibration(); } + void disableCalibration() override { static_cast<CalibratedFingerSensor*>(this->getSensor())->disableCalibration(); } uint16_t getCurl() override { return this->getValue().getTotalCurl(); } }; diff --git a/lib/opengloves/sensor/og_gesture.hpp b/lib/opengloves/sensor/og_gesture.hpp index 9bb0e375..c64365c1 100644 --- a/lib/opengloves/sensor/og_gesture.hpp +++ b/lib/opengloves/sensor/og_gesture.hpp @@ -19,7 +19,7 @@ namespace OpenGloves { void init() override{}; - bool getValue() override + [[nodiscard]] auto getValue() -> bool override { return this->index.getCurl() > this->threshold && this->middle.getCurl() > this->threshold && this->ring.getCurl() > this->threshold && this->pinky.getCurl() > this->threshold; @@ -36,7 +36,7 @@ namespace OpenGloves { void init() override{}; - bool getValue() override { return this->index.getCurl() > this->threshold; } + [[nodiscard]] auto getValue() -> bool override { return this->index.getCurl() > this->threshold; } }; class PinchGesture : public Gesture { @@ -46,12 +46,12 @@ namespace OpenGloves { uint16_t threshold; public: - PinchGesture(ICurl& index, ICurl& thumb, uint16_t threshold) : + PinchGesture(ICurl& index, ICurl& thumb, const uint16_t threshold) : index(index), thumb(thumb), threshold(threshold){}; void init() override{}; - bool getValue() override + [[nodiscard]] auto getValue() -> bool override { return this->index.getCurl() > this->threshold && this->thumb.getCurl() > this->threshold; } diff --git a/lib/opengloves/sensor/og_sensor.hpp b/lib/opengloves/sensor/og_sensor.hpp index caa4a9c8..6b95f0c1 100644 --- a/lib/opengloves/sensor/og_sensor.hpp +++ b/lib/opengloves/sensor/og_sensor.hpp @@ -33,27 +33,26 @@ namespace OpenGloves { StringEncodedMemoizedSensor(SenseShift::Input::ISimpleSensor<_Tp>* sensor, IEncodedInput::Type type) : IStringEncodedMemoizedSensor(type), SenseShift::Input::MemoizedSensor<_Tp>(sensor){}; - void init() override { this->sensor->init(); } + void init() override { this->getSensor()->init(); } - void updateValue() override { this->value = this->sensor->getValue(); } + void updateValue() override { this->value = this->sensor_->getValue(); } - size_t getEncodedLength() const override; + [[nodiscard]] size_t getEncodedLength() const override; - size_t encodeString(char* buffer) const override; + size_t encodeString(char* buffer) override; }; template<> - size_t StringEncodedMemoizedSensor<uint16_t>::getEncodedLength() const + inline size_t StringEncodedMemoizedSensor<uint16_t>::getEncodedLength() const { return 6; } + /// Format as "Axxxx", where A is the type and xxxxx is the value without leading zeros. template<> - size_t StringEncodedMemoizedSensor<uint16_t>::encodeString(char* buffer) const + inline size_t StringEncodedMemoizedSensor<uint16_t>::encodeString(char* buffer) { - // Format as "Axxxx", where A is the type and xxxxx is the value without - // leading zeros. - return snprintf(buffer, this->getEncodedLength(), "%c%d", this->getType(), this->value); + return snprintf(buffer, this->getEncodedLength(), "%c%d", this->getType(), this->getValue()); } template<> @@ -63,11 +62,14 @@ namespace OpenGloves { } template<> - size_t StringEncodedMemoizedSensor<bool>::encodeString(char* buffer) const + size_t StringEncodedMemoizedSensor<bool>::encodeString(char* buffer) { + const auto value = this->getValue(); + if (value) { buffer[0] = this->getType(); } + return value ? this->getEncodedLength() : 0; } @@ -79,20 +81,20 @@ namespace OpenGloves { } template<> - size_t StringEncodedMemoizedSensor<FingerValue>::encodeString(char* buffer) const + size_t StringEncodedMemoizedSensor<FingerValue>::encodeString(char* buffer) { size_t offset = 0; - offset += snprintf(buffer + offset, 6, "%c%d", this->type, this->value.getTotalCurl()); + offset += snprintf(buffer + offset, 6, "%c%d", this->type, this->getValue().getTotalCurl()); - if (this->value.curl.size() > 1) { - for (size_t i = 0; i < this->value.curl.size(); i++) { + if (this->getValue().curl.size() > 1) { + for (size_t i = 0; i < this->getValue().curl.size(); i++) { char knuckle = 'A' + i; - offset += snprintf(buffer + offset, 10, "(%cA%c)%d", this->type, knuckle, this->value.curl[i]); + offset += snprintf(buffer + offset, 10, "(%cA%c)%d", this->type, knuckle, this->getValue().curl[i]); } } - if (this->value.splay.has_value()) { - offset += snprintf(buffer + offset, 9, "(%cB)%d", this->type, this->value.splay.value()); + if (this->getValue().splay.has_value()) { + offset += snprintf(buffer + offset, 9, "(%cB)%d", this->type, this->getValue().splay.value()); } return offset; diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index 2f7bc581..4fb4f43f 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -6,7 +6,7 @@ #include <og_ffb.hpp> #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/input/sensor/digital.hpp> +#include <senseshift/arduino/input/sensor/binary.hpp> #include <senseshift/calibration.hpp> #include <senseshift/freertos/task.hpp> #include <senseshift/input/sensor.hpp> diff --git a/lib/util/senseshift/calibration.hpp b/lib/util/senseshift/calibration.hpp index 53411728..e1602582 100644 --- a/lib/util/senseshift/calibration.hpp +++ b/lib/util/senseshift/calibration.hpp @@ -15,105 +15,106 @@ namespace SenseShift::Calibration { }; class Calibrated : public virtual ICalibrated { - protected: - bool calibrate = false; + bool calibrate_ = false; public: - virtual void resetCalibration() = 0; - void enableCalibration() override { calibrate = true; } - void disableCalibration() override { calibrate = false; } + void resetCalibration() override = 0; + void enableCalibration() override { calibrate_ = true; } + void disableCalibration() override { calibrate_ = false; } }; - template<typename _Tp> + template<typename Tp> struct ICalibrator { - static_assert(std::is_arithmetic<_Tp>::value, "ICalibrator only can be used with arithmetic types"); + static_assert(std::is_arithmetic_v<Tp>, "ICalibrator only can be used with arithmetic types"); virtual void reset() = 0; - virtual void update(_Tp input) = 0; - virtual _Tp calibrate(_Tp input) const = 0; + virtual void update(Tp input) = 0; + virtual auto calibrate(Tp input) const -> Tp = 0; }; - template<typename _Tp, _Tp output_min, _Tp output_max> - class MinMaxCalibrator : public ICalibrator<_Tp> { + template<typename Tp, Tp output_min, Tp output_max> + class MinMaxCalibrator : public ICalibrator<Tp> { public: - MinMaxCalibrator() : value_min(output_max), value_max(output_min) {} + using ValueType = Tp; + + MinMaxCalibrator() : value_min_(output_max), value_max_(output_min) {} - void reset() - { - value_min = output_max; - value_max = output_min; + void reset() override { + value_min_ = output_max; + value_max_ = output_min; } - void update(_Tp input) - { + 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; + if (input < value_min_) { + value_min_ = input; + } + if (input > value_max_) { + value_max_ = input; + } } - _Tp calibrate(_Tp input) const - { + 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 (value_min_ > value_max_) { + return (output_min + output_max) / 2.0F; } - if (input <= value_min) { + if (input <= value_min_) { return output_min; } - if (input >= value_max) { + if (input >= value_max_) { return output_max; } // Map the input range to the output range. - _Tp output = ::SenseShift::accurateMap<_Tp>(input, value_min, value_max, output_min, output_max); + ValueType output = ::SenseShift::remap<ValueType, ValueType>(input, value_min_, value_max_, output_min, output_max); // Lock the range to the output. return std::clamp(output, output_min, output_max); } private: - _Tp value_min; - _Tp value_max; + ValueType value_min_; + ValueType value_max_; }; - template<typename _Tp, _Tp sensor_max, _Tp driver_max_deviation, _Tp output_min, _Tp output_max> - class CenterPointDeviationCalibrator : public ICalibrator<_Tp> { + template<typename Tp, Tp sensor_max, Tp driver_max_deviation, Tp output_min, Tp output_max> + class CenterPointDeviationCalibrator : public ICalibrator<Tp> { public: + using ValueType = Tp; + CenterPointDeviationCalibrator() : range_min(sensor_max), range_max(0) {} - void reset() - { + void reset() override { range_min = sensor_max; range_max = 0; } - void update(_Tp input) - { + void update(Tp input) override { // Update the min and the max. - if (input < range_min) - range_min = ::SenseShift::accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); - if (input > range_max) - range_max = ::SenseShift::accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); + if (input < range_min) { + range_min = ::SenseShift::remap<ValueType>(input, output_min, output_max, 0, sensor_max); + } + if (input > range_max) { + range_max = ::SenseShift::remap<ValueType>(input, output_min, output_max, 0, sensor_max); + } } - _Tp calibrate(_Tp input) const - { + 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 = (range_min + range_max) / 2.0f; + Tp center = (range_min + range_max) / 2.0F; // Map the input to the sensor range of motion. - int output = ::SenseShift::accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); + int output = ::SenseShift::accurateMap<Tp>(input, output_min, output_max, 0, sensor_max); // Find the deviation from the center and clamp it to the maximum that the driver supports. output = std::clamp<int>(output - center, -driver_max_deviation, driver_max_deviation); // Finally map the deviation from the center back to the output range. - return (_Tp)::SenseShift::accurateMap<int>( + return SenseShift::remap<ValueType, int>( output, -driver_max_deviation, driver_max_deviation, @@ -123,29 +124,30 @@ namespace SenseShift::Calibration { } private: - _Tp range_min; - _Tp range_max; + Tp range_min; + Tp range_max; }; - template<typename _Tp, _Tp sensor_max, _Tp driver_max_deviation, _Tp output_min, _Tp output_max> - class FixedCenterPointDeviationCalibrator : public ICalibrator<_Tp> { + template<typename Tp, Tp sensor_max, Tp driver_max_deviation, Tp output_min, Tp output_max> + class FixedCenterPointDeviationCalibrator : public ICalibrator<Tp> { public: - void reset() {} - void update(_Tp input) {} + using ValueType = Tp; + + void reset() override {} + void update(ValueType input) override {} - _Tp calibrate(_Tp input) const - { + 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 = sensor_max / 2.0f; + Tp center = sensor_max / 2.0F; // Map the input to the sensor range of motion. - int output = ::SenseShift::accurateMap<_Tp>(input, output_min, output_max, 0, sensor_max); + int output = ::SenseShift::remap<int, Tp>(input, output_min, output_max, 0, sensor_max); // Find the deviation from the center and clamp it to the maximum that the driver supports. output = std::clamp<int>(output - center, -driver_max_deviation, driver_max_deviation); // Finally map the deviation from the center back to the output range. - return (_Tp)::SenseShift::accurateMap<int>( + return SenseShift::remap<ValueType, int>( output, -driver_max_deviation, driver_max_deviation, diff --git a/lib/util/senseshift/container.hpp b/lib/util/senseshift/container.hpp index 7f0ab894..f8da0365 100644 --- a/lib/util/senseshift/container.hpp +++ b/lib/util/senseshift/container.hpp @@ -12,7 +12,7 @@ namespace SenseShift { * @tparam _Tp The type of the value. */ template<class _Cp, typename _Tp> - inline bool contains(_Cp&& c, _Tp val) + inline auto contains(const _Cp&& c, const _Tp val) -> bool { return std::find(std::begin(c), std::end(c), val) != std::end(c); }; diff --git a/lib/util/senseshift/range.hpp b/lib/util/senseshift/range.hpp index 6dac8598..ea690108 100644 --- a/lib/util/senseshift/range.hpp +++ b/lib/util/senseshift/range.hpp @@ -1,30 +1,21 @@ #include <cstdint> #include <type_traits> -#include <senseshift/logging.hpp> +#include <senseshift/core/logging.hpp> +#include <senseshift/core/helpers.hpp> namespace SenseShift { - template<typename _Tp> - constexpr _Tp accurateMap(_Tp x, _Tp in_min, _Tp in_max, _Tp out_min, _Tp out_max) noexcept + /// Remap \p value from the range (\p min, \p max) to (\p min_out, \p max_out). + template<typename Tp> + constexpr auto accurateMap(Tp value, Tp min, Tp max, Tp min_out, Tp max_out) noexcept -> Tp { - static_assert(std::is_arithmetic<_Tp>::value, "Type must be arithmetic"); - - const _Tp run = in_max - in_min; - if (run == 0) { - log_e("map(): Invalid input range, min == max"); - return (out_min + out_max) / 2; - } - const _Tp rise = out_max - out_min; - const _Tp delta = x - in_min; - return (delta * rise) / run + out_min; + return remap<Tp, Tp>(value, min, max, min_out, max_out); } // Same as the above, but both mins are 0. - template<typename _Tp> - constexpr inline _Tp simpleMap(_Tp x, _Tp in_max, _Tp out_max) noexcept + template<typename Tp> + constexpr auto simpleMap(Tp value, Tp in_max, Tp out_max) noexcept -> Tp { - static_assert(std::is_arithmetic<_Tp>::value, "Type must be arithmetic"); - - return x * out_max / in_max; + return remap_simple<Tp, Tp>(value, in_max, out_max); } } // namespace SenseShift From 176f5e512c39f823c391b6883366c9d6a80ce042 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 28 Jan 2024 00:16:15 +0400 Subject: [PATCH 50/82] refactor(Battery): use analog float sensor --- firmware/firmware.cpp | 16 --------- .../mode_configs/bhaptics/tactsuit_x16.cpp | 3 ++ .../bhaptics/tactsuit_x16_pca9685.cpp | 3 ++ .../mode_configs/bhaptics/tactsuit_x40.cpp | 3 ++ .../arduino/input/sensor/analog.hpp | 22 ++++++------ .../arduino/output/actuator/servo.hpp | 34 ------------------- .../senseshift/arduino/output/analog.hpp | 5 +-- .../senseshift/arduino/output/pca9685.hpp | 10 +++--- .../senseshift/arduino/output/ledc.hpp | 2 +- lib/battery/senseshift/battery.hpp | 1 + lib/battery/senseshift/battery/sensor.hpp | 12 ++++--- lib/bhaptics/senseshift/bh/encoding.hpp | 3 +- .../senseshift/freertos/input/sensor.hpp | 8 ++--- lib/haptics/senseshift/body/haptics/body.cpp | 2 +- lib/haptics/senseshift/body/haptics/body.hpp | 4 +-- lib/haptics/senseshift/body/haptics/plane.cpp | 4 +-- lib/haptics/senseshift/body/haptics/plane.hpp | 6 ++-- lib/io/senseshift/input/sensor.hpp | 5 +-- lib/io/senseshift/output/binary_output.hpp | 10 ------ lib/io/senseshift/output/output.hpp | 5 +-- 20 files changed, 58 insertions(+), 100 deletions(-) delete mode 100644 lib/arduino/senseshift/arduino/output/actuator/servo.hpp delete mode 100644 lib/io/senseshift/output/binary_output.hpp diff --git a/firmware/firmware.cpp b/firmware/firmware.cpp index 213a1fbd..258921f2 100644 --- a/firmware/firmware.cpp +++ b/firmware/firmware.cpp @@ -4,14 +4,6 @@ #include <Arduino.h> #endif // ARDUINO -#if defined(SENSESHIFT_SERIAL_PLOTTER) && SENSESHIFT_SERIAL_PLOTTER == true -#include <senseshift/arduino/components/serial_plotter.hpp> -#endif // SENSESHIFT_SERIAL_PLOTTER - -#ifndef SENSESHIFT_SERIAL_PLOTTER_PORT -#define SENSESHIFT_SERIAL_PLOTTER_PORT Serial -#endif // SENSESHIFT_SERIAL_PLOTTER_PORT - #ifndef PIO_UNIT_TESTING extern void setupMode(); @@ -24,14 +16,6 @@ SenseShift::Application App; void setup() { setupMode(); - -#if defined(SENSESHIFT_SERIAL_PLOTTER) && SENSESHIFT_SERIAL_PLOTTER == true - auto* serialOutputState = new ::SenseShift::Arduino::SerialPlotter_OutputStates<HardwareSerial>( - SENSESHIFT_SERIAL_PLOTTER_PORT, - App.getHapticBody() - ); - serialOutputState->begin(); -#endif // SENSESHIFT_SERIAL_PLOTTER } void loop() diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index f5c566c3..52b95ccf 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -5,7 +5,10 @@ #include <Wire.h> #include "senseshift.h" + +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/ledc.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index 128dcd22..87869e43 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -5,7 +5,10 @@ #include <Wire.h> #include "senseshift.h" + +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pca9685.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 23983157..8a036950 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -5,8 +5,11 @@ #include <Wire.h> #include "senseshift.h" + +#include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/ledc.hpp> #include <senseshift/arduino/output/pca9685.hpp> +#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> diff --git a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp index 122b1906..e95f14f4 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -1,33 +1,35 @@ #pragma once +#include <cstdint> + #include <senseshift/input/sensor.hpp> #include <Arduino.h> namespace SenseShift::Arduino::Input { - using IAnalogSensor = ::SenseShift::Input::ISimpleSensor<uint16_t>; - template<bool Invert = false> - class AnalogSensor : public IAnalogSensor { - uint8_t pin_; + class AnalogSensor : public ::SenseShift::Input::IFloatSensor { + std::uint8_t pin_; public: - AnalogSensor(const uint8_t pin) : pin_(pin) {} + AnalogSensor(const std::uint8_t pin) : pin_(pin) {} void init() override { pinMode(this->pin_, INPUT); }; - [[nodiscard]] auto getValue() -> uint16_t override; + [[nodiscard]] auto getValue() -> float override; }; template<> - [[nodiscard]] inline auto AnalogSensor<false>::getValue() -> uint16_t + [[nodiscard]] inline auto AnalogSensor<false>::getValue() -> float { - return analogRead(this->pin_); + const auto raw = analogRead(this->pin_); + return static_cast<float>(raw) / ANALOG_MAX; } template<> - [[nodiscard]] inline auto AnalogSensor<true>::getValue() -> uint16_t + [[nodiscard]] inline auto AnalogSensor<true>::getValue() -> float { - return ANALOG_MAX - analogRead(this->pin_); + const auto raw = ANALOG_MAX - analogRead(this->pin_); + return static_cast<float>(raw) / ANALOG_MAX; } } // namespace SenseShift::Arduino::Input diff --git a/lib/arduino/senseshift/arduino/output/actuator/servo.hpp b/lib/arduino/senseshift/arduino/output/actuator/servo.hpp deleted file mode 100644 index 29bfa5e1..00000000 --- a/lib/arduino/senseshift/arduino/output/actuator/servo.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include <senseshift/output/actuator.hpp> -#include <senseshift/utility.hpp> - -#include <ESP32Servo.h> - -namespace SenseShift::Arduino::Output { - class ActuatorServo : public ::SenseShift::Output::IActuator<std::uint16_t> { - public: - static inline constexpr const std::uint16_t MAX_INTENSITY = 4095; - - ActuatorServo(const uint8_t pin, const std::uint16_t min = 500, const std::uint16_t max = 2400) : - pin(pin), min(min), max(max){}; - - void setup() override - { - servo.attach(this->pin, this->min, this->max); - this->writeOutput(0); - }; - - void writeOutput(std::uint16_t intensity) override - { - servo.writeMicroseconds( - ::SenseShift::accurateMap<std::uint16_t>(intensity, 0, MAX_INTENSITY, this->min, this->max) - ); - }; - - private: - Servo servo = Servo(); - uint8_t pin; - std::uint16_t min, max; - }; -} // namespace SenseShift::Arduino::Output diff --git a/lib/arduino/senseshift/arduino/output/analog.hpp b/lib/arduino/senseshift/arduino/output/analog.hpp index bcefae41..7dec32b6 100644 --- a/lib/arduino/senseshift/arduino/output/analog.hpp +++ b/lib/arduino/senseshift/arduino/output/analog.hpp @@ -8,7 +8,7 @@ namespace SenseShift::Arduino::Output { /// Arduino analog output - class AnalogOutput : public ::SenseShift::Output::FloatOutput { + class AnalogOutput : public ::SenseShift::Output::IFloatOutput { public: static inline constexpr std::uint16_t MAX_INTENSITY = 255; @@ -20,7 +20,8 @@ namespace SenseShift::Arduino::Output { } void writeState(const float value) override { - analogWrite(this->pin_, value * MAX_INTENSITY); + const auto duty = static_cast<int>(value * MAX_INTENSITY); + analogWrite(this->pin_, duty); } private: diff --git a/lib/arduino/senseshift/arduino/output/pca9685.hpp b/lib/arduino/senseshift/arduino/output/pca9685.hpp index 66798efd..62ea63cf 100644 --- a/lib/arduino/senseshift/arduino/output/pca9685.hpp +++ b/lib/arduino/senseshift/arduino/output/pca9685.hpp @@ -10,7 +10,7 @@ #include <Wire.h> namespace SenseShift::Arduino::Output { - class PCA9685Output : public ::SenseShift::Output::FloatOutput { + class PCA9685Output : public ::SenseShift::Output::IFloatOutput { public: static inline constexpr std::uint16_t MAX_INTENSITY = 4095; @@ -20,12 +20,10 @@ namespace SenseShift::Arduino::Output { this->driver_->begin(); } - void writeState(const ValueType intensity) override + void writeState(const ValueType value) override { - this->driver_->setPin( - this->channel_, - intensity * MAX_INTENSITY - ); + const auto duty = static_cast<std::uint16_t>(value * MAX_INTENSITY); + this->driver_->setPin(this->channel_, duty); } private: diff --git a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp index a74eba96..2d1d810c 100644 --- a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp +++ b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp @@ -11,7 +11,7 @@ namespace SenseShift::Arduino::Output { static const char *const TAG = "output.ledc"; /// Arduino analog output - class LedcOutput : public ::SenseShift::Output::FloatOutput { + class LedcOutput : public ::SenseShift::Output::IFloatOutput { public: explicit LedcOutput( const std::uint8_t pin, diff --git a/lib/battery/senseshift/battery.hpp b/lib/battery/senseshift/battery.hpp index 4de3c867..c6238a0d 100644 --- a/lib/battery/senseshift/battery.hpp +++ b/lib/battery/senseshift/battery.hpp @@ -60,6 +60,7 @@ namespace SenseShift::Battery { }); struct BatteryState { + static constexpr std::uint8_t MAX_LEVEL = 255; uint8_t level; }; diff --git a/lib/battery/senseshift/battery/sensor.hpp b/lib/battery/senseshift/battery/sensor.hpp index ff05f5af..aae97c85 100644 --- a/lib/battery/senseshift/battery/sensor.hpp +++ b/lib/battery/senseshift/battery/sensor.hpp @@ -1,5 +1,7 @@ #pragma once +#include <cstdint> + #include "senseshift/battery.hpp" #include <senseshift/freertos/task.hpp> @@ -18,17 +20,19 @@ namespace SenseShift::Battery { class NaiveBatterySensor : public IBatterySensor { public: - NaiveBatterySensor(::SenseShift::Input::ISimpleSensor<uint16_t>* sensor) : sensor(sensor){}; + explicit NaiveBatterySensor(::SenseShift::Input::IFloatSensor* sensor) : sensor(sensor){}; [[nodiscard]] auto getValue() -> BatteryState override { - return { .level = - static_cast<uint8_t>(::SenseShift::simpleMap<uint16_t>(this->sensor->getValue(), 4095, 255)) }; + const auto level = static_cast<std::uint8_t>(this->sensor->getValue() * BatteryState::MAX_LEVEL); + + return { .level = level}; }; + void init() override { this->sensor->init(); } private: - ISimpleSensor<uint16_t> * sensor; + ::SenseShift::Input::IFloatSensor* sensor; }; class BatterySensor : public ::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState> { diff --git a/lib/bhaptics/senseshift/bh/encoding.hpp b/lib/bhaptics/senseshift/bh/encoding.hpp index 3b05a54f..1a8b8af4 100644 --- a/lib/bhaptics/senseshift/bh/encoding.hpp +++ b/lib/bhaptics/senseshift/bh/encoding.hpp @@ -207,7 +207,8 @@ namespace SenseShift::BH { private: static auto effectDataFromByte(const uint8_t byte, const uint8_t maxValue = 100) -> VibroEffectData { - return VibroEffectData(byte / maxValue); + const auto value = static_cast<float>(byte) / static_cast<float>(maxValue); + return VibroEffectData(value); } }; } // namespace SenseShift::BH diff --git a/lib/freertos/senseshift/freertos/input/sensor.hpp b/lib/freertos/senseshift/freertos/input/sensor.hpp index 8209aa3f..aa2b12a5 100644 --- a/lib/freertos/senseshift/freertos/input/sensor.hpp +++ b/lib/freertos/senseshift/freertos/input/sensor.hpp @@ -32,12 +32,12 @@ namespace SenseShift::FreeRTOS::Input { } }; - template<typename _Tp> - class TaskedSensor : public SensorUpdateTask, public ::SenseShift::Input::ISimpleSensor<_Tp> { + template<typename Tp> + class TaskedSensor : public SensorUpdateTask, public ::SenseShift::Input::ISimpleSensor<Tp> { friend class SensorUpdateTask; private: - using Sensor = ::SenseShift::Input::MemoizedSensor<_Tp>; + using Sensor = ::SenseShift::Input::MemoizedSensor<Tp>; public: TaskedSensor(Sensor* sensor, std::uint32_t updateDelay, TaskConfig taskConfig) : @@ -51,7 +51,7 @@ namespace SenseShift::FreeRTOS::Input { void init() override { this->sensor->init(); }; - _Tp getValue() override { return this->sensor->getValue(); }; + Tp getValue() override { return this->sensor->getValue(); }; private: Sensor* sensor; diff --git a/lib/haptics/senseshift/body/haptics/body.cpp b/lib/haptics/senseshift/body/haptics/body.cpp index e60eb210..5caa7beb 100644 --- a/lib/haptics/senseshift/body/haptics/body.cpp +++ b/lib/haptics/senseshift/body/haptics/body.cpp @@ -19,5 +19,5 @@ namespace SenseShift::Body::Haptics { find->second->effect(pos, val); } - template class OutputBody<Position::Value, Output::FloatOutput::ValueType>; + template class OutputBody<Position::Value, Output::IFloatOutput::ValueType>; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/body.hpp b/lib/haptics/senseshift/body/haptics/body.hpp index 386866a4..6cdd2cbd 100644 --- a/lib/haptics/senseshift/body/haptics/body.hpp +++ b/lib/haptics/senseshift/body/haptics/body.hpp @@ -8,7 +8,7 @@ #include <senseshift/output/output.hpp> namespace SenseShift::Body::Haptics { - /// Output body, contains all the output planes. + /// IOutput body, contains all the output planes. /// /// \tparam Tc The type of the coordinate. /// \tparam To The type of the output value. @@ -40,5 +40,5 @@ namespace SenseShift::Body::Haptics { TargetPlaneMap targets_{}; }; - using FloatBody = OutputBody<Position::Value, Output::FloatOutput::ValueType>; + using FloatBody = OutputBody<Position::Value, Output::IFloatOutput::ValueType>; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/plane.cpp b/lib/haptics/senseshift/body/haptics/plane.cpp index bfbd4f33..9fbe77ee 100644 --- a/lib/haptics/senseshift/body/haptics/plane.cpp +++ b/lib/haptics/senseshift/body/haptics/plane.cpp @@ -77,6 +77,6 @@ namespace SenseShift::Body::Haptics { return nearest->second; } - template class OutputPlane<Position::Value, Output::FloatOutput::ValueType>; - template class OutputPlane_Closest<Position::Value, Output::FloatOutput::ValueType>; + template class OutputPlane<Position::Value, Output::IFloatOutput::ValueType>; + template class OutputPlane_Closest<Position::Value, Output::IFloatOutput::ValueType>; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/plane.hpp b/lib/haptics/senseshift/body/haptics/plane.hpp index eeea313b..a12b3d75 100644 --- a/lib/haptics/senseshift/body/haptics/plane.hpp +++ b/lib/haptics/senseshift/body/haptics/plane.hpp @@ -28,7 +28,7 @@ namespace SenseShift::Body::Haptics { /// 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::Output<Value>; + using Actuator = Output::IOutput<Value>; using ActuatorMap = std::map<Position, Actuator*>; using PositionStateMap = std::map<Position, Value>; @@ -73,8 +73,8 @@ namespace SenseShift::Body::Haptics { [[nodiscard]] static auto findClosestPoint(const PositionSet&, const Position&) -> const Position&; }; - using FloatPlane = OutputPlane<Position::Value, Output::FloatOutput::ValueType>; - using FloatPlane_Closest = OutputPlane_Closest<Position::Value, Output::FloatOutput::ValueType>; + using FloatPlane = OutputPlane<Position::Value, Output::IFloatOutput::ValueType>; + using FloatPlane_Closest = OutputPlane_Closest<Position::Value, Output::IFloatOutput::ValueType>; // TODO: configurable margin class PlaneMapper_Margin { diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index 22b8a116..a8302172 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -21,7 +21,7 @@ namespace SenseShift::Input { /// \tparam Tp Type of the sensor value template<typename Tp> class ISimpleSensor : virtual public IInitializable { - public: + public: using ValueType = Tp; /// Get the current sensor value @@ -29,9 +29,10 @@ namespace SenseShift::Input { }; using IBinarySensor = ISimpleSensor<bool>; + using IFloatSensor = ISimpleSensor<float>; template<typename Tp> - class ISensor : virtual ISimpleSensor<Tp>, ITickable {}; + class ISensor : public virtual ISimpleSensor<Tp>, public ITickable {}; /// Memoized sensor decorator. Stores the last read value and returns it on subsequent calls /// \tparam Tp Type of the sensor value diff --git a/lib/io/senseshift/output/binary_output.hpp b/lib/io/senseshift/output/binary_output.hpp deleted file mode 100644 index c9200a08..00000000 --- a/lib/io/senseshift/output/binary_output.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "senseshift/output/output.hpp" - -namespace SenseShift::Output { - class BinaryOutput : public ::SenseShift::Output::Output<bool> { - public: - virtual void writeOutput(bool) = 0; - }; -} // namespace SenseShift::Output \ No newline at end of file diff --git a/lib/io/senseshift/output/output.hpp b/lib/io/senseshift/output/output.hpp index c02bfaf7..0392714f 100644 --- a/lib/io/senseshift/output/output.hpp +++ b/lib/io/senseshift/output/output.hpp @@ -4,12 +4,13 @@ namespace SenseShift::Output { template<typename Tp> - class Output : public IInitializable { + class IOutput : public IInitializable { public: using ValueType = Tp; virtual void writeState(ValueType value) = 0; }; - using FloatOutput = Output<float>; + using IBinaryOutput = IOutput<bool>; + using IFloatOutput = IOutput<float>; } // namespace SenseShift::Output \ No newline at end of file From 2d163b617c6959723754b6a797bc7ca8b2ca5e05 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 29 Jan 2024 18:47:55 +0400 Subject: [PATCH 51/82] refactor(Sensor): new sensor stack with filters --- firmware/mode_configs/bhaptics/tactal.cpp | 25 +- firmware/mode_configs/bhaptics/tactglove.cpp | 25 +- firmware/mode_configs/bhaptics/tactosy2.cpp | 25 +- firmware/mode_configs/bhaptics/tactosyf.cpp | 25 +- firmware/mode_configs/bhaptics/tactosyh.cpp | 25 +- .../mode_configs/bhaptics/tactsuit_x16.cpp | 25 +- .../bhaptics/tactsuit_x16_pca9685.cpp | 25 +- .../mode_configs/bhaptics/tactsuit_x40.cpp | 25 +- firmware/mode_configs/bhaptics/tactvisor.cpp | 25 +- .../senseshift/arduino/battery/ina219.hpp | 33 -- .../senseshift/arduino/battery/max17048.hpp | 45 --- .../arduino/input/sensor/analog.hpp | 23 +- lib/battery/senseshift/battery.hpp | 88 +++--- lib/battery/senseshift/battery/sensor.hpp | 58 ++-- lib/core/senseshift/core/helpers.hpp | 78 ++++- .../senseshift/freertos/input/sensor.hpp | 56 ++-- lib/freertos/senseshift/freertos/task.hpp | 21 +- .../senseshift/input}/calibration.hpp | 40 +-- lib/io/senseshift/input/filter.hpp | 284 +++++++++++++++++ lib/io/senseshift/input/sensor.hpp | 285 +++++++++++------- lib/io/senseshift/input/sensor/joystick.hpp | 38 --- .../senseshift/opengloves/interface.hpp | 26 +- lib/opengloves/sensor/og_sensor.hpp | 82 +---- test/test_util_calibration/main.cpp | 2 +- 24 files changed, 874 insertions(+), 510 deletions(-) delete mode 100644 lib/arduino/senseshift/arduino/battery/ina219.hpp delete mode 100644 lib/arduino/senseshift/arduino/battery/max17048.hpp rename lib/{util/senseshift => io/senseshift/input}/calibration.hpp (82%) create mode 100644 lib/io/senseshift/input/filter.hpp delete mode 100644 lib/io/senseshift/input/sensor/joystick.hpp diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index 08f35d38..e81c311d 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -15,6 +15,7 @@ #include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; +using namespace SenseShift::Input; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; @@ -54,12 +55,26 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new TaskedSensor<BatteryState>( - new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); + batteryVoltageSensor->addFilters({ + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + }); + auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + ); + batteryTask->begin(); + + auto* batterySensor = new LookupTableInterpolateBatterySensor<const frozen::map<float, float, 21>>( + batteryVoltageSensor, + &VoltageMap::LiPO_1S_42 ); - battery->begin(); + batterySensor->addValueCallback([](BatteryState value) -> void { + app->postEvent(new BatteryLevelEvent(value)); + }); + batterySensor->init(); #endif } diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 7463c1b9..2cca8354 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -16,6 +16,7 @@ #include <senseshift/utility.hpp> using namespace SenseShift; +using namespace SenseShift::Input; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; @@ -62,12 +63,26 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new TaskedSensor<BatteryState>( - new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); + batteryVoltageSensor->addFilters({ + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + }); + auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); - battery->begin(); + batteryTask->begin(); + + auto* batterySensor = new LookupTableInterpolateBatterySensor<const frozen::map<float, float, 21>>( + batteryVoltageSensor, + &VoltageMap::LiPO_1S_42 + ); + batterySensor->addValueCallback([](BatteryState value) -> void { + app->postEvent(new BatteryLevelEvent(value)); + }); + batterySensor->init(); #endif } diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index 74cbcdfd..fb20ce80 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -15,6 +15,7 @@ #include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; +using namespace SenseShift::Input; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; @@ -55,12 +56,26 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new TaskedSensor<BatteryState>( - new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); + batteryVoltageSensor->addFilters({ + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + }); + auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + ); + batteryTask->begin(); + + auto* batterySensor = new LookupTableInterpolateBatterySensor<const frozen::map<float, float, 21>>( + batteryVoltageSensor, + &VoltageMap::LiPO_1S_42 ); - battery->begin(); + batterySensor->addValueCallback([](BatteryState value) -> void { + app->postEvent(new BatteryLevelEvent(value)); + }); + batterySensor->init(); #endif } diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index c8352ee8..cc623ce2 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -15,6 +15,7 @@ #include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; +using namespace SenseShift::Input; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; @@ -56,12 +57,26 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new TaskedSensor<BatteryState>( - new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); + batteryVoltageSensor->addFilters({ + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + }); + auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + ); + batteryTask->begin(); + + auto* batterySensor = new LookupTableInterpolateBatterySensor<const frozen::map<float, float, 21>>( + batteryVoltageSensor, + &VoltageMap::LiPO_1S_42 ); - battery->begin(); + batterySensor->addValueCallback([](BatteryState value) -> void { + app->postEvent(new BatteryLevelEvent(value)); + }); + batterySensor->init(); #endif } diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index a4b8574f..05e6ba9f 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -15,6 +15,7 @@ #include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; +using namespace SenseShift::Input; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; @@ -56,12 +57,26 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new TaskedSensor<BatteryState>( - new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); + batteryVoltageSensor->addFilters({ + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + }); + auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + ); + batteryTask->begin(); + + auto* batterySensor = new LookupTableInterpolateBatterySensor<const frozen::map<float, float, 21>>( + batteryVoltageSensor, + &VoltageMap::LiPO_1S_42 ); - battery->begin(); + batterySensor->addValueCallback([](BatteryState value) -> void { + app->postEvent(new BatteryLevelEvent(value)); + }); + batterySensor->init(); #endif } diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 52b95ccf..f828ec19 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -15,6 +15,7 @@ #include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; +using namespace SenseShift::Input; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; @@ -65,12 +66,26 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new TaskedSensor<BatteryState>( - new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); + batteryVoltageSensor->addFilters({ + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + }); + auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + ); + batteryTask->begin(); + + auto* batterySensor = new LookupTableInterpolateBatterySensor<const frozen::map<float, float, 21>>( + batteryVoltageSensor, + &VoltageMap::LiPO_1S_42 ); - battery->begin(); + batterySensor->addValueCallback([](BatteryState value) -> void { + app->postEvent(new BatteryLevelEvent(value)); + }); + batterySensor->init(); #endif } diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index 87869e43..b1066077 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -15,6 +15,7 @@ #include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; +using namespace SenseShift::Input; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; @@ -70,12 +71,26 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new TaskedSensor<BatteryState>( - new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); + batteryVoltageSensor->addFilters({ + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + }); + auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + ); + batteryTask->begin(); + + auto* batterySensor = new LookupTableInterpolateBatterySensor<const frozen::map<float, float, 21>>( + batteryVoltageSensor, + &VoltageMap::LiPO_1S_42 ); - battery->begin(); + batterySensor->addValueCallback([](BatteryState value) -> void { + app->postEvent(new BatteryLevelEvent(value)); + }); + batterySensor->init(); #endif } diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 8a036950..48ea44ee 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -16,6 +16,7 @@ #include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; +using namespace SenseShift::Input; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; @@ -79,12 +80,26 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new TaskedSensor<BatteryState>( - new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); + batteryVoltageSensor->addFilters({ + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + }); + auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + ); + batteryTask->begin(); + + auto* batterySensor = new LookupTableInterpolateBatterySensor<const frozen::map<float, float, 21>>( + batteryVoltageSensor, + &VoltageMap::LiPO_1S_42 ); - battery->begin(); + batterySensor->addValueCallback([](BatteryState value) -> void { + app->postEvent(new BatteryLevelEvent(value)); + }); + batterySensor->init(); #endif } diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index 1c3f02cb..d5c7565c 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -15,6 +15,7 @@ #include <senseshift/freertos/input/sensor.hpp> using namespace SenseShift; +using namespace SenseShift::Input; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; @@ -54,12 +55,26 @@ void setupMode() bhBleConnection->begin(); #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true - auto* battery = new TaskedSensor<BatteryState>( - new BatterySensor(new NaiveBatterySensor(new AnalogSensor(36)), app), - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); + batteryVoltageSensor->addFilters({ + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + }); + auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + ); + batteryTask->begin(); + + auto* batterySensor = new LookupTableInterpolateBatterySensor<const frozen::map<float, float, 21>>( + batteryVoltageSensor, + &VoltageMap::LiPO_1S_42 ); - battery->begin(); + batterySensor->addValueCallback([](BatteryState value) -> void { + app->postEvent(new BatteryLevelEvent(value)); + }); + batterySensor->init(); #endif } diff --git a/lib/arduino/senseshift/arduino/battery/ina219.hpp b/lib/arduino/senseshift/arduino/battery/ina219.hpp deleted file mode 100644 index a343488d..00000000 --- a/lib/arduino/senseshift/arduino/battery/ina219.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include <senseshift/battery/sensor.hpp> - -#include <Adafruit_INA219.h> - -namespace SenseShift::Arduino::Battery { - class INA219_Battery : public ::SenseShift::Battery::IBatterySensor { - private: - bool active = false; - Adafruit_INA219* sensor; - - public: - INA219_Battery(Adafruit_INA219* sensor) : sensor(sensor){}; - - void init() override { this->active = this->sensor->begin(); } - - ::SenseShift::Battery::BatteryState getValue() override - { - if (!this->active) { - return { 0 }; - } - - auto batteryVoltage = this->sensor->getBusVoltage_V(); - // TODO: change this linear transformation to smth more useful - auto batteryPercentage = (batteryVoltage - 3.0) / 0.96; - - return { - simpleMap<float>(batteryPercentage, 1.0f, 255.0f), - }; - } - }; -} // namespace SenseShift::Arduino::Battery diff --git a/lib/arduino/senseshift/arduino/battery/max17048.hpp b/lib/arduino/senseshift/arduino/battery/max17048.hpp deleted file mode 100644 index dc886cc2..00000000 --- a/lib/arduino/senseshift/arduino/battery/max17048.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include <senseshift/battery/sensor.hpp> - -#include <SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.h> - -namespace SenseShift::Arduino::Battery { - class MAX1704_Battery : public ::SenseShift::Battery::IBatterySensor { - public: - MAX1704_Battery(SFE_MAX1704X* gauge) : gauge(gauge){}; - - /** - * @see - * https://github.com/sparkfun/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/blob/main/examples/Example1_Simple/Example1_Simple.ino - */ - void init() override - { - // Set up the MAX17043 LiPo fuel gauge: - this->active = this->gauge->begin(); - - if (this->active) { - // Quick start restarts the MAX17043 in hopes of getting a more accurate - // guess for the SOC. - this->gauge->quickStart(); - - // We can set an interrupt to alert when the battery SoC gets too low. - // We can alert at anywhere between 1% - 32%: - // this->gauge->setThreshold(SENSESHIFT_BATTERY_THRESHOLD_PERCENTAGE); - } - } - - ::SenseShift::Battery::BatteryState getValue() override - { - if (!this->active) { - return { 0 }; - } - - return { .level = simpleMap(this->gauge->getSOC(), 1.0f, 255.0f) }; - } - - private: - bool active = false; - SFE_MAX1704X* gauge; - }; -} // namespace SenseShift::Arduino::Battery diff --git a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp index e95f14f4..dbef7c39 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -6,13 +6,24 @@ #include <Arduino.h> +#if defined(__AVR__) +#define ANALOG_MAX 1023.0F +#elif defined(ESP32) +#define ANALOG_MAX 4095.0F +#elif !defined(ANALOG_MAX) +#warning "This board doesn't have an auto ANALOG_MAX assignment, please set it manually" +#define ANALOG_MAX static_assert(false, "ANALOG_MAX is not defined") +// Uncomment and set as needed (only touch if you know what you are doing) +// #define ANALOG_MAX 4095.0F +#endif + namespace SenseShift::Arduino::Input { template<bool Invert = false> - class AnalogSensor : public ::SenseShift::Input::IFloatSensor { + class AnalogSimpleSensor : public ::SenseShift::Input::IFloatSimpleSensor { std::uint8_t pin_; public: - AnalogSensor(const std::uint8_t pin) : pin_(pin) {} + explicit AnalogSimpleSensor(const std::uint8_t pin) : pin_(pin) {} void init() override { pinMode(this->pin_, INPUT); }; @@ -20,16 +31,16 @@ namespace SenseShift::Arduino::Input { }; template<> - [[nodiscard]] inline auto AnalogSensor<false>::getValue() -> float + [[nodiscard]] inline auto AnalogSimpleSensor<false>::getValue() -> float { - const auto raw = analogRead(this->pin_); + const std::uint16_t raw = analogRead(this->pin_); return static_cast<float>(raw) / ANALOG_MAX; } template<> - [[nodiscard]] inline auto AnalogSensor<true>::getValue() -> float + [[nodiscard]] inline auto AnalogSimpleSensor<true>::getValue() -> float { - const auto raw = ANALOG_MAX - analogRead(this->pin_); + const std::uint16_t raw = ANALOG_MAX - analogRead(this->pin_); return static_cast<float>(raw) / ANALOG_MAX; } } // namespace SenseShift::Arduino::Input diff --git a/lib/battery/senseshift/battery.hpp b/lib/battery/senseshift/battery.hpp index c6238a0d..ed784445 100644 --- a/lib/battery/senseshift/battery.hpp +++ b/lib/battery/senseshift/battery.hpp @@ -1,67 +1,49 @@ #pragma once #include <cstdint> +#include <limits> +#include <algorithm> #include <frozen/map.h> #include <senseshift/events.hpp> namespace SenseShift::Battery { - // Source: https://blog.ampow.com/lipo-voltage-chart/ - inline static const auto voltageToPercents_1s = frozen::make_map<float, float>({ - // clang-format off - { 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 }, - // clang-format on - }); - inline static const auto voltageToPercents_2s = frozen::make_map<float, float>({ - // clang-format off - { 8.4, 1.0 }, - { 8.3, 0.95 }, - { 8.22, 0.9 }, - { 8.16, 0.85 }, - { 8.05, 0.8 }, - { 7.97, 0.75 }, - { 7.91, 0.7 }, - { 7.83, 0.65 }, - { 7.75, 0.6 }, - { 7.71, 0.55 }, - { 7.67, 0.5 }, - { 7.63, 0.45 }, - { 7.59, 0.4 }, - { 7.57, 0.35 }, - { 7.53, 0.3 }, - { 7.49, 0.25 }, - { 7.45, 0.2 }, - { 7.41, 0.15 }, - { 7.37, 0.1 }, - { 7.22, 0.05 }, - { 6.55, 0.0 }, - // clang-format on - }); + + namespace VoltageMap { + /// Lookup table for LiPO 1S 4.2V batteries + /// \see <a href="https://blog.ampow.com/lipo-voltage-chart/">Source</a> + [[maybe_unused]] inline static const auto LiPO_1S_42= frozen::make_map<float, float>({ + { 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 { - static constexpr std::uint8_t MAX_LEVEL = 255; - uint8_t level; + using VoltageType = float; + using LevelType = std::uint8_t; + + static constexpr LevelType MAX_LEVEL = std::numeric_limits<LevelType>::max(); + LevelType level; }; class BatteryLevelEvent : public IEvent { diff --git a/lib/battery/senseshift/battery/sensor.hpp b/lib/battery/senseshift/battery/sensor.hpp index aae97c85..fdfa525d 100644 --- a/lib/battery/senseshift/battery/sensor.hpp +++ b/lib/battery/senseshift/battery/sensor.hpp @@ -13,41 +13,47 @@ #endif namespace SenseShift::Battery { - /** - * Abstract battery sensor - */ - using IBatterySensor = ::SenseShift::Input::ISimpleSensor<BatteryState>; + /// Abstract battery sensor + using IBatterySensor = ::SenseShift::Input::Sensor<BatteryState>; + + /// Interpolate voltage according to a lookup table. + template<typename Container> + class LookupTableInterpolateBatterySensor : public IBatterySensor { + static_assert(std::is_same_v<typename Container::key_type, typename BatteryState::VoltageType>); + static_assert(std::is_same_v<typename Container::mapped_type, float>); - class NaiveBatterySensor : public IBatterySensor { public: - explicit NaiveBatterySensor(::SenseShift::Input::IFloatSensor* sensor) : sensor(sensor){}; + using VoltageType = typename BatteryState::VoltageType; + using VoltageSource = ::SenseShift::Input::Sensor<VoltageType>; - [[nodiscard]] auto getValue() -> BatteryState override - { - const auto level = static_cast<std::uint8_t>(this->sensor->getValue() * BatteryState::MAX_LEVEL); + LookupTableInterpolateBatterySensor( + VoltageSource* voltage_source, + Container* lookup_table + ) : IBatterySensor(), voltage_source_(voltage_source), lookup_table_(lookup_table) {} - return { .level = level}; - }; + 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); - void init() override { this->sensor->init(); } + LOG_D("battery.sensor", "voltage=%f, level=%f", voltage, level); - private: - ::SenseShift::Input::IFloatSensor* sensor; - }; + const BatteryState value = { + .level = static_cast<typename BatteryState::LevelType>(level * BatteryState::MAX_LEVEL), + }; - class BatterySensor : public ::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState> { - public: - BatterySensor(::SenseShift::Battery::IBatterySensor* sensor, ::SenseShift::IEventDispatcher* eventDispatcher) : - ::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>(sensor), - eventDispatcher(eventDispatcher){}; - - void tick() override - { - this->::SenseShift::Input::MemoizedSensor<::SenseShift::Battery::BatteryState>::tick(); - this->eventDispatcher->postEvent(new ::SenseShift::Battery::BatteryLevelEvent(this->getValue())); + this->publishState(value); + }); + } + + protected: + [[nodiscard]] auto lookupInterpolateLevel(VoltageType voltage) -> float { + return ::SenseShift::lookup_interpolate<VoltageType, float, Container>(*this->lookup_table_, voltage); } private: - ::SenseShift::IEventDispatcher* eventDispatcher; + VoltageSource* voltage_source_; + Container* lookup_table_; }; } // namespace SenseShift::Battery diff --git a/lib/core/senseshift/core/helpers.hpp b/lib/core/senseshift/core/helpers.hpp index 8a68a2fb..35cfe2a0 100644 --- a/lib/core/senseshift/core/helpers.hpp +++ b/lib/core/senseshift/core/helpers.hpp @@ -1,14 +1,16 @@ #pragma once +#include <functional> #include <type_traits> +#include <vector> namespace SenseShift { - /// @name Mathematics - /// @{ - /// Linearly interpolate between \p start and \p end by \p completion (between 0 and 1). - constexpr auto lerp(const float completion, const float start, const float end) -> float + template<typename Tp> + constexpr auto lerp(const float completion, const Tp start, const Tp end) -> Tp { + static_assert(std::is_arithmetic_v<Tp>, "Type must be arithmetic"); + return start + (end - start) * completion; } @@ -27,13 +29,12 @@ namespace SenseShift { template<typename Tp, typename Up> constexpr auto remap(Up value, Up min, Up max, Tp min_out, Tp max_out) -> Tp { - static_assert(std::is_arithmetic_v<Up>, "Type must be arithmetic"); static_assert(std::is_arithmetic_v<Tp>, "Type must be arithmetic"); + static_assert(std::is_arithmetic_v<Up>, "Type must be arithmetic"); 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. @@ -55,5 +56,68 @@ namespace SenseShift { return value * max_out / max; } - /// @} + /// Lookup a value in a table and interpolate between the two closest values. + /// + /// \tparam Tp + /// \tparam To + /// \tparam Container + /// + /// \param lookup_table Lookup table to use in the format of std::map<Tp, Tp> in descending order. + /// \param value + /// + /// \return + template <typename Tp, typename To, typename Container> + auto lookup_interpolate(Container const& lookup_table, Tp value) -> To + { + static_assert(std::is_same_v<typename Container::key_type, Tp>); + static_assert(std::is_same_v<typename Container::mapped_type, To>); + static_assert(std::is_arithmetic_v<Tp>, "lookup_interpolate only supports arithmetic types"); + static_assert(std::is_arithmetic_v<To>, "lookup_interpolate 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; + } + + // Find the two closest values in the lookup table + auto const upper = lookup_table.lower_bound(value); + auto const lower = std::prev(upper); + + // Interpolate between the two closest values + float const completion = (value - lower->first) / (upper->first - lower->first); + + return lerp(completion, lower->second, upper->second); + } + + template<typename... X> + class CallbackManager; + + /// Helper class to allow having multiple subscribers to a callback. + /// + /// \tparam Ts The arguments for the callbacks, wrapped in void(). + template<typename... Ts> + class CallbackManager<void(Ts...)> { + public: + using CallbackType = std::function<void(Ts...)>; + + /// Add a callback to the list. + void add(std::function<void(Ts...)> &&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...); + } + } + [[nodiscard]] auto size() const -> size_t { return this->callbacks_.size(); } + + /// Call all callbacks in this manager. + void operator()(Ts... args) { call(args...); } + + private: + std::vector<std::function<void(Ts...)>> callbacks_; + }; } // namespace SenseShift \ No newline at end of file diff --git a/lib/freertos/senseshift/freertos/input/sensor.hpp b/lib/freertos/senseshift/freertos/input/sensor.hpp index aa2b12a5..667a2581 100644 --- a/lib/freertos/senseshift/freertos/input/sensor.hpp +++ b/lib/freertos/senseshift/freertos/input/sensor.hpp @@ -6,54 +6,36 @@ #include <cstdint> namespace SenseShift::FreeRTOS::Input { - /** - * Sensor update task - */ - class SensorUpdateTask : public Task<SensorUpdateTask> { - friend class Task<SensorUpdateTask>; - - private: - using Sensor = ::SenseShift::ITickable; + /// Sensor update task + template<typename Sensor> + class SensorUpdateTask : public Task<SensorUpdateTask<Sensor>> { + static_assert(std::is_same_v<decltype(&Sensor::init), void (Sensor::*)()>); + static_assert(std::is_same_v<decltype(&Sensor::tick), void (Sensor::*)()>); public: SensorUpdateTask(Sensor* sensor, std::uint32_t updateDelay, TaskConfig taskConfig) : - Task<SensorUpdateTask>(taskConfig), updateDelay(updateDelay){}; + Task<SensorUpdateTask>(taskConfig), sensor_(sensor), updateDelay_(updateDelay) { + log_i("creating SensorUpdateTask: %s", taskConfig.name); + }; - protected: - Sensor* sensor; - std::uint32_t updateDelay; + void begin() override { + this->sensor_->init(); + this->Task<SensorUpdateTask>::begin(); + } - void run() + protected: + [[noreturn]] void run() { while (true) { - this->sensor->tick(); - ::delay(this->updateDelay); + this->sensor_->tick(); + delay(this->updateDelay_); } } - }; - - template<typename Tp> - class TaskedSensor : public SensorUpdateTask, public ::SenseShift::Input::ISimpleSensor<Tp> { - friend class SensorUpdateTask; private: - using Sensor = ::SenseShift::Input::MemoizedSensor<Tp>; - - public: - TaskedSensor(Sensor* sensor, std::uint32_t updateDelay, TaskConfig taskConfig) : - SensorUpdateTask(sensor, updateDelay, taskConfig), sensor(sensor){}; - - void begin() override - { - this->init(); - SensorUpdateTask::begin(); - }; - - void init() override { this->sensor->init(); }; - - Tp getValue() override { return this->sensor->getValue(); }; + friend class Task<SensorUpdateTask>; - private: - Sensor* sensor; + Sensor* sensor_; + std::uint32_t updateDelay_; }; } // namespace SenseShift::FreeRTOS::Input diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index d06415ea..0cbb1a12 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -39,11 +39,9 @@ namespace SenseShift::FreeRTOS { friend class Task; public: - Task(const char* name, uint32_t stackDepth, UBaseType_t priority, const BaseType_t coreId = tskNO_AFFINITY) - { - this->taskConfig = { name, stackDepth, priority, coreId }; + explicit Task(TaskConfig& config) : taskConfig(config) { + log_i("creating SensorUpdateTask: %s", taskConfig.name); }; - Task(TaskConfig& config) : taskConfig(config){}; virtual ~Task() { if (taskHandle) { @@ -56,15 +54,16 @@ namespace SenseShift::FreeRTOS { 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 + 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); diff --git a/lib/util/senseshift/calibration.hpp b/lib/io/senseshift/input/calibration.hpp similarity index 82% rename from lib/util/senseshift/calibration.hpp rename to lib/io/senseshift/input/calibration.hpp index e1602582..bb8a0113 100644 --- a/lib/util/senseshift/calibration.hpp +++ b/lib/io/senseshift/input/calibration.hpp @@ -5,35 +5,31 @@ #pragma once -#include <senseshift/utility.hpp> +#include "senseshift/utility.hpp" -namespace SenseShift::Calibration { +namespace SenseShift::Input { struct ICalibrated { - virtual void resetCalibration() = 0; - virtual void enableCalibration() = 0; - virtual void disableCalibration() = 0; - }; - - class Calibrated : public virtual ICalibrated { - bool calibrate_ = false; - - public: - void resetCalibration() override = 0; - void enableCalibration() override { calibrate_ = true; } - void disableCalibration() override { calibrate_ = false; } + virtual void startCalibration() = 0; + virtual void stopCalibration() = 0; + virtual void reselCalibration() = 0; }; template<typename Tp> struct ICalibrator { - static_assert(std::is_arithmetic_v<Tp>, "ICalibrator only can be used with arithmetic types"); - + /// Reset the calibration. virtual void reset() = 0; + + /// Update the calibration with a new input value. virtual void update(Tp input) = 0; - virtual auto calibrate(Tp input) const -> Tp = 0; + + /// Calibrate the input value. + [[nodiscard]] virtual auto calibrate(Tp input) const -> Tp = 0; }; template<typename Tp, Tp output_min, Tp output_max> class MinMaxCalibrator : public ICalibrator<Tp> { + static_assert(std::is_arithmetic_v<Tp>, "MinMaxCalibrator only can be used with arithmetic types"); + public: using ValueType = Tp; @@ -83,6 +79,8 @@ namespace SenseShift::Calibration { template<typename Tp, Tp sensor_max, Tp driver_max_deviation, Tp output_min, Tp output_max> class CenterPointDeviationCalibrator : public ICalibrator<Tp> { + static_assert(std::is_arithmetic_v<Tp>, "CenterPointDeviationCalibrator only can be used with arithmetic types"); + public: using ValueType = Tp; @@ -104,7 +102,7 @@ namespace SenseShift::Calibration { } auto calibrate(ValueType input) const -> ValueType override { - // Find the center point of the sensor so we know how much we have deviated from it. + // Find the center point of the sensor, so we know how much we have deviated from it. Tp center = (range_min + range_max) / 2.0F; // Map the input to the sensor range of motion. @@ -130,6 +128,8 @@ namespace SenseShift::Calibration { template<typename Tp, Tp sensor_max, Tp driver_max_deviation, Tp output_min, Tp output_max> class FixedCenterPointDeviationCalibrator : public ICalibrator<Tp> { + static_assert(std::is_arithmetic_v<Tp>, "FixedCenterPointDeviationCalibrator only can be used with arithmetic types"); + public: using ValueType = Tp; @@ -137,7 +137,7 @@ namespace SenseShift::Calibration { 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. + // Find the center point of the sensor, so we know how much we have deviated from it. Tp center = sensor_max / 2.0F; // Map the input to the sensor range of motion. @@ -156,4 +156,4 @@ namespace SenseShift::Calibration { ); } }; -} // namespace SenseShift::Calibration +} // namespace SenseShift::Input diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp new file mode 100644 index 00000000..81b5b5d3 --- /dev/null +++ b/lib/io/senseshift/input/filter.hpp @@ -0,0 +1,284 @@ +#pragma once + +#include <algorithm> +#include <array> +#include <cstdint> +#include <cstdlib> +#include <deque> +#include <functional> +#include <type_traits> +#include <utility> +#include <vector> + +#include <senseshift/core/helpers.hpp> + +namespace SenseShift::Input { + template<typename Tp> + class ISimpleSensor; + + template<typename Tp> + class Sensor; + + template<typename Tp> + class IFilter { + public: + using ValueType = Tp; + + virtual auto filter(ISimpleSensor<ValueType>* sensor, ValueType value) -> ValueType = 0; + }; + + template<typename Tp> + class AddFilter : public IFilter<Tp> { + public: + explicit AddFilter(Tp offset) : offset_(offset){}; + + auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override + { + return value + this->offset_; + } + + private: + Tp offset_; + }; + + template<typename Tp> + class IFiltered { + public: + using ValueType = Tp; + + virtual void addFilter(IFilter<ValueType>* filter) = 0; + + virtual void addFilters(std::vector<IFilter<ValueType>*> filters) = 0; + + virtual void setFilters(std::vector<IFilter<ValueType>*> filters) = 0; + + void clearFilters() = 0; + }; + + template<typename Tp> + class SubtractFilter : public IFilter<Tp> { + public: + explicit SubtractFilter(Tp offset) : offset_(offset){}; + + auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override + { + return value - this->offset_; + } + + private: + Tp offset_; + }; + + template<typename Tp> + class MultiplyFilter : public IFilter<Tp> { + public: + explicit MultiplyFilter(Tp factor) : factor_(factor){}; + + auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override + { + return value * this->factor_; + } + + private: + Tp factor_; + }; + + class VoltageDividerFilter : public MultiplyFilter<float> { + public: + /// \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<float>(r2 / (r1 + r2)){}; + }; + + template<typename Tp> + class ClampFilter : public IFilter<Tp> { + public: + ClampFilter(Tp min, Tp max) : min_(min), max_(max){}; + + auto filter(ISimpleSensor<Tp>* /*source*/, Tp value) -> Tp override + { + return std::clamp(value, this->min_, this->max_); + } + + private: + Tp min_; + Tp max_; + }; + + /// An alias for ClampFilter. + template<typename Tp> + using MinMaxFilter = ClampFilter<Tp>; + + /// An alias for ClampFilter. + template<typename Tp> + using RangeFilter = ClampFilter<Tp>; + + template<typename Tp> + class LambdaFilter : public IFilter<Tp> { + public: + using Lambda = std::function<Tp(Tp)>; + + explicit LambdaFilter(Lambda filter) : filter_(std::move(filter)) {}; + + auto filter(ISimpleSensor<Tp>* /*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<typename Tp, typename Sensor> + class SampleAverageFilter : public IFilter<Tp> { + static_assert(std::is_arithmetic_v<Tp>, "SampleAverageFilter only supports arithmetic types"); + static_assert(std::is_same_v<typename Sensor::ValueType, Tp>, "Sensor type must match filter type"); + static_assert(std::is_same_v<decltype(&Sensor::readRawValue), void (Sensor::*)()>, "Can only use sensors with readRawValue()"); + + public: + explicit SampleAverageFilter(std::size_t size) : size_(size){}; + + auto filter(ISimpleSensor<Tp>* 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<std::size_t N, typename Tp, typename Sensor> + class SampleMedianFilter : public IFilter<Tp> { + static_assert(N % 2 == 1, "SampleMedianFilter only supports odd sample sizes"); + static_assert(std::is_same_v<typename Sensor::ValueType, Tp>, "Sensor type must match filter type"); + static_assert(std::is_same_v<decltype(&Sensor::readRawValue), void (Sensor::*)()>, "Can only use sensors with readRawValue()"); + + public: + explicit SampleMedianFilter() = default; + + auto filter(ISimpleSensor<Tp>* sensor, Tp value) -> Tp override + { + this->values = { 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->readRawValue(); + } + + // Sort the array. + std::sort(this->values.begin(), this->values.end()); + + // Return the median of the values. + return this->values[this->size_ / 2]; + } + + private: + std::array<Tp, N> values_; + }; + + template<typename Tp> + class SlidingWindowMovingAverageFilter : public IFilter<Tp> { + static_assert(std::is_arithmetic_v<Tp>, "SlidingWindowAverageFilter only supports arithmetic types"); + + public: + explicit SlidingWindowMovingAverageFilter(size_t window_size) : window_size_(window_size) { }; + + auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override + { + while (this->queue_.size() >= this->window_size_) { + this->queue_.pop_front(); + } + this->queue_.push_back(value); + + return this->getAverage(); + } + + private: + std::size_t window_size_; + std::deque<Tp> values_; + + [[nodiscard]] auto getAverage() const -> Tp + { + Tp sum = 0; + for (auto value : this->queue_) { + sum += value; + } + return sum / this->queue_.size(); + } + }; + + template<typename Tp> + class ExponentialMovingAverageFilter : public IFilter<Tp> { + static_assert(std::is_arithmetic_v<Tp>, "ExponentialMovingAverageFilter only supports arithmetic types"); + + public: + explicit ExponentialMovingAverageFilter(float alpha) : alpha_(alpha) { }; + + auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override + { + this->acc_ = this->alpha_ * value + (1 - this->alpha_) * this->acc_; + + return this->acc_; + } + + private: + 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<float> + { + public: + explicit CenterDeadzoneFilter(float deadzone) : deadzone_(deadzone){}; + + auto filter(ISimpleSensor<float>* /*sensor*/, float value) -> float override + { + float const deviation = std::abs(CENTER - value); + return deviation < deadzone_ ? CENTER : value; + } + + private: + static constexpr float CENTER = 0.5F; + + float deadzone_; + }; + + /// \tparam Container Type of the lookup table container. + template <typename Tp, typename Container> + class LookupTableInterpolationFilter : public IFilter<Tp> + { + static_assert(std::is_same_v<typename Container::value_type, Tp>); + static_assert(std::is_arithmetic_v<Tp>, "LookupTableInterpolationFilter only supports arithmetic types"); + + public: + explicit LookupTableInterpolationFilter(Container const& lookup_table) : lookup_table_(lookup_table) {}; + + auto filter(ISimpleSensor<float>* /*sensor*/, Tp value) -> Tp override + { + return SenseShift::lookup_interpolate<Tp, Container>(this->lookup_table_, value); + } + + private: + Container const& lookup_table_; + }; +} // namespace SenseShift::Input \ No newline at end of file diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index a8302172..c3fb8d02 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -1,20 +1,14 @@ #pragma once #include <type_traits> +#include <vector> +#include <optional> -#include <senseshift/calibration.hpp> -#include <senseshift/core/component.hpp> +#include "senseshift/input/filter.hpp" +#include "senseshift/input/calibration.hpp" -#if defined(__AVR__) -#define ANALOG_MAX 1023 -#elif defined(ESP32) -#define ANALOG_MAX 4095 -#elif !defined(ANALOG_MAX) -#warning "This board doesn't have an auto ANALOG_MAX assignment, please set it manually" -#define ANALOG_MAX static_assert(false, "ANALOG_MAX is not defined") -// Uncomment and set as needed (only touch if you know what you are doing) -// #define ANALOG_MAX 4095 -#endif +#include <senseshift/core/component.hpp> +#include <senseshift/core/helpers.hpp> namespace SenseShift::Input { /// Abstract hardware sensor (e.g. potentiometer, flex sensor, etc.) @@ -24,148 +18,219 @@ namespace SenseShift::Input { public: using ValueType = Tp; - /// Get the current sensor value + explicit ISimpleSensor() = default; + + /// Get the current sensor value. [[nodiscard]] virtual auto getValue() -> ValueType = 0; }; - using IBinarySensor = ISimpleSensor<bool>; - using IFloatSensor = ISimpleSensor<float>; + using IBinarySimpleSensor = ISimpleSensor<bool>; + using IFloatSimpleSensor = ISimpleSensor<float>; template<typename Tp> - class ISensor : public virtual ISimpleSensor<Tp>, public ITickable {}; + class ISensor : public virtual ISimpleSensor<Tp>, public ICalibrated {}; - /// Memoized sensor decorator. Stores the last read value and returns it on subsequent calls - /// \tparam Tp Type of the sensor value template<typename Tp> - class MemoizedSensor : public ISensor<Tp> { + class Sensor : public ISensor<Tp> { public: using ValueType = Tp; + using CallbackManagerType = CallbackManager<void(ValueType)>; + using CallbackType = typename CallbackManagerType::CallbackType; + + explicit Sensor() = default; + + /// Appends a filter to the sensor's filter chain. + /// + /// \param filter The filter to add. + /// + /// \see addFilters for adding multiple filters. + void addFilter(IFilter<ValueType>* 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<IFilter<ValueType>*> filters) { + this->filters_.insert(this->filters_.end(), filters.begin(), filters.end()); + } - /// \param sensor Sensor to be decorated - explicit MemoizedSensor(ISimpleSensor<ValueType>* sensor) : sensor_(sensor){} + /// 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<IFilter<ValueType>*> filters) { this->filters_ = filters; } - /** - * Setup the sensor hardware - */ - void init() override { this->sensor_->init(); } + /// Removes everything from the sensor's filter chain. + void clearFilters() { this->filters_.clear(); } - /** - * Read actual value from the hardware and memoize it - */ - void tick() override { this->value_ = this->sensor_->getValue(); } + void setCalibrator(ICalibrator<ValueType>* calibrator) { this->calibrator_ = calibrator; } - /** - * Get the current memoized value - */ - [[nodiscard]] auto getValue() -> ValueType override { return this->value_; } + void clearCalibrator() { this->calibrator_ = std::nullopt; } - private: - ISimpleSensor<ValueType>* sensor_; - ValueType value_; - }; - - template<typename Tp> - class ICalibratedSimpleSensor : public ISimpleSensor<Tp>, public Calibration::ICalibrated {}; + void startCalibration() override { this->is_calibrating_ = true; } - /// Calibrated sensor decorator - /// \tparam Tp Type of the sensor value - template<typename Tp> - class CalibratedSimpleSensor : public ICalibratedSimpleSensor<Tp> { - public: - using ValueType = Tp; + void stopCalibration() override { this->is_calibrating_ = false; } - /// \param sensor Sensor to be decorated - /// \param calibrator ICalibrator algorithm to be used - CalibratedSimpleSensor(ISimpleSensor<ValueType>* sensor, Calibration::ICalibrator<ValueType>* calibrator) : - sensor_(sensor), calibrator_(calibrator){}; + void reselCalibration() override { + if (this->calibrator_.has_value()) { + this->calibrator_.value()->reset(); + } + } - void init() override { this->sensor_->init(); }; - [[nodiscard]] auto getValue() -> ValueType override { return this->getCalibratedValue(); }; + void addValueCallback(CallbackType &&callback) { this->callback_.add(std::move(callback)); } - void resetCalibration() override { this->calibrator_->reset(); }; - void enableCalibration() override { is_calibrating_ = true; } - void disableCalibration() override { is_calibrating_ = false; } + void addRawValueCallback(CallbackType &&callback) { this->raw_callback_.add(std::move(callback)); } - protected: - [[nodiscard]] auto getCalibratedValue() -> ValueType - { - auto value = this->sensor_->getValue(); + void init() override { } - if (this->is_calibrating_) { - this->calibrator_->update(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_callback_.call(this->raw_value_); - return this->calibrator_->calibrate(value); + this->value_ = this->applyFilters(rawValue); + this->callback_.call(this->value_); } - private: - ISimpleSensor<ValueType>* sensor_; - Calibration::ICalibrator<ValueType>* calibrator_; - bool is_calibrating_ = false; - }; - - /// A sensor that returns the average value of N samples. - /// \tparam Tp Type of the sensor value - template<typename Tp> - class AverageSensor : public ISimpleSensor<Tp> { - static_assert(std::is_arithmetic_v<Tp>, "AverageSensor only supports arithmetic types"); + /// Get the current sensor .value_. + [[nodiscard]] auto getValue() -> ValueType override { + return this->value_; + } - public: - using ValueType = Tp; + /// Get the current raw sensor .raw_value_. + [[nodiscard]] auto getRawValue() -> ValueType { + return this->raw_value_; + } - /// \param sensor Sensor to be decorated - /// \param samples Number of samples to be used - AverageSensor(ISimpleSensor<ValueType>* sensor, const size_t samples) : sensor_(sensor), samples_(samples) {} + protected: + /// Apply current filters to value. + [[nodiscard]] auto applyFilters(ValueType value) -> ValueType { + /// Apply filters + for (auto filter : this->filters_) { + value = filter->filter(this, value); + } - void init() override { this->sensor_->init(); }; + /// Apply calibration + if (this->calibrator_.has_value()) { + if (this->is_calibrating_) { + this->calibrator_.value()->update(value); + } - [[nodiscard]] auto getValue() const -> ValueType override - { - // TODO: another type for sum? - double sum = 0; - for (size_t i = 0; i < this->samples_; i++) { - sum += this->sensor_->getValue(); + value = this->calibrator_.value()->calibrate(value); } - return sum / this->samples_; + return value; } private: - ISimpleSensor<ValueType>* sensor_; - size_t samples_; + friend class IFilter<ValueType>; + friend class ICalibrator<ValueType>; + + /// The sensor's filter chain. + std::vector<IFilter<ValueType>*> filters_ = std::vector<IFilter<ValueType>*>(); + + bool is_calibrating_ = false; + std::optional<ICalibrator<ValueType>*> calibrator_ = std::nullopt; + + ValueType raw_value_; + ValueType value_; + + /// Storage for raw state callbacks. + CallbackManagerType raw_callback_; + /// Storage for filtered state callbacks. + CallbackManagerType callback_; }; - /// A sensor that returns the median value of N samples. - /// \tparam Tp Type of the sensor value - /// \tparam NumSamples Number of samples to be used - template<typename Tp, size_t NumSamples> - class StaticMedianSensor : public ISimpleSensor<Tp> { - static_assert(std::is_arithmetic_v<Tp>, "StaticMedianSensor only supports arithmetic types"); - static_assert(NumSamples % 2 == 1, "StaticMedianSensor only supports odd sample sizes"); + using FloatSensor = Sensor<float>; + using BinarySensor = Sensor<bool>; + template<typename Tp> + class SimpleSensorDecorator : public Sensor<Tp>, public ITickable + { public: using ValueType = Tp; + using SourceType = ISimpleSensor<ValueType>; - explicit StaticMedianSensor(ISimpleSensor<ValueType>* sensor) : sensor_(sensor) {} + explicit SimpleSensorDecorator(SourceType* source) : source_(source) {} - void init() override { this->sensor_->init(); }; + void init() override { + this->source_->init(); + } - [[nodiscard]] auto getValue() -> ValueType override - { - for (size_t i = 0; i < NumSamples; i++) { - this->values_[i] = this->sensor_->getValue(); - } + void tick() override { + this->updateValue(); + } - std::sort(this->values_.begin(), this->values_.end()); + auto updateValue() -> ValueType { + auto const raw_value = this->readRawValue(); + this->publishState(raw_value); - return this->values_[NumSamples / 2]; + LOG_D("decorator.simple", " raw_value=%f, value=%f", raw_value, this->getValue()); + + return this->getValue(); } - private: - /// Buffer to store the last N samples. - /// We are using a static array to avoid dynamic allocation - std::array<ValueType, NumSamples> values_; + [[nodiscard]] auto readRawValue() -> ValueType { + return this->source_->getValue(); + } - ISimpleSensor<Tp>* sensor_; + private: + SourceType* source_; }; + +// template<typename Tp> +// class SensorDecorator : public Sensor<Tp> +// { +// public: +// using ValueType = Tp; +// using SourceType = Sensor<ValueType>; +// +// explicit SensorDecorator(SourceType* source) : source_(source) {} +// +// void init() override { +// this->source_->init(); +// this->source_->addValueCallback([this](ValueType value) { +// this->publishState(value); +// }); +// } +// +// void startCalibration() override { +// this->source_->startCalibration(); +// } +// +// void stopCalibration() override { +// this->source_->stopCalibration(); +// } +// +// void reselCalibration() override { +// this->source_->reselCalibration(); +// } +// +// private: +// SourceType* source_; +// }; + + namespace _private { + class TheFloatSensor : public Sensor<float> { }; + } } // namespace SenseShift::Input diff --git a/lib/io/senseshift/input/sensor/joystick.hpp b/lib/io/senseshift/input/sensor/joystick.hpp deleted file mode 100644 index 0dd95dfe..00000000 --- a/lib/io/senseshift/input/sensor/joystick.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "senseshift/input/sensor.hpp" - -namespace SenseShift::Input { - /** - * Joystick axis sensor decorator - */ - template<typename Tp> - class JoystickAxisSensor : public ISimpleSensor<Tp> { - public: - using ValueType = Tp; - - private: - ISimpleSensor<ValueType>* sensor_; - float dead_zone_; - - /// This function clamps the input to the center of the range if - /// the value is within the threshold. This is to eliminate at-rest - /// noise of the joystick. - [[nodiscard]] auto filterDeadZone(const int value_in) const -> ValueType { - constexpr ValueType center = ANALOG_MAX / 2; - return abs(center - value_in) < dead_zone_ * ANALOG_MAX ? center : value_in; - } - - public: - JoystickAxisSensor(ISimpleSensor<Tp>* sensor, const float dead_zone) : sensor_(sensor), dead_zone_(dead_zone){}; - - void init() override { this->sensor_->init(); }; - - [[nodiscard]] auto getValue() -> uint16_t override - { - auto value = this->sensor_->getValue(); - value = this->filterDeadZone(value); - return value; - } - }; -}; // namespace SenseShift::Input diff --git a/lib/opengloves/senseshift/opengloves/interface.hpp b/lib/opengloves/senseshift/opengloves/interface.hpp index 5e94b1e9..ba7ba8e0 100644 --- a/lib/opengloves/senseshift/opengloves/interface.hpp +++ b/lib/opengloves/senseshift/opengloves/interface.hpp @@ -2,6 +2,7 @@ #include <cstddef> #include <cstdint> +#include <vector> #include <senseshift/buffer.hpp> @@ -10,17 +11,26 @@ namespace SenseShift::OpenGloves { struct ITransport { virtual void setup(){}; - virtual size_t send(const char* buffer, size_t length) = 0; - virtual bool hasData() = 0; - virtual size_t read(char* buffer, size_t length) = 0; + 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; }; struct IEncoding { - virtual size_t - serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors, char* buffer) const = 0; + /// \param [in] sensors + /// \param [out] buffer + virtual auto serialize( + const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors, + char* buffer + ) const -> size_t = 0; - virtual bool deserialize( - const char* buffer, const size_t length, std::map<::OpenGloves::Command, uint16_t>& commands - ) const = 0; + /// \param [in] buffer + /// \param [in] length + /// \param [out] commands + virtual auto deserialize( + const char* buffer, + size_t length, + std::map<::OpenGloves::Command, uint16_t>& commands + ) const -> bool = 0; }; } // namespace SenseShift::OpenGloves diff --git a/lib/opengloves/sensor/og_sensor.hpp b/lib/opengloves/sensor/og_sensor.hpp index 6b95f0c1..e43dba74 100644 --- a/lib/opengloves/sensor/og_sensor.hpp +++ b/lib/opengloves/sensor/og_sensor.hpp @@ -1,25 +1,26 @@ #pragma once -#include <og_protocol.hpp> -#include <senseshift/input/sensor.hpp> - +#include <cstdint> #include <optional> #include <vector> +#include <og_protocol.hpp> +#include <senseshift/input/sensor.hpp> + namespace OpenGloves { struct FingerValue { - std::vector<uint16_t> curl = std::vector<uint16_t>({ 0 }); - std::optional<uint16_t> splay = std::nullopt; + std::vector<std::uint16_t> curl = std::vector<std::uint16_t>({ 0 }); + std::optional<std::uint16_t> splay = std::nullopt; - uint16_t getTotalCurl() const + [[nodiscard]] auto getTotalCurl() const -> std::uint16_t { - if (this->curl.size() == 0) { + if (this->curl.empty()) { return 0; } - uint16_t total = 0; - for (auto curl : this->curl) { - total += curl; + std::uint16_t total = 0; + for (auto c_curl : this->curl) { + total += c_curl; } return total / this->curl.size(); } @@ -35,69 +36,10 @@ namespace OpenGloves { void init() override { this->getSensor()->init(); } - void updateValue() override { this->value = this->sensor_->getValue(); } + void updateValue() override { this->value_ = this->sensor_->getValue(); } [[nodiscard]] size_t getEncodedLength() const override; size_t encodeString(char* buffer) override; }; - - template<> - inline size_t StringEncodedMemoizedSensor<uint16_t>::getEncodedLength() const - { - return 6; - } - - /// Format as "Axxxx", where A is the type and xxxxx is the value without leading zeros. - template<> - inline size_t StringEncodedMemoizedSensor<uint16_t>::encodeString(char* buffer) - { - return snprintf(buffer, this->getEncodedLength(), "%c%d", this->getType(), this->getValue()); - } - - template<> - size_t StringEncodedMemoizedSensor<bool>::getEncodedLength() const - { - return 1; - } - - template<> - size_t StringEncodedMemoizedSensor<bool>::encodeString(char* buffer) - { - const auto value = this->getValue(); - - if (value) { - buffer[0] = this->getType(); - } - - return value ? this->getEncodedLength() : 0; - } - - template<> - size_t StringEncodedMemoizedSensor<FingerValue>::getEncodedLength() const - { - // curl + splay + (3 * knuckle) - return 6 + 9 + (3 * 10); - } - - template<> - size_t StringEncodedMemoizedSensor<FingerValue>::encodeString(char* buffer) - { - size_t offset = 0; - offset += snprintf(buffer + offset, 6, "%c%d", this->type, this->getValue().getTotalCurl()); - - if (this->getValue().curl.size() > 1) { - for (size_t i = 0; i < this->getValue().curl.size(); i++) { - char knuckle = 'A' + i; - offset += snprintf(buffer + offset, 10, "(%cA%c)%d", this->type, knuckle, this->getValue().curl[i]); - } - } - - if (this->getValue().splay.has_value()) { - offset += snprintf(buffer + offset, 9, "(%cB)%d", this->type, this->getValue().splay.value()); - } - - return offset; - } - } // namespace OpenGloves diff --git a/test/test_util_calibration/main.cpp b/test/test_util_calibration/main.cpp index 1fa42a23..ddc9d2b8 100644 --- a/test/test_util_calibration/main.cpp +++ b/test/test_util_calibration/main.cpp @@ -1,4 +1,4 @@ -#include <senseshift/calibration.hpp> +#include "senseshift/input/calibration.hpp" #include <unity.h> using namespace SenseShift::Calibration; From fa661e7d918f8c17b632f4e0a752fc3871431c56 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Fri, 2 Feb 2024 00:12:15 +0400 Subject: [PATCH 52/82] refactor: improve overall code readability --- firmware/mode_configs/bhaptics/tactal.cpp | 1 + firmware/mode_configs/bhaptics/tactglove.cpp | 1 + firmware/mode_configs/bhaptics/tactosy2.cpp | 1 + firmware/mode_configs/bhaptics/tactosyf.cpp | 1 + firmware/mode_configs/bhaptics/tactosyh.cpp | 1 + .../mode_configs/bhaptics/tactsuit_x16.cpp | 1 + .../bhaptics/tactsuit_x16_pca9685.cpp | 1 + .../mode_configs/bhaptics/tactsuit_x40.cpp | 1 + firmware/mode_configs/bhaptics/tactvisor.cpp | 1 + .../input/sensor/{binary.hpp => digital.hpp} | 8 +- lib/core/senseshift/core/helpers.hpp | 7 +- .../senseshift/freertos/input/sensor.hpp | 1 + lib/freertos/senseshift/freertos/task.hpp | 30 +++ .../senseshift/body/hands/hands_interface.hpp | 25 ++ .../senseshift/body/hands/input/gesture.hpp | 105 ++++++++ .../body/hands/input/total_curl.hpp | 53 ++++ lib/haptics/senseshift/body/haptics/body.cpp | 6 +- lib/haptics/senseshift/body/haptics/body.hpp | 10 + .../senseshift/body/haptics/interface.hpp | 2 +- lib/io/senseshift/input/calibration.hpp | 22 +- lib/io/senseshift/input/filter.hpp | 36 ++- lib/io/senseshift/input/sensor.hpp | 79 ++++-- .../senseshift/opengloves/constants.hpp | 7 + lib/util/senseshift/container.hpp | 17 +- test/test_bhaptics_encoding/main.cpp | 227 +++++++++--------- test/test_haptics_body/main.cpp | 62 ++--- test/test_haptics_plane/main.cpp | 106 ++++---- test/test_io_sensor/main.cpp | 79 +++--- test/test_opengloves_gesture/main.cpp | 2 +- 29 files changed, 587 insertions(+), 306 deletions(-) rename lib/arduino/senseshift/arduino/input/sensor/{binary.hpp => digital.hpp} (62%) create mode 100644 lib/hands/senseshift/body/hands/hands_interface.hpp create mode 100644 lib/hands_input/senseshift/body/hands/input/gesture.hpp create mode 100644 lib/hands_input/senseshift/body/hands/input/total_curl.hpp create mode 100644 lib/opengloves/senseshift/opengloves/constants.hpp diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index e81c311d..6be10fed 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -16,6 +16,7 @@ using namespace SenseShift; using namespace SenseShift::Input; +using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 2cca8354..874cd07a 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -17,6 +17,7 @@ using namespace SenseShift; using namespace SenseShift::Input; +using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index fb20ce80..572e52ad 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -16,6 +16,7 @@ using namespace SenseShift; using namespace SenseShift::Input; +using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index cc623ce2..51b67d9f 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -16,6 +16,7 @@ using namespace SenseShift; using namespace SenseShift::Input; +using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 05e6ba9f..277dcb0d 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -16,6 +16,7 @@ using namespace SenseShift; using namespace SenseShift::Input; +using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index f828ec19..5ba9322c 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -16,6 +16,7 @@ using namespace SenseShift; using namespace SenseShift::Input; +using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index b1066077..256222a8 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -16,6 +16,7 @@ using namespace SenseShift; using namespace SenseShift::Input; +using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 48ea44ee..0057140f 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -17,6 +17,7 @@ using namespace SenseShift; using namespace SenseShift::Input; +using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index d5c7565c..f47cf4f5 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -16,6 +16,7 @@ using namespace SenseShift; using namespace SenseShift::Input; +using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; diff --git a/lib/arduino/senseshift/arduino/input/sensor/binary.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp similarity index 62% rename from lib/arduino/senseshift/arduino/input/sensor/binary.hpp rename to lib/arduino/senseshift/arduino/input/sensor/digital.hpp index 44783b98..9a3d101c 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/binary.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -6,11 +6,11 @@ namespace SenseShift::Arduino::Input { template<bool Invert = false> - class BinarySensor : public IBinarySensor { + class DigitalSimpleSensor : public ::SenseShift::Input::IBinarySimpleSensor { uint8_t pin_; public: - BinarySensor(const uint8_t pin) : pin_(pin) {} + DigitalSimpleSensor(const uint8_t pin) : pin_(pin) {} void init() override { pinMode(this->pin_, INPUT_PULLUP); }; @@ -18,12 +18,12 @@ namespace SenseShift::Arduino::Input { }; template<> - [[nodiscard]] inline auto BinarySensor<false>::getValue() -> bool { + [[nodiscard]] inline auto DigitalSimpleSensor<false>::getValue() -> bool { return digitalRead(this->pin_) == LOW; } template<> - [[nodiscard]] inline auto BinarySensor<true>::getValue() -> bool { + [[nodiscard]] inline auto DigitalSimpleSensor<true>::getValue() -> bool { return digitalRead(this->pin_) == HIGH; } } // namespace SenseShift::Arduino::Input diff --git a/lib/core/senseshift/core/helpers.hpp b/lib/core/senseshift/core/helpers.hpp index 35cfe2a0..f15909e9 100644 --- a/lib/core/senseshift/core/helpers.hpp +++ b/lib/core/senseshift/core/helpers.hpp @@ -32,6 +32,11 @@ namespace SenseShift { static_assert(std::is_arithmetic_v<Tp>, "Type must be arithmetic"); static_assert(std::is_arithmetic_v<Up>, "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; } @@ -120,4 +125,4 @@ namespace SenseShift { private: std::vector<std::function<void(Ts...)>> callbacks_; }; -} // namespace SenseShift \ No newline at end of file +} // namespace SenseShift diff --git a/lib/freertos/senseshift/freertos/input/sensor.hpp b/lib/freertos/senseshift/freertos/input/sensor.hpp index 667a2581..fbd34918 100644 --- a/lib/freertos/senseshift/freertos/input/sensor.hpp +++ b/lib/freertos/senseshift/freertos/input/sensor.hpp @@ -29,6 +29,7 @@ namespace SenseShift::FreeRTOS::Input { while (true) { this->sensor_->tick(); delay(this->updateDelay_); + // log_i("high watermark %d", uxTaskGetStackHighWaterMark(NULL)); } } diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index 0cbb1a12..ea7c942a 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -70,6 +70,36 @@ namespace SenseShift::FreeRTOS { } }; + 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 + ); + + 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; diff --git a/lib/hands/senseshift/body/hands/hands_interface.hpp b/lib/hands/senseshift/body/hands/hands_interface.hpp new file mode 100644 index 00000000..4aa48b44 --- /dev/null +++ b/lib/hands/senseshift/body/hands/hands_interface.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include <cstdint> +#include "senseshift/body/haptics/interface.hpp" + +namespace SenseShift::Body { + namespace 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, + }; + + 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 Hands +} // namespace SenseShift::Body diff --git a/lib/hands_input/senseshift/body/hands/input/gesture.hpp b/lib/hands_input/senseshift/body/hands/input/gesture.hpp new file mode 100644 index 00000000..92ca2a94 --- /dev/null +++ b/lib/hands_input/senseshift/body/hands/input/gesture.hpp @@ -0,0 +1,105 @@ +#pragma once + +#include <senseshift/core/component.hpp> +#include <senseshift/input/sensor.hpp> + +namespace SenseShift::Body::Hands::Input { + using Gesture = ::SenseShift::Input::BinarySensor; + + /// An alias for semantic consistency. + using TriggerGesture = ::SenseShift::Input::AnalogThresholdSensor; + + class GrabGesture : public Gesture, ITickable { + 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) {} + + 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 tick() override { + if (this->attach_callbacks_) { + LOG_E("gesture.grab", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); + } + 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_ + ); + } + + private: + Fingers fingers_; + float threshold_; + bool attach_callbacks_ = false; + }; + + class PinchGesture : public Gesture, ITickable { + public: + struct Fingers { + ::SenseShift::Input::FloatSensor* thumb; + ::SenseShift::Input::FloatSensor* index; + }; + + explicit PinchGesture( + Fingers fingers, + float threshold = 0.5F, + bool attach_callbacks = false + ) : fingers_(fingers), threshold_(threshold), attach_callbacks_(attach_callbacks) {} + + 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 tick() override { + if (this->attach_callbacks_) { + LOG_E("gesture.pinch", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); + } + this->recalculateState(); + } + + 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 \ No newline at end of file diff --git a/lib/hands_input/senseshift/body/hands/input/total_curl.hpp b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp new file mode 100644 index 00000000..678f5b80 --- /dev/null +++ b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include <functional> +#include <utility> +#include <vector> + +#include <senseshift/core/component.hpp> +#include <senseshift/input/sensor.hpp> + +namespace SenseShift::Body::Hands::Input { + class TotalCurl : public ::SenseShift::Input::FloatSensor, public ::SenseShift::ITickable { + public: + /// \param joints The joints to calculate the total curl from. + /// \param attach_callbacks Whether to attach callbacks to the joints to recalculate the total curl when they update. + /// If false, the total curl will only be recalculated when the tick() method is called. + /// Setting this to <b>true is not recommended</b>, 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 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; + + for (auto& joint : this->joints_) { + total += joint.getState(); + } + + if (!this->joints_.empty()) { + this->publishState(total / static_cast<float>(this->joints_.size())); + } + } + + private: + std::vector<::SenseShift::Input::FloatSensor> joints_; + + 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 5caa7beb..bb373d3e 100644 --- a/lib/haptics/senseshift/body/haptics/body.cpp +++ b/lib/haptics/senseshift/body/haptics/body.cpp @@ -10,13 +10,13 @@ namespace SenseShift::Body::Haptics { template<typename Tp, typename Ta> void OutputBody<Tp, Ta>::effect(const Target& target, const Position& pos, const typename Plane::Value& val) { - auto find = this->targets_.find(target); - if (find == this->targets_.end()) { + auto plane = this->getTarget(target); + if (!plane.has_value()) { LOG_W(TAG, "No target found for effect: %d", target); return; } - find->second->effect(pos, val); + plane.value()->effect(pos, val); } template class OutputBody<Position::Value, Output::IFloatOutput::ValueType>; diff --git a/lib/haptics/senseshift/body/haptics/body.hpp b/lib/haptics/senseshift/body/haptics/body.hpp index 6cdd2cbd..6586220a 100644 --- a/lib/haptics/senseshift/body/haptics/body.hpp +++ b/lib/haptics/senseshift/body/haptics/body.hpp @@ -4,6 +4,7 @@ #include "senseshift/body/haptics/plane.hpp" #include <map> +#include <optional> #include <senseshift/output/output.hpp> @@ -32,6 +33,15 @@ namespace SenseShift::Body::Haptics { this->targets_[target] = plane; } + auto getTarget(Target target) -> std::optional<Plane*> { + auto find = this->targets_.find(target); + if (find == this->targets_.end()) { + return std::nullopt; + } + + return find->second; + } + void effect(const Target& target, const Position& pos, const typename Plane::Value& val); [[nodiscard]] 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 89f14cff..f0952fd4 100644 --- a/lib/haptics/senseshift/body/haptics/interface.hpp +++ b/lib/haptics/senseshift/body/haptics/interface.hpp @@ -22,7 +22,7 @@ namespace SenseShift::Body::Haptics { ChestFront = 0x00, ChestBack = 0x01, - // Legacy backword compatibility + // Legacy backward compatibility Accessory [[deprecated]] = 0x02, FaceFront, diff --git a/lib/io/senseshift/input/calibration.hpp b/lib/io/senseshift/input/calibration.hpp index bb8a0113..b9baa95a 100644 --- a/lib/io/senseshift/input/calibration.hpp +++ b/lib/io/senseshift/input/calibration.hpp @@ -7,7 +7,7 @@ #include "senseshift/utility.hpp" -namespace SenseShift::Input { +namespace SenseShift::Input::Calibration { struct ICalibrated { virtual void startCalibration() = 0; virtual void stopCalibration() = 0; @@ -26,18 +26,18 @@ namespace SenseShift::Input { [[nodiscard]] virtual auto calibrate(Tp input) const -> Tp = 0; }; - template<typename Tp, Tp output_min, Tp output_max> + template<typename Tp> class MinMaxCalibrator : public ICalibrator<Tp> { static_assert(std::is_arithmetic_v<Tp>, "MinMaxCalibrator only can be used with arithmetic types"); public: using ValueType = Tp; - MinMaxCalibrator() : value_min_(output_max), value_max_(output_min) {} + MinMaxCalibrator(ValueType output_min, ValueType output_max) : 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; + value_min_ = output_max_; + value_max_ = output_min_; } void update(ValueType input) override { @@ -54,25 +54,27 @@ namespace SenseShift::Input { // 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; + return (output_min_ + output_max_) / 2.0F; } if (input <= value_min_) { - return output_min; + return output_min_; } if (input >= value_max_) { - return output_max; + return output_max_; } // Map the input range to the output range. - ValueType output = ::SenseShift::remap<ValueType, ValueType>(input, value_min_, value_max_, output_min, output_max); + ValueType output = ::SenseShift::remap<ValueType, ValueType>(input, value_min_, value_max_, output_min_, output_max_); // Lock the range to the output. - return std::clamp(output, output_min, output_max); + return std::clamp(output, output_min_, output_max_); } private: + const ValueType output_min_; + const ValueType output_max_; ValueType value_min_; ValueType value_max_; }; diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index 81b5b5d3..a86ef341 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -11,10 +11,16 @@ #include <vector> #include <senseshift/core/helpers.hpp> +#include <senseshift/core/logging.hpp> -namespace SenseShift::Input { +namespace SenseShift::Input::Filter { template<typename Tp> - class ISimpleSensor; + class ISimpleSensor { + public: + using ValueType = Tp; + + virtual auto getValue() -> ValueType = 0; + }; template<typename Tp> class Sensor; @@ -164,34 +170,42 @@ namespace SenseShift::Input { std::size_t size_; }; - template<std::size_t N, typename Tp, typename Sensor> + template<typename Tp, typename Sensor> class SampleMedianFilter : public IFilter<Tp> { - static_assert(N % 2 == 1, "SampleMedianFilter only supports odd sample sizes"); static_assert(std::is_same_v<typename Sensor::ValueType, Tp>, "Sensor type must match filter type"); - static_assert(std::is_same_v<decltype(&Sensor::readRawValue), void (Sensor::*)()>, "Can only use sensors with readRawValue()"); + // static_assert(std::is_same_v<decltype(&Sensor::readRawValue), Tp (Sensor::*)()>, "Can only use sensors with readRawValue()"); public: - explicit SampleMedianFilter() = default; + explicit SampleMedianFilter(std::size_t size_) : size_(size_) { + // allocate the array + this->values = new Tp[size_]; + }; auto filter(ISimpleSensor<Tp>* sensor, Tp value) -> Tp override { - this->values = { value }; + 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->readRawValue(); + this->values[i] = sensor->getValue(); } // Sort the array. - std::sort(this->values.begin(), this->values.end()); + std::sort(this->values, this->values + this->size_); // Return the median of the values. return this->values[this->size_ / 2]; } private: - std::array<Tp, N> values_; + std::size_t size_; + Tp* values; }; template<typename Tp> @@ -281,4 +295,4 @@ namespace SenseShift::Input { private: Container const& lookup_table_; }; -} // namespace SenseShift::Input \ No newline at end of file +} // namespace SenseShift::Input diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index c3fb8d02..86b22868 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -10,6 +10,12 @@ #include <senseshift/core/component.hpp> #include <senseshift/core/helpers.hpp> +#define SS_SUBSENSOR_INIT(SENSOR, ATTACH_CALLBACK, CALLBACK) \ + (SENSOR)->init(); \ + if (ATTACH_CALLBACK) { \ + (SENSOR)->addValueCallback(CALLBACK); \ + } + namespace SenseShift::Input { /// Abstract hardware sensor (e.g. potentiometer, flex sensor, etc.) /// \tparam Tp Type of the sensor value @@ -28,7 +34,7 @@ namespace SenseShift::Input { using IFloatSimpleSensor = ISimpleSensor<float>; template<typename Tp> - class ISensor : public virtual ISimpleSensor<Tp>, public ICalibrated {}; + class ISensor : public virtual ISimpleSensor<Tp>, public Calibration::ICalibrated {}; template<typename Tp> class Sensor : public ISensor<Tp> { @@ -44,7 +50,7 @@ namespace SenseShift::Input { /// \param filter The filter to add. /// /// \see addFilters for adding multiple filters. - void addFilter(IFilter<ValueType>* filter) { this->filters_.push_back(filter); } + void addFilter(Filter::IFilter<ValueType>* filter) { this->filters_.push_back(filter); } /// Adds multiple filters to the sensor's filter chain. Appends to the end of the chain. /// @@ -57,7 +63,7 @@ namespace SenseShift::Input { /// new CenterDeadzoneFilter(0.1f), /// }); /// \endcode - void addFilters(std::vector<IFilter<ValueType>*> filters) { + void addFilters(std::vector<Filter::IFilter<ValueType>*> filters) { this->filters_.insert(this->filters_.end(), filters.begin(), filters.end()); } @@ -72,12 +78,12 @@ namespace SenseShift::Input { /// new CenterDeadzoneFilter(0.1f), /// }); /// \endcode - void setFilters(std::vector<IFilter<ValueType>*> filters) { this->filters_ = filters; } + void setFilters(std::vector<Filter::IFilter<ValueType>*> filters) { this->filters_ = filters; } /// Removes everything from the sensor's filter chain. void clearFilters() { this->filters_.clear(); } - void setCalibrator(ICalibrator<ValueType>* calibrator) { this->calibrator_ = calibrator; } + void setCalibrator(Calibration::ICalibrator<ValueType>* calibrator) { this->calibrator_ = calibrator; } void clearCalibrator() { this->calibrator_ = std::nullopt; } @@ -91,9 +97,9 @@ namespace SenseShift::Input { } } - void addValueCallback(CallbackType &&callback) { this->callback_.add(std::move(callback)); } + void addValueCallback(CallbackType &&callback) { this->callbacks_.add(std::move(callback)); } - void addRawValueCallback(CallbackType &&callback) { this->raw_callback_.add(std::move(callback)); } + void addRawValueCallback(CallbackType &&callback) { this->raw_callbacks_.add(std::move(callback)); } void init() override { } @@ -106,10 +112,10 @@ namespace SenseShift::Input { /// \param rawValue The new .raw_value_. void publishState(ValueType rawValue) { this->raw_value_ = rawValue; - this->raw_callback_.call(this->raw_value_); + this->raw_callbacks_.call(this->raw_value_); this->value_ = this->applyFilters(rawValue); - this->callback_.call(this->value_); + this->callbacks_.call(this->value_); } /// Get the current sensor .value_. @@ -125,11 +131,6 @@ namespace SenseShift::Input { protected: /// Apply current filters to value. [[nodiscard]] auto applyFilters(ValueType value) -> ValueType { - /// Apply filters - for (auto filter : this->filters_) { - value = filter->filter(this, value); - } - /// Apply calibration if (this->calibrator_.has_value()) { if (this->is_calibrating_) { @@ -139,26 +140,31 @@ namespace SenseShift::Input { value = this->calibrator_.value()->calibrate(value); } + /// Apply filters + for (auto filter : this->filters_) { + value = filter->filter(nullptr, value); + } + return value; } private: - friend class IFilter<ValueType>; - friend class ICalibrator<ValueType>; + friend class Filter::IFilter<ValueType>; + friend class Calibration::ICalibrator<ValueType>; /// The sensor's filter chain. - std::vector<IFilter<ValueType>*> filters_ = std::vector<IFilter<ValueType>*>(); + std::vector<Filter::IFilter<ValueType>*> filters_ = std::vector<Filter::IFilter<ValueType>*>(); bool is_calibrating_ = false; - std::optional<ICalibrator<ValueType>*> calibrator_ = std::nullopt; + std::optional<Calibration::ICalibrator<ValueType>*> calibrator_ = std::nullopt; ValueType raw_value_; ValueType value_; /// Storage for raw state callbacks. - CallbackManagerType raw_callback_; + CallbackManagerType raw_callbacks_; /// Storage for filtered state callbacks. - CallbackManagerType callback_; + CallbackManagerType callbacks_; }; using FloatSensor = Sensor<float>; @@ -194,6 +200,8 @@ namespace SenseShift::Input { return this->source_->getValue(); } + protected: + private: SourceType* source_; }; @@ -230,6 +238,37 @@ namespace SenseShift::Input { // SourceType* source_; // }; + class AnalogThresholdSensor : public BinarySensor, ITickable { + public: + explicit AnalogThresholdSensor( + ::SenseShift::Input::FloatSensor* index, + float threshold = 0.5F, + bool attach_callbacks = false + ) : index_(index), threshold_(threshold), attach_callbacks_(attach_callbacks) {} + + void init() override { + SS_SUBSENSOR_INIT(this->index_, this->attach_callbacks_, [this](float /*value*/) { + this->recalculateState(); + }); + } + + 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() { + return this->publishState(this->index_->getValue() > this->threshold_); + } + + private: + ::SenseShift::Input::FloatSensor* index_; + float threshold_; + bool attach_callbacks_ = false; + }; + namespace _private { class TheFloatSensor : public Sensor<float> { }; } diff --git a/lib/opengloves/senseshift/opengloves/constants.hpp b/lib/opengloves/senseshift/opengloves/constants.hpp new file mode 100644 index 00000000..df163940 --- /dev/null +++ b/lib/opengloves/senseshift/opengloves/constants.hpp @@ -0,0 +1,7 @@ +#pragma once + +#define OPENGLOVES_FINGERS_TASK_PRIORITY 1 + +#define OPENGLOVES_COMM_SERIAL 0x1 +#define OPENGLOVES_COMM_BTSERIAL 0x2 +#define OPENGLOVES_COMM_BLESERIAL 0x3 diff --git a/lib/util/senseshift/container.hpp b/lib/util/senseshift/container.hpp index f8da0365..613b962b 100644 --- a/lib/util/senseshift/container.hpp +++ b/lib/util/senseshift/container.hpp @@ -2,6 +2,7 @@ #include <algorithm> #include <iterator> +#include <string> #include <type_traits> namespace SenseShift { @@ -11,29 +12,29 @@ namespace SenseShift { * @tparam _Cp The type of the container. * @tparam _Tp The type of the value. */ - template<class _Cp, typename _Tp> - inline auto contains(const _Cp&& c, const _Tp val) -> bool + template<class Cp, typename Tp> + inline auto contains(Cp&& c, Tp val) -> bool { return std::find(std::begin(c), std::end(c), val) != std::end(c); }; template<> - inline bool contains<std::string&, char>(std::string& s, char val) + inline auto contains<std::string&, char>(std::string& s, char val) -> bool { return s.find(val) != std::string::npos; }; - template<typename _Tp> - inline bool contains(_Tp* begin, _Tp* end, const _Tp& val) + template<typename Tp> + inline auto contains(Tp* begin, Tp* end, const Tp& val) -> bool { return std::find(begin, end, val) != end; }; - template<typename _Tp> - constexpr inline bool contains(const _Tp* arr, const std::size_t size, const _Tp& val) + template<typename Tp> + constexpr inline auto contains(const Tp* arr, const std::size_t size, const Tp& val) -> bool { static_assert( - std::is_same<_Tp, typename std::iterator_traits<_Tp*>::value_type>::value, + std::is_same_v<Tp, typename std::iterator_traits<Tp*>::value_type>, "Container and value must be of the same type" ); return std::find(arr, arr + size, val) != arr + size; diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index 0ff45557..72b70776 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -6,25 +6,28 @@ using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; using namespace SenseShift::Output; -class TestActuator : public IActuator<uint16_t> { +class TestActuator : public IOutput<float> { public: bool isSetup = false; - uint16_t intensity = 0; + float intensity = 0; - TestActuator() : IActuator<uint16_t>() {} - void setup() override { this->isSetup = true; } - void writeOutput(uint16_t intensity) override { this->intensity = intensity; } + TestActuator() : IFloatOutput() {} + void init() override { this->isSetup = true; } + void writeState(float newIntensity) override { this->intensity = newIntensity; } }; +#define ASSERT_EQUAL_FLOAT_ROUNDED(expected, actual, precision) \ + TEST_ASSERT_EQUAL_FLOAT( \ + std::round(expected * std::pow(10, precision)) / std::pow(10, precision), \ + std::round(actual * std::pow(10, precision)) / std::pow(10, precision) \ + ) + void test_layout_tactsuitx16(void) { - static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTSUITX16_SIZE; - static const OutputLayout bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX16; - - static constexpr size_t layoutGroupsSize = BH_LAYOUT_TACTSUITX16_GROUPS_SIZE; - static const uint8_t layoutGroups[layoutGroupsSize] = BH_LAYOUT_TACTSUITX16_GROUPS; + static const std::array<OutputLayout, BH_LAYOUT_TACTSUITX16_SIZE> bhLayout = { BH_LAYOUT_TACTSUITX16 }; + static const std::array<std::uint8_t,BH_LAYOUT_TACTSUITX16_GROUPS_SIZE> layoutGroups = BH_LAYOUT_TACTSUITX16_GROUPS; - auto body = new HapticBody(); + auto body = new FloatBody(); TestActuator* actuator0 = new TestActuator(); TestActuator* actuator1 = new TestActuator(); @@ -43,62 +46,61 @@ void test_layout_tactsuitx16(void) TestActuator* actuator14 = new TestActuator(); TestActuator* actuator15 = new TestActuator(); - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ { actuator0, actuator1, actuator2, actuator3 }, { actuator4, actuator5, actuator6, actuator7 }, }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ { actuator8, actuator9, actuator10, actuator11 }, { actuator12, actuator13, actuator14, actuator15 }, }); - auto frontPlane = new VibroPlane(frontOutputs); - auto backPlane = new VibroPlane(backOutputs); + auto frontPlane = new FloatPlane(frontOutputs); + auto backPlane = new FloatPlane(backOutputs); body->addTarget(Target::ChestFront, frontPlane); body->addTarget(Target::ChestBack, backPlane); // body->setup(); - const uint8_t values[] = { + const std::array<uint8_t, 20> values = { 0x01, 0x00, 0x23, 0x00, 0x00, 0x45, 0x00, 0x67, 0x00, 0x00, 0x89, 0x00, 0xab, 0x00, 0x00, 0xcd, 0x00, 0xef, 0x00, 0x00, }; Decoder::applyVestGrouped(body, values, bhLayout, layoutGroups); - TEST_ASSERT_EQUAL_INT(0, actuator0->intensity); - TEST_ASSERT_EQUAL_INT(273, actuator1->intensity); - TEST_ASSERT_EQUAL_INT(3276, actuator2->intensity); - TEST_ASSERT_EQUAL_INT(3549, actuator3->intensity); - TEST_ASSERT_EQUAL_INT(546, actuator4->intensity); - TEST_ASSERT_EQUAL_INT(819, actuator5->intensity); - TEST_ASSERT_EQUAL_INT(3822, actuator6->intensity); - TEST_ASSERT_EQUAL_INT(4095, actuator7->intensity); - - TEST_ASSERT_EQUAL_INT(1092, actuator8->intensity); - TEST_ASSERT_EQUAL_INT(1365, actuator9->intensity); - TEST_ASSERT_EQUAL_INT(2184, actuator10->intensity); - TEST_ASSERT_EQUAL_INT(2457, actuator11->intensity); - TEST_ASSERT_EQUAL_INT(1638, actuator12->intensity); - TEST_ASSERT_EQUAL_INT(1911, actuator13->intensity); - TEST_ASSERT_EQUAL_INT(2730, actuator14->intensity); - TEST_ASSERT_EQUAL_INT(3003, actuator15->intensity); + ASSERT_EQUAL_FLOAT_ROUNDED(0, actuator0->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(273.0F/4095.0F, actuator1->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F/4095.0F, actuator2->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3549.0F/4095.0F, actuator3->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(546.0F/4095.0F, actuator4->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(819.0F/4095.0F, actuator5->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3822.0F/4095.0F, actuator6->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(4095.0F/4095.0F, actuator7->intensity, 2); + + ASSERT_EQUAL_FLOAT_ROUNDED(1092.0F/4095.0F, actuator8->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1365.0F/4095.0F, actuator9->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2184.0F/4095.0F, actuator10->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2457.0F/4095.0F, actuator11->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1638.0F/4095.0F, actuator12->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1911.0F/4095.0F, actuator13->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2730.0F/4095.0F, actuator14->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3003.0F/4095.0F, actuator15->intensity, 2); } void test_layout_tactsuitx40(void) { - static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTSUITX40_SIZE; - static const OutputLayout bhLayout[bhLayoutSize] = BH_LAYOUT_TACTSUITX40; + static const std::array<OutputLayout, BH_LAYOUT_TACTSUITX40_SIZE> bhLayout = { BH_LAYOUT_TACTSUITX40 }; - auto body = new HapticBody(); + auto body = new FloatBody(); - std::vector<std::vector<VibroPlane::Actuator*>> frontMatrix = { + std::vector<std::vector<FloatPlane::Actuator*>> frontMatrix = { { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, }; - std::vector<std::vector<VibroPlane::Actuator*>> backMatrix = { + std::vector<std::vector<FloatPlane::Actuator*>> backMatrix = { { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, @@ -106,11 +108,11 @@ void test_layout_tactsuitx40(void) { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, }; - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>(frontMatrix); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>(backMatrix); + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>(frontMatrix); + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>(backMatrix); - auto frontPlane = new VibroPlane(frontOutputs); - auto backPlane = new VibroPlane(backOutputs); + auto frontPlane = new FloatPlane(frontOutputs); + auto backPlane = new FloatPlane(backOutputs); body->addTarget(Target::ChestFront, frontPlane); body->addTarget(Target::ChestBack, backPlane); @@ -124,55 +126,54 @@ void test_layout_tactsuitx40(void) }, bhLayout ); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[0][0])->intensity); - TEST_ASSERT_EQUAL_INT(273, static_cast<TestActuator*>(frontMatrix[0][1])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[0][2])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[0][3])->intensity); - TEST_ASSERT_EQUAL_INT(546, static_cast<TestActuator*>(frontMatrix[1][0])->intensity); - TEST_ASSERT_EQUAL_INT(819, static_cast<TestActuator*>(frontMatrix[1][1])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[1][2])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[1][3])->intensity); - TEST_ASSERT_EQUAL_INT(1092, static_cast<TestActuator*>(frontMatrix[2][0])->intensity); - TEST_ASSERT_EQUAL_INT(1365, static_cast<TestActuator*>(frontMatrix[2][1])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[2][2])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[2][3])->intensity); - TEST_ASSERT_EQUAL_INT(1638, static_cast<TestActuator*>(frontMatrix[3][0])->intensity); - TEST_ASSERT_EQUAL_INT(1911, static_cast<TestActuator*>(frontMatrix[3][1])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[3][2])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[3][3])->intensity); - TEST_ASSERT_EQUAL_INT(2184, static_cast<TestActuator*>(frontMatrix[4][0])->intensity); - TEST_ASSERT_EQUAL_INT(2457, static_cast<TestActuator*>(frontMatrix[4][1])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[4][2])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(frontMatrix[4][3])->intensity); - - TEST_ASSERT_EQUAL_INT(2730, static_cast<TestActuator*>(backMatrix[0][0])->intensity); - TEST_ASSERT_EQUAL_INT(3003, static_cast<TestActuator*>(backMatrix[0][1])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[0][2])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[0][3])->intensity); - TEST_ASSERT_EQUAL_INT(3276, static_cast<TestActuator*>(backMatrix[1][0])->intensity); - TEST_ASSERT_EQUAL_INT(3549, static_cast<TestActuator*>(backMatrix[1][1])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[1][2])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[1][3])->intensity); - TEST_ASSERT_EQUAL_INT(3822, static_cast<TestActuator*>(backMatrix[2][0])->intensity); - TEST_ASSERT_EQUAL_INT(4095, static_cast<TestActuator*>(backMatrix[2][1])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[2][2])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[2][3])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[3][0])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[3][1])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[3][2])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[3][3])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[4][0])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[4][1])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[4][2])->intensity); - TEST_ASSERT_EQUAL_INT(0, static_cast<TestActuator*>(backMatrix[4][3])->intensity); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[0][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(273.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[0][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[0][2])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[0][3])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(546.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[1][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(819.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[1][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[1][2])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[1][3])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1092.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[2][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1365.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[2][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[2][2])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[2][3])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1638.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[3][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1911.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[3][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[3][2])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[3][3])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2184.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[4][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2457.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[4][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[4][2])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[4][3])->intensity, 2); + + ASSERT_EQUAL_FLOAT_ROUNDED(2730.0F/4095.0F, static_cast<TestActuator*>(backMatrix[0][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3003.0F/4095.0F, static_cast<TestActuator*>(backMatrix[0][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[0][2])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[0][3])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F/4095.0F, static_cast<TestActuator*>(backMatrix[1][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3549.0F/4095.0F, static_cast<TestActuator*>(backMatrix[1][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[1][2])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[1][3])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3822.0F/4095.0F, static_cast<TestActuator*>(backMatrix[2][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(4095.0F/4095.0F, static_cast<TestActuator*>(backMatrix[2][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[2][2])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[2][3])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[3][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[3][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[3][2])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[3][3])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[4][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[4][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[4][2])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[4][3])->intensity, 2); } void test_layout_tactal(void) { - static constexpr size_t bhLayoutSize = BH_LAYOUT_TACTAL_SIZE; - static const ::SenseShift::Body::Haptics::Position bhLayout[bhLayoutSize] = BH_LAYOUT_TACTAL; + static const std::array<Position, BH_LAYOUT_TACTAL_SIZE> bhLayout = { BH_LAYOUT_TACTAL }; - auto body = new HapticBody(); + auto body = new FloatBody(); TestActuator* actuator0 = new TestActuator(); TestActuator* actuator1 = new TestActuator(); @@ -181,28 +182,28 @@ void test_layout_tactal(void) TestActuator* actuator4 = new TestActuator(); TestActuator* actuator5 = new TestActuator(); - auto outputs = PlaneMapper_Margin::mapMatrixCoordinates<VibroPlane::Actuator>({ + auto outputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator>({ { actuator0, actuator1, actuator2, actuator3, actuator4, actuator5 }, }); - auto plane = new VibroPlane(outputs); + auto plane = new FloatPlane(outputs); body->addTarget(Target::FaceFront, plane); Decoder::applyPlain(body, { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 }, bhLayout, Effect::Vibro, Target::FaceFront); - TEST_ASSERT_EQUAL_INT(4095, actuator0->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator1->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator2->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator3->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator4->intensity); - TEST_ASSERT_EQUAL_INT(0, actuator5->intensity); + ASSERT_EQUAL_FLOAT_ROUNDED(1.0F, actuator0->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, actuator1->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, actuator2->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, actuator3->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, actuator4->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, actuator5->intensity, 2); Decoder::applyPlain(body, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, bhLayout, Effect::Vibro, Target::FaceFront); - TEST_ASSERT_EQUAL_INT(655, actuator0->intensity); - TEST_ASSERT_EQUAL_INT(1310, actuator1->intensity); - TEST_ASSERT_EQUAL_INT(1965, actuator2->intensity); - TEST_ASSERT_EQUAL_INT(2620, actuator3->intensity); - TEST_ASSERT_EQUAL_INT(3276, actuator4->intensity); - TEST_ASSERT_EQUAL_INT(3931, actuator5->intensity); + ASSERT_EQUAL_FLOAT_ROUNDED(0.16F, actuator0->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1310.0F/4095.0F, actuator1->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1965.0F/4095.0F, actuator2->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2620.0F/4095.0F, actuator3->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F/4095.0F, actuator4->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3931.0F/4095.0F, actuator5->intensity, 2); } void test_layout_tactglove(void) @@ -214,7 +215,7 @@ void test_layout_tactglove(void) TestActuator* actuatorLittle = new TestActuator(); TestActuator* actuatorWrist = new TestActuator(); - auto body = new HapticBody(); + auto body = new FloatBody(); const auto& bhLayout = TactGloveLeftLayout; addTactGloveActuators( @@ -229,20 +230,20 @@ void test_layout_tactglove(void) ); Decoder::applyPlain(body, { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 }, bhLayout, Effect::Vibro); - TEST_ASSERT_EQUAL_INT(4095, actuatorThumb->intensity); - TEST_ASSERT_EQUAL_INT(0, actuatorIndex->intensity); - TEST_ASSERT_EQUAL_INT(0, actuatorMiddle->intensity); - TEST_ASSERT_EQUAL_INT(0, actuatorRing->intensity); - TEST_ASSERT_EQUAL_INT(0, actuatorLittle->intensity); - TEST_ASSERT_EQUAL_INT(0, actuatorWrist->intensity); + ASSERT_EQUAL_FLOAT_ROUNDED(4095.0F/4095.0F, actuatorThumb->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, actuatorIndex->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, actuatorMiddle->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, actuatorRing->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, actuatorLittle->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(0, actuatorWrist->intensity, 2); Decoder::applyPlain(body, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, bhLayout, Effect::Vibro); - TEST_ASSERT_EQUAL_INT(655, actuatorThumb->intensity); - TEST_ASSERT_EQUAL_INT(1310, actuatorIndex->intensity); - TEST_ASSERT_EQUAL_INT(1965, actuatorMiddle->intensity); - TEST_ASSERT_EQUAL_INT(2620, actuatorRing->intensity); - TEST_ASSERT_EQUAL_INT(3276, actuatorLittle->intensity); - TEST_ASSERT_EQUAL_INT(3931, actuatorWrist->intensity); + ASSERT_EQUAL_FLOAT_ROUNDED(655.0F/4095.0F, actuatorThumb->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1310.0F/4095.0F, actuatorIndex->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1965.0F/4095.0F, actuatorMiddle->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2620.0F/4095.0F, actuatorRing->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F/4095.0F, actuatorLittle->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3931.0F/4095.0F, actuatorWrist->intensity, 2); } int process(void) diff --git a/test/test_haptics_body/main.cpp b/test/test_haptics_body/main.cpp index 7f00d150..96b39736 100644 --- a/test/test_haptics_body/main.cpp +++ b/test/test_haptics_body/main.cpp @@ -4,27 +4,27 @@ using namespace SenseShift::Body::Haptics; using namespace SenseShift::Output; -class TestActuator : public IActuator<uint16_t> { +class TestActuator : public IOutput<float> { public: bool isSetup = false; - uint16_t intensity = 0; + float intensity = 0; - TestActuator() : IActuator<uint16_t>() {} - void setup() override { this->isSetup = true; } - void writeOutput(uint16_t intensity) override { this->intensity = intensity; } + TestActuator() : IFloatOutput() {} + void init() override { this->isSetup = true; } + void writeState(float newIntensity) override { this->intensity = newIntensity; } }; void test_it_sets_up_planes(void) { - auto body = new HapticBody(); + auto body = new FloatBody(); - VibroPlane::ActuatorMap outputs = { + FloatPlane::ActuatorMap outputs = { { { 0, 0 }, new TestActuator() }, { { 0, 1 }, new TestActuator() }, { { 1, 0 }, new TestActuator() }, { { 1, 1 }, new TestActuator() }, }; - auto plane = new VibroPlane(outputs); + auto plane = new FloatPlane(outputs); body->addTarget(Target::ChestFront, plane); body->setup(); @@ -34,14 +34,14 @@ void test_it_sets_up_planes(void) } } -void test_it_handles_effect__vibro(void) +void test_it_handles_effect(void) { auto actuator1 = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - auto body = new HapticBody(); + auto body = new FloatBody(); - auto plane = new VibroPlane({ + auto plane = new FloatPlane({ { { 0, 0 }, actuator1 }, { { 0, 1 }, actuator2 }, { { 1, 0 }, actuator3 }, @@ -50,35 +50,17 @@ void test_it_handles_effect__vibro(void) body->addTarget(Target::ChestFront, plane); - body->effect({ - .effect = Effect::Vibro, - .target = Target::ChestFront, - .position = { 0, 0 }, - .data = (VibroEffectData) 64, - }); - body->effect({ - .effect = Effect::Vibro, - .target = Target::ChestFront, - .position = { 0, 1 }, - .data = (VibroEffectData) 128, - }); - body->effect({ - .effect = Effect::Vibro, - .target = Target::ChestFront, - .position = { 1, 0 }, - .data = (VibroEffectData) 192, - }); - body->effect({ - .effect = Effect::Vibro, - .target = Target::ChestFront, - .position = { 1, 1 }, - .data = (VibroEffectData) 255, - }); + TEST_ASSERT_TRUE(body->getTarget(Target::ChestFront).has_value()); + + body->effect(Target::ChestFront, { 0, 0 }, 0.25F); + body->effect(Target::ChestFront, { 0, 1 }, 0.5F); + body->effect(Target::ChestFront, { 1, 0 }, 0.75F); + body->effect(Target::ChestFront, { 1, 1 }, 1.0F); - TEST_ASSERT_EQUAL(64, actuator1->intensity); - TEST_ASSERT_EQUAL(128, actuator2->intensity); - TEST_ASSERT_EQUAL(192, actuator3->intensity); - TEST_ASSERT_EQUAL(255, actuator4->intensity); + TEST_ASSERT_EQUAL_FLOAT(0.25F, actuator1->intensity); + TEST_ASSERT_EQUAL_FLOAT(0.5F, actuator2->intensity); + TEST_ASSERT_EQUAL_FLOAT(0.75F, actuator3->intensity); + TEST_ASSERT_EQUAL_FLOAT(1.0F, actuator4->intensity); } int process(void) @@ -86,7 +68,7 @@ int process(void) UNITY_BEGIN(); RUN_TEST(test_it_sets_up_planes); - RUN_TEST(test_it_handles_effect__vibro); + RUN_TEST(test_it_handles_effect); return UNITY_END(); } diff --git a/test/test_haptics_plane/main.cpp b/test/test_haptics_plane/main.cpp index 7c8890cc..a9c329a1 100644 --- a/test/test_haptics_plane/main.cpp +++ b/test/test_haptics_plane/main.cpp @@ -4,26 +4,26 @@ using namespace SenseShift::Body::Haptics; using namespace SenseShift::Output; -class TestActuator : public IActuator<uint16_t> { +class TestActuator : public IOutput<float> { public: bool isSetup = false; - uint16_t intensity = 0; + float intensity = 0; - TestActuator() : IActuator<uint16_t>() {} - void setup() override { this->isSetup = true; } - void writeOutput(uint16_t intensity) override { this->intensity = intensity; } + TestActuator() : IFloatOutput() {} + void init() override { this->isSetup = true; } + void writeState(float newIntensity) override { this->intensity = newIntensity; } }; void test_it_sets_up_actuators(void) { - VibroPlane::ActuatorMap outputs = { + FloatPlane::ActuatorMap outputs = { { { 0, 0 }, new TestActuator() }, { { 0, 1 }, new TestActuator() }, { { 1, 0 }, new TestActuator() }, { { 1, 1 }, new TestActuator() }, }; - auto plane = new VibroPlane(outputs); + auto plane = new FloatPlane(outputs); plane->setup(); TEST_ASSERT_EQUAL(outputs.size(), plane->getAvailablePoints()->size()); @@ -39,24 +39,24 @@ void test_it_writes_to_correct_output(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - VibroPlane::ActuatorMap outputs = { + FloatPlane::ActuatorMap outputs = { { { 0, 0 }, actuator }, { { 0, 1 }, actuator2 }, { { 1, 0 }, actuator3 }, { { 1, 1 }, actuator4 }, }; - auto plane = new VibroPlane(outputs); + auto plane = new FloatPlane(outputs); - plane->effect({ 0, 0 }, 64); - plane->effect({ 0, 1 }, 128); - plane->effect({ 1, 0 }, 192); - plane->effect({ 1, 1 }, 255); + plane->effect({ 0, 0 }, 0.25F); + plane->effect({ 0, 1 }, 0.5F); + plane->effect({ 1, 0 }, 0.75F); + plane->effect({ 1, 1 }, 1.0F); - TEST_ASSERT_EQUAL_UINT8(64, actuator->intensity); - TEST_ASSERT_EQUAL_UINT8(128, actuator2->intensity); - TEST_ASSERT_EQUAL_UINT8(192, actuator3->intensity); - TEST_ASSERT_EQUAL_UINT8(255, actuator4->intensity); + TEST_ASSERT_EQUAL_FLOAT(0.25F, actuator->intensity); + TEST_ASSERT_EQUAL_FLOAT(0.5F, actuator2->intensity); + TEST_ASSERT_EQUAL_FLOAT(0.75F, actuator3->intensity); + TEST_ASSERT_EQUAL_FLOAT(1.0F, actuator4->intensity); } void test_it_updates_state(void) @@ -64,31 +64,31 @@ void test_it_updates_state(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - VibroPlane::ActuatorMap outputs = { + FloatPlane::ActuatorMap outputs = { { { 0, 0 }, actuator }, { { 0, 1 }, actuator2 }, { { 1, 0 }, actuator3 }, { { 1, 1 }, actuator4 }, }; - auto plane = new VibroPlane(outputs); + auto plane = new FloatPlane(outputs); - plane->effect({ 0, 0 }, 64); - plane->effect({ 0, 1 }, 128); - plane->effect({ 1, 0 }, 192); - plane->effect({ 1, 1 }, 255); + plane->effect({ 0, 0 }, 0.25F); + plane->effect({ 0, 1 }, 0.5F); + plane->effect({ 1, 0 }, 0.75F); + plane->effect({ 1, 1 }, 1.0F); TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 0, 0 }) > 0); - TEST_ASSERT_EQUAL_UINT8(64, plane->getActuatorStates()->at({ 0, 0 })); + TEST_ASSERT_EQUAL_FLOAT(0.25F, plane->getActuatorStates()->at({ 0, 0 })); TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 0, 1 }) > 0); - TEST_ASSERT_EQUAL_UINT8(128, plane->getActuatorStates()->at({ 0, 1 })); + TEST_ASSERT_EQUAL_FLOAT(0.5F, plane->getActuatorStates()->at({ 0, 1 })); TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 1, 0 }) > 0); - TEST_ASSERT_EQUAL_UINT8(192, plane->getActuatorStates()->at({ 1, 0 })); + TEST_ASSERT_EQUAL_FLOAT(0.75F, plane->getActuatorStates()->at({ 1, 0 })); TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 1, 1 }) > 0); - TEST_ASSERT_EQUAL_UINT8(255, plane->getActuatorStates()->at({ 1, 1 })); + TEST_ASSERT_EQUAL_FLOAT(1.0F, plane->getActuatorStates()->at({ 1, 1 })); } void test_closest_it_writes_to_correct_if_exact(void) @@ -96,24 +96,24 @@ void test_closest_it_writes_to_correct_if_exact(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - VibroPlane_Closest::ActuatorMap outputs = { + FloatPlane_Closest::ActuatorMap outputs = { { { 0, 0 }, actuator }, { { 0, 1 }, actuator2 }, { { 1, 0 }, actuator3 }, { { 1, 1 }, actuator4 }, }; - auto plane = new VibroPlane_Closest(outputs); + auto plane = new FloatPlane_Closest(outputs); - plane->effect({ 0, 0 }, 1); - plane->effect({ 0, 1 }, 2); - plane->effect({ 1, 0 }, 3); - plane->effect({ 1, 1 }, 4); + plane->effect({ 0, 0 }, 0.25F); + plane->effect({ 0, 1 }, 0.5F); + plane->effect({ 1, 0 }, 0.75F); + plane->effect({ 1, 1 }, 1.0F); - TEST_ASSERT_EQUAL(1, actuator->intensity); - TEST_ASSERT_EQUAL(2, actuator2->intensity); - TEST_ASSERT_EQUAL(3, actuator3->intensity); - TEST_ASSERT_EQUAL(4, actuator4->intensity); + TEST_ASSERT_EQUAL_FLOAT(0.25F, actuator->intensity); + TEST_ASSERT_EQUAL_FLOAT(0.5F, actuator2->intensity); + TEST_ASSERT_EQUAL_FLOAT(0.75F, actuator3->intensity); + TEST_ASSERT_EQUAL_FLOAT(1.0F, actuator4->intensity); } void test_closest_it_correctly_finds_closest(void) @@ -121,22 +121,22 @@ void test_closest_it_correctly_finds_closest(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - VibroPlane_Closest::ActuatorMap outputs = { + FloatPlane_Closest::ActuatorMap outputs = { { { 0, 0 }, actuator }, { { 0, 64 }, actuator2 }, { { 64, 0 }, actuator3 }, { { 64, 64 }, actuator4 }, }; - auto plane = new VibroPlane_Closest(outputs); + auto plane = new FloatPlane_Closest(outputs); - plane->effect({ 16, 16 }, 16); - plane->effect({ 65, 65 }, 65); + plane->effect({ 16, 16 }, 0.25F); + plane->effect({ 65, 65 }, 0.5F); - TEST_ASSERT_EQUAL(16, actuator->intensity); - TEST_ASSERT_EQUAL(0, actuator2->intensity); - TEST_ASSERT_EQUAL(0, actuator3->intensity); - TEST_ASSERT_EQUAL(65, actuator4->intensity); + TEST_ASSERT_EQUAL_FLOAT(0.25F, actuator->intensity); + TEST_ASSERT_EQUAL_FLOAT(0, actuator2->intensity); + TEST_ASSERT_EQUAL_FLOAT(0, actuator3->intensity); + TEST_ASSERT_EQUAL_FLOAT(0.5F, actuator4->intensity); } void test_closest_it_updates_state(void) @@ -144,29 +144,29 @@ void test_closest_it_updates_state(void) auto actuator = new TestActuator(), actuator2 = new TestActuator(), actuator3 = new TestActuator(), actuator4 = new TestActuator(); - VibroPlane_Closest::ActuatorMap outputs = { + FloatPlane_Closest::ActuatorMap outputs = { { { 0, 0 }, actuator }, { { 0, 64 }, actuator2 }, { { 64, 0 }, actuator3 }, { { 64, 64 }, actuator4 }, }; - auto plane = new VibroPlane_Closest(outputs); + auto plane = new FloatPlane_Closest(outputs); - plane->effect({ 16, 16 }, 16); - plane->effect({ 65, 65 }, 65); + plane->effect({ 16, 16 }, 0.25F); + plane->effect({ 65, 65 }, 0.5F); TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 0, 0 }) > 0); - TEST_ASSERT_EQUAL(16, plane->getActuatorStates()->at({ 0, 0 })); + TEST_ASSERT_EQUAL_FLOAT(0.25F, plane->getActuatorStates()->at({ 0, 0 })); TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 0, 64 }) > 0); - TEST_ASSERT_EQUAL(0, plane->getActuatorStates()->at({ 0, 64 })); + TEST_ASSERT_EQUAL_FLOAT(0, plane->getActuatorStates()->at({ 0, 64 })); TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 64, 0 }) > 0); - TEST_ASSERT_EQUAL(0, plane->getActuatorStates()->at({ 64, 0 })); + TEST_ASSERT_EQUAL_FLOAT(0, plane->getActuatorStates()->at({ 64, 0 })); TEST_ASSERT_TRUE(plane->getActuatorStates()->count({ 64, 64 }) > 0); - TEST_ASSERT_EQUAL(65, plane->getActuatorStates()->at({ 64, 64 })); + TEST_ASSERT_EQUAL_FLOAT(0.5F, plane->getActuatorStates()->at({ 64, 64 })); } void test_plain_mapper_margin_map_points(void) diff --git a/test/test_io_sensor/main.cpp b/test/test_io_sensor/main.cpp index 74b4ace3..bbb9ecca 100644 --- a/test/test_io_sensor/main.cpp +++ b/test/test_io_sensor/main.cpp @@ -2,22 +2,31 @@ #include <unity.h> using namespace SenseShift::Input; -using namespace SenseShift::Calibration; -class TestAnalogSensor : public ISimpleSensor<int> { +class TestAnalogCountingSensor : public ISimpleSensor<int> { public: int count = 0; int setupCounter = 0; void init() override { this->setupCounter++; }; - int getValue() override { return ++this->count; }; + auto getValue() -> int override { return ++this->count; }; +}; + +class TestAnalogSensor : public ISimpleSensor<int> { +public: + int value = 0; + int setupCounter = 0; + + void init() override { this->setupCounter++; }; + + auto getValue() -> int override { return this->value; }; }; void test_memoized_sensor(void) { - auto inner = new TestAnalogSensor(); - auto sensor = new MemoizedSensor<int>(inner); + auto inner = new TestAnalogCountingSensor(); + auto sensor = new SimpleSensorDecorator(inner); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); sensor->init(); @@ -32,7 +41,7 @@ void test_memoized_sensor(void) TEST_ASSERT_EQUAL_INT(1, sensor->getValue()); } -class DummyCalibrator : public ICalibrator<int> { +class DummyCalibrator : public ::SenseShift::Input::Calibration::ICalibrator<int> { public: uint8_t resetCounter = 0; int calibrated = 0; @@ -48,64 +57,53 @@ class DummyCalibrator : public ICalibrator<int> { void test_calibrated_sensor(void) { - auto inner = new TestAnalogSensor(); + auto inner = new TestAnalogCountingSensor(); auto calibrator = new DummyCalibrator(); - auto sensor = new CalibratedSimpleSensor<int>(inner, calibrator); + + auto sensor = new SimpleSensorDecorator(inner); + sensor->setCalibrator(calibrator); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); sensor->init(); TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); calibrator->update(-1); + sensor->tick(); TEST_ASSERT_EQUAL_INT(-1, sensor->getValue()); - sensor->enableCalibration(); + sensor->startCalibration(); + sensor->tick(); TEST_ASSERT_EQUAL_INT(2, sensor->getValue()); - sensor->disableCalibration(); + sensor->stopCalibration(); + sensor->tick(); TEST_ASSERT_EQUAL_INT(2, sensor->getValue()); - sensor->resetCalibration(); + sensor->reselCalibration(); + sensor->tick(); TEST_ASSERT_EQUAL_INT(0, sensor->getValue()); TEST_ASSERT_EQUAL_INT(1, calibrator->resetCounter); } -void test_average_sensor(void) +void test_sensor_filter_multiply(void) { auto inner = new TestAnalogSensor(); - auto sensor = new AverageSensor<int>(inner, 3); + auto sensor = new SimpleSensorDecorator(inner); + sensor->addFilters({ + new ::SenseShift::Input::Filter::MultiplyFilter(2) + }); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); sensor->init(); TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); - // TODO: mock inner sensor, to return more interesting values - TEST_ASSERT_EQUAL_INT(2, sensor->getValue()); // (1 + 2 + 3) / 3 = 2 - TEST_ASSERT_EQUAL_INT(5, sensor->getValue()); // (4 + 5 + 6) / 3 = 5 - TEST_ASSERT_EQUAL_INT(8, sensor->getValue()); // (7 + 8 + 9) / 3 = 8 - TEST_ASSERT_EQUAL_INT(11, sensor->getValue()); // (10 + 11 + 12) / 3 = 11 - - inner->count = 0; - sensor = new AverageSensor<int>(inner, 10); - - TEST_ASSERT_EQUAL_INT(5, sensor->getValue()); // (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10) / 10 = 5 -} - -void test_static_median_sensor(void) -{ - auto inner = new TestAnalogSensor(); - auto sensor = new StaticMedianSensor<int, 3>(inner); - - 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(2, sensor->getValue()); - // lmao, literally the same as average sensor - // TODO: mock inner sensor, to return more interesting values - TEST_ASSERT_EQUAL_INT(2, sensor->getValue()); // (1, 2, 3) = 2 - TEST_ASSERT_EQUAL_INT(5, sensor->getValue()); // (4, 5, 6) = 5 - TEST_ASSERT_EQUAL_INT(8, sensor->getValue()); // (7, 8, 9) = 8 - TEST_ASSERT_EQUAL_INT(11, sensor->getValue()); // (10, 11, 12) = 11 + inner->value = 16; + sensor->tick(); + TEST_ASSERT_EQUAL_INT(32, sensor->getValue()); } int process(void) @@ -114,8 +112,7 @@ int process(void) RUN_TEST(test_memoized_sensor); RUN_TEST(test_calibrated_sensor); - RUN_TEST(test_average_sensor); - RUN_TEST(test_static_median_sensor); + RUN_TEST(test_sensor_filter_multiply); return UNITY_END(); } diff --git a/test/test_opengloves_gesture/main.cpp b/test/test_opengloves_gesture/main.cpp index 0d89a11a..db4f7057 100644 --- a/test/test_opengloves_gesture/main.cpp +++ b/test/test_opengloves_gesture/main.cpp @@ -1,4 +1,4 @@ -#include <sensor/og_gesture.hpp> +#include <senseshift/body/hands/gestures/grab.hpp> #include <unity.h> using namespace OpenGloves; From 0be58cce53250c6247e012d32c26e00267547c44 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Tue, 6 Feb 2024 13:25:43 +0400 Subject: [PATCH 53/82] refactor(Calibration): apply SFINAE --- lib/arduino_esp32/library.json | 7 ++ lib/bhaptics/senseshift/bh/devices.hpp | 2 +- lib/core/senseshift/core/helpers.hpp | 6 +- lib/hands/hand_interface.hpp | 27 ------ lib/io/senseshift/input/analog_threshold.hpp | 55 ++++++++++++ lib/io/senseshift/input/calibration.hpp | 95 +++++++++++++------- lib/io/senseshift/input/sensor.hpp | 31 ------- platformio.ini | 2 +- test/test_io_sensor/main.cpp | 33 +++++++ test/test_util_calibration/main.cpp | 72 ++++++++------- 10 files changed, 203 insertions(+), 127 deletions(-) create mode 100644 lib/arduino_esp32/library.json delete mode 100644 lib/hands/hand_interface.hpp create mode 100644 lib/io/senseshift/input/analog_threshold.hpp diff --git a/lib/arduino_esp32/library.json b/lib/arduino_esp32/library.json new file mode 100644 index 00000000..d97e8e1b --- /dev/null +++ b/lib/arduino_esp32/library.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", + "frameworks": "arduino", + "platforms": [ + "espressif32" + ] +} diff --git a/lib/bhaptics/senseshift/bh/devices.hpp b/lib/bhaptics/senseshift/bh/devices.hpp index 7b051c85..b90d627c 100644 --- a/lib/bhaptics/senseshift/bh/devices.hpp +++ b/lib/bhaptics/senseshift/bh/devices.hpp @@ -3,7 +3,7 @@ #include <array> #include <tuple> -#include <hand_interface.hpp> +#include "senseshift/body/hands/hands_interface.hpp" #include <senseshift/body/haptics/plane.hpp> #include <senseshift/body/haptics/body.hpp> diff --git a/lib/core/senseshift/core/helpers.hpp b/lib/core/senseshift/core/helpers.hpp index f15909e9..14d8e897 100644 --- a/lib/core/senseshift/core/helpers.hpp +++ b/lib/core/senseshift/core/helpers.hpp @@ -4,6 +4,8 @@ #include <type_traits> #include <vector> +#include <senseshift/core/logging.hpp> + namespace SenseShift { /// Linearly interpolate between \p start and \p end by \p completion (between 0 and 1). template<typename Tp> @@ -26,7 +28,7 @@ namespace SenseShift { /// \param max_out The maximum value of the output range. /// /// \return The remapped value. - template<typename Tp, typename Up> + template<typename Tp, typename Up = Tp> constexpr auto remap(Up value, Up min, Up max, Tp min_out, Tp max_out) -> Tp { static_assert(std::is_arithmetic_v<Tp>, "Type must be arithmetic"); @@ -52,7 +54,7 @@ namespace SenseShift { /// \return The remapped value. /// /// \note This is a simplified version of remap() where the minimum values are 0. - template<typename Tp, typename Up> + template<typename Tp, typename Up = Tp> constexpr auto remap_simple(Up value, Up max, Tp max_out) noexcept -> Tp { static_assert(std::is_arithmetic_v<Up>, "Type must be arithmetic"); diff --git a/lib/hands/hand_interface.hpp b/lib/hands/hand_interface.hpp deleted file mode 100644 index 907a553b..00000000 --- a/lib/hands/hand_interface.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include <cstdint> -#include <senseshift/body/haptics/interface.hpp> - -namespace SenseShift::Body { - namespace Hands { - using HandSideIndex = std::uint8_t; - enum class HandSide : HandSideIndex { 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 Hands -} // namespace SenseShift::Body diff --git a/lib/io/senseshift/input/analog_threshold.hpp b/lib/io/senseshift/input/analog_threshold.hpp new file mode 100644 index 00000000..eb03eec5 --- /dev/null +++ b/lib/io/senseshift/input/analog_threshold.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include "senseshift/input/sensor.hpp" + +namespace SenseShift::Input { + template<typename Tp> + class AnalogThresholdSensor : public BinarySensor, ITickable { + 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<Tp>* source, + Tp threshold_upper, + float 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 <typename U = Tp, std::enable_if_t<std::is_same_v<U, float>, int> = 0> + explicit AnalogThresholdSensor( + ::SenseShift::Input::Sensor<Tp>* source, + float threshold = 0.5f, + bool attach_callbacks = false + ) : AnalogThresholdSensor(source, threshold, threshold, attach_callbacks) { } + + void init() override { + SS_SUBSENSOR_INIT(this->source_, this->attach_callbacks_, [this](Tp /*value*/) { + this->recalculateState(); + }); + } + + 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<Tp>* source_; + + float threshold_lower_, threshold_upper_; + + bool attach_callbacks_ = false; + }; +} \ No newline at end of file diff --git a/lib/io/senseshift/input/calibration.hpp b/lib/io/senseshift/input/calibration.hpp index b9baa95a..51412389 100644 --- a/lib/io/senseshift/input/calibration.hpp +++ b/lib/io/senseshift/input/calibration.hpp @@ -1,12 +1,12 @@ -/** - * Calibrated input - * Credit: https://github.com/JohnRThomas/OpenGloves-Firmware/blob/main/open-gloves/Calibration.hpp - */ +/// Calibrated input +/// Credit: https://github.com/JohnRThomas/OpenGloves-Firmware/blob/main/open-gloves/Calibration.hpp #pragma once #include "senseshift/utility.hpp" +#include <type_traits> + namespace SenseShift::Input::Calibration { struct ICalibrated { virtual void startCalibration() = 0; @@ -33,7 +33,14 @@ namespace SenseShift::Input::Calibration { public: using ValueType = Tp; - MinMaxCalibrator(ValueType output_min, ValueType output_max) : output_min_(output_min), output_max_(output_max), value_min_(output_max), value_max_(output_min) {} + 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<typename U = Tp, std::enable_if_t<std::is_same_v<U, float>, 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_; @@ -75,87 +82,113 @@ namespace SenseShift::Input::Calibration { private: const ValueType output_min_; const ValueType output_max_; + ValueType value_min_; ValueType value_max_; }; - template<typename Tp, Tp sensor_max, Tp driver_max_deviation, Tp output_min, Tp output_max> + template<typename Tp> class CenterPointDeviationCalibrator : public ICalibrator<Tp> { static_assert(std::is_arithmetic_v<Tp>, "CenterPointDeviationCalibrator only can be used with arithmetic types"); public: using ValueType = Tp; - CenterPointDeviationCalibrator() : range_min(sensor_max), range_max(0) {} + 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<typename U = Tp, std::enable_if_t<std::is_same_v<U, float>, 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 { - range_min = sensor_max; - range_max = 0; + this->range_min_ = this->sensor_max_; + this->range_max_ = 0; } void update(Tp input) override { // Update the min and the max. - if (input < range_min) { - range_min = ::SenseShift::remap<ValueType>(input, output_min, output_max, 0, sensor_max); + if (input < this->range_min_) { + this->range_min_ = ::SenseShift::remap<ValueType>(input, this->output_min_, this->output_max_, 0, this->sensor_max_); } - if (input > range_max) { - range_max = ::SenseShift::remap<ValueType>(input, output_min, output_max, 0, sensor_max); + if (input > this->range_max_) { + this->range_max_ = ::SenseShift::remap<ValueType>(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 = (range_min + range_max) / 2.0F; + Tp center = (this->range_min_ + this->range_max_) / 2.0F; // Map the input to the sensor range of motion. - int output = ::SenseShift::accurateMap<Tp>(input, output_min, output_max, 0, sensor_max); + int output = ::SenseShift::accurateMap<Tp>(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<int>(output - center, -driver_max_deviation, driver_max_deviation); + output = std::clamp<int>(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<ValueType, int>( output, - -driver_max_deviation, - driver_max_deviation, - output_min, - output_max + -(this->driver_max_deviation_), + this->driver_max_deviation_, + this->output_min_, + this->output_max_ ); } private: - Tp range_min; - Tp range_max; + const Tp sensor_max_; + const Tp driver_max_deviation_; + const Tp output_min_; + const Tp output_max_; + + Tp range_min_; + Tp range_max_; }; - template<typename Tp, Tp sensor_max, Tp driver_max_deviation, Tp output_min, Tp output_max> + template<typename Tp> class FixedCenterPointDeviationCalibrator : public ICalibrator<Tp> { static_assert(std::is_arithmetic_v<Tp>, "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) {} + 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 = sensor_max / 2.0F; + Tp center = this->sensor_max_ / 2.0F; // Map the input to the sensor range of motion. - int output = ::SenseShift::remap<int, Tp>(input, output_min, output_max, 0, sensor_max); + int output = ::SenseShift::remap<Tp>(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<int>(output - center, -driver_max_deviation, driver_max_deviation); + output = std::clamp<int>(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<ValueType, int>( output, - -driver_max_deviation, - driver_max_deviation, - output_min, - output_max + -(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 +} // namespace SenseShift::Input::Calibration diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index 86b22868..5b1e8ddb 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -238,37 +238,6 @@ namespace SenseShift::Input { // SourceType* source_; // }; - class AnalogThresholdSensor : public BinarySensor, ITickable { - public: - explicit AnalogThresholdSensor( - ::SenseShift::Input::FloatSensor* index, - float threshold = 0.5F, - bool attach_callbacks = false - ) : index_(index), threshold_(threshold), attach_callbacks_(attach_callbacks) {} - - void init() override { - SS_SUBSENSOR_INIT(this->index_, this->attach_callbacks_, [this](float /*value*/) { - this->recalculateState(); - }); - } - - 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() { - return this->publishState(this->index_->getValue() > this->threshold_); - } - - private: - ::SenseShift::Input::FloatSensor* index_; - float threshold_; - bool attach_callbacks_ = false; - }; - namespace _private { class TheFloatSensor : public Sensor<float> { }; } diff --git a/platformio.ini b/platformio.ini index 4815cf7a..2b718462 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,7 +29,7 @@ build_flags = ; -D DEBUG_MODE=0 ; -D DEBUG_ESP_PORT=Serial ; -D SENSESHIFT_SERIAL_PLOTTER=true -; -D SENSESHIFT_BATTERY_ENABLED=true + -D SENSESHIFT_BATTERY_ENABLED=true ; -D SENSESHIFT_BLE_USE_NIMBLE=true build_src_filter = diff --git a/test/test_io_sensor/main.cpp b/test/test_io_sensor/main.cpp index bbb9ecca..f91382fe 100644 --- a/test/test_io_sensor/main.cpp +++ b/test/test_io_sensor/main.cpp @@ -1,4 +1,5 @@ #include <senseshift/input/sensor.hpp> +#include <senseshift/input/analog_threshold.hpp> #include <unity.h> using namespace SenseShift::Input; @@ -106,6 +107,37 @@ void test_sensor_filter_multiply(void) TEST_ASSERT_EQUAL_INT(32, sensor->getValue()); } +void test_sensor_analog_threshold(void) +{ + auto inner = new TestAnalogSensor(); + auto source = new SimpleSensorDecorator(inner); + auto sensor = new AnalogThresholdSensor(source, 120, 80, true); + + TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); + sensor->init(); + TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); + + // 100 is below the threshold, so the sensor should be off + inner->value = 100; + source->tick(); + TEST_ASSERT_FALSE(sensor->getValue()); + + // 130 is above the threshold, so the sensor should be on + inner->value = 130; + source->tick(); + TEST_ASSERT_TRUE(sensor->getValue()); + + // 90 is below the upper threshold, but above the lower threshold, so the sensor should stay on due to hysteresis + inner->value = 90; + source->tick(); + TEST_ASSERT_TRUE(sensor->getValue()); + + // 70 is below the lower threshold, so the sensor should be off + inner->value = 70; + source->tick(); + TEST_ASSERT_FALSE(sensor->getValue()); +} + int process(void) { UNITY_BEGIN(); @@ -113,6 +145,7 @@ int process(void) RUN_TEST(test_memoized_sensor); RUN_TEST(test_calibrated_sensor); RUN_TEST(test_sensor_filter_multiply); + RUN_TEST(test_sensor_analog_threshold); return UNITY_END(); } diff --git a/test/test_util_calibration/main.cpp b/test/test_util_calibration/main.cpp index ddc9d2b8..f554fab5 100644 --- a/test/test_util_calibration/main.cpp +++ b/test/test_util_calibration/main.cpp @@ -1,63 +1,67 @@ #include "senseshift/input/calibration.hpp" #include <unity.h> -using namespace SenseShift::Calibration; +using namespace SenseShift::Input::Calibration; void test_minmax_calibrator(void) { - auto calibrator = new MinMaxCalibrator<uint16_t, 0, 4096>(); + const auto calibrator = new MinMaxCalibrator<float>(); // test uncalibrated neutral value - TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(0)); - TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(10)); - TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(2048)); - TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(4086)); - TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(4096)); - - calibrator->update(10); - calibrator->update(4086); - - TEST_ASSERT_EQUAL_UINT16(0, calibrator->calibrate(0)); - TEST_ASSERT_EQUAL_UINT16(0, calibrator->calibrate(10)); - TEST_ASSERT_EQUAL_UINT16(118, calibrator->calibrate(128)); - TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(2048)); - TEST_ASSERT_EQUAL_UINT16(3977, calibrator->calibrate(3968)); - TEST_ASSERT_EQUAL_UINT16(4096, calibrator->calibrate(4086)); - TEST_ASSERT_EQUAL_UINT16(4096, calibrator->calibrate(4096)); + TEST_ASSERT_EQUAL_FLOAT(0.5F, calibrator->calibrate(0)); + TEST_ASSERT_EQUAL_FLOAT(0.5F, calibrator->calibrate(10)); + TEST_ASSERT_EQUAL_FLOAT(0.5F, calibrator->calibrate(2048)); + TEST_ASSERT_EQUAL_FLOAT(0.5F, calibrator->calibrate(4086)); + TEST_ASSERT_EQUAL_FLOAT(0.5F, calibrator->calibrate(4096)); + + calibrator->update(0.1F); + calibrator->update(0.9F); + + TEST_ASSERT_EQUAL_FLOAT(0.0F, calibrator->calibrate(0.0F)); + TEST_ASSERT_EQUAL_FLOAT(0.0F, calibrator->calibrate(0.1F)); + TEST_ASSERT_EQUAL_FLOAT(0.125F, calibrator->calibrate(0.2F)); + TEST_ASSERT_EQUAL_FLOAT(0.25F, calibrator->calibrate(0.3F)); + TEST_ASSERT_EQUAL_FLOAT(0.375F, calibrator->calibrate(0.4F)); + TEST_ASSERT_EQUAL_FLOAT(0.5F, calibrator->calibrate(0.5F)); + TEST_ASSERT_EQUAL_FLOAT(0.625F, calibrator->calibrate(0.6F)); + TEST_ASSERT_EQUAL_FLOAT(0.75F, calibrator->calibrate(0.7F)); + TEST_ASSERT_EQUAL_FLOAT(0.875F, calibrator->calibrate(0.8F)); + TEST_ASSERT_EQUAL_FLOAT(1.0F, calibrator->calibrate(0.9F)); + TEST_ASSERT_EQUAL_FLOAT(1.0F, calibrator->calibrate(1.0F)); calibrator->reset(); // test uncalibrated neutral value (again) - TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(0)); - TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(10)); - TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(2048)); - TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(4086)); - TEST_ASSERT_EQUAL_UINT16(2048, calibrator->calibrate(4096)); + TEST_ASSERT_EQUAL_FLOAT(0.5F, calibrator->calibrate(0)); + TEST_ASSERT_EQUAL_FLOAT(0.5F, calibrator->calibrate(10)); + TEST_ASSERT_EQUAL_FLOAT(0.5F, calibrator->calibrate(2048)); + TEST_ASSERT_EQUAL_FLOAT(0.5F, calibrator->calibrate(4086)); + TEST_ASSERT_EQUAL_FLOAT(0.5F, calibrator->calibrate(4096)); } void test_center_point_deviation_calibrator(void) { - CenterPointDeviationCalibrator<int, 100, 10, 0, 255> calibrator; + auto calibrator = new CenterPointDeviationCalibrator<int>(100, 10, 0, 255); // Test reset function - calibrator.reset(); + calibrator->reset(); // Test update function - calibrator.update(50); - calibrator.update(75); - calibrator.update(25); + calibrator->update(50); + calibrator->update(75); + calibrator->update(25); // Test calibrate function - TEST_ASSERT_EQUAL_INT(255, calibrator.calibrate(100)); - TEST_ASSERT_EQUAL_INT(191, calibrator.calibrate(75)); - TEST_ASSERT_EQUAL_INT(63, calibrator.calibrate(50)); - TEST_ASSERT_EQUAL_INT(0, calibrator.calibrate(25)); - TEST_ASSERT_EQUAL_INT(0, calibrator.calibrate(0)); + TEST_ASSERT_EQUAL_INT(255, calibrator->calibrate(100)); + TEST_ASSERT_EQUAL_INT(191, calibrator->calibrate(75)); + TEST_ASSERT_EQUAL_INT(63, calibrator->calibrate(50)); + TEST_ASSERT_EQUAL_INT(0, calibrator->calibrate(25)); + TEST_ASSERT_EQUAL_INT(0, calibrator->calibrate(0)); } void test_fixed_center_point_deviation_calibrator(void) { - auto calibrator = new FixedCenterPointDeviationCalibrator<uint16_t, 512, 64, 0, 4096>(); + auto calibrator = new FixedCenterPointDeviationCalibrator<uint16_t>(512, 64, 0, 4096); // below deviation TEST_ASSERT_EQUAL_UINT16(0, calibrator->calibrate(0)); From 2f6cfe1f2abfdb15790625c191d3646f7436111d Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Wed, 7 Feb 2024 22:33:00 +0400 Subject: [PATCH 54/82] refactor(OpenGloves): universal encoder --- lib/opengloves/og_constants.hpp | 7 - lib/opengloves/og_ffb.hpp | 15 - lib/opengloves/og_protocol.hpp | 79 ---- lib/opengloves/opengloves/opengloves.cpp | 113 ++++++ lib/opengloves/opengloves/opengloves.hpp | 350 ++++++++++++++++++ .../senseshift/opengloves/encoding/alpha.cpp | 79 ---- .../senseshift/opengloves/encoding/alpha.hpp | 55 --- .../senseshift/opengloves/interface.hpp | 36 -- .../senseshift/opengloves/opengloves.hpp | 18 + lib/opengloves/sensor/og_gesture.hpp | 59 --- 10 files changed, 481 insertions(+), 330 deletions(-) delete mode 100644 lib/opengloves/og_constants.hpp delete mode 100644 lib/opengloves/og_ffb.hpp delete mode 100644 lib/opengloves/og_protocol.hpp create mode 100644 lib/opengloves/opengloves/opengloves.cpp create mode 100644 lib/opengloves/opengloves/opengloves.hpp delete mode 100644 lib/opengloves/senseshift/opengloves/encoding/alpha.cpp delete mode 100644 lib/opengloves/senseshift/opengloves/encoding/alpha.hpp delete mode 100644 lib/opengloves/senseshift/opengloves/interface.hpp create mode 100644 lib/opengloves/senseshift/opengloves/opengloves.hpp delete mode 100644 lib/opengloves/sensor/og_gesture.hpp diff --git a/lib/opengloves/og_constants.hpp b/lib/opengloves/og_constants.hpp deleted file mode 100644 index df163940..00000000 --- a/lib/opengloves/og_constants.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#define OPENGLOVES_FINGERS_TASK_PRIORITY 1 - -#define OPENGLOVES_COMM_SERIAL 0x1 -#define OPENGLOVES_COMM_BTSERIAL 0x2 -#define OPENGLOVES_COMM_BLESERIAL 0x3 diff --git a/lib/opengloves/og_ffb.hpp b/lib/opengloves/og_ffb.hpp deleted file mode 100644 index ca2c5b9d..00000000 --- a/lib/opengloves/og_ffb.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include <senseshift/output/actuator.hpp> - -#include <optional> - -namespace OpenGloves { - struct HandActuators { - std::optional<::SenseShift::Output::IActuator<uint16_t>*> thumb = std::nullopt; - std::optional<::SenseShift::Output::IActuator<uint16_t>*> index = std::nullopt; - std::optional<::SenseShift::Output::IActuator<uint16_t>*> middle = std::nullopt; - std::optional<::SenseShift::Output::IActuator<uint16_t>*> ring = std::nullopt; - std::optional<::SenseShift::Output::IActuator<uint16_t>*> pinky = std::nullopt; - }; -} // namespace OpenGloves diff --git a/lib/opengloves/og_protocol.hpp b/lib/opengloves/og_protocol.hpp deleted file mode 100644 index f1849a3b..00000000 --- a/lib/opengloves/og_protocol.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include <cstdint> -#include <functional> -#include <vector> - -namespace OpenGloves { - struct IEncodedInput { - public: - enum Type : char { - THUMB = 'A', - INDEX = 'B', - MIDDLE = 'C', - RING = 'D', - PINKY = 'E', - JOY_X = 'F', - JOY_Y = 'G', - JOY_BTN = 'H', - TRIGGER = 'I', - A_BTN = 'J', - B_BTN = 'K', - GRAB = 'L', - PINCH = 'M', - MENU = 'N', - CALIBRATE = 'O' - }; - - IEncodedInput(Type type) : type(type){}; - - constexpr Type getType() const { return this->type; } - - protected: - Type type; - }; - - class IStringEncoded : public IEncodedInput { - public: - IStringEncoded(Type type) : IEncodedInput(type){}; - - virtual size_t getEncodedLength() const = 0; - virtual size_t encodeString(char* buffer) = 0; - }; - - class IStringEncodedMemoizedSensor : public IStringEncoded { - public: - IStringEncodedMemoizedSensor(Type type) : IStringEncoded(type){}; - - virtual void init() = 0; - virtual void updateValue() = 0; - }; - - class ICommunication { - public: - virtual void setup() = 0; - virtual void send(std::vector<IStringEncodedMemoizedSensor*>& sensors) = 0; - virtual bool hasData() = 0; - virtual size_t readCommand(char* buffer, size_t length) = 0; - }; - - using CommandIndex = uint16_t; - enum Command : CommandIndex { - ThumbCurl, - ThumbSplay, - - IndexCurl, - IndexSplay, - - MiddleCurl, - MiddleSplay, - - RingCurl, - RingSplay, - - PinkyCurl, - PinkySplay, - }; - - using CommandCallback = std::function<void(Command, uint16_t)>; -} // namespace OpenGloves diff --git a/lib/opengloves/opengloves/opengloves.cpp b/lib/opengloves/opengloves/opengloves.cpp new file mode 100644 index 00000000..2752e7fc --- /dev/null +++ b/lib/opengloves/opengloves/opengloves.cpp @@ -0,0 +1,113 @@ +#include "opengloves/opengloves.hpp" + +#include <cstdint> +#include <cstdio> +#include <variant> + +namespace og { + + auto AlphaEncoder::encode_input(const Input& input, char* buffer, size_t length) const -> size_t + { + if (std::holds_alternative<InputInfoData>(input)) { + const auto& info = std::get<InputInfoData>(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<InputPeripheralData>(input)) { + const auto peripheral = std::get<InputPeripheralData>(input); + auto written = 0; + + const auto& curl = peripheral.curl.fingers; +#ifdef OG_ENCODE_FAST + for (auto i = 0; i < curl.size(); i++) { + const auto& finger = curl[i]; + const auto& finger_curl = finger.curl_total; + + written += + snprintf(buffer + written, length - written, "%c%.0f", 'A' + i, finger_curl * MAX_ANALOG_VALUE); + } +#else + for (auto i = 0; i < curl.size(); i++) { + const auto& finger = curl[i]; + const auto& joints = finger.curl; + + for (auto j = 0; j < joints.size(); j++) { + const auto& joint = joints[j]; + + // skip if joint is 0.0, except total_curl (it is probably not enabled) + if (joint == 0.0F && j != 0) { + continue; + } + + const auto& jointKey = AlphaEncoder::FINGER_CURL_JOINT_ALPHA_KEY[i][j]; + + written += + snprintf(buffer + written, length - written, "%s%.0f", jointKey.data(), joint * MAX_ANALOG_VALUE); + } + } + + const auto& splay = peripheral.splay.fingers; + for (auto i = 0; i < splay.size(); i++) { + const auto& finger = splay[i]; + + if (finger == 0.0F) { + continue; + } + + written += snprintf( + buffer + written, + length - written, + "(%cB)%.0f", + AlphaEncoder::FINGER_ALPHA_KEY[i], + finger * MAX_ANALOG_VALUE + ); + } +#endif + + 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::parse_output(const char* data, size_t length) const -> Output + { + return {}; + } +} // namespace og \ No newline at end of file diff --git a/lib/opengloves/opengloves/opengloves.hpp b/lib/opengloves/opengloves/opengloves.hpp new file mode 100644 index 00000000..ae8d80aa --- /dev/null +++ b/lib/opengloves/opengloves/opengloves.hpp @@ -0,0 +1,350 @@ +#pragma once + +#include <array> +#include <cstddef> +#include <cstdint> +#include <map> +#include <string> +#include <variant> +#include <vector> + +#ifdef ARDUINO +#include <WString.h> +#endif // ARDUINO + +#ifdef OG_USE_FROZEN +#include <frozen/map.h> +#include <frozen/string.h> +#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, + }; + + union InputFingerCurlData { + std::array<float, 4> curl; // NOLINT(*-magic-numbers): I'm sure our finger aren't changing anytime soon + struct { + float curl_total; + float curl_joint1; + float curl_joint2; + float curl_joint3; + }; + }; + + template<typename Tp> + union InputFingerData { + std::array<Tp, 5> 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; + }; + }; + }; + + struct InputJoystickData { + float x, y; + bool press; + }; + + struct InputButtonData { + bool press; + // bool touch; + }; + + struct InputAnalogButtonData : InputButtonData { + float value; + }; + + /// Input data structure. + /// + /// I know, it is not the prettiest one, but we need this type of punning to efficiently encode/decode the data + struct InputPeripheralData { + InputFingerData<InputFingerCurlData> curl; + InputFingerData<float> splay; + + InputJoystickData joystick; + + union { + std::array<InputButtonData, 4> buttons; + struct { + InputButtonData button_a; + InputButtonData button_b; + InputButtonData button_menu; + InputButtonData button_calibrate; + InputButtonData pinch; + }; + }; + + union { + std::array<InputAnalogButtonData, 2> analog_buttons; + struct { + InputAnalogButtonData trigger; + InputAnalogButtonData grab; + }; + }; + }; + + struct InputInfoData { + Hand hand; + DeviceType device_type; + + unsigned int firmware_version; + }; + + using Input = std::variant<InputInfoData, InputPeripheralData>; + + class Output {}; + + class IEncoder { + public: + [[nodiscard]] virtual auto encode_input(const Input& input, char* buffer, size_t length) const -> size_t = 0; + + [[nodiscard]] auto encode_input(const Input& 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 parse_output(const char* data, size_t length) const -> Output = 0; + + [[nodiscard]] auto parse_output(const std::vector<char>& data) const -> Output + { + return this->parse_output(data.data(), data.size()); + } + + [[nodiscard]] auto parse_output(const std::string& data) const -> Output + { + return this->parse_output(data.data(), data.length()); + } + +#ifdef ARDUINO + [[nodiscard]] auto parse_output(const String& data) const -> Output + { + return this->parse_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 = 4096; + +#ifdef OG_USE_FROZEN + inline static constexpr const auto ALPHA_KEYS_TO_COMMAND = frozen::make_map<frozen::string, Command> +#else + inline static const auto ALPHA_KEYS_TO_COMMAND = std::map<std::string, Command> +#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<Command, frozen::string> +#else + inline static const auto COMMAND_TO_ALPHA_KEY = std::map<Command, std::string> +#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" }, + { Command::Info_FirmwareVersion, INFO_FIRMWARE_VERSION_KEY }, + { Command::Info_DeviceType, INFO_DEVICE_TYPE_KEY }, + { Command::Info_Hand, INFO_HAND_KEY }, + }); + + /// Alpha keys for fingers. + /// <b>MUST</b> be in the same order as the `InputFingerData` struct. + inline static constexpr const std::array<unsigned char, 5> 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 <b>MUST</b> be in the same order as the `InputFingerData` struct. + /// Second level array <b>MUST</b> be in the same order as the `InputFingerCurlData` struct. + inline static const std::array<std::array<std::string, 4>, 5> FINGER_CURL_JOINT_ALPHA_KEY = { { + { "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. + /// <b>MUST</b> be in the same order as the `InputPeripheralData` struct. + inline static constexpr const std::array<unsigned char, 5> BUTTON_ALPHA_KEY = { { + 'J', // Button A + 'K', // Button B + 'N', // Button Menu + 'O', // Button Calibrate + 'M', // Button Pinch + } }; + + /// Alpha keys for analog buttons. + /// <b>MUST</b> be in the same order as the `InputPeripheralData` struct. + inline static constexpr const std::array<unsigned char, 2> ANALOG_BUTTON_ALPHA_KEY = { { + 'P', // Trigger + 'I', // Grab + } }; + + auto encode_input(const Input& input, char* buffer, size_t length) const -> size_t override; + + auto parse_output(const char* data, size_t length) const -> Output override; + }; +} // namespace og \ No newline at end of file diff --git a/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp b/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp deleted file mode 100644 index c9dc738d..00000000 --- a/lib/opengloves/senseshift/opengloves/encoding/alpha.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "senseshift/opengloves/encoding/alpha.hpp" - -#include <string.h> - -namespace SenseShift::OpenGloves { - size_t AlphaEncodingService::serialize( - const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors, char* buffer - ) const - { - buffer[0] = '\0'; - size_t offset = 0; - - for (size_t i = 0; i < sensors.size(); i++) { - auto* sensor = sensors[i]; - offset += sensor->encodeString(buffer + offset); - } - - buffer[offset++] = '\n'; - buffer[offset] = '\0'; - - return offset; - } - - bool AlphaEncodingService::deserialize( - const char* buffer, const size_t length, std::map<::OpenGloves::Command, uint16_t>& commands - ) const - { - std::string input_string(buffer, length); - - size_t start = 0; // Start of the current command - for (size_t i = 0; i < input_string.length(); i++) { - const char ch = input_string[i]; - - // Start a new command if the character is non-numeric or an opening parenthesis - // and previous character is a numeric character - if ((!(isdigit(ch)) || ch == '(') && i > 0 && isdigit(input_string[i - 1])) { - AlphaEncodingService::splitCommand(input_string, start, i, commands); - start = i; - } - } - - AlphaEncodingService::splitCommand(input_string, start, input_string.size(), commands); - - return true; - } - - void AlphaEncodingService::splitCommand( - const std::string& input_string, size_t start, size_t end, std::map<Command, uint16_t>& commands - ) - { - std::string current_command = input_string.substr(start, end - start); - - if (current_command.empty()) { - return; - } - - // Split the command into prefix and number - size_t split_index = current_command.find_last_not_of(valueSymbols.data()) + 1; - - if (split_index >= current_command.size()) { - log_w("Invalid command: %s", current_command.c_str()); - return; - } - - std::string prefix = current_command.substr(0, split_index); - int number = std::stoi(current_command.substr(split_index)); - - // Check if the command prefix is in commandMap - auto it = commandMap.find(prefix); - if (it == commandMap.end()) { - log_w("Unknown command prefix: %s", prefix.c_str()); - return; - } - - // Look up the Command enum value for the prefix in the commandMap - Command command = it->second; - commands[command] = number; - } -} // namespace SenseShift::OpenGloves diff --git a/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp b/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp deleted file mode 100644 index a8f81f7a..00000000 --- a/lib/opengloves/senseshift/opengloves/encoding/alpha.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include <algorithm> -#include <cstdint> -#include <functional> -#include <map> -#include <string> -#include <vector> - -#include <frozen/map.h> -#include <frozen/string.h> -#include <frozen/unordered_map.h> - -#include <og_protocol.hpp> -#include <senseshift/core/logging.hpp> -#include <senseshift/opengloves/interface.hpp> - -#define SENSESHIFT_OPENGLOVES_ALPHA_ENCODING_BUFFER_SIZE 256 - -namespace SenseShift::OpenGloves { - class AlphaEncodingService : public IEncoding { - using Command = ::OpenGloves::Command; - - public: - inline static constexpr frozen::string valueSymbols = "0123456789"; - inline static const auto commandMap = frozen::make_map<std::string, Command>({ - // clang-format off - { "A", Command::ThumbCurl }, - { "(AB)", Command::ThumbSplay }, - { "B", Command::IndexCurl }, - { "(BB)", Command::IndexSplay }, - { "C", Command::MiddleCurl }, - { "(CB)", Command::MiddleSplay }, - { "D", Command::RingCurl }, - { "(DB)", Command::RingSplay }, - { "E", Command::PinkyCurl }, - { "(EB)", Command::PinkySplay }, - // clang-format on - }); - - AlphaEncodingService(){}; - - virtual size_t serialize(const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors, char* buffer) - const override; - - virtual bool deserialize( - const char* buffer, const size_t length, std::map<::OpenGloves::Command, uint16_t>& commands - ) const override; - - private: - static void splitCommand( - const std::string& input_string, size_t start, size_t end, std::map<Command, uint16_t>& commands - ); - }; -} // namespace SenseShift::OpenGloves diff --git a/lib/opengloves/senseshift/opengloves/interface.hpp b/lib/opengloves/senseshift/opengloves/interface.hpp deleted file mode 100644 index ba7ba8e0..00000000 --- a/lib/opengloves/senseshift/opengloves/interface.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include <cstddef> -#include <cstdint> -#include <vector> - -#include <senseshift/buffer.hpp> - -#include "og_protocol.hpp" - -namespace SenseShift::OpenGloves { - struct ITransport { - virtual void setup(){}; - 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; - }; - - struct IEncoding { - /// \param [in] sensors - /// \param [out] buffer - virtual auto serialize( - const std::vector<::OpenGloves::IStringEncodedMemoizedSensor*>& sensors, - char* buffer - ) const -> size_t = 0; - - /// \param [in] buffer - /// \param [in] length - /// \param [out] commands - virtual auto deserialize( - const char* buffer, - size_t length, - std::map<::OpenGloves::Command, uint16_t>& commands - ) const -> bool = 0; - }; -} // namespace SenseShift::OpenGloves diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp new file mode 100644 index 00000000..267711c3 --- /dev/null +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include <cstddef> +#include <cstdint> +#include <map> +#include <optional> +#include <string> + +#include <opengloves/opengloves.hpp> + +namespace SenseShift::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; + }; +} // namespace SenseShift::OpenGloves diff --git a/lib/opengloves/sensor/og_gesture.hpp b/lib/opengloves/sensor/og_gesture.hpp deleted file mode 100644 index c64365c1..00000000 --- a/lib/opengloves/sensor/og_gesture.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include <sensor/og_finger.hpp> - -namespace OpenGloves { - class Gesture : public SenseShift::Input::ISimpleSensor<bool> {}; - - class GrabGesture : public Gesture { - private: - ICurl& index; - ICurl& middle; - ICurl& ring; - ICurl& pinky; - uint16_t threshold; - - public: - GrabGesture(ICurl& index, ICurl& middle, ICurl& ring, ICurl& pinky, uint16_t threshold) : - index(index), middle(middle), ring(ring), pinky(pinky), threshold(threshold){}; - - void init() override{}; - - [[nodiscard]] auto getValue() -> bool override - { - return this->index.getCurl() > this->threshold && this->middle.getCurl() > this->threshold - && this->ring.getCurl() > this->threshold && this->pinky.getCurl() > this->threshold; - } - }; - - class TriggerGesture : public Gesture { - private: - ICurl& index; - uint16_t threshold; - - public: - TriggerGesture(ICurl& index, uint16_t threshold) : index(index), threshold(threshold){}; - - void init() override{}; - - [[nodiscard]] auto getValue() -> bool override { return this->index.getCurl() > this->threshold; } - }; - - class PinchGesture : public Gesture { - private: - ICurl& index; - ICurl& thumb; - uint16_t threshold; - - public: - PinchGesture(ICurl& index, ICurl& thumb, const uint16_t threshold) : - index(index), thumb(thumb), threshold(threshold){}; - - void init() override{}; - - [[nodiscard]] auto getValue() -> bool override - { - return this->index.getCurl() > this->threshold && this->thumb.getCurl() > this->threshold; - } - }; -} // namespace OpenGloves From d1059009e6a8b222efb898bac2bf78c10394c667 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 8 Feb 2024 13:47:06 +0400 Subject: [PATCH 55/82] refactor(OpenGloves): reuse same structure for data and source sensors --- .../mode_configs/opengloves/opengloves.cpp | 225 +++++-------- ini/opengloves-indexer.ini | 304 +++++++++--------- ini/opengloves-lucidgloves.ini | 199 ++++++------ .../senseshift/body/hands/hands_interface.hpp | 5 +- .../senseshift/body/hands/input/gesture.hpp | 3 +- .../body/hands/input/total_curl.hpp | 33 +- lib/io/senseshift/input/sensor.hpp | 87 ++--- lib/opengloves/opengloves/opengloves.cpp | 2 +- lib/opengloves/opengloves/opengloves.hpp | 101 +++--- .../senseshift/opengloves/autoconfig.hpp | 147 +++++---- .../senseshift/opengloves/opengloves.hpp | 2 + lib/opengloves/sensor/og_finger.hpp | 156 --------- lib/opengloves/sensor/og_sensor.hpp | 45 --- .../opengloves/transport/stream.hpp | 11 +- lib/opengloves_task/opengloves_task.hpp | 7 +- 15 files changed, 538 insertions(+), 789 deletions(-) delete mode 100644 lib/opengloves/sensor/og_finger.hpp delete mode 100644 lib/opengloves/sensor/og_sensor.hpp diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index bded27d3..6666dc3f 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -1,225 +1,154 @@ -#include <og_constants.hpp> -#include <opengloves_task.hpp> +#include "senseshift/body/hands/input/gesture.hpp" +#include "senseshift/body/hands/input/total_curl.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/input/sensor/binary.hpp> -#include <senseshift/arduino/output/actuator/servo.hpp> -#include <senseshift/calibration.hpp> +#include <senseshift/arduino/input/sensor/digital.hpp> +#include <senseshift/body/hands/input/gesture.hpp> +#include <senseshift/input/calibration.hpp> +#include <senseshift/input/filter.hpp> #include <senseshift/input/sensor.hpp> -#include <senseshift/input/sensor/joystick.hpp> #include <senseshift/opengloves/autoconfig.hpp> -#include <senseshift/opengloves/transport/stream.hpp> #include <senseshift/utility.hpp> -#include <sensor/og_finger.hpp> -#include <sensor/og_gesture.hpp> -using namespace OpenGloves; -using namespace SenseShift::OpenGloves; +using namespace ::SenseShift::Input; +using namespace ::SenseShift::Arduino::Input; +using namespace ::SenseShift::Body::Hands::Input; +using namespace ::SenseShift::OpenGloves; -HandSensors handSensors = { +InputSensors input_sensors; + +void setupMode() +{ #if FINGER_THUMB_SPLAY - .thumb = FINGER_SPLAY_CLASS( - IEncodedInput::Type::THUMB, + 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 - .thumb = FINGER_CLASS(IEncodedInput::Type::THUMB, PIN_FINGER_THUMB, FINGER_THUMB_INVERT, CALIBRATION_CURL), + 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 - .index = FINGER_SPLAY_CLASS( - IEncodedInput::Type::INDEX, + 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 - .index = FINGER_CLASS(IEncodedInput::Type::INDEX, PIN_FINGER_INDEX, FINGER_INDEX_INVERT, CALIBRATION_CURL), + 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 - .middle = FINGER_SPLAY_CLASS( - IEncodedInput::Type::MIDDLE, + 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 - .middle = FINGER_CLASS(IEncodedInput::Type::MIDDLE, PIN_FINGER_MIDDLE, FINGER_MIDDLE_INVERT, CALIBRATION_CURL), + 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 - .ring = FINGER_SPLAY_CLASS( - IEncodedInput::Type::RING, + 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 - .ring = FINGER_CLASS(IEncodedInput::Type::RING, PIN_FINGER_RING, FINGER_RING_INVERT, CALIBRATION_CURL), + 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 - .pinky = FINGER_SPLAY_CLASS( - IEncodedInput::Type::PINKY, + 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 - .pinky = FINGER_CLASS(IEncodedInput::Type::PINKY, PIN_FINGER_PINKY, FINGER_PINKY_INVERT, CALIBRATION_CURL), + DEFINE_FINGER(pinky_curl, PIN_FINGER_PINKY, FINGER_PINKY_INVERT, CALIBRATION_CURL); + input_sensors.curl.pinky.curl_total = pinky_curl_sensor; #endif -}; -#if BUTTON_CALIBRATE_ENABLED -std::optional<StringEncodedMemoizedSensor<bool>> calibrateButton = - BUTTON_CLASS(IEncodedInput::Type::CALIBRATE, PIN_BUTTON_CALIBRATE, BUTTON_CALIBRATE_INVERT); -#else -std::optional<StringEncodedMemoizedSensor<bool>> calibrateButton = std::nullopt; +#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); + + input_sensors.joystick.x = joystick_x_sensor; + input_sensors.joystick.y = joystick_y_sensor; #endif -std::vector<StringEncodedMemoizedSensor<bool>*> buttons = std::vector<StringEncodedMemoizedSensor<bool>*> -{ - // https://github.com/llvm/llvm-project/issues/63776 - // clang-format off #if BUTTON_A_ENABLED - new BUTTON_CLASS(IEncodedInput::Type::A_BTN, PIN_BUTTON_A, BUTTON_A_INVERT), + auto* button_a = new BUTTON_CLASS(PIN_BUTTON_A, BUTTON_A_INVERT); + input_sensors.button_a.press = button_a; #endif - #if BUTTON_B_ENABLED - new BUTTON_CLASS(IEncodedInput::Type::B_BTN, PIN_BUTTON_B, BUTTON_B_INVERT), + auto* button_b = new BUTTON_CLASS(PIN_BUTTON_B, BUTTON_B_INVERT); + input_sensors.button_b.press = button_b; #endif - #if BUTTON_JOYSTICK_ENABLED - new BUTTON_CLASS(IEncodedInput::Type::JOY_BTN, PIN_BUTTON_JOYSTICK, BUTTON_JOYSTICK_INVERT), + auto* button_joystick = new BUTTON_CLASS(PIN_BUTTON_JOYSTICK, BUTTON_JOYSTICK_INVERT); + input_sensors.joystick.press = button_joystick; #endif - #if BUTTON_MENU_ENABLED - new BUTTON_CLASS(IEncodedInput::Type::MENU, PIN_BUTTON_MENU, BUTTON_MENU_INVERT), + 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; #endif -#if GESTURE_TRIGGER_ENABLED && FINGER_INDEX_ENABLED - new GESTURE_CLASS( - IEncodedInput::Type::TRIGGER, - new TriggerGesture(handSensors.index.value(), GESTURE_TRIGGER_THRESHOLD) - ), +#if GESTURE_TRIGGER_ENABLED + auto* trigger = new AnalogThresholdSensor(index_curl_sensor, GESTURE_TRIGGER_THRESHOLD); + input_sensors.trigger.press = trigger; #elif BUTTON_TRIGGER_ENABLED - new BUTTON_CLASS(IEncodedInput::Type::TRIGGER, PIN_BUTTON_TRIGGER, BUTTON_TRIGGER_INVERT), + auto trigger = new BUTTON_CLASS(PIN_BUTTON_TRIGGER, BUTTON_TRIGGER_INVERT); #endif -#if GESTURE_GRAB_ENABLED && FINGER_INDEX_ENABLED && FINGER_MIDDLE_ENABLED && FINGER_RING_ENABLED && FINGER_PINKY_ENABLED - new GESTURE_CLASS( - IEncodedInput::Type::GRAB, - new GrabGesture( - handSensors.index.value(), - handSensors.middle.value(), - handSensors.ring.value(), - handSensors.pinky.value(), - GESTURE_GRAB_THRESHOLD - ) - ), +#if GESTURE_GRAB_ENABLED + auto* grab = new GrabGesture( + 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 - new BUTTON_CLASS(IEncodedInput::Type::GRAB, PIN_BUTTON_GRAB, BUTTON_GRAB_INVERT), + auto* grab = new BUTTON_CLASS(PIN_BUTTON_GRAB, BUTTON_GRAB_INVERT); #endif -#if GESTURE_PINCH_ENABLED && FINGER_THUMB_ENABLED && FINGER_INDEX_ENABLED - new GESTURE_CLASS( - IEncodedInput::Type::PINCH, - new PinchGesture(handSensors.thumb.value(), handSensors.index.value(), GESTURE_PINCH_THRESHOLD) - ), -#elif BUTTON_PINCH_ENABLED - new BUTTON_CLASS(IEncodedInput::Type::PINCH, PIN_BUTTON_PINCH, BUTTON_PINCH_INVERT), -#endif - // clang-format on -}; - -std::vector<StringEncodedMemoizedSensor<uint16_t>*> joysticks = { -#if JOYSTICK_ENABLED - new JOYSTICK_CLASS(IEncodedInput::Type::JOY_X, PIN_JOYSTICK_X, JOYSTICK_X_INVERT, JOYSTICK_DEADZONE), - new JOYSTICK_CLASS(IEncodedInput::Type::JOY_Y, PIN_JOYSTICK_Y, JOYSTICK_Y_INVERT, JOYSTICK_DEADZONE), -#endif - // todo: get joystick movement from Thumb finger movement? -}; - -std::vector<IStringEncodedMemoizedSensor*> otherSensors = std::vector<IStringEncodedMemoizedSensor*>(); - -OpenGlovesTrackingTaskConfig config = - OpenGlovesTrackingTaskConfig(UPDATE_RATE, CALIBRATION_DURATION, CALIBRATION_ALWAYS_CALIBRATE); -OpenGlovesTrackingTask* trackingTask; - -#if FFB_ENABLED -HandActuators handActuators = { -#if FFB_THUMB_ENABLED - .thumb = new SenseShift::Arduino::Output::ActuatorServo(PIN_FFB_THUMB), -#endif - -#if FFB_INDEX_ENABLED - .index = new SenseShift::Arduino::Output::ActuatorServo(PIN_FFB_INDEX), -#endif - -#if FFB_MIDDLE_ENABLED - .middle = new SenseShift::Arduino::Output::ActuatorServo(PIN_FFB_MIDDLE), -#endif - -#if FFB_RING_ENABLED - .ring = new SenseShift::Arduino::Output::ActuatorServo(PIN_FFB_RING), -#endif - -#if FFB_PINKY_ENABLED - .pinky = new SenseShift::Arduino::Output::ActuatorServo(PIN_FFB_PINKY), -#endif -}; -OpenGlovesForceFeedbackTask* ffbTask; -#endif - -void setupMode() -{ - auto* communication = AutoConfig::setupTransport(); - - trackingTask = new OpenGlovesTrackingTask( - config, - *communication, - handSensors, - buttons, - joysticks, - otherSensors, - calibrateButton, - { - .name = "OpenGlovesSensorTask", - .stackDepth = 8192, - .priority = OPENGLOVES_FINGERS_TASK_PRIORITY, - } +#if GESTURE_PINCH_ENABLED + auto* pinch = new PinchGesture( + PinchGesture::Fingers{ .thumb = thumb_curl_sensor, .index = index_curl_sensor }, + GESTURE_PINCH_THRESHOLD ); - trackingTask->begin(); - -#if FFB_ENABLED - ffbTask = new OpenGlovesForceFeedbackTask( - *communication, - handActuators, - UPDATE_RATE, - { - .name = "OpenGlovesForceFeedbackTask", - .stackDepth = 8192, - .priority = OPENGLOVES_FINGERS_TASK_PRIORITY, - } - ); - ffbTask->begin(); + input_sensors.pinch.press = pinch; +#elif BUTTON_PINCH_ENABLED + auto* pinch = new BUTTON_CLASS(PIN_BUTTON_PINCH, BUTTON_PINCH_INVERT); #endif } diff --git a/ini/opengloves-indexer.ini b/ini/opengloves-indexer.ini index 7d5cd163..e9e8f5a8 100644 --- a/ini/opengloves-indexer.ini +++ b/ini/opengloves-indexer.ini @@ -3,173 +3,173 @@ ; 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} - ; 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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + +<mode_configs/opengloves/opengloves.cpp> +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} - ; 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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + +<mode_configs/opengloves/opengloves.cpp> +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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + +<mode_configs/opengloves/opengloves.cpp> +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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + +<mode_configs/opengloves/opengloves.cpp> +lib_deps = ${opengloves.lib_deps} diff --git a/ini/opengloves-lucidgloves.ini b/ini/opengloves-lucidgloves.ini index f4047f55..f535f768 100644 --- a/ini/opengloves-lucidgloves.ini +++ b/ini/opengloves-lucidgloves.ini @@ -3,114 +3,115 @@ ; 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} - ; 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 - -build_unflags = ${opengloves.build_unflags} -build_src_filter = ${opengloves.build_src_filter} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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 + +build_unflags = ${opengloves.build_unflags} +build_src_filter = ${opengloves.build_src_filter} + +<mode_configs/opengloves/opengloves.cpp> +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} - ; 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 - - ; todo: add servo pins - -build_unflags = ${opengloves.build_unflags} -build_src_filter = ${opengloves.build_src_filter} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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 + +; todo: add servo pins + +build_unflags = ${opengloves.build_unflags} +build_src_filter = ${opengloves.build_src_filter} + +<mode_configs/opengloves/opengloves.cpp> +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} - ; 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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + ; 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} + +<mode_configs/opengloves/opengloves.cpp> +lib_deps = ${opengloves.lib_deps} diff --git a/lib/hands/senseshift/body/hands/hands_interface.hpp b/lib/hands/senseshift/body/hands/hands_interface.hpp index 4aa48b44..a8887906 100644 --- a/lib/hands/senseshift/body/hands/hands_interface.hpp +++ b/lib/hands/senseshift/body/hands/hands_interface.hpp @@ -1,7 +1,8 @@ #pragma once +#include <senseshift/body/haptics/interface.hpp> + #include <cstdint> -#include "senseshift/body/haptics/interface.hpp" namespace SenseShift::Body { namespace Hands { @@ -21,5 +22,5 @@ namespace SenseShift::Body { /// Distal phalanx of the volar surface of the any finger. static constexpr const ::SenseShift::Body::Haptics::Position FINGERTIP_POSITION(127, 16); } // namespace Haptics - } // namespace Hands + } // namespace Hands } // namespace SenseShift::Body diff --git a/lib/hands_input/senseshift/body/hands/input/gesture.hpp b/lib/hands_input/senseshift/body/hands/input/gesture.hpp index 92ca2a94..ad462051 100644 --- a/lib/hands_input/senseshift/body/hands/input/gesture.hpp +++ b/lib/hands_input/senseshift/body/hands/input/gesture.hpp @@ -2,12 +2,13 @@ #include <senseshift/core/component.hpp> #include <senseshift/input/sensor.hpp> +#include <senseshift/input/analog_threshold.hpp> namespace SenseShift::Body::Hands::Input { using Gesture = ::SenseShift::Input::BinarySensor; /// An alias for semantic consistency. - using TriggerGesture = ::SenseShift::Input::AnalogThresholdSensor; + using TriggerGesture = ::SenseShift::Input::AnalogThresholdSensor<float>; class GrabGesture : public Gesture, ITickable { public: 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 678f5b80..26538afc 100644 --- a/lib/hands_input/senseshift/body/hands/input/total_curl.hpp +++ b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp @@ -11,33 +11,38 @@ namespace SenseShift::Body::Hands::Input { class TotalCurl : public ::SenseShift::Input::FloatSensor, public ::SenseShift::ITickable { public: /// \param joints The joints to calculate the total curl from. - /// \param attach_callbacks Whether to attach callbacks to the joints to recalculate the total curl when they update. + /// \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 <b>true is not recommended</b>, 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 { + /// Setting this to <b>true is not recommended</b>, 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(); }); + SS_SUBSENSOR_INIT(&joint, this->attach_callbacks_, [this](float /*value*/) { + this->recalculateState(); + }); } } - void tick() override { + 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() { + void recalculateState() + { float total = 0.0F; for (auto& joint : this->joints_) { - total += joint.getState(); + total += joint.getValue(); } if (!this->joints_.empty()) { @@ -50,4 +55,4 @@ namespace SenseShift::Body::Hands::Input { bool attach_callbacks_ = false; }; -} // namespace SenseShift::Body::Hands::Input +} // namespace SenseShift::Body::Hands::Input diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index 5b1e8ddb..6d2046ea 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -1,11 +1,11 @@ #pragma once +#include <optional> #include <type_traits> #include <vector> -#include <optional> -#include "senseshift/input/filter.hpp" #include "senseshift/input/calibration.hpp" +#include "senseshift/input/filter.hpp" #include <senseshift/core/component.hpp> #include <senseshift/core/helpers.hpp> @@ -63,7 +63,8 @@ namespace SenseShift::Input { /// new CenterDeadzoneFilter(0.1f), /// }); /// \endcode - void addFilters(std::vector<Filter::IFilter<ValueType>*> filters) { + void addFilters(std::vector<Filter::IFilter<ValueType>*> filters) + { this->filters_.insert(this->filters_.end(), filters.begin(), filters.end()); } @@ -91,17 +92,18 @@ namespace SenseShift::Input { void stopCalibration() override { this->is_calibrating_ = false; } - void reselCalibration() override { + void reselCalibration() override + { if (this->calibrator_.has_value()) { this->calibrator_.value()->reset(); } } - void addValueCallback(CallbackType &&callback) { this->callbacks_.add(std::move(callback)); } + void addValueCallback(CallbackType&& callback) { this->callbacks_.add(std::move(callback)); } - void addRawValueCallback(CallbackType &&callback) { this->raw_callbacks_.add(std::move(callback)); } + void addRawValueCallback(CallbackType&& callback) { this->raw_callbacks_.add(std::move(callback)); } - void init() override { } + void init() override {} /// Publish the given state to the sensor. /// @@ -110,7 +112,8 @@ namespace SenseShift::Input { /// Finally, the filtered value will be assigned to the sensor's .value_. /// /// \param rawValue The new .raw_value_. - void publishState(ValueType rawValue) { + void publishState(ValueType rawValue) + { this->raw_value_ = rawValue; this->raw_callbacks_.call(this->raw_value_); @@ -119,18 +122,15 @@ namespace SenseShift::Input { } /// Get the current sensor .value_. - [[nodiscard]] auto getValue() -> ValueType override { - return this->value_; - } + [[nodiscard]] auto getValue() -> ValueType override { return this->value_; } /// Get the current raw sensor .raw_value_. - [[nodiscard]] auto getRawValue() -> ValueType { - return this->raw_value_; - } + [[nodiscard]] auto getRawValue() -> ValueType { return this->raw_value_; } protected: /// Apply current filters to value. - [[nodiscard]] auto applyFilters(ValueType value) -> ValueType { + [[nodiscard]] auto applyFilters(ValueType value) -> ValueType + { /// Apply calibration if (this->calibrator_.has_value()) { if (this->is_calibrating_) { @@ -168,26 +168,24 @@ namespace SenseShift::Input { }; using FloatSensor = Sensor<float>; + + // todo: support double/triple/N-times/long click and so on using BinarySensor = Sensor<bool>; template<typename Tp> - class SimpleSensorDecorator : public Sensor<Tp>, public ITickable - { + class SimpleSensorDecorator : public Sensor<Tp>, public ITickable { public: using ValueType = Tp; using SourceType = ISimpleSensor<ValueType>; 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 updateValue() -> ValueType + { auto const raw_value = this->readRawValue(); this->publishState(raw_value); @@ -196,49 +194,14 @@ namespace SenseShift::Input { return this->getValue(); } - [[nodiscard]] auto readRawValue() -> ValueType { - return this->source_->getValue(); - } + [[nodiscard]] auto readRawValue() -> ValueType { return this->source_->getValue(); } protected: - private: SourceType* source_; }; -// template<typename Tp> -// class SensorDecorator : public Sensor<Tp> -// { -// public: -// using ValueType = Tp; -// using SourceType = Sensor<ValueType>; -// -// explicit SensorDecorator(SourceType* source) : source_(source) {} -// -// void init() override { -// this->source_->init(); -// this->source_->addValueCallback([this](ValueType value) { -// this->publishState(value); -// }); -// } -// -// void startCalibration() override { -// this->source_->startCalibration(); -// } -// -// void stopCalibration() override { -// this->source_->stopCalibration(); -// } -// -// void reselCalibration() override { -// this->source_->reselCalibration(); -// } -// -// private: -// SourceType* source_; -// }; - namespace _private { - class TheFloatSensor : public Sensor<float> { }; - } + class TheFloatSensor : public Sensor<float> {}; + } // namespace _private } // namespace SenseShift::Input diff --git a/lib/opengloves/opengloves/opengloves.cpp b/lib/opengloves/opengloves/opengloves.cpp index 2752e7fc..951391b6 100644 --- a/lib/opengloves/opengloves/opengloves.cpp +++ b/lib/opengloves/opengloves/opengloves.cpp @@ -6,7 +6,7 @@ namespace og { - auto AlphaEncoder::encode_input(const Input& input, char* buffer, size_t length) const -> size_t + auto AlphaEncoder::encode_input(const InputData& input, char* buffer, size_t length) const -> size_t { if (std::holds_alternative<InputInfoData>(input)) { const auto& info = std::get<InputInfoData>(input); diff --git a/lib/opengloves/opengloves/opengloves.hpp b/lib/opengloves/opengloves/opengloves.hpp index ae8d80aa..d01bbfeb 100644 --- a/lib/opengloves/opengloves/opengloves.hpp +++ b/lib/opengloves/opengloves/opengloves.hpp @@ -33,18 +33,20 @@ namespace og { DeviceType_LucidGloves, }; - union InputFingerCurlData { - std::array<float, 4> curl; // NOLINT(*-magic-numbers): I'm sure our finger aren't changing anytime soon + template<typename Tf = float> + union InputFingerCurl { + std::array<Tf, 4> curl; // NOLINT(*-magic-numbers): I'm sure our finger aren't changing anytime soon struct { - float curl_total; - float curl_joint1; - float curl_joint2; - float curl_joint3; + Tf curl_total; + Tf curl_joint1; + Tf curl_joint2; + Tf curl_joint3; }; }; + using InputFingerCurlData = InputFingerCurl<float>; template<typename Tp> - union InputFingerData { + union InputFinger { std::array<Tp, 5> fingers; // NOLINT(*-magic-numbers): We aren't going to grow any new fingers soon tbh struct { Tp thumb; @@ -58,49 +60,58 @@ namespace og { }; }; }; + using InputFingerData = InputFinger<float>; - struct InputJoystickData { - float x, y; - bool press; + template<typename Tf = float, typename Tb = bool> + struct InputJoystick { + Tf x, y; + Tb press; }; + using InputJoystickData = InputJoystick<float, bool>; - struct InputButtonData { - bool press; + template<typename Tb = bool> + struct InputButton { + Tb press; // bool touch; }; + using InputButtonData = InputButton<bool>; - struct InputAnalogButtonData : InputButtonData { - float value; + template<typename Tf = float, typename Tb = bool> + struct InputAnalogButton : InputButton<Tb> { + Tf value; }; + using InputAnalogButtonData = InputAnalogButton<float, bool>; /// Input data structure. /// /// I know, it is not the prettiest one, but we need this type of punning to efficiently encode/decode the data - struct InputPeripheralData { - InputFingerData<InputFingerCurlData> curl; - InputFingerData<float> splay; + template<typename Tf = float, typename Tb = bool> + struct InputPeripheral { + InputFinger<InputFingerCurl<Tf>> curl; + InputFinger<Tf> splay; - InputJoystickData joystick; + InputJoystick<Tf, Tb> joystick; union { - std::array<InputButtonData, 4> buttons; + std::array<InputButton<Tb>, 4> buttons; struct { - InputButtonData button_a; - InputButtonData button_b; - InputButtonData button_menu; - InputButtonData button_calibrate; - InputButtonData pinch; + InputButton<Tb> button_a; + InputButton<Tb> button_b; + InputButton<Tb> button_menu; + InputButton<Tb> button_calibrate; + InputButton<Tb> pinch; }; }; union { - std::array<InputAnalogButtonData, 2> analog_buttons; + std::array<InputAnalogButton<Tf, Tb>, 2> analog_buttons; struct { - InputAnalogButtonData trigger; - InputAnalogButtonData grab; + InputAnalogButton<Tf, Tb> trigger; + InputAnalogButton<Tf, Tb> grab; }; }; }; + using InputPeripheralData = InputPeripheral<float, bool>; struct InputInfoData { Hand hand; @@ -109,15 +120,16 @@ namespace og { unsigned int firmware_version; }; - using Input = std::variant<InputInfoData, InputPeripheralData>; + using InputData = std::variant<InputInfoData, InputPeripheralData>; class Output {}; class IEncoder { public: - [[nodiscard]] virtual auto encode_input(const Input& input, char* buffer, size_t length) const -> size_t = 0; + [[nodiscard]] virtual auto encode_input(const InputData& input, char* buffer, size_t length) const + -> size_t = 0; - [[nodiscard]] auto encode_input(const Input& input) const -> std::string + [[nodiscard]] auto encode_input(const InputData& input) const -> std::string { std::string buffer; buffer.resize(OG_BUFFER_SIZE); @@ -300,9 +312,15 @@ namespace og { { 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. @@ -318,13 +336,18 @@ namespace og { /// Alpha keys for finger curl joints. Top level is the finger, second level is the joint. /// The top level <b>MUST</b> be in the same order as the `InputFingerData` struct. /// Second level array <b>MUST</b> be in the same order as the `InputFingerCurlData` struct. - inline static const std::array<std::array<std::string, 4>, 5> FINGER_CURL_JOINT_ALPHA_KEY = { { - { "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) - } }; +#ifdef OG_USE_FROZEN + inline static constexpr const std::array<std::array<frozen::string, 4>, 5> FINGER_CURL_JOINT_ALPHA_KEY = +#else + inline static const std::array<std::array<std::string, 4>, 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. /// <b>MUST</b> be in the same order as the `InputPeripheralData` struct. @@ -343,8 +366,8 @@ namespace og { 'I', // Grab } }; - auto encode_input(const Input& input, char* buffer, size_t length) const -> size_t override; + [[nodiscard]] auto encode_input(const InputData& input, char* buffer, size_t length) const -> size_t override; - auto parse_output(const char* data, size_t length) const -> Output override; + [[nodiscard]] auto parse_output(const char* data, size_t length) const -> Output override; }; } // namespace og \ No newline at end of file diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index 35419d72..4f114d03 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -1,6 +1,6 @@ #pragma once -#include <senseshift/opengloves/interface.hpp> +#include <senseshift/opengloves/opengloves.hpp> #ifdef ARDUINO #include <senseshift/opengloves/transport/stream.hpp> @@ -29,10 +29,10 @@ #pragma region Calibration #ifndef CALIBRATION_CURL -#define CALIBRATION_CURL ::SenseShift::Calibration::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX> +#define CALIBRATION_CURL new ::SenseShift::Input::Calibration::MinMaxCalibrator<float>() #endif #ifndef CALIBRATION_SPLAY -#define CALIBRATION_SPLAY ::SenseShift::Calibration::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX> +#define CALIBRATION_SPLAY new ::SenseShift::Input::Calibration::CenterPointDeviationCalibrator<float>(0.66F, 0.005F) #endif #ifndef CALIBRATION_DURATION @@ -43,61 +43,93 @@ #pragma region Fingers -#define FINGER_THUMB_ENABLED (defined(PIN_FINGER_THUMB) && (PIN_FINGER_THUMB != -1)) -#define FINGER_INDEX_ENABLED (defined(PIN_FINGER_INDEX) && (PIN_FINGER_INDEX != -1)) -#define FINGER_MIDDLE_ENABLED (defined(PIN_FINGER_MIDDLE) && (PIN_FINGER_MIDDLE != -1)) -#define FINGER_RING_ENABLED (defined(PIN_FINGER_RING) && (PIN_FINGER_RING != -1)) -#define FINGER_PINKY_ENABLED (defined(PIN_FINGER_PINKY) && (PIN_FINGER_PINKY != -1)) -#define FINGER_CLASS(type, curl_pin, curl_invert, curl_calib) \ - FingerSensor( \ - new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Input::StaticMedianSensor<uint16_t, 5>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin) \ - ), \ - new curl_calib() \ - ), \ - type \ - ) -#define FINGER_THUMB_SPLAY (FINGER_THUMB_ENABLED && defined(PIN_FINGER_THUMB_SPLAY) && (PIN_FINGER_THUMB_SPLAY != -1)) -#define FINGER_INDEX_SPLAY (FINGER_INDEX_ENABLED && defined(PIN_FINGER_INDEX_SPLAY) && (PIN_FINGER_INDEX_SPLAY != -1)) -#define FINGER_MIDDLE_SPLAY \ - (FINGER_MIDDLE_ENABLED && defined(PIN_FINGER_MIDDLE_SPLAY) && (PIN_FINGER_MIDDLE_SPLAY != -1)) -#define FINGER_RING_SPLAY (FINGER_RING_ENABLED && defined(PIN_FINGER_RING_SPLAY) && (PIN_FINGER_RING_SPLAY != -1)) -#define FINGER_PINKY_SPLAY (FINGER_PINKY_ENABLED && defined(PIN_FINGER_PINKY_SPLAY) && (PIN_FINGER_PINKY_SPLAY != -1)) -#define FINGER_SPLAY_CLASS(type, curl_pin, curl_invert, curl_calib, splay_pin, splay_invert, splay_calib) \ - FingerSensor( \ - new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Input::StaticMedianSensor<uint16_t, 5>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<curl_invert>(curl_pin) \ - ), \ - new curl_calib() \ - ), \ - new ::SenseShift::Input::CalibratedSimpleSensor<uint16_t>( \ - new ::SenseShift::Input::StaticMedianSensor<uint16_t, 5>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<splay_invert>(splay_pin) \ - ), \ - new splay_calib() \ - ), \ - type \ - ) +#ifdef PIN_FINGER_THUMB +#define FINGER_THUMB_ENABLED (PIN_FINGER_THUMB != -1) +#else +#define FINGER_THUMB_ENABLED false +#endif + +#ifdef PIN_FINGER_INDEX +#define FINGER_INDEX_ENABLED (PIN_FINGER_INDEX != -1) +#else +#define FINGER_INDEX_ENABLED false +#endif + +#ifdef PIN_FINGER_MIDDLE +#define FINGER_MIDDLE_ENABLED (PIN_FINGER_MIDDLE != -1) +#else +#define FINGER_MIDDLE_ENABLED false +#endif + +#ifdef PIN_FINGER_RING +#define FINGER_RING_ENABLED (PIN_FINGER_RING != -1) +#else +#define FINGER_RING_ENABLED false +#endif + +#ifdef PIN_FINGER_PINKY +#define FINGER_PINKY_ENABLED (PIN_FINGER_PINKY != -1) +#else +#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_INVERT>(CURL_PIN) \ + ); \ + NAME##_sensor->addFilters({ new ::SenseShift::Input::Filter::ExponentialMovingAverageFilter<float>(0.8F) }); \ + NAME##_sensor->setCalibrator((CURL_CALIB)); + +#ifdef PIN_FINGER_THUMB_SPLAY +#define FINGER_THUMB_SPLAY (FINGER_THUMB_ENABLED && (PIN_FINGER_THUMB_SPLAY != -1)) +#else +#define FINGER_THUMB_SPLAY false +#endif + +#ifdef PIN_FINGER_INDEX_SPLAY +#define FINGER_INDEX_SPLAY (FINGER_INDEX_ENABLED && (PIN_FINGER_INDEX_SPLAY != -1)) +#else +#define FINGER_INDEX_SPLAY false +#endif + +#ifdef PIN_FINGER_MIDDLE_SPLAY +#define FINGER_MIDDLE_SPLAY (FINGER_MIDDLE_ENABLED && (PIN_FINGER_MIDDLE_SPLAY != -1)) +#else +#define FINGER_MIDDLE_SPLAY false +#endif + +#ifdef PIN_FINGER_RING_SPLAY +#define FINGER_RING_SPLAY (FINGER_RING_ENABLED && (PIN_FINGER_RING_SPLAY != -1)) +#else +#define FINGER_RING_SPLAY false +#endif + +#ifdef PIN_FINGER_PINKY_SPLAY +#define FINGER_PINKY_SPLAY (FINGER_PINKY_ENABLED && (PIN_FINGER_PINKY_SPLAY != -1)) +#else +#define FINGER_PINKY_SPLAY false +#endif + +#define DEFINE_FINGER_SPLAY(NAME, CURL_PIN, CURL_INVERT, CURL_CALIB, SPLAY_PIN, SPLAY_INVERT, SPLAY_CALIB) \ + DEFINE_FINGER(NAME##_curl, CURL_PIN, CURL_INVERT, CURL_CALIB); \ + DEFINE_FINGER(NAME##_splay, SPLAY_PIN, SPLAY_INVERT, SPLAY_CALIB); #pragma endregion #pragma region Joysticks -#define JOYSTICK_ENABLED \ - (defined(PIN_JOYSTICK_X) && defined(PIN_JOYSTICK_Y) && (PIN_JOYSTICK_X != -1) && (PIN_JOYSTICK_Y != -1)) +#if defined(PIN_JOYSTICK_X) && defined(PIN_JOYSTICK_Y) +#define JOYSTICK_ENABLED (PIN_JOYSTICK_X != -1) && (PIN_JOYSTICK_Y != -1) +#else +#define JOYSTICK_ENABLED false +#endif -#define JOYSTICK_CLASS(type, pin, invert, deadzone) \ - StringEncodedMemoizedSensor<uint16_t>( \ - new ::SenseShift::Input::JoystickAxisSensor<uint16_t>( \ - new ::SenseShift::Input::StaticMedianSensor<uint16_t, 5>( \ - new ::SenseShift::Arduino::Input::AnalogSensor<invert>(pin) \ - ), \ - deadzone \ - ), \ - type \ - ) +#define DEFINE_JOYSTICK_AXIS(NAME, PIN, INVERT, DEADZONE) \ + auto NAME##_sensor = \ + new ::SenseShift::Input::SimpleSensorDecorator(new ::SenseShift::Arduino::Input::AnalogSimpleSensor<INVERT>(PIN) \ + ); \ + NAME##_sensor->addFilters({ new ::SenseShift::Input::Filter::ExponentialMovingAverageFilter<float>(0.8F), \ + new ::SenseShift::Input::Filter::CenterDeadzoneFilter(DEADZONE) }); #pragma endregion @@ -112,27 +144,24 @@ #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)) -#define BUTTON_CLASS(_type, _pin, _invert) \ - StringEncodedMemoizedSensor<bool>(new ::SenseShift::Arduino::Input::BinarySensor<_invert>(_pin), _type) +#define BUTTON_CLASS(PIN, INVERT) SimpleSensorDecorator(new DigitalSimpleSensor<INVERT>(PIN)); #pragma endregion #pragma region Gestures #ifndef GESTURE_TRIGGER_THRESHOLD -#define GESTURE_TRIGGER_THRESHOLD (ANALOG_MAX / 2) +#define GESTURE_TRIGGER_THRESHOLD (0.5F) #endif #ifndef GESTURE_GRAB_THRESHOLD -#define GESTURE_GRAB_THRESHOLD (ANALOG_MAX / 2) +#define GESTURE_GRAB_THRESHOLD (0.5F) #endif #ifndef GESTURE_PINCH_THRESHOLD -#define GESTURE_PINCH_THRESHOLD (ANALOG_MAX / 2) +#define GESTURE_PINCH_THRESHOLD (0.5F) #endif -#define GESTURE_CLASS(_type, _sensor) StringEncodedMemoizedSensor<bool>(_sensor, _type) - #pragma endregion #define FFB_THUMB_ENABLED (defined(PIN_FFB_THUMB) && (PIN_FFB_THUMB != -1)) diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index 267711c3..fa948e4d 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -15,4 +15,6 @@ namespace SenseShift::OpenGloves { virtual auto hasData() -> bool = 0; virtual auto read(char* buffer, size_t length) -> size_t = 0; }; + + using InputSensors = og::InputPeripheral<::SenseShift::Input::FloatSensor*, ::SenseShift::Input::BinarySensor*>; } // namespace SenseShift::OpenGloves diff --git a/lib/opengloves/sensor/og_finger.hpp b/lib/opengloves/sensor/og_finger.hpp deleted file mode 100644 index 95760b7a..00000000 --- a/lib/opengloves/sensor/og_finger.hpp +++ /dev/null @@ -1,156 +0,0 @@ -#pragma once - -#include <optional> - -#include "og_sensor.hpp" - -namespace OpenGloves { - struct FingerSensors { - std::vector<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> curl = - std::vector<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*>(); - std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay = std::nullopt; - - FingerSensors( - std::vector<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> curl, - std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay = std::nullopt - ) : - curl(curl), splay(splay){}; - - FingerSensors( - SenseShift::Input::CalibratedSimpleSensor<uint16_t>* curl1, - std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay = std::nullopt - ) : - curl({ curl1 }), splay(splay){}; - }; - - class ICurl { - public: - /** - * Get finger curl value. - */ - virtual uint16_t getCurl() = 0; - }; - - using IFingerSensor = SenseShift::Input::ISimpleSensor<FingerValue>; - - class SimpleFingerSensor : public IFingerSensor, public ICurl { - public: - SimpleFingerSensor(FingerSensors sensors) : sensors(sensors){}; - - SimpleFingerSensor( - SenseShift::Input::CalibratedSimpleSensor<uint16_t>* curl1, - std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay = std::nullopt - ) : - sensors(curl1, splay){}; - - void init() override - { - for (auto sensor : sensors.curl) { - sensor->init(); - } - if (sensors.splay.has_value()) { - sensors.splay.value()->init(); - } - } - - [[nodiscard]] auto getValue() -> FingerValue override - { - FingerValue value{ - .curl = std::vector<uint16_t>(), - .splay = std::nullopt, - }; - for (auto sensor : sensors.curl) { - value.curl.push_back(sensor->getValue()); - } - if (sensors.splay.has_value()) { - value.splay = sensors.splay.value()->getValue(); - } - return value; - } - - [[nodiscard]] auto getCurl() -> uint16_t override { return this->getValue().getTotalCurl(); } - - protected: - FingerSensors sensors; - }; - - /** - * Simple finger sensor that only provides calibration. - */ - class CalibratedFingerSensor : public SimpleFingerSensor, public SenseShift::Calibration::ICalibrated { - public: - CalibratedFingerSensor(FingerSensors sensors) : SimpleFingerSensor(sensors){}; - - CalibratedFingerSensor( - SenseShift::Input::CalibratedSimpleSensor<uint16_t>* curl1, - std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay = std::nullopt - ) : - SimpleFingerSensor(curl1, splay){}; - - void resetCalibration() override - { - for (auto sensor : this->sensors.curl) { - sensor->resetCalibration(); - } - if (this->sensors.splay.has_value()) { - this->sensors.splay.value()->resetCalibration(); - } - } - - void enableCalibration() override - { - for (auto sensor : this->sensors.curl) { - sensor->enableCalibration(); - } - if (this->sensors.splay.has_value()) { - this->sensors.splay.value()->enableCalibration(); - } - } - - void disableCalibration() override - { - for (auto sensor : this->sensors.curl) { - sensor->disableCalibration(); - } - if (this->sensors.splay.has_value()) { - this->sensors.splay.value()->disableCalibration(); - } - } - }; - - class FingerSensor : - public StringEncodedMemoizedSensor<FingerValue>, - public SenseShift::Calibration::ICalibrated, - public ICurl { - public: - FingerSensor(CalibratedFingerSensor* sensor, IEncodedInput::Type type) : - StringEncodedMemoizedSensor<FingerValue>(sensor, type){}; - - FingerSensor( - SenseShift::Input::CalibratedSimpleSensor<uint16_t>* curl1, - std::optional<SenseShift::Input::CalibratedSimpleSensor<uint16_t>*> splay, - IEncodedInput::Type type - ) : - StringEncodedMemoizedSensor<FingerValue>(new CalibratedFingerSensor(curl1, splay), type){}; - - FingerSensor(SenseShift::Input::CalibratedSimpleSensor<uint16_t>* curl1, IEncodedInput::Type type) : - StringEncodedMemoizedSensor<FingerValue>(new CalibratedFingerSensor(curl1, std::nullopt), type){}; - - void resetCalibration() override { static_cast<CalibratedFingerSensor*>(this->getSensor())->resetCalibration(); } - - void enableCalibration() override { static_cast<CalibratedFingerSensor*>(this->getSensor())->enableCalibration(); } - - void disableCalibration() override { static_cast<CalibratedFingerSensor*>(this->getSensor())->disableCalibration(); } - - uint16_t getCurl() override { return this->getValue().getTotalCurl(); } - }; - - struct HandSensors { - std::optional<FingerSensor> thumb = std::nullopt; - std::optional<FingerSensor> index = std::nullopt; - std::optional<FingerSensor> middle = std::nullopt; - std::optional<FingerSensor> ring = std::nullopt; - std::optional<FingerSensor> pinky = std::nullopt; - }; - -} // namespace OpenGloves diff --git a/lib/opengloves/sensor/og_sensor.hpp b/lib/opengloves/sensor/og_sensor.hpp deleted file mode 100644 index e43dba74..00000000 --- a/lib/opengloves/sensor/og_sensor.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include <cstdint> -#include <optional> -#include <vector> - -#include <og_protocol.hpp> -#include <senseshift/input/sensor.hpp> - -namespace OpenGloves { - struct FingerValue { - std::vector<std::uint16_t> curl = std::vector<std::uint16_t>({ 0 }); - std::optional<std::uint16_t> splay = std::nullopt; - - [[nodiscard]] auto getTotalCurl() const -> std::uint16_t - { - if (this->curl.empty()) { - return 0; - } - - std::uint16_t total = 0; - for (auto c_curl : this->curl) { - total += c_curl; - } - return total / this->curl.size(); - } - }; - - template<typename _Tp> - class StringEncodedMemoizedSensor : - public IStringEncodedMemoizedSensor, - public SenseShift::Input::MemoizedSensor<_Tp> { - public: - StringEncodedMemoizedSensor(SenseShift::Input::ISimpleSensor<_Tp>* sensor, IEncodedInput::Type type) : - IStringEncodedMemoizedSensor(type), SenseShift::Input::MemoizedSensor<_Tp>(sensor){}; - - void init() override { this->getSensor()->init(); } - - void updateValue() override { this->value_ = this->sensor_->getValue(); } - - [[nodiscard]] size_t getEncodedLength() const override; - - size_t encodeString(char* buffer) override; - }; -} // namespace OpenGloves diff --git a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp index f249f954..d3128165 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp @@ -1,18 +1,17 @@ #pragma once +#include <senseshift/buffer.hpp> + #include <BLESerial.hpp> #include <BluetoothSerial.h> #include <HardwareSerial.h> #include <Print.h> #include <WiFi.h> -#include <og_protocol.hpp> -#include <senseshift/opengloves/interface.hpp> +#include <senseshift/opengloves/opengloves.hpp> namespace SenseShift::OpenGloves { class IStreamTransport : public ITransport { - using IStringEncodedMemoizedSensor = ::OpenGloves::IStringEncodedMemoizedSensor; - protected: Stream* channel; char* buffer = new char[256]; @@ -57,7 +56,7 @@ namespace SenseShift::OpenGloves { StreamTransport(Stream& channel) : IStreamTransport(&channel){}; StreamTransport(Stream* channel) : IStreamTransport(channel){}; - void setup() override { this->mReady = true; } + void init() override { this->mReady = true; } bool isReady() override { return this->channel != nullptr && this->mReady; } @@ -101,7 +100,7 @@ namespace SenseShift::OpenGloves { public: WiFiSerialTransport(WiFiServer& server) : IStreamTransport(nullptr), m_server(server){}; - void setup() override + void init() override { auto* client = static_cast<WiFiClient*>(this->channel); if (client != nullptr) { diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp index 4fb4f43f..c327890d 100644 --- a/lib/opengloves_task/opengloves_task.hpp +++ b/lib/opengloves_task/opengloves_task.hpp @@ -4,15 +4,12 @@ #include <optional> -#include <og_ffb.hpp> #include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/input/sensor/binary.hpp> -#include <senseshift/calibration.hpp> +#include <senseshift/arduino/input/sensor/digital.hpp> #include <senseshift/freertos/task.hpp> #include <senseshift/input/sensor.hpp> -#include <senseshift/input/sensor/joystick.hpp> #include <senseshift/opengloves/encoding/alpha.hpp> -#include <senseshift/opengloves/interface.hpp> +#include <senseshift/opengloves/opengloves.hpp> #include <senseshift/utility.hpp> #include <sensor/og_finger.hpp> #include <sensor/og_gesture.hpp> From 3b8a90edb35a5ca2c6eca9d8871fe33e093a583a Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 8 Feb 2024 14:14:17 +0400 Subject: [PATCH 56/82] refactor(FreeRTOS): make SensorUpdateTask universal for components --- firmware/mode_configs/bhaptics/tactal.cpp | 12 ++-- firmware/mode_configs/bhaptics/tactglove.cpp | 12 ++-- firmware/mode_configs/bhaptics/tactosy2.cpp | 12 ++-- firmware/mode_configs/bhaptics/tactosyf.cpp | 12 ++-- firmware/mode_configs/bhaptics/tactosyh.cpp | 12 ++-- .../mode_configs/bhaptics/tactsuit_x16.cpp | 14 ++--- .../bhaptics/tactsuit_x16_pca9685.cpp | 14 ++--- .../mode_configs/bhaptics/tactsuit_x40.cpp | 12 ++-- firmware/mode_configs/bhaptics/tactvisor.cpp | 12 ++-- lib/battery/senseshift/battery/sensor.hpp | 18 +++--- lib/core/senseshift/core/helpers.hpp | 23 ++++---- .../senseshift/freertos/input/sensor.hpp | 32 ---------- lib/freertos/senseshift/freertos/task.hpp | 54 ++++++++++++++--- lib/io/senseshift/input/filter.hpp | 59 +++++++++---------- 14 files changed, 150 insertions(+), 148 deletions(-) diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index 6be10fed..efab08b5 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -58,13 +58,13 @@ void setupMode() #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ - new MultiplyFilter(3.3F), // Convert to raw pin voltage - new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( - batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 874cd07a..8d3fa066 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -66,13 +66,13 @@ void setupMode() #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ - new MultiplyFilter(3.3F), // Convert to raw pin voltage - new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( - batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index 572e52ad..f18515f9 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -59,13 +59,13 @@ void setupMode() #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ - new MultiplyFilter(3.3F), // Convert to raw pin voltage - new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( - batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index 51b67d9f..886857c3 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -60,13 +60,13 @@ void setupMode() #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ - new MultiplyFilter(3.3F), // Convert to raw pin voltage - new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( - batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 277dcb0d..5646060f 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -60,13 +60,13 @@ void setupMode() #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ - new MultiplyFilter(3.3F), // Convert to raw pin voltage - new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( - batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 5ba9322c..7a448b06 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -30,7 +30,7 @@ Application* app = &App; static const std::array<OutputLayout, BH_LAYOUT_TACTSUITX16_SIZE> bhLayout = { BH_LAYOUT_TACTSUITX16 }; // Ouput indices, responsible for x40 => x16 grouping -static const std::array<std::uint8_t,BH_LAYOUT_TACTSUITX16_GROUPS_SIZE> layoutGroups = BH_LAYOUT_TACTSUITX16_GROUPS; +static const std::array<std::uint8_t, BH_LAYOUT_TACTSUITX16_GROUPS_SIZE> layoutGroups = BH_LAYOUT_TACTSUITX16_GROUPS; void setupMode() { @@ -69,13 +69,13 @@ void setupMode() #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ - new MultiplyFilter(3.3F), // Convert to raw pin voltage - new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( - batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index 256222a8..38ea195f 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -30,7 +30,7 @@ Application* app = &App; static const std::array<OutputLayout, BH_LAYOUT_TACTSUITX16_SIZE> bhLayout = { BH_LAYOUT_TACTSUITX16 }; // Ouput indices, responsible for x40 => x16 grouping -static const std::array<std::uint8_t,BH_LAYOUT_TACTSUITX16_GROUPS_SIZE> layoutGroups = BH_LAYOUT_TACTSUITX16_GROUPS; +static const std::array<std::uint8_t, BH_LAYOUT_TACTSUITX16_GROUPS_SIZE> layoutGroups = BH_LAYOUT_TACTSUITX16_GROUPS; void setupMode() { @@ -74,13 +74,13 @@ void setupMode() #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ - new MultiplyFilter(3.3F), // Convert to raw pin voltage - new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( - batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 0057140f..6454ed61 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -83,13 +83,13 @@ void setupMode() #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ - new MultiplyFilter(3.3F), // Convert to raw pin voltage - new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( - batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index f47cf4f5..1135d457 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -58,13 +58,13 @@ void setupMode() #if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ - new MultiplyFilter(3.3F), // Convert to raw pin voltage - new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage + new MultiplyFilter(3.3F), // Convert to raw pin voltage + new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new SensorUpdateTask<SimpleSensorDecorator<float>>( - batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( + batteryVoltageSensor, + SENSESHIFT_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/lib/battery/senseshift/battery/sensor.hpp b/lib/battery/senseshift/battery/sensor.hpp index fdfa525d..19cfc6de 100644 --- a/lib/battery/senseshift/battery/sensor.hpp +++ b/lib/battery/senseshift/battery/sensor.hpp @@ -26,12 +26,13 @@ namespace SenseShift::Battery { using VoltageType = typename BatteryState::VoltageType; using VoltageSource = ::SenseShift::Input::Sensor<VoltageType>; - LookupTableInterpolateBatterySensor( - VoltageSource* voltage_source, - Container* lookup_table - ) : IBatterySensor(), voltage_source_(voltage_source), lookup_table_(lookup_table) {} + LookupTableInterpolateBatterySensor(VoltageSource* voltage_source, Container* lookup_table) : + IBatterySensor(), voltage_source_(voltage_source), lookup_table_(lookup_table) + { + } - void init() override { + void init() override + { this->voltage_source_->init(); this->voltage_source_->addValueCallback([this](VoltageType voltage) { // Current level in % (0.0 - 1.0) @@ -40,7 +41,7 @@ namespace SenseShift::Battery { LOG_D("battery.sensor", "voltage=%f, level=%f", voltage, level); const BatteryState value = { - .level = static_cast<typename BatteryState::LevelType>(level * BatteryState::MAX_LEVEL), + .level = static_cast<typename BatteryState::LevelType>(level * BatteryState::MAX_LEVEL), }; this->publishState(value); @@ -48,8 +49,9 @@ namespace SenseShift::Battery { } protected: - [[nodiscard]] auto lookupInterpolateLevel(VoltageType voltage) -> float { - return ::SenseShift::lookup_interpolate<VoltageType, float, Container>(*this->lookup_table_, voltage); + [[nodiscard]] auto lookupInterpolateLevel(VoltageType voltage) -> float + { + return ::SenseShift::lookup_table_interpolate<VoltageType, float, Container>(*this->lookup_table_, voltage); } private: diff --git a/lib/core/senseshift/core/helpers.hpp b/lib/core/senseshift/core/helpers.hpp index 14d8e897..1d4fb8b1 100644 --- a/lib/core/senseshift/core/helpers.hpp +++ b/lib/core/senseshift/core/helpers.hpp @@ -73,13 +73,13 @@ namespace SenseShift { /// \param value /// /// \return - template <typename Tp, typename To, typename Container> - auto lookup_interpolate(Container const& lookup_table, Tp value) -> To + template<typename Tp, typename To, typename Container> + auto lookup_table_interpolate(Container const& lookup_table, Tp value) -> To { static_assert(std::is_same_v<typename Container::key_type, Tp>); static_assert(std::is_same_v<typename Container::mapped_type, To>); - static_assert(std::is_arithmetic_v<Tp>, "lookup_interpolate only supports arithmetic types"); - static_assert(std::is_arithmetic_v<To>, "lookup_interpolate only supports arithmetic types"); + static_assert(std::is_arithmetic_v<Tp>, "lookup_table_interpolate only supports arithmetic types"); + static_assert(std::is_arithmetic_v<To>, "lookup_table_interpolate 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) { @@ -102,20 +102,21 @@ namespace SenseShift { template<typename... X> class CallbackManager; - /// Helper class to allow having multiple subscribers to a callback. - /// - /// \tparam Ts The arguments for the callbacks, wrapped in void(). + /// Helper class to allow having multiple subscribers to a callback. + /// + /// \tparam Ts The arguments for the callbacks, wrapped in void(). template<typename... Ts> class CallbackManager<void(Ts...)> { public: using CallbackType = std::function<void(Ts...)>; /// Add a callback to the list. - void add(std::function<void(Ts...)> &&callback) { this->callbacks_.push_back(std::move(callback)); } + void add(std::function<void(Ts...)>&& callback) { this->callbacks_.push_back(std::move(callback)); } /// Call all callbacks in this manager. - void call(Ts... args) { - for (auto &callback : this->callbacks_) { + void call(Ts... args) + { + for (auto& callback : this->callbacks_) { callback(args...); } } @@ -127,4 +128,4 @@ namespace SenseShift { private: std::vector<std::function<void(Ts...)>> callbacks_; }; -} // namespace SenseShift +} // namespace SenseShift diff --git a/lib/freertos/senseshift/freertos/input/sensor.hpp b/lib/freertos/senseshift/freertos/input/sensor.hpp index fbd34918..2a31d67d 100644 --- a/lib/freertos/senseshift/freertos/input/sensor.hpp +++ b/lib/freertos/senseshift/freertos/input/sensor.hpp @@ -6,37 +6,5 @@ #include <cstdint> namespace SenseShift::FreeRTOS::Input { - /// Sensor update task - template<typename Sensor> - class SensorUpdateTask : public Task<SensorUpdateTask<Sensor>> { - static_assert(std::is_same_v<decltype(&Sensor::init), void (Sensor::*)()>); - static_assert(std::is_same_v<decltype(&Sensor::tick), void (Sensor::*)()>); - public: - SensorUpdateTask(Sensor* sensor, std::uint32_t updateDelay, TaskConfig taskConfig) : - Task<SensorUpdateTask>(taskConfig), sensor_(sensor), updateDelay_(updateDelay) { - log_i("creating SensorUpdateTask: %s", taskConfig.name); - }; - - void begin() override { - this->sensor_->init(); - this->Task<SensorUpdateTask>::begin(); - } - - protected: - [[noreturn]] void run() - { - while (true) { - this->sensor_->tick(); - delay(this->updateDelay_); - // log_i("high watermark %d", uxTaskGetStackHighWaterMark(NULL)); - } - } - - private: - friend class Task<SensorUpdateTask>; - - Sensor* sensor_; - std::uint32_t updateDelay_; - }; } // namespace SenseShift::FreeRTOS::Input diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index ea7c942a..9bea8bd8 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -39,8 +39,9 @@ namespace SenseShift::FreeRTOS { friend class Task; public: - explicit Task(TaskConfig& config) : taskConfig(config) { - log_i("creating SensorUpdateTask: %s", taskConfig.name); + explicit Task(TaskConfig& config) : taskConfig(config) + { + log_i("creating ComponentUpdateTask: %s", taskConfig.name); }; virtual ~Task() { @@ -83,17 +84,17 @@ namespace SenseShift::FreeRTOS { 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 + "Task: %s\n\tStack High Watermark: %d\n\tState: %d\n", + pxTaskStatusArray[i].pcTaskName, + pxTaskStatusArray[i].usStackHighWaterMark, + pxTaskStatusArray[i].eCurrentState ); if (pxTaskStatusArray[i].usStackHighWaterMark < 20) { log_w( - "Warning: Task %s has low stack space, only %dB awailable!", - pxTaskStatusArray[i].pcTaskName, - pxTaskStatusArray[i].usStackHighWaterMark * 4 + "Warning: Task %s has low stack space, only %dB awailable!", + pxTaskStatusArray[i].pcTaskName, + pxTaskStatusArray[i].usStackHighWaterMark * 4 ); } } @@ -110,4 +111,39 @@ namespace SenseShift::FreeRTOS { task->run(); } }; + + template<typename Tp> + class ComponentUpdateTask : public Task<ComponentUpdateTask<Tp>> { + static_assert(std::is_same_v<decltype(&Tp::init), void (Tp::*)()>); + static_assert(std::is_same_v<decltype(&Tp::tick), void (Tp::*)()>); + + public: + ComponentUpdateTask(Tp* component, std::uint32_t updateDelay, TaskConfig taskConfig) : + Task<ComponentUpdateTask>(taskConfig), component_(component), updateDelay_(updateDelay) + { + log_i("creating ComponentUpdateTask: %s", taskConfig.name); + }; + + void begin() override + { + this->component_->init(); + this->Task<ComponentUpdateTask>::begin(); + } + + protected: + [[noreturn]] void run() + { + while (true) { + this->component_->tick(); + delay(this->updateDelay_); + // log_i("high watermark %d", uxTaskGetStackHighWaterMark(NULL)); + } + } + + private: + friend class Task<ComponentUpdateTask>; + + Tp* component_; + std::uint32_t updateDelay_; + }; } // namespace SenseShift::FreeRTOS diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index a86ef341..75f65dc2 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -38,10 +38,7 @@ namespace SenseShift::Input::Filter { public: explicit AddFilter(Tp offset) : offset_(offset){}; - auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override - { - return value + this->offset_; - } + auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override { return value + this->offset_; } private: Tp offset_; @@ -66,10 +63,7 @@ namespace SenseShift::Input::Filter { public: explicit SubtractFilter(Tp offset) : offset_(offset){}; - auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override - { - return value - this->offset_; - } + auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override { return value - this->offset_; } private: Tp offset_; @@ -80,12 +74,9 @@ namespace SenseShift::Input::Filter { public: explicit MultiplyFilter(Tp factor) : factor_(factor){}; - auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override - { - return value * this->factor_; - } + auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override { return value * this->factor_; } - private: + private: Tp factor_; }; @@ -131,12 +122,9 @@ namespace SenseShift::Input::Filter { public: using Lambda = std::function<Tp(Tp)>; - explicit LambdaFilter(Lambda filter) : filter_(std::move(filter)) {}; + explicit LambdaFilter(Lambda filter) : filter_(std::move(filter)){}; - auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override - { - return this->filter_(value); - } + auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override { return this->filter_(value); } private: Lambda filter_; @@ -147,7 +135,10 @@ namespace SenseShift::Input::Filter { class SampleAverageFilter : public IFilter<Tp> { static_assert(std::is_arithmetic_v<Tp>, "SampleAverageFilter only supports arithmetic types"); static_assert(std::is_same_v<typename Sensor::ValueType, Tp>, "Sensor type must match filter type"); - static_assert(std::is_same_v<decltype(&Sensor::readRawValue), void (Sensor::*)()>, "Can only use sensors with readRawValue()"); + static_assert( + std::is_same_v<decltype(&Sensor::readRawValue), void (Sensor::*)()>, + "Can only use sensors with readRawValue()" + ); public: explicit SampleAverageFilter(std::size_t size) : size_(size){}; @@ -173,10 +164,12 @@ namespace SenseShift::Input::Filter { template<typename Tp, typename Sensor> class SampleMedianFilter : public IFilter<Tp> { static_assert(std::is_same_v<typename Sensor::ValueType, Tp>, "Sensor type must match filter type"); - // static_assert(std::is_same_v<decltype(&Sensor::readRawValue), Tp (Sensor::*)()>, "Can only use sensors with readRawValue()"); + // static_assert(std::is_same_v<decltype(&Sensor::readRawValue), Tp (Sensor::*)()>, "Can only use sensors with + // readRawValue()"); public: - explicit SampleMedianFilter(std::size_t size_) : size_(size_) { + explicit SampleMedianFilter(std::size_t size_) : size_(size_) + { // allocate the array this->values = new Tp[size_]; }; @@ -213,7 +206,7 @@ namespace SenseShift::Input::Filter { static_assert(std::is_arithmetic_v<Tp>, "SlidingWindowAverageFilter only supports arithmetic types"); public: - explicit SlidingWindowMovingAverageFilter(size_t window_size) : window_size_(window_size) { }; + explicit SlidingWindowMovingAverageFilter(size_t window_size) : window_size_(window_size){}; auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override { @@ -244,7 +237,7 @@ namespace SenseShift::Input::Filter { static_assert(std::is_arithmetic_v<Tp>, "ExponentialMovingAverageFilter only supports arithmetic types"); public: - explicit ExponentialMovingAverageFilter(float alpha) : alpha_(alpha) { }; + explicit ExponentialMovingAverageFilter(float alpha) : alpha_(alpha){}; auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override { @@ -260,8 +253,7 @@ namespace SenseShift::Input::Filter { /// 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<float> - { + class CenterDeadzoneFilter : public IFilter<float> { public: explicit CenterDeadzoneFilter(float deadzone) : deadzone_(deadzone){}; @@ -271,28 +263,31 @@ namespace SenseShift::Input::Filter { return deviation < deadzone_ ? CENTER : value; } - private: + private: static constexpr float CENTER = 0.5F; 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 <typename Tp, typename Container> - class LookupTableInterpolationFilter : public IFilter<Tp> - { + template<typename Tp, typename Container> + class LookupTableInterpolationFilter : public IFilter<Tp> { static_assert(std::is_same_v<typename Container::value_type, Tp>); static_assert(std::is_arithmetic_v<Tp>, "LookupTableInterpolationFilter only supports arithmetic types"); public: - explicit LookupTableInterpolationFilter(Container const& lookup_table) : lookup_table_(lookup_table) {}; + explicit LookupTableInterpolationFilter(Container const& lookup_table) : lookup_table_(lookup_table){}; auto filter(ISimpleSensor<float>* /*sensor*/, Tp value) -> Tp override { - return SenseShift::lookup_interpolate<Tp, Container>(this->lookup_table_, value); + return SenseShift::lookup_table_interpolate<Tp, Container>(this->lookup_table_, value); } private: Container const& lookup_table_; }; -} // namespace SenseShift::Input +} // namespace SenseShift::Input::Filter From 13f3b54ec42c1c54fd5d4598af1166131559e5f3 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 8 Feb 2024 14:22:20 +0400 Subject: [PATCH 57/82] test(Gestures): refactor old OG tests --- test/test_body_gestures/main.cpp | 104 ++++++++++++++++++++++++++ test/test_opengloves_gesture/main.cpp | 102 ------------------------- 2 files changed, 104 insertions(+), 102 deletions(-) create mode 100644 test/test_body_gestures/main.cpp delete mode 100644 test/test_opengloves_gesture/main.cpp diff --git a/test/test_body_gestures/main.cpp b/test/test_body_gestures/main.cpp new file mode 100644 index 00000000..57d543ea --- /dev/null +++ b/test/test_body_gestures/main.cpp @@ -0,0 +1,104 @@ +#include <senseshift/body/hands/input/gesture.hpp> +#include <senseshift/input/sensor.hpp> +#include <unity.h> + +using namespace SenseShift::Input; +using namespace SenseShift::Body::Hands::Input; + +void test_gesture_trigger(void) +{ + float threshold = 0.5f; + auto* index = new FloatSensor(); + + auto* gesture = new TriggerGesture(index, threshold, true); + + index->publishState(0.4f); + TEST_ASSERT_FALSE(gesture->getValue()); + + index->publishState(0.6f); + TEST_ASSERT_TRUE(gesture->getValue()); +} + +void test_gesture_grab(void) +{ + float threshold = 0.5f; + + auto* index = new FloatSensor(); + auto* middle = new FloatSensor(); + auto* ring = new FloatSensor(); + auto* pinky = new FloatSensor(); + + auto* gesture = new GrabGesture( + { + .index = index, + .middle = middle, + .ring = ring, + .pinky = pinky, + }, + threshold, + true + ); + + TEST_ASSERT_FALSE(gesture->getValue()); + + index->publishState(0.6); + TEST_ASSERT_FALSE(gesture->getValue()); + + middle->publishState(0.6); + TEST_ASSERT_FALSE(gesture->getValue()); + + ring->publishState(0.6); + TEST_ASSERT_FALSE(gesture->getValue()); + + pinky->publishState(0.6); + TEST_ASSERT_TRUE(gesture->getValue()); +} + +void test_gesture_pinch(void) +{ + float threshold = 0.5f; + + auto* thumb = new FloatSensor(); + auto* index = new FloatSensor(); + + auto* gesture = new PinchGesture({ .thumb = thumb, .index = index }, threshold, true); + + TEST_ASSERT_FALSE(gesture->getValue()); + + thumb->publishState(0.6f); + TEST_ASSERT_FALSE(gesture->getValue()); + + index->publishState(0.6f); + TEST_ASSERT_TRUE(gesture->getValue()); +} + +int process(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_gesture_grab); + RUN_TEST(test_gesture_trigger); + RUN_TEST(test_gesture_pinch); + + return UNITY_END(); +} + +#ifdef ARDUINO + +#include <Arduino.h> + +void setup(void) +{ + process(); +} + +void loop(void) {} + +#else + +int main(int argc, char** argv) +{ + return process(); +} + +#endif diff --git a/test/test_opengloves_gesture/main.cpp b/test/test_opengloves_gesture/main.cpp deleted file mode 100644 index db4f7057..00000000 --- a/test/test_opengloves_gesture/main.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include <senseshift/body/hands/gestures/grab.hpp> -#include <unity.h> - -using namespace OpenGloves; - -class TestCurlFinger : public ICurl { - public: - uint16_t value; - - TestCurlFinger(uint16_t initialValue = 0) : value(initialValue){}; - - uint16_t getCurl() override { return this->value; } -}; - -void test_gesture_grab(void) -{ - uint16_t threshold = 2047; - - auto index = TestCurlFinger(threshold - 1); - auto middle = TestCurlFinger(threshold - 1); - auto ring = TestCurlFinger(threshold - 1); - auto pinky = TestCurlFinger(threshold - 1); - - auto gesture = GrabGesture(index, middle, ring, pinky, threshold); - - TEST_ASSERT_FALSE(gesture.getValue()); - - index.value = threshold + 1; - TEST_ASSERT_FALSE(gesture.getValue()); - - middle.value = threshold + 1; - TEST_ASSERT_FALSE(gesture.getValue()); - - ring.value = threshold + 1; - TEST_ASSERT_FALSE(gesture.getValue()); - - pinky.value = threshold + 1; - TEST_ASSERT_TRUE(gesture.getValue()); -} - -void test_gesture_trigger(void) -{ - uint16_t threshold = 2047; - - auto index = TestCurlFinger(threshold - 1); - - auto gesture = TriggerGesture(index, threshold); - - TEST_ASSERT_FALSE(gesture.getValue()); - - index.value = threshold + 1; - TEST_ASSERT_TRUE(gesture.getValue()); -} - -void test_gesture_pinch(void) -{ - uint16_t threshold = 2047; - - auto index = TestCurlFinger(threshold - 1); - auto middle = TestCurlFinger(threshold - 1); - - auto gesture = PinchGesture(index, middle, threshold); - - TEST_ASSERT_FALSE(gesture.getValue()); - - index.value = threshold + 1; - TEST_ASSERT_FALSE(gesture.getValue()); - - middle.value = threshold + 1; - TEST_ASSERT_TRUE(gesture.getValue()); -} - -int process(void) -{ - UNITY_BEGIN(); - - RUN_TEST(test_gesture_grab); - RUN_TEST(test_gesture_trigger); - RUN_TEST(test_gesture_pinch); - - return UNITY_END(); -} - -#ifdef ARDUINO - -#include <Arduino.h> - -void setup(void) -{ - process(); -} - -void loop(void) {} - -#else - -int main(int argc, char** argv) -{ - return process(); -} - -#endif From 809f14e68d27f67c2422e284f27060c6999755c8 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 8 Feb 2024 18:30:24 +0400 Subject: [PATCH 58/82] fix: sensor template deduction --- 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 +- .../mode_configs/bhaptics/tactsuit_x16.cpp | 2 +- .../bhaptics/tactsuit_x16_pca9685.cpp | 2 +- .../mode_configs/bhaptics/tactsuit_x40.cpp | 2 +- firmware/mode_configs/bhaptics/tactvisor.cpp | 2 +- .../mode_configs/opengloves/opengloves.cpp | 2 +- lib/io/senseshift/input/analog_threshold.hpp | 51 +++++++++++-------- test/test_body_gestures/main.cpp | 15 ++++-- 12 files changed, 52 insertions(+), 34 deletions(-) diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index efab08b5..e68ee5a1 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<SimpleSensorDecorator<float>>( batteryVoltageSensor, SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 8d3fa066..024bf872 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<SimpleSensorDecorator<float>>( batteryVoltageSensor, SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index f18515f9..21dfa3c1 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<SimpleSensorDecorator<float>>( batteryVoltageSensor, SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index 886857c3..9b9a4a60 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<SimpleSensorDecorator<float>>( batteryVoltageSensor, SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 5646060f..11fa6192 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<SimpleSensorDecorator<float>>( batteryVoltageSensor, SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 7a448b06..72d82490 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<SimpleSensorDecorator<float>>( batteryVoltageSensor, SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_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 38ea195f..d5826492 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -77,7 +77,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<SimpleSensorDecorator<float>>( batteryVoltageSensor, SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 6454ed61..ce0b0a8e 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.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<SimpleSensorDecorator<float>>( batteryVoltageSensor, SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index 1135d457..128f2199 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<SimpleSensorDecorator<float>>( batteryVoltageSensor, SENSESHIFT_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 6666dc3f..d25e5733 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -122,7 +122,7 @@ void setupMode() #endif #if GESTURE_TRIGGER_ENABLED - auto* trigger = new AnalogThresholdSensor(index_curl_sensor, GESTURE_TRIGGER_THRESHOLD); + auto* trigger = new 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); diff --git a/lib/io/senseshift/input/analog_threshold.hpp b/lib/io/senseshift/input/analog_threshold.hpp index eb03eec5..46eb53d4 100644 --- a/lib/io/senseshift/input/analog_threshold.hpp +++ b/lib/io/senseshift/input/analog_threshold.hpp @@ -1,55 +1,66 @@ #pragma once #include "senseshift/input/sensor.hpp" +#include <type_traits> namespace SenseShift::Input { - template<typename Tp> + template<typename Tp = float> class AnalogThresholdSensor : public BinarySensor, ITickable { - public: + 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<Tp>* source, - Tp threshold_upper, - float threshold_lower, - bool attach_callbacks = false - ) : source_(source), threshold_upper_(threshold_upper), threshold_lower_(threshold_lower), attach_callbacks_(attach_callbacks) {} + ::SenseShift::Input::Sensor<Tp>* 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 <typename U = Tp, std::enable_if_t<std::is_same_v<U, float>, int> = 0> + template<typename U = Tp, std::enable_if_t<std::is_same_v<U, float>, int> = 0> explicit AnalogThresholdSensor( - ::SenseShift::Input::Sensor<Tp>* source, - float threshold = 0.5f, - bool attach_callbacks = false - ) : AnalogThresholdSensor(source, threshold, threshold, attach_callbacks) { } + ::SenseShift::Input::Sensor<Tp>* source, float threshold = 0.5f, bool attach_callbacks = false + ) : + AnalogThresholdSensor(source, threshold, threshold, attach_callbacks) + { + } - void init() override { + void init() override + { SS_SUBSENSOR_INIT(this->source_, this->attach_callbacks_, [this](Tp /*value*/) { this->recalculateState(); }); } - void tick() override { + void tick() override + { if (this->attach_callbacks_) { - LOG_E("sensor.analog_threshold", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); + 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(); + void recalculateState() + { + const auto sensor_value = this->source_->getValue(); this->publishState(sensor_value >= (this->getValue() ? this->threshold_lower_ : this->threshold_upper_)); } - private: + private: ::SenseShift::Input::Sensor<Tp>* source_; - float threshold_lower_, threshold_upper_; + Tp threshold_lower_, threshold_upper_; bool attach_callbacks_ = false; }; -} \ No newline at end of file +} // namespace SenseShift::Input diff --git a/test/test_body_gestures/main.cpp b/test/test_body_gestures/main.cpp index 57d543ea..5f9e800d 100644 --- a/test/test_body_gestures/main.cpp +++ b/test/test_body_gestures/main.cpp @@ -10,12 +10,14 @@ void test_gesture_trigger(void) float threshold = 0.5f; auto* index = new FloatSensor(); - auto* gesture = new TriggerGesture(index, threshold, true); + auto* gesture = new TriggerGesture(index, threshold); index->publishState(0.4f); + gesture->tick(); TEST_ASSERT_FALSE(gesture->getValue()); index->publishState(0.6f); + gesture->tick(); TEST_ASSERT_TRUE(gesture->getValue()); } @@ -35,22 +37,25 @@ void test_gesture_grab(void) .ring = ring, .pinky = pinky, }, - threshold, - true + threshold ); TEST_ASSERT_FALSE(gesture->getValue()); index->publishState(0.6); + gesture->tick(); TEST_ASSERT_FALSE(gesture->getValue()); middle->publishState(0.6); + gesture->tick(); TEST_ASSERT_FALSE(gesture->getValue()); ring->publishState(0.6); + gesture->tick(); TEST_ASSERT_FALSE(gesture->getValue()); pinky->publishState(0.6); + gesture->tick(); TEST_ASSERT_TRUE(gesture->getValue()); } @@ -61,14 +66,16 @@ void test_gesture_pinch(void) auto* thumb = new FloatSensor(); auto* index = new FloatSensor(); - auto* gesture = new PinchGesture({ .thumb = thumb, .index = index }, threshold, true); + auto* gesture = new PinchGesture({ .thumb = thumb, .index = index }, threshold); TEST_ASSERT_FALSE(gesture->getValue()); thumb->publishState(0.6f); + gesture->tick(); TEST_ASSERT_FALSE(gesture->getValue()); index->publishState(0.6f); + gesture->tick(); TEST_ASSERT_TRUE(gesture->getValue()); } From f43319a60840e6341e254c811518ea4152bdc861 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 8 Feb 2024 20:27:27 +0400 Subject: [PATCH 59/82] test(OpenGloves): update old alpha-encoding unit test --- .github/workflows/ci.yml | 20 +- lib/io/senseshift/input/calibration.hpp | 105 +++++++--- lib/opengloves/opengloves/opengloves.cpp | 103 ++++++--- lib/opengloves/opengloves/opengloves.hpp | 2 +- test/test_opengloves/main.cpp | 159 -------------- test/test_opengloves_alpha_encoding/main.cpp | 210 +++++++++++-------- test/test_opengloves_finger/main.cpp | 177 ---------------- 7 files changed, 281 insertions(+), 495 deletions(-) delete mode 100644 test/test_opengloves/main.cpp delete mode 100644 test/test_opengloves_finger/main.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bade01aa..6a12df0c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [ ubuntu-latest ] target: - bhaptics_tactsuit_x16 - bhaptics_tactsuit_x16_pca9685 @@ -32,10 +32,10 @@ jobs: - bhaptics_tactal - bhaptics_tactvisor - bhaptics_tactglove_right - battery_flag: [SENSESHIFT_BATTERY_ENABLED=true] - serial_plotter_flag: [SENSESHIFT_SERIAL_PLOTTER=false] - nimble_flag: [SENSESHIFT_BLE_USE_NIMBLE=false] - coverage: [false] + battery_flag: [ SENSESHIFT_BATTERY_ENABLED=true ] + serial_plotter_flag: [ SENSESHIFT_SERIAL_PLOTTER=false ] + nimble_flag: [ SENSESHIFT_BLE_USE_NIMBLE=false ] + coverage: [ false ] include: # Extra tests for x40, as it uses the most features @@ -165,7 +165,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [ ubuntu-latest ] target: - lucidgloves-prototype3 - lucidgloves-prototype4 @@ -176,20 +176,20 @@ jobs: comm_flag: - COMMUNICATION_PROTOCOL=OPENGLOVES_COMM_SERIAL - COMMUNICATION_PROTOCOL=OPENGLOVES_COMM_BTSERIAL - coverage: [false] + coverage: [ false ] include: - os: ubuntu-latest target: lucidgloves-prototype4-ffb - curl_calibration_flag: CALIBRATION_CURL="::SenseShift::Calibration::MinMaxCalibrator<uint16_t, 0, ANALOG_MAX>" + curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::MinMaxCalibrator<float>()" coverage: true - os: ubuntu-latest target: lucidgloves-prototype4-ffb - curl_calibration_flag: CALIBRATION_CURL="::SenseShift::Calibration::CenterPointDeviationCalibrator<uint16_t, 20, 270, 0, ANALOG_MAX>" + curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::CenterPointDeviationCalibrator<float>(0.66F, 0.005F)" coverage: true - os: ubuntu-latest target: lucidgloves-prototype4-ffb - curl_calibration_flag: CALIBRATION_CURL="::SenseShift::Calibration::FixedCenterPointDeviationCalibrator<uint16_t, 20, 270, 0, ANALOG_MAX>" + curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::FixedCenterPointDeviationCalibrator<float>(0.66F, 0.005F)" coverage: true - os: ubuntu-latest target: indexer-csf diff --git a/lib/io/senseshift/input/calibration.hpp b/lib/io/senseshift/input/calibration.hpp index 51412389..b5a271a5 100644 --- a/lib/io/senseshift/input/calibration.hpp +++ b/lib/io/senseshift/input/calibration.hpp @@ -33,21 +33,25 @@ namespace SenseShift::Input::Calibration { 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) {} + 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<typename U = Tp, std::enable_if_t<std::is_same_v<U, float>, 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) {} + 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 { + void reset() override + { value_min_ = output_max_; value_max_ = output_min_; } - void update(ValueType input) override { + void update(ValueType input) override + { // Update the min and the max. if (input < value_min_) { value_min_ = input; @@ -57,7 +61,8 @@ namespace SenseShift::Input::Calibration { } } - auto calibrate(ValueType input) const -> ValueType override { + 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_) { @@ -73,7 +78,8 @@ namespace SenseShift::Input::Calibration { } // Map the input range to the output range. - ValueType output = ::SenseShift::remap<ValueType, ValueType>(input, value_min_, value_max_, output_min_, output_max_); + ValueType output = + ::SenseShift::remap<ValueType, ValueType>(input, value_min_, value_max_, output_min_, output_max_); // Lock the range to the output. return std::clamp(output, output_min_, output_max_); @@ -89,43 +95,63 @@ namespace SenseShift::Input::Calibration { template<typename Tp> class CenterPointDeviationCalibrator : public ICalibrator<Tp> { - static_assert(std::is_arithmetic_v<Tp>, "CenterPointDeviationCalibrator only can be used with arithmetic types"); + static_assert( + std::is_arithmetic_v<Tp>, "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) {} + 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<typename U = Tp, std::enable_if_t<std::is_same_v<U, float>, 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) {} + 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 { + void reset() override + { this->range_min_ = this->sensor_max_; this->range_max_ = 0; } - void update(Tp input) override { + void update(Tp input) override + { // Update the min and the max. if (input < this->range_min_) { - this->range_min_ = ::SenseShift::remap<ValueType>(input, this->output_min_, this->output_max_, 0, this->sensor_max_); + this->range_min_ = + ::SenseShift::remap<ValueType>(input, this->output_min_, this->output_max_, 0, this->sensor_max_); } if (input > this->range_max_) { - this->range_max_ = ::SenseShift::remap<ValueType>(input, this->output_min_, this->output_max_, 0, this->sensor_max_); + this->range_max_ = + ::SenseShift::remap<ValueType>(input, this->output_min_, this->output_max_, 0, this->sensor_max_); } } - auto calibrate(ValueType input) const -> ValueType 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->range_min_ + this->range_max_) / 2.0F; // Map the input to the sensor range of motion. - int output = ::SenseShift::accurateMap<Tp>(input, this->output_min_, this->output_max_, 0, this->sensor_max_); + int output = + ::SenseShift::accurateMap<Tp>(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<int>(output - center, -(this->driver_max_deviation_), this->driver_max_deviation_); @@ -152,20 +178,39 @@ namespace SenseShift::Input::Calibration { template<typename Tp> class FixedCenterPointDeviationCalibrator : public ICalibrator<Tp> { - static_assert(std::is_arithmetic_v<Tp>, "FixedCenterPointDeviationCalibrator only can be used with arithmetic types"); + static_assert( + std::is_arithmetic_v<Tp>, "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) {} + ) : + sensor_max_(sensor_max), + driver_max_deviation_(driver_max_deviation), + output_min_(output_min), + output_max_(output_max) + { + } + + template<typename U = Tp, std::enable_if_t<std::is_same_v<U, float>, 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 { + 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; @@ -185,10 +230,10 @@ namespace SenseShift::Input::Calibration { ); } - private: + private: const Tp sensor_max_; const Tp driver_max_deviation_; const Tp output_min_; const Tp output_max_; }; -} // namespace SenseShift::Input::Calibration +} // namespace SenseShift::Input::Calibration diff --git a/lib/opengloves/opengloves/opengloves.cpp b/lib/opengloves/opengloves/opengloves.cpp index 951391b6..0411c6d9 100644 --- a/lib/opengloves/opengloves/opengloves.cpp +++ b/lib/opengloves/opengloves/opengloves.cpp @@ -1,9 +1,24 @@ #include "opengloves/opengloves.hpp" +#include <cmath> #include <cstdint> #include <cstdio> #include <variant> +#ifdef OG_ENCODE_FAST +template<typename Tp = int, typename Tu = float> +auto ifloor(Tu x) -> Tp +{ + return (Tp) x - (x < (Tp) x); +} + +template<typename Tp = int, typename Tu = float> +auto iceil(Tu x) -> Tp +{ + return (Tp) x + (x > (Tp) x); +} +#endif + namespace og { auto AlphaEncoder::encode_input(const InputData& input, char* buffer, size_t length) const -> size_t @@ -32,52 +47,84 @@ namespace og { const auto peripheral = std::get<InputPeripheralData>(input); auto written = 0; - const auto& curl = peripheral.curl.fingers; + const auto& curls = peripheral.curl.fingers; + const auto& splays = peripheral.splay.fingers; #ifdef OG_ENCODE_FAST - for (auto i = 0; i < curl.size(); i++) { - const auto& finger = curl[i]; + 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%.0f", 'A' + i, finger_curl * MAX_ANALOG_VALUE); + written += snprintf( + buffer + written, + length - written, + "%c%u", + 'A' + i, + ifloor<std::uint8_t, float>(finger_curl * MAX_ANALOG_VALUE) + ); } #else - for (auto i = 0; i < curl.size(); i++) { - const auto& finger = curl[i]; - const auto& joints = finger.curl; + 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%.0f", + finger_alpha_key, + std::floor(finger_curl.curl_total * MAX_ANALOG_VALUE) + ); + + if (finger_splay > 0.0F) { + written += snprintf( + buffer + written, + length - written, + "(%cB)%.0f", + finger_alpha_key, + std::floor(finger_splay * MAX_ANALOG_VALUE) + ); + } - for (auto j = 0; j < joints.size(); j++) { + 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; - // skip if joint is 0.0, except total_curl (it is probably not enabled) - if (joint == 0.0F && j != 0) { + if (joint == 0.0F) { continue; } - const auto& jointKey = AlphaEncoder::FINGER_CURL_JOINT_ALPHA_KEY[i][j]; - - written += - snprintf(buffer + written, length - written, "%s%.0f", jointKey.data(), joint * MAX_ANALOG_VALUE); + written += snprintf( + buffer + written, + length - written, + "(%cA%c)%.0f", + finger_alpha_key, + joint_alpha_key, + std::floor(joint * MAX_ANALOG_VALUE) + ); } } - - const auto& splay = peripheral.splay.fingers; - for (auto i = 0; i < splay.size(); i++) { - const auto& finger = splay[i]; - - if (finger == 0.0F) { - continue; - } - +#endif + if (peripheral.joystick.x != 0.0F) { written += snprintf( buffer + written, length - written, - "(%cB)%.0f", - AlphaEncoder::FINGER_ALPHA_KEY[i], - finger * MAX_ANALOG_VALUE + "F%.0f", + std::floor(peripheral.joystick.x * MAX_ANALOG_VALUE) ); } -#endif + if (peripheral.joystick.y != 0.0F) { + written += snprintf( + buffer + written, + length - written, + "G%.0f", + std::floor(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++) { diff --git a/lib/opengloves/opengloves/opengloves.hpp b/lib/opengloves/opengloves/opengloves.hpp index d01bbfeb..7cfbda4f 100644 --- a/lib/opengloves/opengloves/opengloves.hpp +++ b/lib/opengloves/opengloves/opengloves.hpp @@ -231,7 +231,7 @@ namespace og { 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 = 4096; + 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<frozen::string, Command> diff --git a/test/test_opengloves/main.cpp b/test/test_opengloves/main.cpp deleted file mode 100644 index 7f607d6f..00000000 --- a/test/test_opengloves/main.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include <sensor/og_sensor.hpp> -#include <unity.h> - -using namespace OpenGloves; - -class TestAnalogSensor : public SenseShift::Input::ISimpleSensor<uint16_t> { - private: - uint16_t count = 0; - - public: - int setupCounter = 0; - - void init() override { this->setupCounter++; }; - - uint16_t getValue() override { return ++this->count; }; -}; - -class TestBinarySensor : public SenseShift::Input::ISimpleSensor<bool> { - public: - bool value = false; - int setupCounter = 0; - - void init() override { this->setupCounter++; }; - - bool getValue() override { return this->value; }; -}; - -class TestFingerSensor : public SenseShift::Input::ISimpleSensor<FingerValue> { - public: - FingerValue value; - int setupCounter = 0; - - void init() override { this->setupCounter++; }; - - FingerValue getValue() override { return this->value; }; -}; - -void test_string_encoded_sensor_uint16(void) -{ - auto inner = new TestAnalogSensor(); - auto sensor = new StringEncodedMemoizedSensor<uint16_t>(inner, IEncodedInput::Type::INDEX); - - TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->init(); - TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); - - TEST_ASSERT_EQUAL_INT(0, sensor->getValue()); - TEST_ASSERT_EQUAL_INT(0, sensor->getValue()); - - sensor->updateValue(); - - TEST_ASSERT_EQUAL_INT(1, sensor->getValue()); - TEST_ASSERT_EQUAL_INT(1, sensor->getValue()); - - char buffer[6]; - TEST_ASSERT_EQUAL_INT(2, sensor->encodeString(buffer)); - TEST_ASSERT_EQUAL_STRING("B1", buffer); -} - -void test_string_encoded_sensor_bool(void) -{ - auto inner = new TestBinarySensor(); - auto sensor = new StringEncodedMemoizedSensor<bool>(inner, IEncodedInput::Type::A_BTN); - - TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->init(); - TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); - - TEST_ASSERT_FALSE(sensor->getValue()); - - char buffer[1]; - TEST_ASSERT_EQUAL_INT(0, sensor->encodeString(buffer)); - TEST_ASSERT_EQUAL_STRING("", buffer); - - sensor->updateValue(); - - TEST_ASSERT_FALSE(sensor->getValue()); - - inner->value = true; - - TEST_ASSERT_FALSE(sensor->getValue()); - - sensor->updateValue(); - - TEST_ASSERT_TRUE(sensor->getValue()); - - TEST_ASSERT_EQUAL_INT(1, sensor->encodeString(buffer)); - TEST_ASSERT_EQUAL_STRING("J", buffer); -} - -void test_string_encoded_sensor_fingervalue(void) -{ - auto inner = new TestFingerSensor(); - auto sensor = new StringEncodedMemoizedSensor<FingerValue>(inner, IEncodedInput::Type::THUMB); - - TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->init(); - TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); - - // curl-only - char buffer[sensor->getEncodedLength()]; - sensor->encodeString(buffer); - TEST_ASSERT_EQUAL_STRING("A0", buffer); - - inner->value.curl = { 256 }; - sensor->updateValue(); - sensor->encodeString(buffer); - TEST_ASSERT_EQUAL_STRING("A256", buffer); - - // curl + splay - inner->value.splay = 420; - sensor->updateValue(); - sensor->encodeString(buffer); - TEST_ASSERT_EQUAL_STRING("A256(AB)420", buffer); - - // multi-curl - inner->value.curl = { 128, 256, 512 }; - inner->value.splay = std::nullopt; - sensor->updateValue(); - sensor->encodeString(buffer); - TEST_ASSERT_EQUAL_STRING("A298(AAA)128(AAB)256(AAC)512", buffer); // 298 = (128 + 256 + 512) / 3 - - // multi-curl + splay - inner->value.splay = 69; - sensor->updateValue(); - sensor->encodeString(buffer); - TEST_ASSERT_EQUAL_STRING("A298(AAA)128(AAB)256(AAC)512(AB)69", buffer); // 298 = (128 + 256 + 512) / 3 -} - -int process(void) -{ - UNITY_BEGIN(); - - RUN_TEST(test_string_encoded_sensor_uint16); - RUN_TEST(test_string_encoded_sensor_bool); - RUN_TEST(test_string_encoded_sensor_fingervalue); - - return UNITY_END(); -} - -#ifdef ARDUINO - -#include <Arduino.h> - -void setup(void) -{ - process(); -} - -void loop(void) {} - -#else - -int main(int argc, char** argv) -{ - return process(); -} - -#endif diff --git a/test/test_opengloves_alpha_encoding/main.cpp b/test/test_opengloves_alpha_encoding/main.cpp index 68be53cd..2d599457 100644 --- a/test/test_opengloves_alpha_encoding/main.cpp +++ b/test/test_opengloves_alpha_encoding/main.cpp @@ -1,111 +1,141 @@ -#include <senseshift/opengloves/encoding/alpha.hpp> +#include <opengloves/opengloves.hpp> #include <unity.h> -using namespace OpenGloves; -using namespace SenseShift::OpenGloves; +using namespace og; -void testSplitCommands(void) +void test_encode_input_peripherals(void) { - std::map<std::string, std::map<Command, int>> input_strings = { - // curl only + const IEncoder* encoder = new AlphaEncoder(); + + const std::vector<std::tuple<InputPeripheralData, std::string>> cases = { { - "A2048\n\0", - { - { Command::ThumbCurl, 2048 }, - }, + InputPeripheralData({ + .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, + }, + }, + }), + "A2047B2047C2047D2047E2047\n", }, - // curl only { - "A100B200C300D400E500", - { - { Command::ThumbCurl, 100 }, - { Command::IndexCurl, 200 }, - { Command::MiddleCurl, 300 }, - { Command::RingCurl, 400 }, - { Command::PinkyCurl, 500 }, - }, + InputPeripheralData({ + .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, + }, + }, + }), + "A0B0C0D0E0\n", }, - // curl (unordered) { - "E500A100B200D400C300", - { - { Command::ThumbCurl, 100 }, - { Command::IndexCurl, 200 }, - { Command::MiddleCurl, 300 }, - { Command::RingCurl, 400 }, - { Command::PinkyCurl, 500 }, - }, + InputPeripheralData({ + .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, + }, + }, + }), + "A4095B4095C4095D4095E4095\n", }, - // curl (with invalid data) { - "A100B200C300D400E", - { - { Command::ThumbCurl, 100 }, - { Command::IndexCurl, 200 }, - { Command::MiddleCurl, 300 }, - { Command::RingCurl, 400 }, - }, + InputPeripheralData({ + .splay = { + .thumb = 0.5, + .index = 0.5, + .middle = 0.5, + .ring = 0.5, + .pinky = 0.5, + }, + }), + "A0(AB)2047B0(BB)2047C0(CB)2047D0(DB)2047E0(EB)2047\n", }, - // curl (with unknown prefix) { - "X100A100B200C300D400E500", - { - { Command::ThumbCurl, 100 }, - { Command::IndexCurl, 200 }, - { Command::MiddleCurl, 300 }, - { Command::RingCurl, 400 }, - { Command::PinkyCurl, 500 }, - }, + InputPeripheralData({ + .joystick = { + .x = 0.5, + .y = 0.5, + .press = true, + }, + }), + "A0B0C0D0E0F2047G2047H\n" }, - // curl + splay { - "A1(AB)2B3(BB)4C5(CB)6D7(DB)8E9(EB)10", - { - { Command::ThumbCurl, 1 }, - { Command::ThumbSplay, 2 }, - { Command::IndexCurl, 3 }, - { Command::IndexSplay, 4 }, - { Command::MiddleCurl, 5 }, - { Command::MiddleSplay, 6 }, - { Command::RingCurl, 7 }, - { Command::RingSplay, 8 }, - { Command::PinkyCurl, 9 }, - { Command::PinkySplay, 10 }, - }, + InputPeripheralData({ + .buttons = { true, false, false, true }, + }), + "A0B0C0D0E0JO\n" }, - // curl + splay (unordered) { - "E9A1B3D7C5(BB)4(AB)2(EB)10(CB)6(DB)8", - { - { Command::ThumbCurl, 1 }, - { Command::ThumbSplay, 2 }, - { Command::IndexCurl, 3 }, - { Command::IndexSplay, 4 }, - { Command::MiddleCurl, 5 }, - { Command::MiddleSplay, 6 }, - { Command::RingCurl, 7 }, - { Command::RingSplay, 8 }, - { Command::PinkyCurl, 9 }, - { Command::PinkySplay, 10 }, - }, - }, + InputPeripheralData({ + .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, + }, + }, + .splay = { + .thumb = 0.5, + .index = 0.5, + .middle = 0.5, + .ring = 0.5, + .pinky = 0.5, + }, + }), + "A2047(AB)2047B2047(BB)2047C2047(CB)2047D2047(DB)2047E2047(EB)2047\n", + } }; - auto encoding_service = AlphaEncodingService(); - - for (auto& [input_string, expected_commands] : input_strings) { - std::map<Command, uint16_t> commands = {}; - encoding_service.deserialize(input_string.c_str(), input_string.length(), commands); - - TEST_ASSERT_EQUAL_size_t_MESSAGE( - expected_commands.size(), - commands.size(), - "Expected commands size does not match actual commands size" - ); - - for (auto& [command, value] : expected_commands) { - TEST_ASSERT_EQUAL_INT(value, commands[command]); - } + for (const auto& [data, expected] : cases) { + const auto encoded = encoder->encode_input(data); + TEST_ASSERT_EQUAL_STRING(expected.c_str(), encoded.c_str()); } } @@ -113,7 +143,7 @@ int process(void) { UNITY_BEGIN(); - RUN_TEST(testSplitCommands); + RUN_TEST(test_encode_input_peripherals); return UNITY_END(); } diff --git a/test/test_opengloves_finger/main.cpp b/test/test_opengloves_finger/main.cpp deleted file mode 100644 index 569bcda8..00000000 --- a/test/test_opengloves_finger/main.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include <sensor/og_finger.hpp> -#include <unity.h> - -using namespace OpenGloves; -using namespace SenseShift::Calibration; - -class TestAnalogSensor : public SenseShift::Input::ISimpleSensor<uint16_t> { - private: - uint16_t count = 0; - - public: - int setupCounter = 0; - - void init() override { this->setupCounter++; }; - - uint16_t getValue() override { return this->count++; }; -}; - -class DummyCalibrator : public ICalibrator<uint16_t> { - public: - uint8_t resetCounter = 0; - std::optional<uint16_t> calibrated = std::nullopt; - - void reset() override - { - this->resetCounter++; - this->calibrated = std::nullopt; - }; - void update(uint16_t input) override { this->calibrated = input; }; - uint16_t calibrate(uint16_t input) const override { return this->calibrated.value_or(input); }; -}; - -void test_simple_finger_sensor_curl(void) -{ - auto* inner = new TestAnalogSensor(); - auto* calibrator = new DummyCalibrator(); - auto* calibrated = new SenseShift::Input::CalibratedSimpleSensor<uint16_t>(inner, calibrator); - auto* sensor = new SimpleFingerSensor(calibrated); - - TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->init(); - TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); - - // since the sensor is not memoized, the value is updated on every call - TEST_ASSERT_EQUAL_INT(0, sensor->getValue().curl[0]); - TEST_ASSERT_EQUAL_INT(1, sensor->getCurl()); - - calibrator->calibrated = 100; - - TEST_ASSERT_EQUAL_INT(100, sensor->getValue().curl[0]); // 2 is inside - TEST_ASSERT_EQUAL_INT(100, sensor->getCurl()); // 3 is inside - - calibrator->calibrated = std::nullopt; - - TEST_ASSERT_EQUAL_INT(4, sensor->getValue().curl[0]); - TEST_ASSERT_EQUAL_INT(5, sensor->getCurl()); -} - -void test_simple_finger_sensor_curl_flex(void) -{ - auto* inner_curl = new TestAnalogSensor(); - auto* calibrator_curl = new DummyCalibrator(); - auto* calibrated_curl = new SenseShift::Input::CalibratedSimpleSensor<uint16_t>(inner_curl, calibrator_curl); - - auto* inner_flex = new TestAnalogSensor(); - auto* calibrator_flex = new DummyCalibrator(); - auto* calibrated_flex = new SenseShift::Input::CalibratedSimpleSensor<uint16_t>(inner_flex, calibrator_flex); - - auto* sensor = new SimpleFingerSensor(calibrated_curl, calibrated_flex); - - TEST_ASSERT_EQUAL_INT(0, inner_curl->setupCounter); - TEST_ASSERT_EQUAL_INT(0, inner_flex->setupCounter); - sensor->init(); - TEST_ASSERT_EQUAL_INT(1, inner_curl->setupCounter); - TEST_ASSERT_EQUAL_INT(1, inner_flex->setupCounter); - - // since the sensor is not memoized, the value is updated on every call - TEST_ASSERT_EQUAL_INT(0, sensor->getValue().curl[0]); - TEST_ASSERT_EQUAL_INT(1, sensor->getValue().splay.value()); - TEST_ASSERT_EQUAL_INT(2, sensor->getCurl()); - - calibrator_curl->calibrated = 100; - calibrator_flex->calibrated = 200; - - TEST_ASSERT_EQUAL_INT(100, sensor->getValue().curl[0]); // 3 is inside - TEST_ASSERT_EQUAL_INT(200, sensor->getValue().splay.value()); // 4 is inside - TEST_ASSERT_EQUAL_INT(100, sensor->getCurl()); // 5 is inside - - calibrator_curl->calibrated = std::nullopt; - calibrator_flex->calibrated = std::nullopt; - - TEST_ASSERT_EQUAL_INT(6, sensor->getValue().curl[0]); - TEST_ASSERT_EQUAL_INT(7, sensor->getValue().splay.value()); - TEST_ASSERT_EQUAL_INT(8, sensor->getCurl()); -} - -// todo: tests for multi-curl - -void test_finger_sensor_curl(void) -{ - auto* inner = new TestAnalogSensor(); - auto* calibrator = new DummyCalibrator(); - auto* calibrated = new SenseShift::Input::CalibratedSimpleSensor<uint16_t>(inner, calibrator); - auto* sensor = new FingerSensor(calibrated, IEncodedInput::Type::INDEX); - - TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->init(); - TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); - - TEST_ASSERT_EQUAL_INT(0, sensor->getValue().curl[0]); - TEST_ASSERT_EQUAL_INT(0, sensor->getCurl()); - - sensor->updateValue(); - - TEST_ASSERT_EQUAL_INT(0, sensor->getValue().curl[0]); - TEST_ASSERT_EQUAL_INT(0, sensor->getCurl()); - - calibrator->calibrated = 100; - - TEST_ASSERT_EQUAL_INT(0, sensor->getValue().curl[0]); - TEST_ASSERT_EQUAL_INT(0, sensor->getCurl()); - - sensor->updateValue(); // +1 is inside - - TEST_ASSERT_EQUAL_INT(100, sensor->getValue().curl[0]); - TEST_ASSERT_EQUAL_INT(100, sensor->getCurl()); - - TEST_ASSERT_EQUAL_INT(0, calibrator->resetCounter); - sensor->resetCalibration(); - TEST_ASSERT_EQUAL_INT(1, calibrator->resetCounter); - - sensor->enableCalibration(); - sensor->updateValue(); // +1 is inside - TEST_ASSERT_EQUAL_INT(2, sensor->getValue().curl[0]); - TEST_ASSERT_EQUAL_INT(2, sensor->getCurl()); - - sensor->updateValue(); // +1 is inside - TEST_ASSERT_EQUAL_INT(3, sensor->getValue().curl[0]); - TEST_ASSERT_EQUAL_INT(3, sensor->getCurl()); - - sensor->disableCalibration(); - sensor->updateValue(); // +1 is inside, but calibrated to 3 - TEST_ASSERT_EQUAL_INT(3, sensor->getValue().curl[0]); - TEST_ASSERT_EQUAL_INT(3, sensor->getCurl()); -} - -int process(void) -{ - UNITY_BEGIN(); - - RUN_TEST(test_simple_finger_sensor_curl); - RUN_TEST(test_simple_finger_sensor_curl_flex); - - RUN_TEST(test_finger_sensor_curl); - - return UNITY_END(); -} - -#ifdef ARDUINO - -#include <Arduino.h> - -void setup(void) -{ - process(); -} - -void loop(void) {} - -#else - -int main(int argc, char** argv) -{ - return process(); -} - -#endif From 48d827701088683b0f0a6816a3733e5021b027f8 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Fri, 9 Feb 2024 15:35:46 +0400 Subject: [PATCH 60/82] test: cover edge-cases --- firmware/mode_configs/bhaptics/tactal.cpp | 3 +- firmware/mode_configs/bhaptics/tactglove.cpp | 3 +- firmware/mode_configs/bhaptics/tactosy2.cpp | 3 +- firmware/mode_configs/bhaptics/tactosyf.cpp | 3 +- firmware/mode_configs/bhaptics/tactosyh.cpp | 3 +- .../mode_configs/bhaptics/tactsuit_x16.cpp | 3 +- .../bhaptics/tactsuit_x16_pca9685.cpp | 3 +- .../mode_configs/bhaptics/tactsuit_x40.cpp | 3 +- firmware/mode_configs/bhaptics/tactvisor.cpp | 3 +- include/senseshift.h | 4 +- .../senseshift/{ => battery}/battery.hpp | 32 +---- .../{sensor.hpp => input/battery_sensor.hpp} | 15 +- .../senseshift/bh/ble/connection.hpp | 7 +- lib/io/senseshift/input/calibration.hpp | 3 +- lib/opengloves/opengloves/opengloves.hpp | 16 ++- lib/util/senseshift/range.hpp | 21 --- lib/util/senseshift/utility.hpp | 2 +- test/test_battery/main.cpp | 53 +++++++ test/test_body_gestures/main.cpp | 18 +-- test/test_core_helpers/main.cpp | 132 ++++++++++++++++++ .../main.cpp | 0 test/test_opengloves_alpha_encoding/main.cpp | 36 ++++- test/test_util_buffer/main.cpp | 1 - .../main.cpp | 29 +--- 24 files changed, 274 insertions(+), 122 deletions(-) rename lib/battery/senseshift/{ => battery}/battery.hpp (50%) rename lib/battery/senseshift/battery/{sensor.hpp => input/battery_sensor.hpp} (85%) delete mode 100644 lib/util/senseshift/range.hpp create mode 100644 test/test_battery/main.cpp create mode 100644 test/test_core_helpers/main.cpp rename test/{test_util_calibration => test_io_calibration}/main.cpp (100%) rename test/{test_util => test_util_container}/main.cpp (63%) diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index e68ee5a1..8a452ab5 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -6,9 +6,9 @@ #include "senseshift.h" +#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/ledc.hpp> -#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -21,6 +21,7 @@ using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; +using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 024bf872..1fa2aa4e 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -6,9 +6,9 @@ #include "senseshift.h" +#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/ledc.hpp> -#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -22,6 +22,7 @@ using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; +using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index 21dfa3c1..e630072b 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -6,9 +6,9 @@ #include "senseshift.h" +#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/ledc.hpp> -#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -21,6 +21,7 @@ using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; +using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index 9b9a4a60..d35a6427 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -6,9 +6,9 @@ #include "senseshift.h" +#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/ledc.hpp> -#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -21,6 +21,7 @@ using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; +using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 11fa6192..3fd258cc 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -6,9 +6,9 @@ #include "senseshift.h" +#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/ledc.hpp> -#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -21,6 +21,7 @@ using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; +using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 72d82490..1f8bd345 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -6,9 +6,9 @@ #include "senseshift.h" +#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/ledc.hpp> -#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -21,6 +21,7 @@ using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; +using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index d5826492..e3ac3769 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -6,9 +6,9 @@ #include "senseshift.h" +#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pca9685.hpp> -#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -21,6 +21,7 @@ using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; +using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index ce0b0a8e..3a88f119 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -6,10 +6,10 @@ #include "senseshift.h" +#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/ledc.hpp> #include <senseshift/arduino/output/pca9685.hpp> -#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -22,6 +22,7 @@ using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; +using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index 128f2199..83b44903 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -6,9 +6,9 @@ #include "senseshift.h" +#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/ledc.hpp> -#include <senseshift/battery/sensor.hpp> #include <senseshift/bh/ble/connection.hpp> #include <senseshift/bh/devices.hpp> #include <senseshift/bh/encoding.hpp> @@ -21,6 +21,7 @@ using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; +using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; diff --git a/include/senseshift.h b/include/senseshift.h index ec98103d..d3d8629d 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -2,7 +2,7 @@ #include "config/all.h" -#include <senseshift/battery/sensor.hpp> +#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/body/haptics/body.hpp> #include <senseshift/events.hpp> @@ -21,6 +21,6 @@ namespace SenseShift { private: std::vector<const IEventListener*> event_listeners_{}; Body::Haptics::FloatBody* vibro_body_; - Battery::IBatterySensor* battery_ = nullptr; + Battery::Input::IBatterySensor* battery_ = nullptr; }; } // namespace SenseShift diff --git a/lib/battery/senseshift/battery.hpp b/lib/battery/senseshift/battery/battery.hpp similarity index 50% rename from lib/battery/senseshift/battery.hpp rename to lib/battery/senseshift/battery/battery.hpp index ed784445..0f4e587c 100644 --- a/lib/battery/senseshift/battery.hpp +++ b/lib/battery/senseshift/battery/battery.hpp @@ -2,39 +2,21 @@ #include <cstdint> #include <limits> -#include <algorithm> -#include <frozen/map.h> +#include "frozen/map.h" -#include <senseshift/events.hpp> +#include "senseshift/events.hpp" namespace SenseShift::Battery { namespace VoltageMap { /// Lookup table for LiPO 1S 4.2V batteries /// \see <a href="https://blog.ampow.com/lipo-voltage-chart/">Source</a> - [[maybe_unused]] inline static const auto LiPO_1S_42= frozen::make_map<float, float>({ - { 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 }, + [[maybe_unused]] inline static const auto LiPO_1S_42 = frozen::make_map<float, float>({ + { 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 diff --git a/lib/battery/senseshift/battery/sensor.hpp b/lib/battery/senseshift/battery/input/battery_sensor.hpp similarity index 85% rename from lib/battery/senseshift/battery/sensor.hpp rename to lib/battery/senseshift/battery/input/battery_sensor.hpp index 19cfc6de..d0314a03 100644 --- a/lib/battery/senseshift/battery/sensor.hpp +++ b/lib/battery/senseshift/battery/input/battery_sensor.hpp @@ -2,17 +2,12 @@ #include <cstdint> -#include "senseshift/battery.hpp" +#include "senseshift/battery/battery.hpp" -#include <senseshift/freertos/task.hpp> -#include <senseshift/input/sensor.hpp> -#include <senseshift/utility.hpp> +#include "senseshift/core/helpers.hpp" +#include "senseshift/input/sensor.hpp" -#ifndef SENSESHIFT_BATTERY_TASK_PRIORITY -#define SENSESHIFT_BATTERY_TASK_PRIORITY 1 -#endif - -namespace SenseShift::Battery { +namespace SenseShift::Battery::Input { /// Abstract battery sensor using IBatterySensor = ::SenseShift::Input::Sensor<BatteryState>; @@ -58,4 +53,4 @@ namespace SenseShift::Battery { VoltageSource* voltage_source_; Container* lookup_table_; }; -} // namespace SenseShift::Battery +} // namespace SenseShift::Battery::Input diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp index a0265f74..e5033fb1 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -1,6 +1,7 @@ #pragma once -#include <senseshift/battery.hpp> +#include "senseshift/battery/battery.hpp" +#include "senseshift/core/helpers.hpp" #include <senseshift/bh/ble/constants.hpp> #include <senseshift/bh/constants.hpp> #include <senseshift/events.hpp> @@ -44,9 +45,9 @@ namespace SenseShift::BH::BLE { void handleEvent(const IEvent* event) const override { if (event->eventName == OH_EVENT_BATTERY_LEVEL) { - uint16_t level = simpleMap<uint8_t>( + uint16_t level = remap_simple<std::uint8_t, std::uint8_t>( static_cast<const ::SenseShift::Battery::BatteryLevelEvent*>(event)->state.level, - 255, + ::SenseShift::Battery::BatteryState::MAX_LEVEL, 100 ); diff --git a/lib/io/senseshift/input/calibration.hpp b/lib/io/senseshift/input/calibration.hpp index b5a271a5..fd6ec99e 100644 --- a/lib/io/senseshift/input/calibration.hpp +++ b/lib/io/senseshift/input/calibration.hpp @@ -150,8 +150,7 @@ namespace SenseShift::Input::Calibration { Tp center = (this->range_min_ + this->range_max_) / 2.0F; // Map the input to the sensor range of motion. - int output = - ::SenseShift::accurateMap<Tp>(input, this->output_min_, this->output_max_, 0, this->sensor_max_); + int output = ::SenseShift::remap<Tp>(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<int>(output - center, -(this->driver_max_deviation_), this->driver_max_deviation_); diff --git a/lib/opengloves/opengloves/opengloves.hpp b/lib/opengloves/opengloves/opengloves.hpp index 7cfbda4f..fed4d11c 100644 --- a/lib/opengloves/opengloves/opengloves.hpp +++ b/lib/opengloves/opengloves/opengloves.hpp @@ -36,11 +36,15 @@ namespace og { template<typename Tf = float> union InputFingerCurl { std::array<Tf, 4> curl; // NOLINT(*-magic-numbers): I'm sure our finger aren't changing anytime soon - struct { + union { Tf curl_total; - Tf curl_joint1; - Tf curl_joint2; - Tf curl_joint3; + + struct { + Tf curl_joint0; + Tf curl_joint1; + Tf curl_joint2; + Tf curl_joint3; + }; }; }; using InputFingerCurlData = InputFingerCurl<float>; @@ -77,7 +81,7 @@ namespace og { using InputButtonData = InputButton<bool>; template<typename Tf = float, typename Tb = bool> - struct InputAnalogButton : InputButton<Tb> { + struct InputAnalogButton : public InputButton<Tb> { Tf value; }; using InputAnalogButtonData = InputAnalogButton<float, bool>; @@ -93,7 +97,7 @@ namespace og { InputJoystick<Tf, Tb> joystick; union { - std::array<InputButton<Tb>, 4> buttons; + std::array<InputButton<Tb>, 5> buttons; struct { InputButton<Tb> button_a; InputButton<Tb> button_b; diff --git a/lib/util/senseshift/range.hpp b/lib/util/senseshift/range.hpp deleted file mode 100644 index ea690108..00000000 --- a/lib/util/senseshift/range.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#include <cstdint> -#include <type_traits> - -#include <senseshift/core/logging.hpp> -#include <senseshift/core/helpers.hpp> - -namespace SenseShift { - /// Remap \p value from the range (\p min, \p max) to (\p min_out, \p max_out). - template<typename Tp> - constexpr auto accurateMap(Tp value, Tp min, Tp max, Tp min_out, Tp max_out) noexcept -> Tp - { - return remap<Tp, Tp>(value, min, max, min_out, max_out); - } - - // Same as the above, but both mins are 0. - template<typename Tp> - constexpr auto simpleMap(Tp value, Tp in_max, Tp out_max) noexcept -> Tp - { - return remap_simple<Tp, Tp>(value, in_max, out_max); - } -} // namespace SenseShift diff --git a/lib/util/senseshift/utility.hpp b/lib/util/senseshift/utility.hpp index 5c95fd01..595944a9 100644 --- a/lib/util/senseshift/utility.hpp +++ b/lib/util/senseshift/utility.hpp @@ -5,4 +5,4 @@ #include <type_traits> #include "senseshift/container.hpp" -#include "senseshift/range.hpp" +#include "senseshift/core/helpers.hpp" diff --git a/test/test_battery/main.cpp b/test/test_battery/main.cpp new file mode 100644 index 00000000..c563d37c --- /dev/null +++ b/test/test_battery/main.cpp @@ -0,0 +1,53 @@ +#include <senseshift/battery/input/battery_sensor.hpp> +#include <senseshift/input/sensor.hpp> +#include <unity.h> + +using namespace SenseShift::Input; +using namespace SenseShift::Battery; +using namespace SenseShift::Battery::Input; + +void test_battery_sensor(void) +{ + auto* source = new FloatSensor(); + + auto* battery = new LookupTableInterpolateBatterySensor(source, &VoltageMap::LiPO_1S_42); + battery->init(); + + source->publishState(0.f); + TEST_ASSERT_EQUAL_INT(0, battery->getValue().level); + + source->publishState(4.2f); + TEST_ASSERT_EQUAL_INT(255, battery->getValue().level); + + source->publishState(3.7f); + TEST_ASSERT_EQUAL_INT(31, battery->getValue().level); +} + +int process(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_battery_sensor); + + return UNITY_END(); +} + +#ifdef ARDUINO + +#include <Arduino.h> + +void setup(void) +{ + process(); +} + +void loop(void) {} + +#else + +int main(int argc, char** argv) +{ + return process(); +} + +#endif \ No newline at end of file diff --git a/test/test_body_gestures/main.cpp b/test/test_body_gestures/main.cpp index 5f9e800d..e63fb03f 100644 --- a/test/test_body_gestures/main.cpp +++ b/test/test_body_gestures/main.cpp @@ -10,14 +10,13 @@ void test_gesture_trigger(void) float threshold = 0.5f; auto* index = new FloatSensor(); - auto* gesture = new TriggerGesture(index, threshold); + auto* gesture = new TriggerGesture(index, threshold, true); + gesture->init(); index->publishState(0.4f); - gesture->tick(); TEST_ASSERT_FALSE(gesture->getValue()); index->publishState(0.6f); - gesture->tick(); TEST_ASSERT_TRUE(gesture->getValue()); } @@ -37,25 +36,23 @@ void test_gesture_grab(void) .ring = ring, .pinky = pinky, }, - threshold + threshold, + true ); + gesture->init(); TEST_ASSERT_FALSE(gesture->getValue()); index->publishState(0.6); - gesture->tick(); TEST_ASSERT_FALSE(gesture->getValue()); middle->publishState(0.6); - gesture->tick(); TEST_ASSERT_FALSE(gesture->getValue()); ring->publishState(0.6); - gesture->tick(); TEST_ASSERT_FALSE(gesture->getValue()); pinky->publishState(0.6); - gesture->tick(); TEST_ASSERT_TRUE(gesture->getValue()); } @@ -66,16 +63,15 @@ void test_gesture_pinch(void) auto* thumb = new FloatSensor(); auto* index = new FloatSensor(); - auto* gesture = new PinchGesture({ .thumb = thumb, .index = index }, threshold); + auto* gesture = new PinchGesture({ .thumb = thumb, .index = index }, threshold, true); + gesture->init(); TEST_ASSERT_FALSE(gesture->getValue()); thumb->publishState(0.6f); - gesture->tick(); TEST_ASSERT_FALSE(gesture->getValue()); index->publishState(0.6f); - gesture->tick(); TEST_ASSERT_TRUE(gesture->getValue()); } diff --git a/test/test_core_helpers/main.cpp b/test/test_core_helpers/main.cpp new file mode 100644 index 00000000..d13815bd --- /dev/null +++ b/test/test_core_helpers/main.cpp @@ -0,0 +1,132 @@ +#include <senseshift/core/helpers.hpp> +#include <unity.h> + +#include <map> +#include <cstdint> + +using namespace SenseShift; + +void test_lerp_uint8(void) +{ + TEST_ASSERT_EQUAL_UINT16(0, lerp<std::uint8_t>(0.0f, 0, 255)); + TEST_ASSERT_EQUAL_UINT16(127, lerp<std::uint8_t>(0.5f, 0, 255)); + TEST_ASSERT_EQUAL_UINT16(255, lerp<std::uint8_t>(1.0f, 0, 255)); + + TEST_ASSERT_EQUAL_UINT16(0, lerp<std::uint8_t>(0.0f, 0, 0)); +} + +void test_lerp_float(void) +{ + TEST_ASSERT_EQUAL_FLOAT(-1.0f, lerp<float>(0.0f, -1.0f, 1.0f)); + TEST_ASSERT_EQUAL_FLOAT(0.0f, lerp<float>(0.5f, -1.0f, 1.0f)); + TEST_ASSERT_EQUAL_FLOAT(1.0f, lerp<float>(1.0f, -1.0f, 1.0f)); + + TEST_ASSERT_EQUAL_FLOAT(0.0f, lerp<float>(0.0f, 0.0f, 0.0f)); +} + +void test_remap_uint16(void) +{ + TEST_ASSERT_EQUAL_UINT16(0, remap(0, 0, 4095, 0, 255)); + TEST_ASSERT_EQUAL_UINT16(127, remap(2047, 0, 4095, 0, 255)); + TEST_ASSERT_EQUAL_UINT16(255, remap(4095, 0, 4095, 0, 255)); + + TEST_ASSERT_EQUAL_UINT16(127, remap(0, 0, 4095, 127, 255)); + TEST_ASSERT_EQUAL_UINT16(190, remap(2047, 0, 4095, 127, 255)); + TEST_ASSERT_EQUAL_UINT16(255, remap(4095, 0, 4095, 127, 255)); + + TEST_ASSERT_EQUAL_UINT16(0, remap(2048, 2048, 4095, 0, 255)); + TEST_ASSERT_EQUAL_UINT16(127, remap(3071, 2048, 4095, 0, 255)); + TEST_ASSERT_EQUAL_UINT16(255, remap(4095, 2048, 4095, 0, 255)); + + TEST_ASSERT_EQUAL_UINT16(2047, remap(343, 343, 343, 0, 4095)); +} + +void test_remap_float(void) +{ + TEST_ASSERT_EQUAL_FLOAT(0.0f, remap(0.0f, 0.0f, 1.0f, 0.0f, 255.0f)); + TEST_ASSERT_EQUAL_FLOAT(127.5f, remap(0.5f, 0.0f, 1.0f, 0.0f, 255.0f)); + TEST_ASSERT_EQUAL_FLOAT(255.0f, remap(1.0f, 0.0f, 1.0f, 0.0f, 255.0f)); + + TEST_ASSERT_EQUAL_FLOAT(0.5f, remap(0.0f, -1.0f, 1.0f, 0.0f, 1.0f)); + + TEST_ASSERT_EQUAL_FLOAT(0.125f, remap(0.2f, 0.1f, 0.9f, 0.f, 1.f)); +} + +void test_remap_simple_uint16(void) +{ + TEST_ASSERT_EQUAL_UINT16(0, remap_simple(0, 4095, 255)); + TEST_ASSERT_EQUAL_UINT16(127, remap_simple(2047, 4095, 255)); + TEST_ASSERT_EQUAL_UINT16(255, remap_simple(4095, 4095, 255)); +} + +void test_remap_simple_float(void) +{ + TEST_ASSERT_EQUAL_FLOAT(0.0f, remap_simple(0.0f, 1.0f, 255.0f)); + TEST_ASSERT_EQUAL_FLOAT(127.5f, remap_simple(0.5f, 1.0f, 255.0f)); + TEST_ASSERT_EQUAL_FLOAT(255.0f, remap_simple(1.0f, 1.0f, 255.0f)); +} + +// Wtf? https://stackoverflow.com/questions/4295890 +#define COMMAE , + +void test_lookup_table_interpolate_float(void) +{ + const std::map<float, float> table = { + { 0.0f, 13.0f }, + { 0.5f, 16.0f }, + { 0.6f, 17.0f }, + { 1.0f, 18.0f }, + }; + + TEST_ASSERT_EQUAL_FLOAT(13.0f, lookup_table_interpolate<float COMMAE float>(table, 0.0f)); + TEST_ASSERT_EQUAL_FLOAT(13.6f, lookup_table_interpolate<float COMMAE float>(table, 0.1f)); + TEST_ASSERT_EQUAL_FLOAT(14.2f, lookup_table_interpolate<float COMMAE float>(table, 0.2f)); + TEST_ASSERT_EQUAL_FLOAT(14.5f, lookup_table_interpolate<float COMMAE float>(table, 0.25f)); + TEST_ASSERT_EQUAL_FLOAT(14.8f, lookup_table_interpolate<float COMMAE float>(table, 0.3f)); + TEST_ASSERT_EQUAL_FLOAT(15.4f, lookup_table_interpolate<float COMMAE float>(table, 0.4f)); + TEST_ASSERT_EQUAL_FLOAT(16.0f, lookup_table_interpolate<float COMMAE float>(table, 0.5f)); + TEST_ASSERT_EQUAL_FLOAT(16.5f, lookup_table_interpolate<float COMMAE float>(table, 0.55f)); + TEST_ASSERT_EQUAL_FLOAT(17.0f, lookup_table_interpolate<float COMMAE float>(table, 0.6f)); + TEST_ASSERT_EQUAL_FLOAT(17.25f, lookup_table_interpolate<float COMMAE float>(table, 0.7f)); + TEST_ASSERT_EQUAL_FLOAT(17.5f, lookup_table_interpolate<float COMMAE float>(table, 0.8f)); + TEST_ASSERT_EQUAL_FLOAT(17.75f, lookup_table_interpolate<float COMMAE float>(table, 0.9f)); + TEST_ASSERT_EQUAL_FLOAT(18.0f, lookup_table_interpolate<float COMMAE float>(table, 1.0f)); +} + +int process(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_lerp_uint8); + RUN_TEST(test_lerp_float); + + RUN_TEST(test_remap_uint16); + RUN_TEST(test_remap_float); + + RUN_TEST(test_remap_simple_uint16); + RUN_TEST(test_remap_simple_float); + + RUN_TEST(test_lookup_table_interpolate_float); + + return UNITY_END(); +} + +#ifdef ARDUINO + +#include <Arduino.h> + +void setup(void) +{ + process(); +} + +void loop(void) {} + +#else + +int main(int argc, char** argv) +{ + return process(); +} + +#endif diff --git a/test/test_util_calibration/main.cpp b/test/test_io_calibration/main.cpp similarity index 100% rename from test/test_util_calibration/main.cpp rename to test/test_io_calibration/main.cpp diff --git a/test/test_opengloves_alpha_encoding/main.cpp b/test/test_opengloves_alpha_encoding/main.cpp index 2d599457..c0162e99 100644 --- a/test/test_opengloves_alpha_encoding/main.cpp +++ b/test/test_opengloves_alpha_encoding/main.cpp @@ -86,6 +86,28 @@ void test_encode_input_peripherals(void) }), "A0(AB)2047B0(BB)2047C0(CB)2047D0(DB)2047E0(EB)2047\n", }, + { + InputPeripheralData({ + .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 }, + }, + }, + }), + "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", + }, { InputPeripheralData({ .joystick = { @@ -97,11 +119,19 @@ void test_encode_input_peripherals(void) "A0B0C0D0E0F2047G2047H\n" }, { - InputPeripheralData({ - .buttons = { true, false, false, true }, - }), + InputPeripheralData{ + .button_a = { .press = true }, + .button_calibrate = { .press = true }, + }, "A0B0C0D0E0JO\n" }, + { + InputPeripheralData{ + .pinch = { true }, + .grab = { true }, + }, + "A0B0C0D0E0MI\n" + }, { InputPeripheralData({ .curl = { diff --git a/test/test_util_buffer/main.cpp b/test/test_util_buffer/main.cpp index 40f1221c..14eec519 100644 --- a/test/test_util_buffer/main.cpp +++ b/test/test_util_buffer/main.cpp @@ -1,4 +1,3 @@ -#include <senseshift/utility.hpp> #include <unity.h> #include <senseshift/buffer.hpp> diff --git a/test/test_util/main.cpp b/test/test_util_container/main.cpp similarity index 63% rename from test/test_util/main.cpp rename to test/test_util_container/main.cpp index 4be719ba..ed0279ca 100644 --- a/test/test_util/main.cpp +++ b/test/test_util_container/main.cpp @@ -45,30 +45,6 @@ void test_contains_string(void) TEST_ASSERT_FALSE(contains(s, 'z')); } -void test_accurate_map(void) -{ - TEST_ASSERT_EQUAL_UINT16(0, accurateMap(0, 0, 4095, 0, 255)); - TEST_ASSERT_EQUAL_UINT16(127, accurateMap(2047, 0, 4095, 0, 255)); - TEST_ASSERT_EQUAL_UINT16(255, accurateMap(4095, 0, 4095, 0, 255)); - - TEST_ASSERT_EQUAL_UINT16(127, accurateMap(0, 0, 4095, 127, 255)); - TEST_ASSERT_EQUAL_UINT16(190, accurateMap(2047, 0, 4095, 127, 255)); - TEST_ASSERT_EQUAL_UINT16(255, accurateMap(4095, 0, 4095, 127, 255)); - - TEST_ASSERT_EQUAL_UINT16(0, accurateMap(2048, 2048, 4095, 0, 255)); - TEST_ASSERT_EQUAL_UINT16(127, accurateMap(3071, 2048, 4095, 0, 255)); - TEST_ASSERT_EQUAL_UINT16(255, accurateMap(4095, 2048, 4095, 0, 255)); - - TEST_ASSERT_EQUAL_UINT16(2047, accurateMap(343, 343, 343, 0, 4095)); -} - -void test_simple_map(void) -{ - TEST_ASSERT_EQUAL_UINT16(0, simpleMap(0, 4095, 255)); - TEST_ASSERT_EQUAL_UINT16(127, simpleMap(2047, 4095, 255)); - TEST_ASSERT_EQUAL_UINT16(255, simpleMap(4095, 4095, 255)); -} - int process(void) { UNITY_BEGIN(); @@ -77,9 +53,6 @@ int process(void) RUN_TEST(test_contains_iterator); RUN_TEST(test_contains_string); - RUN_TEST(test_accurate_map); - RUN_TEST(test_simple_map); - return UNITY_END(); } @@ -101,4 +74,4 @@ int main(int argc, char** argv) return process(); } -#endif +#endif \ No newline at end of file From 01c9a063f87f406d58ddbd948e5704f7fbbc61f8 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Fri, 9 Feb 2024 18:15:03 +0400 Subject: [PATCH 61/82] feat(OpenGloves) re-introduce simple data sending --- .../mode_configs/opengloves/opengloves.cpp | 17 + lib/core/senseshift/core/component.hpp | 22 +- lib/freertos/senseshift/freertos/task.hpp | 2 +- .../senseshift/body/hands/input/gesture.hpp | 45 +-- .../body/hands/input/total_curl.hpp | 2 +- lib/io/senseshift/input/analog_threshold.hpp | 2 +- lib/io/senseshift/input/sensor.hpp | 6 +- lib/opengloves/opengloves/opengloves.hpp | 8 +- .../senseshift/opengloves/opengloves.hpp | 110 +++++- .../senseshift/opengloves/opengloves_task.hpp | 183 +++++++++ lib/opengloves_task/opengloves_task.hpp | 348 ------------------ 11 files changed, 360 insertions(+), 385 deletions(-) create mode 100644 lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp delete mode 100644 lib/opengloves_task/opengloves_task.hpp diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index d25e5733..a3e97875 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -7,6 +7,8 @@ #include <senseshift/input/filter.hpp> #include <senseshift/input/sensor.hpp> #include <senseshift/opengloves/autoconfig.hpp> +#include <senseshift/opengloves/opengloves.hpp> +#include <senseshift/opengloves/opengloves_task.hpp> #include <senseshift/utility.hpp> using namespace ::SenseShift::Input; @@ -150,6 +152,21 @@ void setupMode() #elif BUTTON_PINCH_ENABLED auto* pinch = new BUTTON_CLASS(PIN_BUTTON_PINCH, BUTTON_PINCH_INVERT); #endif + + OpenGlovesTrackingComponent::Config const tracking_config(2000, false); + auto* opengloves_tracking = + new OpenGlovesTrackingComponent(tracking_config, input_sensors, new StreamTransport(Serial)); + + auto* opengloves_tracking_task = new ::SenseShift::FreeRTOS::ComponentUpdateTask<OpenGlovesTrackingComponent>( + opengloves_tracking, + 1000 / 60, + { + .name = "OpenGlovesSensorTask", + .stackDepth = 8192, + .priority = 1, + } + ); + opengloves_tracking_task->begin(); } void loopMode() diff --git a/lib/core/senseshift/core/component.hpp b/lib/core/senseshift/core/component.hpp index 8fae06dd..8ead9f04 100644 --- a/lib/core/senseshift/core/component.hpp +++ b/lib/core/senseshift/core/component.hpp @@ -1,18 +1,31 @@ #pragma once +#define SS_INIT_NOT_NULL(ptr) \ + if ((ptr) != nullptr) { \ + (ptr)->init(); \ + } +#define SS_TICK_NOT_NULL(ptr) \ + if ((ptr) != nullptr) { \ + (ptr)->tick(); \ + } + namespace SenseShift { class IInitializable { - public: + public: + virtual ~IInitializable() = default; + virtual void init() = 0; }; class ITickable { - public: + public: + virtual ~ITickable() = default; + virtual void tick() = 0; }; - class Component : public IInitializable, public ITickable { - public: + class Component : public virtual IInitializable, public virtual ITickable { + public: /// @brief Initialize the component. /// /// Where the component's initialization should happen. @@ -30,4 +43,3 @@ namespace SenseShift { void tick() override {} }; } // namespace SenseShift - diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index 9bea8bd8..aab82a70 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -112,7 +112,7 @@ namespace SenseShift::FreeRTOS { } }; - template<typename Tp> + template<typename Tp = Component> class ComponentUpdateTask : public Task<ComponentUpdateTask<Tp>> { static_assert(std::is_same_v<decltype(&Tp::init), void (Tp::*)()>); static_assert(std::is_same_v<decltype(&Tp::tick), void (Tp::*)()>); diff --git a/lib/hands_input/senseshift/body/hands/input/gesture.hpp b/lib/hands_input/senseshift/body/hands/input/gesture.hpp index ad462051..eccb911f 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 <senseshift/core/component.hpp> -#include <senseshift/input/sensor.hpp> #include <senseshift/input/analog_threshold.hpp> +#include <senseshift/input/sensor.hpp> namespace SenseShift::Body::Hands::Input { using Gesture = ::SenseShift::Input::BinarySensor; @@ -10,7 +10,7 @@ namespace SenseShift::Body::Hands::Input { /// An alias for semantic consistency. using TriggerGesture = ::SenseShift::Input::AnalogThresholdSensor<float>; - class GrabGesture : public Gesture, ITickable { + class GrabGesture : public Gesture { public: struct Fingers { ::SenseShift::Input::FloatSensor* index; @@ -19,13 +19,13 @@ namespace SenseShift::Body::Hands::Input { ::SenseShift::Input::FloatSensor* pinky; }; - explicit GrabGesture( - Fingers fingers, - float threshold = 0.5F, - bool attach_callbacks = false - ) : fingers_(fingers), threshold_(threshold), attach_callbacks_(attach_callbacks) {} + explicit GrabGesture(Fingers fingers, float threshold = 0.5F, bool attach_callbacks = false) : + fingers_(fingers), threshold_(threshold), attach_callbacks_(attach_callbacks) + { + } - void init() override { + void init() override + { SS_SUBSENSOR_INIT(this->fingers_.index, this->attach_callbacks_, [this](float /*value*/) { this->recalculateState(); }); @@ -40,14 +40,16 @@ namespace SenseShift::Body::Hands::Input { }); } - void tick() override { + 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(); } - void recalculateState() { + void recalculateState() + { return this->publishState( this->fingers_.index->getValue() > this->threshold_ && this->fingers_.middle->getValue() > this->threshold_ @@ -62,20 +64,20 @@ namespace SenseShift::Body::Hands::Input { bool attach_callbacks_ = false; }; - class PinchGesture : public Gesture, ITickable { + class PinchGesture : public Gesture { public: struct Fingers { ::SenseShift::Input::FloatSensor* thumb; ::SenseShift::Input::FloatSensor* index; }; - explicit PinchGesture( - Fingers fingers, - float threshold = 0.5F, - bool attach_callbacks = false - ) : fingers_(fingers), threshold_(threshold), attach_callbacks_(attach_callbacks) {} + explicit PinchGesture(Fingers fingers, float threshold = 0.5F, bool attach_callbacks = false) : + fingers_(fingers), threshold_(threshold), attach_callbacks_(attach_callbacks) + { + } - void init() override { + void init() override + { SS_SUBSENSOR_INIT(this->fingers_.thumb, this->attach_callbacks_, [this](float /*value*/) { this->recalculateState(); }); @@ -84,17 +86,18 @@ namespace SenseShift::Body::Hands::Input { }); } - void tick() override { + 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(); } - void recalculateState() { + void recalculateState() + { return this->publishState( - this->fingers_.thumb->getValue() > this->threshold_ - && this->fingers_.index->getValue() > this->threshold_ + this->fingers_.thumb->getValue() > this->threshold_ && this->fingers_.index->getValue() > this->threshold_ ); } 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 26538afc..e086b894 100644 --- a/lib/hands_input/senseshift/body/hands/input/total_curl.hpp +++ b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp @@ -8,7 +8,7 @@ #include <senseshift/input/sensor.hpp> namespace SenseShift::Body::Hands::Input { - class TotalCurl : public ::SenseShift::Input::FloatSensor, public ::SenseShift::ITickable { + 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. diff --git a/lib/io/senseshift/input/analog_threshold.hpp b/lib/io/senseshift/input/analog_threshold.hpp index 46eb53d4..48397ef4 100644 --- a/lib/io/senseshift/input/analog_threshold.hpp +++ b/lib/io/senseshift/input/analog_threshold.hpp @@ -5,7 +5,7 @@ namespace SenseShift::Input { template<typename Tp = float> - class AnalogThresholdSensor : public BinarySensor, ITickable { + class AnalogThresholdSensor : public BinarySensor { public: /// Analog threshold sensor with hysteresis. /// diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index 6d2046ea..e76b53b8 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -20,7 +20,7 @@ namespace SenseShift::Input { /// Abstract hardware sensor (e.g. potentiometer, flex sensor, etc.) /// \tparam Tp Type of the sensor value template<typename Tp> - class ISimpleSensor : virtual public IInitializable { + class ISimpleSensor : public virtual IInitializable { public: using ValueType = Tp; @@ -37,7 +37,7 @@ namespace SenseShift::Input { class ISensor : public virtual ISimpleSensor<Tp>, public Calibration::ICalibrated {}; template<typename Tp> - class Sensor : public ISensor<Tp> { + class Sensor : public ISensor<Tp>, public Component { public: using ValueType = Tp; using CallbackManagerType = CallbackManager<void(ValueType)>; @@ -173,7 +173,7 @@ namespace SenseShift::Input { using BinarySensor = Sensor<bool>; template<typename Tp> - class SimpleSensorDecorator : public Sensor<Tp>, public ITickable { + class SimpleSensorDecorator : public Sensor<Tp> { public: using ValueType = Tp; using SourceType = ISimpleSensor<ValueType>; diff --git a/lib/opengloves/opengloves/opengloves.hpp b/lib/opengloves/opengloves/opengloves.hpp index fed4d11c..4d5b470f 100644 --- a/lib/opengloves/opengloves/opengloves.hpp +++ b/lib/opengloves/opengloves/opengloves.hpp @@ -38,7 +38,7 @@ namespace og { std::array<Tf, 4> curl; // NOLINT(*-magic-numbers): I'm sure our finger aren't changing anytime soon union { Tf curl_total; - + struct { Tf curl_joint0; Tf curl_joint1; @@ -146,18 +146,18 @@ namespace og { [[nodiscard]] virtual auto parse_output(const char* data, size_t length) const -> Output = 0; - [[nodiscard]] auto parse_output(const std::vector<char>& data) const -> Output + [[nodiscard]] inline auto parse_output(const std::vector<char>& data) const -> Output { return this->parse_output(data.data(), data.size()); } - [[nodiscard]] auto parse_output(const std::string& data) const -> Output + [[nodiscard]] inline auto parse_output(const std::string& data) const -> Output { return this->parse_output(data.data(), data.length()); } #ifdef ARDUINO - [[nodiscard]] auto parse_output(const String& data) const -> Output + [[nodiscard]] inline auto parse_output(const String& data) const -> Output { return this->parse_output(data.c_str(), data.length()); } diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index fa948e4d..14354bcd 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -16,5 +16,113 @@ namespace SenseShift::OpenGloves { virtual auto read(char* buffer, size_t length) -> size_t = 0; }; - using InputSensors = og::InputPeripheral<::SenseShift::Input::FloatSensor*, ::SenseShift::Input::BinarySensor*>; + using FloatSensor = ::SenseShift::Input::FloatSensor; + using BinarySensor = ::SenseShift::Input::BinarySensor; + + class InputSensors : public og::InputPeripheral<FloatSensor*, BinarySensor*>, public Component { + public: + void init() override + { + for (auto& finger_curl : this->curl.fingers) { + for (auto& joint_sensor : finger_curl.curl) { + SS_INIT_NOT_NULL(joint_sensor); + } + } + + for (auto& finger_splay : this->splay.fingers) { + SS_INIT_NOT_NULL(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); + } + } + + 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& finger_splay : this->splay.fingers) { + SS_TICK_NOT_NULL(finger_splay); + } + + SS_TICK_NOT_NULL(this->joystick.x); + SS_TICK_NOT_NULL(this->joystick.y); + SS_TICK_NOT_NULL(this->joystick.press); + + for (auto& button : this->buttons) { + SS_TICK_NOT_NULL(button.press); + } + + for (auto& analog_button : this->analog_buttons) { + SS_TICK_NOT_NULL(analog_button.press); + SS_TICK_NOT_NULL(analog_button.value); + } + } + + 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(); + } + } + + 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; + } + }; } // namespace SenseShift::OpenGloves diff --git a/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp b/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp new file mode 100644 index 00000000..bed2ed48 --- /dev/null +++ b/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp @@ -0,0 +1,183 @@ +#pragma once + +#include <Arduino.h> + +#include <cstddef> +#include <optional> + +#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 "senseshift/opengloves/opengloves.hpp" +#include "senseshift/utility.hpp" +#include <opengloves/opengloves.hpp> +#include <utility> + +namespace SenseShift::OpenGloves { + class OpenGlovesTrackingComponent : public SenseShift::Component { + 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) + { + this->encoder_ = new og::AlphaEncoder(); + } + + void init() override + { + this->communication_->init(); + this->input_sensors_.init(); + } + + void tick() override + { + const auto data = this->input_sensors_.collectData(); + + char buffer[256]; + this->encoder_->encode_input(data, buffer, sizeof(buffer)); + this->communication_->send(buffer, sizeof(buffer)); + } + + private: + Config& config; + InputSensors input_sensors_; + ITransport* communication_; + og::IEncoder* encoder_; + }; + + // class OpenGlovesForceFeedbackTask : public SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask> { + // friend class SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>; + // + // public: + // OpenGlovesForceFeedbackTask( + // ::SenseShift::OpenGloves::ITransport& communication, + // HandActuators& actuators, + // size_t updateRate, + // SenseShift::FreeRTOS::TaskConfig taskConfig + // ) : + // communication(communication), + // actuators(actuators), + // SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>(taskConfig) + // { + // this->updateIntervalMs = 1000 / updateRate; + // }; + // + // void begin() override + // { + // log_d("Starting OpenGloves force feedback task: %p", this); + // this->setup(); + // this->SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>::begin(); + // }; + // + // private: + // ::SenseShift::OpenGloves::ITransport& communication; + // HandActuators& actuators; + // size_t updateIntervalMs; + // ::SenseShift::OpenGloves::AlphaEncodingService encodingService = + // ::SenseShift::OpenGloves::AlphaEncodingService(); + // + // void setup() + // { + // log_d("Setting up OpenGloves force feedback task: %p", this); + // this->communication.setup(); + // + // if (this->actuators.thumb.has_value()) { + // this->actuators.thumb.value()->setup(); + // } + // + // if (this->actuators.index.has_value()) { + // this->actuators.index.value()->setup(); + // } + // + // if (this->actuators.middle.has_value()) { + // this->actuators.middle.value()->setup(); + // } + // + // if (this->actuators.ring.has_value()) { + // this->actuators.ring.value()->setup(); + // } + // + // if (this->actuators.pinky.has_value()) { + // this->actuators.pinky.value()->setup(); + // } + // } + // + // void run() + // { + // char commandBuffer[256]; + // std::string command; + // while (true) { + // auto now = millis(); + // + // if (this->communication.hasData()) { + // auto bytesRead = this->communication.read(commandBuffer, sizeof(commandBuffer)); + // if (bytesRead == 0) { + // continue; + // } + // + // std::map<::OpenGloves::Command, uint16_t> commands = {}; + // this->encodingService.deserialize(commandBuffer, bytesRead, commands); + // + // for (auto& [command, value] : commands) { + // this->handleCommand(command, value); + // } + // } + // + // // Delay until the next update. + // auto elapsed = millis() - now; + // if (elapsed < this->updateIntervalMs) { + // delay(this->updateIntervalMs - elapsed); + // } + // } + // } + // + // void handleCommand(Command command, uint16_t value) + // { + // switch (command) { + // case Command::ThumbCurl: + // if (this->actuators.thumb.has_value()) { + // this->actuators.thumb.value()->writeOutput(value); + // } + // break; + // case Command::IndexCurl: + // if (this->actuators.index.has_value()) { + // this->actuators.index.value()->writeOutput(value); + // } + // break; + // case Command::MiddleCurl: + // if (this->actuators.middle.has_value()) { + // this->actuators.middle.value()->writeOutput(value); + // } + // break; + // case Command::RingCurl: + // if (this->actuators.ring.has_value()) { + // this->actuators.ring.value()->writeOutput(value); + // } + // break; + // case Command::PinkyCurl: + // if (this->actuators.pinky.has_value()) { + // this->actuators.pinky.value()->writeOutput(value); + // } + // break; + // default: + // log_w("Unhandled command: %d", command); + // break; + // } + // } + // }; +} // namespace SenseShift::OpenGloves diff --git a/lib/opengloves_task/opengloves_task.hpp b/lib/opengloves_task/opengloves_task.hpp deleted file mode 100644 index c327890d..00000000 --- a/lib/opengloves_task/opengloves_task.hpp +++ /dev/null @@ -1,348 +0,0 @@ -#pragma once - -#include <Arduino.h> - -#include <optional> - -#include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/input/sensor/digital.hpp> -#include <senseshift/freertos/task.hpp> -#include <senseshift/input/sensor.hpp> -#include <senseshift/opengloves/encoding/alpha.hpp> -#include <senseshift/opengloves/opengloves.hpp> -#include <senseshift/utility.hpp> -#include <sensor/og_finger.hpp> -#include <sensor/og_gesture.hpp> - -namespace OpenGloves { - struct OpenGlovesTrackingTaskConfig { - size_t updateIntervalMs; - size_t calibrationDuration; - bool alwaysCalibrate; - - /** - * @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. - */ - OpenGlovesTrackingTaskConfig(size_t updateRate, size_t calibrationDuration, bool alwaysCalibrate) : - calibrationDuration(calibrationDuration), alwaysCalibrate(alwaysCalibrate) - { - // Convert the update rate to an interval in milliseconds. - this->updateIntervalMs = 1000 / updateRate; - } - }; - - class OpenGlovesTrackingTask : public SenseShift::FreeRTOS::Task<OpenGlovesTrackingTask> { - friend class SenseShift::FreeRTOS::Task<OpenGlovesTrackingTask>; - - public: - /** - * @param config The configuration for the OpenGloves tracking task. - * @param communication The communication interface. - * @param fingers The finger sensors. - * @param buttons The button sensors. - * @param joysticks The joystick sensors. - * @param otherSensors Other sensors that should be updated. - * @param calibrationButton The calibration button sensor, optional. - * @param taskConfig The task configuration. - */ - OpenGlovesTrackingTask( - OpenGlovesTrackingTaskConfig& config, - ::SenseShift::OpenGloves::ITransport& communication, - HandSensors& fingers, - std::vector<StringEncodedMemoizedSensor<bool>*>& buttons, - std::vector<StringEncodedMemoizedSensor<uint16_t>*>& joysticks, - std::vector<IStringEncodedMemoizedSensor*>& otherSensors, - std::optional<StringEncodedMemoizedSensor<bool>>& calibrationButton, - SenseShift::FreeRTOS::TaskConfig taskConfig - ) : - config(config), - communication(communication), - fingers(fingers), - buttons(buttons), - joysticks(joysticks), - otherSensors(otherSensors), - calibrationButton(calibrationButton), - allSensors(std::vector<IStringEncodedMemoizedSensor*>()), - SenseShift::FreeRTOS::Task<OpenGlovesTrackingTask>(taskConfig) - { - if (fingers.thumb.has_value()) { - auto* thumb = &fingers.thumb.value(); - this->calibrated.push_back(thumb); - this->allSensors.push_back(thumb); - } - if (fingers.index.has_value()) { - auto* index = &fingers.index.value(); - this->calibrated.push_back(index); - this->allSensors.push_back(index); - } - if (fingers.middle.has_value()) { - auto* middle = &fingers.middle.value(); - this->calibrated.push_back(middle); - this->allSensors.push_back(middle); - } - if (fingers.ring.has_value()) { - auto* ring = &fingers.ring.value(); - this->calibrated.push_back(ring); - this->allSensors.push_back(ring); - } - if (fingers.pinky.has_value()) { - auto* pinky = &fingers.pinky.value(); - this->calibrated.push_back(pinky); - this->allSensors.push_back(pinky); - } - - for (auto* button : buttons) { - this->allSensors.push_back(button); - } - - if (calibrationButton.has_value()) { - this->allSensors.push_back(&calibrationButton.value()); - } - - for (auto* joystick : joysticks) { - this->allSensors.push_back(joystick); - } - - for (auto* otherSensor : otherSensors) { - this->allSensors.push_back(otherSensor); - } - - // sort all sensors by type for easier debugging - std::sort( - this->allSensors.begin(), - this->allSensors.end(), - [](IStringEncodedMemoizedSensor* a, IStringEncodedMemoizedSensor* b) { - return a->getType() < b->getType(); - } - ); - } - - void begin() override - { - log_d("Starting OpenGloves tracking task: %p", this); - this->setup(); - this->SenseShift::FreeRTOS::Task<OpenGlovesTrackingTask>::begin(); - }; - - private: - OpenGlovesTrackingTaskConfig& config; - - HandSensors& fingers; - ::SenseShift::OpenGloves::ITransport& communication; - ::SenseShift::OpenGloves::AlphaEncodingService encodingService = - ::SenseShift::OpenGloves::AlphaEncodingService(); - - std::vector<StringEncodedMemoizedSensor<bool>*>& buttons; - std::vector<StringEncodedMemoizedSensor<uint16_t>*>& joysticks; - std::vector<IStringEncodedMemoizedSensor*>& otherSensors; - - std::vector<IStringEncodedMemoizedSensor*> allSensors; - - std::optional<StringEncodedMemoizedSensor<bool>>& calibrationButton; - std::vector<SenseShift::Calibration::ICalibrated*> calibrated = - std::vector<SenseShift::Calibration::ICalibrated*>(); - unsigned long long calibrationStarted = 0; - - void startCalibration() - { - for (auto* input : this->calibrated) { - input->resetCalibration(); - input->enableCalibration(); - } - this->calibrationStarted = millis(); - } - - void setup() - { - log_d("Setting up OpenGloves tracking task: %p", this); - log_d("There is a total of %d sensors", this->allSensors.size()); - for (auto* input : this->allSensors) { - log_d("Setting up sensor: %c", input->getType()); - input->init(); - } - - // Start calibration if no calibration button is present or if configured to always calibrate. - if (!this->calibrationButton.has_value() || this->config.alwaysCalibrate) { - log_d("Starting calibration on startup"); - this->startCalibration(); - } - - this->communication.setup(); - } - - void run() - { - while (true) { - auto now = millis(); - - // Update the sensors. - for (auto* input : this->allSensors) { - input->updateValue(); - } - - // Update the calibration if calibration has not started, calibration is not configured to always run, - // and the calibration button is present and pressed. - if (calibrationStarted == 0 && - !this->config.alwaysCalibrate && - this->calibrationButton.has_value() && - this->calibrationButton.value().getValue() - ) { - log_d("Calibration started"); - this->startCalibration(); - } - - // Send the sensor values. - char command[256]; - size_t length = this->encodingService.serialize(this->allSensors, command); - this->communication.send(command, length); - - // Check if the calibration has finished. - if (!(this->config.alwaysCalibrate) && calibrationStarted > 0 && (now - calibrationStarted) > CALIBRATION_DURATION) { - log_d("Calibration finished"); - for (size_t i = 0; i < calibrated.size(); i++) { - auto* input = calibrated[i]; - input->disableCalibration(); - } - calibrationStarted = 0; - } - - // Delay until the next update. - auto elapsed = millis() - now; - - log_d( - "Update took %d ms, theoretical max rate is %dHz (target is %dHz)", - elapsed, - 1000 / elapsed, - 1000 / this->config.updateIntervalMs - ); - - if (elapsed < this->config.updateIntervalMs) { - delay(this->config.updateIntervalMs - elapsed); - } - } - }; - }; - - class OpenGlovesForceFeedbackTask : public SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask> { - friend class SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>; - - public: - OpenGlovesForceFeedbackTask( - ::SenseShift::OpenGloves::ITransport& communication, - HandActuators& actuators, - size_t updateRate, - SenseShift::FreeRTOS::TaskConfig taskConfig - ) : - communication(communication), - actuators(actuators), - SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>(taskConfig) - { - this->updateIntervalMs = 1000 / updateRate; - }; - - void begin() override - { - log_d("Starting OpenGloves force feedback task: %p", this); - this->setup(); - this->SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>::begin(); - }; - - private: - ::SenseShift::OpenGloves::ITransport& communication; - HandActuators& actuators; - size_t updateIntervalMs; - ::SenseShift::OpenGloves::AlphaEncodingService encodingService = - ::SenseShift::OpenGloves::AlphaEncodingService(); - - void setup() - { - log_d("Setting up OpenGloves force feedback task: %p", this); - this->communication.setup(); - - if (this->actuators.thumb.has_value()) { - this->actuators.thumb.value()->setup(); - } - - if (this->actuators.index.has_value()) { - this->actuators.index.value()->setup(); - } - - if (this->actuators.middle.has_value()) { - this->actuators.middle.value()->setup(); - } - - if (this->actuators.ring.has_value()) { - this->actuators.ring.value()->setup(); - } - - if (this->actuators.pinky.has_value()) { - this->actuators.pinky.value()->setup(); - } - } - - void run() - { - char commandBuffer[256]; - std::string command; - while (true) { - auto now = millis(); - - if (this->communication.hasData()) { - auto bytesRead = this->communication.read(commandBuffer, sizeof(commandBuffer)); - if (bytesRead == 0) { - continue; - } - - std::map<::OpenGloves::Command, uint16_t> commands = {}; - this->encodingService.deserialize(commandBuffer, bytesRead, commands); - - for (auto& [command, value] : commands) { - this->handleCommand(command, value); - } - } - - // Delay until the next update. - auto elapsed = millis() - now; - if (elapsed < this->updateIntervalMs) { - delay(this->updateIntervalMs - elapsed); - } - } - } - - void handleCommand(Command command, uint16_t value) - { - switch (command) { - case Command::ThumbCurl: - if (this->actuators.thumb.has_value()) { - this->actuators.thumb.value()->writeOutput(value); - } - break; - case Command::IndexCurl: - if (this->actuators.index.has_value()) { - this->actuators.index.value()->writeOutput(value); - } - break; - case Command::MiddleCurl: - if (this->actuators.middle.has_value()) { - this->actuators.middle.value()->writeOutput(value); - } - break; - case Command::RingCurl: - if (this->actuators.ring.has_value()) { - this->actuators.ring.value()->writeOutput(value); - } - break; - case Command::PinkyCurl: - if (this->actuators.pinky.has_value()) { - this->actuators.pinky.value()->writeOutput(value); - } - break; - default: - log_w("Unhandled command: %d", command); - break; - } - } - }; -} // namespace OpenGloves From 825e6f0a0d20125f8040ac38cf92a1063d771e10 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sat, 10 Feb 2024 22:20:47 +0400 Subject: [PATCH 62/82] test(Input): cover filters --- lib/io/senseshift/input/filter.hpp | 49 ++++-- test/test_io_filter/main.cpp | 172 +++++++++++++++++++ test/test_opengloves_alpha_encoding/main.cpp | 4 + 3 files changed, 207 insertions(+), 18 deletions(-) create mode 100644 test/test_io_filter/main.cpp diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index 75f65dc2..6601d5ad 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -2,6 +2,7 @@ #include <algorithm> #include <array> +#include <cmath> #include <cstdint> #include <cstdlib> #include <deque> @@ -33,17 +34,6 @@ namespace SenseShift::Input::Filter { virtual auto filter(ISimpleSensor<ValueType>* sensor, ValueType value) -> ValueType = 0; }; - template<typename Tp> - class AddFilter : public IFilter<Tp> { - public: - explicit AddFilter(Tp offset) : offset_(offset){}; - - auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override { return value + this->offset_; } - - private: - Tp offset_; - }; - template<typename Tp> class IFiltered { public: @@ -58,6 +48,17 @@ namespace SenseShift::Input::Filter { void clearFilters() = 0; }; + template<typename Tp> + class AddFilter : public IFilter<Tp> { + public: + explicit AddFilter(Tp offset) : offset_(offset){}; + + auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override { return value + this->offset_; } + + private: + Tp offset_; + }; + template<typename Tp> class SubtractFilter : public IFilter<Tp> { public: @@ -82,6 +83,8 @@ namespace SenseShift::Input::Filter { class VoltageDividerFilter : public MultiplyFilter<float> { 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. @@ -91,7 +94,7 @@ namespace SenseShift::Input::Filter { /// \code /// new VoltageDividerFilter(27000.0F, 100000.0F); /// \endcode - explicit VoltageDividerFilter(float r1, float r2) : MultiplyFilter<float>(r2 / (r1 + r2)){}; + explicit VoltageDividerFilter(float r1, float r2) : MultiplyFilter<float>((r1 + r2) / r2){}; }; template<typename Tp> @@ -220,7 +223,7 @@ namespace SenseShift::Input::Filter { private: std::size_t window_size_; - std::deque<Tp> values_; + std::deque<Tp> queue_; [[nodiscard]] auto getAverage() const -> Tp { @@ -239,14 +242,24 @@ namespace SenseShift::Input::Filter { public: explicit ExponentialMovingAverageFilter(float alpha) : alpha_(alpha){}; + template<typename U = Tp, std::enable_if_t<std::is_same_v<U, float>, int> = 0> + explicit ExponentialMovingAverageFilter(float alpha) : alpha_(alpha), acc_(std::nanf){}; + auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override { - this->acc_ = this->alpha_ * value + (1 - this->alpha_) * this->acc_; + if (this->is_first_) { + this->is_first_ = false; + + this->acc_ = value; + return this->acc_; + } + this->acc_ = (this->alpha_ * value) + ((1 - this->alpha_) * this->acc_); return this->acc_; } private: + bool is_first_ = true; float alpha_; Tp acc_; }; @@ -255,16 +268,16 @@ namespace SenseShift::Input::Filter { /// Usually used to filter out noise in the joystick. class CenterDeadzoneFilter : public IFilter<float> { public: - explicit CenterDeadzoneFilter(float deadzone) : deadzone_(deadzone){}; + explicit CenterDeadzoneFilter(float deadzone, float center = 0.5f) : deadzone_(deadzone), center_(center){}; auto filter(ISimpleSensor<float>* /*sensor*/, float value) -> float override { - float const deviation = std::abs(CENTER - value); - return deviation < deadzone_ ? CENTER : value; + float const deviation = std::abs(value - this->center_); + return deviation < deadzone_ ? this->center_ : value; } private: - static constexpr float CENTER = 0.5F; + const float center_; float deadzone_; }; diff --git a/test/test_io_filter/main.cpp b/test/test_io_filter/main.cpp new file mode 100644 index 00000000..f5002158 --- /dev/null +++ b/test/test_io_filter/main.cpp @@ -0,0 +1,172 @@ +#include <senseshift/input/filter.hpp> +#include <senseshift/input/sensor.hpp> +#include <unity.h> + +#define ASSERT_EQUAL_FLOAT_ROUNDED(expected, actual, precision) \ + TEST_ASSERT_EQUAL_FLOAT( \ + std::round(expected* std::pow(10, precision)) / std::pow(10, precision), \ + std::round(actual * std::pow(10, precision)) / std::pow(10, precision) \ + ) + +using namespace SenseShift::Input; +using namespace SenseShift::Input::Filter; + +void test_add_filter(void) +{ + IFilter<float>* filter = new AddFilter<float>(5.0f); + + TEST_ASSERT_EQUAL_FLOAT(10.0f, filter->filter(nullptr, 5.0f)); + TEST_ASSERT_EQUAL_FLOAT(11.0f, filter->filter(nullptr, 6.0f)); + TEST_ASSERT_EQUAL_FLOAT(12.0f, filter->filter(nullptr, 7.0f)); +} + +void test_subtract_filter(void) +{ + IFilter<float>* filter = new SubtractFilter<float>(5.0f); + + TEST_ASSERT_EQUAL_FLOAT(0.0f, filter->filter(nullptr, 5.0f)); + TEST_ASSERT_EQUAL_FLOAT(-1.0f, filter->filter(nullptr, 4.0f)); + TEST_ASSERT_EQUAL_FLOAT(-2.0f, filter->filter(nullptr, 3.0f)); +} + +void test_multiply_filter(void) +{ + IFilter<float>* filter = new MultiplyFilter<float>(5.0f); + + TEST_ASSERT_EQUAL_FLOAT(25.0f, filter->filter(nullptr, 5.0f)); + TEST_ASSERT_EQUAL_FLOAT(30.0f, filter->filter(nullptr, 6.0f)); + TEST_ASSERT_EQUAL_FLOAT(35.0f, filter->filter(nullptr, 7.0f)); +} + +void test_voltage_divider_filter(void) +{ + IFilter<float>* filter = new VoltageDividerFilter(27000.0F, 100000.0F); + + TEST_ASSERT_EQUAL_FLOAT(0.0F, filter->filter(nullptr, 0.0F)); + TEST_ASSERT_EQUAL_FLOAT(3.429F, filter->filter(nullptr, 2.7F)); + TEST_ASSERT_EQUAL_FLOAT(3.81F, filter->filter(nullptr, 3.0F)); + TEST_ASSERT_EQUAL_FLOAT(4.191F, filter->filter(nullptr, 3.3F)); +} + +void test_clamp_filter(void) +{ + IFilter<float>* filter = new ClampFilter<float>(0.0f, 1.0f); + + TEST_ASSERT_EQUAL_FLOAT(0.0f, filter->filter(nullptr, -1.0f)); + TEST_ASSERT_EQUAL_FLOAT(0.0f, filter->filter(nullptr, 0.0f)); + TEST_ASSERT_EQUAL_FLOAT(0.5f, filter->filter(nullptr, 0.5f)); + TEST_ASSERT_EQUAL_FLOAT(1.0f, filter->filter(nullptr, 1.0f)); + TEST_ASSERT_EQUAL_FLOAT(1.0f, filter->filter(nullptr, 2.0f)); +} + +void test_lambda_filter(void) +{ + IFilter<float>* filter = new LambdaFilter<float>([](float value) { + return value * 42.F; // Cause after all, 42 is the answer to everything. + }); + + TEST_ASSERT_EQUAL_FLOAT(42.0f, filter->filter(nullptr, 1.0f)); + TEST_ASSERT_EQUAL_FLOAT(84.0f, filter->filter(nullptr, 2.0f)); + TEST_ASSERT_EQUAL_FLOAT(126.0f, filter->filter(nullptr, 3.0f)); +} + +void test_sliding_window_moving_average_filter(void) +{ + IFilter<float>* filter = new SlidingWindowMovingAverageFilter<float>(3); + + TEST_ASSERT_EQUAL_FLOAT(1.0f, filter->filter(nullptr, 1.0f)); // 1 / 1 = 1 + TEST_ASSERT_EQUAL_FLOAT(1.5f, filter->filter(nullptr, 2.0f)); // (1 + 2) / 2 = 1.5 + TEST_ASSERT_EQUAL_FLOAT(2.0f, filter->filter(nullptr, 3.0f)); // (1 + 2 + 3) / 3 = 2 + TEST_ASSERT_EQUAL_FLOAT(3.0f, filter->filter(nullptr, 4.0f)); // (2 + 3 + 4) / 3 = 3 + TEST_ASSERT_EQUAL_FLOAT(4.0f, filter->filter(nullptr, 5.0f)); // (3 + 4 + 5) / 3 = 4 + TEST_ASSERT_EQUAL_FLOAT(5.0f, filter->filter(nullptr, 6.0f)); // (4 + 5 + 6) / 3 = 5 + TEST_ASSERT_EQUAL_FLOAT(6.0f, filter->filter(nullptr, 7.0f)); // (5 + 6 + 7) / 3 = 6 + TEST_ASSERT_EQUAL_FLOAT(7.0f, filter->filter(nullptr, 8.0f)); // (6 + 7 + 8) / 3 = 7 + TEST_ASSERT_EQUAL_FLOAT(8.0f, filter->filter(nullptr, 9.0f)); // (7 + 8 + 9) / 3 = 8 + TEST_ASSERT_EQUAL_FLOAT(9.0f, filter->filter(nullptr, 10.0f)); // (8 + 9 + 10) / 3 = 9 + TEST_ASSERT_EQUAL_FLOAT(10.0f, filter->filter(nullptr, 11.0f)); // (9 + 10 + 11) / 3 = 10 + + ASSERT_EQUAL_FLOAT_ROUNDED(10.67f, filter->filter(nullptr, 11.0f), 2); // (10 + 11 + 11) / 3 = 10.67 + TEST_ASSERT_EQUAL_FLOAT(11.0f, filter->filter(nullptr, 11.0f)); // (11 + 11 + 11) / 3 = 11 + ASSERT_EQUAL_FLOAT_ROUNDED(11.33f, filter->filter(nullptr, 12.0f), 2); // (11 + 11 + 12) / 3 = 11.33 +} + +void test_exponential_moving_average_filter(void) +{ + IFilter<float>* filter = new ExponentialMovingAverageFilter<float>(0.5f); + ASSERT_EQUAL_FLOAT_ROUNDED(1.0f, filter->filter(nullptr, 1.0f), 2); // 1.0 + ASSERT_EQUAL_FLOAT_ROUNDED(1.5f, filter->filter(nullptr, 2.0f), 2); // (0.5 * 1.0) + (0.5 * 2.0) = 1.5 + ASSERT_EQUAL_FLOAT_ROUNDED(2.25f, filter->filter(nullptr, 3.0f), 2); // (0.5 * 1.5) + (0.5 * 3.0) = 2.25 + ASSERT_EQUAL_FLOAT_ROUNDED(3.125f, filter->filter(nullptr, 4.0f), 2); // (0.5 * 2.25) + (0.5 * 4.0) = 3.125 + ASSERT_EQUAL_FLOAT_ROUNDED(4.0625f, filter->filter(nullptr, 5.0f), 2); // (0.5 * 3.125) + (0.5 * 5.0) = 4.0625 + + filter = new ExponentialMovingAverageFilter<float>(0.1f); + ASSERT_EQUAL_FLOAT_ROUNDED(1.0f, filter->filter(nullptr, 1.0f), 2); // 1.0 + ASSERT_EQUAL_FLOAT_ROUNDED(1.1f, filter->filter(nullptr, 2.0f), 2); // (0.1 * 2.0) + (0.9 * 1.0) = 1.1 + ASSERT_EQUAL_FLOAT_ROUNDED(1.29f, filter->filter(nullptr, 3.0f), 2); // (0.1 * 3.0) + (0.9 * 1.1) = 1.29 + ASSERT_EQUAL_FLOAT_ROUNDED(1.561f, filter->filter(nullptr, 4.0f), 2); // (0.1 * 4.0) + (0.9 * 1.29) = 1.561 + ASSERT_EQUAL_FLOAT_ROUNDED(1.9049f, filter->filter(nullptr, 5.0f), 2); // (0.1 * 5.0) + (0.9 * 1.561) = 1.9049 + + filter = new ExponentialMovingAverageFilter<float>(0.9f); + ASSERT_EQUAL_FLOAT_ROUNDED(1.0f, filter->filter(nullptr, 1.0f), 2); // 1.0 + ASSERT_EQUAL_FLOAT_ROUNDED(1.9f, filter->filter(nullptr, 2.0f), 2); // (0.9 * 2.0) + (0.1 * 1.0) = 1.9 + ASSERT_EQUAL_FLOAT_ROUNDED(2.89f, filter->filter(nullptr, 3.0f), 2); // (0.9 * 3.0) + (0.1 * 1.9) = 2.89 + ASSERT_EQUAL_FLOAT_ROUNDED(3.889f, filter->filter(nullptr, 4.0f), 2); // (0.9 * 4.0) + (0.1 * 2.89) = 3.889 + ASSERT_EQUAL_FLOAT_ROUNDED(4.8889f, filter->filter(nullptr, 5.0f), 2); // (0.9 * 5.0) + (0.1 * 3.889) = 4.8889 + ASSERT_EQUAL_FLOAT_ROUNDED(4.98889, filter->filter(nullptr, 5.0f), 2); // (0.9 * 5.0) + (0.1 * 4.8889) = 4.98889 + ASSERT_EQUAL_FLOAT_ROUNDED(4.99889, filter->filter(nullptr, 5.0f), 2); // (0.9 * 5.0) + (0.1 * 4.98889) = 4.99889 + ASSERT_EQUAL_FLOAT_ROUNDED(4.999889, filter->filter(nullptr, 5.0f), 2); // (0.9 * 5.0) + (0.1 * 4.99889) = 4.999889 +} + +void test_center_deadzone_filter(void) +{ + IFilter<float>* filter = new CenterDeadzoneFilter(0.1f); + + TEST_ASSERT_EQUAL_FLOAT(0.0f, filter->filter(nullptr, 0.0f)); + TEST_ASSERT_EQUAL_FLOAT(0.1f, filter->filter(nullptr, 0.1f)); + + // Inside the deadzone + TEST_ASSERT_EQUAL_FLOAT(0.5f, filter->filter(nullptr, 0.43f)); + TEST_ASSERT_EQUAL_FLOAT(0.5f, filter->filter(nullptr, 0.5f)); + TEST_ASSERT_EQUAL_FLOAT(0.5f, filter->filter(nullptr, 0.57f)); + + TEST_ASSERT_EQUAL_FLOAT(0.9f, filter->filter(nullptr, 0.9f)); + TEST_ASSERT_EQUAL_FLOAT(1.0f, filter->filter(nullptr, 1.0f)); +} + +int process(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_add_filter); + RUN_TEST(test_subtract_filter); + RUN_TEST(test_multiply_filter); + RUN_TEST(test_voltage_divider_filter); + RUN_TEST(test_clamp_filter); + RUN_TEST(test_lambda_filter); + RUN_TEST(test_sliding_window_moving_average_filter); + RUN_TEST(test_exponential_moving_average_filter); + RUN_TEST(test_center_deadzone_filter); + + return UNITY_END(); +} + +#ifdef ARDUINO + +#include <Arduino.h> + +void setup(void) +{ + process(); +} + +void loop(void) {} + +#else + +int main(int argc, char** argv) +{ + return process(); +} + +#endif \ No newline at end of file diff --git a/test/test_opengloves_alpha_encoding/main.cpp b/test/test_opengloves_alpha_encoding/main.cpp index c0162e99..4786fa0a 100644 --- a/test/test_opengloves_alpha_encoding/main.cpp +++ b/test/test_opengloves_alpha_encoding/main.cpp @@ -8,6 +8,10 @@ void test_encode_input_peripherals(void) const IEncoder* encoder = new AlphaEncoder(); const std::vector<std::tuple<InputPeripheralData, std::string>> cases = { + { + InputPeripheralData{}, + "A0B0C0D0E0\n", + }, { InputPeripheralData({ .curl = { From 728bd795448dfe797d26ec0d722fe19bf9291718 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sat, 10 Feb 2024 22:58:14 +0400 Subject: [PATCH 63/82] fix(OpenGloves): tick input sensors --- .../mode_configs/opengloves/opengloves.cpp | 3 +- ini/opengloves-lucidgloves.ini | 2 - .../arduino/input/sensor/digital.hpp | 6 ++- lib/io/senseshift/input/filter.hpp | 3 -- lib/io/senseshift/input/sensor.hpp | 6 +++ lib/opengloves/opengloves/opengloves.cpp | 2 +- lib/opengloves/opengloves/opengloves.hpp | 5 ++ .../senseshift/opengloves/opengloves.hpp | 2 +- .../senseshift/opengloves/opengloves_task.hpp | 50 +++++++++++++++--- test/test_io_sensor/main.cpp | 51 +++++++++---------- 10 files changed, 88 insertions(+), 42 deletions(-) diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index a3e97875..1a603125 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -153,7 +153,8 @@ void setupMode() auto* pinch = new BUTTON_CLASS(PIN_BUTTON_PINCH, BUTTON_PINCH_INVERT); #endif - OpenGlovesTrackingComponent::Config const tracking_config(2000, false); + Serial.begin(115200); + OpenGlovesTrackingComponent::Config tracking_config(2000, true); auto* opengloves_tracking = new OpenGlovesTrackingComponent(tracking_config, input_sensors, new StreamTransport(Serial)); diff --git a/ini/opengloves-lucidgloves.ini b/ini/opengloves-lucidgloves.ini index f535f768..f150cfc4 100644 --- a/ini/opengloves-lucidgloves.ini +++ b/ini/opengloves-lucidgloves.ini @@ -65,8 +65,6 @@ build_flags = ${opengloves.build_flags} -D OG_ENCODE_FAST ; -D PIN_BUTTON_GRAB=13 ; unused if GESTURE_GRAB is true ; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true -; todo: add servo pins - build_unflags = ${opengloves.build_unflags} build_src_filter = ${opengloves.build_src_filter} +<mode_configs/opengloves/opengloves.cpp> diff --git a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp index 9a3d101c..cc3e7573 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -18,12 +18,14 @@ namespace SenseShift::Arduino::Input { }; template<> - [[nodiscard]] inline auto DigitalSimpleSensor<false>::getValue() -> bool { + [[nodiscard]] inline auto DigitalSimpleSensor<false>::getValue() -> bool + { return digitalRead(this->pin_) == LOW; } template<> - [[nodiscard]] inline auto DigitalSimpleSensor<true>::getValue() -> bool { + [[nodiscard]] inline auto DigitalSimpleSensor<true>::getValue() -> bool + { return digitalRead(this->pin_) == HIGH; } } // namespace SenseShift::Arduino::Input diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index 6601d5ad..b13bc857 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -242,9 +242,6 @@ namespace SenseShift::Input::Filter { public: explicit ExponentialMovingAverageFilter(float alpha) : alpha_(alpha){}; - template<typename U = Tp, std::enable_if_t<std::is_same_v<U, float>, int> = 0> - explicit ExponentialMovingAverageFilter(float alpha) : alpha_(alpha), acc_(std::nanf){}; - auto filter(ISimpleSensor<Tp>* /*sensor*/, Tp value) -> Tp override { if (this->is_first_) { diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index e76b53b8..3d6e1b1f 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -45,6 +45,12 @@ namespace SenseShift::Input { explicit Sensor() = default; + template<typename U = Tp, std::enable_if_t<std::is_same_v<U, float>, 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. diff --git a/lib/opengloves/opengloves/opengloves.cpp b/lib/opengloves/opengloves/opengloves.cpp index 0411c6d9..924f8914 100644 --- a/lib/opengloves/opengloves/opengloves.cpp +++ b/lib/opengloves/opengloves/opengloves.cpp @@ -59,7 +59,7 @@ namespace og { length - written, "%c%u", 'A' + i, - ifloor<std::uint8_t, float>(finger_curl * MAX_ANALOG_VALUE) + ifloor<std::uint16_t, float>(finger_curl * MAX_ANALOG_VALUE) ); } #else diff --git a/lib/opengloves/opengloves/opengloves.hpp b/lib/opengloves/opengloves/opengloves.hpp index 4d5b470f..e961f908 100644 --- a/lib/opengloves/opengloves/opengloves.hpp +++ b/lib/opengloves/opengloves/opengloves.hpp @@ -35,10 +35,15 @@ namespace og { template<typename Tf = float> union InputFingerCurl { + /// Access the curl as an array. std::array<Tf, 4> 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; diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index 14354bcd..0b2d6832 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -75,7 +75,7 @@ namespace SenseShift::OpenGloves { auto collectData() -> og::InputPeripheralData { - og::InputPeripheralData data; + og::InputPeripheralData data{}; const auto& curls = this->curl.fingers; const auto& splays = this->splay.fingers; diff --git a/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp b/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp index bed2ed48..2a5a6f93 100644 --- a/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp +++ b/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp @@ -2,6 +2,7 @@ #include <Arduino.h> +#include <array> #include <cstddef> #include <optional> @@ -15,6 +16,11 @@ #include <opengloves/opengloves.hpp> #include <utility> +#define SS_START_CALIBRATION_NOT_NULL(ptr) \ + if ((ptr) != nullptr) { \ + (ptr)->startCalibration(); \ + } + namespace SenseShift::OpenGloves { class OpenGlovesTrackingComponent : public SenseShift::Component { public: @@ -32,8 +38,8 @@ namespace SenseShift::OpenGloves { } }; - OpenGlovesTrackingComponent(Config config, InputSensors& input_sensors, ITransport* communication) : - config(config), input_sensors_(std::move(input_sensors)), communication_(communication) + OpenGlovesTrackingComponent(Config& config, InputSensors& input_sensors, ITransport* communication) : + config_(config), input_sensors_(std::move(input_sensors)), communication_(communication) { this->encoder_ = new og::AlphaEncoder(); } @@ -42,19 +48,51 @@ namespace SenseShift::OpenGloves { { this->communication_->init(); this->input_sensors_.init(); + + if (this->config_.always_calibrate_) { + this->startCalibration(); + } } void tick() override { + this->input_sensors_.tick(); const auto data = this->input_sensors_.collectData(); + const auto length = this->encoder_->encode_input(data, buffer.data(), buffer.size()); + this->communication_->send(buffer.data(), length); + } + + protected: + void startCalibration() + { + for (auto& finger_curl : this->input_sensors_.curl.fingers) { + for (auto& joint_sensor : finger_curl.curl) { + SS_START_CALIBRATION_NOT_NULL(joint_sensor); + } + } - char buffer[256]; - this->encoder_->encode_input(data, buffer, sizeof(buffer)); - this->communication_->send(buffer, sizeof(buffer)); + for (auto& finger_splay : this->input_sensors_.splay.fingers) { + SS_START_CALIBRATION_NOT_NULL(finger_splay); + } + + SS_START_CALIBRATION_NOT_NULL(this->input_sensors_.joystick.x); + SS_START_CALIBRATION_NOT_NULL(this->input_sensors_.joystick.y); + SS_START_CALIBRATION_NOT_NULL(this->input_sensors_.joystick.press); + + for (auto& button : this->input_sensors_.buttons) { + SS_START_CALIBRATION_NOT_NULL(button.press); + } + + for (auto& analog_button : this->input_sensors_.analog_buttons) { + SS_START_CALIBRATION_NOT_NULL(analog_button.press); + SS_START_CALIBRATION_NOT_NULL(analog_button.value); + } } private: - Config& config; + std::array<char, 256> buffer; + + Config& config_; InputSensors input_sensors_; ITransport* communication_; og::IEncoder* encoder_; diff --git a/test/test_io_sensor/main.cpp b/test/test_io_sensor/main.cpp index f91382fe..188cbeaf 100644 --- a/test/test_io_sensor/main.cpp +++ b/test/test_io_sensor/main.cpp @@ -1,5 +1,5 @@ -#include <senseshift/input/sensor.hpp> #include <senseshift/input/analog_threshold.hpp> +#include <senseshift/input/sensor.hpp> #include <unity.h> using namespace SenseShift::Input; @@ -15,7 +15,7 @@ class TestAnalogCountingSensor : public ISimpleSensor<int> { }; class TestAnalogSensor : public ISimpleSensor<int> { -public: + public: int value = 0; int setupCounter = 0; @@ -42,57 +42,56 @@ void test_memoized_sensor(void) TEST_ASSERT_EQUAL_INT(1, sensor->getValue()); } -class DummyCalibrator : public ::SenseShift::Input::Calibration::ICalibrator<int> { +class DummyCalibrator : public ::SenseShift::Input::Calibration::ICalibrator<float> { public: uint8_t resetCounter = 0; - int calibrated = 0; + float calibrated = 0.0f; void reset() override { this->resetCounter++; - this->calibrated = 0; + this->calibrated = 0.0f; }; - void update(int input) override { this->calibrated = input; }; - int calibrate(int 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) { - auto inner = new TestAnalogCountingSensor(); + auto inner = new FloatSensor(); auto calibrator = new DummyCalibrator(); auto sensor = new SimpleSensorDecorator(inner); sensor->setCalibrator(calibrator); - TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); - sensor->init(); - TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); + calibrator->update(-1.0f); + sensor->publishState(0.0f); + TEST_ASSERT_EQUAL_FLOAT(-1.0f, sensor->getValue()); - calibrator->update(-1); - sensor->tick(); - TEST_ASSERT_EQUAL_INT(-1, sensor->getValue()); + sensor->publishState(100.0f); + TEST_ASSERT_EQUAL_FLOAT(-1.0f, sensor->getValue()); + + calibrator->update(2.0f); + sensor->publishState(102.0f); + TEST_ASSERT_EQUAL_FLOAT(2.0f, sensor->getValue()); sensor->startCalibration(); - sensor->tick(); - TEST_ASSERT_EQUAL_INT(2, sensor->getValue()); + sensor->publishState(200.0f); + TEST_ASSERT_EQUAL_FLOAT(200.0f, sensor->getValue()); - sensor->stopCalibration(); - sensor->tick(); - TEST_ASSERT_EQUAL_INT(2, sensor->getValue()); + sensor->publishState(202.0f); + TEST_ASSERT_EQUAL_FLOAT(202.0f, sensor->getValue()); - sensor->reselCalibration(); - sensor->tick(); - TEST_ASSERT_EQUAL_INT(0, sensor->getValue()); - TEST_ASSERT_EQUAL_INT(1, calibrator->resetCounter); + sensor->stopCalibration(); + sensor->publishState(300.0f); + TEST_ASSERT_EQUAL_FLOAT(202.0f, sensor->getValue()); } void test_sensor_filter_multiply(void) { auto inner = new TestAnalogSensor(); auto sensor = new SimpleSensorDecorator(inner); - sensor->addFilters({ - new ::SenseShift::Input::Filter::MultiplyFilter(2) - }); + sensor->addFilters({ new ::SenseShift::Input::Filter::MultiplyFilter(2) }); TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); sensor->init(); From 54212c08806bef11cbd6ef340e24fd31520b440d Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 11 Feb 2024 00:16:39 +0400 Subject: [PATCH 64/82] fix(OpenGloves): incorrect gesture alpha char --- lib/opengloves/opengloves/opengloves.hpp | 6 +++--- test/test_opengloves_alpha_encoding/main.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/opengloves/opengloves/opengloves.hpp b/lib/opengloves/opengloves/opengloves.hpp index e961f908..25448169 100644 --- a/lib/opengloves/opengloves/opengloves.hpp +++ b/lib/opengloves/opengloves/opengloves.hpp @@ -371,12 +371,12 @@ namespace og { /// Alpha keys for analog buttons. /// <b>MUST</b> be in the same order as the `InputPeripheralData` struct. inline static constexpr const std::array<unsigned char, 2> ANALOG_BUTTON_ALPHA_KEY = { { - 'P', // Trigger - 'I', // Grab + 'I', // Trigger + 'L', // Grab } }; [[nodiscard]] auto encode_input(const InputData& input, char* buffer, size_t length) const -> size_t override; [[nodiscard]] auto parse_output(const char* data, size_t length) const -> Output override; }; -} // namespace og \ No newline at end of file +} // namespace og diff --git a/test/test_opengloves_alpha_encoding/main.cpp b/test/test_opengloves_alpha_encoding/main.cpp index 4786fa0a..40cb2638 100644 --- a/test/test_opengloves_alpha_encoding/main.cpp +++ b/test/test_opengloves_alpha_encoding/main.cpp @@ -134,7 +134,7 @@ void test_encode_input_peripherals(void) .pinch = { true }, .grab = { true }, }, - "A0B0C0D0E0MI\n" + "A0B0C0D0E0ML\n" }, { InputPeripheralData({ From 637f5617c3adcf3f77fed2af1c995e1638137b6e Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 11 Feb 2024 13:20:48 +0400 Subject: [PATCH 65/82] test(OpenGloves): update Wokwi test --- .wokwi/lucidgloves-prototype3+serial/test.yaml | 10 +++++----- .wokwi/lucidgloves-prototype4+serial/test.yaml | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.wokwi/lucidgloves-prototype3+serial/test.yaml b/.wokwi/lucidgloves-prototype3+serial/test.yaml index 95f55e39..7dc4c210 100644 --- a/.wokwi/lucidgloves-prototype3+serial/test.yaml +++ b/.wokwi/lucidgloves-prototype3+serial/test.yaml @@ -45,32 +45,32 @@ steps: part-id: pot-thumb control: position value: 1 - - wait-serial: "A4095B4095C0D0E0F2047G2047IM" # M is for Pinch gesture + - wait-serial: "A4095B4095C0D0E0F2047G2047MI" # M is for Pinch gesture # Curl Middle finger - set-control: part-id: pot-middle control: position value: 1 - - wait-serial: "A4095B4095C4095D0E0F2047G2047IM" + - wait-serial: "A4095B4095C4095D0E0F2047G2047MI" # Curl Ring finger - set-control: part-id: pot-ring control: position value: 1 - - wait-serial: "A4095B4095C4095D4095E0F2047G2047IM" + - wait-serial: "A4095B4095C4095D4095E0F2047G2047MI" # Curl Pinky finger - set-control: part-id: pot-pinky control: position value: 1 - - wait-serial: "A4095B4095C4095D4095E4095F2047G2047ILM" # L is for the Grab gesture + - 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' + - wait-serial: "A1024B4095C4095D4095E4095F2047G2047IL" diff --git a/.wokwi/lucidgloves-prototype4+serial/test.yaml b/.wokwi/lucidgloves-prototype4+serial/test.yaml index f89d70f4..cfd56eb9 100644 --- a/.wokwi/lucidgloves-prototype4+serial/test.yaml +++ b/.wokwi/lucidgloves-prototype4+serial/test.yaml @@ -45,28 +45,28 @@ steps: part-id: pot-thumb control: position value: 1 - - wait-serial: "A4095B4095C0D0E0F2047G2047IM" # M is for Pinch gesture + - wait-serial: "A4095B4095C0D0E0F2047G2047MI" # M is for Pinch gesture # Curl Middle finger - set-control: part-id: pot-middle control: position value: 1 - - wait-serial: "A4095B4095C4095D0E0F2047G2047IM" + - wait-serial: "A4095B4095C4095D0E0F2047G2047MI" # Curl Ring finger - set-control: part-id: pot-ring control: position value: 1 - - wait-serial: "A4095B4095C4095D4095E0F2047G2047IM" + - wait-serial: "A4095B4095C4095D4095E0F2047G2047MI" # Curl Pinky finger - set-control: part-id: pot-pinky control: position value: 1 - - wait-serial: "A4095B4095C4095D4095E4095F2047G2047ILM" # L is for the Grab gesture + - wait-serial: "A4095B4095C4095D4095E4095F2047G2047MIL" # L is for the Grab gesture # Partially Release Thumb finger - set-control: From a2fd378c335c4cf3217dd14e002ce01fab1d57ca Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 11 Feb 2024 19:45:21 +0400 Subject: [PATCH 66/82] perf(OpenGloves): fix slow tick rate --- .../mode_configs/opengloves/opengloves.cpp | 9 +- lib/freertos/senseshift/freertos/task.hpp | 14 ++- lib/opengloves/opengloves/opengloves.cpp | 86 +++++++++-------- .../opengloves/transport/stream.hpp | 4 + .../senseshift/opengloves/opengloves_task.hpp | 96 ++++++++++++++----- 5 files changed, 140 insertions(+), 69 deletions(-) diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 1a603125..1491b2e3 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -153,14 +153,13 @@ void setupMode() auto* pinch = new BUTTON_CLASS(PIN_BUTTON_PINCH, BUTTON_PINCH_INVERT); #endif - Serial.begin(115200); - OpenGlovesTrackingComponent::Config tracking_config(2000, true); - auto* opengloves_tracking = - new OpenGlovesTrackingComponent(tracking_config, input_sensors, new StreamTransport(Serial)); + auto* communication = AutoConfig::setupTransport(); + OpenGlovesTrackingComponent::Config tracking_config(CALIBRATION_DURATION, CALIBRATION_ALWAYS_CALIBRATE); + auto* opengloves_tracking = new OpenGlovesTrackingComponent(tracking_config, input_sensors, communication); auto* opengloves_tracking_task = new ::SenseShift::FreeRTOS::ComponentUpdateTask<OpenGlovesTrackingComponent>( opengloves_tracking, - 1000 / 60, + 1000 / UPDATE_RATE, { .name = "OpenGlovesSensorTask", .stackDepth = 8192, diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index aab82a70..38ea81a0 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -133,10 +133,20 @@ namespace SenseShift::FreeRTOS { protected: [[noreturn]] void run() { + auto now = millis(); + auto targetHz = 1000 / this->updateDelay_; + while (true) { + now = millis(); + this->component_->tick(); - delay(this->updateDelay_); - // log_i("high watermark %d", uxTaskGetStackHighWaterMark(NULL)); + + 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); + } } } diff --git a/lib/opengloves/opengloves/opengloves.cpp b/lib/opengloves/opengloves/opengloves.cpp index 924f8914..94e044d2 100644 --- a/lib/opengloves/opengloves/opengloves.cpp +++ b/lib/opengloves/opengloves/opengloves.cpp @@ -5,22 +5,43 @@ #include <cstdio> #include <variant> -#ifdef OG_ENCODE_FAST -template<typename Tp = int, typename Tu = float> -auto ifloor(Tu x) -> Tp -{ - return (Tp) x - (x < (Tp) x); -} - -template<typename Tp = int, typename Tu = float> -auto iceil(Tu x) -> Tp -{ - return (Tp) x + (x > (Tp) x); -} -#endif - namespace og { +#ifdef OG_ENCODE_FASTER + inline auto ifloor(float x) -> int + { + union Cast { + double d; + long l; + }; + volatile Cast c; + c.d = d + 6755399441055743.5; + return c.l; + } +#elifdef OG_ENCODE_FAST + /// Source: https://stackoverflow.com/questions/429632/429812#429812 + inline int float2int(double d) + { + union Cast { + double d; + long l; + }; + volatile Cast c; + c.d = d + 6755399441055744; + return c.l; + } + + inline auto ifloor(float x) -> int + { + return float2int(x) - (x < float2int(x)); + } +#else + inline auto ifloor(float x) -> int + { + return static_cast<int>(std::floor(x)); + } +#endif + auto AlphaEncoder::encode_input(const InputData& input, char* buffer, size_t length) const -> size_t { if (std::holds_alternative<InputInfoData>(input)) { @@ -54,13 +75,8 @@ namespace og { const auto& finger = curls[i]; const auto& finger_curl = finger.curl_total; - written += snprintf( - buffer + written, - length - written, - "%c%u", - 'A' + i, - ifloor<std::uint16_t, float>(finger_curl * MAX_ANALOG_VALUE) - ); + 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++) { @@ -71,18 +87,18 @@ namespace og { written += snprintf( buffer + written, length - written, - "%c%.0f", + "%c%u", finger_alpha_key, - std::floor(finger_curl.curl_total * MAX_ANALOG_VALUE) + ifloor(finger_curl.curl_total * MAX_ANALOG_VALUE) ); if (finger_splay > 0.0F) { written += snprintf( buffer + written, length - written, - "(%cB)%.0f", + "(%cB)%u", finger_alpha_key, - std::floor(finger_splay * MAX_ANALOG_VALUE) + ifloor(finger_splay * MAX_ANALOG_VALUE) ); } @@ -98,29 +114,21 @@ namespace og { written += snprintf( buffer + written, length - written, - "(%cA%c)%.0f", + "(%cA%c)%u", finger_alpha_key, joint_alpha_key, - std::floor(joint * MAX_ANALOG_VALUE) + ifloor(joint * MAX_ANALOG_VALUE) ); } } #endif if (peripheral.joystick.x != 0.0F) { - written += snprintf( - buffer + written, - length - written, - "F%.0f", - std::floor(peripheral.joystick.x * MAX_ANALOG_VALUE) - ); + 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%.0f", - std::floor(peripheral.joystick.y * MAX_ANALOG_VALUE) - ); + 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"); diff --git a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp index d3128165..d233c44a 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp @@ -74,6 +74,8 @@ namespace SenseShift::OpenGloves { return serial->isReady() && serial->hasClient(); } + void init() override {} + virtual size_t send(const char* buffer, size_t length) override { auto written = this->channel->write(buffer, length); @@ -89,6 +91,8 @@ namespace SenseShift::OpenGloves { public: BLESerialTransport(BLESerial& channel) : IStreamTransport(&channel){}; + void init() override {} + bool isReady() override { auto* serial = static_cast<BLESerial*>(this->channel); diff --git a/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp b/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp index 2a5a6f93..b2e6a4cf 100644 --- a/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp +++ b/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp @@ -15,10 +15,11 @@ #include "senseshift/utility.hpp" #include <opengloves/opengloves.hpp> #include <utility> +#include <vector> -#define SS_START_CALIBRATION_NOT_NULL(ptr) \ - if ((ptr) != nullptr) { \ - (ptr)->startCalibration(); \ +#define SS_ADD_CALIBRATOR_NOT_NULL(PTR, STORAGE) \ + if ((PTR) != nullptr) { \ + STORAGE.push_back(PTR); \ } namespace SenseShift::OpenGloves { @@ -42,6 +43,29 @@ namespace SenseShift::OpenGloves { config_(config), input_sensors_(std::move(input_sensors)), communication_(communication) { this->encoder_ = new og::AlphaEncoder(); + + for (auto& finger_curl : this->input_sensors_.curl.fingers) { + for (auto& joint_sensor : finger_curl.curl) { + SS_ADD_CALIBRATOR_NOT_NULL(joint_sensor, this->calibrated_inputs_); + } + } + + for (auto& finger_splay : this->input_sensors_.splay.fingers) { + SS_ADD_CALIBRATOR_NOT_NULL(finger_splay, this->calibrated_inputs_); + } + + SS_ADD_CALIBRATOR_NOT_NULL(this->input_sensors_.joystick.x, this->calibrated_inputs_); + SS_ADD_CALIBRATOR_NOT_NULL(this->input_sensors_.joystick.y, this->calibrated_inputs_); + SS_ADD_CALIBRATOR_NOT_NULL(this->input_sensors_.joystick.press, this->calibrated_inputs_); + + for (auto& button : this->input_sensors_.buttons) { + SS_ADD_CALIBRATOR_NOT_NULL(button.press, this->calibrated_inputs_); + } + + for (auto& analog_button : this->input_sensors_.analog_buttons) { + SS_ADD_CALIBRATOR_NOT_NULL(analog_button.press, this->calibrated_inputs_); + SS_ADD_CALIBRATOR_NOT_NULL(analog_button.value, this->calibrated_inputs_); + } } void init() override @@ -49,49 +73,75 @@ namespace SenseShift::OpenGloves { this->communication_->init(); this->input_sensors_.init(); - if (this->config_.always_calibrate_) { + // 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 = millis(); + + // auto now = millis(); this->input_sensors_.tick(); + // const auto tickTime = millis() - now; + + // now = millis(); const auto data = this->input_sensors_.collectData(); + // const auto collectTime = millis() - now; + + if (data.button_calibrate.press) { + this->startCalibration(); + } + + // now = millis(); const auto length = this->encoder_->encode_input(data, buffer.data(), buffer.size()); + // const auto encodeTime = millis() - now; + + // now = millis(); this->communication_->send(buffer.data(), length); + // const auto sendTime = millis() - now; + + if (!this->config_.always_calibrate_ && (millis() - this->calibration_start_time_) > this->config_.calibration_duration_ms_) { + this->stopCalibration(); + } + + // log_d( + // "total: %d, tick: %d, collect: %d, encode: %d, send: %d", + // millis() - start, + // tickTime, + // collectTime, + // encodeTime, + // sendTime + // ); } protected: void startCalibration() { - for (auto& finger_curl : this->input_sensors_.curl.fingers) { - for (auto& joint_sensor : finger_curl.curl) { - SS_START_CALIBRATION_NOT_NULL(joint_sensor); - } - } - - for (auto& finger_splay : this->input_sensors_.splay.fingers) { - SS_START_CALIBRATION_NOT_NULL(finger_splay); - } - - SS_START_CALIBRATION_NOT_NULL(this->input_sensors_.joystick.x); - SS_START_CALIBRATION_NOT_NULL(this->input_sensors_.joystick.y); - SS_START_CALIBRATION_NOT_NULL(this->input_sensors_.joystick.press); - - for (auto& button : this->input_sensors_.buttons) { - SS_START_CALIBRATION_NOT_NULL(button.press); + log_i("Starting calibration"); + for (auto& calibrated_input : this->calibrated_inputs_) { + calibrated_input->reselCalibration(); + calibrated_input->startCalibration(); } + this->calibration_start_time_ = millis(); + } - for (auto& analog_button : this->input_sensors_.analog_buttons) { - SS_START_CALIBRATION_NOT_NULL(analog_button.press); - SS_START_CALIBRATION_NOT_NULL(analog_button.value); + void stopCalibration() + { + log_i("Stopping calibration"); + for (auto& calibrated_input : this->calibrated_inputs_) { + calibrated_input->stopCalibration(); } } private: std::array<char, 256> buffer; + unsigned long long calibration_start_time_; + std::vector<::SenseShift::Input::Calibration::ICalibrated*> calibrated_inputs_; + Config& config_; InputSensors input_sensors_; ITransport* communication_; From 9b493d22e2d889cbc8a24f832b110b603b86e354 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 11 Feb 2024 22:40:18 +0400 Subject: [PATCH 67/82] feat(OpenGloves): add decoder for FFB --- lib/opengloves/opengloves/opengloves.cpp | 103 ++++++++++++++++++- lib/opengloves/opengloves/opengloves.hpp | 55 ++++++++-- test/test_opengloves_alpha_encoding/main.cpp | 55 ++++++++++ 3 files changed, 202 insertions(+), 11 deletions(-) diff --git a/lib/opengloves/opengloves/opengloves.cpp b/lib/opengloves/opengloves/opengloves.cpp index 94e044d2..b454efd4 100644 --- a/lib/opengloves/opengloves/opengloves.cpp +++ b/lib/opengloves/opengloves/opengloves.cpp @@ -1,8 +1,10 @@ #include "opengloves/opengloves.hpp" +#include <cctype> #include <cmath> #include <cstdint> #include <cstdio> +#include <string> #include <variant> namespace og { @@ -161,8 +163,105 @@ namespace og { return 0; } - auto AlphaEncoder::parse_output(const char* data, size_t length) const -> Output + auto AlphaEncoder::decode_output(const char* data, size_t length) const -> OutputData { - return {}; + 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"); + if (thumb_curl != commands.end()) { + OutputForceFeedbackData ffb{}; + + ffb.thumb = std::stof(thumb_curl->second) / MAX_ANALOG_VALUE; + + const auto& index_curl = commands.find("B"); + if (index_curl != commands.end()) { + ffb.index = std::stof(index_curl->second) / MAX_ANALOG_VALUE; + } + + const auto& middle_curl = commands.find("C"); + if (middle_curl != commands.end()) { + ffb.middle = std::stof(middle_curl->second) / MAX_ANALOG_VALUE; + } + + const auto& ring_curl = commands.find("D"); + if (ring_curl != commands.end()) { + ffb.ring = std::stof(ring_curl->second) / MAX_ANALOG_VALUE; + } + + const auto& pinky_curl = commands.find("E"); + 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::string, std::string> + { + std::map<std::string, std::string> 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<std::string, std::string>& 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 index 25448169..5bd4266f 100644 --- a/lib/opengloves/opengloves/opengloves.hpp +++ b/lib/opengloves/opengloves/opengloves.hpp @@ -51,6 +51,12 @@ namespace og { 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<float>; @@ -68,6 +74,12 @@ namespace og { 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<float>; @@ -131,7 +143,27 @@ namespace og { using InputData = std::variant<InputInfoData, InputPeripheralData>; - class Output {}; + template<typename Tf = float, typename Tb = bool> + using OutputForceFeedback = InputFinger<Tf>; + using OutputForceFeedbackData = OutputForceFeedback<float, bool>; + + template<typename Tf = float, typename Tb = bool> + 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<float, bool>; + + class OutputInvalid { + auto operator==(const OutputInvalid& /*unused*/) const -> bool { return true; } + }; + using OutputData = std::variant<OutputInvalid, OutputForceFeedbackData, OutputHapticsData>; class IEncoder { public: @@ -149,22 +181,22 @@ namespace og { return buffer; } - [[nodiscard]] virtual auto parse_output(const char* data, size_t length) const -> Output = 0; + [[nodiscard]] virtual auto decode_output(const char* data, size_t length) const -> OutputData = 0; - [[nodiscard]] inline auto parse_output(const std::vector<char>& data) const -> Output + [[nodiscard]] inline auto decode_output(const std::vector<char>& data) const -> OutputData { - return this->parse_output(data.data(), data.size()); + return this->decode_output(data.data(), data.size()); } - [[nodiscard]] inline auto parse_output(const std::string& data) const -> Output + [[nodiscard]] inline auto decode_output(const std::string& data) const -> OutputData { - return this->parse_output(data.data(), data.length()); + return this->decode_output(data.data(), data.length()); } #ifdef ARDUINO - [[nodiscard]] inline auto parse_output(const String& data) const -> Output + [[nodiscard]] inline auto decode_output(const String& data) const -> OutputData { - return this->parse_output(data.c_str(), data.length()); + return this->decode_output(data.c_str(), data.length()); } #endif // ARDUINO }; @@ -377,6 +409,11 @@ namespace og { [[nodiscard]] auto encode_input(const InputData& input, char* buffer, size_t length) const -> size_t override; - [[nodiscard]] auto parse_output(const char* data, size_t length) const -> Output 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<std::string, std::string>; + void split_command(const char* data, size_t start, size_t length, std::map<std::string, std::string>& commands) + const; }; } // namespace og diff --git a/test/test_opengloves_alpha_encoding/main.cpp b/test/test_opengloves_alpha_encoding/main.cpp index 40cb2638..9467b45c 100644 --- a/test/test_opengloves_alpha_encoding/main.cpp +++ b/test/test_opengloves_alpha_encoding/main.cpp @@ -173,11 +173,66 @@ void test_encode_input_peripherals(void) } } +void test_decode_output_ffb(void) +{ + const IEncoder* encoder = new AlphaEncoder(); + + std::map<std::string, OutputForceFeedbackData> 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<OutputForceFeedbackData>(decoded)); + TEST_ASSERT_TRUE(std::get<OutputForceFeedbackData>(decoded) == expected); + } +} + int process(void) { UNITY_BEGIN(); RUN_TEST(test_encode_input_peripherals); + RUN_TEST(test_decode_output_ffb); return UNITY_END(); } From 529a0ccc413306b56095b8afea2d3f8598c45f6f Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 18 Feb 2024 13:42:34 +0400 Subject: [PATCH 68/82] feat(OpenGloves): bring back FFB --- .github/workflows/release.yml | 4 +- .../mode_configs/opengloves/opengloves.cpp | 53 +++- ini/opengloves-lucidgloves.ini | 114 ++++---- ini/opengloves.ini | 118 ++++----- lib/arduino/library.json | 21 +- .../senseshift/arduino/output/servo.hpp | 31 +++ .../senseshift/freertos/input/sensor.hpp | 10 - .../senseshift/body/hands/hands_interface.hpp | 36 ++- lib/opengloves/opengloves/opengloves.cpp | 19 +- lib/opengloves/opengloves/opengloves.hpp | 5 +- .../senseshift/opengloves/autoconfig.hpp | 17 +- .../senseshift/opengloves/constants.hpp | 6 +- .../senseshift/opengloves/opengloves.hpp | 79 +++++- .../opengloves/transport/stream.hpp | 36 +-- .../senseshift/opengloves/opengloves_task.hpp | 246 +++++------------- platformio.ini | 48 ++-- 16 files changed, 441 insertions(+), 402 deletions(-) create mode 100644 lib/arduino/senseshift/arduino/output/servo.hpp delete mode 100644 lib/freertos/senseshift/freertos/input/sensor.hpp diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6eb7910a..d2eecde2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -132,8 +132,8 @@ jobs: - indexer-cs - indexer-csf comm_flag: - - OPENGLOVES_COMMUNCATION=OPENGLOVES_COMM_SERIAL - - OPENGLOVES_COMMUNCATION=OPENGLOVES_COMM_BTSERIAL + - OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_SERIAL + - OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL steps: - uses: actions/checkout@v3 with: diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 1491b2e3..0720afe7 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -2,6 +2,7 @@ #include "senseshift/body/hands/input/total_curl.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/input/sensor/digital.hpp> +#include <senseshift/arduino/output/servo.hpp> #include <senseshift/body/hands/input/gesture.hpp> #include <senseshift/input/calibration.hpp> #include <senseshift/input/filter.hpp> @@ -13,11 +14,16 @@ using namespace ::SenseShift::Input; using namespace ::SenseShift::Arduino::Input; +using namespace ::SenseShift::Arduino::Output; using namespace ::SenseShift::Body::Hands::Input; using namespace ::SenseShift::OpenGloves; InputSensors input_sensors; +#ifdef FFB_ENABLED +OutputWriters output_writers; +#endif + void setupMode() { #if FINGER_THUMB_SPLAY @@ -154,19 +160,62 @@ void setupMode() #endif auto* communication = AutoConfig::setupTransport(); + auto* encoding = new og::AlphaEncoder(); OpenGlovesTrackingComponent::Config tracking_config(CALIBRATION_DURATION, CALIBRATION_ALWAYS_CALIBRATE); - auto* opengloves_tracking = new OpenGlovesTrackingComponent(tracking_config, input_sensors, communication); + auto* opengloves_tracking = + new OpenGlovesTrackingComponent(tracking_config, input_sensors, communication, encoding); auto* opengloves_tracking_task = new ::SenseShift::FreeRTOS::ComponentUpdateTask<OpenGlovesTrackingComponent>( opengloves_tracking, 1000 / UPDATE_RATE, { - .name = "OpenGlovesSensorTask", + .name = "OG_TRACKING", .stackDepth = 8192, .priority = 1, } ); opengloves_tracking_task->begin(); + +#if FFB_ENABLED + +#if FFB_THUMB_ENABLED + auto* thumb_ffb_output = new ServoOutput(PIN_FFB_THUMB); + output_writers.ffb.thumb = thumb_ffb_output; +#endif + +#if FFB_INDEX_ENABLED + auto* index_ffb_output = new ServoOutput(PIN_FFB_INDEX); + output_writers.ffb.index = index_ffb_output; +#endif + +#if FFB_MIDDLE_ENABLED + auto* middle_ffb_output = new ServoOutput(PIN_FFB_MIDDLE); + output_writers.ffb.middle = middle_ffb_output; +#endif + +#if FFB_RING_ENABLED + auto* ring_ffb_output = new ServoOutput(PIN_FFB_RING); + output_writers.ffb.ring = ring_ffb_output; +#endif + +#if FFB_PINKY_ENABLED + auto* pinky_ffb_output = new ServoOutput(PIN_FFB_PINKY); + output_writers.ffb.pinky = pinky_ffb_output; +#endif + + auto* og_ffb = new OpenGlovesForceFeedbackComponent(output_writers, communication, encoding); + + auto* og_ffb_task = new ::SenseShift::FreeRTOS::ComponentUpdateTask<OpenGlovesForceFeedbackComponent>( + og_ffb, + 1000 / UPDATE_RATE, + { + .name = "OG_FFB", + .stackDepth = 8192, + .priority = 1, + } + ); + og_ffb_task->begin(); +#endif } void loopMode() diff --git a/ini/opengloves-lucidgloves.ini b/ini/opengloves-lucidgloves.ini index f150cfc4..1c50b00a 100644 --- a/ini/opengloves-lucidgloves.ini +++ b/ini/opengloves-lucidgloves.ini @@ -12,24 +12,26 @@ 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 + ; 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_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_A=27 + -D PIN_BUTTON_B=14 + + -D CALIBRATION_ALWAYS_CALIBRATE=true build_unflags = ${opengloves.build_unflags} build_src_filter = ${opengloves.build_src_filter} - +<mode_configs/opengloves/opengloves.cpp> + +<mode_configs/opengloves/opengloves.cpp> lib_deps = ${opengloves.lib_deps} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -45,29 +47,29 @@ 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 + ; 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} - +<mode_configs/opengloves/opengloves.cpp> + +<mode_configs/opengloves/opengloves.cpp> lib_deps = ${opengloves.lib_deps} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -83,33 +85,33 @@ 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=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 + ; 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} - +<mode_configs/opengloves/opengloves.cpp> + +<mode_configs/opengloves/opengloves.cpp> lib_deps = ${opengloves.lib_deps} diff --git a/ini/opengloves.ini b/ini/opengloves.ini index b7bb70cc..12819792 100644 --- a/ini/opengloves.ini +++ b/ini/opengloves.ini @@ -1,60 +1,60 @@ [opengloves] -platform = platformio/espressif32@^6.1.0 -platform_packages = - platformio/framework-arduinoespressif32@^3.20007.0 -framework = arduino -board = esp32doit-devkit-v1 -upload_speed = 921600 -monitor_speed = 115200 - -build_flags = ${common.build_flags} - -D OPENGLOVES - - ; Communication - ; -D OPENGLOVES_COMMUNCATION=OPENGLOVES_COMM_SERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL, OPENGLOVES_COMM_BLESERIAL - ; Serial - -D SERIAL_BAUDRATE=115200 - -D SERIAL_PORT=Serial ; Serial, Serial1, Serial2, Serial3 - ; BTSerial - '-D BTSERIAL_PREFIX="SenseShift_OG"' - ; '-D BTSERIAL_NAME="SenseShift_OG_Left"' - - ; Sensors - -D FINGER_THUMB_INVERT=false - -D FINGER_INDEX_INVERT=false - -D FINGER_MIDDLE_INVERT=false - -D FINGER_RING_INVERT=false - -D FINGER_PINKY_INVERT=false - - -D FINGER_THUMB_SPLAY_INVERT=false - -D FINGER_INDEX_SPLAY_INVERT=false - -D FINGER_MIDDLE_SPLAY_INVERT=false - -D FINGER_RING_SPLAY_INVERT=false - -D FINGER_PINKY_SPLAY_INVERT=false - - -D JOYSTICK_X_INVERT=false - -D JOYSTICK_Y_INVERT=false - -D JOYSTICK_DEADZONE=0.1 - -D BUTTON_JOYSTICK_INVERT=false - - -D BUTTON_A_INVERT=false - -D BUTTON_B_INVERT=false - -D BUTTON_MENU_INVERT=false - -D BUTTON_CALIBRATE_INVERT=false - -D BUTTON_TRIGGER_INVERT=false - -D BUTTON_GRAB_INVERT=false - -D BUTTON_PINCH_INVERT=false - - -D GESTURE_TRIGGER_ENABLED=true - -D GESTURE_GRAB_ENABLED=true - -D GESTURE_PINCH_ENABLED=true - - ; Calibration - -D CALIBRATION_ALWAYS_CALIBRATE=true - -D CALIBRATION_DURATION=2000 ; in ms - - -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} +platform = platformio/espressif32@^6.1.0 +platform_packages = + platformio/framework-arduinoespressif32@^3.20014.231204 +framework = arduino +board = esp32doit-devkit-v1 +upload_speed = 921600 +monitor_speed = 115200 + +build_flags = ${common.build_flags} + -D OPENGLOVES + + ; Communication + ; -D OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL, OPENGLOVES_COMM_BLESERIAL + ; Serial + -D SERIAL_BAUDRATE=115200 + -D SERIAL_PORT=Serial ; Serial, Serial1, Serial2, Serial3 + ; BTSerial + '-D BTSERIAL_PREFIX="SenseShift_OG"' + ; '-D BTSERIAL_NAME="SenseShift_OG_Left"' + + ; Sensors + -D FINGER_THUMB_INVERT=false + -D FINGER_INDEX_INVERT=false + -D FINGER_MIDDLE_INVERT=false + -D FINGER_RING_INVERT=false + -D FINGER_PINKY_INVERT=false + + -D FINGER_THUMB_SPLAY_INVERT=false + -D FINGER_INDEX_SPLAY_INVERT=false + -D FINGER_MIDDLE_SPLAY_INVERT=false + -D FINGER_RING_SPLAY_INVERT=false + -D FINGER_PINKY_SPLAY_INVERT=false + + -D JOYSTICK_X_INVERT=false + -D JOYSTICK_Y_INVERT=false + -D JOYSTICK_DEADZONE=0.1 + -D BUTTON_JOYSTICK_INVERT=false + + -D BUTTON_A_INVERT=false + -D BUTTON_B_INVERT=false + -D BUTTON_MENU_INVERT=false + -D BUTTON_CALIBRATE_INVERT=false + -D BUTTON_TRIGGER_INVERT=false + -D BUTTON_GRAB_INVERT=false + -D BUTTON_PINCH_INVERT=false + + -D GESTURE_TRIGGER_ENABLED=true + -D GESTURE_GRAB_ENABLED=true + -D GESTURE_PINCH_ENABLED=true + + ; Calibration + -D CALIBRATION_ALWAYS_CALIBRATE=false + -D CALIBRATION_DURATION=2000 ; in ms + + -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} diff --git a/lib/arduino/library.json b/lib/arduino/library.json index 8434426d..b906817b 100644 --- a/lib/arduino/library.json +++ b/lib/arduino/library.json @@ -1,12 +1,13 @@ { - "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", - "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" - } + "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", + "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": "^1.1.2" + } } diff --git a/lib/arduino/senseshift/arduino/output/servo.hpp b/lib/arduino/senseshift/arduino/output/servo.hpp new file mode 100644 index 00000000..81f238eb --- /dev/null +++ b/lib/arduino/senseshift/arduino/output/servo.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include <cstddef> +#include <cstdint> + +#ifdef ESP32 +#include <ESP32Servo.h> +#else +#include <Servo.h> +#endif + +#include <senseshift/output/output.hpp> + +namespace SenseShift::Arduino::Output { + class ServoOutput : public ::SenseShift::Output::IFloatOutput { + public: + ServoOutput(size_t pin) : pin_(pin){}; + + void init() override { this->servo_.attach(this->pin_); } + + void writeState(const ValueType value) override + { + const auto duty = static_cast<std::uint16_t>(value * 180); + this->servo_.write(duty); + } + + private: + Servo servo_; + size_t pin_; + }; +} // namespace SenseShift::Arduino::Output \ No newline at end of file diff --git a/lib/freertos/senseshift/freertos/input/sensor.hpp b/lib/freertos/senseshift/freertos/input/sensor.hpp deleted file mode 100644 index 2a31d67d..00000000 --- a/lib/freertos/senseshift/freertos/input/sensor.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include <senseshift/freertos/task.hpp> -#include <senseshift/input/sensor.hpp> - -#include <cstdint> - -namespace SenseShift::FreeRTOS::Input { - -} // namespace SenseShift::FreeRTOS::Input diff --git a/lib/hands/senseshift/body/hands/hands_interface.hpp b/lib/hands/senseshift/body/hands/hands_interface.hpp index a8887906..cee4877e 100644 --- a/lib/hands/senseshift/body/hands/hands_interface.hpp +++ b/lib/hands/senseshift/body/hands/hands_interface.hpp @@ -4,23 +4,21 @@ #include <cstdint> -namespace SenseShift::Body { - namespace 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, - }; +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, + }; - 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 Hands -} // namespace SenseShift::Body + 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/opengloves/opengloves/opengloves.cpp b/lib/opengloves/opengloves/opengloves.cpp index b454efd4..8f3f0c45 100644 --- a/lib/opengloves/opengloves/opengloves.cpp +++ b/lib/opengloves/opengloves/opengloves.cpp @@ -10,7 +10,7 @@ namespace og { #ifdef OG_ENCODE_FASTER - inline auto ifloor(float x) -> int + inline auto ifloor(float d) -> int { union Cast { double d; @@ -176,27 +176,32 @@ namespace og { // We assume all commands are for ffb, if there is any ffb command const auto& thumb_curl = commands.find("A"); - if (thumb_curl != commands.end()) { + 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{}; - ffb.thumb = std::stof(thumb_curl->second) / MAX_ANALOG_VALUE; + if (thumb_curl != commands.end()) { + ffb.thumb = std::stof(thumb_curl->second) / MAX_ANALOG_VALUE; + } - const auto& index_curl = commands.find("B"); if (index_curl != commands.end()) { ffb.index = std::stof(index_curl->second) / MAX_ANALOG_VALUE; } - const auto& middle_curl = commands.find("C"); if (middle_curl != commands.end()) { ffb.middle = std::stof(middle_curl->second) / MAX_ANALOG_VALUE; } - const auto& ring_curl = commands.find("D"); if (ring_curl != commands.end()) { ffb.ring = std::stof(ring_curl->second) / MAX_ANALOG_VALUE; } - const auto& pinky_curl = commands.find("E"); if (pinky_curl != commands.end()) { ffb.pinky = std::stof(pinky_curl->second) / MAX_ANALOG_VALUE; } diff --git a/lib/opengloves/opengloves/opengloves.hpp b/lib/opengloves/opengloves/opengloves.hpp index 5bd4266f..2d9fd3b4 100644 --- a/lib/opengloves/opengloves/opengloves.hpp +++ b/lib/opengloves/opengloves/opengloves.hpp @@ -114,7 +114,10 @@ namespace og { InputJoystick<Tf, Tb> joystick; union { - std::array<InputButton<Tb>, 5> buttons; + /// Buttons as array. + /// <b>MUST</b> be the same length as the struct below + std::array<InputButton<Tb>, 5> buttons; // NOLINT(*-magic-numbers) We keep it here for clarity + struct { InputButton<Tb> button_a; InputButton<Tb> button_b; diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index 4f114d03..a2e452b0 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -1,5 +1,6 @@ #pragma once +#include <senseshift/opengloves/constants.hpp> #include <senseshift/opengloves/opengloves.hpp> #ifdef ARDUINO @@ -8,8 +9,8 @@ #pragma region Communication -#ifndef OPENGLOVES_COMMUNCATION -#define OPENGLOVES_COMMUNCATION OPENGLOVES_COMM_SERIAL +#ifndef OPENGLOVES_COMMUNICATION +#define OPENGLOVES_COMMUNICATION OPENGLOVES_COMM_SERIAL #endif #ifndef SERIAL_PORT @@ -182,14 +183,14 @@ namespace SenseShift::OpenGloves::AutoConfig { /** * Setup the transport for the OpenGloves interface. */ - [[nodiscard]] ITransport* setupTransport(void) + [[nodiscard]] auto setupTransport() -> ITransport* { -#if OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_SERIAL // Serial +#if OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_SERIAL // Serial auto* pSerial = &SERIAL_PORT; pSerial->begin(SERIAL_BAUDRATE); return new StreamTransport(pSerial); -#elif (OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL) \ - || (OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BLESERIAL) // Bluetooth Serial +#elif (OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BTSERIAL) \ + || (OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BLESERIAL) // Bluetooth Serial std::string name; #ifdef BTSERIAL_NAME name = BTSERIAL_NAME; @@ -201,11 +202,11 @@ namespace SenseShift::OpenGloves::AutoConfig { log_i("Generated Bluetooth name: %s", name.c_str()); #endif -#if OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BTSERIAL // Bluetooth Classic +#if OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BTSERIAL // Bluetooth Classic BluetoothSerial* pBtSerial = new BluetoothSerial(); pBtSerial->begin(name.c_str()); return new BluetoothSerialTransport(*pBtSerial); -#elif OPENGLOVES_COMMUNCATION == OPENGLOVES_COMM_BLESERIAL // Bluetooth Low Energy +#elif OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BLESERIAL // Bluetooth Low Energy BLESerial* pBleSerial = new BLESerial(); pBleSerial->begin(name.c_str()); return new BLESerialTransport(*pBleSerial); diff --git a/lib/opengloves/senseshift/opengloves/constants.hpp b/lib/opengloves/senseshift/opengloves/constants.hpp index df163940..b9de70c9 100644 --- a/lib/opengloves/senseshift/opengloves/constants.hpp +++ b/lib/opengloves/senseshift/opengloves/constants.hpp @@ -2,6 +2,6 @@ #define OPENGLOVES_FINGERS_TASK_PRIORITY 1 -#define OPENGLOVES_COMM_SERIAL 0x1 -#define OPENGLOVES_COMM_BTSERIAL 0x2 -#define OPENGLOVES_COMM_BLESERIAL 0x3 +#define OPENGLOVES_COMM_SERIAL 1 +#define OPENGLOVES_COMM_BTSERIAL 2 +#define OPENGLOVES_COMM_BLESERIAL 3 diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index 0b2d6832..cd4cbd0e 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -1,13 +1,16 @@ #pragma once #include <cstddef> -#include <cstdint> -#include <map> -#include <optional> -#include <string> +#include <set> +#include <variant> +#include <vector> #include <opengloves/opengloves.hpp> +#include <senseshift/core/component.hpp> +#include <senseshift/input/sensor.hpp> +#include <senseshift/output/output.hpp> + namespace SenseShift::OpenGloves { class ITransport : public IInitializable { public: @@ -19,18 +22,27 @@ namespace SenseShift::OpenGloves { using FloatSensor = ::SenseShift::Input::FloatSensor; using BinarySensor = ::SenseShift::Input::BinarySensor; - class InputSensors : public og::InputPeripheral<FloatSensor*, BinarySensor*>, public Component { + class InputSensors : + public og::InputPeripheral<FloatSensor*, BinarySensor*>, + 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) { - SS_INIT_NOT_NULL(joint_sensor); + if (joint_sensor != nullptr) { + joint_sensor->init(); + this->calibrated_inputs_.insert(joint_sensor); + } } } for (auto& finger_splay : this->splay.fingers) { - SS_INIT_NOT_NULL(finger_splay); + if (finger_splay != nullptr) { + finger_splay->init(); + this->calibrated_inputs_.insert(finger_splay); + } } SS_INIT_NOT_NULL(this->joystick.x); @@ -124,5 +136,58 @@ namespace SenseShift::OpenGloves { return data; } + + 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 stopCalibration() override + { + for (const auto& calibrated_input : this->calibrated_inputs_) { + calibrated_input->stopCalibration(); + } + } + + private: + std::set<FloatSensor*> calibrated_inputs_{}; + }; + + using FloatOutput = ::SenseShift::Output::IFloatOutput; + + class OutputWriters : public IInitializable { + public: + og::OutputForceFeedback<FloatOutput*, void*> ffb; + + void init() override + { + for (auto& finger : this->ffb.fingers) { + if (finger != nullptr) { + finger->init(); + } + } + } + + void apply(const og::OutputData& data) + { + if (std::holds_alternative<og::OutputForceFeedbackData>(data)) { + const auto& ffb_data = std::get<og::OutputForceFeedbackData>(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_arduino/senseshift/opengloves/transport/stream.hpp b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp index d233c44a..12d413e2 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp @@ -1,5 +1,7 @@ #pragma once +#include <array> + #include <senseshift/buffer.hpp> #include <BLESerial.hpp> @@ -14,12 +16,12 @@ namespace SenseShift::OpenGloves { class IStreamTransport : public ITransport { protected: Stream* channel; - char* buffer = new char[256]; + std::array<char, 256> buffer_{}; public: IStreamTransport(Stream* channel) : channel(channel){}; - size_t send(const char* buffer, size_t length) override + auto send(const char* buffer, size_t length) -> size_t override { if (!this->isReady()) { return 0; @@ -31,17 +33,17 @@ namespace SenseShift::OpenGloves { return written; } - virtual bool isReady() = 0; + virtual auto isReady() -> bool = 0; - virtual bool hasData() override + auto hasData() -> bool override { return this->isReady() && this->channel != nullptr && this->channel->available() > 0; } - virtual size_t read(char* buffer, size_t length) + auto read(char* buffer, size_t length) -> size_t override { if (!this->hasData()) { - return false; + return 0U; } size_t bytesRead = this->channel->readBytesUntil('\n', buffer, length); @@ -53,12 +55,12 @@ namespace SenseShift::OpenGloves { class StreamTransport : public IStreamTransport { public: - StreamTransport(Stream& channel) : IStreamTransport(&channel){}; - StreamTransport(Stream* channel) : IStreamTransport(channel){}; + explicit StreamTransport(Stream& channel) : IStreamTransport(&channel){}; + explicit StreamTransport(Stream* channel) : IStreamTransport(channel){}; void init() override { this->mReady = true; } - bool isReady() override { return this->channel != nullptr && this->mReady; } + auto isReady() -> bool override { return this->channel != nullptr && this->mReady; } private: bool mReady = false; @@ -66,9 +68,9 @@ namespace SenseShift::OpenGloves { class BluetoothSerialTransport : public IStreamTransport { public: - BluetoothSerialTransport(BluetoothSerial& channel) : IStreamTransport(&channel){}; + explicit BluetoothSerialTransport(BluetoothSerial& channel) : IStreamTransport(&channel){}; - bool isReady() override + auto isReady() -> bool override { auto* serial = static_cast<BluetoothSerial*>(this->channel); return serial->isReady() && serial->hasClient(); @@ -76,7 +78,7 @@ namespace SenseShift::OpenGloves { void init() override {} - virtual size_t send(const char* buffer, size_t length) override + auto send(const char* buffer, size_t length) -> size_t override { auto written = this->channel->write(buffer, length); @@ -89,11 +91,11 @@ namespace SenseShift::OpenGloves { class BLESerialTransport : public IStreamTransport { public: - BLESerialTransport(BLESerial& channel) : IStreamTransport(&channel){}; + explicit BLESerialTransport(BLESerial& channel) : IStreamTransport(&channel){}; void init() override {} - bool isReady() override + auto isReady() -> bool override { auto* serial = static_cast<BLESerial*>(this->channel); return serial->connected(); @@ -108,7 +110,7 @@ namespace SenseShift::OpenGloves { { auto* client = static_cast<WiFiClient*>(this->channel); if (client != nullptr) { - if (client->connected()) { + if (client->connected() != 0U) { return; } } @@ -117,14 +119,14 @@ namespace SenseShift::OpenGloves { this->channel = new WiFiClient(this->m_server.available()); } - bool isReady() override + auto isReady() -> bool override { if (this->channel == nullptr) { return false; } auto* client = static_cast<WiFiClient*>(this->channel); - return client->connected(); + return client->connected() != 0U; } private: diff --git a/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp b/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp index b2e6a4cf..f8509f3d 100644 --- a/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp +++ b/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp @@ -17,11 +17,6 @@ #include <utility> #include <vector> -#define SS_ADD_CALIBRATOR_NOT_NULL(PTR, STORAGE) \ - if ((PTR) != nullptr) { \ - STORAGE.push_back(PTR); \ - } - namespace SenseShift::OpenGloves { class OpenGlovesTrackingComponent : public SenseShift::Component { public: @@ -39,33 +34,14 @@ namespace SenseShift::OpenGloves { } }; - OpenGlovesTrackingComponent(Config& config, InputSensors& input_sensors, ITransport* communication) : - config_(config), input_sensors_(std::move(input_sensors)), communication_(communication) + OpenGlovesTrackingComponent( + Config& config, + InputSensors& input_sensors, + ITransport* communication, + og::IEncoder* encoder = new og::AlphaEncoder() + ) : + config_(config), input_sensors_(std::move(input_sensors)), communication_(communication), encoder_(encoder) { - this->encoder_ = new og::AlphaEncoder(); - - for (auto& finger_curl : this->input_sensors_.curl.fingers) { - for (auto& joint_sensor : finger_curl.curl) { - SS_ADD_CALIBRATOR_NOT_NULL(joint_sensor, this->calibrated_inputs_); - } - } - - for (auto& finger_splay : this->input_sensors_.splay.fingers) { - SS_ADD_CALIBRATOR_NOT_NULL(finger_splay, this->calibrated_inputs_); - } - - SS_ADD_CALIBRATOR_NOT_NULL(this->input_sensors_.joystick.x, this->calibrated_inputs_); - SS_ADD_CALIBRATOR_NOT_NULL(this->input_sensors_.joystick.y, this->calibrated_inputs_); - SS_ADD_CALIBRATOR_NOT_NULL(this->input_sensors_.joystick.press, this->calibrated_inputs_); - - for (auto& button : this->input_sensors_.buttons) { - SS_ADD_CALIBRATOR_NOT_NULL(button.press, this->calibrated_inputs_); - } - - for (auto& analog_button : this->input_sensors_.analog_buttons) { - SS_ADD_CALIBRATOR_NOT_NULL(analog_button.press, this->calibrated_inputs_); - SS_ADD_CALIBRATOR_NOT_NULL(analog_button.value, this->calibrated_inputs_); - } } void init() override @@ -81,39 +57,47 @@ namespace SenseShift::OpenGloves { void tick() override { - // const auto start = millis(); + // const auto start = micros(); - // auto now = millis(); + // auto now = micros(); this->input_sensors_.tick(); - // const auto tickTime = millis() - now; + // const auto tickTime = micros() - now; - // now = millis(); + // now = micros(); const auto data = this->input_sensors_.collectData(); - // const auto collectTime = millis() - now; + // const auto collectTime = micros() - now; - if (data.button_calibrate.press) { + bool const calibrate_pressed = data.button_calibrate.press; + if (calibrate_pressed && this->calibration_start_time_ == 0) { this->startCalibration(); } - // now = millis(); + // now = micros(); const auto length = this->encoder_->encode_input(data, buffer.data(), buffer.size()); - // const auto encodeTime = millis() - now; + // const auto encodeTime = micros() - now; - // now = millis(); + // now = micros(); this->communication_->send(buffer.data(), length); - // const auto sendTime = millis() - now; + // const auto sendTime = micros() - now; + + 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_; - if (!this->config_.always_calibrate_ && (millis() - this->calibration_start_time_) > this->config_.calibration_duration_ms_) { - this->stopCalibration(); + if (calibration_done) { + this->stopCalibration(); + } } - // log_d( - // "total: %d, tick: %d, collect: %d, encode: %d, send: %d", - // millis() - start, + // 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 + // sendTime, + // 1000000.0 / total // ); } @@ -121,26 +105,22 @@ namespace SenseShift::OpenGloves { void startCalibration() { log_i("Starting calibration"); - for (auto& calibrated_input : this->calibrated_inputs_) { - calibrated_input->reselCalibration(); - calibrated_input->startCalibration(); - } + this->input_sensors_.reselCalibration(); + this->input_sensors_.startCalibration(); this->calibration_start_time_ = millis(); } void stopCalibration() { log_i("Stopping calibration"); - for (auto& calibrated_input : this->calibrated_inputs_) { - calibrated_input->stopCalibration(); - } + this->input_sensors_.stopCalibration(); + this->calibration_start_time_ = 0; } private: - std::array<char, 256> buffer; + std::array<char, 256> buffer = {}; - unsigned long long calibration_start_time_; - std::vector<::SenseShift::Input::Calibration::ICalibrated*> calibrated_inputs_; + unsigned long long calibration_start_time_ = 0; Config& config_; InputSensors input_sensors_; @@ -148,124 +128,36 @@ namespace SenseShift::OpenGloves { og::IEncoder* encoder_; }; - // class OpenGlovesForceFeedbackTask : public SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask> { - // friend class SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>; - // - // public: - // OpenGlovesForceFeedbackTask( - // ::SenseShift::OpenGloves::ITransport& communication, - // HandActuators& actuators, - // size_t updateRate, - // SenseShift::FreeRTOS::TaskConfig taskConfig - // ) : - // communication(communication), - // actuators(actuators), - // SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>(taskConfig) - // { - // this->updateIntervalMs = 1000 / updateRate; - // }; - // - // void begin() override - // { - // log_d("Starting OpenGloves force feedback task: %p", this); - // this->setup(); - // this->SenseShift::FreeRTOS::Task<OpenGlovesForceFeedbackTask>::begin(); - // }; - // - // private: - // ::SenseShift::OpenGloves::ITransport& communication; - // HandActuators& actuators; - // size_t updateIntervalMs; - // ::SenseShift::OpenGloves::AlphaEncodingService encodingService = - // ::SenseShift::OpenGloves::AlphaEncodingService(); - // - // void setup() - // { - // log_d("Setting up OpenGloves force feedback task: %p", this); - // this->communication.setup(); - // - // if (this->actuators.thumb.has_value()) { - // this->actuators.thumb.value()->setup(); - // } - // - // if (this->actuators.index.has_value()) { - // this->actuators.index.value()->setup(); - // } - // - // if (this->actuators.middle.has_value()) { - // this->actuators.middle.value()->setup(); - // } - // - // if (this->actuators.ring.has_value()) { - // this->actuators.ring.value()->setup(); - // } - // - // if (this->actuators.pinky.has_value()) { - // this->actuators.pinky.value()->setup(); - // } - // } - // - // void run() - // { - // char commandBuffer[256]; - // std::string command; - // while (true) { - // auto now = millis(); - // - // if (this->communication.hasData()) { - // auto bytesRead = this->communication.read(commandBuffer, sizeof(commandBuffer)); - // if (bytesRead == 0) { - // continue; - // } - // - // std::map<::OpenGloves::Command, uint16_t> commands = {}; - // this->encodingService.deserialize(commandBuffer, bytesRead, commands); - // - // for (auto& [command, value] : commands) { - // this->handleCommand(command, value); - // } - // } - // - // // Delay until the next update. - // auto elapsed = millis() - now; - // if (elapsed < this->updateIntervalMs) { - // delay(this->updateIntervalMs - elapsed); - // } - // } - // } - // - // void handleCommand(Command command, uint16_t value) - // { - // switch (command) { - // case Command::ThumbCurl: - // if (this->actuators.thumb.has_value()) { - // this->actuators.thumb.value()->writeOutput(value); - // } - // break; - // case Command::IndexCurl: - // if (this->actuators.index.has_value()) { - // this->actuators.index.value()->writeOutput(value); - // } - // break; - // case Command::MiddleCurl: - // if (this->actuators.middle.has_value()) { - // this->actuators.middle.value()->writeOutput(value); - // } - // break; - // case Command::RingCurl: - // if (this->actuators.ring.has_value()) { - // this->actuators.ring.value()->writeOutput(value); - // } - // break; - // case Command::PinkyCurl: - // if (this->actuators.pinky.has_value()) { - // this->actuators.pinky.value()->writeOutput(value); - // } - // break; - // default: - // log_w("Unhandled command: %d", command); - // break; - // } - // } - // }; + class OpenGlovesForceFeedbackComponent : public SenseShift::Component { + public: + OpenGlovesForceFeedbackComponent( + OutputWriters& output_writers, + ::SenseShift::OpenGloves::ITransport* communication, + og::IEncoder* encoder = new og::AlphaEncoder() + ) : + output_writers_(output_writers), communication_(communication), encoder_(encoder){}; + + 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 = this->encoder_->decode_output(this->buffer.data(), length); + this->output_writers_.apply(output); + } + } + + private: + std::array<char, 256> buffer = {}; + + OutputWriters output_writers_; + ::SenseShift::OpenGloves::ITransport* communication_; + og::IEncoder* encoder_; + }; } // namespace SenseShift::OpenGloves diff --git a/platformio.ini b/platformio.ini index 2b718462..ea55d804 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,58 +9,58 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] -description = Open Source Haptic-feedback device firmware -lib_dir = ./lib -src_dir = ./firmware +description = Open Source Haptic-feedback device firmware +lib_dir = ./lib +src_dir = ./firmware extra_configs = - ini/bhaptics.ini + 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 +default_envs = bhaptics_tactsuit_x16, bhaptics_tactal, bhaptics_tactglove_left, lucidgloves-prototype3 [common] -build_unflags = +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 SENSESHIFT_SERIAL_PLOTTER=true - -D SENSESHIFT_BATTERY_ENABLED=true +; -D SENSESHIFT_BATTERY_ENABLED=true ; -D SENSESHIFT_BLE_USE_NIMBLE=true -build_src_filter = +build_src_filter = +<*> -<mode_configs> -lib_deps = +lib_deps = [env] -build_flags = ${common.build_flags} -build_unflags = ${common.build_unflags} +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+ +lib_deps = ${common.lib_deps} +lib_ldf_mode = deep+ -check_tool = clangtidy +check_tool = clangtidy check_flags = clangtidy: --config-file=./.clang-tidy --fix debug_build_flags = -Os [env:native] -platform = native +platform = native -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} - -lgcov - --coverage +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} + -lgcov + --coverage build_src_filter = ${common.build_src_filter} - +<mode_configs/test.cpp> -lib_deps = ${common.lib_deps} - fabiobatsilva/ArduinoFake@^0.4 + +<mode_configs/test.cpp> +lib_deps = ${common.lib_deps} + fabiobatsilva/ArduinoFake@^0.4 -test_ignore = test_embedded +test_ignore = test_embedded From dbf35e25094344c14f5b14a76387a8f5afe51de3 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 18 Feb 2024 13:45:55 +0400 Subject: [PATCH 69/82] fix(BLE Serial): fix sending duplicate strings --- ini/bhaptics.ini | 418 +++++++++++++++++------------------ lib/ble_serial/BLESerial.hpp | 4 +- 2 files changed, 211 insertions(+), 211 deletions(-) diff --git a/ini/bhaptics.ini b/ini/bhaptics.ini index ac624ea8..f3289e11 100644 --- a/ini/bhaptics.ini +++ b/ini/bhaptics.ini @@ -1,71 +1,71 @@ [bhaptics] -platform = platformio/espressif32@^6.1.0 -platform_packages = - platformio/framework-arduinoespressif32@^3.20007.0 -framework = arduino -board = esp32doit-devkit-v1 -upload_speed = 921600 -monitor_speed = 115200 +platform = platformio/espressif32@^6.1.0 +platform_packages = + platformio/framework-arduinoespressif32@^3.20014.231204 +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} +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} +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} - +<mode_configs/bhaptics/tactsuit_x16.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactsuit_x16.cpp> +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} +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} - +<mode_configs/bhaptics/tactsuit_x16_pca9685.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactsuit_x16_pca9685.cpp> +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} +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} - +<mode_configs/bhaptics/tactsuit_x40.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactsuit_x40.cpp> +lib_deps = ${bhaptics.lib_deps} ; [env:bhaptics_tactbelt] ; platform = ${bhaptics.platform} @@ -86,183 +86,183 @@ lib_deps = ${bhaptics.lib_deps} ; 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} +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} - +<mode_configs/bhaptics/tactosy2.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosy2.cpp> +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} +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} - +<mode_configs/bhaptics/tactosy2.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosy2.cpp> +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} +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} - +<mode_configs/bhaptics/tactosyh.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosyh.cpp> +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} +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} - +<mode_configs/bhaptics/tactosyh.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosyh.cpp> +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} +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} - +<mode_configs/bhaptics/tactosyf.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosyf.cpp> +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} +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} - +<mode_configs/bhaptics/tactosyf.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosyf.cpp> +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} +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} - +<mode_configs/bhaptics/tactal.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactal.cpp> +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} +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} - +<mode_configs/bhaptics/tactvisor.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactvisor.cpp> +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} +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 SENSESHIFT_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} - +<mode_configs/bhaptics/tactglove.cpp> -lib_deps = ${bhaptics.lib_deps} +build_flags = ${bhaptics.build_flags} + -D BH_DEVICE_TACTGLOVE + -D SENSESHIFT_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} + +<mode_configs/bhaptics/tactglove.cpp> +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} +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 SENSESHIFT_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} - +<mode_configs/bhaptics/tactglove.cpp> -lib_deps = ${bhaptics.lib_deps} +build_flags = ${bhaptics.build_flags} + -D BH_DEVICE_TACTGLOVE + -D SENSESHIFT_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} + +<mode_configs/bhaptics/tactglove.cpp> +lib_deps = ${bhaptics.lib_deps} diff --git a/lib/ble_serial/BLESerial.hpp b/lib/ble_serial/BLESerial.hpp index b239eec2..090ecb75 100644 --- a/lib/ble_serial/BLESerial.hpp +++ b/lib/ble_serial/BLESerial.hpp @@ -42,7 +42,7 @@ class BLESerial : public Stream { } this->m_pTxCharacteristic->setValue(const_cast<uint8_t*>(buffer), bufferSize); - this->flush(); + // this->flush(); return bufferSize; } @@ -54,7 +54,7 @@ class BLESerial : public Stream { } this->m_pTxCharacteristic->setValue(&byte, 1); - this->flush(); + // this->flush(); return 1; } From 74cd0aaf56365a1cab9703df4a4b798698519af5 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 18 Feb 2024 15:17:06 +0400 Subject: [PATCH 70/82] fix(bHaptics): removed file being included --- firmware/mode_configs/bhaptics/tactal.cpp | 7 +++---- firmware/mode_configs/bhaptics/tactglove.cpp | 7 +++---- firmware/mode_configs/bhaptics/tactosy2.cpp | 7 +++---- firmware/mode_configs/bhaptics/tactosyf.cpp | 7 +++---- firmware/mode_configs/bhaptics/tactosyh.cpp | 7 +++---- firmware/mode_configs/bhaptics/tactsuit_x16.cpp | 7 +++---- firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp | 7 +++---- firmware/mode_configs/bhaptics/tactsuit_x40.cpp | 7 +++---- firmware/mode_configs/bhaptics/tactvisor.cpp | 7 +++---- 9 files changed, 27 insertions(+), 36 deletions(-) diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index 8a452ab5..ec8ea898 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -4,22 +4,21 @@ #include <Arduino.h> #include <Wire.h> -#include "senseshift.h" +#include <senseshift.h> -#include "senseshift/battery/input/battery_sensor.hpp" #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/input/sensor.hpp> +#include <senseshift/freertos/task.hpp> using namespace SenseShift; using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 1fa2aa4e..d67f58e6 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -4,15 +4,15 @@ #include <Arduino.h> #include <Wire.h> -#include "senseshift.h" +#include <senseshift.h> -#include "senseshift/battery/input/battery_sensor.hpp" #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/input/sensor.hpp> +#include <senseshift/freertos/task.hpp> #include <senseshift/utility.hpp> using namespace SenseShift; @@ -20,7 +20,6 @@ using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index e630072b..c3053bd3 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -4,22 +4,21 @@ #include <Arduino.h> #include <Wire.h> -#include "senseshift.h" +#include <senseshift.h> -#include "senseshift/battery/input/battery_sensor.hpp" #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/input/sensor.hpp> +#include <senseshift/freertos/task.hpp> using namespace SenseShift; using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index d35a6427..b2c47e26 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -4,22 +4,21 @@ #include <Arduino.h> #include <Wire.h> -#include "senseshift.h" +#include <senseshift.h> -#include "senseshift/battery/input/battery_sensor.hpp" #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/input/sensor.hpp> +#include <senseshift/freertos/task.hpp> using namespace SenseShift; using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 3fd258cc..11bbe0a4 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -4,22 +4,21 @@ #include <Arduino.h> #include <Wire.h> -#include "senseshift.h" +#include <senseshift.h> -#include "senseshift/battery/input/battery_sensor.hpp" #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/input/sensor.hpp> +#include <senseshift/freertos/task.hpp> using namespace SenseShift; using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 1f8bd345..ae6011f2 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -4,22 +4,21 @@ #include <Arduino.h> #include <Wire.h> -#include "senseshift.h" +#include <senseshift.h> -#include "senseshift/battery/input/battery_sensor.hpp" #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/input/sensor.hpp> +#include <senseshift/freertos/task.hpp> using namespace SenseShift; using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index e3ac3769..b8b05c77 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -4,22 +4,21 @@ #include <Arduino.h> #include <Wire.h> -#include "senseshift.h" +#include <senseshift.h> -#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/pca9685.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/input/sensor.hpp> +#include <senseshift/freertos/task.hpp> using namespace SenseShift; using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 3a88f119..a3d77b06 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -4,23 +4,22 @@ #include <Arduino.h> #include <Wire.h> -#include "senseshift.h" +#include <senseshift.h> -#include "senseshift/battery/input/battery_sensor.hpp" #include <senseshift/arduino/input/sensor/analog.hpp> #include <senseshift/arduino/output/ledc.hpp> #include <senseshift/arduino/output/pca9685.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/input/sensor.hpp> +#include <senseshift/freertos/task.hpp> using namespace SenseShift; using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index 83b44903..38ece6af 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -4,22 +4,21 @@ #include <Arduino.h> #include <Wire.h> -#include "senseshift.h" +#include <senseshift.h> -#include "senseshift/battery/input/battery_sensor.hpp" #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/input/sensor.hpp> +#include <senseshift/freertos/task.hpp> using namespace SenseShift; using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; using namespace SenseShift::Arduino::Input; -using namespace SenseShift::FreeRTOS::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; From ddff5a42355b7215cd6b5bf99918a44cec2bee4a Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 18 Feb 2024 18:20:23 +0400 Subject: [PATCH 71/82] style(clang-format): lint-fix --- firmware/senseshift.cpp | 4 +- .../senseshift/arduino/output/analog.hpp | 10 +- .../senseshift/arduino/output/pca9685.hpp | 4 +- .../senseshift/arduino/output/ledc.hpp | 42 ++++---- lib/bhaptics/senseshift/bh/devices.hpp | 43 +++----- lib/bhaptics/senseshift/bh/encoding.hpp | 55 +++++------ lib/haptics/senseshift/body/haptics/body.cpp | 4 +- lib/haptics/senseshift/body/haptics/body.hpp | 10 +- lib/haptics/senseshift/body/haptics/plane.cpp | 9 +- lib/haptics/senseshift/body/haptics/plane.hpp | 13 +-- lib/io/senseshift/output/output.hpp | 2 +- lib/math/senseshift/math/point2.hpp | 5 +- test/test_bhaptics_encoding/main.cpp | 97 ++++++++++--------- test/test_core_helpers/main.cpp | 2 +- 14 files changed, 142 insertions(+), 158 deletions(-) diff --git a/firmware/senseshift.cpp b/firmware/senseshift.cpp index d6445325..a4f7ab8b 100644 --- a/firmware/senseshift.cpp +++ b/firmware/senseshift.cpp @@ -9,11 +9,11 @@ #include <senseshift/core/logging.hpp> namespace SenseShift { - static const char *const TAG = "application"; + static const char* const TAG = "application"; Application::Application() { - this->vibro_body_ = new Body::Haptics::FloatBody (); + this->vibro_body_ = new Body::Haptics::FloatBody(); } void Application::postEvent(const IEvent* event) diff --git a/lib/arduino/senseshift/arduino/output/analog.hpp b/lib/arduino/senseshift/arduino/output/analog.hpp index 7dec32b6..28358ac3 100644 --- a/lib/arduino/senseshift/arduino/output/analog.hpp +++ b/lib/arduino/senseshift/arduino/output/analog.hpp @@ -12,14 +12,12 @@ namespace SenseShift::Arduino::Output { public: static inline constexpr std::uint16_t MAX_INTENSITY = 255; - explicit AnalogOutput(const std::uint8_t pin) : pin_(pin) { - } + explicit AnalogOutput(const std::uint8_t pin) : pin_(pin) {} - void init() override { - pinMode(this->pin_, OUTPUT); - } + void init() override { pinMode(this->pin_, OUTPUT); } - void writeState(const float value) override { + void writeState(const float value) override + { const auto duty = static_cast<int>(value * MAX_INTENSITY); analogWrite(this->pin_, duty); } diff --git a/lib/arduino/senseshift/arduino/output/pca9685.hpp b/lib/arduino/senseshift/arduino/output/pca9685.hpp index 62ea63cf..1bbffd38 100644 --- a/lib/arduino/senseshift/arduino/output/pca9685.hpp +++ b/lib/arduino/senseshift/arduino/output/pca9685.hpp @@ -16,9 +16,7 @@ namespace SenseShift::Arduino::Output { PCA9685Output(Adafruit_PWMServoDriver* driver, const std::uint8_t num) : driver_(driver), channel_(num){}; - void init() override { - this->driver_->begin(); - } + void init() override { this->driver_->begin(); } void writeState(const ValueType value) override { diff --git a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp index 2d1d810c..6c29efed 100644 --- a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp +++ b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp @@ -4,49 +4,53 @@ #include <esp32-hal-ledc.h> -#include <senseshift/output/output.hpp> #include <senseshift/core/logging.hpp> +#include <senseshift/output/output.hpp> namespace SenseShift::Arduino::Output { - static const char *const TAG = "output.ledc"; + static const char* const TAG = "output.ledc"; /// Arduino analog output class LedcOutput : public ::SenseShift::Output::IFloatOutput { - public: + 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) {} + 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) + { + } - void init() override { + 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){ - LOG_E(TAG, "setup failed (freq = %u, resolution = %u). Try setting different resolution or frequency", this->analog_frequency_, this->analog_resolution_); + if (ledcSetup(this->channel_, this->analog_frequency_, this->analog_resolution_) == 0) { + LOG_E( + TAG, + "setup failed (freq = %u, resolution = %u). Try setting different resolution or frequency", + this->analog_frequency_, + this->analog_resolution_ + ); return; } ledcAttachPin(this->pin_, this->channel_); } - [[nodiscard]] auto getMaxValue() const -> std::uint32_t { - return (1 << analog_resolution_) - 1; - } + [[nodiscard]] auto getMaxValue() const -> std::uint32_t { return (1 << analog_resolution_) - 1; } - void writeState(const float value) override { + void writeState(const float value) override + { const auto duty = static_cast<std::uint32_t>(value * this->getMaxValue()); LOG_V(TAG, "GPIO %d - Writing %d to Channel %d", this->pin_, duty, this->channel_); ledcWrite(this->channel_, duty); }; - protected: - static auto findChannel(std::uint8_t /*pin*/) -> std::int8_t { - return CHANNELS++; - } + protected: + static auto findChannel(std::uint8_t /*pin*/) -> std::int8_t { return CHANNELS++; } - private: + private: static inline std::uint8_t CHANNELS = 0; std::uint8_t pin_; diff --git a/lib/bhaptics/senseshift/bh/devices.hpp b/lib/bhaptics/senseshift/bh/devices.hpp index b90d627c..5cd2b438 100644 --- a/lib/bhaptics/senseshift/bh/devices.hpp +++ b/lib/bhaptics/senseshift/bh/devices.hpp @@ -5,8 +5,8 @@ #include "senseshift/body/hands/hands_interface.hpp" -#include <senseshift/body/haptics/plane.hpp> #include <senseshift/body/haptics/body.hpp> +#include <senseshift/body/haptics/plane.hpp> #pragma region BH_DEVICE_TACTSUITX40 @@ -299,8 +299,12 @@ namespace SenseShift::BH { // TactGlove Wrist motor position static constexpr const Position WRIST_MOTOR_POSITION(127, 191); - static constexpr const std::array<OutputLayout, BH_LAYOUT_TACTGLOVE_SIZE> TactGloveLeftLayout = { BH_LAYOUT_TACTGLOVE_LEFT }; - static constexpr const std::array<OutputLayout, BH_LAYOUT_TACTGLOVE_SIZE> TactGloveRightLayout = { BH_LAYOUT_TACTGLOVE_RIGHT }; + static constexpr const std::array<OutputLayout, BH_LAYOUT_TACTGLOVE_SIZE> TactGloveLeftLayout = { + BH_LAYOUT_TACTGLOVE_LEFT + }; + static constexpr const std::array<OutputLayout, BH_LAYOUT_TACTGLOVE_SIZE> TactGloveRightLayout = { + BH_LAYOUT_TACTGLOVE_RIGHT + }; inline void addTactGloveActuators( FloatBody* hapticBody, @@ -311,49 +315,32 @@ namespace SenseShift::BH { 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 } }) - ); + 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 } }) - ); + 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 } }) - ); + 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 } }) - ); + 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 } }) - ); + 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 } }) - ); + 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 1a8b8af4..e23a55f3 100644 --- a/lib/bhaptics/senseshift/bh/encoding.hpp +++ b/lib/bhaptics/senseshift/bh/encoding.hpp @@ -7,8 +7,8 @@ #include <string> #include <tuple> -#include <senseshift/body/haptics/interface.hpp> #include <senseshift/body/haptics/body.hpp> +#include <senseshift/body/haptics/interface.hpp> namespace SenseShift::BH { class Decoder { @@ -30,26 +30,21 @@ namespace SenseShift::BH { const std::array<std::uint8_t, N>& value, const std::array<OutputLayout, N>& 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<FloatBody::Plane::Value>(effectDataFromByte(byte)) - ); + output->effect(target, position, static_cast<FloatBody::Plane::Value>(effectDataFromByte(byte))); } } template<size_t N> static void applyPlain( - FloatBody* output, - std::string& value, - const std::array<OutputLayout, N>& layout, - const Effect effect - ) { + FloatBody* output, std::string& value, const std::array<OutputLayout, N>& layout, const Effect effect + ) + { std::array<std::uint8_t, N> buf{}; std::size_t copyLength = std::min(value.size(), sizeof(buf)); std::memcpy(buf.data(), value.c_str(), copyLength); @@ -67,16 +62,13 @@ namespace SenseShift::BH { const std::array<Position, N>& 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<FloatBody::Plane::Value>(effectDataFromByte(byte)) - ); + output->effect(target, position, static_cast<FloatBody::Plane::Value>(effectDataFromByte(byte))); } } @@ -87,7 +79,8 @@ namespace SenseShift::BH { const std::array<Position, N>& layout, const Effect effect, const Target target - ) { + ) + { std::array<std::uint8_t, N> buf{}; std::size_t copyLength = std::min(value.size(), sizeof(buf)); std::memcpy(buf.data(), value.c_str(), copyLength); @@ -102,7 +95,8 @@ namespace SenseShift::BH { FloatBody* output, const std::array<uint8_t, VEST_PAYLOAD_SIZE>& value, const std::array<OutputLayout, VEST_LAYOUT_SIZE>& layout - ) { + ) + { for (size_t i = 0; i < VEST_PAYLOAD_SIZE; i++) { const std::uint8_t byte = value[i]; const size_t actIndex = i * 2; @@ -120,11 +114,9 @@ namespace SenseShift::BH { } } - static void applyVest( - FloatBody* output, - std::string& value, - const std::array<OutputLayout, VEST_LAYOUT_SIZE>& layout - ) { + static void + applyVest(FloatBody* output, std::string& value, const std::array<OutputLayout, VEST_LAYOUT_SIZE>& layout) + { std::array<std::uint8_t, VEST_PAYLOAD_SIZE> buf{}; const size_t copyLength = std::min(value.size(), sizeof(buf)); std::memcpy(buf.data(), value.c_str(), copyLength); @@ -141,7 +133,8 @@ namespace SenseShift::BH { const std::array<std::uint8_t, VEST_PAYLOAD_SIZE>& value, const std::array<OutputLayout, VEST_LAYOUT_SIZE>& layout, const std::array<std::uint8_t, N>& layoutGroups - ) { + ) + { std::array<std::uint8_t, VEST_LAYOUT_SIZE> result{}; // Unpack values @@ -182,11 +175,8 @@ namespace SenseShift::BH { const auto target = std::get<0>(layout[i]); const auto position = std::get<1>(layout[i]); - output->effect( - target, - position, - static_cast<FloatBody::Plane::Value>(effectDataFromByte(result[i], 15)) - ); + output + ->effect(target, position, static_cast<FloatBody::Plane::Value>(effectDataFromByte(result[i], 15))); } } @@ -196,7 +186,8 @@ namespace SenseShift::BH { std::string& value, const std::array<OutputLayout, VEST_LAYOUT_SIZE>& layout, const std::array<std::uint8_t, N>& layoutGroups - ) { + ) + { std::array<std::uint8_t, VEST_PAYLOAD_SIZE> buf{}; const size_t copyLength = std::min(value.size(), sizeof(buf)); std::memcpy(buf.data(), value.c_str(), copyLength); diff --git a/lib/haptics/senseshift/body/haptics/body.cpp b/lib/haptics/senseshift/body/haptics/body.cpp index bb373d3e..eac297c1 100644 --- a/lib/haptics/senseshift/body/haptics/body.cpp +++ b/lib/haptics/senseshift/body/haptics/body.cpp @@ -1,11 +1,11 @@ #include "senseshift/body/haptics/body.hpp" #include "senseshift/body/haptics/interface.hpp" -#include <senseshift/output/output.hpp> #include <senseshift/core/logging.hpp> +#include <senseshift/output/output.hpp> namespace SenseShift::Body::Haptics { - static const char *const TAG = "haptic.body"; + static const char* const TAG = "haptic.body"; template<typename Tp, typename Ta> void OutputBody<Tp, Ta>::effect(const Target& target, const Position& pos, const typename Plane::Value& val) diff --git a/lib/haptics/senseshift/body/haptics/body.hpp b/lib/haptics/senseshift/body/haptics/body.hpp index 6586220a..d381348a 100644 --- a/lib/haptics/senseshift/body/haptics/body.hpp +++ b/lib/haptics/senseshift/body/haptics/body.hpp @@ -23,17 +23,17 @@ namespace SenseShift::Body::Haptics { OutputBody() = default; - void setup() { + void setup() + { for (auto& [target, plane] : this->targets_) { plane->setup(); } } - void addTarget(Target target, Plane* plane) { - this->targets_[target] = plane; - } + void addTarget(Target target, Plane* plane) { this->targets_[target] = plane; } - auto getTarget(Target target) -> std::optional<Plane*> { + auto getTarget(Target target) -> std::optional<Plane*> + { auto find = this->targets_.find(target); if (find == this->targets_.end()) { return std::nullopt; diff --git a/lib/haptics/senseshift/body/haptics/plane.cpp b/lib/haptics/senseshift/body/haptics/plane.cpp index 9fbe77ee..85fb184b 100644 --- a/lib/haptics/senseshift/body/haptics/plane.cpp +++ b/lib/haptics/senseshift/body/haptics/plane.cpp @@ -4,11 +4,11 @@ #include <algorithm> #include <map> -#include <senseshift/output/output.hpp> #include <senseshift/core/logging.hpp> +#include <senseshift/output/output.hpp> namespace SenseShift::Body::Haptics { - static const char *const TAG = "haptic.plane"; + static const char* const TAG = "haptic.plane"; template<typename Tc, typename To> void OutputPlane<Tc, To>::setActuators(const ActuatorMap& actuators) @@ -58,7 +58,8 @@ namespace SenseShift::Body::Haptics { } template<typename Tc, typename To> - [[nodiscard]] auto OutputPlane_Closest<Tc, To>::findClosestPoint(const PositionSet& pts, const Position& target) -> const Position& + [[nodiscard]] auto OutputPlane_Closest<Tc, To>::findClosestPoint(const PositionSet& pts, const Position& target) + -> const Position& { // check if exact point exists const auto find = pts.find(target); @@ -69,7 +70,7 @@ namespace SenseShift::Body::Haptics { // find the closest point by square distance std::multimap<float, Position> distance_map = {}; for (const auto& point : pts) { - distance_map.insert({(target - point), point }); + distance_map.insert({ (target - point), point }); } const auto nearest = std::min_element(distance_map.begin(), distance_map.end()); diff --git a/lib/haptics/senseshift/body/haptics/plane.hpp b/lib/haptics/senseshift/body/haptics/plane.hpp index a12b3d75..5971ee32 100644 --- a/lib/haptics/senseshift/body/haptics/plane.hpp +++ b/lib/haptics/senseshift/body/haptics/plane.hpp @@ -7,9 +7,9 @@ #include <set> #include <vector> +#include <senseshift/math/point2.hpp> #include <senseshift/output/output.hpp> #include <senseshift/utility.hpp> -#include <senseshift/math/point2.hpp> namespace SenseShift::Body::Haptics { /// Output "plane" (e.g. Chest, Palm, Finger, etc.). @@ -59,17 +59,18 @@ namespace SenseShift::Body::Haptics { /// \tparam To The type of the output value. template<typename Tc, typename To> class OutputPlane_Closest : public OutputPlane<Tc, To> { - public: + public: using Value = To; using PositionSet = typename OutputPlane<Tc, To>::PositionSet; - explicit OutputPlane_Closest(const typename OutputPlane<Tc, To>::ActuatorMap& actuators) : OutputPlane<Tc, To>(actuators) + explicit OutputPlane_Closest(const typename OutputPlane<Tc, To>::ActuatorMap& actuators) : + OutputPlane<Tc, To>(actuators) { } void effect(const Position&, const Value&) override; - private: + private: [[nodiscard]] static auto findClosestPoint(const PositionSet&, const Position&) -> const Position&; }; @@ -79,10 +80,10 @@ namespace SenseShift::Body::Haptics { // TODO: configurable margin class PlaneMapper_Margin { public: - /// Maps a 2D matrix into a 1D (coord, object) map. template<typename Tp> - [[nodiscard]] static constexpr auto mapMatrixCoordinates(std::vector<std::vector<Tp*>> map2d) -> std::map<Position, Tp*> + [[nodiscard]] static constexpr auto mapMatrixCoordinates(std::vector<std::vector<Tp*>> map2d) + -> std::map<Position, Tp*> { std::map<Position, Tp*> points{}; diff --git a/lib/io/senseshift/output/output.hpp b/lib/io/senseshift/output/output.hpp index 0392714f..581770d7 100644 --- a/lib/io/senseshift/output/output.hpp +++ b/lib/io/senseshift/output/output.hpp @@ -5,7 +5,7 @@ namespace SenseShift::Output { template<typename Tp> class IOutput : public IInitializable { - public: + public: using ValueType = Tp; virtual void writeState(ValueType value) = 0; diff --git a/lib/math/senseshift/math/point2.hpp b/lib/math/senseshift/math/point2.hpp index faa2f475..57d3f1e2 100644 --- a/lib/math/senseshift/math/point2.hpp +++ b/lib/math/senseshift/math/point2.hpp @@ -25,7 +25,10 @@ namespace SenseShift::Math { constexpr inline auto operator!=(const Point2<Tp>& rhs) const -> bool { return !(*this == rhs); } - constexpr auto operator<(const Point2<Tp>& rhs) const -> bool { return std::tie(x, y) < std::tie(rhs.x, rhs.y); } + constexpr auto operator<(const Point2<Tp>& rhs) const -> bool + { + return std::tie(x, y) < std::tie(rhs.x, rhs.y); + } constexpr auto operator-(const Point2<Tp>& rhs) const -> float { diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index 72b70776..0d171a91 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -16,16 +16,17 @@ class TestActuator : public IOutput<float> { void writeState(float newIntensity) override { this->intensity = newIntensity; } }; -#define ASSERT_EQUAL_FLOAT_ROUNDED(expected, actual, precision) \ - TEST_ASSERT_EQUAL_FLOAT( \ - std::round(expected * std::pow(10, precision)) / std::pow(10, precision), \ - std::round(actual * std::pow(10, precision)) / std::pow(10, precision) \ +#define ASSERT_EQUAL_FLOAT_ROUNDED(expected, actual, precision) \ + TEST_ASSERT_EQUAL_FLOAT( \ + std::round(expected* std::pow(10, precision)) / std::pow(10, precision), \ + std::round(actual * std::pow(10, precision)) / std::pow(10, precision) \ ) void test_layout_tactsuitx16(void) { static const std::array<OutputLayout, BH_LAYOUT_TACTSUITX16_SIZE> bhLayout = { BH_LAYOUT_TACTSUITX16 }; - static const std::array<std::uint8_t,BH_LAYOUT_TACTSUITX16_GROUPS_SIZE> layoutGroups = BH_LAYOUT_TACTSUITX16_GROUPS; + static const std::array<std::uint8_t, BH_LAYOUT_TACTSUITX16_GROUPS_SIZE> layoutGroups = + BH_LAYOUT_TACTSUITX16_GROUPS; auto body = new FloatBody(); @@ -69,22 +70,22 @@ void test_layout_tactsuitx16(void) Decoder::applyVestGrouped(body, values, bhLayout, layoutGroups); ASSERT_EQUAL_FLOAT_ROUNDED(0, actuator0->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(273.0F/4095.0F, actuator1->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F/4095.0F, actuator2->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3549.0F/4095.0F, actuator3->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(546.0F/4095.0F, actuator4->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(819.0F/4095.0F, actuator5->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3822.0F/4095.0F, actuator6->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(4095.0F/4095.0F, actuator7->intensity, 2); - - ASSERT_EQUAL_FLOAT_ROUNDED(1092.0F/4095.0F, actuator8->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(1365.0F/4095.0F, actuator9->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(2184.0F/4095.0F, actuator10->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(2457.0F/4095.0F, actuator11->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(1638.0F/4095.0F, actuator12->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(1911.0F/4095.0F, actuator13->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(2730.0F/4095.0F, actuator14->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3003.0F/4095.0F, actuator15->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(273.0F / 4095.0F, actuator1->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F / 4095.0F, actuator2->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3549.0F / 4095.0F, actuator3->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(546.0F / 4095.0F, actuator4->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(819.0F / 4095.0F, actuator5->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3822.0F / 4095.0F, actuator6->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(4095.0F / 4095.0F, actuator7->intensity, 2); + + ASSERT_EQUAL_FLOAT_ROUNDED(1092.0F / 4095.0F, actuator8->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1365.0F / 4095.0F, actuator9->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2184.0F / 4095.0F, actuator10->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2457.0F / 4095.0F, actuator11->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1638.0F / 4095.0F, actuator12->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1911.0F / 4095.0F, actuator13->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2730.0F / 4095.0F, actuator14->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3003.0F / 4095.0F, actuator15->intensity, 2); } void test_layout_tactsuitx40(void) @@ -127,36 +128,36 @@ void test_layout_tactsuitx40(void) bhLayout ); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[0][0])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(273.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[0][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(273.0F / 4095.0F, static_cast<TestActuator*>(frontMatrix[0][1])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[0][2])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[0][3])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(546.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[1][0])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(819.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[1][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(546.0F / 4095.0F, static_cast<TestActuator*>(frontMatrix[1][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(819.0F / 4095.0F, static_cast<TestActuator*>(frontMatrix[1][1])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[1][2])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[1][3])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(1092.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[2][0])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(1365.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[2][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1092.0F / 4095.0F, static_cast<TestActuator*>(frontMatrix[2][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1365.0F / 4095.0F, static_cast<TestActuator*>(frontMatrix[2][1])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[2][2])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[2][3])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(1638.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[3][0])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(1911.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[3][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1638.0F / 4095.0F, static_cast<TestActuator*>(frontMatrix[3][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1911.0F / 4095.0F, static_cast<TestActuator*>(frontMatrix[3][1])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[3][2])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[3][3])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(2184.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[4][0])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(2457.0F/4095.0F, static_cast<TestActuator*>(frontMatrix[4][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2184.0F / 4095.0F, static_cast<TestActuator*>(frontMatrix[4][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2457.0F / 4095.0F, static_cast<TestActuator*>(frontMatrix[4][1])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[4][2])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(frontMatrix[4][3])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(2730.0F/4095.0F, static_cast<TestActuator*>(backMatrix[0][0])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3003.0F/4095.0F, static_cast<TestActuator*>(backMatrix[0][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2730.0F / 4095.0F, static_cast<TestActuator*>(backMatrix[0][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3003.0F / 4095.0F, static_cast<TestActuator*>(backMatrix[0][1])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[0][2])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[0][3])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F/4095.0F, static_cast<TestActuator*>(backMatrix[1][0])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3549.0F/4095.0F, static_cast<TestActuator*>(backMatrix[1][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F / 4095.0F, static_cast<TestActuator*>(backMatrix[1][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3549.0F / 4095.0F, static_cast<TestActuator*>(backMatrix[1][1])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[1][2])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[1][3])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3822.0F/4095.0F, static_cast<TestActuator*>(backMatrix[2][0])->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(4095.0F/4095.0F, static_cast<TestActuator*>(backMatrix[2][1])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3822.0F / 4095.0F, static_cast<TestActuator*>(backMatrix[2][0])->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(4095.0F / 4095.0F, static_cast<TestActuator*>(backMatrix[2][1])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[2][2])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[2][3])->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, static_cast<TestActuator*>(backMatrix[3][0])->intensity, 2); @@ -199,11 +200,11 @@ void test_layout_tactal(void) Decoder::applyPlain(body, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, bhLayout, Effect::Vibro, Target::FaceFront); ASSERT_EQUAL_FLOAT_ROUNDED(0.16F, actuator0->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(1310.0F/4095.0F, actuator1->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(1965.0F/4095.0F, actuator2->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(2620.0F/4095.0F, actuator3->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F/4095.0F, actuator4->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3931.0F/4095.0F, actuator5->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1310.0F / 4095.0F, actuator1->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1965.0F / 4095.0F, actuator2->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2620.0F / 4095.0F, actuator3->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F / 4095.0F, actuator4->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3931.0F / 4095.0F, actuator5->intensity, 2); } void test_layout_tactglove(void) @@ -230,7 +231,7 @@ void test_layout_tactglove(void) ); Decoder::applyPlain(body, { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 }, bhLayout, Effect::Vibro); - ASSERT_EQUAL_FLOAT_ROUNDED(4095.0F/4095.0F, actuatorThumb->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(4095.0F / 4095.0F, actuatorThumb->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, actuatorIndex->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, actuatorMiddle->intensity, 2); ASSERT_EQUAL_FLOAT_ROUNDED(0, actuatorRing->intensity, 2); @@ -238,12 +239,12 @@ void test_layout_tactglove(void) ASSERT_EQUAL_FLOAT_ROUNDED(0, actuatorWrist->intensity, 2); Decoder::applyPlain(body, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, bhLayout, Effect::Vibro); - ASSERT_EQUAL_FLOAT_ROUNDED(655.0F/4095.0F, actuatorThumb->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(1310.0F/4095.0F, actuatorIndex->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(1965.0F/4095.0F, actuatorMiddle->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(2620.0F/4095.0F, actuatorRing->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F/4095.0F, actuatorLittle->intensity, 2); - ASSERT_EQUAL_FLOAT_ROUNDED(3931.0F/4095.0F, actuatorWrist->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(655.0F / 4095.0F, actuatorThumb->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1310.0F / 4095.0F, actuatorIndex->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(1965.0F / 4095.0F, actuatorMiddle->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(2620.0F / 4095.0F, actuatorRing->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3276.0F / 4095.0F, actuatorLittle->intensity, 2); + ASSERT_EQUAL_FLOAT_ROUNDED(3931.0F / 4095.0F, actuatorWrist->intensity, 2); } int process(void) diff --git a/test/test_core_helpers/main.cpp b/test/test_core_helpers/main.cpp index d13815bd..5dbfd888 100644 --- a/test/test_core_helpers/main.cpp +++ b/test/test_core_helpers/main.cpp @@ -1,8 +1,8 @@ #include <senseshift/core/helpers.hpp> #include <unity.h> -#include <map> #include <cstdint> +#include <map> using namespace SenseShift; From c2d34c6c05c9a7fb1b51619370b83fb7daa8e405 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 18 Feb 2024 18:20:23 +0400 Subject: [PATCH 72/82] ci(Wokwi): execute calibration --- .wokwi/lucidgloves-prototype4+serial/test.yaml | 15 +++++++++++++++ .../senseshift/opengloves/autoconfig.hpp | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/.wokwi/lucidgloves-prototype4+serial/test.yaml b/.wokwi/lucidgloves-prototype4+serial/test.yaml index cfd56eb9..d3a1f656 100644 --- a/.wokwi/lucidgloves-prototype4+serial/test.yaml +++ b/.wokwi/lucidgloves-prototype4+serial/test.yaml @@ -3,6 +3,21 @@ version: 1 author: Leonid Meleshin steps: + - delay: 2000ms + + # Press calibration button + - set-control: + part-id: btn3 + control: pressed + value: 1 + + - delay: 250ms + + - set-control: + part-id: btn3 + control: pressed + value: 0 + - wait-serial: "A0B0C0D0E0F2047G2047" # Press the 'A' button diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index a2e452b0..dd97a556 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -174,6 +174,10 @@ #define FFB_ENABLED \ (FFB_THUMB_ENABLED || FFB_INDEX_ENABLED || FFB_MIDDLE_ENABLED || FFB_RING_ENABLED || FFB_PINKY_ENABLED) +#ifndef CALIBRATION_ALWAYS_CALIBRATE +#define CALIBRATION_ALWAYS_CALIBRATE false +#endif + #ifndef UPDATE_RATE #define UPDATE_RATE 90 #endif From 6c1bcc2457de7a591037087178240a84fb89e9b1 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Sun, 18 Feb 2024 21:42:06 +0400 Subject: [PATCH 73/82] feat(deps): remove Frozen lib from submodules --- .gitmodules | 3 --- lib/frozen | 1 - platformio.ini | 1 + 3 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 .gitmodules delete mode 160000 lib/frozen diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index fb9d97bc..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "lib/frozen"] - path = lib/frozen - url = https://github.com/senseshift/frozen.git diff --git a/lib/frozen b/lib/frozen deleted file mode 160000 index 3a4f00cb..00000000 --- a/lib/frozen +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3a4f00cb83d580880b8a79864a479e1a14eb8c74 diff --git a/platformio.ini b/platformio.ini index 4815cf7a..ce93b43b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -37,6 +37,7 @@ build_src_filter = -<mode_configs> lib_deps = + https://github.com/senseshift/frozen.git#feature/platformio [env] build_flags = ${common.build_flags} From 2f0b2164da0c01e8920e3b4b982e5c31fdceb93c Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 19 Feb 2024 15:59:20 +0400 Subject: [PATCH 74/82] refactor(OpenGloves): separate autoconfig for tracking/ffb --- .../mode_configs/opengloves/opengloves.cpp | 195 +----------------- lib/freertos/senseshift/freertos/task.hpp | 5 + .../senseshift/opengloves/autoconfig.hpp | 185 ++++++++++++++++- 3 files changed, 198 insertions(+), 187 deletions(-) diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 0720afe7..382ad083 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -1,172 +1,21 @@ -#include "senseshift/body/hands/input/gesture.hpp" -#include "senseshift/body/hands/input/total_curl.hpp" -#include <senseshift/arduino/input/sensor/analog.hpp> -#include <senseshift/arduino/input/sensor/digital.hpp> -#include <senseshift/arduino/output/servo.hpp> -#include <senseshift/body/hands/input/gesture.hpp> -#include <senseshift/input/calibration.hpp> -#include <senseshift/input/filter.hpp> -#include <senseshift/input/sensor.hpp> +#include <senseshift/freertos/task.hpp> #include <senseshift/opengloves/autoconfig.hpp> -#include <senseshift/opengloves/opengloves.hpp> #include <senseshift/opengloves/opengloves_task.hpp> -#include <senseshift/utility.hpp> -using namespace ::SenseShift::Input; -using namespace ::SenseShift::Arduino::Input; -using namespace ::SenseShift::Arduino::Output; -using namespace ::SenseShift::Body::Hands::Input; -using namespace ::SenseShift::OpenGloves; - -InputSensors input_sensors; - -#ifdef FFB_ENABLED -OutputWriters output_writers; -#endif +using namespace SenseShift::OpenGloves; void setupMode() { -#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 - ); -#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; -#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 - ); -#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; -#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 - ); -#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; -#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 - ); -#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; -#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 - ); -#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; -#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); - - 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, 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; -#endif - -#if GESTURE_TRIGGER_ENABLED - auto* trigger = new 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 - auto* grab = new GrabGesture( - 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, BUTTON_GRAB_INVERT); -#endif + auto* communication = AutoConfig::createTransport(); + auto* encoding = new og::AlphaEncoder(); -#if GESTURE_PINCH_ENABLED - auto* pinch = new PinchGesture( - 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, BUTTON_PINCH_INVERT); -#endif + auto input_sensors = AutoConfig::createInput(); - auto* communication = AutoConfig::setupTransport(); - auto* encoding = new og::AlphaEncoder(); OpenGlovesTrackingComponent::Config tracking_config(CALIBRATION_DURATION, CALIBRATION_ALWAYS_CALIBRATE); - auto* opengloves_tracking = - new OpenGlovesTrackingComponent(tracking_config, input_sensors, communication, encoding); + auto* og_tracking = new OpenGlovesTrackingComponent(tracking_config, input_sensors, communication, encoding); - auto* opengloves_tracking_task = new ::SenseShift::FreeRTOS::ComponentUpdateTask<OpenGlovesTrackingComponent>( - opengloves_tracking, + auto* og_tracking_task = new SenseShift::FreeRTOS::ComponentUpdateTask<OpenGlovesTrackingComponent>( + og_tracking, 1000 / UPDATE_RATE, { .name = "OG_TRACKING", @@ -174,34 +23,10 @@ void setupMode() .priority = 1, } ); - opengloves_tracking_task->begin(); + og_tracking_task->begin(); #if FFB_ENABLED - -#if FFB_THUMB_ENABLED - auto* thumb_ffb_output = new ServoOutput(PIN_FFB_THUMB); - output_writers.ffb.thumb = thumb_ffb_output; -#endif - -#if FFB_INDEX_ENABLED - auto* index_ffb_output = new ServoOutput(PIN_FFB_INDEX); - output_writers.ffb.index = index_ffb_output; -#endif - -#if FFB_MIDDLE_ENABLED - auto* middle_ffb_output = new ServoOutput(PIN_FFB_MIDDLE); - output_writers.ffb.middle = middle_ffb_output; -#endif - -#if FFB_RING_ENABLED - auto* ring_ffb_output = new ServoOutput(PIN_FFB_RING); - output_writers.ffb.ring = ring_ffb_output; -#endif - -#if FFB_PINKY_ENABLED - auto* pinky_ffb_output = new ServoOutput(PIN_FFB_PINKY); - output_writers.ffb.pinky = pinky_ffb_output; -#endif + auto output_writers = AutoConfig::createFfbOutputs(); auto* og_ffb = new OpenGlovesForceFeedbackComponent(output_writers, communication, encoding); diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index 38ea81a0..ee4f3028 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -1,10 +1,15 @@ #pragma once +#include <cstdint> +#include <type_traits> + +#include <senseshift/core/component.hpp> #include <senseshift/core/logging.hpp> extern "C" void delay(uint32_t ms); #if defined(ESP32) +#include <Arduino.h> #include <freertos/FreeRTOS.h> // Include the base FreeRTOS definitions. #include <freertos/task.h> // Include the task definitions. diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index dd97a556..de6eeaf2 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -1,5 +1,13 @@ #pragma once +#include <senseshift/arduino/input/sensor/analog.hpp> +#include <senseshift/arduino/input/sensor/digital.hpp> +#include <senseshift/arduino/output/servo.hpp> +#include <senseshift/body/hands/input/gesture.hpp> +#include <senseshift/body/hands/input/total_curl.hpp> +#include <senseshift/input/calibration.hpp> +#include <senseshift/input/filter.hpp> +#include <senseshift/input/sensor.hpp> #include <senseshift/opengloves/constants.hpp> #include <senseshift/opengloves/opengloves.hpp> @@ -145,7 +153,8 @@ #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)) -#define BUTTON_CLASS(PIN, INVERT) SimpleSensorDecorator(new DigitalSimpleSensor<INVERT>(PIN)); +#define BUTTON_CLASS(PIN, INVERT) \ + ::SenseShift::Input::SimpleSensorDecorator(new ::SenseShift::Arduino::Input::DigitalSimpleSensor<INVERT>(PIN)); #pragma endregion @@ -184,10 +193,182 @@ namespace SenseShift::OpenGloves::AutoConfig { + [[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 + ); +#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; +#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 + ); +#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; +#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 + ); +#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; +#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 + ); +#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; +#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 + ); +#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; +#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); + + 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, 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; +#endif + +#if GESTURE_TRIGGER_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 + 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, BUTTON_GRAB_INVERT); +#endif + +#if GESTURE_PINCH_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; +#elif BUTTON_PINCH_ENABLED + auto* pinch = new BUTTON_CLASS(PIN_BUTTON_PINCH, BUTTON_PINCH_INVERT); +#endif + + return input_sensors; + } + + [[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; +#endif + +#if FFB_INDEX_ENABLED + 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; +#endif + +#if FFB_RING_ENABLED + 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; +#endif + + return output_writers; + } + /** * Setup the transport for the OpenGloves interface. */ - [[nodiscard]] auto setupTransport() -> ITransport* + [[nodiscard]] auto createTransport() -> ITransport* { #if OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_SERIAL // Serial auto* pSerial = &SERIAL_PORT; From 0628ff691aeec648fe58b7940a4a4b581460ef4f Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 19 Feb 2024 16:36:45 +0400 Subject: [PATCH 75/82] style: format INI files --- ini/bhaptics.ini | 415 ++++++++++++++++++--------------- ini/opengloves-indexer.ini | 306 ++++++++++++------------ ini/opengloves-lucidgloves.ini | 203 ++++++++-------- ini/opengloves.ini | 116 ++++----- platformio.ini | 71 +++--- 5 files changed, 581 insertions(+), 530 deletions(-) diff --git a/ini/bhaptics.ini b/ini/bhaptics.ini index f3289e11..0d3c4343 100644 --- a/ini/bhaptics.ini +++ b/ini/bhaptics.ini @@ -1,71 +1,78 @@ [bhaptics] -platform = platformio/espressif32@^6.1.0 +platform = platformio/espressif32@^6.1.0 platform_packages = - platformio/framework-arduinoespressif32@^3.20014.231204 -framework = arduino -board = esp32doit-devkit-v1 -upload_speed = 921600 -monitor_speed = 115200 + platformio/framework-arduinoespressif32@^3.20014.231204 +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_flags = + ${common.build_flags} + -D BHAPTICS +build_unflags = ${common.build_unflags} build_src_filter = ${common.build_src_filter} -lib_deps = ${common.lib_deps} +lib_deps = ${common.lib_deps} [env:bhaptics_tactsuit_x16] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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} - +<mode_configs/bhaptics/tactsuit_x16.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactsuit_x16.cpp> +lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactsuit_x16_pca9685] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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} - +<mode_configs/bhaptics/tactsuit_x16_pca9685.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactsuit_x16_pca9685.cpp> +lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactsuit_x40] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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} - +<mode_configs/bhaptics/tactsuit_x40.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactsuit_x40.cpp> +lib_deps = ${bhaptics.lib_deps} ; [env:bhaptics_tactbelt] ; platform = ${bhaptics.platform} @@ -86,183 +93,203 @@ lib_deps = ${bhaptics.lib_deps} ; lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactosy2_forearm_left] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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} - +<mode_configs/bhaptics/tactosy2.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosy2.cpp> +lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactosy2_forearm_right] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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} - +<mode_configs/bhaptics/tactosy2.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosy2.cpp> +lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactosyh_hand_left] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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} - +<mode_configs/bhaptics/tactosyh.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosyh.cpp> +lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactosyh_hand_right] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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} - +<mode_configs/bhaptics/tactosyh.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosyh.cpp> +lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactosyf_foot_left] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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} - +<mode_configs/bhaptics/tactosyf.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosyf.cpp> +lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactosyf_foot_right] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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} - +<mode_configs/bhaptics/tactosyf.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactosyf.cpp> +lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactal] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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} - +<mode_configs/bhaptics/tactal.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactal.cpp> +lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactvisor] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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} - +<mode_configs/bhaptics/tactvisor.cpp> -lib_deps = ${bhaptics.lib_deps} +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} + +<mode_configs/bhaptics/tactvisor.cpp> +lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactglove_left] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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 SENSESHIFT_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} - +<mode_configs/bhaptics/tactglove.cpp> -lib_deps = ${bhaptics.lib_deps} +build_flags = + ${bhaptics.build_flags} + -D BH_DEVICE_TACTGLOVE + -D SENSESHIFT_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} + +<mode_configs/bhaptics/tactglove.cpp> +lib_deps = ${bhaptics.lib_deps} [env:bhaptics_tactglove_right] -platform = ${bhaptics.platform} +platform = ${bhaptics.platform} platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} +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 SENSESHIFT_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} - +<mode_configs/bhaptics/tactglove.cpp> -lib_deps = ${bhaptics.lib_deps} +build_flags = + ${bhaptics.build_flags} + -D BH_DEVICE_TACTGLOVE + -D SENSESHIFT_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} + +<mode_configs/bhaptics/tactglove.cpp> +lib_deps = ${bhaptics.lib_deps} diff --git a/ini/opengloves-indexer.ini b/ini/opengloves-indexer.ini index e9e8f5a8..08048903 100644 --- a/ini/opengloves-indexer.ini +++ b/ini/opengloves-indexer.ini @@ -3,173 +3,183 @@ ; Wiring Diagram: https://github.com/Valsvirtuals/Indexer/wiki/wiring-and-pinout ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; [env:indexer-c] -platform = ${opengloves.platform} +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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + +<mode_configs/opengloves/opengloves.cpp> +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 = ${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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + +<mode_configs/opengloves/opengloves.cpp> +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 = ${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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + +<mode_configs/opengloves/opengloves.cpp> +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 = ${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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + +<mode_configs/opengloves/opengloves.cpp> +lib_deps = ${opengloves.lib_deps} diff --git a/ini/opengloves-lucidgloves.ini b/ini/opengloves-lucidgloves.ini index 1c50b00a..b777cee8 100644 --- a/ini/opengloves-lucidgloves.ini +++ b/ini/opengloves-lucidgloves.ini @@ -3,115 +3,124 @@ ; Wiring Diagram: https://github.com/LucidVR/lucidgloves/wiki/Prototype-3-Wiring-Diagram ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; [env:lucidgloves-prototype3] -platform = ${opengloves.platform} +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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + +<mode_configs/opengloves/opengloves.cpp> +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 = ${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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + +<mode_configs/opengloves/opengloves.cpp> +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 = ${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} - ; 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} - +<mode_configs/opengloves/opengloves.cpp> -lib_deps = ${opengloves.lib_deps} +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} + +<mode_configs/opengloves/opengloves.cpp> +lib_deps = ${opengloves.lib_deps} diff --git a/ini/opengloves.ini b/ini/opengloves.ini index 12819792..ab5c8333 100644 --- a/ini/opengloves.ini +++ b/ini/opengloves.ini @@ -1,60 +1,62 @@ [opengloves] -platform = platformio/espressif32@^6.1.0 +platform = platformio/espressif32@^6.1.0 platform_packages = - platformio/framework-arduinoespressif32@^3.20014.231204 -framework = arduino -board = esp32doit-devkit-v1 -upload_speed = 921600 -monitor_speed = 115200 - -build_flags = ${common.build_flags} - -D OPENGLOVES - - ; Communication - ; -D OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL, OPENGLOVES_COMM_BLESERIAL - ; Serial - -D SERIAL_BAUDRATE=115200 - -D SERIAL_PORT=Serial ; Serial, Serial1, Serial2, Serial3 - ; BTSerial - '-D BTSERIAL_PREFIX="SenseShift_OG"' - ; '-D BTSERIAL_NAME="SenseShift_OG_Left"' - - ; Sensors - -D FINGER_THUMB_INVERT=false - -D FINGER_INDEX_INVERT=false - -D FINGER_MIDDLE_INVERT=false - -D FINGER_RING_INVERT=false - -D FINGER_PINKY_INVERT=false - - -D FINGER_THUMB_SPLAY_INVERT=false - -D FINGER_INDEX_SPLAY_INVERT=false - -D FINGER_MIDDLE_SPLAY_INVERT=false - -D FINGER_RING_SPLAY_INVERT=false - -D FINGER_PINKY_SPLAY_INVERT=false - - -D JOYSTICK_X_INVERT=false - -D JOYSTICK_Y_INVERT=false - -D JOYSTICK_DEADZONE=0.1 - -D BUTTON_JOYSTICK_INVERT=false - - -D BUTTON_A_INVERT=false - -D BUTTON_B_INVERT=false - -D BUTTON_MENU_INVERT=false - -D BUTTON_CALIBRATE_INVERT=false - -D BUTTON_TRIGGER_INVERT=false - -D BUTTON_GRAB_INVERT=false - -D BUTTON_PINCH_INVERT=false - - -D GESTURE_TRIGGER_ENABLED=true - -D GESTURE_GRAB_ENABLED=true - -D GESTURE_PINCH_ENABLED=true - - ; Calibration - -D CALIBRATION_ALWAYS_CALIBRATE=false - -D CALIBRATION_DURATION=2000 ; in ms - - -D UPDATE_RATE=90 ; sensors update rate in Hz - -build_unflags = ${common.build_unflags} + platformio/framework-arduinoespressif32@^3.20014.231204 +framework = arduino +board = esp32doit-devkit-v1 +upload_speed = 921600 +monitor_speed = 115200 + +build_flags = + ${common.build_flags} + -D OPENGLOVES + + ;;;; 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 + -D SERIAL_PORT=Serial + ;;;; BTSerial + '-D BTSERIAL_PREFIX="SenseShift_OG"' + ; '-D BTSERIAL_NAME="SenseShift_OG_Left"' + + ; Sensors + -D FINGER_THUMB_INVERT=false + -D FINGER_INDEX_INVERT=false + -D FINGER_MIDDLE_INVERT=false + -D FINGER_RING_INVERT=false + -D FINGER_PINKY_INVERT=false + + -D FINGER_THUMB_SPLAY_INVERT=false + -D FINGER_INDEX_SPLAY_INVERT=false + -D FINGER_MIDDLE_SPLAY_INVERT=false + -D FINGER_RING_SPLAY_INVERT=false + -D FINGER_PINKY_SPLAY_INVERT=false + + -D JOYSTICK_X_INVERT=false + -D JOYSTICK_Y_INVERT=false + -D JOYSTICK_DEADZONE=0.1 + -D BUTTON_JOYSTICK_INVERT=false + + -D BUTTON_A_INVERT=false + -D BUTTON_B_INVERT=false + -D BUTTON_MENU_INVERT=false + -D BUTTON_CALIBRATE_INVERT=false + -D BUTTON_TRIGGER_INVERT=false + -D BUTTON_GRAB_INVERT=false + -D BUTTON_PINCH_INVERT=false + + -D GESTURE_TRIGGER_ENABLED=true + -D GESTURE_GRAB_ENABLED=true + -D GESTURE_PINCH_ENABLED=true + + ;;;; Calibration + -D CALIBRATION_ALWAYS_CALIBRATE=false + -D CALIBRATION_DURATION=2000 ; in ms + + -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 = ${common.lib_deps} diff --git a/platformio.ini b/platformio.ini index ea55d804..71400ed6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,58 +9,61 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] -description = Open Source Haptic-feedback device firmware -lib_dir = ./lib -src_dir = ./firmware +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 + 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 [common] build_unflags = - -std=gnu++11 -build_flags = - -std=gnu++17 - -D __OH_FIRMWARE__ - -D CORE_DEBUG_LEVEL=3 -; -D DEBUG_MODE=0 -; -D DEBUG_ESP_PORT=Serial -; -D SENSESHIFT_SERIAL_PLOTTER=true -; -D SENSESHIFT_BATTERY_ENABLED=true -; -D SENSESHIFT_BLE_USE_NIMBLE=true + -std=gnu++11 +build_flags = + -std=gnu++17 + -D __OH_FIRMWARE__ + -D CORE_DEBUG_LEVEL=3 +; -D DEBUG_MODE=0 +; -D DEBUG_ESP_PORT=Serial +; -D SENSESHIFT_SERIAL_PLOTTER=true +; -D SENSESHIFT_BATTERY_ENABLED=true +; -D SENSESHIFT_BLE_USE_NIMBLE=true build_src_filter = - +<*> - -<mode_configs> + +<*> + -<mode_configs> lib_deps = [env] -build_flags = ${common.build_flags} -build_unflags = ${common.build_unflags} +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+ +lib_deps = ${common.lib_deps} +lib_ldf_mode = deep+ -check_tool = clangtidy +check_tool = clangtidy check_flags = - clangtidy: --config-file=./.clang-tidy --fix + clangtidy: --config-file=./.clang-tidy --fix debug_build_flags = -Os [env:native] platform = native -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} - -lgcov - --coverage -build_src_filter = ${common.build_src_filter} - +<mode_configs/test.cpp> -lib_deps = ${common.lib_deps} - fabiobatsilva/ArduinoFake@^0.4 +build_unflags = ${common.build_unflags} +build_flags = + ${common.build_flags} + -lgcov + --coverage +build_src_filter = + ${common.build_src_filter} + +<mode_configs/test.cpp> +lib_deps = + ${common.lib_deps} + fabiobatsilva/ArduinoFake@^0.4 test_ignore = test_embedded From 1d42b34a407293904fe7426d79bde7e4a3ee9d99 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 19 Feb 2024 19:43:14 +0400 Subject: [PATCH 76/82] fix(OpenGloves): manually initialize sensor pointers --- lib/opengloves/opengloves/opengloves.hpp | 40 ++++ test/test_opengloves_alpha_encoding/main.cpp | 238 ++++++++----------- 2 files changed, 142 insertions(+), 136 deletions(-) diff --git a/lib/opengloves/opengloves/opengloves.hpp b/lib/opengloves/opengloves/opengloves.hpp index 2d9fd3b4..e6d708c7 100644 --- a/lib/opengloves/opengloves/opengloves.hpp +++ b/lib/opengloves/opengloves/opengloves.hpp @@ -3,8 +3,10 @@ #include <array> #include <cstddef> #include <cstdint> +#include <initializer_list> #include <map> #include <string> +#include <type_traits> #include <variant> #include <vector> @@ -108,6 +110,44 @@ namespace og { /// I know, it is not the prettiest one, but we need this type of punning to efficiently encode/decode the data template<typename Tf = float, typename Tb = bool> struct InputPeripheral { + template< + typename U = Tf, + typename V = Tb, + std::enable_if_t<std::is_floating_point_v<U> && std::is_same_v<V, bool>, 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<U> && std::is_pointer_v<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<InputFingerCurl<Tf>> curl; InputFinger<Tf> splay; diff --git a/test/test_opengloves_alpha_encoding/main.cpp b/test/test_opengloves_alpha_encoding/main.cpp index 9467b45c..7fd164d0 100644 --- a/test/test_opengloves_alpha_encoding/main.cpp +++ b/test/test_opengloves_alpha_encoding/main.cpp @@ -7,169 +7,135 @@ 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<std::tuple<InputPeripheralData, std::string>> cases = { { - InputPeripheralData{}, + defaultEmpty, "A0B0C0D0E0\n", }, { - InputPeripheralData({ - .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, - }, - }, - }), - "A2047B2047C2047D2047E2047\n", + halfCurl, + "A2047B2047C2047D2047E2047\n", }, { - InputPeripheralData({ - .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, - }, - }, - }), - "A0B0C0D0E0\n", + zeroCurl, + "A0B0C0D0E0\n", }, { - InputPeripheralData({ - .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, - }, - }, - }), - "A4095B4095C4095D4095E4095\n", + fullCurl, + "A4095B4095C4095D4095E4095\n", }, { - InputPeripheralData({ - .splay = { - .thumb = 0.5, - .index = 0.5, - .middle = 0.5, - .ring = 0.5, - .pinky = 0.5, - }, - }), - "A0(AB)2047B0(BB)2047C0(CB)2047D0(DB)2047E0(EB)2047\n", + halfSplay, + "A0(AB)2047B0(BB)2047C0(CB)2047D0(DB)2047E0(EB)2047\n", }, { - InputPeripheralData({ - .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 }, - }, - }, - }), + 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", }, { - InputPeripheralData({ - .joystick = { - .x = 0.5, - .y = 0.5, - .press = true, - }, - }), - "A0B0C0D0E0F2047G2047H\n" + joystick, + "A0B0C0D0E0F2047G2047H\n", }, { - InputPeripheralData{ - .button_a = { .press = true }, - .button_calibrate = { .press = true }, - }, - "A0B0C0D0E0JO\n" + buttons, + "A0B0C0D0E0JO\n", }, { - InputPeripheralData{ - .pinch = { true }, - .grab = { true }, - }, - "A0B0C0D0E0ML\n" + gesture, + "A0B0C0D0E0ML\n", }, { - InputPeripheralData({ - .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, - }, - }, - .splay = { - .thumb = 0.5, - .index = 0.5, - .middle = 0.5, - .ring = 0.5, - .pinky = 0.5, - }, - }), + halfCurlSplay, "A2047(AB)2047B2047(BB)2047C2047(CB)2047D2047(DB)2047E2047(EB)2047\n", } }; - for (const auto& [data, expected] : cases) { + 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(expected.c_str(), encoded.c_str()); + TEST_ASSERT_EQUAL_STRING_MESSAGE( + expected.c_str(), + encoded.c_str(), + ("Failed case " + std::to_string(i)).c_str() + ); } } From dc59f8721b0133b081d39d3fda5234049c5a44c3 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 19 Feb 2024 21:18:49 +0400 Subject: [PATCH 77/82] feat(Arduino): bring back INA219 Current Sensor --- .../arduino/input/sensor/ina219.hpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 lib/arduino/senseshift/arduino/input/sensor/ina219.hpp diff --git a/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp b/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp new file mode 100644 index 00000000..a2f4e6eb --- /dev/null +++ b/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include <cstdint> + +#include <senseshift/input/sensor.hpp> + +#include <Adafruit_INA219.h> + +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 \ No newline at end of file From 78431bbc41bd9959c83f9ee93719ecd12b03c3b7 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Mon, 19 Feb 2024 21:19:08 +0400 Subject: [PATCH 78/82] chore: remove references of output serial plotter --- .github/scripts/get_firmware_name.sh | 5 - .github/workflows/ci.yml | 10 +- .github/workflows/codeql-analysis.yml | 165 +++++++++++++------------- platformio.ini | 1 - 4 files changed, 83 insertions(+), 98 deletions(-) diff --git a/.github/scripts/get_firmware_name.sh b/.github/scripts/get_firmware_name.sh index 36b1bfb9..120fafe3 100755 --- a/.github/scripts/get_firmware_name.sh +++ b/.github/scripts/get_firmware_name.sh @@ -18,11 +18,6 @@ getBhapticsName() { target="$target+battery" fi - if [[ $flags =~ SENSESHIFT_SERIAL_PLOTTER=true ]]; then - echo "::debug::Serial Plotter is enabled, appending +serialplotter to the target" - target="$target+serialplotter" - fi - echo "firmware=$target" if [[ -n "$GITHUB_ACTIONS" ]]; then echo "firmware=$target" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a12df0c..85d5c815 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ on: jobs: build-bhaptics: - name: Build ${{ matrix.target }} ${{ matrix.coverage && 'with coverage' || 'without coverage' }}, -D ${{ matrix.battery_flag }} -D ${{ matrix.serial_plotter_flag }} -D ${{ matrix.nimble_flag }} + name: Build ${{ matrix.target }} ${{ matrix.coverage && 'with coverage' || 'without coverage' }}, -D ${{ matrix.battery_flag }} -D ${{ matrix.nimble_flag }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -33,7 +33,6 @@ jobs: - bhaptics_tactvisor - bhaptics_tactglove_right battery_flag: [ SENSESHIFT_BATTERY_ENABLED=true ] - serial_plotter_flag: [ SENSESHIFT_SERIAL_PLOTTER=false ] nimble_flag: [ SENSESHIFT_BLE_USE_NIMBLE=false ] coverage: [ false ] @@ -43,19 +42,16 @@ jobs: os: ubuntu-latest coverage: true battery_flag: SENSESHIFT_BATTERY_ENABLED=true - serial_plotter_flag: SENSESHIFT_SERIAL_PLOTTER=true nimble_flag: SENSESHIFT_BLE_USE_NIMBLE=true # - target: bhaptics_tactsuit_x40 # os: ubuntu-latest # coverage: true # battery_flag: SENSESHIFT_BATTERY_ENABLED=true - # serial_plotter_flag: SENSESHIFT_SERIAL_PLOTTER=true # nimble_flag: SENSESHIFT_BLE_USE_NIMBLE=false - target: bhaptics_tactsuit_x40 os: ubuntu-latest coverage: false battery_flag: SENSESHIFT_BATTERY_ENABLED=true - serial_plotter_flag: SENSESHIFT_SERIAL_PLOTTER=false nimble_flag: SENSESHIFT_BLE_USE_NIMBLE=true steps: @@ -66,7 +62,7 @@ jobs: - name: Get firmware name id: firmware_name run: | - ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} ${{ matrix.serial_plotter_flag }} ${{ matrix.battery_flag }} ${{ matrix.nimble_flag }} + ./.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 @@ -81,13 +77,11 @@ jobs: 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.serial_plotter_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.serial_plotter_flag }}/' platformio.ini sed -i '' '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.nimble_flag }}/' platformio.ini - name: Speedup package installation diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index ed8f6731..8cfbff2c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,89 +32,86 @@ jobs: # Enabling all flags to test build for every feature battery_flag: - SENSESHIFT_BATTERY_ENABLED=true - serial_plotter_flag: - - SENSESHIFT_SERIAL_PLOTTER=true steps: - - name: Checkout repository - uses: actions/checkout@v3 - 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@v2 - 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@v3 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - name: Cache PlatformIO - uses: actions/cache@v3 - with: - path: ~/.platformio - key: ${{ runner.os }}-pio-${{ hashFiles('**/lockfiles') }} - restore-keys: | - ${{ runner.os }}-pio- - - name: Set up Python - uses: actions/setup-python@v4 - 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 - sed -i '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.serial_plotter_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: Build - run: | - pio run --environment bhaptics_tactsuit_x40 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{matrix.language}}" + - name: Checkout repository + uses: actions/checkout@v3 + 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@v2 + 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@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Cache PlatformIO + uses: actions/cache@v3 + with: + path: ~/.platformio + key: ${{ runner.os }}-pio-${{ hashFiles('**/lockfiles') }} + restore-keys: | + ${{ runner.os }}-pio- + - name: Set up Python + uses: actions/setup-python@v4 + 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: Build + run: | + pio run --environment bhaptics_tactsuit_x40 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/platformio.ini b/platformio.ini index 7262c036..e6d2c7c4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,7 +28,6 @@ build_flags = -D CORE_DEBUG_LEVEL=3 ; -D DEBUG_MODE=0 ; -D DEBUG_ESP_PORT=Serial -; -D SENSESHIFT_SERIAL_PLOTTER=true ; -D SENSESHIFT_BATTERY_ENABLED=true ; -D SENSESHIFT_BLE_USE_NIMBLE=true From bf53c10b7ae08ead2d4d6578108e977eb26b33cc Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 22 Feb 2024 17:21:59 +0400 Subject: [PATCH 79/82] perf(OpenGloves): remove unoptimized float casting (#96) * perf(OpenGloves): remove unoptimized float casting * style: lint-fix --- examples/float_benchmark/float_benchmark.ino | 129 +++++++++++++++++++ lib/opengloves/opengloves/opengloves.cpp | 32 +---- 2 files changed, 130 insertions(+), 31 deletions(-) create mode 100644 examples/float_benchmark/float_benchmark.ino diff --git a/examples/float_benchmark/float_benchmark.ino b/examples/float_benchmark/float_benchmark.ino new file mode 100644 index 00000000..99a7da2e --- /dev/null +++ b/examples/float_benchmark/float_benchmark.ino @@ -0,0 +1,129 @@ +#include <Arduino.h> + +#ifdef ESP32 +#include <WiFi.h> +#else +#include <ESP8266WiFi.h> +#endif + +#include <inttypes.h> + +#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<int>(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<int>(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: +} diff --git a/lib/opengloves/opengloves/opengloves.cpp b/lib/opengloves/opengloves/opengloves.cpp index 8f3f0c45..010c0204 100644 --- a/lib/opengloves/opengloves/opengloves.cpp +++ b/lib/opengloves/opengloves/opengloves.cpp @@ -9,40 +9,10 @@ namespace og { -#ifdef OG_ENCODE_FASTER - inline auto ifloor(float d) -> int - { - union Cast { - double d; - long l; - }; - volatile Cast c; - c.d = d + 6755399441055743.5; - return c.l; - } -#elifdef OG_ENCODE_FAST - /// Source: https://stackoverflow.com/questions/429632/429812#429812 - inline int float2int(double d) - { - union Cast { - double d; - long l; - }; - volatile Cast c; - c.d = d + 6755399441055744; - return c.l; - } - inline auto ifloor(float x) -> int { - return float2int(x) - (x < float2int(x)); + return static_cast<int>(x); } -#else - inline auto ifloor(float x) -> int - { - return static_cast<int>(std::floor(x)); - } -#endif auto AlphaEncoder::encode_input(const InputData& input, char* buffer, size_t length) const -> size_t { From 47ba284bff723b43daf9badbf3568be4ad340739 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 22 Feb 2024 20:09:29 +0400 Subject: [PATCH 80/82] chore(IDE): stage CLion workspace config (#97) --- .gitignore | 1 - .idea/.gitignore | 8 ++ .idea/codeStyles/Project.xml | 122 +++++++++++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/editor.xml | 102 ++++++++++++++++ .idea/inspectionProfiles/Project_Default.xml | 6 + .idea/misc.xml | 17 +++ .idea/senseshift-firmware.iml | 2 + .idea/vcs.xml | 6 + 9 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/editor.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/senseshift-firmware.iml create mode 100644 .idea/vcs.xml diff --git a/.gitignore b/.gitignore index ef82776d..320eb8b6 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ *.bak *.code-workspace -.idea cmake-build-debug # PlatformIO files/dirs diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..13566b81 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..9afdb1ca --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,122 @@ +<component name="ProjectCodeStyleConfiguration"> + <code_scheme name="Project" version="173"> + <option name="OTHER_INDENT_OPTIONS"> + <value /> + </option> + <RiderCodeStyleSettings> + <option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" /> + </RiderCodeStyleSettings> + <clangFormatSettings> + <option name="ENABLED" value="true" /> + </clangFormatSettings> + <files> + <extensions> + <pair source="cpp" header="hpp" fileNamingConvention="NONE" /> + <pair source="c" header="h" fileNamingConvention="NONE" /> + <pair source="cu" header="cuh" fileNamingConvention="NONE" /> + <pair source="ixx" header="" fileNamingConvention="NONE" /> + <pair source="mxx" header="" fileNamingConvention="NONE" /> + <pair source="cppm" header="" fileNamingConvention="NONE" /> + <pair source="ccm" header="" fileNamingConvention="NONE" /> + <pair source="cxxm" header="" fileNamingConvention="NONE" /> + <pair source="c++m" header="" fileNamingConvention="NONE" /> + </extensions> + </files> + </code_scheme> +</component> \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..79ee123c --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ +<component name="ProjectCodeStyleConfiguration"> + <state> + <option name="USE_PER_PROJECT_SETTINGS" value="true" /> + </state> +</component> \ No newline at end of file diff --git a/.idea/editor.xml b/.idea/editor.xml new file mode 100644 index 00000000..66c86790 --- /dev/null +++ b/.idea/editor.xml @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="BackendCodeEditorSettings"> + <option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" /> + <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" /> + </component> +</project> \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..146e386f --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="Project Default" /> + <inspection_tool class="IncorrectFormatting" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> + </profile> +</component> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..d858eb18 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ExternalStorageConfigurationManager" enabled="true" /> + <component name="PlatformIOSettings"> + <option name="linkedExternalProjectsSettings"> + <PlatformioProjectSettings> + <option name="externalProjectPath" value="$PROJECT_DIR$" /> + <option name="modules"> + <set> + <option value="$PROJECT_DIR$" /> + </set> + </option> + </PlatformioProjectSettings> + </option> + </component> + <component name="PlatformIOWorkspace" PROJECT_DIR="$PROJECT_DIR$" /> +</project> \ No newline at end of file diff --git a/.idea/senseshift-firmware.iml b/.idea/senseshift-firmware.iml new file mode 100644 index 00000000..d986c559 --- /dev/null +++ b/.idea/senseshift-firmware.iml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module classpath="External" external.linked.project.id="senseshift-firmware" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="PlatformIO" type="CPP_MODULE" version="4" /> \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="" vcs="Git" /> + </component> +</project> \ No newline at end of file From 433793b7f3be3dfe6569a06ecc38d21e4383df5e Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 22 Feb 2024 22:04:34 +0400 Subject: [PATCH 81/82] feat: deduct interpolation template --- .../battery/input/battery_sensor.hpp | 5 ++- lib/core/senseshift/core/helpers.hpp | 26 ++++++++------- lib/io/senseshift/input/filter.hpp | 8 ++--- test/test_core_helpers/main.cpp | 29 ++++++++--------- test/test_io_filter/main.cpp | 32 ++++++++++++++++++- 5 files changed, 67 insertions(+), 33 deletions(-) diff --git a/lib/battery/senseshift/battery/input/battery_sensor.hpp b/lib/battery/senseshift/battery/input/battery_sensor.hpp index d0314a03..0ac6a840 100644 --- a/lib/battery/senseshift/battery/input/battery_sensor.hpp +++ b/lib/battery/senseshift/battery/input/battery_sensor.hpp @@ -46,7 +46,10 @@ namespace SenseShift::Battery::Input { protected: [[nodiscard]] auto lookupInterpolateLevel(VoltageType voltage) -> float { - return ::SenseShift::lookup_table_interpolate<VoltageType, float, Container>(*this->lookup_table_, voltage); + return ::SenseShift::lookup_table_interpolate_linear<Container, VoltageType, float>( + *this->lookup_table_, + voltage + ); } private: diff --git a/lib/core/senseshift/core/helpers.hpp b/lib/core/senseshift/core/helpers.hpp index 1d4fb8b1..2ce47264 100644 --- a/lib/core/senseshift/core/helpers.hpp +++ b/lib/core/senseshift/core/helpers.hpp @@ -65,21 +65,25 @@ namespace SenseShift { /// Lookup a value in a table and interpolate between the two closest values. /// - /// \tparam Tp - /// \tparam To - /// \tparam Container + /// \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<Tp, Tp> in descending order. /// \param value /// /// \return - template<typename Tp, typename To, typename Container> - auto lookup_table_interpolate(Container const& lookup_table, Tp value) -> To + 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<typename Container::key_type, Tp>); - static_assert(std::is_same_v<typename Container::mapped_type, To>); - static_assert(std::is_arithmetic_v<Tp>, "lookup_table_interpolate only supports arithmetic types"); - static_assert(std::is_arithmetic_v<To>, "lookup_table_interpolate only supports arithmetic types"); + static_assert(std::is_same_v<typename Container::key_type, Tp> && std::is_same_v<typename Container::mapped_type, To>); + static_assert( + std::is_arithmetic_v<Tp> && std::is_arithmetic_v<To>, + "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) { @@ -111,7 +115,7 @@ namespace SenseShift { using CallbackType = std::function<void(Ts...)>; /// Add a callback to the list. - void add(std::function<void(Ts...)>&& callback) { this->callbacks_.push_back(std::move(callback)); } + void add(CallbackType&& callback) { this->callbacks_.push_back(std::move(callback)); } /// Call all callbacks in this manager. void call(Ts... args) @@ -126,6 +130,6 @@ namespace SenseShift { void operator()(Ts... args) { call(args...); } private: - std::vector<std::function<void(Ts...)>> callbacks_; + std::vector<CallbackType> callbacks_; }; } // namespace SenseShift diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index b13bc857..fe534ee4 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -265,7 +265,7 @@ namespace SenseShift::Input::Filter { /// Usually used to filter out noise in the joystick. class CenterDeadzoneFilter : public IFilter<float> { public: - explicit CenterDeadzoneFilter(float deadzone, float center = 0.5f) : deadzone_(deadzone), center_(center){}; + explicit CenterDeadzoneFilter(float deadzone, float center = 0.5F) : deadzone_(deadzone), center_(center){}; auto filter(ISimpleSensor<float>* /*sensor*/, float value) -> float override { @@ -284,9 +284,9 @@ namespace SenseShift::Input::Filter { /// /// \tparam Tp Type of the lookup table values. /// \tparam Container Type of the lookup table container. - template<typename Tp, typename Container> + template<typename Container, typename Tp = typename Container::mapped_type> class LookupTableInterpolationFilter : public IFilter<Tp> { - static_assert(std::is_same_v<typename Container::value_type, Tp>); + static_assert(std::is_same_v<typename Container::key_type, Tp>); static_assert(std::is_arithmetic_v<Tp>, "LookupTableInterpolationFilter only supports arithmetic types"); public: @@ -294,7 +294,7 @@ namespace SenseShift::Input::Filter { auto filter(ISimpleSensor<float>* /*sensor*/, Tp value) -> Tp override { - return SenseShift::lookup_table_interpolate<Tp, Container>(this->lookup_table_, value); + return SenseShift::lookup_table_interpolate_linear<Container, Tp, Tp>(this->lookup_table_, value); } private: diff --git a/test/test_core_helpers/main.cpp b/test/test_core_helpers/main.cpp index 5dbfd888..e1bcdd29 100644 --- a/test/test_core_helpers/main.cpp +++ b/test/test_core_helpers/main.cpp @@ -66,9 +66,6 @@ void test_remap_simple_float(void) TEST_ASSERT_EQUAL_FLOAT(255.0f, remap_simple(1.0f, 1.0f, 255.0f)); } -// Wtf? https://stackoverflow.com/questions/4295890 -#define COMMAE , - void test_lookup_table_interpolate_float(void) { const std::map<float, float> table = { @@ -78,19 +75,19 @@ void test_lookup_table_interpolate_float(void) { 1.0f, 18.0f }, }; - TEST_ASSERT_EQUAL_FLOAT(13.0f, lookup_table_interpolate<float COMMAE float>(table, 0.0f)); - TEST_ASSERT_EQUAL_FLOAT(13.6f, lookup_table_interpolate<float COMMAE float>(table, 0.1f)); - TEST_ASSERT_EQUAL_FLOAT(14.2f, lookup_table_interpolate<float COMMAE float>(table, 0.2f)); - TEST_ASSERT_EQUAL_FLOAT(14.5f, lookup_table_interpolate<float COMMAE float>(table, 0.25f)); - TEST_ASSERT_EQUAL_FLOAT(14.8f, lookup_table_interpolate<float COMMAE float>(table, 0.3f)); - TEST_ASSERT_EQUAL_FLOAT(15.4f, lookup_table_interpolate<float COMMAE float>(table, 0.4f)); - TEST_ASSERT_EQUAL_FLOAT(16.0f, lookup_table_interpolate<float COMMAE float>(table, 0.5f)); - TEST_ASSERT_EQUAL_FLOAT(16.5f, lookup_table_interpolate<float COMMAE float>(table, 0.55f)); - TEST_ASSERT_EQUAL_FLOAT(17.0f, lookup_table_interpolate<float COMMAE float>(table, 0.6f)); - TEST_ASSERT_EQUAL_FLOAT(17.25f, lookup_table_interpolate<float COMMAE float>(table, 0.7f)); - TEST_ASSERT_EQUAL_FLOAT(17.5f, lookup_table_interpolate<float COMMAE float>(table, 0.8f)); - TEST_ASSERT_EQUAL_FLOAT(17.75f, lookup_table_interpolate<float COMMAE float>(table, 0.9f)); - TEST_ASSERT_EQUAL_FLOAT(18.0f, lookup_table_interpolate<float COMMAE float>(table, 1.0f)); + TEST_ASSERT_EQUAL_FLOAT(13.0f, lookup_table_interpolate_linear(table, 0.0f)); + TEST_ASSERT_EQUAL_FLOAT(13.6f, lookup_table_interpolate_linear(table, 0.1f)); + TEST_ASSERT_EQUAL_FLOAT(14.2f, lookup_table_interpolate_linear(table, 0.2f)); + TEST_ASSERT_EQUAL_FLOAT(14.5f, lookup_table_interpolate_linear(table, 0.25f)); + TEST_ASSERT_EQUAL_FLOAT(14.8f, lookup_table_interpolate_linear(table, 0.3f)); + TEST_ASSERT_EQUAL_FLOAT(15.4f, lookup_table_interpolate_linear(table, 0.4f)); + TEST_ASSERT_EQUAL_FLOAT(16.0f, lookup_table_interpolate_linear(table, 0.5f)); + TEST_ASSERT_EQUAL_FLOAT(16.5f, lookup_table_interpolate_linear(table, 0.55f)); + TEST_ASSERT_EQUAL_FLOAT(17.0f, lookup_table_interpolate_linear(table, 0.6f)); + TEST_ASSERT_EQUAL_FLOAT(17.25f, lookup_table_interpolate_linear(table, 0.7f)); + TEST_ASSERT_EQUAL_FLOAT(17.5f, lookup_table_interpolate_linear(table, 0.8f)); + TEST_ASSERT_EQUAL_FLOAT(17.75f, lookup_table_interpolate_linear(table, 0.9f)); + TEST_ASSERT_EQUAL_FLOAT(18.0f, lookup_table_interpolate_linear(table, 1.0f)); } int process(void) diff --git a/test/test_io_filter/main.cpp b/test/test_io_filter/main.cpp index f5002158..dc3e77f2 100644 --- a/test/test_io_filter/main.cpp +++ b/test/test_io_filter/main.cpp @@ -2,6 +2,8 @@ #include <senseshift/input/sensor.hpp> #include <unity.h> +#include <map> + #define ASSERT_EQUAL_FLOAT_ROUNDED(expected, actual, precision) \ TEST_ASSERT_EQUAL_FLOAT( \ std::round(expected* std::pow(10, precision)) / std::pow(10, precision), \ @@ -134,6 +136,33 @@ void test_center_deadzone_filter(void) TEST_ASSERT_EQUAL_FLOAT(1.0f, filter->filter(nullptr, 1.0f)); } +void test_lookup_table_interpolate_linear_filter(void) +{ + const std::map<float, float> lookup_table = { + { 0.0f, 0.0f }, { 1.0f, 3.5f }, { 2.0f, 7.0f }, { 3.0f, 10.5f }, { 4.0f, 14.0f }, { 5.0f, 17.5f }, + }; + IFilter<float>* filter = new LookupTableInterpolationFilter(lookup_table); + + // test existing values + TEST_ASSERT_EQUAL_FLOAT(0.0f, filter->filter(nullptr, 0.0f)); + TEST_ASSERT_EQUAL_FLOAT(3.5f, filter->filter(nullptr, 1.0f)); + TEST_ASSERT_EQUAL_FLOAT(7.0f, filter->filter(nullptr, 2.0f)); + TEST_ASSERT_EQUAL_FLOAT(10.5f, filter->filter(nullptr, 3.0f)); + TEST_ASSERT_EQUAL_FLOAT(14.0f, filter->filter(nullptr, 4.0f)); + TEST_ASSERT_EQUAL_FLOAT(17.5f, filter->filter(nullptr, 5.0f)); + + // test values in between + TEST_ASSERT_EQUAL_FLOAT(1.75f, filter->filter(nullptr, 0.5f)); + TEST_ASSERT_EQUAL_FLOAT(5.25f, filter->filter(nullptr, 1.5f)); + TEST_ASSERT_EQUAL_FLOAT(8.75f, filter->filter(nullptr, 2.5f)); + TEST_ASSERT_EQUAL_FLOAT(12.25f, filter->filter(nullptr, 3.5f)); + TEST_ASSERT_EQUAL_FLOAT(15.75f, filter->filter(nullptr, 4.5f)); + + // test out of range + TEST_ASSERT_EQUAL_FLOAT(0.0f, filter->filter(nullptr, -1.0f)); + TEST_ASSERT_EQUAL_FLOAT(17.5f, filter->filter(nullptr, 6.0f)); +} + int process(void) { UNITY_BEGIN(); @@ -147,6 +176,7 @@ int process(void) RUN_TEST(test_sliding_window_moving_average_filter); RUN_TEST(test_exponential_moving_average_filter); RUN_TEST(test_center_deadzone_filter); + RUN_TEST(test_lookup_table_interpolate_linear_filter); return UNITY_END(); } @@ -169,4 +199,4 @@ int main(int argc, char** argv) return process(); } -#endif \ No newline at end of file +#endif From c7afbe4aad62bf96137e40ae4ba8d0fc5b4e6c75 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin <hello@leon0399.ru> Date: Thu, 22 Feb 2024 22:25:26 +0400 Subject: [PATCH 82/82] chore: shorten project defines prefix --- .github/scripts/get_firmware_name.sh | 4 ++-- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/release.yml | 4 ++-- firmware/mode_configs/bhaptics/tactal.cpp | 6 +++--- firmware/mode_configs/bhaptics/tactglove.cpp | 8 ++++---- firmware/mode_configs/bhaptics/tactosy2.cpp | 6 +++--- firmware/mode_configs/bhaptics/tactosyf.cpp | 6 +++--- firmware/mode_configs/bhaptics/tactosyh.cpp | 6 +++--- firmware/mode_configs/bhaptics/tactsuit_x16.cpp | 6 +++--- .../bhaptics/tactsuit_x16_pca9685.cpp | 6 +++--- firmware/mode_configs/bhaptics/tactsuit_x40.cpp | 6 +++--- firmware/mode_configs/bhaptics/tactvisor.cpp | 6 +++--- include/config/battery.h | 16 ++++++++-------- include/config/bluetooth.h | 4 ++-- ini/bhaptics.ini | 4 ++-- .../senseshift/bh/ble/connection.cpp | 8 ++++---- .../senseshift/bh/ble/connection.hpp | 2 +- platformio.ini | 4 ++-- 19 files changed, 60 insertions(+), 60 deletions(-) diff --git a/.github/scripts/get_firmware_name.sh b/.github/scripts/get_firmware_name.sh index 120fafe3..b759981f 100755 --- a/.github/scripts/get_firmware_name.sh +++ b/.github/scripts/get_firmware_name.sh @@ -8,12 +8,12 @@ getBhapticsName() { echo "::debug::Getting bHaptics name for $target" echo "::debug::Flags are $flags" - if [[ $flags =~ SENSESHIFT_BLE_USE_NIMBLE=true ]]; then + if [[ $flags =~ SS_BLE_USE_NIMBLE=true ]]; then echo "::debug::Nimble is enabled, appending +nimble to the target" target="$target+nimble" fi - if [[ $flags =~ SENSESHIFT_BATTERY_ENABLED=true ]]; then + if [[ $flags =~ SS_BATTERY_ENABLED=true ]]; then echo "::debug::Battery is enabled, appending +battery to the target" target="$target+battery" fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85d5c815..0531d546 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,8 +32,8 @@ jobs: - bhaptics_tactal - bhaptics_tactvisor - bhaptics_tactglove_right - battery_flag: [ SENSESHIFT_BATTERY_ENABLED=true ] - nimble_flag: [ SENSESHIFT_BLE_USE_NIMBLE=false ] + battery_flag: [ SS_BATTERY_ENABLED=true ] + nimble_flag: [ SS_BLE_USE_NIMBLE=false ] coverage: [ false ] include: @@ -41,18 +41,18 @@ jobs: - target: bhaptics_tactsuit_x40 os: ubuntu-latest coverage: true - battery_flag: SENSESHIFT_BATTERY_ENABLED=true - nimble_flag: SENSESHIFT_BLE_USE_NIMBLE=true + battery_flag: SS_BATTERY_ENABLED=true + nimble_flag: SS_BLE_USE_NIMBLE=true # - target: bhaptics_tactsuit_x40 # os: ubuntu-latest # coverage: true - # battery_flag: SENSESHIFT_BATTERY_ENABLED=true - # nimble_flag: SENSESHIFT_BLE_USE_NIMBLE=false + # battery_flag: SS_BATTERY_ENABLED=true + # nimble_flag: SS_BLE_USE_NIMBLE=false - target: bhaptics_tactsuit_x40 os: ubuntu-latest coverage: false - battery_flag: SENSESHIFT_BATTERY_ENABLED=true - nimble_flag: SENSESHIFT_BLE_USE_NIMBLE=true + battery_flag: SS_BATTERY_ENABLED=true + nimble_flag: SS_BLE_USE_NIMBLE=true steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8cfbff2c..423dd5d6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -31,7 +31,7 @@ jobs: # Enabling all flags to test build for every feature battery_flag: - - SENSESHIFT_BATTERY_ENABLED=true + - SS_BATTERY_ENABLED=true steps: - name: Checkout repository diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d2eecde2..9d042345 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,9 +33,9 @@ jobs: - bhaptics_tactglove_left - bhaptics_tactglove_right battery_flag: - - SENSESHIFT_BATTERY_ENABLED=true + - SS_BATTERY_ENABLED=true nimble_flag: - - SENSESHIFT_BLE_USE_NIMBLE=true + - SS_BLE_USE_NIMBLE=true steps: - uses: actions/checkout@v3 diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index ec8ea898..cfdd4e9c 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -55,7 +55,7 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true +#if defined(SS_BATTERY_ENABLED) && SS_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ new MultiplyFilter(3.3F), // Convert to raw pin voltage @@ -63,8 +63,8 @@ void setupMode() }); auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask<SimpleSensorDecorator<float>>( batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + SS_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index d67f58e6..d1397408 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -28,7 +28,7 @@ using namespace SenseShift::Body::Haptics; extern Application App; Application* app = &App; -static constexpr Body::Hands::HandSide handSide = Body::Hands::HandSide::SENSESHIFT_HAND_SIDE; +static constexpr Body::Hands::HandSide handSide = Body::Hands::HandSide::SS_HAND_SIDE; // clang-format off static const auto& bhLayout = handSide == Body::Hands::HandSide::Left ? BH::TactGloveLeftLayout : BH::TactGloveRightLayout; // clang-format on @@ -63,7 +63,7 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true +#if defined(SS_BATTERY_ENABLED) && SS_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ new MultiplyFilter(3.3F), // Convert to raw pin voltage @@ -71,8 +71,8 @@ void setupMode() }); auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask<SimpleSensorDecorator<float>>( batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + SS_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index c3053bd3..ea6373b4 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -56,7 +56,7 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true +#if defined(SS_BATTERY_ENABLED) && SS_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ new MultiplyFilter(3.3F), // Convert to raw pin voltage @@ -64,8 +64,8 @@ void setupMode() }); auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask<SimpleSensorDecorator<float>>( batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + SS_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index b2c47e26..63860af4 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -57,7 +57,7 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true +#if defined(SS_BATTERY_ENABLED) && SS_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ new MultiplyFilter(3.3F), // Convert to raw pin voltage @@ -65,8 +65,8 @@ void setupMode() }); auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask<SimpleSensorDecorator<float>>( batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + SS_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 11bbe0a4..be8bfd79 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -57,7 +57,7 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true +#if defined(SS_BATTERY_ENABLED) && SS_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ new MultiplyFilter(3.3F), // Convert to raw pin voltage @@ -65,8 +65,8 @@ void setupMode() }); auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask<SimpleSensorDecorator<float>>( batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + SS_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index ae6011f2..bdc9521b 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -66,7 +66,7 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true +#if defined(SS_BATTERY_ENABLED) && SS_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ new MultiplyFilter(3.3F), // Convert to raw pin voltage @@ -74,8 +74,8 @@ void setupMode() }); auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask<SimpleSensorDecorator<float>>( batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + SS_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index b8b05c77..2042b582 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -71,7 +71,7 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true +#if defined(SS_BATTERY_ENABLED) && SS_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ new MultiplyFilter(3.3F), // Convert to raw pin voltage @@ -79,8 +79,8 @@ void setupMode() }); auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask<SimpleSensorDecorator<float>>( batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + SS_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index a3d77b06..09e0dab1 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -80,7 +80,7 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true +#if defined(SS_BATTERY_ENABLED) && SS_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ new MultiplyFilter(3.3F), // Convert to raw pin voltage @@ -88,8 +88,8 @@ void setupMode() }); auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask<SimpleSensorDecorator<float>>( batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + SS_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index 38ece6af..b6c618bc 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -55,7 +55,7 @@ void setupMode() ); bhBleConnection->begin(); -#if defined(SENSESHIFT_BATTERY_ENABLED) && SENSESHIFT_BATTERY_ENABLED == true +#if defined(SS_BATTERY_ENABLED) && SS_BATTERY_ENABLED == true auto* batteryVoltageSensor = new SimpleSensorDecorator(new AnalogSimpleSensor(36)); batteryVoltageSensor->addFilters({ new MultiplyFilter(3.3F), // Convert to raw pin voltage @@ -63,8 +63,8 @@ void setupMode() }); auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask<SimpleSensorDecorator<float>>( batteryVoltageSensor, - SENSESHIFT_BATTERY_SAMPLE_RATE, - { "ADC Battery", 4096, SENSESHIFT_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } + SS_BATTERY_SAMPLE_RATE, + { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } ); batteryTask->begin(); diff --git a/include/config/battery.h b/include/config/battery.h index 67747fa3..219b57f1 100644 --- a/include/config/battery.h +++ b/include/config/battery.h @@ -1,17 +1,17 @@ #pragma once -#ifndef SENSESHIFT_BATTERY_ENABLED -#define SENSESHIFT_BATTERY_ENABLED false +#ifndef SS_BATTERY_ENABLED +#define SS_BATTERY_ENABLED false #endif -#ifndef SENSESHIFT_BATTERY_SAMPLE_RATE -#define SENSESHIFT_BATTERY_SAMPLE_RATE 10000 +#ifndef SS_BATTERY_SAMPLE_RATE +#define SS_BATTERY_SAMPLE_RATE 10000 #endif -#ifndef SENSESHIFT_BATTERY_THRESHOLD_PERCENTAGE -#define SENSESHIFT_BATTERY_THRESHOLD_PERCENTAGE 20 +#ifndef SS_BATTERY_THRESHOLD_PERCENTAGE +#define SS_BATTERY_THRESHOLD_PERCENTAGE 20 #endif -#ifndef SENSESHIFT_BATTERY_TASK_PRIORITY -#define SENSESHIFT_BATTERY_TASK_PRIORITY 1 +#ifndef SS_BATTERY_TASK_PRIORITY +#define SS_BATTERY_TASK_PRIORITY 1 #endif diff --git a/include/config/bluetooth.h b/include/config/bluetooth.h index 3de034d4..79ac1c95 100644 --- a/include/config/bluetooth.h +++ b/include/config/bluetooth.h @@ -11,6 +11,6 @@ } #endif -#ifndef SENSESHIFT_BLE_USE_NIMBLE -#define SENSESHIFT_BLE_USE_NIMBLE false +#ifndef SS_BLE_USE_NIMBLE +#define SS_BLE_USE_NIMBLE false #endif diff --git a/ini/bhaptics.ini b/ini/bhaptics.ini index 0d3c4343..a9dc121b 100644 --- a/ini/bhaptics.ini +++ b/ini/bhaptics.ini @@ -263,7 +263,7 @@ monitor_speed = ${bhaptics.monitor_speed} build_flags = ${bhaptics.build_flags} -D BH_DEVICE_TACTGLOVE - -D SENSESHIFT_HAND_SIDE=Left + -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 }' @@ -284,7 +284,7 @@ monitor_speed = ${bhaptics.monitor_speed} build_flags = ${bhaptics.build_flags} -D BH_DEVICE_TACTGLOVE - -D SENSESHIFT_HAND_SIDE=Right + -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 }' diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp index db642a43..2e05de3a 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -6,7 +6,7 @@ #include <Arduino.h> -#if defined(SENSESHIFT_BLE_USE_NIMBLE) && SENSESHIFT_BLE_USE_NIMBLE == true +#if defined(SS_BLE_USE_NIMBLE) && SS_BLE_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(SENSESHIFT_BLE_USE_NIMBLE) && SENSESHIFT_BLE_USE_NIMBLE == true +#if defined(SS_BLE_USE_NIMBLE) && SS_BLE_USE_NIMBLE == true void onStatus(BLECharacteristic* pCharacteristic, Status s, int code) override #else void onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code) override @@ -182,7 +182,7 @@ namespace SenseShift::BH::BLE { | PROPERTY_NOTIFY // for whatever reason, it have to be writable, otherwise Desktop app crashes ); -#if !defined(SENSESHIFT_BLE_USE_NIMBLE) || SENSESHIFT_BLE_USE_NIMBLE != true +#if !defined(SS_BLE_USE_NIMBLE) || SS_BLE_USE_NIMBLE != true batteryChar->addDescriptor(new BLE2902()); #endif @@ -209,7 +209,7 @@ namespace SenseShift::BH::BLE { ); monitorChar->setCallbacks(new LogOutputCharCallbacks()); -#if !defined(SENSESHIFT_BLE_USE_NIMBLE) || SENSESHIFT_BLE_USE_NIMBLE != true +#if !defined(SS_BLE_USE_NIMBLE) || SS_BLE_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 e5033fb1..c35810b4 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -10,7 +10,7 @@ #include <Arduino.h> #include <esp_wifi.h> -#if defined(SENSESHIFT_BLE_USE_NIMBLE) && SENSESHIFT_BLE_USE_NIMBLE == true +#if defined(SS_BLE_USE_NIMBLE) && SS_BLE_USE_NIMBLE == true #include <NimBLEDevice.h> #else #include <BLEDevice.h> diff --git a/platformio.ini b/platformio.ini index e6d2c7c4..fb8423bb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,8 +28,8 @@ build_flags = -D CORE_DEBUG_LEVEL=3 ; -D DEBUG_MODE=0 ; -D DEBUG_ESP_PORT=Serial -; -D SENSESHIFT_BATTERY_ENABLED=true -; -D SENSESHIFT_BLE_USE_NIMBLE=true +; -D SS_BATTERY_ENABLED=true +; -D SS_BLE_USE_NIMBLE=true build_src_filter = +<*>