Add i2c update function with some stop bit shenanigans

This commit is contained in:
Archie Hilton 2024-07-07 21:18:03 +01:00
parent 5c963b0592
commit c8d1093faa
3 changed files with 35 additions and 13 deletions

View File

@ -3,7 +3,9 @@
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
#include <functional>
#include <array> #include <array>
#include <span>
namespace Framebuffer { namespace Framebuffer {
class FramebufferListener { class FramebufferListener {
@ -26,20 +28,29 @@ namespace Framebuffer {
static constexpr size_t ROWS = (FB_HEIGHT/ROW_HEIGHT); static constexpr size_t ROWS = (FB_HEIGHT/ROW_HEIGHT);
static constexpr size_t SIZE = FB_WIDTH * ROWS; static constexpr size_t SIZE = FB_WIDTH * ROWS;
std::array<uint8_t, SIZE> m_buffer; std::array<uint8_t, SIZE> m_buffer;
FramebufferListener &m_listener; std::function<void(std::span<uint8_t>)> m_listener_update;
void update_listener() { void update_listener() {
m_listener.update(0, 0, m_buffer.data(), m_buffer.size()); m_listener_update(m_buffer);
} }
public: public:
Framebuffer(FramebufferListener &listener) Framebuffer(std::function<void(std::span<uint8_t>)> f)
: m_listener(listener) { : m_listener_update(f) {
} }
void fill(uint8_t val) { FrameBufferBase::fill(m_buffer.data(), m_buffer.size(), val); } void fill(uint8_t val) {
void putc(size_t x, size_t y, char c) { FrameBufferBase::putc(m_buffer.data(), ROW_HEIGHT, m_buffer.size(), x, y, c); } FrameBufferBase::fill(m_buffer.data(), m_buffer.size(), val);
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();
}
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(); } uint8_t *data() { return m_buffer.data(); }
size_t size() { return m_buffer.size(); } size_t size() { return m_buffer.size(); }
}; };

View File

@ -3,6 +3,7 @@
#include "hardware/gpio.h" #include "hardware/gpio.h"
#include "hardware/i2c.h" #include "hardware/i2c.h"
#include "hardware/regs/i2c.h"
#include "pico/time.h" #include "pico/time.h"
#include "pico/types.h" #include "pico/types.h"
@ -16,7 +17,6 @@
static bool failure = false; static bool failure = false;
static uint8_t encoder_pos = 0; static uint8_t encoder_pos = 0;
void irq_callback(uint gpio, uint32_t events) { void irq_callback(uint gpio, uint32_t events) {
@ -90,7 +90,7 @@ static void write_cmd(uint8_t cmd) {
} }
ssd1306::ssd1306() 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_DISP | 0x00); // Off
write_cmd(SET_MUX_RATIO); // The height 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) { void ssd1306::update(std::span<uint8_t> data) {
set_coordinates(x, 128, y, 7); set_coordinates(0, 128, 0, 7);
write_cmd(SET_MEM_ADDR); write_cmd(SET_MEM_ADDR);
write_cmd(0x00); // Horizontal 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();
} }

View File

@ -35,6 +35,6 @@ public:
void flush(); void flush();
void set_coordinates(uint8_t start_x, uint8_t end_x, uint8_t start_y, uint8_t end_y); 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<uint8_t> data);
}; };