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 {
|
fn get(&self, x: i32, y: i32) -> u8 {
|
||||||
if (0..17).contains(&x) && (0..7).contains(&y) {
|
if (0..17).contains(&x) && (0..7).contains(&y) {
|
||||||
self.fb[1 + pixel_addr(x, y)]
|
self.fb[1 + pixel_addr(x, y)]
|
||||||
|
|
@ -239,6 +245,7 @@ struct App {
|
||||||
beatflash: u8,
|
beatflash: u8,
|
||||||
beatflash_off: i64,
|
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 {
|
fn master_bar_ns(track: &track_format::Track, tempo: i64) -> i64 {
|
||||||
|
|
@ -294,6 +301,7 @@ impl App {
|
||||||
beatflash: 0,
|
beatflash: 0,
|
||||||
beatflash_off: 0,
|
beatflash_off: 0,
|
||||||
bpm_flash_off: 0,
|
bpm_flash_off: 0,
|
||||||
|
full_flash_off: 0,
|
||||||
};
|
};
|
||||||
app.load(0, 0, now_ns);
|
app.load(0, 0, now_ns);
|
||||||
app
|
app
|
||||||
|
|
@ -405,6 +413,10 @@ impl App {
|
||||||
while now_ns >= self.next[li] {
|
while now_ns >= self.next[li] {
|
||||||
self.step[li] = (self.step[li] + 1) % steps;
|
self.step[li] = (self.step[li] + 1) % steps;
|
||||||
if li == 0 {
|
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;
|
self.m_steps += 1;
|
||||||
let bar = (self.m_steps - 1) / steps as i64;
|
let bar = (self.m_steps - 1) / steps as i64;
|
||||||
if bar != self.lastbar {
|
if bar != self.lastbar {
|
||||||
|
|
@ -458,6 +470,12 @@ fn lvl_bright(lvl: u8) -> u8 {
|
||||||
|
|
||||||
// ============================== RENDERING ==============================
|
// ============================== RENDERING ==============================
|
||||||
fn render<I: I2c>(m: &mut Matrix<I>, app: &App, now_ns: i64) {
|
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();
|
m.clear();
|
||||||
// a tempo nudge briefly forces the Ticker (so X/Y is visible from Grid/Pendulum)
|
// 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 {
|
let view = if app.view != View::Ticker && now_ns < app.bpm_flash_off {
|
||||||
|
|
@ -708,24 +726,24 @@ fn main() -> ! {
|
||||||
app.next_track(now_ns);
|
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 {
|
if x && !px {
|
||||||
held_x = us;
|
held_x = us;
|
||||||
nextrep_x = us + 350_000;
|
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 {
|
} else if x && px && us >= nextrep_x {
|
||||||
nextrep_x = us + 120_000;
|
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);
|
app.set_bpm(app.tempo + d, now_ns);
|
||||||
}
|
}
|
||||||
// Y: tempo up
|
// Y: tempo down
|
||||||
if y && !py {
|
if y && !py {
|
||||||
held_y = us;
|
held_y = us;
|
||||||
nextrep_y = us + 350_000;
|
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 {
|
} else if y && py && us >= nextrep_y {
|
||||||
nextrep_y = us + 120_000;
|
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);
|
app.set_bpm(app.tempo + d, now_ns);
|
||||||
}
|
}
|
||||||
pa = a;
|
pa = a;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue