Files
cardboy/Firmware/main/include/display.hpp
2025-10-11 11:15:39 +02:00

63 lines
2.0 KiB
C++

//
// 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 <array>
#include <bitset>
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