WIP
This commit is contained in:
parent
3ea618d155
commit
48e729d76c
2 changed files with 63 additions and 46 deletions
101
protodemo.c
101
protodemo.c
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <cmath>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
@ -38,7 +39,7 @@ const uint8_t all_pins[] = {
|
||||||
PIN_CLK,
|
PIN_CLK,
|
||||||
PIN_LAT,
|
PIN_LAT,
|
||||||
};
|
};
|
||||||
#define DATA_OVERHEAD (6)
|
#define DATA_OVERHEAD (5)
|
||||||
#define DELAY_OVERHEAD (4)
|
#define DELAY_OVERHEAD (4)
|
||||||
#define CLOCKS_PER_DELAY (1)
|
#define CLOCKS_PER_DELAY (1)
|
||||||
// so for example a DATA word with a delay of 3 will take DATA_OVERHEAD+3*CLOCKS_PER_DELAY
|
// so for example a DATA word with a delay of 3 will take DATA_OVERHEAD+3*CLOCKS_PER_DELAY
|
||||||
|
|
@ -81,7 +82,7 @@ static inline void protomatter_program_init(PIO pio, int sm, uint offset) {
|
||||||
#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 (7)
|
#define w (r|g|b)
|
||||||
|
|
||||||
uint32_t pixels[][ACROSS] = {
|
uint32_t pixels[][ACROSS] = {
|
||||||
{_,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,_,c,c,_,_,y,_,y,_,m,m,m,_,w,w,w,_}, // 0
|
||||||
|
|
@ -121,15 +122,19 @@ constexpr uint32_t oe_bit = 1u << PIN_OE;
|
||||||
constexpr uint32_t oe_active = 0;
|
constexpr uint32_t oe_active = 0;
|
||||||
constexpr uint32_t oe_inactive = oe_bit;
|
constexpr uint32_t oe_inactive = oe_bit;
|
||||||
|
|
||||||
constexpr uint32_t pre_latch_delay = 10;
|
constexpr uint32_t post_oe_delay = 10;
|
||||||
constexpr uint32_t post_latch_delay = 17;
|
constexpr uint32_t post_latch_delay = 17;
|
||||||
constexpr uint32_t post_oe_delay = 20;
|
constexpr uint32_t post_addr_delay = 20;
|
||||||
|
|
||||||
uint32_t rgb(int r, int g, int b) {
|
uint32_t rgb(unsigned r, unsigned g, unsigned b) {
|
||||||
|
assert(r < 256);
|
||||||
|
assert(g < 256);
|
||||||
|
assert(b < 256);
|
||||||
return (r << 16) | (g << 8) | b;
|
return (r << 16) | (g << 8) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t colorwheel(int i) {
|
uint32_t colorwheel(int i) {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
@ -141,15 +146,18 @@ uint32_t colorwheel(int i) {
|
||||||
return rgb(i * 3, 255 - i * 3, 0);
|
return rgb(i * 3, 255 - i * 3, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> test_pattern() {
|
std::vector<uint32_t> test_pattern(int offs, int brightness) {
|
||||||
std::vector<uint32_t> result;
|
std::vector<uint32_t> result;
|
||||||
uint32_t time=0;
|
uint32_t time=0;
|
||||||
|
|
||||||
for(int i=0; i<ACROSS; i++) {
|
for(int i=0; i<ACROSS; i++) {
|
||||||
pixels[12][i] = colorwheel(2*i);
|
pixels[11][i] = rgb(i*8, i*8, i*8);
|
||||||
pixels[13][i] = colorwheel(2*i+64);
|
//int j = 255 - i * 8;
|
||||||
pixels[14][i] = colorwheel(2*i+128);
|
//pixels[ 5][i] = rgb(j, j, j);
|
||||||
pixels[15][i] = colorwheel(2*i+192);
|
pixels[12][i] = colorwheel(2*i + offs);
|
||||||
|
pixels[13][i] = colorwheel(2*i+64 + offs);
|
||||||
|
pixels[14][i] = colorwheel(2*i+128 + offs);
|
||||||
|
pixels[15][i] = colorwheel(2*i+192 + offs);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto do_delay = [&](uint32_t delay) {
|
auto do_delay = [&](uint32_t delay) {
|
||||||
|
|
@ -179,8 +187,8 @@ std::vector<uint32_t> test_pattern() {
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto add_data_word = [&](uint32_t addr_bits, bool r0, bool g0, bool b0, bool r1, bool g1, bool b1) {
|
auto add_pixels = [&](uint32_t addr_bits, bool r0, bool g0, bool b0, bool r1, bool g1, bool b1, bool active) {
|
||||||
uint32_t data = oe_active | addr_bits;
|
uint32_t data = (active ? oe_active : oe_inactive) | addr_bits;
|
||||||
if(r0) data |= (1 << PIN_R0);
|
if(r0) data |= (1 << PIN_R0);
|
||||||
if(g0) data |= (1 << PIN_G0);
|
if(g0) data |= (1 << PIN_G0);
|
||||||
if(b0) data |= (1 << PIN_B0);
|
if(b0) data |= (1 << PIN_B0);
|
||||||
|
|
@ -189,20 +197,27 @@ std::vector<uint32_t> test_pattern() {
|
||||||
if(b1) data |= (1 << PIN_B1);
|
if(b1) data |= (1 << PIN_B1);
|
||||||
|
|
||||||
do_data(data, data_delay);
|
do_data(data, data_delay);
|
||||||
do_data(data | clk_bit, data_delay);
|
do_data(data | clk_bit, clock_delay);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t base_active_time = ACROSS * (2 * DATA_OVERHEAD + data_delay + clock_delay);
|
||||||
|
|
||||||
|
int last_bit = 0;
|
||||||
|
int prev_addr = 7;
|
||||||
for(int bit = 7; bit >= 0; bit--) {
|
for(int bit = 7; bit >= 0; bit--) {
|
||||||
int last_bit = (bit + 1) % 8;
|
|
||||||
uint32_t desired_duration = 400 << last_bit; // mumble
|
|
||||||
|
|
||||||
uint32_t r = 1 << (16 + bit);
|
uint32_t r = 1 << (16 + bit);
|
||||||
uint32_t g = 1 << (8 + bit);
|
uint32_t g = 1 << (8 + bit);
|
||||||
uint32_t b = 1 << bit;
|
uint32_t b = 1 << bit;
|
||||||
|
|
||||||
for(int addr = 0; addr < 8; addr++) {
|
for(int addr = 0; addr < 8; addr++) {
|
||||||
|
uint32_t desired_duration = base_active_time << last_bit;
|
||||||
|
last_bit = bit;
|
||||||
uint32_t t_start = time;
|
uint32_t t_start = time;
|
||||||
uint32_t addr_bits = calc_addr_bits((addr + 7) % 8); // address of previous line
|
|
||||||
|
// illuminate the right row for data in the shift register (the previous address)
|
||||||
|
uint32_t addr_bits = calc_addr_bits(prev_addr);
|
||||||
|
prev_addr = addr;
|
||||||
|
|
||||||
for(int across = 0; across < ACROSS; across++) {
|
for(int across = 0; across < ACROSS; across++) {
|
||||||
auto pixel0 = pixels[addr][across];
|
auto pixel0 = pixels[addr][across];
|
||||||
|
|
@ -214,26 +229,26 @@ std::vector<uint32_t> test_pattern() {
|
||||||
auto g1 = pixel1 & g;
|
auto g1 = pixel1 & g;
|
||||||
auto b1 = pixel1 & b;
|
auto b1 = pixel1 & b;
|
||||||
|
|
||||||
add_data_word(addr_bits, r0, g0, b0, r1, g1, b1);
|
add_pixels(addr_bits, r0, g0, b0, r1, g1, b1, across < brightness);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t t_end = time;
|
uint32_t t_end = time;
|
||||||
uint32_t duration = t_end - t_start;
|
uint32_t duration = t_end - t_start;
|
||||||
|
|
||||||
printf("line duration %d\n", duration);
|
// hold /OE low until desired time has elapsed to illuminate the LAST line
|
||||||
// hold /OE low until desired time has elapsed
|
|
||||||
if (duration < desired_duration) {
|
if (duration < desired_duration) {
|
||||||
printf("additional duration %d\n", desired_duration - duration);
|
|
||||||
do_delay(desired_duration - duration);
|
do_delay(desired_duration - duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
do_data(addr_bits | oe_inactive, pre_latch_delay);
|
|
||||||
do_data(addr_bits | oe_inactive | lat_bit, post_latch_delay);
|
|
||||||
addr_bits = calc_addr_bits(addr);
|
|
||||||
do_data(addr_bits | oe_inactive, post_oe_delay);
|
do_data(addr_bits | oe_inactive, post_oe_delay);
|
||||||
|
do_data(addr_bits | oe_inactive | lat_bit, post_latch_delay);
|
||||||
|
|
||||||
|
// with oe inactive, set address bits to illuminate THIS line
|
||||||
|
//addr_bits = calc_addr_bits(addr);
|
||||||
|
do_data(addr_bits | oe_inactive, post_addr_delay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("Time %d (%.1f us)\n", time, time*1e6/clock_get_hz(clk_sys));
|
//printf("Time %d (%.1f us)\n", time, time*1e6/clock_get_hz(clk_sys));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -241,7 +256,6 @@ std::vector<uint32_t> test_pattern() {
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
PIO pio = pio0;
|
PIO pio = pio0;
|
||||||
int sm = pio_claim_unused_sm(pio, true);
|
int sm = pio_claim_unused_sm(pio, true);
|
||||||
pio_sm_config_xfer(pio, sm, PIO_DIR_TO_SM, 256, 1);
|
|
||||||
|
|
||||||
printf("clock %fMHz\n", clock_get_hz(clk_sys)/1e6);
|
printf("clock %fMHz\n", clock_get_hz(clk_sys)/1e6);
|
||||||
|
|
||||||
|
|
@ -252,25 +266,28 @@ printf("clock %fMHz\n", clock_get_hz(clk_sys)/1e6);
|
||||||
pio_sm_set_clkdiv(pio, sm, 1.0);
|
pio_sm_set_clkdiv(pio, sm, 1.0);
|
||||||
|
|
||||||
protomatter_program_init(pio, sm, offset);
|
protomatter_program_init(pio, sm, offset);
|
||||||
|
pio_sm_set_clkdiv(pio, sm, 1.0);
|
||||||
|
|
||||||
std::vector<uint32_t> data = test_pattern();
|
std::vector<uint32_t> data = test_pattern(0, 0);
|
||||||
|
FILE *f = fopen("pattern.txt", "w");
|
||||||
|
for(auto i: data) { fprintf(f, "0x%08x, ", i); }
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
int n = argc > 1 ? atoi(argv[1]) : 1;
|
||||||
std::vector<uint32_t> dc;
|
|
||||||
int rep = 0;
|
|
||||||
while(dc.size() + data.size() < UINT16_MAX / sizeof(uint32_t)) {
|
|
||||||
rep ++;
|
|
||||||
std::copy(data.begin(), data.end(), std::back_inserter(dc));
|
|
||||||
}
|
|
||||||
std::swap(dc, data);
|
|
||||||
|
|
||||||
uint32_t *databuf = &data[0];
|
|
||||||
size_t datasize = data.size() * sizeof(uint32_t);
|
|
||||||
assert(datasize < 65536);
|
|
||||||
|
|
||||||
printf("%zd data elements (%d repetitions)\n", data.size(), rep);
|
|
||||||
int n = argc > 1 ? atoi(argv[1]) : 1;
|
|
||||||
for(int i=0; i<n; i++) {
|
for(int i=0; i<n; i++) {
|
||||||
pio_sm_xfer_data(pio, sm, PIO_DIR_TO_SM, datasize, databuf);
|
float f = (1 + sin(i / 100.)) / 2;
|
||||||
|
int b = int(f * 32);
|
||||||
|
printf("%d\n", b);
|
||||||
|
std::vector<uint32_t> data = test_pattern(i, b);
|
||||||
|
|
||||||
|
uint32_t *databuf = &data[0];
|
||||||
|
size_t datasize = data.size() * sizeof(uint32_t);
|
||||||
|
assert(datasize < 65536);
|
||||||
|
|
||||||
|
if (i == 0) { printf("%zd data elements\n", data.size()); }
|
||||||
|
|
||||||
|
if(i == 0)
|
||||||
|
pio_sm_config_xfer(pio, sm, PIO_DIR_TO_SM, datasize, 1);
|
||||||
|
pio_sm_xfer_data(pio, sm, PIO_DIR_TO_SM, datasize, databuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,14 @@ top:
|
||||||
jmp !x do_delay
|
jmp !x do_delay
|
||||||
out x, 3
|
out x, 3
|
||||||
out pins, 28
|
out pins, 28
|
||||||
jmp delay_loop
|
|
||||||
|
|
||||||
do_delay:
|
|
||||||
out x, 31
|
|
||||||
delay_loop:
|
delay_loop:
|
||||||
jmp x--, delay_loop
|
jmp x--, delay_loop
|
||||||
.wrap
|
.wrap
|
||||||
|
|
||||||
|
do_delay:
|
||||||
|
out x, 31
|
||||||
|
jmp delay_loop
|
||||||
|
|
||||||
;; fill program out to 32 instructions so nothing else can load
|
;; fill program out to 32 instructions so nothing else can load
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue