Add dithering

This commit is contained in:
shylie 2025-06-05 17:39:03 -04:00
parent 1c9fc51d01
commit 8115ae1412
4 changed files with 37 additions and 13 deletions

View File

@ -2,26 +2,25 @@
#define PICOLED_H
#include <cstddef>
#include <cstdint>
namespace picoled
{
class pixel
{
friend class oled;
public:
pixel() :
pixel(false)
pixel(0)
{}
pixel(bool on) :
on(on)
pixel(uint8_t value) :
value(value)
{}
bool is_on() const { return on; }
void invert() { on = !on; }
private:
bool on;
uint8_t value;
};
class oled
@ -44,9 +43,13 @@ public:
size_t get_width() const { return width; }
size_t get_height() const { return height; }
virtual void update() const = 0;
void update() const;
protected:
virtual void update_impl() const = 0;
bool is_on(int x, int y) const;
size_t width;
size_t height;

View File

@ -16,7 +16,8 @@ public:
ssd1306(i2c_inst* i2c, uint8_t address);
virtual ~ssd1306();
void update() const override;
protected:
void update_impl() const override;
private:
void command(uint8_t cmd) const;

View File

@ -77,7 +77,7 @@ ssd1306::~ssd1306()
delete[] buffer;
}
void ssd1306::update() const
void ssd1306::update_impl() const
{
// clear display to zero
memset(&buffer[1], 0, width * height * sizeof(*buffer));
@ -86,7 +86,7 @@ void ssd1306::update() const
{
for (int y = 0; y < height; y++)
{
if (!(*this)(x, y).is_on()) { continue; }
if (!is_on(x, y)) { continue; }
const int index = (width - x - 1) + (y / 8) * width;
const uint8_t bits = 1 << (y & 7);

View File

@ -1,5 +1,14 @@
#include "picoled.h"
#include <cstdlib>
namespace
{
picoled::pixel DUMMY_PIXEL;
}
namespace picoled
{
@ -14,18 +23,29 @@ oled::~oled()
delete[] pixels;
}
pixel& oled::operator()(int x, int y)
{
static pixel dummy;
if (x < 0 || x >= width || y < 0 || y >= height) { return dummy; }
if (x < 0 || x >= width || y < 0 || y >= height) { return DUMMY_PIXEL; }
return pixels[x + y * width];
}
const pixel& oled::operator()(int x, int y) const
{
if (x < 0 || x >= width || y < 0 || y >= height) { return DUMMY_PIXEL; }
return pixels[x + y * width];
}
void oled::update() const
{
update_impl();
}
bool oled::is_on(int x, int y) const
{
return (*this)(x, y).value > rand() % 0xFF;
}
void oled::clear()
{
for (int i = 0; i < width * height; i++)