Double the pixel clock rate
.. by moving the "assert CLK after each data" into the PIO program, cutting the amount of PIO data in half.
This commit is contained in:
parent
a532a9105e
commit
3d6b58f74d
5 changed files with 44 additions and 51 deletions
|
|
@ -1,29 +1,26 @@
|
||||||
import sys
|
import io
|
||||||
from contextlib import contextmanager
|
import pathlib
|
||||||
|
from contextlib import redirect_stdout
|
||||||
|
|
||||||
import adafruit_pioasm
|
import adafruit_pioasm
|
||||||
import click
|
import click
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def temporary_stdout(filename):
|
|
||||||
old_stdout = sys.stdout
|
|
||||||
try:
|
|
||||||
with open(filename, "w", encoding="utf-8") as sys.stdout:
|
|
||||||
yield sys.stdout
|
|
||||||
finally:
|
|
||||||
sys.stdout = old_stdout
|
|
||||||
|
|
||||||
@click.command
|
@click.command
|
||||||
@click.argument("infile")
|
@click.argument("infile")
|
||||||
@click.argument("outfile")
|
@click.argument("outfile")
|
||||||
def main(infile, outfile):
|
def main(infile, outfile):
|
||||||
program_name = infile.rpartition("/")[2].partition(".")[0]
|
program_name = pathlib.Path(infile).stem
|
||||||
print(program_name)
|
|
||||||
program = adafruit_pioasm.Program.from_file(infile, build_debuginfo=True)
|
program = adafruit_pioasm.Program.from_file(infile, build_debuginfo=True)
|
||||||
|
|
||||||
with temporary_stdout(outfile):
|
c_program = io.StringIO()
|
||||||
|
with redirect_stdout(c_program):
|
||||||
program.print_c_program(program_name)
|
program.print_c_program(program_name)
|
||||||
|
|
||||||
|
with open(outfile, "w", encoding="utf-8") as out:
|
||||||
|
print("#pragma once", file=out)
|
||||||
|
print("", file=out)
|
||||||
|
print(c_program.getvalue().rstrip().replace("True", "true"), file=out)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,8 @@ struct piomatter : piomatter_base {
|
||||||
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,
|
sm_config_set_wrap(&c, offset + protomatter_wrap_target,
|
||||||
offset + protomatter_wrap);
|
offset + protomatter_wrap);
|
||||||
|
// 1 side-set pin
|
||||||
|
sm_config_set_sideset(&c, 2, true, false);
|
||||||
sm_config_set_out_shift(&c, /* shift_right= */ false,
|
sm_config_set_out_shift(&c, /* shift_right= */ false,
|
||||||
/* auto_pull = */ true, 32);
|
/* auto_pull = */ true, 32);
|
||||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||||
|
|
@ -119,10 +121,11 @@ struct piomatter : piomatter_base {
|
||||||
// frequency is approximately the best sustainable clock with current
|
// frequency is approximately the best sustainable clock with current
|
||||||
// FW & kernel.
|
// FW & kernel.
|
||||||
constexpr double target_freq =
|
constexpr double target_freq =
|
||||||
2700000; // 2.7MHz PIO clock -> 1.35MHz pixel clock
|
2700000 * 2; // 2.7MHz pixel clock, 2 PIO cycles per pixel
|
||||||
double div = clock_get_hz(clk_sys) / target_freq;
|
double div = clock_get_hz(clk_sys) / target_freq;
|
||||||
sm_config_set_clkdiv(&c, div);
|
sm_config_set_clkdiv(&c, div);
|
||||||
sm_config_set_out_pins(&c, 0, 28);
|
sm_config_set_out_pins(&c, 0, 28);
|
||||||
|
sm_config_set_sideset_pins(&c, pinout::PIN_CLK);
|
||||||
pio_sm_init(pio, sm, offset, &c);
|
pio_sm_init(pio, sm, offset, &c);
|
||||||
pio_sm_set_enabled(pio, sm, true);
|
pio_sm_set_enabled(pio, sm, true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,24 +2,27 @@
|
||||||
|
|
||||||
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 = 1;
|
||||||
const bool protomatter_sideset_enable = 0;
|
const bool protomatter_sideset_enable = true;
|
||||||
const uint16_t protomatter[] = {
|
const uint16_t protomatter[] = {
|
||||||
// ; data format (out-shift-right):
|
// ; data format (out-shift-right):
|
||||||
// ; MSB ... LSB
|
// ; MSB ... LSB
|
||||||
// ; 0 ddd......ddd: 31-bit delay
|
// ; 0 ddd......ddd: 31-bit delay
|
||||||
// ; 1 ccc......ccc: 31 bit data count
|
// ; 1 ccc......ccc: 31 bit data count
|
||||||
|
// .side_set 1 opt
|
||||||
// .wrap_target
|
// .wrap_target
|
||||||
// top:
|
// top:
|
||||||
0x6021, // out x, 1
|
0x6021, // out x, 1
|
||||||
0x605f, // out y, 31
|
0x605f, // out y, 31
|
||||||
0x0025, // jmp !x delay_loop
|
0x0025, // jmp !x do_delay
|
||||||
// data_loop:
|
// data_loop:
|
||||||
0x6000, // out pins, 32
|
0x6000, // out pins, 32
|
||||||
0x0083, // jmp y--, data_loop
|
0x1883, // jmp y--, data_loop side 1 ; assert clk bit
|
||||||
// .wrap
|
// .wrap
|
||||||
|
// do_delay:
|
||||||
|
0x6000, // out pins, 32
|
||||||
// delay_loop:
|
// delay_loop:
|
||||||
0x0085, // jmp y--, delay_loop
|
0x0086, // jmp y--, delay_loop
|
||||||
0x0000, // jmp top
|
0x0000, // jmp top
|
||||||
// ;; fill program out to 32 instructions so nothing else can load
|
// ;; fill program out to 32 instructions so nothing else can load
|
||||||
0xa042, // nop
|
0xa042, // nop
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@
|
||||||
|
|
||||||
namespace piomatter {
|
namespace piomatter {
|
||||||
|
|
||||||
constexpr unsigned DATA_OVERHEAD = 3;
|
constexpr int DATA_OVERHEAD = 3;
|
||||||
constexpr unsigned CLOCKS_PER_DATA = 2;
|
constexpr int CLOCKS_PER_DATA = 2;
|
||||||
constexpr unsigned DELAY_OVERHEAD = 5;
|
constexpr int DELAY_OVERHEAD = 5;
|
||||||
constexpr unsigned CLOCKS_PER_DELAY = 1;
|
constexpr int 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;
|
||||||
|
|
@ -137,12 +137,12 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
|
||||||
|
|
||||||
int data_count = 0;
|
int data_count = 0;
|
||||||
|
|
||||||
auto do_delay = [&](uint32_t delay) {
|
auto do_data_delay = [&](uint32_t data, int32_t delay) {
|
||||||
if (delay == 0)
|
delay = std::max((delay / CLOCKS_PER_DELAY) - DELAY_OVERHEAD, 1);
|
||||||
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));
|
||||||
|
result.push_back(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto prep_data = [&data_count, &result](uint32_t n) {
|
auto prep_data = [&data_count, &result](uint32_t n) {
|
||||||
|
|
@ -153,27 +153,15 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
|
||||||
data_count = n;
|
data_count = n;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto do_data = [&](uint32_t d) {
|
|
||||||
assert(data_count);
|
|
||||||
data_count--;
|
|
||||||
result.push_back(d);
|
|
||||||
};
|
|
||||||
|
|
||||||
int32_t active_time;
|
int32_t active_time;
|
||||||
|
|
||||||
auto do_data_active = [&active_time, &do_data](uint32_t d) {
|
auto do_data_clk_active = [&active_time, &data_count, &result](uint32_t d) {
|
||||||
bool active = active_time > 0;
|
bool active = active_time > 0;
|
||||||
active_time--;
|
active_time--;
|
||||||
d |= active ? pinout::oe_active : pinout::oe_inactive;
|
d |= active ? pinout::oe_active : pinout::oe_inactive;
|
||||||
do_data(d);
|
assert(data_count);
|
||||||
};
|
data_count--;
|
||||||
|
result.push_back(d);
|
||||||
auto do_data_delay = [&prep_data, &do_data, &do_delay](uint32_t d,
|
|
||||||
int32_t delay) {
|
|
||||||
prep_data(1);
|
|
||||||
do_data(d);
|
|
||||||
if (delay > 0)
|
|
||||||
do_delay(delay);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto calc_addr_bits = [](int addr) {
|
auto calc_addr_bits = [](int addr) {
|
||||||
|
|
@ -195,9 +183,9 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto add_pixels = [&do_data_active, &result](uint32_t addr_bits, bool r0,
|
auto add_pixels = [&do_data_clk_active,
|
||||||
bool g0, bool b0, bool r1,
|
&result](uint32_t addr_bits, bool r0, bool g0, bool b0,
|
||||||
bool g1, bool b1) {
|
bool r1, bool g1, bool b1) {
|
||||||
uint32_t data = addr_bits;
|
uint32_t data = addr_bits;
|
||||||
if (r0)
|
if (r0)
|
||||||
data |= (1 << pinout::PIN_RGB[0]);
|
data |= (1 << pinout::PIN_RGB[0]);
|
||||||
|
|
@ -212,8 +200,7 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
|
||||||
if (b1)
|
if (b1)
|
||||||
data |= (1 << pinout::PIN_RGB[5]);
|
data |= (1 << pinout::PIN_RGB[5]);
|
||||||
|
|
||||||
do_data_active(data);
|
do_data_clk_active(data);
|
||||||
do_data_active(data | pinout::clk_bit);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int last_bit = 0;
|
int last_bit = 0;
|
||||||
|
|
@ -243,7 +230,7 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
|
||||||
active_time = 1 << last_bit;
|
active_time = 1 << last_bit;
|
||||||
last_bit = bit;
|
last_bit = bit;
|
||||||
|
|
||||||
prep_data(2 * pixels_across);
|
prep_data(pixels_across);
|
||||||
auto mapiter = matrixmap.map.begin() + 2 * addr * pixels_across;
|
auto mapiter = matrixmap.map.begin() + 2 * addr * pixels_across;
|
||||||
for (size_t x = 0; x < pixels_across; x++) {
|
for (size_t x = 0; x < pixels_across; x++) {
|
||||||
assert(mapiter != matrixmap.map.end());
|
assert(mapiter != matrixmap.map.end());
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,20 @@
|
||||||
; 0 ddd......ddd: 31-bit delay
|
; 0 ddd......ddd: 31-bit delay
|
||||||
; 1 ccc......ccc: 31 bit data count
|
; 1 ccc......ccc: 31 bit data count
|
||||||
|
|
||||||
|
.side_set 1 opt
|
||||||
.wrap_target
|
.wrap_target
|
||||||
top:
|
top:
|
||||||
out x, 1
|
out x, 1
|
||||||
out y, 31
|
out y, 31
|
||||||
jmp !x delay_loop
|
jmp !x do_delay
|
||||||
|
|
||||||
data_loop:
|
data_loop:
|
||||||
out pins, 32
|
out pins, 32
|
||||||
jmp y--, data_loop
|
jmp y--, data_loop side 1 ; assert clk bit
|
||||||
.wrap
|
.wrap
|
||||||
|
|
||||||
|
do_delay:
|
||||||
|
out pins, 32
|
||||||
delay_loop:
|
delay_loop:
|
||||||
jmp y--, delay_loop
|
jmp y--, delay_loop
|
||||||
jmp top
|
jmp top
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue