18extern "C" auto stbi_write_png(
char const *filename,
int w,
int h,
int comp,
const void *data,
int stride_in_bytes)
55 bool save_images =
true) noexcept
56 : spi_(device.get_spi()), cs_(device.get_output(
Pin{0})),
57 dc_(device.get_output(
Pin{1})),
58 rst_(device.get_output(
Pin{2})),
59 busy_(device.get_input(
Pin{3})),
61 output_dir_(
"mock_outputs") {
63 std::filesystem::create_directories(output_dir_);
72 if (init_should_fail_) {
81 [[nodiscard]]
auto clear() -> std::expected<void, Error> {
89 [[nodiscard]]
auto display(std::span<const std::byte> buffer) -> std::expected<void, Error> {
94 if (display_should_fail_) {
100 if (
auto result =
wake(); !result) {
106 last_buffer_ = std::vector<std::byte>(buffer.begin(), buffer.end());
110 save_buffer_as_png(buffer);
116 [[nodiscard]]
auto display_planes(std::span<
const std::span<const std::byte>> planes) -> std::expected<void, Error> {
117 if (planes.empty()) {
121 if (planes.size() == 1) {
127 std::vector<std::byte> combined_buffer;
129 std::size_t total_size = 0;
130 for (
const auto &plane : planes) {
131 total_size += plane.size();
133 combined_buffer.reserve(total_size);
135 for (
const auto &plane : planes) {
136 combined_buffer.insert(combined_buffer.end(), plane.begin(), plane.end());
139 return display(combined_buffer);
143 [[nodiscard]]
auto sleep() -> std::expected<void, Error> {
145 if (sleep_should_fail_) {
152 [[nodiscard]]
auto wake() -> std::expected<void, Error> {
154 if (wake_should_fail_) {
161 [[nodiscard]]
auto power_off() -> std::expected<void, Error> {
166 [[nodiscard]]
auto power_on() -> std::expected<void, Error> {
172 [[nodiscard]]
auto width() const noexcept -> std::
size_t {
return width_; }
174 [[nodiscard]]
auto height() const noexcept -> std::
size_t {
return height_; }
180 return (width_ * height_ * bpp + 7) / 8;
199 [[nodiscard]]
auto init_called() const noexcept ->
bool {
return init_count_ > 0; }
201 [[nodiscard]]
auto display_called() const noexcept ->
bool {
return display_count_ > 0; }
203 [[nodiscard]]
auto sleep_called() const noexcept ->
bool {
return sleep_count_ > 0; }
205 [[nodiscard]]
auto wake_called() const noexcept ->
bool {
return wake_count_ > 0; }
207 [[nodiscard]]
auto clear_called() const noexcept ->
bool {
return clear_count_ > 0; }
209 [[nodiscard]]
auto init_count() const noexcept -> std::
size_t {
return init_count_; }
211 [[nodiscard]]
auto display_count() const noexcept -> std::
size_t {
return display_count_; }
213 [[nodiscard]]
auto sleep_count() const noexcept -> std::
size_t {
return sleep_count_; }
215 [[nodiscard]]
auto wake_count() const noexcept -> std::
size_t {
return wake_count_; }
217 [[nodiscard]]
auto clear_count() const noexcept -> std::
size_t {
return clear_count_; }
219 [[nodiscard]]
auto is_asleep() const noexcept ->
bool {
return is_asleep_; }
221 [[nodiscard]]
auto is_initialized() const noexcept ->
bool {
return initialized_; }
223 [[nodiscard]]
auto last_buffer() const noexcept -> const std::vector<std::
byte> & {
return last_buffer_; }
236 std::filesystem::create_directories(output_dir_);
243 auto save_buffer_as_png(std::span<const std::byte> buffer)
const ->
void {
245 std::filesystem::create_directories(output_dir_);
248 const auto now = std::chrono::system_clock::now();
249 const auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
250 const auto filename = std::format(
"{}/frame_{:013d}.png", output_dir_, timestamp);
253 auto render_width = width_;
254 auto render_height = height_;
256 if (!buffer.empty() && height_ > 0) {
257 const auto bytes_per_row = buffer.size() / height_;
259 if (mode_bpp == 1 && bytes_per_row * height_ == buffer.size()) {
260 render_width = bytes_per_row * 8;
262 if (mode_bpp == 2 && bytes_per_row * height_ == buffer.size()) {
263 render_width = bytes_per_row * 4;
266 std::vector<std::uint8_t> rgb_data;
267 rgb_data.reserve(render_width * render_height * 3);
269 for (std::size_t y = 0; y < render_height; ++y) {
270 for (std::size_t x = 0; x < render_width; ++x) {
273 rgb_data.push_back(rgb.r);
274 rgb_data.push_back(rgb.g);
275 rgb_data.push_back(rgb.b);
280 stbi_write_png(filename.c_str(),
static_cast<int>(render_width),
static_cast<int>(render_height), 3,
281 rgb_data.data(),
static_cast<int>(render_width * 3));
286 Device::HalOutput cs_;
287 Device::HalOutput dc_;
288 Device::HalOutput rst_;
289 Device::HalInput busy_;
299 bool init_should_fail_{};
300 bool display_should_fail_{};
301 bool sleep_should_fail_{};
302 bool wake_should_fail_{};
305 std::size_t init_count_{};
306 std::size_t display_count_{};
307 std::size_t sleep_count_{};
308 std::size_t wake_count_{};
309 std::size_t clear_count_{};
312 std::vector<std::byte> last_buffer_;
316 std::string output_dir_;
321 static constexpr bool supports_grayscale =
true;
322 static constexpr bool supports_partial_refresh =
true;
323 static constexpr bool supports_power_control =
true;
324 static constexpr bool supports_wake_from_sleep =
true;
325 static constexpr std::size_t max_width = 800;
326 static constexpr std::size_t max_height = 600;
Compile-time driver capability traits system.
Definition device.hpp:158
Definition mock_driver.hpp:44
auto init_count() const noexcept -> std::size_t
Definition mock_driver.hpp:209
auto clear_called() const noexcept -> bool
Definition mock_driver.hpp:207
auto is_asleep() const noexcept -> bool
Definition mock_driver.hpp:219
auto display_planes(std::span< const std::span< const std::byte > > planes) -> std::expected< void, Error >
Definition mock_driver.hpp:116
auto is_initialized() const noexcept -> bool
Definition mock_driver.hpp:221
auto wake_called() const noexcept -> bool
Definition mock_driver.hpp:205
auto wake_count() const noexcept -> std::size_t
Definition mock_driver.hpp:215
auto sleep_called() const noexcept -> bool
Definition mock_driver.hpp:203
auto init_called() const noexcept -> bool
Definition mock_driver.hpp:199
auto display_count() const noexcept -> std::size_t
Definition mock_driver.hpp:211
auto power_off() -> std::expected< void, Error >
Definition mock_driver.hpp:161
auto clear() -> std::expected< void, Error >
Definition mock_driver.hpp:81
auto configure_wake_failure(bool should_fail) noexcept -> void
Definition mock_driver.hpp:196
auto supports_partial_refresh() const noexcept -> bool
Definition mock_driver.hpp:183
auto init(DisplayMode mode) -> std::expected< void, Error >
Definition mock_driver.hpp:70
auto display_called() const noexcept -> bool
Definition mock_driver.hpp:201
auto power_on() -> std::expected< void, Error >
Definition mock_driver.hpp:166
auto clear_count() const noexcept -> std::size_t
Definition mock_driver.hpp:217
auto configure_display_failure(bool should_fail) noexcept -> void
Definition mock_driver.hpp:192
auto display(std::span< const std::byte > buffer) -> std::expected< void, Error >
Definition mock_driver.hpp:89
auto height() const noexcept -> std::size_t
Definition mock_driver.hpp:174
auto reset_counts() noexcept -> void
Definition mock_driver.hpp:225
auto mode() const noexcept -> DisplayMode
Definition mock_driver.hpp:176
auto set_output_directory(std::string_view dir) -> void
Definition mock_driver.hpp:233
auto wake() -> std::expected< void, Error >
Definition mock_driver.hpp:152
auto configure_init_failure(bool should_fail) noexcept -> void
Definition mock_driver.hpp:190
auto width() const noexcept -> std::size_t
Definition mock_driver.hpp:172
MockDriver(Device &device, std::size_t width=600, std::size_t height=300, bool save_images=true) noexcept
Construct MockDriver using Linux Device with custom dimensions.
Definition mock_driver.hpp:54
auto buffer_size() const noexcept -> std::size_t
Definition mock_driver.hpp:178
auto sleep_count() const noexcept -> std::size_t
Definition mock_driver.hpp:213
auto supports_wake() const noexcept -> bool
Definition mock_driver.hpp:187
auto enable_image_saving(bool enable) -> void
Definition mock_driver.hpp:240
auto sleep() -> std::expected< void, Error >
Definition mock_driver.hpp:143
auto supports_power_control() const noexcept -> bool
Definition mock_driver.hpp:185
auto last_buffer() const noexcept -> const std::vector< std::byte > &
Definition mock_driver.hpp:223
auto configure_sleep_failure(bool should_fail) noexcept -> void
Definition mock_driver.hpp:194
auto stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes) -> int
@ DriverNotInitialized
Driver has not been initialized.
@ InvalidDimensions
Invalid image dimensions.
@ DriverInitFailed
Driver initialization failed.
@ TransferFailed
SPI/data transfer failed.
@ RefreshFailed
Display refresh operation failed.
constexpr auto bits_per_pixel(DisplayMode mode) noexcept -> std::uint8_t
Get bits per pixel for a display mode.
Definition driver.hpp:60
constexpr auto color_to_rgb(Color color) noexcept -> RGB
Convert a Color enum to RGB values.
Definition pixel_codec.hpp:154
DisplayMode
Definition driver.hpp:46
@ Spectra6
6-color: Black, White, Red, Yellow, Blue, Green (3-bit)
@ BlackWhite
1-bit black and white (2 colors)
auto get_pixel_from_buffer(DisplayMode mode, std::span< const std::byte > buffer, std::size_t width, std::size_t height, std::size_t x, std::size_t y) noexcept -> Color
Read a pixel from a buffer based on display mode.
Definition pixel_codec.hpp:569
Centralized pixel encoding/decoding utilities for framebuffers.
Definition errors.hpp:140
Driver capabilities trait template.
Definition capabilities.hpp:110