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:
parent
86cd4a0242
commit
e46ff02c0c
1 changed files with 25 additions and 7 deletions
|
|
@ -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)]
|
||||
|
|
@ -239,6 +245,7 @@ struct App {
|
|||
beatflash: u8,
|
||||
beatflash_off: i64,
|
||||
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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue