Compare commits
3 Commits
91b49cd536
...
8d8369440c
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d8369440c | |||
| 6218cdfc51 | |||
| 51e2f5097d |
28
eink.hpp
28
eink.hpp
@@ -21,6 +21,9 @@ template <std::uint16_t Width, std::uint16_t Height, typename Spi, io::P RstPin,
|
||||
class Eink {
|
||||
using word_t = typename Spi::word_t;
|
||||
|
||||
struct original_lut_tag {
|
||||
};
|
||||
|
||||
static io::Pin<RstPin> m_rst;
|
||||
static io::Pin<BusyPin> m_busy;
|
||||
|
||||
@@ -37,6 +40,7 @@ class Eink {
|
||||
WRITE_RAM_RED = 0x26,
|
||||
READ_RAM = 0x27,
|
||||
LOAD_OTP_TO_RAM = 0x31,
|
||||
WRITE_LUT = 0x32,
|
||||
BORDER_WAVEFORM_CONTROL = 0x3C,
|
||||
READ_RAM_CHANNEL = 0x41,
|
||||
SET_RAM_X_ADDR_POSITIONS = 0x44,
|
||||
@@ -141,6 +145,17 @@ class Eink {
|
||||
template <typename RleImage>
|
||||
static void draw(const RleImage &rleImage)
|
||||
{
|
||||
draw(rleImage, original_lut_tag{});
|
||||
}
|
||||
|
||||
template <typename RleImage, typename Lut = original_lut_tag>
|
||||
static void draw(const RleImage &rleImage, const Lut &lut)
|
||||
{
|
||||
constexpr auto USE_ORIGINAL_LUT = std::is_same_v<Lut, original_lut_tag>;
|
||||
if constexpr (!USE_ORIGINAL_LUT) {
|
||||
writeLut(lut);
|
||||
}
|
||||
|
||||
constexpr auto sendImageChannel = [](const auto command, const auto &image) {
|
||||
sendCommand(command);
|
||||
for (auto j = std::size_t{0}; j < image.size(); ++j) {
|
||||
@@ -159,7 +174,7 @@ class Eink {
|
||||
sendImageChannel(Cmd::WRITE_RAM_RED, std::get<1>(rleImage));
|
||||
|
||||
sendCommand(Cmd::DISPLAY_UPDATE_CONTROL_2);
|
||||
sendData(0xF7);
|
||||
sendData(USE_ORIGINAL_LUT ? 0xF7 : 0xC7);
|
||||
sendCommand(Cmd::UPDATE_DISPLAY);
|
||||
waitUntilIdle();
|
||||
}
|
||||
@@ -195,6 +210,17 @@ class Eink {
|
||||
waitUntilIdle();
|
||||
}
|
||||
|
||||
static void writeLut(const Waveform &lut)
|
||||
{
|
||||
const auto flashLutPtr = reinterpret_cast<const std::byte *>(&lut);
|
||||
|
||||
sendCommand(Cmd::WRITE_LUT);
|
||||
for (auto i = std::size_t{0}; i < sizeof(lut); ++i) {
|
||||
const auto lutByte = flash::load(flashLutPtr[i]);
|
||||
sendData(static_cast<word_t>(lutByte));
|
||||
}
|
||||
}
|
||||
|
||||
static void autoPatternFill()
|
||||
{
|
||||
constexpr auto RED_PATTERN_FILL_CMD = static_cast<Cmd>(0x46);
|
||||
|
||||
32
eink_spi.hpp
32
eink_spi.hpp
@@ -15,17 +15,26 @@ namespace eink {
|
||||
|
||||
template <io::P SclPin, io::P SdaPin, io::P CsPin, io::P DcPin, std::uint32_t Freq = 100'000>
|
||||
class Spi {
|
||||
template <std::uint32_t StaticClockCycles>
|
||||
static constexpr double calcClockDelay()
|
||||
{
|
||||
// TODO: Verify static clock cycles
|
||||
constexpr auto staticClockCycles = 10;
|
||||
constexpr auto maxFrequency = F_CPU / staticClockCycles;
|
||||
constexpr auto maxFrequency = F_CPU / StaticClockCycles;
|
||||
static_assert(Freq <= maxFrequency, "SPI frequency not achievable using selected clock speed");
|
||||
constexpr auto staticDelay = (1.0 * 1000 * 1000 / maxFrequency);
|
||||
const auto delayUs = ((1.0 * 1000 * 1000 / Freq) - staticDelay) / 2;
|
||||
return (delayUs > 0 ? delayUs : 0);
|
||||
}
|
||||
|
||||
static constexpr double calcWriteClockDelay()
|
||||
{
|
||||
return calcClockDelay<8>();
|
||||
}
|
||||
|
||||
static constexpr double calcReadClockDelay()
|
||||
{
|
||||
return calcClockDelay<5>();
|
||||
}
|
||||
|
||||
static constexpr auto THREE_WIRE_SPI = (DcPin == io::P::NONE);
|
||||
|
||||
public:
|
||||
@@ -42,7 +51,7 @@ class Spi {
|
||||
sm_dc.dir(io::Dir::OUT);
|
||||
}
|
||||
|
||||
static void write(const word_t data, const bool command = true)
|
||||
static void write(word_t data, const bool command = true)
|
||||
{
|
||||
constexpr auto numBits = THREE_WIRE_SPI ? 9 : 8;
|
||||
|
||||
@@ -66,10 +75,10 @@ class Spi {
|
||||
|
||||
sm_sda = data >> bitPos & 1;
|
||||
|
||||
_delay_us(DELAY_US);
|
||||
_delay_us(WRITE_DELAY_US);
|
||||
sm_scl.toggle();
|
||||
|
||||
_delay_us(DELAY_US);
|
||||
_delay_us(WRITE_DELAY_US);
|
||||
sm_scl.toggle();
|
||||
},
|
||||
std::make_index_sequence<numBits>{});
|
||||
@@ -85,9 +94,9 @@ class Spi {
|
||||
|
||||
if constexpr (THREE_WIRE_SPI) {
|
||||
sm_sda = true;
|
||||
_delay_us(DELAY_US);
|
||||
_delay_us(READ_DELAY_US);
|
||||
sm_scl.toggle();
|
||||
_delay_us(DELAY_US);
|
||||
_delay_us(READ_DELAY_US);
|
||||
sm_scl.toggle();
|
||||
}
|
||||
|
||||
@@ -102,13 +111,13 @@ class Spi {
|
||||
[&](const auto idx) {
|
||||
constexpr auto bitPos = numBits - idx.value - 1;
|
||||
|
||||
_delay_us(DELAY_US);
|
||||
_delay_us(READ_DELAY_US);
|
||||
sm_scl.toggle();
|
||||
|
||||
const auto receivedBit = sm_sda.read();
|
||||
res |= word_t{receivedBit} << bitPos;
|
||||
|
||||
_delay_us(DELAY_US);
|
||||
_delay_us(READ_DELAY_US);
|
||||
sm_scl.toggle();
|
||||
},
|
||||
std::make_index_sequence<numBits>{});
|
||||
@@ -129,7 +138,8 @@ class Spi {
|
||||
static io::Pin<CsPin> sm_cs;
|
||||
static io::Pin<DcPin> sm_dc;
|
||||
|
||||
static constexpr auto DELAY_US = calcClockDelay();
|
||||
static constexpr auto WRITE_DELAY_US = calcWriteClockDelay();
|
||||
static constexpr auto READ_DELAY_US = calcReadClockDelay();
|
||||
|
||||
static inline std::uint8_t disableInterrupts()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user