Revert changes to badger2040 library

pull/903/head
kennedn 2024-02-19 16:40:13 +00:00
rodzic c5a7c59510
commit b5f67b0426
1 zmienionych plików z 234 dodań i 260 usunięć

Wyświetl plik

@ -1,18 +1,18 @@
#include "badger2040.hpp"
#include <math.h>
#include <string.h> #include <string.h>
#include <math.h>
#include "hardware/pwm.h" #include "hardware/pwm.h"
#include "hardware/watchdog.h" #include "hardware/watchdog.h"
#include "badger2040.hpp"
namespace pimoroni { namespace pimoroni {
void Badger2040::init() { void Badger2040::init() {
// set clock speed to 12MHz to reduce the maximum current draw on the // set clock speed to 12MHz to reduce the maximum current draw on the
// battery. when updating a small, monochrome, display only every few // battery. when updating a small, monochrome, display only every few
// seconds or so then you don't need much processing power anyway... // seconds or so then you don't need much processing power anyway...
// set_sys_clock_khz(48000, true); //set_sys_clock_khz(48000, true);
gpio_set_function(ENABLE_3V3, GPIO_FUNC_SIO); gpio_set_function(ENABLE_3V3, GPIO_FUNC_SIO);
gpio_set_dir(ENABLE_3V3, GPIO_OUT); gpio_set_dir(ENABLE_3V3, GPIO_OUT);
@ -50,12 +50,12 @@ void Badger2040::init() {
uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E);
_wake_button_states |= gpio_get_all() & mask; _wake_button_states |= gpio_get_all() & mask;
/* /*
// wait for button to be released before continuing // wait for button to be released before continuing
while(gpio_get_all() & mask) { while(gpio_get_all() & mask) {
tight_loop_contents(); tight_loop_contents();
} }
*/ */
// led control pin // led control pin
pwm_config cfg = pwm_get_default_config(); pwm_config cfg = pwm_get_default_config();
@ -67,9 +67,9 @@ void Badger2040::init() {
uc8151_legacy.init(); uc8151_legacy.init();
// TODO: set default image? // TODO: set default image?
} }
void Badger2040::halt() { void Badger2040::halt() {
gpio_put(ENABLE_3V3, 0); gpio_put(ENABLE_3V3, 0);
// If running on USB we will not actually power down, so emulate the behaviour // If running on USB we will not actually power down, so emulate the behaviour
@ -77,382 +77,356 @@ void Badger2040::halt() {
// Note: Don't use wait_for_press as that waits for the button to be release and // Note: Don't use wait_for_press as that waits for the button to be release and
// we want the reboot to complete before the button is released. // we want the reboot to complete before the button is released.
update_button_states(); update_button_states();
while (_button_states == 0) { while(_button_states == 0) {
update_button_states(); update_button_states();
} }
watchdog_reboot(0, 0, 0); watchdog_reboot(0, 0, 0);
} }
uint8_t _dither_value(int32_t x, int32_t y, uint8_t p) { uint8_t _dither_value(int32_t x, int32_t y, uint8_t p) {
// ordered dither matrix used in 4-bit mode // ordered dither matrix used in 4-bit mode
static uint8_t _odm[16] = { static uint8_t _odm[16] = {
0, 8, 2, 10, 0, 8, 2, 10,
12, 4, 14, 6, 12, 4, 14, 6,
3, 11, 1, 9, 3, 11, 1, 9,
15, 7, 13, 5}; 15, 7, 13, 5
};
if (p == 0) { if (p == 0) {
return 1; return 1;
} }
if (p == 15) { if (p == 15) {
return 0; return 0;
} }
// calculate dither matrix offset // calculate dither matrix offset
uint32_t dmo = (x & 0b11) | ((y & 0b11) << 2); uint32_t dmo = (x & 0b11) | ((y & 0b11) << 2);
return p <= _odm[dmo] ? 1 : 0; return p <= _odm[dmo] ? 1 : 0;
} }
// Return dither values for an entire byte in the column // Return dither values for an entire byte in the column
uint8_t _dither_column_value(int32_t x, uint8_t p) { uint8_t _dither_column_value(int32_t x, uint8_t p) {
if (p == 0) { if (p == 0) {
return 0xff; return 0xff;
} }
if (p == 15) { if (p == 15) {
return 0; return 0;
} }
uint8_t val = 0; uint8_t val = 0;
for (int32_t y = 0; y < 4; ++y) { for (int32_t y = 0; y < 4; ++y) {
val |= _dither_value(x, y, p) << (7 - y); val |= _dither_value(x, y, p) << (7 - y);
} }
val |= val >> 4; val |= val >> 4;
return val; return val;
} }
void Badger2040::clear() {
void Badger2040::clear() {
const uint32_t column_len = 128 / 8; const uint32_t column_len = 128 / 8;
const uint32_t buf_len = column_len * 296; const uint32_t buf_len = column_len * 296;
uint8_t* buf = uc8151_legacy.get_frame_buffer(); uint8_t* buf = uc8151_legacy.get_frame_buffer();
if (_pen == 0) { if (_pen == 0) {
memset(buf, 0xff, buf_len); memset(buf, 0xff, buf_len);
} else if (_pen == 15) {
memset(buf, 0, buf_len);
} else {
for (uint32_t x = 0; x < 296; x++) {
uint8_t val = _dither_column_value(x, _pen);
memset(buf, val, column_len);
buf += column_len;
}
} }
} else if (_pen == 15) {
memset(buf, 0, buf_len);
void Badger2040::pixel(int32_t x, int32_t y) {
if (_thickness == 1) {
uc8151_legacy.pixel(x, y, _dither_value(x, y, _pen));
} else {
uint8_t ht = _thickness / 2;
for (int sy = 0; sy < _thickness; sy++) {
for (int sx = 0; sx < _thickness; sx++) {
uc8151_legacy.pixel(x + sx - ht, y + sy - ht, _dither_value(x + sx - ht, y + sy - ht, _pen));
}
}
} }
} else {
for(uint32_t x = 0; x < 296; x++) {
uint8_t val = _dither_column_value(x, _pen);
memset(buf, val, column_len);
buf += column_len;
}
}
}
// Display a portion of an image (icon sheet) at dx, dy void Badger2040::pixel(int32_t x, int32_t y) {
void Badger2040::icon(const uint8_t* data, int sheet_width, int icon_size, int index, int dx, int dy) { if(_thickness == 1) {
uc8151_legacy.pixel(x, y, _dither_value(x, y, _pen));
}else{
uint8_t ht = _thickness / 2;
for(int sy = 0; sy < _thickness; sy++) {
for(int sx = 0; sx < _thickness; sx++) {
uc8151_legacy.pixel(x + sx - ht, y + sy - ht, _dither_value(x + sx - ht, y + sy - ht, _pen));
}
}
}
}
// Display a portion of an image (icon sheet) at dx, dy
void Badger2040::icon(const uint8_t *data, int sheet_width, int icon_size, int index, int dx, int dy) {
image(data, sheet_width, icon_size * index, 0, icon_size, icon_size, dx, dy); image(data, sheet_width, icon_size * index, 0, icon_size, icon_size, dx, dy);
} }
// Display an image that fills the screen (296*128) // Display an image that fills the screen (296*128)
void Badger2040::image(const uint8_t* data) { void Badger2040::image(const uint8_t* data) {
uint8_t* ptr = uc8151_legacy.get_frame_buffer(); uint8_t* ptr = uc8151_legacy.get_frame_buffer();
for (uint32_t x = 0; x < 296; ++x) { for (uint32_t x = 0; x < 296; ++x) {
// extract bitmask for this pixel // extract bitmask for this pixel
uint32_t bm = 0b10000000 >> (x & 0b111); uint32_t bm = 0b10000000 >> (x & 0b111);
for (uint32_t y = 0; y < 128; y += 8) { for (uint32_t y = 0; y < 128; y += 8) {
uint8_t val = 0; uint8_t val = 0;
for (uint32_t cy = 0; cy < 8; ++cy) { for (uint32_t cy = 0; cy < 8; ++cy) {
// work out byte offset in source data // work out byte offset in source data
uint32_t o = ((y + cy) * (296 >> 3)) + (x >> 3); uint32_t o = ((y + cy) * (296 >> 3)) + (x >> 3);
// Set bit in val if set in source data // Set bit in val if set in source data
if (data[o] & bm) { if (data[o] & bm) {
val |= 0b10000000 >> cy; val |= 0b10000000 >> cy;
} }
}
*ptr++ = val;
} }
*ptr++ = val;
}
} }
} }
// Display an image smaller than the screen (sw*sh) at dx, dy // Display an image smaller than the screen (sw*sh) at dx, dy
void Badger2040::image(const uint8_t* data, int w, int h, int x, int y) { void Badger2040::image(const uint8_t *data, int w, int h, int x, int y) {
if (x == 0 && y == 0 && w == 296 && h == 128) { if (x == 0 && y == 0 && w == 296 && h == 128) {
image(data); image(data);
} else {
image(data, w, 0, 0, w, h, x, y);
} }
} else {
image(data, w, 0, 0, w, h, x, y);
void Badger2040::image(const uint8_t* data, int stride, int sx, int sy, int dw, int dh, int dx, int dy) {
for (auto y = 0; y < dh; y++) {
for (auto x = 0; x < dw; x++) {
// work out byte offset in source data
uint32_t o = ((y + sy) * (stride >> 3)) + ((x + sx) >> 3);
// extract bitmask for this pixel
uint32_t bm = 0b10000000 >> ((x + sx) & 0b111);
// draw the pixel
uc8151_legacy.pixel(dx + x, dy + y, data[o] & bm);
}
} }
} }
void Badger2040::rectangle(int32_t x, int32_t y, int32_t w, int32_t h) { void Badger2040::image(const uint8_t *data, int stride, int sx, int sy, int dw, int dh, int dx, int dy) {
for(auto y = 0; y < dh; y++) {
for(auto x = 0; x < dw; x++) {
// work out byte offset in source data
uint32_t o = ((y + sy) * (stride >> 3)) + ((x + sx) >> 3);
// extract bitmask for this pixel
uint32_t bm = 0b10000000 >> ((x + sx) & 0b111);
// draw the pixel
uc8151_legacy.pixel(dx + x, dy + y, data[o] & bm);
}
}
}
void Badger2040::rectangle(int32_t x, int32_t y, int32_t w, int32_t h) {
// Adjust for thickness // Adjust for thickness
uint32_t ht = _thickness / 2; uint32_t ht = _thickness / 2;
x -= ht; x -= ht;
if (x < 0) { if (x < 0) {
w += x; w += x;
x = 0; x = 0;
} }
y -= ht; y -= ht;
if (y < 0) { if (y < 0) {
h += y; h += y;
y = 0; y = 0;
} }
w += _thickness - 1; w += _thickness - 1;
h += _thickness - 1; h += _thickness - 1;
if (x + w > 296) { if (x + w > 296) {
w = 296 - x; w = 296 - x;
} }
if (y + h > 128) { if (y + h > 128) {
h = 128 - y; h = 128 - y;
} }
if (h >= 8) { if (h >= 8) {
// Directly write to the frame buffer when clearing a large area // Directly write to the frame buffer when clearing a large area
uint8_t* buf = uc8151_legacy.get_frame_buffer(); uint8_t* buf = uc8151_legacy.get_frame_buffer();
for (int cx = x; cx < x + w; cx++) { for(int cx = x; cx < x + w; cx++) {
uint8_t* buf_ptr = &buf[cx * 16 + y / 8]; uint8_t* buf_ptr = &buf[cx * 16 + y / 8];
uint8_t first_mask = 0xff >> (y & 7); uint8_t first_mask = 0xff >> (y & 7);
uint8_t last_mask = 0xff >> ((y + h) & 7); uint8_t last_mask = 0xff >> ((y + h) & 7);
uint32_t val = _dither_column_value(cx, _pen); uint32_t val = _dither_column_value(cx, _pen);
*buf_ptr &= ~first_mask; *buf_ptr &= ~first_mask;
*buf_ptr++ |= (val & first_mask); *buf_ptr++ |= (val & first_mask);
for (int32_t c = h - (8 - (y & 7)); c >= 8; c -= 8) { for (int32_t c = h - (8 - (y & 7)); c >= 8; c -= 8) {
*buf_ptr++ = val; *buf_ptr++ = val;
}
*buf_ptr &= last_mask;
*buf_ptr |= (val & (~last_mask));
} }
} else { *buf_ptr &= last_mask;
for (int cx = x; cx < x + w; cx++) { *buf_ptr |= (val & (~last_mask));
for (int cy = y; cy < y + h; cy++) { }
uc8151_legacy.pixel(cx, cy, _dither_value(cx, cy, _pen)); }
} else {
for(int cx = x; cx < x + w; cx++) {
for(int cy = y; cy < y + h; cy++) {
uc8151_legacy.pixel(cx, cy, _dither_value(cx, cy, _pen));
} }
}
} }
} }
void Badger2040::line(int32_t x1, int32_t y1, int32_t x2, int32_t y2) { void Badger2040::line(int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
int32_t x = x1, y = y1, dx, dy, incx, incy, balance; int32_t x = x1, y = y1, dx, dy, incx, incy, balance;
if (x2 >= x1) { if(x2 >= x1) {dx = x2 - x1; incx = 1;} else {dx = x1 - x2; incx = -1;}
dx = x2 - x1; if(y2 >= y1) {dy = y2 - y1; incy = 1;} else {dy = y1 - y2; incy = -1;}
incx = 1;
if(dx >= dy) {
dy <<= 1; balance = dy - dx; dx <<= 1;
while(x != x2) {
pixel(x, y);
if (balance >= 0) {y += incy; balance -= dx;}
balance += dy; x += incx;
}
} else { } else {
dx = x1 - x2; dx <<= 1; balance = dx - dy; dy <<= 1;
incx = -1; while(y != y2) {
} pixel(x, y);
if (y2 >= y1) { if(balance >= 0) {x += incx; balance -= dy;}
dy = y2 - y1; balance += dx; y += incy;
incy = 1; }
} else {
dy = y1 - y2;
incy = -1;
} }
}
if (dx >= dy) { void Badger2040::debug_command(uint8_t reg, size_t len, const uint8_t *data) {
dy <<= 1;
balance = dy - dx;
dx <<= 1;
while (x != x2) {
pixel(x, y);
if (balance >= 0) {
y += incy;
balance -= dx;
}
balance += dy;
x += incx;
}
} else {
dx <<= 1;
balance = dx - dy;
dy <<= 1;
while (y != y2) {
pixel(x, y);
if (balance >= 0) {
x += incx;
balance -= dy;
}
balance += dx;
y += incy;
}
}
}
void Badger2040::debug_command(uint8_t reg, size_t len, const uint8_t* data) {
uc8151_legacy.command(reg, len, data); uc8151_legacy.command(reg, len, data);
} }
void Badger2040::dump_otp(uint8_t* data) { void Badger2040::dump_otp(uint8_t *data) {
uc8151_legacy.read(0xa2, 0xFFF, data); uc8151_legacy.read(0xa2, 0xFFF, data);
} }
void Badger2040::update_button_states() { void Badger2040::update_button_states() {
uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E) | (1UL << USER); uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E) | (1UL << USER);
_button_states = gpio_get_all() & mask; _button_states = gpio_get_all() & mask;
_button_states ^= (1UL << USER); // USER button state is inverted _button_states ^= (1UL << USER); // USER button state is inverted
} }
uint32_t Badger2040::button_states() { uint32_t Badger2040::button_states() {
return _button_states; return _button_states;
} }
bool Badger2040::is_busy() { bool Badger2040::is_busy() {
return uc8151_legacy.is_busy(); return uc8151_legacy.is_busy();
} }
void Badger2040::power_off() { void Badger2040::power_off() {
uc8151_legacy.power_off(); uc8151_legacy.power_off();
} }
void Badger2040::invert(bool invert) { void Badger2040::invert(bool invert) {
uc8151_legacy.invert(invert); uc8151_legacy.invert(invert);
} }
void Badger2040::update_speed(uint8_t speed) { void Badger2040::update_speed(uint8_t speed) {
uc8151_legacy.update_speed(speed); uc8151_legacy.update_speed(speed);
} }
uint32_t Badger2040::update_time() { uint32_t Badger2040::update_time() {
return uc8151_legacy.update_time(); return uc8151_legacy.update_time();
} }
void Badger2040::partial_update(int x, int y, int w, int h, bool blocking) { void Badger2040::partial_update(int x, int y, int w, int h, bool blocking) {
uc8151_legacy.partial_update(x, y, w, h, blocking); uc8151_legacy.partial_update(x, y, w, h, blocking);
} }
void Badger2040::update(bool blocking) { void Badger2040::update(bool blocking) {
uc8151_legacy.update(blocking); uc8151_legacy.update(blocking);
} }
const hershey::font_glyph_t* Badger2040::glyph_data(unsigned char c) { const hershey::font_glyph_t* Badger2040::glyph_data(unsigned char c) {
return hershey::glyph_data(_font, c); return hershey::glyph_data(_font, c);
} }
int32_t Badger2040::glyph(unsigned char c, int32_t x, int32_t y, float s, float a) { int32_t Badger2040::glyph(unsigned char c, int32_t x, int32_t y, float s, float a) {
if (_bitmap_font) { if (_bitmap_font) {
bitmap::character( bitmap::character(_bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) {
_bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) { for(auto px = 0; px < w; px++) {
for (auto px = 0; px < w; px++) { for(auto py = 0; py < h; py++) {
for (auto py = 0; py < h; py++) { pixel(x + px, y + py);
pixel(x + px, y + py); }
} }
} }, c, x, y, std::max(1.0f, s));
}, return 0;
c, x, y, std::max(1.0f, s));
return 0;
} else { } else {
return hershey::glyph( return hershey::glyph(_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { line(x1, y1, x2, y2);
line(x1, y1, x2, y2); }, c, x, y, s, a);
},
c, x, y, s, a);
} }
} }
void Badger2040::text(std::string message, int32_t x, int32_t y, float s, float a, uint8_t letter_spacing) { void Badger2040::text(std::string message, int32_t x, int32_t y, float s, float a, uint8_t letter_spacing) {
if (_bitmap_font) { if (_bitmap_font) {
bitmap::text( bitmap::text(_bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) {
_bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) { for(auto px = 0; px < w; px++) {
for (auto px = 0; px < w; px++) { for(auto py = 0; py < h; py++) {
for (auto py = 0; py < h; py++) { pixel(x + px, y + py);
pixel(x + px, y + py); }
} }
} }, message, x, y, 296 - x, std::max(1.0f, s), letter_spacing);
},
message, x, y, 296 - x, std::max(1.0f, s), letter_spacing);
} else { } else {
hershey::text( hershey::text(_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { line(x1, y1, x2, y2);
line(x1, y1, x2, y2); }, message, x, y, s, a);
},
message, x, y, s, a);
} }
} }
int32_t Badger2040::measure_text(std::string message, float s, uint8_t letter_spacing) { int32_t Badger2040::measure_text(std::string message, float s, uint8_t letter_spacing) {
if (_bitmap_font) return bitmap::measure_text(_bitmap_font, message, std::max(1.0f, s), letter_spacing); if (_bitmap_font) return bitmap::measure_text(_bitmap_font, message, std::max(1.0f, s), letter_spacing);
return hershey::measure_text(_font, message, s); return hershey::measure_text(_font, message, s);
} }
int32_t Badger2040::measure_glyph(unsigned char c, float s) { int32_t Badger2040::measure_glyph(unsigned char c, float s) {
if (_bitmap_font) return bitmap::measure_character(_bitmap_font, c, std::max(1.0f, s)); if (_bitmap_font) return bitmap::measure_character(_bitmap_font, c, std::max(1.0f, s));
return hershey::measure_glyph(_font, c, s); return hershey::measure_glyph(_font, c, s);
} }
void Badger2040::font(std::string name) { void Badger2040::font(std::string name) {
if (name == "bitmap6") { if (name == "bitmap6") {
_bitmap_font = &font6; _bitmap_font = &font6;
_font = nullptr; _font = nullptr;
} else if (name == "bitmap8") { } else if (name == "bitmap8") {
_bitmap_font = &font8; _bitmap_font = &font8;
_font = nullptr; _font = nullptr;
} else if (name == "bitmap14_outline") { } else if (name == "bitmap14_outline") {
_bitmap_font = &font14_outline; _bitmap_font = &font14_outline;
_font = nullptr; _font = nullptr;
} else { } else {
// check that font exists and assign it // check that font exists and assign it
if (hershey::fonts.find(name) != hershey::fonts.end()) { if(hershey::fonts.find(name) != hershey::fonts.end()) {
_bitmap_font = nullptr; _bitmap_font = nullptr;
_font = hershey::fonts[name]; _font = hershey::fonts[name];
} }
} }
} }
void Badger2040::pen(uint8_t pen) { void Badger2040::pen(uint8_t pen) {
_pen = pen; _pen = pen;
} }
void Badger2040::thickness(uint8_t thickness) { void Badger2040::thickness(uint8_t thickness) {
_thickness = thickness; _thickness = thickness;
} }
void Badger2040::led(uint8_t brightness) { void Badger2040::led(uint8_t brightness) {
// set the led brightness from 1 to 256 with gamma correction // set the led brightness from 1 to 256 with gamma correction
float gamma = 2.8; float gamma = 2.8;
uint16_t v = (uint16_t)(pow((float)(brightness) / 256.0f, gamma) * 65535.0f + 0.5f); uint16_t v = (uint16_t)(pow((float)(brightness) / 256.0f, gamma) * 65535.0f + 0.5f);
pwm_set_gpio_level(LED, v); pwm_set_gpio_level(LED, v);
} }
bool Badger2040::pressed(uint8_t button) { bool Badger2040::pressed(uint8_t button) {
return (_button_states & (1UL << button)) != 0; return (_button_states & (1UL << button)) != 0;
} }
bool Badger2040::pressed_to_wake(uint8_t button) { bool Badger2040::pressed_to_wake(uint8_t button) {
return (_wake_button_states & (1UL << button)) != 0; return (_wake_button_states & (1UL << button)) != 0;
} }
void Badger2040::wait_for_press() { void Badger2040::wait_for_press() {
update_button_states(); update_button_states();
while (_button_states == 0) { while(_button_states == 0) {
update_button_states(); update_button_states();
tight_loop_contents(); tight_loop_contents();
} }
uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E);
while (gpio_get_all() & mask) { while(gpio_get_all() & mask) {
tight_loop_contents(); tight_loop_contents();
} }
}
} }
} // namespace pimoroni