summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-04-19 16:52:33 +1000
committerjacqueline <me@jacqueline.id.au>2024-04-19 16:52:33 +1000
commit5b99267cb9f0344e519956096867aea5468ecf9f (patch)
tree9a6fd47602c4a4971434b1ed30142fd383ca8cdb /src/drivers
parent8e113ea9ae595b1bc37e7a567b0bc6b90ec81c05 (diff)
parent7c075cf5b776feaed2065f936dff0c176635b89d (diff)
downloadtangara-fw-5b99267cb9f0344e519956096867aea5468ecf9f.tar.gz
Merge branch 'main' of codeberg.org:cool-tech-zone/tangara-fw
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/haptics.cpp68
-rw-r--r--src/drivers/include/haptics.hpp50
-rw-r--r--src/drivers/include/nvs.hpp6
-rw-r--r--src/drivers/nvs.cpp14
4 files changed, 102 insertions, 36 deletions
diff --git a/src/drivers/haptics.cpp b/src/drivers/haptics.cpp
index 46136e62..f7b18086 100644
--- a/src/drivers/haptics.cpp
+++ b/src/drivers/haptics.cpp
@@ -10,6 +10,7 @@
#include <cstdint>
#include <initializer_list>
#include <mutex>
+#include <variant>
#include "assert.h"
#include "driver/gpio.h"
@@ -27,24 +28,55 @@ namespace drivers {
static constexpr char kTag[] = "haptics";
static constexpr uint8_t kHapticsAddress = 0x5A;
-Haptics::Haptics() {
+Haptics::Haptics(const std::variant<ErmMotor, LraMotor>& motor) {
PowerUp();
- // Put into ERM Open Loop:
- // (§8.5.4.1 Programming for ERM Open-Loop Operation)
- // - Turn off N_ERM_LRA first
- WriteRegister(Register::kControl1,
- static_cast<uint8_t>(RegisterDefaults::kControl1) &
- (~ControlMask::kNErmLra));
- // - Turn on ERM_OPEN_LOOP
- WriteRegister(Register::kControl3,
- static_cast<uint8_t>(RegisterDefaults::kControl3) |
- ControlMask::kErmOpenLoop);
-
- // Set library
- // TODO(robin): try the other libraries and test response. C is marginal, D
- // too much?
- WriteRegister(Register::kWaveformLibrary, static_cast<uint8_t>(kDefaultLibrary));
+ // TODO: Break out into helper functions
+ // TODO: Use LRA closed loop instead, loading in calibration data from NVS, or
+ // running calibration + storing the result first if necessary.
+
+ if (std::holds_alternative<ErmMotor>(motor)) {
+ ESP_LOGI(kTag, "Setting up ERM motor...");
+
+ // Put into ERM Open Loop:
+ // (§8.5.4.1 Programming for ERM Open-Loop Operation)
+
+ // - Turn off N_ERM_LRA first
+ WriteRegister(Register::kFeedbackControl,
+ static_cast<uint8_t>(RegisterDefaults::kFeedbackControl) &
+ (~ControlMask::kNErmLra));
+
+ // - Turn on ERM_OPEN_LOOP
+ WriteRegister(Register::kControl3,
+ static_cast<uint8_t>(RegisterDefaults::kControl3) |
+ ControlMask::kErmOpenLoop);
+
+ // Set library
+ // TODO(robin): try the other libraries and test response. C is marginal, D
+ // too much?
+ WriteRegister(Register::kWaveformLibrary, static_cast<uint8_t>(kDefaultErmLibrary));
+
+ } else if (std::holds_alternative<LraMotor>(motor)) {
+ ESP_LOGI(kTag, "Setting up LRA motor...");
+ // TODO:
+ // auto lraInit = std::get<LraMotor>(motor);
+
+ // Put into LRA Open Loop:
+ // (§8.5.4.1 Programming for LRA Open-Loop Operation)
+
+ // - Turn on N_ERM_LRA first
+ WriteRegister(Register::kFeedbackControl,
+ static_cast<uint8_t>(RegisterDefaults::kFeedbackControl) &
+ (ControlMask::kNErmLra));
+
+ // - Turn on LRA_OPEN_LOOP
+ WriteRegister(Register::kControl3,
+ static_cast<uint8_t>(RegisterDefaults::kControl3) |
+ ControlMask::kLraOpenLoop);
+
+ // Set library; only option is the LRA one for, well, LRA motors.
+ WriteRegister(Register::kWaveformLibrary, static_cast<uint8_t>(Library::LRA));
+ }
// Set mode (internal trigger, on writing 1 to Go register)
WriteRegister(Register::kMode, static_cast<uint8_t>(Mode::kInternalTrigger));
@@ -93,13 +125,13 @@ auto Haptics::SetWaveformEffect(Effect effect) -> void {
auto Haptics::TourEffects() -> void {
- TourEffects(Effect::kFirst, Effect::kLast, kDefaultLibrary);
+ TourEffects(Effect::kFirst, Effect::kLast, kDefaultErmLibrary);
}
auto Haptics::TourEffects(Library lib) -> void {
TourEffects(Effect::kFirst, Effect::kLast, lib);
}
auto Haptics::TourEffects(Effect from, Effect to) -> void {
- TourEffects(from, to, kDefaultLibrary);
+ TourEffects(from, to, kDefaultErmLibrary);
}
auto Haptics::TourEffects(Effect from, Effect to, Library lib) -> void {
ESP_LOGI(kTag, "With library #%u...", static_cast<uint8_t>(lib));
diff --git a/src/drivers/include/haptics.hpp b/src/drivers/include/haptics.hpp
index 6cfcbb0d..940c3c6d 100644
--- a/src/drivers/include/haptics.hpp
+++ b/src/drivers/include/haptics.hpp
@@ -11,13 +11,24 @@
#include <mutex>
#include <optional>
#include <string>
+#include <variant>
namespace drivers {
+typedef std::monostate ErmMotor;
+struct LraMotor {
+ // TODO: fill out with calibration data from https://www.ti.com/lit/ds/symlink/drv2605l.pdf
+ bool hi;
+};
+
class Haptics {
public:
- static auto Create() -> Haptics* { return new Haptics(); }
- Haptics();
+ static auto Create(const std::variant<ErmMotor, LraMotor>& motor)
+ -> Haptics* {
+ return new Haptics(motor);
+ }
+
+ Haptics(const std::variant<ErmMotor, LraMotor>& motor);
~Haptics();
// Not copyable or movable.
@@ -169,11 +180,12 @@ class Haptics {
B = 2, // 3V, Rise: 40-60ms, Brake: 5-15ms
C = 3, // 3V, Rise: 60-80ms, Brake: 10-20ms
D = 4, // 3V, Rise: 100-140ms, Brake: 15-25ms
- E = 5 // 3V, Rise: >140ms, Brake: >30ms
- // 6 is LRA-only, 7 is 4.5V+
+ E = 5, // 3V, Rise: >140ms, Brake: >30ms
+ LRA = 6
+ // 7 is 4.5V+
};
- static constexpr Library kDefaultLibrary = Library::C;
+ static constexpr Library kDefaultErmLibrary = Library::C;
auto PowerDown() -> void;
auto Reset() -> void;
@@ -214,10 +226,12 @@ class Haptics {
};
struct ControlMask {
- // Control1
+ // FeedbackControl
static constexpr uint8_t kNErmLra = 0b10000000;
+
// Control3
static constexpr uint8_t kErmOpenLoop = 0b00100000;
+ static constexpr uint8_t kLraOpenLoop = 0b00000001;
};
// §8.6 Register Map
@@ -257,12 +271,12 @@ class Haptics {
// A bunch of different options, not grouped
// in any particular sensible way
- kControl1 = 0x1A,
- kControl2 = 0x1B,
- kControl3 = 0x1C,
- kControl4 = 0x1D,
- kControl5 = 0x1E,
- kControl6 = 0x1F,
+ kFeedbackControl = 0x1A,
+ kControl1 = 0x1B,
+ kControl2 = 0x1C,
+ kControl3 = 0x1D,
+ kControl4 = 0x1E,
+ kControl5 = 0x1F,
kSupplyVoltageMonitor = 0x21, // "VBAT"
kLraResonancePeriod = 0x22,
@@ -295,12 +309,12 @@ class Haptics {
kOverdriveClampVoltage = 0x8C,
kAutoCalibrationCompensationResult = 0x0C,
kAutoCalibrationBackEmfResult = 0x6C,
- kControl1 = 0x36,
- kControl2 = 0x93,
- kControl3 = 0xF5,
- kControl4 = 0xA0,
- kControl5 = 0x20,
- kControl6 = 0x80,
+ kFeedbackControl = 0x36,
+ kControl1 = 0x93,
+ kControl2 = 0xF5,
+ kControl3 = 0xA0,
+ kControl4 = 0x20,
+ kControl5 = 0x80,
kSupplyVoltageMonitor = 0,
kLraResonancePeriod = 0,
};
diff --git a/src/drivers/include/nvs.hpp b/src/drivers/include/nvs.hpp
index 25396622..7c74ceb0 100644
--- a/src/drivers/include/nvs.hpp
+++ b/src/drivers/include/nvs.hpp
@@ -68,6 +68,7 @@ class NvsStorage {
auto Read() -> void;
auto Write() -> bool;
+ // Hardware Compatibility
auto LockPolarity() -> bool;
auto LockPolarity(bool) -> void;
@@ -76,6 +77,10 @@ class NvsStorage {
auto DisplaySize(std::pair<std::optional<uint16_t>, std::optional<uint16_t>>)
-> void;
+ auto HapticMotorIsErm() -> bool;
+ auto HapticMotorIsErm(bool) -> void;
+ // /Hardware Compatibility
+
auto PreferredBluetoothDevice() -> std::optional<bluetooth::MacAndName>;
auto PreferredBluetoothDevice(std::optional<bluetooth::MacAndName>) -> void;
@@ -130,6 +135,7 @@ class NvsStorage {
Setting<uint8_t> lock_polarity_;
Setting<uint16_t> display_cols_;
Setting<uint16_t> display_rows_;
+ Setting<uint8_t> haptic_motor_type_;
Setting<uint8_t> brightness_;
Setting<uint8_t> sensitivity_;
diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp
index fbdb5286..c8befe48 100644
--- a/src/drivers/nvs.cpp
+++ b/src/drivers/nvs.cpp
@@ -39,6 +39,7 @@ static constexpr char kKeyScrollSensitivity[] = "scroll";
static constexpr char kKeyLockPolarity[] = "lockpol";
static constexpr char kKeyDisplayCols[] = "dispcols";
static constexpr char kKeyDisplayRows[] = "disprows";
+static constexpr char kKeyHapticMotorType[] = "hapticmtype";
static constexpr char kKeyDbAutoIndex[] = "dbautoindex";
static auto nvs_get_string(nvs_handle_t nvs, const char* key)
@@ -166,6 +167,7 @@ NvsStorage::NvsStorage(nvs_handle_t handle)
lock_polarity_(kKeyLockPolarity),
display_cols_(kKeyDisplayCols),
display_rows_(kKeyDisplayRows),
+ haptic_motor_type_(kKeyHapticMotorType),
brightness_(kKeyBrightness),
sensitivity_(kKeyScrollSensitivity),
amp_max_vol_(kKeyAmpMaxVolume),
@@ -188,6 +190,7 @@ auto NvsStorage::Read() -> void {
lock_polarity_.read(handle_);
display_cols_.read(handle_);
display_rows_.read(handle_);
+ haptic_motor_type_.read(handle_),
brightness_.read(handle_);
sensitivity_.read(handle_);
amp_max_vol_.read(handle_);
@@ -205,6 +208,7 @@ auto NvsStorage::Write() -> bool {
lock_polarity_.write(handle_);
display_cols_.write(handle_);
display_rows_.write(handle_);
+ haptic_motor_type_.write(handle_),
brightness_.write(handle_);
sensitivity_.write(handle_);
amp_max_vol_.write(handle_);
@@ -243,6 +247,16 @@ auto NvsStorage::LockPolarity(bool p) -> void {
lock_polarity_.set(p);
}
+auto NvsStorage::HapticMotorIsErm() -> bool {
+ std::lock_guard<std::mutex> lock{mutex_};
+ return haptic_motor_type_.get().value_or(0) > 0;
+}
+
+auto NvsStorage::HapticMotorIsErm(bool p) -> void {
+ std::lock_guard<std::mutex> lock{mutex_};
+ haptic_motor_type_.set(p);
+}
+
auto NvsStorage::DisplaySize()
-> std::pair<std::optional<uint16_t>, std::optional<uint16_t>> {
std::lock_guard<std::mutex> lock{mutex_};