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 @@
|
||||
# BQ25896 Power Management IC
|
||||
|
||||
[Product page](https://www.ti.com/product/BQ25896)
|
||||
[Data sheet](https://www.ti.com/lit/gpn/bq25896)
|
||||
[Refence implementation](https://github.com/lewisxhe/XPowersLib/blob/73b92a6641b72c0aca2be989207689cb05da9788/src/PowersBQ25896.tpp)
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "Bq25896.h"
|
||||
|
||||
#define TAG "BQ27220"
|
||||
|
||||
void Bq25896::powerOff() {
|
||||
TT_LOG_I(TAG, "Power off");
|
||||
bitOn(0x09, BIT(5));
|
||||
}
|
||||
|
||||
void Bq25896::powerOn() {
|
||||
TT_LOG_I(TAG, "Power on");
|
||||
bitOff(0x09, BIT(5));
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/i2c/I2cDevice.h>
|
||||
|
||||
constexpr auto BQ25896_ADDRESS = 0x6b;
|
||||
|
||||
class Bq25896 final : public tt::hal::i2c::I2cDevice {
|
||||
|
||||
public:
|
||||
|
||||
explicit Bq25896(i2c_port_t port) : I2cDevice(port, BQ25896_ADDRESS) {
|
||||
powerOn();
|
||||
}
|
||||
|
||||
std::string getName() const override { return "BQ25896"; }
|
||||
|
||||
std::string getDescription() const override { return "I2C 1 cell 3A buck battery charger with power path and PSEL"; }
|
||||
|
||||
void powerOff();
|
||||
|
||||
void powerOn();
|
||||
};
|
||||
@@ -127,7 +127,7 @@ bool Bq27220::getCurrent(int16_t &value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Bq27220::getBatteryStatus(Bq27220::BatteryStatus &batt_sta) {
|
||||
bool Bq27220::getBatteryStatus(BatteryStatus &batt_sta) {
|
||||
if (readRegister16(registers::CMD_BATTERY_STATUS, batt_sta.full)) {
|
||||
swapEndianess(batt_sta.full);
|
||||
return true;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
class Bq27220 final : public tt::hal::i2c::I2cDevice {
|
||||
|
||||
private:
|
||||
uint32_t accessKey;
|
||||
|
||||
bool unsealDevice();
|
||||
@@ -15,7 +14,7 @@ private:
|
||||
bool sendSubCommand(uint16_t subCmd, bool waitConfirm = false);
|
||||
bool writeConfig16(uint16_t address, uint16_t value);
|
||||
bool configPreamble(bool &isSealed);
|
||||
bool configEpilouge(const bool isSealed);
|
||||
bool configEpilouge(bool isSealed);
|
||||
|
||||
template<typename T>
|
||||
bool performConfigUpdate(T configUpdateFunc)
|
||||
@@ -86,9 +85,9 @@ public:
|
||||
uint16_t full;
|
||||
};
|
||||
|
||||
std::string getName() const final { return "BQ27220"; }
|
||||
std::string getName() const override { return "BQ27220"; }
|
||||
|
||||
std::string getDescription() const final { return "I2C-controlled CEDV battery fuel gauge"; }
|
||||
std::string getDescription() const override { return "I2C-controlled CEDV battery fuel gauge"; }
|
||||
|
||||
explicit Bq27220(i2c_port_t port) : I2cDevice(port, BQ27220_ADDRESS), accessKey(0xFFFFFFFF) {}
|
||||
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
# ST7796
|
||||
|
||||
A basic ESP32 LVGL driver for ST7796 displays.
|
||||
|
||||
|
||||
@@ -67,27 +67,12 @@ bool St7796Display::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lc
|
||||
|
||||
const esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = configuration->resetPin, // Set to -1 if not use
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
.color_space = ESP_LCD_COLOR_SPACE_RGB,
|
||||
#else
|
||||
.color_space = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
#endif
|
||||
.bits_per_pixel = 16,
|
||||
.vendor_config = &vendor_config
|
||||
};
|
||||
/*
|
||||
const esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = configuration->resetPin,
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = 16,
|
||||
.flags = {
|
||||
.reset_active_high = false
|
||||
},
|
||||
.vendor_config = nullptr
|
||||
};
|
||||
*/
|
||||
|
||||
if (esp_lcd_new_panel_st7796(ioHandle, &panel_config, &panelHandle) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to create panel");
|
||||
return false;
|
||||
@@ -148,7 +133,14 @@ lvgl_port_display_cfg_t St7796Display::getLvglPortDisplayConfig(esp_lcd_panel_io
|
||||
.mirror_y = configuration->mirrorY,
|
||||
},
|
||||
.color_format = LV_COLOR_FORMAT_NATIVE,
|
||||
.flags = {.buff_dma = true, .buff_spiram = false, .sw_rotate = false, .swap_bytes = true, .full_refresh = false, .direct_mode = false}
|
||||
.flags = {
|
||||
.buff_dma = true,
|
||||
.buff_spiram = false,
|
||||
.sw_rotate = false,
|
||||
.swap_bytes = true,
|
||||
.full_refresh = false,
|
||||
.direct_mode = false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <Tactility/hal/spi/Spi.h>
|
||||
|
||||
#include <EspLcdDisplay.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <functional>
|
||||
|
||||
class St7796Display final : public EspLcdDisplay {
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
class Tca8418 final : public tt::hal::i2c::I2cDevice {
|
||||
|
||||
private:
|
||||
|
||||
uint8_t tca8418_address;
|
||||
uint32_t last_update_micros;
|
||||
uint32_t this_update_micros;
|
||||
|
||||
Reference in New Issue
Block a user