summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/CMakeLists.txt2
-rw-r--r--src/drivers/display.cpp82
-rw-r--r--src/drivers/include/display.hpp3
3 files changed, 63 insertions, 24 deletions
diff --git a/src/drivers/CMakeLists.txt b/src/drivers/CMakeLists.txt
index 25fdc187..67dc0236 100644
--- a/src/drivers/CMakeLists.txt
+++ b/src/drivers/CMakeLists.txt
@@ -2,5 +2,5 @@ idf_component_register(
SRCS "touchwheel.cpp" "dac.cpp" "gpio_expander.cpp" "battery.cpp" "storage.cpp" "i2c.cpp"
"spi.cpp" "display.cpp" "display_init.cpp" "samd.cpp"
INCLUDE_DIRS "include"
- REQUIRES "esp_adc" "fatfs" "result" "lvgl" "span")
+ REQUIRES "esp_adc" "fatfs" "result" "lvgl" "span" "tasks")
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})
diff --git a/src/drivers/display.cpp b/src/drivers/display.cpp
index 2888903c..a8aeb935 100644
--- a/src/drivers/display.cpp
+++ b/src/drivers/display.cpp
@@ -21,6 +21,7 @@
#include "display_init.hpp"
#include "gpio_expander.hpp"
#include "soc/soc.h"
+#include "tasks.hpp"
static const char* kTag = "DISPLAY";
@@ -49,6 +50,19 @@ static const int kDisplayBufferSize = (kDisplayWidth * kDisplayHeight) / 10;
DMA_ATTR static lv_color_t sBuffer1[kDisplayBufferSize];
DMA_ATTR static lv_color_t sBuffer2[kDisplayBufferSize];
+struct RenderTaskArgs {
+ std::atomic<bool>* quit;
+ QueueHandle_t work_queue;
+};
+
+struct FlushArgs {
+ lv_disp_drv_t* driver;
+ const lv_area_t* area;
+ lv_color_t* color_map;
+};
+
+void RenderMain(void* raw_args);
+
namespace drivers {
/*
@@ -138,7 +152,9 @@ auto Display::Create(GpioExpander* expander,
}
Display::Display(GpioExpander* gpio, spi_device_handle_t handle)
- : gpio_(gpio), handle_(handle) {}
+ : gpio_(gpio),
+ handle_(handle),
+ worker_task_(tasks::Worker::Start<tasks::Type::kUiFlush>()) {}
Display::~Display() {}
@@ -225,31 +241,51 @@ void Display::SendTransaction(TransactionType type,
void Display::OnLvglFlush(lv_disp_drv_t* disp_drv,
const lv_area_t* area,
lv_color_t* color_map) {
- // Ideally we want to complete a single flush as quickly as possible, so grab
- // the bus for this entire transaction sequence.
- spi_device_acquire_bus(handle_, portMAX_DELAY);
-
- // 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);
- SendCommandWithData(displays::ST77XX_CASET, reinterpret_cast<uint8_t*>(data),
- 4);
-
- data[0] = SPI_SWAP_DATA_TX(area->y1, 16);
- data[1] = SPI_SWAP_DATA_TX(area->y2, 16);
- SendCommandWithData(displays::ST77XX_RASET, reinterpret_cast<uint8_t*>(data),
- 4);
+ // area is stack-allocated, so it isn't safe to reference from the flush
+ // thread.
+ lv_area_t area_copy = *area;
+ worker_task_->Dispatch<void>([=, this]() {
+ // Ideally we want to complete a single flush as quickly as possible, so
+ // grab the bus for this entire transaction sequence.
+ spi_device_acquire_bus(handle_, portMAX_DELAY);
+
+ // 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_copy.x1, 16);
+ data[1] = SPI_SWAP_DATA_TX(area_copy.x2, 16);
+ SendCommandWithData(displays::ST77XX_CASET,
+ reinterpret_cast<uint8_t*>(data), 4);
+
+ data[0] = SPI_SWAP_DATA_TX(area_copy.y1, 16);
+ data[1] = SPI_SWAP_DATA_TX(area_copy.y2, 16);
+ SendCommandWithData(displays::ST77XX_RASET,
+ reinterpret_cast<uint8_t*>(data), 4);
+
+ // Now send the pixels for this region.
+ uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
+ SendCommandWithData(displays::ST77XX_RAMWR,
+ reinterpret_cast<uint8_t*>(color_map), size * 2);
+
+ spi_device_release_bus(handle_);
+
+ lv_disp_flush_ready(&driver_);
+ });
+}
- // Now send the pixels for this region.
- uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
- SendCommandWithData(displays::ST77XX_RAMWR,
- reinterpret_cast<uint8_t*>(color_map), size * 2);
+void RenderMain(void* raw_args) {
+ RenderTaskArgs* args = reinterpret_cast<RenderTaskArgs*>(raw_args);
+ QueueHandle_t queue = args->work_queue;
+ std::atomic<bool>* quit = args->quit;
+ delete args;
- spi_device_release_bus(handle_);
+ while (!quit->load()) {
+ // TODO: flush data here! Yay speed.
+ }
- lv_disp_flush_ready(&driver_);
+ vQueueDelete(queue);
+ delete quit;
+ vTaskDelete(NULL);
}
} // namespace drivers
diff --git a/src/drivers/include/display.hpp b/src/drivers/include/display.hpp
index f8a28503..68ddf9fe 100644
--- a/src/drivers/include/display.hpp
+++ b/src/drivers/include/display.hpp
@@ -6,6 +6,7 @@
#include "driver/spi_master.h"
#include "lvgl/lvgl.h"
#include "result.hpp"
+#include "tasks.hpp"
#include "display_init.hpp"
#include "gpio_expander.hpp"
@@ -37,6 +38,8 @@ class Display {
GpioExpander* gpio_;
spi_device_handle_t handle_;
+ std::unique_ptr<tasks::Worker> worker_task_;
+
lv_disp_draw_buf_t buffers_;
lv_disp_drv_t driver_;
lv_disp_t* display_ = nullptr;