From 48e729d76c54b441f42a174d4ec2c76272f9e8ab Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 12 Dec 2024 20:02:08 -0600 Subject: [PATCH] WIP --- protodemo.c | 101 ++++++++++++++++++++++++++++-------------------- protomatter.pio | 8 ++-- 2 files changed, 63 insertions(+), 46 deletions(-) diff --git a/protodemo.c b/protodemo.c index a6a9a2f..23fdf68 100644 --- a/protodemo.c +++ b/protodemo.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -38,7 +39,7 @@ const uint8_t all_pins[] = { PIN_CLK, PIN_LAT, }; -#define DATA_OVERHEAD (6) +#define DATA_OVERHEAD (5) #define DELAY_OVERHEAD (4) #define CLOCKS_PER_DELAY (1) // 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 c (g|b) #define m (r|b) -#define w (7) +#define w (r|g|b) uint32_t pixels[][ACROSS] = { {_,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_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_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; } uint32_t colorwheel(int i) { + i = i & 0xff; if(i < 85) { 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); } -std::vector test_pattern() { +std::vector test_pattern(int offs, int brightness) { std::vector result; uint32_t time=0; for(int i=0; i test_pattern() { return data; }; - auto add_data_word = [&](uint32_t addr_bits, bool r0, bool g0, bool b0, bool r1, bool g1, bool b1) { - uint32_t data = oe_active | addr_bits; + auto add_pixels = [&](uint32_t addr_bits, bool r0, bool g0, bool b0, bool r1, bool g1, bool b1, bool active) { + uint32_t data = (active ? oe_active : oe_inactive) | addr_bits; if(r0) data |= (1 << PIN_R0); if(g0) data |= (1 << PIN_G0); if(b0) data |= (1 << PIN_B0); @@ -189,20 +197,27 @@ std::vector test_pattern() { if(b1) data |= (1 << PIN_B1); 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--) { - int last_bit = (bit + 1) % 8; - uint32_t desired_duration = 400 << last_bit; // mumble uint32_t r = 1 << (16 + bit); uint32_t g = 1 << (8 + bit); uint32_t b = 1 << bit; 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 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++) { auto pixel0 = pixels[addr][across]; @@ -214,26 +229,26 @@ std::vector test_pattern() { auto g1 = pixel1 & g; 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 duration = t_end - t_start; - printf("line duration %d\n", duration); - // hold /OE low until desired time has elapsed + // hold /OE low until desired time has elapsed to illuminate the LAST line if (duration < desired_duration) { - printf("additional duration %d\n", 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 | 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; } @@ -241,7 +256,6 @@ std::vector test_pattern() { int main(int argc, char **argv) { PIO pio = pio0; 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); @@ -252,25 +266,28 @@ printf("clock %fMHz\n", clock_get_hz(clk_sys)/1e6); pio_sm_set_clkdiv(pio, sm, 1.0); protomatter_program_init(pio, sm, offset); + pio_sm_set_clkdiv(pio, sm, 1.0); - std::vector data = test_pattern(); +std::vector data = test_pattern(0, 0); +FILE *f = fopen("pattern.txt", "w"); +for(auto i: data) { fprintf(f, "0x%08x, ", i); } +fclose(f); - -std::vector 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; + int n = argc > 1 ? atoi(argv[1]) : 1; for(int i=0; i 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); } } diff --git a/protomatter.pio b/protomatter.pio index 2569436..0d6ca1d 100644 --- a/protomatter.pio +++ b/protomatter.pio @@ -10,14 +10,14 @@ top: jmp !x do_delay out x, 3 out pins, 28 - jmp delay_loop - -do_delay: - out x, 31 delay_loop: jmp x--, delay_loop .wrap +do_delay: + out x, 31 + jmp delay_loop + ;; fill program out to 32 instructions so nothing else can load nop nop