format code
This commit is contained in:
parent
75989420bd
commit
01ca95d283
9 changed files with 235 additions and 186 deletions
|
|
@ -12,28 +12,20 @@ struct buffer_manager {
|
||||||
free_buffers.push(2);
|
free_buffers.push(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_free_buffer() {
|
int get_free_buffer() { return free_buffers.pop_blocking(); }
|
||||||
return free_buffers.pop_blocking();
|
void put_free_buffer(int i) { free_buffers.push(i); }
|
||||||
}
|
|
||||||
void put_free_buffer(int i) {
|
|
||||||
free_buffers.push(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_filled_buffer() {
|
int get_filled_buffer() {
|
||||||
auto r = filled_buffers.pop_nonblocking();
|
auto r = filled_buffers.pop_nonblocking();
|
||||||
return r ? r.value() : no_buffer;
|
return r ? r.value() : no_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_filled_buffer(int i) {
|
void put_filled_buffer(int i) { filled_buffers.push(i); }
|
||||||
filled_buffers.push(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
void request_exit() {
|
void request_exit() { filled_buffers.push(exit_request); }
|
||||||
filled_buffers.push(exit_request);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
thread_queue<int> free_buffers, filled_buffers;
|
thread_queue<int> free_buffers, filled_buffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace piomatter
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace piomatter {
|
namespace piomatter {
|
||||||
|
|
||||||
|
|
@ -26,31 +26,23 @@ int orientation_cw(int width, int height, int x, int y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template<typename Cb>
|
template <typename Cb>
|
||||||
void submap(std::vector<int> &result,
|
void submap(std::vector<int> &result, int width, int height, int start_x,
|
||||||
int width, int height,
|
int dx, int count_x_in, int start_y, int dy, int count_y,
|
||||||
int start_x, int dx, int count_x_in,
|
int half_panel_height, const Cb &cb) {
|
||||||
int start_y, int dy, int count_y,
|
|
||||||
int half_panel_height,
|
|
||||||
const Cb &cb) {
|
|
||||||
|
|
||||||
for(int y = start_y; count_y; count_y -= 2, y += dy ) {
|
for (int y = start_y; count_y; count_y -= 2, y += dy) {
|
||||||
for(int x = start_x, count_x = count_x_in; count_x--; x += dx )
|
for (int x = start_x, count_x = count_x_in; count_x--; x += dx) {
|
||||||
{
|
result.push_back(cb(width, height, x, y));
|
||||||
result.push_back(cb(width, height, x,y));
|
result.push_back(cb(width, height, x, y + dy * half_panel_height));
|
||||||
result.push_back(cb(width, height, x,y+dy*half_panel_height));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
template<typename Cb>
|
template <typename Cb>
|
||||||
matrix_map make_matrixmap(
|
matrix_map make_matrixmap(int width, int height, int n_addr_lines,
|
||||||
int width,
|
bool serpentine, const Cb &cb) {
|
||||||
int height,
|
|
||||||
int n_addr_lines,
|
|
||||||
bool serpentine,
|
|
||||||
const Cb &cb) {
|
|
||||||
|
|
||||||
int panel_height = 2 << n_addr_lines;
|
int panel_height = 2 << n_addr_lines;
|
||||||
if (height % panel_height != 0) {
|
if (height % panel_height != 0) {
|
||||||
|
|
@ -61,10 +53,10 @@ matrix_map make_matrixmap(
|
||||||
int v_panels = height / panel_height;
|
int v_panels = height / panel_height;
|
||||||
int pixels_across = width * v_panels;
|
int pixels_across = width * v_panels;
|
||||||
matrix_map result;
|
matrix_map result;
|
||||||
result.reserve(width*height);
|
result.reserve(width * height);
|
||||||
|
|
||||||
for(int i=0; i<half_panel_height; i++) {
|
for (int i = 0; i < half_panel_height; i++) {
|
||||||
for(int j=0; j<pixels_across; j++) {
|
for (int j = 0; j < pixels_across; j++) {
|
||||||
int panel_no = j / width;
|
int panel_no = j / width;
|
||||||
int panel_idx = j % width;
|
int panel_idx = j % width;
|
||||||
int x, y0, y1;
|
int x, y0, y1;
|
||||||
|
|
@ -87,14 +79,20 @@ matrix_map make_matrixmap(
|
||||||
}
|
}
|
||||||
|
|
||||||
struct matrix_geometry {
|
struct matrix_geometry {
|
||||||
template<typename Cb>
|
template <typename Cb>
|
||||||
matrix_geometry(int pixels_across, int n_addr_lines, int n_planes, int width, int height, bool serpentine, const Cb &cb) : pixels_across(pixels_across), n_addr_lines(n_addr_lines), n_planes(n_planes), width(width), height(height), map{make_matrixmap(width, height, n_addr_lines, serpentine, cb)} {
|
matrix_geometry(int pixels_across, int n_addr_lines, int n_planes,
|
||||||
|
int width, int height, bool serpentine, const Cb &cb)
|
||||||
|
: pixels_across(pixels_across), n_addr_lines(n_addr_lines),
|
||||||
|
n_planes(n_planes), width(width),
|
||||||
|
height(height), map{make_matrixmap(width, height, n_addr_lines,
|
||||||
|
serpentine, cb)} {
|
||||||
int pixels_down = 2 << n_addr_lines;
|
int pixels_down = 2 << n_addr_lines;
|
||||||
if (map.size() != pixels_down * pixels_across) {
|
if (map.size() != pixels_down * pixels_across) {
|
||||||
throw std::range_error("map size does not match calculated pixel count");
|
throw std::range_error(
|
||||||
|
"map size does not match calculated pixel count");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
int pixels_across, n_addr_lines, n_planes, width, height;
|
int pixels_across, n_addr_lines, n_planes, width, height;
|
||||||
matrix_map map;
|
matrix_map map;
|
||||||
};
|
};
|
||||||
}
|
} // namespace piomatter
|
||||||
|
|
|
||||||
|
|
@ -22,4 +22,4 @@ struct adafruit_matrix_bonnet_pinout {
|
||||||
static constexpr uint32_t post_addr_delay = 500;
|
static constexpr uint32_t post_addr_delay = 500;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace piomatter
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,24 @@
|
||||||
|
|
||||||
#include "hardware/pio.h"
|
#include "hardware/pio.h"
|
||||||
|
|
||||||
#include "piomatter/pins.h"
|
|
||||||
#include "piomatter/buffer_manager.h"
|
#include "piomatter/buffer_manager.h"
|
||||||
#include "piomatter/render.h"
|
|
||||||
#include "piomatter/matrixmap.h"
|
#include "piomatter/matrixmap.h"
|
||||||
|
#include "piomatter/pins.h"
|
||||||
#include "piomatter/protomatter.pio.h"
|
#include "piomatter/protomatter.pio.h"
|
||||||
|
#include "piomatter/render.h"
|
||||||
|
|
||||||
namespace piomatter {
|
namespace piomatter {
|
||||||
|
|
||||||
constexpr size_t MAX_XFER = 65532;
|
constexpr size_t MAX_XFER = 65532;
|
||||||
|
|
||||||
void pio_sm_xfer_data_large(PIO pio, int sm, int direction, size_t size, uint32_t *databuf) {
|
void pio_sm_xfer_data_large(PIO pio, int sm, int direction, size_t size,
|
||||||
while(size) {
|
uint32_t *databuf) {
|
||||||
|
while (size) {
|
||||||
size_t xfersize = std::min(size_t{MAX_XFER}, size);
|
size_t xfersize = std::min(size_t{MAX_XFER}, size);
|
||||||
int r = pio_sm_xfer_data(pio, sm, direction, xfersize, databuf);
|
int r = pio_sm_xfer_data(pio, sm, direction, xfersize, databuf);
|
||||||
if (r) {
|
if (r) {
|
||||||
throw std::runtime_error("pio_sm_xfer_data (reboot may be required)");
|
throw std::runtime_error(
|
||||||
|
"pio_sm_xfer_data (reboot may be required)");
|
||||||
}
|
}
|
||||||
size -= xfersize;
|
size -= xfersize;
|
||||||
databuf += xfersize / sizeof(*databuf);
|
databuf += xfersize / sizeof(*databuf);
|
||||||
|
|
@ -31,10 +33,14 @@ struct piomatter_base {
|
||||||
virtual void show() = 0;
|
virtual void show() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class pinout=adafruit_matrix_bonnet_pinout, class colorspace=colorspace_rgb888>
|
template <class pinout = adafruit_matrix_bonnet_pinout,
|
||||||
|
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>;
|
||||||
piomatter(std::span<typename colorspace::data_type const> framebuffer, const matrix_geometry &geometry) : framebuffer(framebuffer), geometry{geometry}, converter{}, blitter_thread{&piomatter::blit_thread, this} {
|
piomatter(std::span<typename colorspace::data_type const> framebuffer,
|
||||||
|
const matrix_geometry &geometry)
|
||||||
|
: framebuffer(framebuffer), geometry{geometry}, converter{},
|
||||||
|
blitter_thread{&piomatter::blit_thread, this} {
|
||||||
if (geometry.n_addr_lines > std::size(pinout::PIN_ADDR)) {
|
if (geometry.n_addr_lines > std::size(pinout::PIN_ADDR)) {
|
||||||
throw std::runtime_error("too many address lines requested");
|
throw std::runtime_error("too many address lines requested");
|
||||||
}
|
}
|
||||||
|
|
@ -57,10 +63,10 @@ struct piomatter : piomatter_base {
|
||||||
pin_deinit_one(pinout::PIN_CLK);
|
pin_deinit_one(pinout::PIN_CLK);
|
||||||
pin_deinit_one(pinout::PIN_LAT);
|
pin_deinit_one(pinout::PIN_LAT);
|
||||||
|
|
||||||
for(const auto p : pinout::PIN_RGB)
|
for (const auto p : pinout::PIN_RGB)
|
||||||
pin_deinit_one(p);
|
pin_deinit_one(p);
|
||||||
|
|
||||||
for(size_t i=0; i<geometry.n_addr_lines; i++) {
|
for (size_t i = 0; i < geometry.n_addr_lines; i++) {
|
||||||
pin_deinit_one(pinout::PIN_ADDR[i]);
|
pin_deinit_one(pinout::PIN_ADDR[i]);
|
||||||
}
|
}
|
||||||
pio_sm_unclaim(pio, sm);
|
pio_sm_unclaim(pio, sm);
|
||||||
|
|
@ -71,7 +77,8 @@ struct piomatter : piomatter_base {
|
||||||
blitter_thread.join();
|
blitter_thread.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
|
private:
|
||||||
void program_init() {
|
void program_init() {
|
||||||
pio = pio0;
|
pio = pio0;
|
||||||
sm = pio_claim_unused_sm(pio, true);
|
sm = pio_claim_unused_sm(pio, true);
|
||||||
|
|
@ -90,7 +97,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
uint offset = pio_add_program(pio, &protomatter_program);
|
uint offset = pio_add_program(pio, &protomatter_program);
|
||||||
if (offset== PIO_ORIGIN_INVALID) {
|
if (offset == PIO_ORIGIN_INVALID) {
|
||||||
throw std::runtime_error("pio_add_program");
|
throw std::runtime_error("pio_add_program");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,8 +105,10 @@ private:
|
||||||
pio_sm_set_clkdiv(pio, sm, 1.0);
|
pio_sm_set_clkdiv(pio, sm, 1.0);
|
||||||
|
|
||||||
pio_sm_config c = pio_get_default_sm_config();
|
pio_sm_config c = pio_get_default_sm_config();
|
||||||
sm_config_set_wrap(&c, offset + protomatter_wrap_target, offset + protomatter_wrap);
|
sm_config_set_wrap(&c, offset + protomatter_wrap_target,
|
||||||
sm_config_set_out_shift(&c, /* shift_right= */ false, /* auto_pull = */ true, 32);
|
offset + protomatter_wrap);
|
||||||
|
sm_config_set_out_shift(&c, /* shift_right= */ false,
|
||||||
|
/* auto_pull = */ true, 32);
|
||||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||||
sm_config_set_clkdiv(&c, 1.0);
|
sm_config_set_clkdiv(&c, 1.0);
|
||||||
sm_config_set_out_pins(&c, 0, 28);
|
sm_config_set_out_pins(&c, 0, 28);
|
||||||
|
|
@ -110,10 +119,10 @@ private:
|
||||||
pin_init_one(pinout::PIN_CLK);
|
pin_init_one(pinout::PIN_CLK);
|
||||||
pin_init_one(pinout::PIN_LAT);
|
pin_init_one(pinout::PIN_LAT);
|
||||||
|
|
||||||
for(const auto p : pinout::PIN_RGB)
|
for (const auto p : pinout::PIN_RGB)
|
||||||
pin_init_one(p);
|
pin_init_one(p);
|
||||||
|
|
||||||
for(size_t i=0; i<geometry.n_addr_lines; i++) {
|
for (size_t i = 0; i < geometry.n_addr_lines; i++) {
|
||||||
pin_init_one(pinout::PIN_ADDR[i]);
|
pin_init_one(pinout::PIN_ADDR[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -133,8 +142,9 @@ private:
|
||||||
size_t datasize = 0;
|
size_t datasize = 0;
|
||||||
int old_buffer_idx = buffer_manager::no_buffer;
|
int old_buffer_idx = buffer_manager::no_buffer;
|
||||||
int buffer_idx;
|
int buffer_idx;
|
||||||
while((buffer_idx = manager.get_filled_buffer()) != buffer_manager::exit_request) {
|
while ((buffer_idx = manager.get_filled_buffer()) !=
|
||||||
if(buffer_idx != buffer_manager::no_buffer) {
|
buffer_manager::exit_request) {
|
||||||
|
if (buffer_idx != buffer_manager::no_buffer) {
|
||||||
const auto &buffer = buffers[buffer_idx];
|
const auto &buffer = buffers[buffer_idx];
|
||||||
databuf = &buffer[0];
|
databuf = &buffer[0];
|
||||||
datasize = buffer.size() * sizeof(*databuf);
|
datasize = buffer.size() * sizeof(*databuf);
|
||||||
|
|
@ -144,7 +154,8 @@ private:
|
||||||
old_buffer_idx = buffer_idx;
|
old_buffer_idx = buffer_idx;
|
||||||
}
|
}
|
||||||
if (datasize) {
|
if (datasize) {
|
||||||
pio_sm_xfer_data_large(pio, sm, PIO_DIR_TO_SM, datasize, (uint32_t*)databuf);
|
pio_sm_xfer_data_large(pio, sm, PIO_DIR_TO_SM, datasize,
|
||||||
|
(uint32_t *)databuf);
|
||||||
} else {
|
} else {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
}
|
}
|
||||||
|
|
@ -161,4 +172,4 @@ private:
|
||||||
std::thread blitter_thread;
|
std::thread blitter_thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace piomatter
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
const int protomatter_wrap = 4;
|
const int protomatter_wrap = 4;
|
||||||
const int protomatter_wrap_target = 0;
|
const int protomatter_wrap_target = 0;
|
||||||
const int protomatter_sideset_pin_count = 0;
|
const int protomatter_sideset_pin_count = 0;
|
||||||
|
|
@ -46,4 +48,3 @@ const uint16_t protomatter[] = {
|
||||||
0xa042, // nop
|
0xa042, // nop
|
||||||
0xa042, // nop
|
0xa042, // nop
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,49 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "matrixmap.h"
|
||||||
|
#include <cassert>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
|
||||||
#include "matrixmap.h"
|
|
||||||
|
|
||||||
namespace piomatter {
|
namespace piomatter {
|
||||||
|
|
||||||
|
|
||||||
constexpr unsigned DATA_OVERHEAD = 3;
|
constexpr unsigned DATA_OVERHEAD = 3;
|
||||||
constexpr unsigned CLOCKS_PER_DATA = 2;
|
constexpr unsigned CLOCKS_PER_DATA = 2;
|
||||||
constexpr unsigned DELAY_OVERHEAD = 5;
|
constexpr unsigned DELAY_OVERHEAD = 5;
|
||||||
constexpr unsigned CLOCKS_PER_DELAY = 1;
|
constexpr unsigned CLOCKS_PER_DELAY = 1;
|
||||||
|
|
||||||
constexpr uint32_t command_data = 1u <<31;
|
constexpr uint32_t command_data = 1u << 31;
|
||||||
constexpr uint32_t command_delay = 0;
|
constexpr uint32_t command_delay = 0;
|
||||||
|
|
||||||
struct gamma_lut {
|
struct gamma_lut {
|
||||||
gamma_lut(double exponent=2.2) {
|
gamma_lut(double exponent = 2.2) {
|
||||||
for(int i=0; i<256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
auto v = std::max(i, int(round(1023 * pow(i / 255, exponent))));
|
auto v = std::max(i, int(round(1023 * pow(i / 255, exponent))));
|
||||||
lut[i] = v;
|
lut[i] = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned convert(unsigned v) {
|
unsigned convert(unsigned v) {
|
||||||
if(v >= std::size(lut)) return 1023;
|
if (v >= std::size(lut))
|
||||||
|
return 1023;
|
||||||
return lut[v];
|
return lut[v];
|
||||||
}
|
}
|
||||||
|
|
||||||
void convert_rgb888_packed_to_rgb10(std::vector<uint32_t> &result, std::span<const uint8_t> source) {
|
void convert_rgb888_packed_to_rgb10(std::vector<uint32_t> &result,
|
||||||
|
std::span<const uint8_t> source) {
|
||||||
result.resize(source.size() / 3);
|
result.resize(source.size() / 3);
|
||||||
for(size_t i=0; i<source.size(); i+=3) {
|
for (size_t i = 0; i < source.size(); i += 3) {
|
||||||
uint32_t r = source[i+0] & 0xff;
|
uint32_t r = source[i + 0] & 0xff;
|
||||||
uint32_t g = source[i+1] & 0xff;
|
uint32_t g = source[i + 1] & 0xff;
|
||||||
uint32_t b = source[i+2] & 0xff;
|
uint32_t b = source[i + 2] & 0xff;
|
||||||
result[i] = (convert(r) << 20) | (convert(g) << 10) | convert(b);
|
result[i] = (convert(r) << 20) | (convert(g) << 10) | convert(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void convert_rgb888_to_rgb10(std::vector<uint32_t> &result,
|
||||||
void convert_rgb888_to_rgb10(std::vector<uint32_t> &result, std::span<const uint32_t> source) {
|
std::span<const uint32_t> source) {
|
||||||
result.resize(source.size());
|
result.resize(source.size());
|
||||||
for(size_t i=0; i<source.size(); i++) {
|
for (size_t i = 0; i < source.size(); i++) {
|
||||||
uint32_t data = source[i];
|
uint32_t data = source[i];
|
||||||
uint32_t r = (data >> 16) & 0xff;
|
uint32_t r = (data >> 16) & 0xff;
|
||||||
uint32_t g = (data >> 8) & 0xff;
|
uint32_t g = (data >> 8) & 0xff;
|
||||||
|
|
@ -51,16 +52,16 @@ struct gamma_lut {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void convert_rgb565_to_rgb10(std::vector<uint32_t> &result,
|
||||||
void convert_rgb565_to_rgb10(std::vector<uint32_t> &result, std::span<const uint16_t> source) {
|
std::span<const uint16_t> source) {
|
||||||
result.resize(source.size());
|
result.resize(source.size());
|
||||||
for(size_t i=0; i<source.size(); i++) {
|
for (size_t i = 0; i < source.size(); i++) {
|
||||||
uint32_t data = source[i];
|
uint32_t data = source[i];
|
||||||
unsigned r5 = (data >> 11) & 0x1f;
|
unsigned r5 = (data >> 11) & 0x1f;
|
||||||
unsigned r = (r5 << 3) | (r5 >> 2);
|
unsigned r = (r5 << 3) | (r5 >> 2);
|
||||||
unsigned g6 = (data >> 5) & 0x3f;
|
unsigned g6 = (data >> 5) & 0x3f;
|
||||||
unsigned g = (g6 << 2) | (g6 >> 4);
|
unsigned g = (g6 << 2) | (g6 >> 4);
|
||||||
unsigned b5 = (data) & 0x1f;
|
unsigned b5 = (data)&0x1f;
|
||||||
unsigned b = (b5 << 3) | (b5 >> 2);
|
unsigned b = (b5 << 3) | (b5 >> 2);
|
||||||
|
|
||||||
result[i] = (convert(r) << 20) | (convert(g) << 10) | convert(b);
|
result[i] = (convert(r) << 20) | (convert(g) << 10) | convert(b);
|
||||||
|
|
@ -73,9 +74,10 @@ struct gamma_lut {
|
||||||
struct colorspace_rgb565 {
|
struct colorspace_rgb565 {
|
||||||
using data_type = uint16_t;
|
using data_type = uint16_t;
|
||||||
|
|
||||||
colorspace_rgb565(float gamma=2.2) : lut{gamma} {}
|
colorspace_rgb565(float gamma = 2.2) : lut{gamma} {}
|
||||||
gamma_lut lut;
|
gamma_lut lut;
|
||||||
const std::span<const uint32_t> convert(std::span<const data_type> data_in) {
|
const std::span<const uint32_t>
|
||||||
|
convert(std::span<const data_type> data_in) {
|
||||||
lut.convert_rgb565_to_rgb10(rgb10, data_in);
|
lut.convert_rgb565_to_rgb10(rgb10, data_in);
|
||||||
return rgb10;
|
return rgb10;
|
||||||
}
|
}
|
||||||
|
|
@ -85,9 +87,10 @@ struct colorspace_rgb565 {
|
||||||
struct colorspace_rgb888 {
|
struct colorspace_rgb888 {
|
||||||
using data_type = uint32_t;
|
using data_type = uint32_t;
|
||||||
|
|
||||||
colorspace_rgb888(float gamma=2.2) : lut{gamma} {}
|
colorspace_rgb888(float gamma = 2.2) : lut{gamma} {}
|
||||||
gamma_lut lut;
|
gamma_lut lut;
|
||||||
const std::span<const uint32_t> convert(std::span<const data_type> data_in) {
|
const std::span<const uint32_t>
|
||||||
|
convert(std::span<const data_type> data_in) {
|
||||||
lut.convert_rgb888_to_rgb10(rgb10, data_in);
|
lut.convert_rgb888_to_rgb10(rgb10, data_in);
|
||||||
return rgb10;
|
return rgb10;
|
||||||
}
|
}
|
||||||
|
|
@ -97,9 +100,10 @@ struct colorspace_rgb888 {
|
||||||
struct colorspace_rgb888_packed {
|
struct colorspace_rgb888_packed {
|
||||||
using data_type = uint8_t;
|
using data_type = uint8_t;
|
||||||
|
|
||||||
colorspace_rgb888_packed(float gamma=2.2) : lut{gamma} {}
|
colorspace_rgb888_packed(float gamma = 2.2) : lut{gamma} {}
|
||||||
gamma_lut lut;
|
gamma_lut lut;
|
||||||
const std::span<const uint32_t> convert(std::span<const data_type> data_in) {
|
const std::span<const uint32_t>
|
||||||
|
convert(std::span<const data_type> data_in) {
|
||||||
lut.convert_rgb888_packed_to_rgb10(rgb10, data_in);
|
lut.convert_rgb888_packed_to_rgb10(rgb10, data_in);
|
||||||
return rgb10;
|
return rgb10;
|
||||||
}
|
}
|
||||||
|
|
@ -109,21 +113,24 @@ struct colorspace_rgb888_packed {
|
||||||
struct colorspace_rgb10 {
|
struct colorspace_rgb10 {
|
||||||
using data_type = uint32_t;
|
using data_type = uint32_t;
|
||||||
|
|
||||||
const std::span<const uint32_t> convert(std::span<const data_type> data_in) {
|
const std::span<const uint32_t>
|
||||||
|
convert(std::span<const data_type> data_in) {
|
||||||
return data_in;
|
return data_in;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Render a buffer in linear RGB10 format into a piomatter stream
|
// Render a buffer in linear RGB10 format into a piomatter stream
|
||||||
template<typename pinout>
|
template <typename pinout>
|
||||||
void protomatter_render_rgb10(std::vector<uint32_t> &result, const matrix_geometry &matrixmap, const uint32_t *pixels) {
|
void protomatter_render_rgb10(std::vector<uint32_t> &result,
|
||||||
|
const matrix_geometry &matrixmap,
|
||||||
|
const uint32_t *pixels) {
|
||||||
result.clear();
|
result.clear();
|
||||||
|
|
||||||
int data_count = 0;
|
int data_count = 0;
|
||||||
|
|
||||||
auto do_delay = [&](uint32_t delay) {
|
auto do_delay = [&](uint32_t delay) {
|
||||||
if (delay == 0) return;
|
if (delay == 0)
|
||||||
|
return;
|
||||||
assert(delay < 1000000);
|
assert(delay < 1000000);
|
||||||
assert(!data_count);
|
assert(!data_count);
|
||||||
result.push_back(command_delay | (delay ? delay - 1 : 0));
|
result.push_back(command_delay | (delay ? delay - 1 : 0));
|
||||||
|
|
@ -139,7 +146,7 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result, const matrix_geomet
|
||||||
|
|
||||||
auto do_data = [&](uint32_t d) {
|
auto do_data = [&](uint32_t d) {
|
||||||
assert(data_count);
|
assert(data_count);
|
||||||
data_count --;
|
data_count--;
|
||||||
result.push_back(d);
|
result.push_back(d);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -151,35 +158,49 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result, const matrix_geomet
|
||||||
|
|
||||||
auto calc_addr_bits = [](int addr) {
|
auto calc_addr_bits = [](int addr) {
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
if(addr & 1) data |= (1 << pinout::PIN_ADDR[0]);
|
if (addr & 1)
|
||||||
if(addr & 2) data |= (1 << pinout::PIN_ADDR[1]);
|
data |= (1 << pinout::PIN_ADDR[0]);
|
||||||
if(addr & 4) data |= (1 << pinout::PIN_ADDR[2]);
|
if (addr & 2)
|
||||||
if constexpr(std::size(pinout::PIN_ADDR) >= 4) {
|
data |= (1 << pinout::PIN_ADDR[1]);
|
||||||
if(addr & 8) data |= (1 << pinout::PIN_ADDR[3]);
|
if (addr & 4)
|
||||||
|
data |= (1 << pinout::PIN_ADDR[2]);
|
||||||
|
if constexpr (std::size(pinout::PIN_ADDR) >= 4) {
|
||||||
|
if (addr & 8)
|
||||||
|
data |= (1 << pinout::PIN_ADDR[3]);
|
||||||
}
|
}
|
||||||
if constexpr(std::size(pinout::PIN_ADDR) >= 5) {
|
if constexpr (std::size(pinout::PIN_ADDR) >= 5) {
|
||||||
if(addr & 16) data |= (1 << pinout::PIN_ADDR[4]);
|
if (addr & 16)
|
||||||
|
data |= (1 << pinout::PIN_ADDR[4]);
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto add_pixels = [&do_data, &result](uint32_t addr_bits, bool r0, bool g0, bool b0, bool r1, bool g1, bool b1, bool active) {
|
auto add_pixels = [&do_data, &result](uint32_t addr_bits, bool r0, bool g0,
|
||||||
uint32_t data = (active ? pinout::oe_active : pinout::oe_inactive) | addr_bits;
|
bool b0, bool r1, bool g1, bool b1,
|
||||||
if(r0) data |= (1 << pinout::PIN_RGB[0]);
|
bool active) {
|
||||||
if(g0) data |= (1 << pinout::PIN_RGB[1]);
|
uint32_t data =
|
||||||
if(b0) data |= (1 << pinout::PIN_RGB[2]);
|
(active ? pinout::oe_active : pinout::oe_inactive) | addr_bits;
|
||||||
if(r1) data |= (1 << pinout::PIN_RGB[3]);
|
if (r0)
|
||||||
if(g1) data |= (1 << pinout::PIN_RGB[4]);
|
data |= (1 << pinout::PIN_RGB[0]);
|
||||||
if(b1) data |= (1 << pinout::PIN_RGB[5]);
|
if (g0)
|
||||||
|
data |= (1 << pinout::PIN_RGB[1]);
|
||||||
|
if (b0)
|
||||||
|
data |= (1 << pinout::PIN_RGB[2]);
|
||||||
|
if (r1)
|
||||||
|
data |= (1 << pinout::PIN_RGB[3]);
|
||||||
|
if (g1)
|
||||||
|
data |= (1 << pinout::PIN_RGB[4]);
|
||||||
|
if (b1)
|
||||||
|
data |= (1 << pinout::PIN_RGB[5]);
|
||||||
|
|
||||||
do_data(data);
|
do_data(data);
|
||||||
do_data(data | pinout::clk_bit);
|
do_data(data | pinout::clk_bit);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int last_bit = 0;
|
int last_bit = 0;
|
||||||
int prev_addr = 7;
|
int prev_addr = 7;
|
||||||
// illuminate the right row for data in the shift register (the previous address)
|
// illuminate the right row for data in the shift register (the previous
|
||||||
|
// address)
|
||||||
uint32_t addr_bits = calc_addr_bits(prev_addr);
|
uint32_t addr_bits = calc_addr_bits(prev_addr);
|
||||||
|
|
||||||
const auto n_addr = 1u << matrixmap.n_addr_lines;
|
const auto n_addr = 1u << matrixmap.n_addr_lines;
|
||||||
|
|
@ -188,21 +209,21 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result, const matrix_geomet
|
||||||
unsigned offset = n_bits - n_planes;
|
unsigned offset = n_bits - n_planes;
|
||||||
const auto pixels_across = matrixmap.pixels_across;
|
const auto pixels_across = matrixmap.pixels_across;
|
||||||
|
|
||||||
for(int addr = 0; addr < n_addr; addr++) {
|
for (int addr = 0; addr < n_addr; addr++) {
|
||||||
for(int bit = n_planes - 1; bit >= 0; bit--) {
|
for (int bit = n_planes - 1; bit >= 0; bit--) {
|
||||||
uint32_t r = 1 << (20 + offset + bit);
|
uint32_t r = 1 << (20 + offset + bit);
|
||||||
uint32_t g = 1 << (10 + offset + bit);
|
uint32_t g = 1 << (10 + offset + bit);
|
||||||
uint32_t b = 1 << (0 + offset + bit);
|
uint32_t b = 1 << (0 + offset + bit);
|
||||||
|
|
||||||
// the shortest /OE we can do is one DATA_OVERHEAD...
|
// the shortest /OE we can do is one DATA_OVERHEAD...
|
||||||
// TODO: should make sure desired duration of MSB is at least `pixels_across`
|
// TODO: should make sure desired duration of MSB is at least
|
||||||
|
// `pixels_across`
|
||||||
uint32_t desired_duration = 1 << last_bit;
|
uint32_t desired_duration = 1 << last_bit;
|
||||||
last_bit = bit;
|
last_bit = bit;
|
||||||
|
|
||||||
|
|
||||||
prep_data(2 * pixels_across);
|
prep_data(2 * pixels_across);
|
||||||
auto mapiter = matrixmap.map.begin() + 2 * addr * pixels_across;
|
auto mapiter = matrixmap.map.begin() + 2 * addr * pixels_across;
|
||||||
for(int x = 0; x < pixels_across; x++) {
|
for (int x = 0; x < pixels_across; x++) {
|
||||||
assert(mapiter != matrixmap.map.end());
|
assert(mapiter != matrixmap.map.end());
|
||||||
auto pixel0 = pixels[*mapiter++];
|
auto pixel0 = pixels[*mapiter++];
|
||||||
auto r0 = pixel0 & r;
|
auto r0 = pixel0 & r;
|
||||||
|
|
@ -214,26 +235,32 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result, const matrix_geomet
|
||||||
auto g1 = pixel1 & g;
|
auto g1 = pixel1 & g;
|
||||||
auto b1 = pixel1 & b;
|
auto b1 = pixel1 & b;
|
||||||
|
|
||||||
add_pixels(addr_bits, r0, g0, b0, r1, g1, b1, x < desired_duration);
|
add_pixels(addr_bits, r0, g0, b0, r1, g1, b1,
|
||||||
|
x < desired_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// hold /OE low until desired time has elapsed to illuminate the LAST line
|
// hold /OE low until desired time has elapsed to illuminate the
|
||||||
|
// LAST line
|
||||||
int remain = desired_duration - pixels_across;
|
int remain = desired_duration - pixels_across;
|
||||||
if (remain > 0) {
|
if (remain > 0) {
|
||||||
do_data_delay(addr_bits | pinout::oe_active, remain * CLOCKS_PER_DATA - DELAY_OVERHEAD);
|
do_data_delay(addr_bits | pinout::oe_active,
|
||||||
|
remain * CLOCKS_PER_DATA - DELAY_OVERHEAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
do_data_delay(addr_bits | pinout::oe_inactive, pinout::post_oe_delay);
|
do_data_delay(addr_bits | pinout::oe_inactive,
|
||||||
do_data_delay(addr_bits | pinout::oe_inactive | pinout::lat_bit, pinout::post_latch_delay);
|
pinout::post_oe_delay);
|
||||||
|
do_data_delay(addr_bits | pinout::oe_inactive | pinout::lat_bit,
|
||||||
|
pinout::post_latch_delay);
|
||||||
|
|
||||||
// with oe inactive, set address bits to illuminate THIS line
|
// with oe inactive, set address bits to illuminate THIS line
|
||||||
if (addr != prev_addr) {
|
if (addr != prev_addr) {
|
||||||
addr_bits = calc_addr_bits(addr);
|
addr_bits = calc_addr_bits(addr);
|
||||||
do_data_delay(addr_bits | pinout::oe_inactive, pinout::post_addr_delay);
|
do_data_delay(addr_bits | pinout::oe_inactive,
|
||||||
|
pinout::post_addr_delay);
|
||||||
prev_addr = addr;
|
prev_addr = addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace piomatter
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <optional>
|
|
||||||
#include <mutex>
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
namespace piomatter {
|
namespace piomatter {
|
||||||
|
|
||||||
template<class T>
|
template <class T> struct thread_queue {
|
||||||
struct thread_queue {
|
|
||||||
thread_queue() : queue{}, mutex{}, cv{} {}
|
thread_queue() : queue{}, mutex{}, cv{} {}
|
||||||
|
|
||||||
void push(T t) {
|
void push(T t) {
|
||||||
|
|
@ -18,7 +17,9 @@ struct thread_queue {
|
||||||
|
|
||||||
std::optional<T> pop_nonblocking() {
|
std::optional<T> pop_nonblocking() {
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
if (queue.empty()) { return {}; }
|
if (queue.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
T val = queue.front();
|
T val = queue.front();
|
||||||
queue.pop();
|
queue.pop();
|
||||||
return val;
|
return val;
|
||||||
|
|
@ -26,15 +27,18 @@ struct thread_queue {
|
||||||
|
|
||||||
T pop_blocking() {
|
T pop_blocking() {
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
while (queue.empty()) { cv.wait(lock); }
|
while (queue.empty()) {
|
||||||
|
cv.wait(lock);
|
||||||
|
}
|
||||||
T val = queue.front();
|
T val = queue.front();
|
||||||
queue.pop();
|
queue.pop();
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
|
private:
|
||||||
std::queue<T> queue;
|
std::queue<T> queue;
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace piomatter
|
||||||
|
|
|
||||||
96
protodemo.c
96
protodemo.c
|
|
@ -1,10 +1,10 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "piomatter/piomatter.h"
|
#include "piomatter/piomatter.h"
|
||||||
|
|
||||||
|
|
@ -12,30 +12,46 @@
|
||||||
#define r (255 << 16)
|
#define r (255 << 16)
|
||||||
#define g (255 << 8)
|
#define g (255 << 8)
|
||||||
#define b (255)
|
#define b (255)
|
||||||
#define y (r|g)
|
#define y (r | g)
|
||||||
#define c (g|b)
|
#define c (g | b)
|
||||||
#define m (r|b)
|
#define m (r | b)
|
||||||
#define w (r|g|b)
|
#define w (r | g | b)
|
||||||
|
|
||||||
constexpr int width = 64, height = 64;
|
constexpr int width = 64, height = 64;
|
||||||
|
|
||||||
uint32_t pixels[height][width] = {
|
uint32_t pixels[height][width] = {
|
||||||
{_,w,_,_,r,r,_,_,_,g,_,_,b,b,b,_,c,c,_,_,y,_,y,_,m,m,m,_,w,w,w,_}, // 0
|
{_, w, _, _, r, r, _, _, _, g, _, _, b, b, b, _,
|
||||||
{w,_,w,_,r,_,r,_,g,_,g,_,b,_,_,_,c,_,c,_,y,_,y,_,_,m,_,_,_,w,_,_}, // 1
|
c, c, _, _, y, _, y, _, m, m, m, _, w, w, w, _}, // 0
|
||||||
{w,w,w,_,r,_,r,_,g,g,g,_,b,b,_,_,c,c,_,_,y,_,y,_,_,m,_,_,_,w,_,_}, // 2
|
{w, _, w, _, r, _, r, _, g, _, g, _, b, _, _, _,
|
||||||
{w,_,w,_,r,_,r,_,g,_,g,_,b,_,_,_,c,_,c,_,y,_,y,_,_,m,_,_,_,w,_,_}, // 3
|
c, _, c, _, y, _, y, _, _, m, _, _, _, w, _, _}, // 1
|
||||||
{w,_,w,_,r,r,_,_,g,_,g,_,b,_,_,_,c,_,c,_,_,y,_,_,m,m,m,_,_,w,_,_}, // 4
|
{w, w, w, _, r, _, r, _, g, g, g, _, b, b, _, _,
|
||||||
{_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_}, // 5
|
c, c, _, _, y, _, y, _, _, m, _, _, _, w, _, _}, // 2
|
||||||
{_,c,_,_,y,y,_,_,_,m,_,_,r,r,r,_,g,g,_,_,b,_,b,_,w,w,w,_,c,c,c,_}, // 6
|
{w, _, w, _, r, _, r, _, g, _, g, _, b, _, _, _,
|
||||||
{c,_,c,_,y,_,y,_,m,_,m,_,r,_,_,_,g,_,g,_,b,_,b,_,_,w,_,_,_,c,_,_}, // 7
|
c, _, c, _, y, _, y, _, _, m, _, _, _, w, _, _}, // 3
|
||||||
{c,c,c,_,y,_,y,_,m,m,m,_,r,r,_,_,g,g,_,_,b,_,b,_,_,w,_,_,_,c,_,_}, // 8
|
{w, _, w, _, r, r, _, _, g, _, g, _, b, _, _, _,
|
||||||
{c,_,c,_,y,_,y,_,m,_,m,_,r,_,_,_,g,_,g,_,b,_,b,_,_,w,_,_,_,c,_,_}, // 9
|
c, _, c, _, _, y, _, _, m, m, m, _, _, w, _, _}, // 4
|
||||||
{c,_,c,_,y,y,_,_,m,_,m,_,r,_,_,_,g,_,g,_,_,b,_,_,w,w,w,_,_,c,_,_}, // 10
|
{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
|
||||||
{_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_}, // 11
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}, // 5
|
||||||
{r,y,g,c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,g}, // 12
|
{_, c, _, _, y, y, _, _, _, m, _, _, r, r, r, _,
|
||||||
{y,g,c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,g,y}, // 13
|
g, g, _, _, b, _, b, _, w, w, w, _, c, c, c, _}, // 6
|
||||||
{g,c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,g,c,b}, // 14
|
{c, _, c, _, y, _, y, _, m, _, m, _, r, _, _, _,
|
||||||
{c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,y,g,c,b,m,r,g,c,b,m}, // 15
|
g, _, g, _, b, _, b, _, _, w, _, _, _, c, _, _}, // 7
|
||||||
|
{c, c, c, _, y, _, y, _, m, m, m, _, r, r, _, _,
|
||||||
|
g, g, _, _, b, _, b, _, _, w, _, _, _, c, _, _}, // 8
|
||||||
|
{c, _, c, _, y, _, y, _, m, _, m, _, r, _, _, _,
|
||||||
|
g, _, g, _, b, _, b, _, _, w, _, _, _, c, _, _}, // 9
|
||||||
|
{c, _, c, _, y, y, _, _, m, _, m, _, r, _, _, _,
|
||||||
|
g, _, g, _, _, b, _, _, w, w, w, _, _, c, _, _}, // 10
|
||||||
|
{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
|
||||||
|
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}, // 11
|
||||||
|
{r, y, g, c, b, m, r, y, g, c, b, m, r, y, g, c,
|
||||||
|
b, m, r, y, g, c, b, m, r, y, g, c, b, m, r, g}, // 12
|
||||||
|
{y, g, c, b, m, r, y, g, c, b, m, r, y, g, c, b,
|
||||||
|
m, r, y, g, c, b, m, r, y, g, c, b, m, r, g, y}, // 13
|
||||||
|
{g, c, b, m, r, y, g, c, b, m, r, y, g, c, b, m,
|
||||||
|
r, y, g, c, b, m, r, y, g, c, b, m, r, g, c, b}, // 14
|
||||||
|
{c, b, m, r, y, g, c, b, m, r, y, g, c, b, m, r,
|
||||||
|
y, g, c, b, m, r, y, g, c, b, m, r, g, c, b, m}, // 15
|
||||||
};
|
};
|
||||||
#undef r
|
#undef r
|
||||||
#undef g
|
#undef g
|
||||||
|
|
@ -45,14 +61,14 @@ uint32_t pixels[height][width] = {
|
||||||
#undef w
|
#undef w
|
||||||
#undef _
|
#undef _
|
||||||
|
|
||||||
#define rgb(r,g,b) ((r << 16) | (g << 8) | b)
|
#define rgb(r, g, b) ((r << 16) | (g << 8) | b)
|
||||||
|
|
||||||
uint32_t colorwheel(int i) {
|
uint32_t colorwheel(int i) {
|
||||||
i = i & 0xff;
|
i = i & 0xff;
|
||||||
if(i < 85) {
|
if (i < 85) {
|
||||||
return rgb(255 - i * 3, 0, i * 3);
|
return rgb(255 - i * 3, 0, i * 3);
|
||||||
}
|
}
|
||||||
if(i < 170) {
|
if (i < 170) {
|
||||||
i -= 85;
|
i -= 85;
|
||||||
return rgb(0, i * 3, 255 - i * 3);
|
return rgb(0, i * 3, 255 - i * 3);
|
||||||
}
|
}
|
||||||
|
|
@ -61,15 +77,15 @@ uint32_t colorwheel(int i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_pattern(int offs) {
|
void test_pattern(int offs) {
|
||||||
for(int i=0; i<width; i++) {
|
for (int i = 0; i < width; i++) {
|
||||||
pixels[height-5][i] = rgb(1+i*4, 1+i*4, 1+i*4);
|
pixels[height - 5][i] = rgb(1 + i * 4, 1 + i * 4, 1 + i * 4);
|
||||||
pixels[height-4][i] = colorwheel(2*i + offs / 3);
|
pixels[height - 4][i] = colorwheel(2 * i + offs / 3);
|
||||||
pixels[height-3][i] = colorwheel(2*i+64 + offs / 5);
|
pixels[height - 3][i] = colorwheel(2 * i + 64 + offs / 5);
|
||||||
pixels[height-2][i] = colorwheel(2*i+128 + offs / 2);
|
pixels[height - 2][i] = colorwheel(2 * i + 128 + offs / 2);
|
||||||
pixels[height-1][i] = colorwheel(2*i+192 + offs / 7);
|
pixels[height - 1][i] = colorwheel(2 * i + 192 + offs / 7);
|
||||||
}
|
}
|
||||||
for(int i=0; i<height; i++) {
|
for (int i = 0; i < height; i++) {
|
||||||
pixels[i][i] = rgb(0xff,0xff,0xff);
|
pixels[i][i] = rgb(0xff, 0xff, 0xff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,18 +93,18 @@ static uint64_t monotonicns64() {
|
||||||
|
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||||
return tp.tv_sec * UINT64_C(1000000000)+ tp.tv_nsec;
|
return tp.tv_sec * UINT64_C(1000000000) + tp.tv_nsec;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
int n = argc > 1 ? atoi(argv[1]) : 0;
|
int n = argc > 1 ? atoi(argv[1]) : 0;
|
||||||
|
|
||||||
piomatter::matrix_geometry geometry(128, 4, 10, 64, 64, true, piomatter::orientation_normal);
|
piomatter::matrix_geometry geometry(128, 4, 10, 64, 64, true,
|
||||||
piomatter::piomatter p(std::span(&pixels[0][0], 64*64), geometry);
|
piomatter::orientation_normal);
|
||||||
|
piomatter::piomatter p(std::span(&pixels[0][0], 64 * 64), geometry);
|
||||||
|
|
||||||
uint64_t start = monotonicns64();
|
uint64_t start = monotonicns64();
|
||||||
for(int i=0; i<n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
test_pattern(i);
|
test_pattern(i);
|
||||||
p.show();
|
p.show();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue