From 83a064ddc1156b4d66ff8551b7c639b6432f9dd8 Mon Sep 17 00:00:00 2001 From: BlackMark Date: Sun, 29 May 2022 18:45:46 +0200 Subject: [PATCH] Implement multi-channel run length encoded images in flash memory --- eink.hpp | 50 +++++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/eink.hpp b/eink.hpp index ce5f3e3..111de6f 100644 --- a/eink.hpp +++ b/eink.hpp @@ -1,7 +1,9 @@ #pragma once -#include +#include +#include +#include #include #include @@ -146,41 +148,35 @@ class Eink { _delay_ms(200); } - template - static void draw(const Image &image) + template + static void draw(const RleImage &rleImage) { - constexpr auto lookup = [](std::uint8_t bits) { - auto block = ImageBlock{}; - util::for_constexpr( - [&](const auto idx) { - block[idx.value] = static_cast(bits % 3); - bits /= 3; - }, - std::make_index_sequence{}); - return block; + constexpr auto pgm_load = [](const auto &object) { + using object_t = std::remove_cvref_t; + auto buffer = object_t{}; + auto rawBuffer = reinterpret_cast(&buffer); + for (auto i = std::size_t{0}; i < sizeof(object_t); ++i) { + rawBuffer[i] = static_cast(pgm_read_byte(&reinterpret_cast(&object)[i])); + } + return buffer; }; - constexpr auto sendImageChannel = [lookup](const auto command, const auto image) { + constexpr auto sendImageChannel = [pgm_load](const auto command, const auto &image) { sendCommand(command); - auto buffer = std::uint8_t{0}; - auto bufferPos = std::uint8_t{0}; - for (auto i = std::uint16_t{0}; i < Width * Height / BLOCK_SIZE; i++) { - const auto block = lookup(pgm_read_byte(&image[i])); - for (auto p = std::uint8_t{0}; p < BLOCK_SIZE; ++p) { - const auto pixel = std::uint8_t{(command == Cmd::WRITE_RAM_BLACK) ? (block[p] != Color::BLACK) - : (block[p] == Color::RED)}; - buffer |= pixel << (7 - bufferPos++); - if (bufferPos == 8) { - sendData(buffer); - buffer = 0; - bufferPos = 0; + for (auto j = std::size_t{0}; j < image.size(); ++j) { + const auto [count, data] = pgm_load(image[j]); + for (auto i = std::uint16_t{0}; i < count; ++i) { + if (command == Cmd::WRITE_RAM_BLACK) { + sendData(data); + } else { + sendData(~data); } } } }; - sendImageChannel(Cmd::WRITE_RAM_BLACK, image.data()); - sendImageChannel(Cmd::WRITE_RAM_RED, image.data()); + sendImageChannel(Cmd::WRITE_RAM_BLACK, std::get<0>(rleImage)); + sendImageChannel(Cmd::WRITE_RAM_RED, std::get<1>(rleImage)); sendCommand(Cmd::DISPLAY_UPDATE_CONTROL_2); sendData(0xF7);