Compare commits

..

3 Commits

Author SHA1 Message Date
8d8369440c Implement uploading custom waveform lut 2022-06-03 11:07:49 +02:00
6218cdfc51 Rename voltages to shorter names 2022-06-03 10:18:52 +02:00
51e2f5097d Tune software spi frequency 2022-06-02 23:15:22 +02:00
3 changed files with 52 additions and 16 deletions

View File

@@ -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);

View File

@@ -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()
{

View File

@@ -7,10 +7,10 @@ namespace eink {
// [SOURCE]_[VCOM]
enum class Voltage : std::uint8_t {
VSS_DCVCOM = 0b00,
VSH1_VSH1DCVCOM = 0b01,
VSL_VSLDCVCOM = 0b10,
VSH2_NA = 0b11,
VSS1 = 0b00,
VSH1 = 0b01,
VSL1 = 0b10,
VSH2 = 0b11,
};
struct [[gnu::packed]] Phases