KN-86 Deckline — Haptic Feedback System Addendum
Parent Documents:
KN-86-Pi-Zero-Build-Specification.md(hardware spec, GPIO budget, BOM — supersedes the archived Pico-eraKN-86-Modern-Build-Specification.md)KN-86-Prototype-Architecture.md(Pi Zero hardware, audio subsystem)KN-86-UI-Design-System.md(interaction patterns, sound design)KN-86-Cartridge-Grammar-Spec.md(stdlib API, cartridge authoring surface)KN-86-PCM-Voice-Bark-Addendum.md(companion sensory channel — audio barks)
1. Motivation
Section titled “1. Motivation”The KN-86 Deckline sells its fiction through multi-sensory feedback. Amber text on the screen carries narrative. The Kailh Choc switches provide the “Deckline Chatter” — audible clicks as the operator works the grid. The YM2149 PSG punctuates state changes with tones, noise, and (per the bark addendum) short PCM voice stings. What’s missing is the fourth channel: the hands.
Modern devices that feel authoritative — high-end game controllers, the iPhone, mechanical watches — all use haptic feedback as a signal layer. When you press the home button on an iPhone, the click you feel isn’t a real button; it’s an LRA pulse perfectly timed to the press detection. The illusion is total because the physical sensation matches the visual and audio feedback at the millisecond level.
The KN-86 has an opportunity to use haptics as a third narrative channel, coordinated with the display and the PSG. A subtle tick on every keypress reinforces that the device responded. A sharp double-pulse on EVAL makes the commit feel weighty. A sustained buzz when ICE catches you, paired with the “BREACH” bark and the on-screen alert, turns a moment of gameplay into a moment of physical panic. Three signals arriving simultaneously — hand, ear, eye — is how you make a $600 prototype feel like a $6,000 industrial device.
Design constraint: Haptics supplement, never replace, the existing feedback. The device must work identically with haptics disabled (bad actuator, low battery conservation mode, operator preference). Every haptic event has an audio and/or visual counterpart that carries the same information.
2. Technical Approach
Section titled “2. Technical Approach”Two actuator technologies are viable. The decision between them shapes everything downstream.
2A. Option A — ERM (Eccentric Rotating Mass)
Section titled “2A. Option A — ERM (Eccentric Rotating Mass)”A tiny DC motor with an off-center weight. Same technology as 1990s pagers and most low-end phone vibrations.
| Property | Value |
|---|---|
| Size | ~10mm diameter, ~3mm thick (coin-type) |
| Drive | Single GPIO through a transistor + flyback diode |
| Voltage | 3V typical |
| Current | 80–100mA when active |
| Startup latency | 20–50ms to reach rated vibration |
| Stop latency | 50–100ms to spin down |
| Cost | $0.50–1.50 per unit |
| Pins required | 1 GPIO |
| Driver IC | None (discrete transistor) |
Strengths: Dirt cheap. Trivial circuit. One GPIO pin. Available from any supplier in quantity.
Weaknesses: The spin-up/spin-down lag is the killer. You cannot produce a crisp, short tick — everything becomes a “buzz” because the motor is still accelerating when you want it to stop. Haptic events under ~80ms in duration are impossible. Feel is mushy and toy-like.
Appropriate use cases: Sustained alerts (ICE detection, mission failure, low battery), where the vibration is meant to last 300ms+ anyway. Inappropriate for per-keypress feedback.
2B. Option B — LRA (Linear Resonant Actuator) + Driver IC
Section titled “2B. Option B — LRA (Linear Resonant Actuator) + Driver IC”A voice-coil driving a mass on a spring. Same technology as iPhone Taptic Engine, PS5 DualSense, Apple Watch. Drives a precise frequency, produces sharp pulses with millisecond accuracy.
| Property | Value |
|---|---|
| Size | ~10mm × 3.4mm coin LRA (e.g., G1040003D from Jinlong) |
| Drive | I2C-controlled haptic driver IC (DRV2605L or similar) |
| Voltage | 3V typical, AC resonant drive |
| Current | 60–80mA peak during pulse |
| Startup latency | <10ms (driver IC handles auto-resonance) |
| Stop latency | <10ms (active braking in driver) |
| Cost | $3–5 per unit (LRA + driver IC) |
| Pins required | 2 GPIO (I2C SDA + SCL) |
| Driver IC | TI DRV2605L ($2.50) — 123 built-in effects, I2C interface, library support |
Strengths: Precise, crisp pulses. Can produce a 10ms “tick” that feels like a button click. Driver IC has a built-in effect library (sharp click, double click, triple click, soft bump, ramp up, long buzz, etc.) — you send an effect ID over I2C and the driver handles the waveform. Zero CPU overhead during playback.
Weaknesses: Costs ~5× more. Needs two GPIO pins (I2C). Driver IC adds an I2C device to the system bus. Slightly more complex firmware integration.
Appropriate use cases: Everything ERM is bad at — per-keypress feedback, EVAL confirmations, subtle state transitions, rhythmic patterns. Also works for sustained buzzes (effects 47–52 in the DRV2605L library are long ramps and buzzes).
2C. Recommendation: LRA + DRV2605L
Section titled “2C. Recommendation: LRA + DRV2605L”The LRA path is the right call for a device whose entire identity is “premium handheld with tactile authenticity.” The extra $3 per unit is trivial in a $600 prototype budget and a production device targeting a prosumer price point. The crispness is non-negotiable — a mushy ERM buzz would undermine the Kailh Choc click that is the device’s most-advertised tactile feature.
For prototype validation, an ERM can be used as a cost-free fallback if the LRA path hits a blocker. But the production spec should target LRA.
2D. GPIO Budget Impact
Section titled “2D. GPIO Budget Impact”The Pi Zero 2 W has abundant GPIO (40 header pins, 26 of them general-purpose). The haptic driver’s I2C bus is free in pin count — no peripheral needs to be sacrificed. If additional I2C peripherals are added later (IMU, RTC, external EEPROM), they share the bus; each additional device is free in pin count.
Recommendation: Bring up LRA + DRV2605L on the Pi Zero 2 W I2C1 bus. Validate the tactile experience. No pin-budget decision is blocking this path.
3. Physical Integration
Section titled “3. Physical Integration”3A. Mounting Location
Section titled “3A. Mounting Location”The LRA should be mounted on the inside of the base shell, directly under the palm rest / switch plate. The operator’s hands rest on the switch plate while operating — any vibration coupled through the plate is felt in both hands simultaneously. This is the same approach used by laptop trackpads (LRA under the deck) and game controllers (LRAs in the grip areas).
| Consideration | Detail |
|---|---|
| Mount type | Double-sided adhesive pad (3M VHB) directly to the underside of the switch PCB mounting plate |
| Isolation | Foam gasket around the LRA prevents rattling against the shell |
| Orientation | Coin LRAs are omnidirectional; orientation doesn’t matter |
| Distance from display | >30mm (prevent display controller interference) |
| Distance from speaker | >40mm (prevent acoustic coupling that would muddy both outputs) |
3B. Power
Section titled “3B. Power”LRA peak current (~80mA) is well within the Pi Zero 2 W’s power budget. No additional power regulation needed. The DRV2605L handles its own supply filtering. Add a 10µF decoupling capacitor at the driver IC per datasheet.
3C. Prototype Wiring
Section titled “3C. Prototype Wiring”On the Pi Zero 2 W:
- I2C1 SDA → DRV2605L SDA (GPIO 2)
- I2C1 SCL → DRV2605L SCL (GPIO 3)
- 3.3V → DRV2605L VDD
- GND → DRV2605L GND
- DRV2605L OUT+/OUT- → LRA terminals
- IN/TRIG pin tied to VDD (use I2C mode, not GPIO trigger mode)
That’s the complete circuit. Two signal pins, two power pins, two output pins, one cap.
4. Software Interface
Section titled “4. Software Interface”4A. Stdlib Addition (nosh_stdlib.h)
Section titled “4A. Stdlib Addition (nosh_stdlib.h)”/* ---- Haptic Feedback ---- */
/* Built-in effect IDs — a curated subset of DRV2605L library effects, * mapped to semantic KN-86 interaction moments. Cartridge authors use * these semantic names rather than raw effect numbers. */typedef enum { HAPTIC_NONE = 0, HAPTIC_KEY_TICK = 1, /* Soft click, ~10ms — per-keypress feedback */ HAPTIC_CONFIRM = 2, /* Sharp click, ~15ms — EVAL commit */ HAPTIC_DENY = 3, /* Double bump, ~40ms — invalid action */ HAPTIC_DRILL = 4, /* Descending ramp, ~60ms — CAR into child */ HAPTIC_EMERGE = 5, /* Ascending ramp, ~60ms — BACK out of depth */ HAPTIC_ALERT = 6, /* Triple tick, ~80ms — attention required */ HAPTIC_WARNING = 7, /* Long buzz, ~300ms — critical state */ HAPTIC_FAIL = 8, /* Sustained pulse, ~500ms — mission failed / ICE breach */ HAPTIC_SUCCESS = 9, /* Rising triple-pulse, ~150ms — mission complete */ HAPTIC_LINK_ESTABLISH = 10, /* Soft sustained, ~200ms — link protocol handshake */ HAPTIC_CART_INSERT = 11, /* Sharp tap, ~20ms — cartridge detected */ HAPTIC_LAMBDA_RECORD = 12, /* Slow pulse, ~40ms — macro recording state */ HAPTIC_LAMBDA_PLAYBACK = 13, /* Per-key soft tick — macro replay feedback */} HapticEffect;
/* Trigger a haptic effect. Non-blocking — returns immediately, effect * plays out asynchronously via driver IC. */void stdlib_haptic(SystemState *state, HapticEffect effect);
/* Trigger a raw DRV2605L effect ID (1-123). For advanced authors who * want access to the full driver library. */void stdlib_haptic_raw(SystemState *state, uint8_t effect_id);
/* Stop any currently playing haptic effect. */void stdlib_haptic_stop(SystemState *state);
/* Check if haptic hardware is present and initialized. Returns false * on devices without haptic actuators or when initialization failed. */bool stdlib_haptic_available(SystemState *state);4B. Firmware-Level Haptic Events (Not Cartridge-Triggered)
Section titled “4B. Firmware-Level Haptic Events (Not Cartridge-Triggered)”The nOSh runtime fires haptic events for universal interactions. Cartridges cannot suppress these. They must be identical across all cartridges so muscle memory is preserved.
| Event | Effect | Rationale |
|---|---|---|
| Any keypress | HAPTIC_KEY_TICK (if enabled in SYS menu) | Confirms press was registered |
| EVAL press | HAPTIC_CONFIRM (overrides KEY_TICK) | EVAL is always significant |
| BACK with non-empty nav stack | HAPTIC_EMERGE | Navigation feedback |
| SYS menu open | HAPTIC_KEY_TICK | Consistent with general UI |
| SYS hold → force abort | HAPTIC_WARNING | Emergency action should feel heavy |
| LAMBDA record start | HAPTIC_LAMBDA_RECORD | Mode change feedback |
| LAMBDA record stop | Same (second pulse) | Mode change feedback |
| Cartridge insert detected | HAPTIC_CART_INSERT | Confirms physical action |
| Mission board refresh | HAPTIC_ALERT | New contracts available |
| Mission complete (success) | HAPTIC_SUCCESS | Major win moment |
| Mission complete (failure) | HAPTIC_FAIL | Major loss moment |
| Link session established | HAPTIC_LINK_ESTABLISH | Connection feedback |
4C. Cartridge-Triggered Haptics
Section titled “4C. Cartridge-Triggered Haptics”Cartridges use stdlib_haptic() for module-specific moments. Guidelines:
- Co-occur with audio events. Every haptic should have a matching PSG tone or bark. Never a silent buzz.
- Reserve intense effects.
HAPTIC_FAILandHAPTIC_WARNINGare for genuine gameplay consequences, not minor state changes. - Budget: ~5–10 cartridge-triggered haptics per 30-minute session. More than this causes fatigue and dilutes meaning.
- Never block on haptics. Triggering a haptic is fire-and-forget; game logic proceeds immediately.
Example usage:
CELL_ON_EVAL(network_node) { cell_network_node *self = (cell_network_node *)_self; if (self->compromised) { /* Three-channel celebration: bark + haptic + text */ stdlib_bark_play(g_state, "CLEAN"); stdlib_haptic(g_state, HAPTIC_SUCCESS); nosh_print(g_state, 0, 12, "> EXTRACTED. NO TRACE."); } else if (ice_triggered(self)) { /* Failure mode */ stdlib_bark_play(g_state, "BREACH"); stdlib_haptic(g_state, HAPTIC_FAIL); nosh_print(g_state, 0, 12, "> ICE DETECTED. BURN IMMINENT."); } else { stdlib_haptic(g_state, HAPTIC_DENY); stdlib_sfx_error(); }}4D. User Preferences (SYS Menu)
Section titled “4D. User Preferences (SYS Menu)”The SYS menu gains a Haptic submenu with three settings:
| Setting | Values | Default |
|---|---|---|
| Haptic Master | OFF / ON | ON |
| Keypress Haptics | OFF / SUBTLE / NORMAL | SUBTLE |
| Event Haptics | OFF / ON | ON |
Settings persist in DeckState. “Keypress Haptics OFF” disables HAPTIC_KEY_TICK on every key but keeps HAPTIC_CONFIRM on EVAL (EVAL is always felt). “Haptic Master OFF” disables everything including cartridge-triggered effects.
5. Integration with PCM Bark System
Section titled “5. Integration with PCM Bark System”The haptic and bark systems are designed to work in coordination. The bark addendum’s design philosophy — “three channels delivering the same moment” — extends naturally to haptics as the physical channel.
Synchronization principles:
- Trigger together. Cartridge code should fire both simultaneously when both are warranted:
stdlib_bark_play("BREACH"); stdlib_haptic(HAPTIC_FAIL); - Latency matching. Both systems are non-blocking and fire on the same frame. Any sub-10ms skew is imperceptible.
- Intensity matching. A subtle bark (“CLEAN”) pairs with
HAPTIC_SUCCESS(sharp triple-pulse). An intense bark (“BURNED”) pairs withHAPTIC_FAIL(sustained pulse). Mismatches (loud bark + weak haptic, or vice versa) feel uncanny. - Graceful degradation. If haptics are disabled (user preference or hardware failure), barks still play. If audio is muted, haptics still fire. Each channel carries enough information on its own.
Combined stdlib helper:
/* Fire a bark and matching haptic together. Convenience function. */void stdlib_signal(SystemState *state, const char *bark_label, HapticEffect effect);6. Questions for Agent Review
Section titled “6. Questions for Agent Review”For Embedded Systems Agent:
Section titled “For Embedded Systems Agent:”- DRV2605L alternatives: Are there smaller/cheaper haptic driver ICs worth considering? The DA7280 (Dialog Semi) and LC898302 (Sanyo) are alternatives. Is the DRV2605L’s effect library + I2C interface worth the cost premium?
- Power budget: LRA peak current is ~80mA. Combined with PSG audio (peak ~20mA), display, and CPU, does the Pi Zero 2 W’s power path have headroom at all operating states, including under USB-MSC update mode? If not, does the LRA need its own rail?
- Physical mounting validation: How do we verify the LRA doesn’t cause the display to vibrate visibly, or the speaker to rattle, during sustained effects (HAPTIC_WARNING, HAPTIC_FAIL)?
For C Engineer Agent:
Section titled “For C Engineer Agent:”- I2C integration: The codebase has no existing I2C peripherals. Adding the DRV2605L means introducing an I2C driver. Use Linux
i2c-devioctls directly, or abstract through the platform layer (nosh_platform.h) so emulator and device share an interface? - Async effect playback: DRV2605L effects run for tens to hundreds of milliseconds. The
stdlib_haptic()call must return immediately. How do we handle overlapping requests — queue them, cancel the previous, or drop the new? - Emulator haptic simulation: On macOS/Linux desktop, there’s no haptic hardware. Should the emulator visualize haptic events (e.g., a brief screen tint, a text indicator in the debug overlay) to help cartridge authors verify their haptic timing matches their intent?
For Gameplay Design Agent:
Section titled “For Gameplay Design Agent:”- Haptic budget per session: Is the proposed “5–10 cartridge-triggered haptics per 30 minutes” right? Should this be per-mission, per-phase, or time-based?
- Semantic effect mapping: The 13 proposed HapticEffect IDs map to interaction moments. Are these the right moments? Missing any? Too many?
- Cartridge-specific haptic vocabulary: Should cartridges be able to define custom haptic sequences (like they define custom PCM barks), or is the nOSh runtime-provided library sufficient?
For QA Agent:
Section titled “For QA Agent:”- Tactile quality acceptance: What’s the standard for “good” haptics? Can a first-time user distinguish HAPTIC_CONFIRM from HAPTIC_DENY without seeing the screen? Is a blind user test part of QA?
- Durability testing: LRAs have finite life (rated ~1 million cycles typically). With per-keypress haptics enabled, how many months of heavy use before failure? Does this justify socketing the LRA for replacement?
7. Risk Assessment
Section titled “7. Risk Assessment”| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| GPIO budget unresolvable in production | Medium | High | Ship haptics on prototype only. Use prototype validation to justify reshuffling production pins during PCB design. Acceptable fallback: production ships without haptics; haptics become a “revision 2” feature. |
| LRA feels different across units | Low | Medium | Specify a single part number with tight tolerances. QA samples multiple units per batch. DRV2605L auto-resonance detection handles minor variation automatically. |
| Per-keypress haptics annoy users | Medium | Medium | Default to SUBTLE, not NORMAL. Expose clear SYS menu toggle. Ship with haptics on EVAL only by default; full-key haptics as opt-in. |
| Haptic + audio phase out of sync | Low | Low | Both systems fire from the same frame. Any real skew is under 16ms (one frame at 60fps), below perceptual threshold for these event types. |
| DRV2605L supply chain issue | Low | Medium | Second-source identified (DA7280). Driver abstraction layer allows swap without cartridge changes. |
| Haptic fatigue over long sessions | Medium | Low | Budget enforcement in cartridge reviews. Default settings err toward less haptic. Long sessions (>2 hours) show haptic usage stats in SYS menu. |
| Adhesive mount loosens over time | Medium | Medium | Use 3M VHB (automotive-grade). Include service note in repair docs. Alternative: mechanical bracket for production. |
| Battery drain from haptics | Low | Medium | Each haptic pulse is brief (<500ms) and low current. Estimated <1% additional drain under normal use. SYS menu includes battery-saver mode that disables keypress haptics. |
8. Success Criteria
Section titled “8. Success Criteria”- On the prototype, pressing EVAL produces a synchronized experience: Kailh Choc click (audible), PSG confirm tone (~10ms), haptic
HAPTIC_CONFIRMpulse (~15ms), and on-screen feedback (next frame). A user describes the device as “feeling crisp” or “feeling expensive” unprompted. - Triggering
HAPTIC_FAILalongside a “BREACH” bark during ICE detection produces an unmistakable, visceral “failure moment” — the operator feels the failure before reading the text. - With all haptics disabled via SYS menu, the device functions identically in every respect except tactile output. No game state, no audio, no display element changes.
- Three blind users can distinguish
HAPTIC_CONFIRMfromHAPTIC_DENYwith >80% accuracy after 30 seconds of familiarization. - The LRA survives 100,000 keypress-triggered haptic pulses without performance degradation.
- The DRV2605L I2C bus does not interfere with any other system timing (display refresh, PSG audio, key matrix scan).
- Cartridge authors can add a haptic trigger to an existing handler with a single line of code:
stdlib_haptic(g_state, HAPTIC_ALERT);— no direct driver interaction needed.