Skip to content

Commit

Permalink
Merge pull request #5 from adafruit/fixgamma
Browse files Browse the repository at this point in the history
fix gamma curve, it was all broken!
  • Loading branch information
jepler authored Jan 16, 2025
2 parents 3658640 + eddb20c commit b015674
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 22 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
./*.pio.h
protodemo
./build
*.egg-info
8 changes: 7 additions & 1 deletion examples/playframes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import glob
import sys
import time

import adafruit_raspberry_pi5_piomatter
import numpy as np
Expand All @@ -20,10 +21,15 @@

geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=64, height=32, n_addr_lines=4, rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
framebuffer = np.asarray(Image.open(images[0])) + 0 # Make a mutable copy
nimages = len(images)
matrix = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB888Packed(framebuffer, geometry)

while True:
t0 = time.monotonic()
for i in images:
print(i)
framebuffer[:] = np.asarray(Image.open(i))
matrix.show()
t1 = time.monotonic()
dt = t1 - t0
fps = nimages/dt
print(f"{nimages} frames in {dt}s, {fps}fps")
49 changes: 28 additions & 21 deletions src/include/piomatter/render.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
namespace piomatter {

constexpr unsigned DATA_OVERHEAD = 3;
constexpr unsigned CLOCKS_PER_DATA = 2;
// this is ... flatly wrong!? but it's the number that makes the ramp intensity
// correct to my eye
constexpr unsigned CLOCKS_PER_DATA = 128;
constexpr unsigned DELAY_OVERHEAD = 5;
constexpr unsigned CLOCKS_PER_DELAY = 1;

Expand All @@ -18,7 +20,7 @@ constexpr uint32_t command_delay = 0;
struct gamma_lut {
gamma_lut(double exponent = 2.2) {
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;
}
}
Expand Down Expand Up @@ -159,10 +161,21 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
result.push_back(d);
};

auto do_data_delay = [&](uint32_t d, uint32_t delay) {
int32_t active_time;

auto do_data_active = [&active_time, &do_data](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);
do_delay(delay);
if (delay > 0)
do_delay(delay);
};

auto calc_addr_bits = [](int addr) {
Expand All @@ -184,11 +197,10 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
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) {
uint32_t data =
(active ? pinout::oe_active : pinout::oe_inactive) | addr_bits;
auto add_pixels = [&do_data_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]);
if (g0)
Expand All @@ -202,8 +214,8 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
if (b1)
data |= (1 << pinout::PIN_RGB[5]);

do_data(data);
do_data(data | pinout::clk_bit);
do_data_active(data);
do_data_active(data | pinout::clk_bit);
};

int last_bit = 0;
Expand All @@ -230,7 +242,7 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
// the shortest /OE we can do is one DATA_OVERHEAD...
// TODO: should make sure desired duration of MSB is at least
// `pixels_across`
uint32_t desired_duration = 1 << last_bit;
active_time = 1 << last_bit;
last_bit = bit;

prep_data(2 * pixels_across);
Expand All @@ -247,17 +259,12 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
auto g1 = pixel1 & g;
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);
}

// hold /OE low until desired time has elapsed to illuminate the
// LAST line
int remain = desired_duration - pixels_across;
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,
active_time * CLOCKS_PER_DATA / CLOCKS_PER_DELAY -
DELAY_OVERHEAD);

do_data_delay(addr_bits | pinout::oe_inactive,
pinout::post_oe_delay);
Expand Down

0 comments on commit b015674

Please sign in to comment.