summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcooljqln <cooljqln@noreply.codeberg.org>2025-03-19 03:31:18 +0000
committercooljqln <cooljqln@noreply.codeberg.org>2025-03-19 03:31:18 +0000
commit34e7ce869b8d451e0586e96cc4dabbff8efb56d3 (patch)
treecca0de0ededc0ec001028c64f2424294f6c7e029
parentfe38a57120145f73abf170400fe4a0eb0fd2714a (diff)
parent4ddeeee0f2ca1bfd70b7045446fc719afe357431 (diff)
downloadtangara-fw-34e7ce869b8d451e0586e96cc4dabbff8efb56d3.tar.gz
Merge pull request 'Support padding the left side of the display with black columns' (#302) from display_padding into main
Reviewed-on: https://codeberg.org/cool-tech-zone/tangara-fw/pulls/302
-rw-r--r--src/drivers/display.cpp62
-rw-r--r--src/drivers/display_init.cpp1
-rw-r--r--src/drivers/include/drivers/display.hpp4
-rw-r--r--src/drivers/include/drivers/display_init.hpp1
-rw-r--r--src/drivers/include/drivers/nvs.hpp4
-rw-r--r--src/drivers/nvs.cpp14
-rw-r--r--src/tangara/ui/ui_fsm.cpp3
7 files changed, 73 insertions, 16 deletions
diff --git a/src/drivers/display.cpp b/src/drivers/display.cpp
index 2fcb9dc0..0ae37688 100644
--- a/src/drivers/display.cpp
+++ b/src/drivers/display.cpp
@@ -136,21 +136,35 @@ auto Display::Create(IGpios& expander,
spi_device_handle_t handle;
spi_bus_add_device(VSPI_HOST, &spi_cfg, &handle);
- auto display = std::make_unique<Display>(expander, handle);
+ auto display = std::make_unique<Display>(expander, handle, init_data.pad);
// Now we reset the display into a known state, then configure it
ESP_LOGI(kTag, "Sending init sequences");
+
+ // Hold the SPI bus for the entire init sequence, as otherwise SD init may
+ // grab it and delay showing the boot splash. The total time until boot is
+ // finished may be increased by doing this, but a short boot with no feedback
+ // feels worse than a longer boot that doesn't tell you anything.
+ spi_device_acquire_bus(handle, portMAX_DELAY);
+ expander.SdMuxEnable(false);
+
for (int i = 0; i < init_data.num_sequences; i++) {
display->SendInitialisationSequence(init_data.sequences[i]);
}
+ display->WriteLeftPad(reinterpret_cast<uint8_t*>(kDisplayBuffer));
+
+ expander.SdMuxEnable(true);
+ spi_device_release_bus(handle);
+
// The hardware is now configured correctly. Next, initialise the LVGL display
// driver.
ESP_LOGI(kTag, "Init buffers");
assert(esp_ptr_dma_capable(kDisplayBuffer));
ESP_LOGI(kTag, "Creating display");
- display->display_ = lv_display_create(init_data.width, init_data.height);
+ display->display_ =
+ lv_display_create(init_data.width - init_data.pad, init_data.height);
lv_display_set_buffers(display->display_, kDisplayBuffer, NULL,
sizeof(kDisplayBuffer),
LV_DISPLAY_RENDER_MODE_PARTIAL);
@@ -162,12 +176,13 @@ auto Display::Create(IGpios& expander,
return display.release();
}
-Display::Display(IGpios& gpio, spi_device_handle_t handle)
+Display::Display(IGpios& gpio, spi_device_handle_t handle, uint_fast8_t pad)
: gpio_(gpio),
handle_(handle),
first_flush_finished_(false),
display_on_(false),
- brightness_(0) {}
+ brightness_(0),
+ pad_(pad) {}
Display::~Display() {
ledc_fade_func_uninstall();
@@ -223,13 +238,6 @@ auto Display::SetDutyCycle(uint_fast8_t new_duty, bool fade) -> void {
}
void Display::SendInitialisationSequence(const uint8_t* data) {
- // Hold the SPI bus for the entire init sequence, as otherwise SD init may
- // grab it and delay showing the boot splash. The total time until boot is
- // finished may be increased by doing this, but a short boot with no feedback
- // feels worse than a longer boot that doesn't tell you anything.
- spi_device_acquire_bus(handle_, portMAX_DELAY);
- gpio_.SdMuxEnable(false);
-
// First byte of the data is the number of commands.
for (int i = *(data++); i > 0; i--) {
uint8_t command = *(data++);
@@ -249,9 +257,33 @@ void Display::SendInitialisationSequence(const uint8_t* data) {
vTaskDelay(pdMS_TO_TICKS(sleep_duration_ms));
}
}
+}
- gpio_.SdMuxEnable(true);
- spi_device_release_bus(handle_);
+void Display::WriteLeftPad(uint8_t* buffer) {
+ if (pad_ == 0) {
+ return;
+ }
+
+ uint16_t data1[2] = {0, 0};
+
+ // Select the left pad_ cols
+ data1[0] = SPI_SWAP_DATA_TX(0, 16);
+ data1[1] = SPI_SWAP_DATA_TX(pad_, 16);
+ SendCommandWithData(displays::ST77XX_CASET, reinterpret_cast<uint8_t*>(data1),
+ 4);
+
+ // Select all rows
+ data1[0] = SPI_SWAP_DATA_TX(0, 16);
+ data1[1] = SPI_SWAP_DATA_TX(128, 16);
+ SendCommandWithData(displays::ST77XX_RASET, reinterpret_cast<uint8_t*>(data1),
+ 4);
+
+ // Prep our beautiful zeroes.
+ size_t len = pad_ * 128 * 3;
+ std::memset(buffer, 0, len);
+
+ // Write our beautiful zeroes.
+ SendCommandWithData(displays::ST77XX_RAMWR, buffer, len);
}
IRAM_ATTR
@@ -309,8 +341,8 @@ void Display::OnLvglFlush(const lv_area_t* area, uint8_t* color_map) {
// First we need to specify the rectangle of the display we're writing into.
uint16_t data[2] = {0, 0};
- data[0] = SPI_SWAP_DATA_TX(area->x1, 16);
- data[1] = SPI_SWAP_DATA_TX(area->x2, 16);
+ data[0] = SPI_SWAP_DATA_TX(area->x1 + pad_, 16);
+ data[1] = SPI_SWAP_DATA_TX(area->x2 + pad_, 16);
SendCommandWithData(displays::ST77XX_CASET, reinterpret_cast<uint8_t*>(data),
4);
diff --git a/src/drivers/display_init.cpp b/src/drivers/display_init.cpp
index edd36a8d..62cd18dd 100644
--- a/src/drivers/display_init.cpp
+++ b/src/drivers/display_init.cpp
@@ -103,6 +103,7 @@ static const uint8_t kST7735RCommonFooter[]{
const InitialisationData kST7735R = {
.width = 160,
.height = 128,
+ .pad = 0,
.num_sequences = 3,
.sequences = {kST7735RCommonHeader, kST7735RCommonGreen,
kST7735RCommonFooter}};
diff --git a/src/drivers/include/drivers/display.hpp b/src/drivers/include/drivers/display.hpp
index e5001c48..88bb07c4 100644
--- a/src/drivers/include/drivers/display.hpp
+++ b/src/drivers/include/drivers/display.hpp
@@ -34,7 +34,7 @@ class Display {
static auto Create(IGpios& expander,
const displays::InitialisationData& init_data) -> Display*;
- Display(IGpios& gpio, spi_device_handle_t handle);
+ Display(IGpios& gpio, spi_device_handle_t handle, uint_fast8_t pad);
~Display();
auto SetDisplayOn(bool) -> void;
@@ -54,6 +54,7 @@ class Display {
bool first_flush_finished_;
bool display_on_;
uint_fast8_t brightness_;
+ uint_fast8_t pad_;
lv_display_t* display_ = nullptr;
@@ -63,6 +64,7 @@ class Display {
};
void SendInitialisationSequence(const uint8_t* data);
+ void WriteLeftPad(uint8_t *buffer);
void SendCommandWithData(uint8_t command, const uint8_t* data, size_t length);
diff --git a/src/drivers/include/drivers/display_init.hpp b/src/drivers/include/drivers/display_init.hpp
index 9bf5b3f5..6ccdb417 100644
--- a/src/drivers/include/drivers/display_init.hpp
+++ b/src/drivers/include/drivers/display_init.hpp
@@ -17,6 +17,7 @@ extern const uint8_t kDelayBit;
struct InitialisationData {
uint16_t width;
uint16_t height;
+ uint8_t pad;
uint8_t num_sequences;
const uint8_t* sequences[4];
};
diff --git a/src/drivers/include/drivers/nvs.hpp b/src/drivers/include/drivers/nvs.hpp
index 21d32f42..7ef1fbf7 100644
--- a/src/drivers/include/drivers/nvs.hpp
+++ b/src/drivers/include/drivers/nvs.hpp
@@ -93,6 +93,9 @@ class NvsStorage {
auto FastCharge() -> bool;
auto FastCharge(bool) -> void;
+ auto DisplayLeftPadding() -> uint8_t;
+ auto DisplayLeftPadding(uint8_t) -> void;
+
auto PreferredBluetoothDevice() -> std::optional<bluetooth::MacAndName>;
auto PreferredBluetoothDevice(std::optional<bluetooth::MacAndName>) -> void;
@@ -177,6 +180,7 @@ class NvsStorage {
Setting<uint8_t> lock_polarity_;
Setting<uint16_t> display_cols_;
Setting<uint16_t> display_rows_;
+ Setting<uint8_t> display_left_padding_;
Setting<uint8_t> haptic_motor_type_;
Setting<LraData> lra_calibration_;
Setting<uint8_t> fast_charge_;
diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp
index 3250e556..374c71d6 100644
--- a/src/drivers/nvs.cpp
+++ b/src/drivers/nvs.cpp
@@ -41,6 +41,7 @@ static constexpr char kKeyScrollSensitivity[] = "scroll";
static constexpr char kKeyLockPolarity[] = "lockpol";
static constexpr char kKeyDisplayCols[] = "dispcols";
static constexpr char kKeyDisplayRows[] = "disprows";
+static constexpr char kKeyDisplayLeftPadding[] = "displeftpad";
static constexpr char kKeyHapticMotorType[] = "hapticmtype";
static constexpr char kKeyLraCalibration[] = "lra_cali";
static constexpr char kKeyDbAutoIndex[] = "dbautoindex";
@@ -266,6 +267,7 @@ NvsStorage::NvsStorage(nvs_handle_t handle)
lock_polarity_(kKeyLockPolarity),
display_cols_(kKeyDisplayCols),
display_rows_(kKeyDisplayRows),
+ display_left_padding_(kKeyDisplayLeftPadding),
haptic_motor_type_(kKeyHapticMotorType),
lra_calibration_(kKeyLraCalibration),
fast_charge_(kKeyFastCharge),
@@ -297,6 +299,7 @@ auto NvsStorage::Read() -> void {
lock_polarity_.read(handle_);
display_cols_.read(handle_);
display_rows_.read(handle_);
+ display_left_padding_.read(handle_);
haptic_motor_type_.read(handle_);
lra_calibration_.read(handle_);
fast_charge_.read(handle_);
@@ -323,6 +326,7 @@ auto NvsStorage::Write() -> bool {
lock_polarity_.write(handle_);
display_cols_.write(handle_);
display_rows_.write(handle_);
+ display_left_padding_.write(handle_);
haptic_motor_type_.write(handle_);
lra_calibration_.write(handle_);
fast_charge_.write(handle_);
@@ -403,6 +407,16 @@ auto NvsStorage::DisplaySize(
display_rows_.set(std::move(size.second));
}
+auto NvsStorage::DisplayLeftPadding() -> uint8_t {
+ std::lock_guard<std::mutex> lock{mutex_};
+ return display_left_padding_.get().value_or(0);
+}
+
+auto NvsStorage::DisplayLeftPadding(uint8_t val) -> void {
+ std::lock_guard<std::mutex> lock{mutex_};
+ display_left_padding_.set(val);
+}
+
auto NvsStorage::PreferredBluetoothDevice()
-> std::optional<bluetooth::MacAndName> {
std::lock_guard<std::mutex> lock{mutex_};
diff --git a/src/tangara/ui/ui_fsm.cpp b/src/tangara/ui/ui_fsm.cpp
index ebc4b635..020917e2 100644
--- a/src/tangara/ui/ui_fsm.cpp
+++ b/src/tangara/ui/ui_fsm.cpp
@@ -352,10 +352,13 @@ void UiState::react(const internal::InitDisplay& ev) {
// HACK: correct the display size for our prototypes.
// ev.nvs.DisplaySize({161, 130});
+ // HACK: correct the display padding for batch 2.
+ // ev.nvs.DisplayLeftPadding(3);
auto actual_size = ev.nvs.DisplaySize();
init_data.width = actual_size.first.value_or(init_data.width);
init_data.height = actual_size.second.value_or(init_data.height);
+ init_data.pad = ev.nvs.DisplayLeftPadding();
sDisplay.reset(drivers::Display::Create(ev.gpios, init_data));
sCurrentScreen.reset(new screens::Splash());