summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-09-05 15:36:33 +1000
committerjacqueline <me@jacqueline.id.au>2023-09-05 15:36:33 +1000
commitf0d82cfb0959c48e251246aa988989e1cfddc4af (patch)
treea2c6499aaaaf858d13454ebcb812eac52a03d7cd /src
parentb413b2f2641b0c7448762e9dc801f4ca7f00095c (diff)
downloadtangara-fw-f0d82cfb0959c48e251246aa988989e1cfddc4af.tar.gz
Fix display buffers not actually being in DMA ram
Diffstat (limited to 'src')
-rw-r--r--src/drivers/display.cpp48
-rw-r--r--src/drivers/include/display.hpp4
2 files changed, 30 insertions, 22 deletions
diff --git a/src/drivers/display.cpp b/src/drivers/display.cpp
index 7ab7b3e8..e261402d 100644
--- a/src/drivers/display.cpp
+++ b/src/drivers/display.cpp
@@ -31,6 +31,7 @@
#include "display_init.hpp"
#include "gpios.hpp"
+#include "misc/lv_color.h"
#include "soc/soc.h"
#include "tasks.hpp"
@@ -48,18 +49,11 @@ static const gpio_num_t kDisplayCs = GPIO_NUM_22;
/*
* The size of each of our two display buffers. This is fundamentally a balance
* between performance and memory usage. LVGL docs recommend a buffer 1/10th the
- * size of the screen is the best tradeoff, but we instead just use the max DMA
- * buffer size.
+ * size of the screen is the best tradeoff
* We use two buffers so that one can be flushed to the screen at the same time
* as the other is being drawn.
*/
-static const int kDisplayBufferSize = SPI_MAX_DMA_LEN;
-
-// Allocate both buffers in static memory to ensure that they're in DRAM, with
-// minimal fragmentation. We most cases we always need these buffers anyway, so
-// it's not a memory hit we can avoid.
-DMA_ATTR static lv_color_t sBuffer1[kDisplayBufferSize];
-DMA_ATTR static lv_color_t sBuffer2[kDisplayBufferSize];
+static const int kDisplayBufferSize = kDisplayWidth * kDisplayHeight / 10;
namespace drivers {
@@ -153,8 +147,8 @@ auto Display::Create(IGpios& expander,
// The hardware is now configured correctly. Next, initialise the LVGL display
// driver.
ESP_LOGI(kTag, "Init buffers");
- lv_disp_draw_buf_init(&display->buffers_, sBuffer1, sBuffer2,
- kDisplayBufferSize);
+ lv_disp_draw_buf_init(&display->buffers_, display->buffer1_,
+ display->buffer2_, kDisplayBufferSize);
lv_disp_drv_init(&display->driver_);
display->driver_.draw_buf = &display->buffers_;
display->driver_.hor_res = kDisplayWidth;
@@ -172,10 +166,21 @@ auto Display::Create(IGpios& expander,
}
Display::Display(IGpios& gpio, spi_device_handle_t handle)
- : gpio_(gpio), handle_(handle), display_on_(false), brightness_(0) {}
+ : gpio_(gpio), handle_(handle), display_on_(false), brightness_(0) {
+ transaction_ = reinterpret_cast<spi_transaction_t*>(
+ heap_caps_malloc(sizeof(spi_transaction_t), MALLOC_CAP_DMA));
+ memset(transaction_, 0, sizeof(spi_transaction_t));
+ buffer1_ = reinterpret_cast<lv_color_t*>(heap_caps_malloc(
+ kDisplayBufferSize * sizeof(lv_color_t), MALLOC_CAP_DMA));
+ buffer2_ = reinterpret_cast<lv_color_t*>(heap_caps_malloc(
+ kDisplayBufferSize * sizeof(lv_color_t), MALLOC_CAP_DMA));
+}
Display::~Display() {
ledc_fade_func_uninstall();
+ free(transaction_);
+ free(buffer1_);
+ free(buffer2_);
}
auto Display::SetDisplayOn(bool enabled) -> void {
@@ -257,29 +262,28 @@ void Display::SendTransaction(TransactionType type,
return;
}
- spi_transaction_t transaction;
- memset(&transaction, 0, sizeof(transaction));
+ memset(transaction_, 0, sizeof(spi_transaction_t));
- transaction.rx_buffer = NULL;
+ transaction_->rx_buffer = NULL;
// Length is in bits, so multiply by 8.
- transaction.length = length * 8;
- transaction.rxlength = 0; // Match `length` value.
+ transaction_->length = length * 8;
+ transaction_->rxlength = 0; // Match `length` value.
// If the data to transmit is very short, then we can fit it directly
// inside the transaction struct.
- if (transaction.length <= 32) {
- transaction.flags = SPI_TRANS_USE_TXDATA;
- std::memcpy(&transaction.tx_data, data, length);
+ if (transaction_->length <= 32) {
+ transaction_->flags = SPI_TRANS_USE_TXDATA;
+ std::memcpy(&transaction_->tx_data, data, length);
} else {
// Note: LVGL's buffers are in DMA-accessible memory, so whatever pointer
// it handed us should be DMA-accessible already. No need to copy.
- transaction.tx_buffer = data;
+ transaction_->tx_buffer = data;
}
gpio_set_level(kDisplayDr, type);
// TODO(jacqueline): Handle these errors.
- esp_err_t ret = spi_device_polling_transmit(handle_, &transaction);
+ esp_err_t ret = spi_device_polling_transmit(handle_, transaction_);
ESP_ERROR_CHECK(ret);
}
diff --git a/src/drivers/include/display.hpp b/src/drivers/include/display.hpp
index b0aa5d58..45cb67e4 100644
--- a/src/drivers/include/display.hpp
+++ b/src/drivers/include/display.hpp
@@ -51,11 +51,15 @@ class Display {
private:
IGpios& gpio_;
spi_device_handle_t handle_;
+ spi_transaction_t *transaction_;
bool display_on_;
uint_fast8_t brightness_;
lv_disp_draw_buf_t buffers_;
+ lv_color_t* buffer1_;
+ lv_color_t* buffer2_;
+
lv_disp_drv_t driver_;
lv_disp_t* display_ = nullptr;