Merge develop into main (#307)
## Launcher - Launcher now has optional power button to show - Launcher layout improvements - Removed text from Launcher (translations with larger amounts of text did not fit small device formats) ## T-Lora Pager - Implement power off (created `BQ25896` driver) - Implemented haptics (created `DRV2605` driver project) and buzz on startup - Reversed scroll wheel - Created `TloraEncoder` device and relocated its logic from `TloraKeyboard` - Disabled SPIRAM test to save 0.5 seconds of boot time (current boot time is very slow) - Update `ST7796` esp_lcd driver to v1.3.4 - Fixed keyboard bug: delete queue in destructor - Fixed driver dependencies: Avoiding usage of global static shared_ptr. Properly constructor-inject everywhere, or use `tt::hal::findDevices()` - I2C configuration is now immutable (you cannot disable it anymore from the I2C Settings app, as it would break crucial drivers) - Renamed I2C and UART subsystems to "Internal" ## Drivers - On/off interface added to `PowerDevice` - Created `tt::hal::Configuration.createDevices`, which is intended to replace all custom create calls for display, keyboard, etc. - Created `EncoderDevice` as a `Device` subtype ## Other Improvements - Changed `findDevices(type, function)` into a templatized function. - Improved SD card mounting ## Fixes - Show Screenshot app again - Fixed Statusbar: some updates were allowed to time out and fail silently: When the Statusbar service would do a state update, the LVGL statusbar would never get updated due to this timeout. - Fixed memory leaks in all `createSdCard()` functions (in most board implementations)
This commit is contained in:
committed by
GitHub
parent
e9f72490fc
commit
50007ea9ed
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRC_DIRS "Source"
|
||||
INCLUDE_DIRS "Source"
|
||||
REQUIRES Tactility
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
# DRV2605 Haptic Driver
|
||||
|
||||
[Datasheet](https://www.ti.com/product/DRV2605)
|
||||
[Reference implementation](https://github.com/lewisxhe/SensorLib/blob/master/src/SensorDRV2605.hpp)
|
||||
[Usage in T-Lora Pager code from LilyGO](https://github.com/Xinyuan-LilyGO/LilyGoLib/blob/6b534a28b0ec31313e4a7e89c5e8b7e4437e6fd1/src/LilyGo_LoRa_Pager.cpp#L956)
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "Drv2605.h"
|
||||
|
||||
bool Drv2605::init() {
|
||||
uint8_t status;
|
||||
if (!readRegister8(static_cast<uint8_t>(Register::Status), status)) {
|
||||
TT_LOG_E(TAG, "Failed to read status");
|
||||
return false;
|
||||
}
|
||||
status >>= 5;
|
||||
|
||||
ChipId chip_id = static_cast<ChipId>(status);
|
||||
if (chip_id != ChipId::DRV2604 && chip_id != ChipId::DRV2604L && chip_id != ChipId::DRV2605 && chip_id != ChipId::DRV2605L) {
|
||||
TT_LOG_E(TAG, "Unknown chip id %02x", chip_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
writeRegister(Register::Mode, 0x00); // Get out of standby
|
||||
|
||||
writeRegister(Register::RealtimePlaybackInput, 0x00); // Disable
|
||||
|
||||
|
||||
setWaveFormForClick();
|
||||
|
||||
// ERM open loop
|
||||
|
||||
uint8_t feedback;
|
||||
if (!readRegister(Register::Feedback, feedback)) {
|
||||
TT_LOG_E(TAG, "Failed to read feedback");
|
||||
return false;
|
||||
}
|
||||
|
||||
writeRegister(Register::Feedback, feedback & 0x7F); // N_ERM_LRA off
|
||||
|
||||
bitOnByIndex(static_cast<uint8_t>(Register::Control3), 5); // ERM_OPEN_LOOP on
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Drv2605::setWaveFormForBuzz() {
|
||||
writeRegister(Register::WaveSequence1, 1); // Strong click
|
||||
writeRegister(Register::WaveSequence2, 1); // Strong click
|
||||
writeRegister(Register::WaveSequence3, 1); // Strong click
|
||||
writeRegister(Register::WaveSequence4, 0); // End sequence
|
||||
|
||||
writeRegister(Register::OverdriveTimeOffset, 0); // No overdrive
|
||||
|
||||
writeRegister(Register::SustainTimeOffsetPostivie, 0);
|
||||
writeRegister(Register::SustainTimeOffsetNegative, 0);
|
||||
writeRegister(Register::BrakeTimeOffset, 0);
|
||||
|
||||
writeRegister(Register::AudioInputLevelMax, 0x64);
|
||||
}
|
||||
|
||||
void Drv2605::setWaveFormForClick() {
|
||||
writeRegister(Register::WaveSequence1, 1); // Strong click
|
||||
writeRegister(Register::WaveSequence2, 0); // End sequence
|
||||
|
||||
writeRegister(Register::OverdriveTimeOffset, 0); // No overdrive
|
||||
|
||||
writeRegister(Register::SustainTimeOffsetPostivie, 0);
|
||||
writeRegister(Register::SustainTimeOffsetNegative, 0);
|
||||
writeRegister(Register::BrakeTimeOffset, 0);
|
||||
|
||||
writeRegister(Register::AudioInputLevelMax, 0x64);
|
||||
}
|
||||
|
||||
void Drv2605::setWaveForm(uint8_t slot, uint8_t waveform) {
|
||||
writeRegister8(static_cast<uint8_t>(Register::WaveSequence1) + slot, waveform);
|
||||
}
|
||||
|
||||
void Drv2605::selectLibrary(uint8_t library) {
|
||||
writeRegister(Register::WaveLibrarySelect, library);
|
||||
}
|
||||
|
||||
void Drv2605::startPlayback() {
|
||||
writeRegister(Register::Go, 0x01);
|
||||
}
|
||||
|
||||
void Drv2605::stopPlayback() {
|
||||
writeRegister(Register::Go, 0x00);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/i2c/I2cDevice.h>
|
||||
|
||||
class Drv2605 : public tt::hal::i2c::I2cDevice {
|
||||
|
||||
static constexpr auto* TAG = "DRV2605";
|
||||
static constexpr auto ADDRESS = 0x5A;
|
||||
|
||||
bool autoPlayStartupBuzz;
|
||||
|
||||
// Chip IDs
|
||||
enum class ChipId {
|
||||
DRV2604 = 0x04, // Has RAM. Doesn't havew licensed ROM library.
|
||||
DRV2605 = 0x03, // Has licensed ROM library. Doesn't have RAM.
|
||||
DRV2604L = 0x06, // Low-voltage variant of the DRV2604.
|
||||
DRV2605L = 0x07 // Low-voltage variant of the DRV2605.
|
||||
};
|
||||
|
||||
enum class Register {
|
||||
Status = 0x00,
|
||||
Mode = 0x01,
|
||||
RealtimePlaybackInput = 0x02,
|
||||
WaveLibrarySelect = 0x03,
|
||||
WaveSequence1 = 0x04,
|
||||
WaveSequence2 = 0x05,
|
||||
WaveSequence3 = 0x06,
|
||||
WaveSequence4 = 0x07,
|
||||
WaveSequence5 = 0x08,
|
||||
WaveSequence6 = 0x09,
|
||||
WaveSequence7 = 0x0A,
|
||||
WaveSequence8 = 0x0B,
|
||||
Go = 0x0C,
|
||||
OverdriveTimeOffset = 0x0D,
|
||||
SustainTimeOffsetPostivie = 0x0E,
|
||||
SustainTimeOffsetNegative = 0x0F,
|
||||
BrakeTimeOffset = 0x10,
|
||||
AudioControl = 0x11,
|
||||
AudioInputLevelMin = 0x12,
|
||||
AudioInputLevelMax = 0x13,
|
||||
AudioOutputLevelMin = 0x14,
|
||||
AudioOutputLevelMax = 0x15,
|
||||
RatedVoltage = 0x16,
|
||||
OverdriveClampVoltage = 0x17,
|
||||
AutoCalibrationCompensation = 0x18,
|
||||
AutoCalibrationBackEmf = 0x19,
|
||||
Feedback = 0x1A,
|
||||
Control1 = 0x1B,
|
||||
Control2 = 0x1C,
|
||||
Control3 = 0x1D,
|
||||
Control4 = 0x1E,
|
||||
Vbat = 0x21,
|
||||
LraResonancePeriod = 0x22,
|
||||
};
|
||||
|
||||
bool writeRegister(Register reg, const uint8_t value) const {
|
||||
return writeRegister8(static_cast<uint8_t>(reg), value);
|
||||
}
|
||||
|
||||
bool readRegister(Register reg, uint8_t& value) const {
|
||||
return readRegister8(static_cast<uint8_t>(reg), value);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit Drv2605(i2c_port_t port, bool autoPlayStartupBuzz = true) : I2cDevice(port, ADDRESS), autoPlayStartupBuzz(autoPlayStartupBuzz) {
|
||||
if (!init()) {
|
||||
TT_LOG_E(TAG, "Failed to initialize DRV2605");
|
||||
}
|
||||
|
||||
if (autoPlayStartupBuzz) {
|
||||
setWaveFormForBuzz();
|
||||
startPlayback();
|
||||
}
|
||||
}
|
||||
|
||||
std::string getName() const final { return "DRV2605"; }
|
||||
std::string getDescription() const final { return "Haptic driver for ERM/LRA with waveform library & auto-resonance tracking"; }
|
||||
|
||||
bool init();
|
||||
|
||||
void setWaveFormForBuzz();
|
||||
void setWaveFormForClick();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param slot a value from 0 to 7
|
||||
* @param waveform
|
||||
*/
|
||||
void setWaveForm(uint8_t slot, uint8_t waveform);
|
||||
void selectLibrary(uint8_t library);
|
||||
void startPlayback();
|
||||
void stopPlayback();
|
||||
};
|
||||
Reference in New Issue
Block a user