allow multiple schedules for temporal dithering
(however, there's no code yet to generate such schedules)
This commit is contained in:
parent
39bc663b26
commit
68c24fcc00
3 changed files with 29 additions and 22 deletions
|
|
@ -86,8 +86,9 @@ struct schedule_entry {
|
||||||
};
|
};
|
||||||
|
|
||||||
using schedule = std::vector<schedule_entry>;
|
using schedule = std::vector<schedule_entry>;
|
||||||
|
using schedule_sequence = std::vector<schedule>;
|
||||||
|
|
||||||
schedule make_simple_schedule(int n_planes, int pixels_across) {
|
schedule_sequence make_simple_schedule(int n_planes, int pixels_across) {
|
||||||
schedule result;
|
schedule result;
|
||||||
uint32_t max_count = 1 << n_planes;
|
uint32_t max_count = 1 << n_planes;
|
||||||
while (max_count < pixels_across)
|
while (max_count < pixels_across)
|
||||||
|
|
@ -96,7 +97,7 @@ schedule make_simple_schedule(int n_planes, int pixels_across) {
|
||||||
for (int i = 0; i < n_planes; i++) {
|
for (int i = 0; i < n_planes; i++) {
|
||||||
result.emplace_back(10 - i, max_count >> i);
|
result.emplace_back(10 - i, max_count >> i);
|
||||||
}
|
}
|
||||||
return result;
|
return {result};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct matrix_geometry {
|
struct matrix_geometry {
|
||||||
|
|
@ -115,10 +116,10 @@ struct matrix_geometry {
|
||||||
|
|
||||||
matrix_geometry(size_t pixels_across, size_t n_addr_lines, size_t width,
|
matrix_geometry(size_t pixels_across, size_t n_addr_lines, size_t width,
|
||||||
size_t height, matrix_map map, size_t n_lanes,
|
size_t height, matrix_map map, size_t n_lanes,
|
||||||
const std::vector<schedule_entry> schedule)
|
const schedule_sequence &schedules)
|
||||||
: pixels_across(pixels_across), n_addr_lines(n_addr_lines),
|
: pixels_across(pixels_across), n_addr_lines(n_addr_lines),
|
||||||
n_lanes(n_lanes), width(width), height(height),
|
n_lanes(n_lanes), width(width), height(height),
|
||||||
map(map), schedule{schedule} {
|
map(map), schedules{schedules} {
|
||||||
size_t pixels_down = n_lanes << n_addr_lines;
|
size_t pixels_down = n_lanes << n_addr_lines;
|
||||||
if (map.size() != pixels_down * pixels_across) {
|
if (map.size() != pixels_down * pixels_across) {
|
||||||
throw std::range_error(
|
throw std::range_error(
|
||||||
|
|
@ -127,7 +128,7 @@ struct matrix_geometry {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t pixels_across, n_addr_lines, n_lanes;
|
size_t pixels_across, n_addr_lines, n_lanes;
|
||||||
std::vector<schedule_entry> schedule;
|
schedule_sequence schedules;
|
||||||
size_t width, height;
|
size_t width, height;
|
||||||
matrix_map map;
|
matrix_map map;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ template <class pinout = adafruit_matrix_bonnet_pinout,
|
||||||
class colorspace = colorspace_rgb888>
|
class colorspace = colorspace_rgb888>
|
||||||
struct piomatter : piomatter_base {
|
struct piomatter : piomatter_base {
|
||||||
using buffer_type = std::vector<uint32_t>;
|
using buffer_type = std::vector<uint32_t>;
|
||||||
|
using bufseq_type = std::vector<buffer_type>;
|
||||||
piomatter(std::span<typename colorspace::data_type const> framebuffer,
|
piomatter(std::span<typename colorspace::data_type const> framebuffer,
|
||||||
const matrix_geometry &geometry)
|
const matrix_geometry &geometry)
|
||||||
: framebuffer(framebuffer), geometry{geometry}, converter{},
|
: framebuffer(framebuffer), geometry{geometry}, converter{},
|
||||||
|
|
@ -63,9 +64,13 @@ struct piomatter : piomatter_base {
|
||||||
|
|
||||||
void show() override {
|
void show() override {
|
||||||
int buffer_idx = manager.get_free_buffer();
|
int buffer_idx = manager.get_free_buffer();
|
||||||
auto &buffer = buffers[buffer_idx];
|
auto &bufseq = buffers[buffer_idx];
|
||||||
|
bufseq.resize(geometry.schedules.size());
|
||||||
auto converted = converter.convert(framebuffer);
|
auto converted = converter.convert(framebuffer);
|
||||||
protomatter_render_rgb10<pinout>(buffer, geometry, converted.data());
|
for (size_t i = 0; i < geometry.schedules.size(); i++) {
|
||||||
|
protomatter_render_rgb10<pinout>(
|
||||||
|
bufseq[i], geometry, geometry.schedules[i], converted.data());
|
||||||
|
}
|
||||||
manager.put_filled_buffer(buffer_idx);
|
manager.put_filled_buffer(buffer_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,26 +166,27 @@ struct piomatter : piomatter_base {
|
||||||
}
|
}
|
||||||
|
|
||||||
void blit_thread() {
|
void blit_thread() {
|
||||||
const uint32_t *databuf = nullptr;
|
int cur_buffer_idx = buffer_manager::no_buffer;
|
||||||
size_t datasize = 0;
|
|
||||||
int old_buffer_idx = buffer_manager::no_buffer;
|
|
||||||
int buffer_idx;
|
int buffer_idx;
|
||||||
|
int seq_idx = -1;
|
||||||
uint64_t t0, t1;
|
uint64_t t0, t1;
|
||||||
t0 = monotonicns64();
|
t0 = monotonicns64();
|
||||||
while ((buffer_idx = manager.get_filled_buffer()) !=
|
while ((buffer_idx = manager.get_filled_buffer()) !=
|
||||||
buffer_manager::exit_request) {
|
buffer_manager::exit_request) {
|
||||||
if (buffer_idx != buffer_manager::no_buffer) {
|
if (buffer_idx != buffer_manager::no_buffer) {
|
||||||
const auto &buffer = buffers[buffer_idx];
|
if (cur_buffer_idx != buffer_manager::no_buffer) {
|
||||||
databuf = &buffer[0];
|
manager.put_free_buffer(cur_buffer_idx);
|
||||||
datasize = buffer.size() * sizeof(*databuf);
|
|
||||||
if (old_buffer_idx != buffer_manager::no_buffer) {
|
|
||||||
manager.put_free_buffer(old_buffer_idx);
|
|
||||||
}
|
}
|
||||||
old_buffer_idx = buffer_idx;
|
cur_buffer_idx = buffer_idx;
|
||||||
}
|
}
|
||||||
if (datasize) {
|
if (cur_buffer_idx != buffer_manager::no_buffer) {
|
||||||
|
const auto &cur_buf = buffers[cur_buffer_idx];
|
||||||
|
seq_idx = (seq_idx + 1) % cur_buf.size();
|
||||||
|
const auto &data = cur_buf[seq_idx];
|
||||||
|
auto datasize = sizeof(uint32_t) * data.size();
|
||||||
|
auto dataptr = const_cast<uint32_t *>(&data[0]);
|
||||||
pio_sm_xfer_data_large(pio, sm, PIO_DIR_TO_SM, datasize,
|
pio_sm_xfer_data_large(pio, sm, PIO_DIR_TO_SM, datasize,
|
||||||
(uint32_t *)databuf);
|
dataptr);
|
||||||
t1 = monotonicns64();
|
t1 = monotonicns64();
|
||||||
if (t0 != t1) {
|
if (t0 != t1) {
|
||||||
fps = 1e9 / (t1 - t0);
|
fps = 1e9 / (t1 - t0);
|
||||||
|
|
@ -195,7 +201,7 @@ struct piomatter : piomatter_base {
|
||||||
PIO pio = NULL;
|
PIO pio = NULL;
|
||||||
int sm = -1;
|
int sm = -1;
|
||||||
std::span<typename colorspace::data_type const> framebuffer;
|
std::span<typename colorspace::data_type const> framebuffer;
|
||||||
buffer_type buffers[3];
|
bufseq_type buffers[3];
|
||||||
buffer_manager manager{};
|
buffer_manager manager{};
|
||||||
matrix_geometry geometry;
|
matrix_geometry geometry;
|
||||||
colorspace converter;
|
colorspace converter;
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ struct colorspace_rgb10 {
|
||||||
template <typename pinout>
|
template <typename pinout>
|
||||||
void protomatter_render_rgb10(std::vector<uint32_t> &result,
|
void protomatter_render_rgb10(std::vector<uint32_t> &result,
|
||||||
const matrix_geometry &matrixmap,
|
const matrix_geometry &matrixmap,
|
||||||
const uint32_t *pixels) {
|
const schedule &sched, const uint32_t *pixels) {
|
||||||
result.clear();
|
result.clear();
|
||||||
|
|
||||||
int data_count = 0;
|
int data_count = 0;
|
||||||
|
|
@ -194,8 +194,8 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
|
||||||
uint32_t addr_bits = calc_addr_bits(prev_addr);
|
uint32_t addr_bits = calc_addr_bits(prev_addr);
|
||||||
|
|
||||||
for (size_t addr = 0; addr < n_addr; addr++) {
|
for (size_t addr = 0; addr < n_addr; addr++) {
|
||||||
uint32_t active_time = matrixmap.schedule.back().active_time;
|
uint32_t active_time = sched.back().active_time;
|
||||||
for (auto &schedule_ent : matrixmap.schedule) {
|
for (auto &schedule_ent : sched) {
|
||||||
uint32_t r_mask = 1 << (20 + schedule_ent.shift);
|
uint32_t r_mask = 1 << (20 + schedule_ent.shift);
|
||||||
uint32_t g_mask = 1 << (10 + schedule_ent.shift);
|
uint32_t g_mask = 1 << (10 + schedule_ent.shift);
|
||||||
uint32_t b_mask = 1 << (0 + schedule_ent.shift);
|
uint32_t b_mask = 1 << (0 + schedule_ent.shift);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue