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_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;
|
||||
uint32_t max_count = 1 << n_planes;
|
||||
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++) {
|
||||
result.emplace_back(10 - i, max_count >> i);
|
||||
}
|
||||
return result;
|
||||
return {result};
|
||||
}
|
||||
|
||||
struct matrix_geometry {
|
||||
|
|
@ -115,10 +116,10 @@ struct matrix_geometry {
|
|||
|
||||
matrix_geometry(size_t pixels_across, size_t n_addr_lines, size_t width,
|
||||
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),
|
||||
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;
|
||||
if (map.size() != pixels_down * pixels_across) {
|
||||
throw std::range_error(
|
||||
|
|
@ -127,7 +128,7 @@ struct matrix_geometry {
|
|||
}
|
||||
|
||||
size_t pixels_across, n_addr_lines, n_lanes;
|
||||
std::vector<schedule_entry> schedule;
|
||||
schedule_sequence schedules;
|
||||
size_t width, height;
|
||||
matrix_map map;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ template <class pinout = adafruit_matrix_bonnet_pinout,
|
|||
class colorspace = colorspace_rgb888>
|
||||
struct piomatter : piomatter_base {
|
||||
using buffer_type = std::vector<uint32_t>;
|
||||
using bufseq_type = std::vector<buffer_type>;
|
||||
piomatter(std::span<typename colorspace::data_type const> framebuffer,
|
||||
const matrix_geometry &geometry)
|
||||
: framebuffer(framebuffer), geometry{geometry}, converter{},
|
||||
|
|
@ -63,9 +64,13 @@ struct piomatter : piomatter_base {
|
|||
|
||||
void show() override {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -161,26 +166,27 @@ struct piomatter : piomatter_base {
|
|||
}
|
||||
|
||||
void blit_thread() {
|
||||
const uint32_t *databuf = nullptr;
|
||||
size_t datasize = 0;
|
||||
int old_buffer_idx = buffer_manager::no_buffer;
|
||||
int cur_buffer_idx = buffer_manager::no_buffer;
|
||||
int buffer_idx;
|
||||
int seq_idx = -1;
|
||||
uint64_t t0, t1;
|
||||
t0 = monotonicns64();
|
||||
while ((buffer_idx = manager.get_filled_buffer()) !=
|
||||
buffer_manager::exit_request) {
|
||||
if (buffer_idx != buffer_manager::no_buffer) {
|
||||
const auto &buffer = buffers[buffer_idx];
|
||||
databuf = &buffer[0];
|
||||
datasize = buffer.size() * sizeof(*databuf);
|
||||
if (old_buffer_idx != buffer_manager::no_buffer) {
|
||||
manager.put_free_buffer(old_buffer_idx);
|
||||
if (cur_buffer_idx != buffer_manager::no_buffer) {
|
||||
manager.put_free_buffer(cur_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,
|
||||
(uint32_t *)databuf);
|
||||
dataptr);
|
||||
t1 = monotonicns64();
|
||||
if (t0 != t1) {
|
||||
fps = 1e9 / (t1 - t0);
|
||||
|
|
@ -195,7 +201,7 @@ struct piomatter : piomatter_base {
|
|||
PIO pio = NULL;
|
||||
int sm = -1;
|
||||
std::span<typename colorspace::data_type const> framebuffer;
|
||||
buffer_type buffers[3];
|
||||
bufseq_type buffers[3];
|
||||
buffer_manager manager{};
|
||||
matrix_geometry geometry;
|
||||
colorspace converter;
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ struct colorspace_rgb10 {
|
|||
template <typename pinout>
|
||||
void protomatter_render_rgb10(std::vector<uint32_t> &result,
|
||||
const matrix_geometry &matrixmap,
|
||||
const uint32_t *pixels) {
|
||||
const schedule &sched, const uint32_t *pixels) {
|
||||
result.clear();
|
||||
|
||||
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);
|
||||
|
||||
for (size_t addr = 0; addr < n_addr; addr++) {
|
||||
uint32_t active_time = matrixmap.schedule.back().active_time;
|
||||
for (auto &schedule_ent : matrixmap.schedule) {
|
||||
uint32_t active_time = sched.back().active_time;
|
||||
for (auto &schedule_ent : sched) {
|
||||
uint32_t r_mask = 1 << (20 + schedule_ent.shift);
|
||||
uint32_t g_mask = 1 << (10 + schedule_ent.shift);
|
||||
uint32_t b_mask = 1 << (0 + schedule_ent.shift);
|
||||
|
|
|
|||
Loading…
Reference in a new issue