From c8d1093faab4f219437ae3c2f93a6dbdce5c1a73 Mon Sep 17 00:00:00 2001 From: Archie Hilton Date: Sun, 7 Jul 2024 21:18:03 +0100 Subject: [PATCH] Add i2c update function with some stop bit shenanigans --- src/framebuffer.hh | 25 ++++++++++++++++++------- src/main.cc | 21 ++++++++++++++++----- src/main.hh | 2 +- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/framebuffer.hh b/src/framebuffer.hh index 199c645..273273b 100644 --- a/src/framebuffer.hh +++ b/src/framebuffer.hh @@ -3,7 +3,9 @@ #include #include +#include #include +#include namespace Framebuffer { class FramebufferListener { @@ -26,20 +28,29 @@ namespace Framebuffer { static constexpr size_t ROWS = (FB_HEIGHT/ROW_HEIGHT); static constexpr size_t SIZE = FB_WIDTH * ROWS; std::array m_buffer; - FramebufferListener &m_listener; + std::function)> m_listener_update; void update_listener() { - m_listener.update(0, 0, m_buffer.data(), m_buffer.size()); + m_listener_update(m_buffer); } public: - Framebuffer(FramebufferListener &listener) - : m_listener(listener) { + Framebuffer(std::function)> f) + : m_listener_update(f) { } - void fill(uint8_t val) { FrameBufferBase::fill(m_buffer.data(), m_buffer.size(), val); } - void putc(size_t x, size_t y, char c) { FrameBufferBase::putc(m_buffer.data(), ROW_HEIGHT, m_buffer.size(), x, y, c); } - void puts(size_t x, size_t y, const char *s) { FrameBufferBase::putc(m_buffer.data(), ROW_HEIGHT, m_buffer.size(), x, y, s); } + void fill(uint8_t val) { + FrameBufferBase::fill(m_buffer.data(), m_buffer.size(), val); + update_listener(); + } + void putc(size_t x, size_t y, char c) { + FrameBufferBase::putc(m_buffer.data(), ROW_HEIGHT, m_buffer.size(), x, y, c); + update_listener(); + } + void puts(size_t x, size_t y, const char *s) { + FrameBufferBase::putc(m_buffer.data(), ROW_HEIGHT, m_buffer.size(), x, y, s); + update_listener(); + } uint8_t *data() { return m_buffer.data(); } size_t size() { return m_buffer.size(); } }; diff --git a/src/main.cc b/src/main.cc index 78ecc74..2a20dfb 100644 --- a/src/main.cc +++ b/src/main.cc @@ -3,6 +3,7 @@ #include "hardware/gpio.h" #include "hardware/i2c.h" +#include "hardware/regs/i2c.h" #include "pico/time.h" #include "pico/types.h" @@ -16,7 +17,6 @@ static bool failure = false; - static uint8_t encoder_pos = 0; void irq_callback(uint gpio, uint32_t events) { @@ -90,7 +90,7 @@ static void write_cmd(uint8_t cmd) { } ssd1306::ssd1306() - : m_frame_buffer(*this) { + : m_frame_buffer(std::bind(&ssd1306::update, this, std::placeholders::_1)) { write_cmd(SET_DISP | 0x00); // Off write_cmd(SET_MUX_RATIO); // The height @@ -157,10 +157,21 @@ void ssd1306::flush() { } } -void ssd1306::update(size_t x, size_t y, uint8_t *data, size_t len) { - set_coordinates(x, 128, y, 7); +void ssd1306::update(std::span data) { + set_coordinates(0, 128, 0, 7); write_cmd(SET_MEM_ADDR); write_cmd(0x00); // Horizontal - // TODO: Something with nostop and then spitting raw bytes? might work... + uint8_t write = 0x40; + i2c_write_blocking(i2c0, ADDR, &write, 1, true); + i2c_write_raw_blocking(i2c0, data.data(), data.size()-1); + + while (!i2c_get_write_available(i2c0)) tight_loop_contents(); + + // Write a stop bit with the final byte + i2c_get_hw(i2c0)->data_cmd = 1 << I2C_IC_DATA_CMD_STOP_LSB | data.data()[data.size()-1]; + + // https://github.com/raspberrypi/pico-sdk/issues/812#issuecomment-1983833379 + // Wait for the stop bit to clock out + while (!(i2c0->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_STOP_DET_BITS)) tight_loop_contents(); } diff --git a/src/main.hh b/src/main.hh index 2fadd57..e94d895 100644 --- a/src/main.hh +++ b/src/main.hh @@ -35,6 +35,6 @@ public: void flush(); void set_coordinates(uint8_t start_x, uint8_t end_x, uint8_t start_y, uint8_t end_y); - void update(size_t x, size_t y, uint8_t *data, size_t len); + void update(std::span data); };