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 <cstddef>
#include <functional>
#include <array>
#include <span>
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<uint8_t, SIZE> m_buffer;
FramebufferListener &m_listener;
std::function<void(std::span<uint8_t>)> 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<void(std::span<uint8_t>)> 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(); }
};

View File

@ -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<uint8_t> 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();
}

View File

@ -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<uint8_t> data);
};