diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/drivers/display.cpp | 82 | ||||
| -rw-r--r-- | src/drivers/include/display.hpp | 3 |
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; |
