Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions keyboard_keyboard/code/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,32 @@ pub const SPLASH_DURATION_MS: u32 = 3000;

pub const DIAG_LOGGING: bool = false; // set true to see raw ADC / calibration logs
pub const LOG_INTERVAL_MS: u32 = 500;
pub const LOG_SWITCH: usize = 0; // HE1 — first switch
pub const LOG_SWITCH: usize = 89; // HE90 — debugging spurious triggers

// ── Baseline drift tracking ───────────────────────────────────────────────────
// IIR: baseline += (filtered - baseline) / ALPHA each idle tick.
// At 1 kHz this gives a ~1 s time constant — fast enough to absorb boot drift,
// slow enough that held notes never corrupt the baseline.
pub const BASELINE_TRACKING_ALPHA: u32 = 1024;
// Hard cap on how far the tracked baseline may wander from the boot-calibrated
// value. Must stay well under RELEASE_DELTA so sustained crosstalk from a held
// chord on neighboring switches can never, by itself, drift a baseline far
// enough to cross FIRST_DELTA/RELEASE_DELTA once the chord releases.
pub const BASELINE_DRIFT_MAX: u16 = 40;

// ── Special function keys ─────────────────────────────────────────────────────
pub const RECALIBRATE_KEY: usize = 74; // HE75 → snapshot recalibration
pub const ALL_NOTES_OFF_KEY: usize = 75; // HE76 → CC 123 all channels
pub const RECALIBRATE_FLASH_MS: u32 = 1500;

// ── Voice select keys (HE71–HE73, AM10 decoder) ───────────────────────────────
// PC sent on melody_channel. Mapping: key A→triangle, B→square, C→saw.
pub const VOICE_KEY_A: usize = 70; // HE71
pub const VOICE_KEY_B: usize = 71; // HE72
pub const VOICE_KEY_C: usize = 72; // HE73
pub const VOICE_PC_A: u8 = 0; // triangle
pub const VOICE_PC_B: u8 = 1; // square
pub const VOICE_PC_C: u8 = 2; // saw

// ── Settings screen ───────────────────────────────────────────────────────────
pub const SETTINGS_OPEN: usize = 73; // HE74 → open / close settings
Expand Down Expand Up @@ -133,7 +158,7 @@ pub const SWITCH_TO_NOTE: [u8; NUM_SWITCHES] = [
59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87,
// Row 5 — HE59–70 (base 54)
54, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76,
80, // HE71 — skipped 56 and 78 (those keys don't exist on the board)
80, // HE70 — skipped 56 and 78 (those keys don't exist on the board)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];

Expand Down
2 changes: 1 addition & 1 deletion keyboard_keyboard/code/src/display/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod screens;
pub use screens::{draw_main, draw_settings, draw_splash};
pub use screens::{draw_main, draw_recalibrating, draw_settings, draw_splash};

const NOTE_NAMES: [&str; 12] = [
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B",
Expand Down
38 changes: 38 additions & 0 deletions keyboard_keyboard/code/src/display/screens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ use heapless::String;

const SPRITE_ATLAS: &[u8] = include_bytes!("../../../../images/Keyboard-Keyboard-Spritesheet.raw");

pub fn draw_recalibrating(disp: &mut LcdDisplay) {
disp.clear();
Text::with_alignment(
"RECALIBRATING",
Point::new(64, 20),
MonoTextStyle::new(&FONT_6X9, BinaryColor::On),
Alignment::Center,
)
.draw(disp)
.ok();
disp.flush().ok();
}

pub fn draw_splash(disp: &mut LcdDisplay) {
disp.clear();
let atlas = ImageRawBE::<BinaryColor>::new(SPRITE_ATLAS, 128);
Expand Down Expand Up @@ -102,6 +115,31 @@ pub fn draw_main(disp: &mut LcdDisplay, state: &DisplayState) {
.draw(disp)
.ok();

// Bottom-right volume level (0–10)
if let Some(vol) = state.volume_level {
let mut vol_str: String<4> = String::new();
write!(vol_str, "{}", vol).ok();
Text::with_alignment(
vol_str.as_str(),
center + Point::new(54, 15),
MonoTextStyle::new(&FONT_6X9, off),
Alignment::Center,
)
.draw(disp)
.ok();
}

// Bottom-left waveform icon (20×8 px at display position 5,24)
if let Some(voice) = state.current_voice {
let atlas_x = match voice {
0 => 40, // triangle
1 => 20, // square
_ => 0, // saw
};
let icon = atlas.sub_image(&Rectangle::new(Point::new(atlas_x, 64), Size::new(20, 8)));
Image::new(&icon, Point::new(5, 24)).draw(disp).ok();
}

disp.flush().ok();
}

Expand Down
Loading
Loading