// // Created by Stepan Usatiuk on 02.03.2025. // #ifndef CB_DISPLAY_HPP #define CB_DISPLAY_HPP #include "config.hpp" #include "driver/spi_master.h" // (Async memcpy removed for debugging simplification) #include #include namespace SMD { static constexpr size_t kLineBytes = DISP_WIDTH / 8; static constexpr size_t kLineMultiSingle = (kLineBytes + 2); static constexpr size_t kLineDataBytes = kLineMultiSingle * DISP_HEIGHT + 2; extern uint8_t* dma_buf; void init(); // Double-buffered asynchronous frame pipeline: // Usage pattern each frame: // SMD::frame_ready(); // (start of frame) waits for previous transfer & ensures draw buffer is ready/synced // ... write pixels into dma_buf via set_pixel / surface ... // SMD::send_frame(); // (end of frame) queues SPI DMA of current framebuffer; once SPI finishes the sent buffer // // is optionally cleared so the alternate buffer is ready for the next frame void send_frame(bool clear_after_send = true); void frame_ready(); bool frame_transfer_in_flight(); // optional diagnostic: is a frame transfer still in flight? __attribute__((always_inline)) static void set_pixel(int x, int y, bool value) { assert(x >= 0 && x < DISP_WIDTH && y >= 0 && y < DISP_HEIGHT); unsigned lineIdx = 2 + kLineMultiSingle * y + (x / 8); unsigned bitIdx = 1 << (7 - (x % 8)) % 8; if (value) { dma_buf[lineIdx] &= ~bitIdx; } else { dma_buf[lineIdx] |= bitIdx; } } extern "C" void s_spi_post_cb(spi_transaction_t* trans); static inline spi_device_interface_config_t _devcfg = { .mode = 0, // SPI mode 0 .clock_speed_hz = 10 * 1000 * 1000, // Clock out at 10 MHz .spics_io_num = SPI_DISP_CS, // CS pin .flags = SPI_DEVICE_POSITIVE_CS, .queue_size = 1, .pre_cb = nullptr, .post_cb = s_spi_post_cb, }; extern spi_device_handle_t _spi; }; // namespace SMD #endif // DISPLAY_HPP