mirror of
https://github.com/usatiuk/cardboy.git
synced 2025-10-28 23:27:49 +01:00
91 lines
2.6 KiB
C++
91 lines
2.6 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>
|
|
|
|
#include "Surface.hpp"
|
|
#include "Window.hpp"
|
|
|
|
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[SMD::kLineDataBytes];
|
|
|
|
void init();
|
|
// Simplified asynchronous frame pipeline:
|
|
// Usage pattern each frame:
|
|
// SMD::async_draw_wait(); // (start of frame) waits for previous transfer+clear & guarantees pixel area is zeroed
|
|
// ... write pixels into dma_buf via set_pixel / surface ...
|
|
// SMD::async_draw_start(); // (end of frame) queues SPI DMA of current framebuffer; when DMA completes it triggers
|
|
// // a background clear of pixel bytes for next frame
|
|
void async_draw_start();
|
|
void async_draw_wait();
|
|
bool async_draw_busy(); // optional diagnostic: is a frame transfer still in flight?
|
|
|
|
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 = 6 * 1000 * 1000, // Clock out at 10 MHz
|
|
.spics_io_num = SPI_DISP_CS, // CS pin
|
|
.flags = SPI_DEVICE_POSITIVE_CS,
|
|
.queue_size = 3,
|
|
.pre_cb = nullptr,
|
|
.post_cb = s_spi_post_cb,
|
|
};
|
|
extern spi_device_handle_t _spi;
|
|
void ensure_clear_task(); // idempotent; called from init
|
|
}; // namespace SMD
|
|
|
|
class SMDSurface : public Surface<SMDSurface, BwPixel>, public StandardEventQueue<SMDSurface> {
|
|
public:
|
|
using PixelType = BwPixel;
|
|
|
|
SMDSurface(EventLoop* loop);
|
|
|
|
~SMDSurface() override;
|
|
|
|
void draw_pixel_impl(unsigned x, unsigned y, const BwPixel& pixel);
|
|
|
|
void clear_impl();
|
|
|
|
int get_width_impl() const;
|
|
|
|
int get_height_impl() const;
|
|
|
|
template<typename T>
|
|
EventHandlingResult handle(const T& event) {
|
|
return _window->handle(event);
|
|
}
|
|
|
|
EventHandlingResult handle(SurfaceResizeEvent event);
|
|
};
|
|
|
|
|
|
#endif // DISPLAY_HPP
|