pm-grid: swap X/Y tempo buttons + full-screen strobe on the downbeat

- Swap X/Y: X now tempo-up, Y tempo-down (match the physical Scroll Pack layout).
- On the master lane's step 0 (the '1'), flash the entire 17x7 matrix at full
  brightness for 80ms — a visual downbeat strobe.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Me Here 2026-06-03 14:52:04 -05:00
parent 86cd4a0242
commit e46ff02c0c

View file

@ -145,6 +145,12 @@ impl<I: I2c> Matrix<I> {
}
}
fn fill(&mut self, v: u8) {
for b in self.fb[1..].iter_mut() {
*b = v;
}
}
fn get(&self, x: i32, y: i32) -> u8 {
if (0..17).contains(&x) && (0..7).contains(&y) {
self.fb[1 + pixel_addr(x, y)]
@ -238,7 +244,8 @@ struct App {
scroll_total: i32,
beatflash: u8,
beatflash_off: i64,
bpm_flash_off: i64, // while >0 and active, Grid/Pendulum briefly show the Ticker so nudges are visible
bpm_flash_off: i64, // while >0 and active, Grid/Pendulum briefly show the Ticker so nudges are visible
full_flash_off: i64, // strobe the WHOLE matrix bright on the downbeat ("the 1")
}
fn master_bar_ns(track: &track_format::Track, tempo: i64) -> i64 {
@ -294,6 +301,7 @@ impl App {
beatflash: 0,
beatflash_off: 0,
bpm_flash_off: 0,
full_flash_off: 0,
};
app.load(0, 0, now_ns);
app
@ -405,6 +413,10 @@ impl App {
while now_ns >= self.next[li] {
self.step[li] = (self.step[li] + 1) % steps;
if li == 0 {
if self.step[li] == 0 {
// the downbeat — strobe the entire matrix bright
self.full_flash_off = now_ns + 80_000_000;
}
self.m_steps += 1;
let bar = (self.m_steps - 1) / steps as i64;
if bar != self.lastbar {
@ -458,6 +470,12 @@ fn lvl_bright(lvl: u8) -> u8 {
// ============================== RENDERING ==============================
fn render<I: I2c>(m: &mut Matrix<I>, app: &App, now_ns: i64) {
// downbeat strobe: the whole matrix at full brightness on "the 1"
if now_ns < app.full_flash_off {
m.fill(255);
m.show();
return;
}
m.clear();
// a tempo nudge briefly forces the Ticker (so X/Y is visible from Grid/Pendulum)
let view = if app.view != View::Ticker && now_ns < app.bpm_flash_off {
@ -708,24 +726,24 @@ fn main() -> ! {
app.next_track(now_ns);
}
}
// X: tempo down (tap -1, auto-repeat; -5 after 1.5s held)
// X: tempo up (tap +1, auto-repeat; +5 after 1.5s held) [X/Y swapped per hardware layout]
if x && !px {
held_x = us;
nextrep_x = us + 350_000;
app.set_bpm(app.tempo - 1, now_ns);
app.set_bpm(app.tempo + 1, now_ns);
} else if x && px && us >= nextrep_x {
nextrep_x = us + 120_000;
let d = if us - held_x > 1_500_000 { -5 } else { -1 };
let d = if us - held_x > 1_500_000 { 5 } else { 1 };
app.set_bpm(app.tempo + d, now_ns);
}
// Y: tempo up
// Y: tempo down
if y && !py {
held_y = us;
nextrep_y = us + 350_000;
app.set_bpm(app.tempo + 1, now_ns);
app.set_bpm(app.tempo - 1, now_ns);
} else if y && py && us >= nextrep_y {
nextrep_y = us + 120_000;
let d = if us - held_y > 1_500_000 { 5 } else { 1 };
let d = if us - held_y > 1_500_000 { -5 } else { -1 };
app.set_bpm(app.tempo + d, now_ns);
}
pa = a;