Implement multi-channel run length encoded images in flash memory

This commit is contained in:
BlackMark 2022-05-29 18:45:46 +02:00
parent 75046d1c1a
commit 83a064ddc1

View File

@ -1,7 +1,9 @@
#pragma once #pragma once
#include <utility> #include <tuple>
#include <type_traits>
#include <cstddef>
#include <cstdint> #include <cstdint>
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
@ -146,41 +148,35 @@ class Eink {
_delay_ms(200); _delay_ms(200);
} }
template <typename Image> template <typename RleImage>
static void draw(const Image &image) static void draw(const RleImage &rleImage)
{ {
constexpr auto lookup = [](std::uint8_t bits) { constexpr auto pgm_load = [](const auto &object) {
auto block = ImageBlock{}; using object_t = std::remove_cvref_t<decltype(object)>;
util::for_constexpr( auto buffer = object_t{};
[&](const auto idx) { auto rawBuffer = reinterpret_cast<std::byte *>(&buffer);
block[idx.value] = static_cast<Color>(bits % 3); for (auto i = std::size_t{0}; i < sizeof(object_t); ++i) {
bits /= 3; rawBuffer[i] = static_cast<std::byte>(pgm_read_byte(&reinterpret_cast<const std::byte *>(&object)[i]));
}, }
std::make_index_sequence<BLOCK_SIZE>{}); return buffer;
return block;
}; };
constexpr auto sendImageChannel = [lookup](const auto command, const auto image) { constexpr auto sendImageChannel = [pgm_load](const auto command, const auto &image) {
sendCommand(command); sendCommand(command);
auto buffer = std::uint8_t{0}; for (auto j = std::size_t{0}; j < image.size(); ++j) {
auto bufferPos = std::uint8_t{0}; const auto [count, data] = pgm_load(image[j]);
for (auto i = std::uint16_t{0}; i < Width * Height / BLOCK_SIZE; i++) { for (auto i = std::uint16_t{0}; i < count; ++i) {
const auto block = lookup(pgm_read_byte(&image[i])); if (command == Cmd::WRITE_RAM_BLACK) {
for (auto p = std::uint8_t{0}; p < BLOCK_SIZE; ++p) { sendData(data);
const auto pixel = std::uint8_t{(command == Cmd::WRITE_RAM_BLACK) ? (block[p] != Color::BLACK) } else {
: (block[p] == Color::RED)}; sendData(~data);
buffer |= pixel << (7 - bufferPos++);
if (bufferPos == 8) {
sendData(buffer);
buffer = 0;
bufferPos = 0;
} }
} }
} }
}; };
sendImageChannel(Cmd::WRITE_RAM_BLACK, image.data()); sendImageChannel(Cmd::WRITE_RAM_BLACK, std::get<0>(rleImage));
sendImageChannel(Cmd::WRITE_RAM_RED, image.data()); sendImageChannel(Cmd::WRITE_RAM_RED, std::get<1>(rleImage));
sendCommand(Cmd::DISPLAY_UPDATE_CONTROL_2); sendCommand(Cmd::DISPLAY_UPDATE_CONTROL_2);
sendData(0xF7); sendData(0xF7);