Files
cardboy/Firmware/main/include/display.hpp
2025-10-07 01:14:38 +02:00

86 lines
2.3 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"
#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;
DMA_ATTR extern uint8_t dma_buf[SMD::kLineDataBytes];
void init();
void clear();
void draw();
// Asynchronous (DMA queued) draw API
void draw_async_start(); // queue frame transfer if none in flight
void draw_async_wait(); // wait for any in-flight transfer to finish
bool draw_async_busy(); // true if a transfer is 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;
}
}
static inline spi_device_interface_config_t _devcfg = {
.mode = 0, // SPI mode 0
.clock_speed_hz = 2 * 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 = lcd_spi_pre_transfer_callback, //Specify pre-transfer callback to handle D/C line
};
extern spi_device_handle_t _spi;
extern bool _vcom;
extern bool _inFlight;
extern spi_transaction_t _tx; // persistent transaction struct for async API
}; // 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