#pragma once #include "cardboy/sdk/display_spec.hpp" #include "cardboy/sdk/platform.hpp" #include "config.hpp" #include #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" class PlatformFramebuffer final : public cardboy::sdk::FramebufferFacade { public: [[nodiscard]] int width_impl() const { return cardboy::sdk::kDisplayWidth; } [[nodiscard]] int height_impl() const { return cardboy::sdk::kDisplayHeight; } __attribute__((always_inline)) void drawPixel_impl(int x, int y, bool on) { if (x < 0 || y < 0 || x >= width() || y >= height()) return; SMD::set_pixel(x, y, on); } void clear_impl(bool on) { for (int y = 0; y < height(); ++y) for (int x = 0; x < width(); ++x) SMD::set_pixel(x, y, on); } __attribute__((always_inline)) void frameReady_impl() { SMD::frame_ready(); } __attribute__((always_inline)) void sendFrame_impl(bool clear) { SMD::send_frame(clear); } __attribute__((always_inline)) [[nodiscard]] bool frameInFlight_impl() const { return SMD::frame_transfer_in_flight(); } }; class PlatformInput final : public cardboy::sdk::InputFacade { public: cardboy::sdk::InputState readState_impl() { cardboy::sdk::InputState state{}; const uint8_t pressed = Buttons::get().get_pressed(); if (pressed & BTN_UP) state.up = true; if (pressed & BTN_LEFT) state.left = true; if (pressed & BTN_RIGHT) state.right = true; if (pressed & BTN_DOWN) state.down = true; if (pressed & BTN_A) state.a = true; if (pressed & BTN_B) state.b = true; if (pressed & BTN_SELECT) state.select = true; if (pressed & BTN_START) state.start = true; return state; } }; class PlatformClock final : public cardboy::sdk::ClockFacade { public: std::uint32_t millis_impl() { TickType_t ticks = xTaskGetTickCount(); return static_cast((static_cast(ticks) * 1000ULL) / configTICK_RATE_HZ); } void sleep_ms_impl(std::uint32_t ms) { if (ms == 0) return; PowerHelper::get().delay(static_cast(ms), static_cast(ms)); } };