diff --git a/src/assemble.py b/src/assemble.py index 645d656..400898d 100644 --- a/src/assemble.py +++ b/src/assemble.py @@ -1,29 +1,26 @@ -import sys -from contextlib import contextmanager +import io +import pathlib +from contextlib import redirect_stdout import adafruit_pioasm 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.argument("infile") @click.argument("outfile") def main(infile, outfile): - program_name = infile.rpartition("/")[2].partition(".")[0] - print(program_name) + program_name = pathlib.Path(infile).stem 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) + 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__': main() diff --git a/src/include/piomatter/piomatter.h b/src/include/piomatter/piomatter.h index 062c5d4..0f63e4d 100644 --- a/src/include/piomatter/piomatter.h +++ b/src/include/piomatter/piomatter.h @@ -111,6 +111,8 @@ struct piomatter : piomatter_base { pio_sm_config c = pio_get_default_sm_config(); sm_config_set_wrap(&c, offset + protomatter_wrap_target, offset + protomatter_wrap); + // 1 side-set pin + sm_config_set_sideset(&c, 2, true, false); sm_config_set_out_shift(&c, /* shift_right= */ false, /* auto_pull = */ true, 32); 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 // FW & kernel. 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; sm_config_set_clkdiv(&c, div); 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_set_enabled(pio, sm, true); diff --git a/src/include/piomatter/protomatter.pio.h b/src/include/piomatter/protomatter.pio.h index 0a2d84b..73485e2 100644 --- a/src/include/piomatter/protomatter.pio.h +++ b/src/include/piomatter/protomatter.pio.h @@ -2,24 +2,27 @@ const int protomatter_wrap = 4; const int protomatter_wrap_target = 0; -const int protomatter_sideset_pin_count = 0; -const bool protomatter_sideset_enable = 0; +const int protomatter_sideset_pin_count = 1; +const bool protomatter_sideset_enable = true; const uint16_t protomatter[] = { // ; data format (out-shift-right): // ; MSB ... LSB // ; 0 ddd......ddd: 31-bit delay // ; 1 ccc......ccc: 31 bit data count + // .side_set 1 opt // .wrap_target // top: 0x6021, // out x, 1 0x605f, // out y, 31 - 0x0025, // jmp !x delay_loop + 0x0025, // jmp !x do_delay // data_loop: 0x6000, // out pins, 32 - 0x0083, // jmp y--, data_loop + 0x1883, // jmp y--, data_loop side 1 ; assert clk bit // .wrap + // do_delay: + 0x6000, // out pins, 32 // delay_loop: - 0x0085, // jmp y--, delay_loop + 0x0086, // jmp y--, delay_loop 0x0000, // jmp top // ;; fill program out to 32 instructions so nothing else can load 0xa042, // nop diff --git a/src/include/piomatter/render.h b/src/include/piomatter/render.h index 4e8abe8..12c49c4 100644 --- a/src/include/piomatter/render.h +++ b/src/include/piomatter/render.h @@ -7,10 +7,10 @@ namespace piomatter { -constexpr unsigned DATA_OVERHEAD = 3; -constexpr unsigned CLOCKS_PER_DATA = 2; -constexpr unsigned DELAY_OVERHEAD = 5; -constexpr unsigned CLOCKS_PER_DELAY = 1; +constexpr int DATA_OVERHEAD = 3; +constexpr int CLOCKS_PER_DATA = 2; +constexpr int DELAY_OVERHEAD = 5; +constexpr int CLOCKS_PER_DELAY = 1; constexpr uint32_t command_data = 1u << 31; constexpr uint32_t command_delay = 0; @@ -137,12 +137,12 @@ void protomatter_render_rgb10(std::vector &result, int data_count = 0; - auto do_delay = [&](uint32_t delay) { - if (delay == 0) - return; + auto do_data_delay = [&](uint32_t data, int32_t delay) { + delay = std::max((delay / CLOCKS_PER_DELAY) - DELAY_OVERHEAD, 1); assert(delay < 1000000); assert(!data_count); result.push_back(command_delay | (delay ? delay - 1 : 0)); + result.push_back(data); }; auto prep_data = [&data_count, &result](uint32_t n) { @@ -153,27 +153,15 @@ void protomatter_render_rgb10(std::vector &result, data_count = n; }; - auto do_data = [&](uint32_t d) { - assert(data_count); - data_count--; - result.push_back(d); - }; - 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; active_time--; d |= active ? pinout::oe_active : pinout::oe_inactive; - do_data(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); + assert(data_count); + data_count--; + result.push_back(d); }; auto calc_addr_bits = [](int addr) { @@ -195,9 +183,9 @@ void protomatter_render_rgb10(std::vector &result, return data; }; - auto add_pixels = [&do_data_active, &result](uint32_t addr_bits, bool r0, - bool g0, bool b0, bool r1, - bool g1, bool b1) { + auto add_pixels = [&do_data_clk_active, + &result](uint32_t addr_bits, bool r0, bool g0, bool b0, + bool r1, bool g1, bool b1) { uint32_t data = addr_bits; if (r0) data |= (1 << pinout::PIN_RGB[0]); @@ -212,8 +200,7 @@ void protomatter_render_rgb10(std::vector &result, if (b1) data |= (1 << pinout::PIN_RGB[5]); - do_data_active(data); - do_data_active(data | pinout::clk_bit); + do_data_clk_active(data); }; int last_bit = 0; @@ -243,7 +230,7 @@ void protomatter_render_rgb10(std::vector &result, active_time = 1 << last_bit; last_bit = bit; - prep_data(2 * pixels_across); + prep_data(pixels_across); auto mapiter = matrixmap.map.begin() + 2 * addr * pixels_across; for (size_t x = 0; x < pixels_across; x++) { assert(mapiter != matrixmap.map.end()); diff --git a/src/protomatter.pio b/src/protomatter.pio index c4f082a..1aef1f2 100644 --- a/src/protomatter.pio +++ b/src/protomatter.pio @@ -3,17 +3,20 @@ ; 0 ddd......ddd: 31-bit delay ; 1 ccc......ccc: 31 bit data count +.side_set 1 opt .wrap_target top: out x, 1 out y, 31 - jmp !x delay_loop + jmp !x do_delay data_loop: out pins, 32 - jmp y--, data_loop + jmp y--, data_loop side 1 ; assert clk bit .wrap +do_delay: + out pins, 32 delay_loop: jmp y--, delay_loop jmp top