code wiki / (root) / nx_transducer_characterizer.nx

nx_transducer_characterizer.nx source

↩ module page · 212 lines · 11940 B

1// nx_transducer_characterizer.nx -- meta-level instrument characterization. 2// 3// module: nishi-core.perception.transducer_characterizer 4// depends: nishi-core.perception.profile + nishi-core.io.syscalls 5// disk_kb: 6 6// capability: PERCEPTION 7// wired_status: PARTIAL_WIRED 8// 9// MISSING_CAPABILITIES: 10// - STIMULUS_GENERATION (log-swept-sine, MLS, calibrated reference; 11// queued, depends on nx_synthesis_engine landing) 12// - FFT_RESPONSE_COMPUTE (FFT + cross-spectrum / auto-spectrum for 13// time-domain transducers; queued, depends on nx_fft landing) 14// - SPATIAL_RESPONSE_COMPUTE (gamma curves, gamut measurement, 15// spatial-frequency response for visual transducers) 16// - CALIBRATION_REFERENCE_APPLY (load stored reference-transducer 17// calibration and apply offset before response computation) 18// - PROVENANCE_STORE_WRITE (persist measured curve to provenance 19// curve store) 20// 21// license_tier: PUBLIC_NISHI_SUBSTRATE 22// genealogy_id: feedback-substrate-primitives-meta-not-one-off_2026 + 23// feedback-substrate-does-heavy-lifting-user-is-partner-not-gate_2026 + 24// feedback-multi-species-perceptual-substrate-not-anthropocentric_2026 + 25// farina_2000_swept_sine_room_acoustics_aes + 26// schroeder_1979_mls_measurement + 27// poynton_2003_digital_video_image_systems + 28// feedback-end-to-end-bit-traceability-architecture 29// 30// Per cardinals [[feedback-substrate-primitives-meta-not-one-off]] and 31// [[feedback-substrate-does-heavy-lifting-user-is-partner-not-gate]]: 32// THIS primitive characterizes ANY transducer chain — audio output (DAC + 33// amp + speaker), audio input (mic + preamp + ADC), haptic motor, camera 34// sensor, accelerometer, display, thermocouple, gas/scent sensor, hydrophone, 35// even composite multi-stage chains. Originally scoped to a "rig" during 36// dog perceptual test bring-up, then promoted to meta-level when the user 37// surfaced reuse across products. 38// 39// Reuse set served by this single primitive: 40// - Dog perceptual test rig (first use, audio output FRF) 41// - Prey-spec dog toy production line (each shipped toy characterized) 42// - Livestock acoustic welfare sensors (audio input FRF) 43// - Conservation acoustic recorders (audio input + filter chain) 44// - Veterinary diagnostic stethoscopes (audio input low-frequency) 45// - Working-dog training devices (audio output FRF) 46// - Beekeeping hive sensors (vibration input) 47// - Aquaculture hydrophones (audio input + pressure-equivalent) 48// - Nishi /video pipeline (camera + display + mic + speaker) 49// - Nishi field-recording sensor suite 50// - nishi-silicon test bench when silicon ships 51// 52// User invocation (substrate hides product-domain specifics): 53// nishi transducer-characterize <transducer_name> --kind <KIND> --stim <STIM> 54// 55// THIS IS A PARTIAL_WIRED STUB. Sealed enums + function signatures + the 56// honest-verdict gate are wired so downstream callers can compose against 57// stable shapes while the FFT + stimulus generator + persistence layer lands. 58 59import "nx_syscalls.nx" 60import "nx_perceptual_profile.nx" 61 62// ===== Transducer kind sealed enum (meta — covers full reuse set) = 63 64const NX_TXR_KIND_AUDIO_OUTPUT: i64 = 1 // DAC + amp + speaker chain 65const NX_TXR_KIND_AUDIO_INPUT: i64 = 2 // mic + preamp + ADC chain 66const NX_TXR_KIND_VIBRATION_OUTPUT: i64 = 3 // haptic motor, LRA, ERM 67const NX_TXR_KIND_VIBRATION_INPUT: i64 = 4 // accelerometer, geophone 68const NX_TXR_KIND_VISUAL_OUTPUT: i64 = 5 // display, LED matrix, projector 69const NX_TXR_KIND_VISUAL_INPUT: i64 = 6 // camera sensor, photodiode array 70const NX_TXR_KIND_THERMAL_OUTPUT: i64 = 7 // Peltier, resistive heater 71const NX_TXR_KIND_THERMAL_INPUT: i64 = 8 // thermocouple, IR sensor, RTD 72const NX_TXR_KIND_PRESSURE_INPUT: i64 = 9 // pressure sensor, hydrophone 73const NX_TXR_KIND_CHEMICAL_INPUT: i64 = 10 // gas / scent / volatile sensor 74const NX_TXR_KIND_CHEMICAL_OUTPUT: i64 = 11 // scent cartridge dispense 75const NX_TXR_KIND_ELECTRICAL_LOOPBACK: i64 = 12 // pure electrical, no air gap 76const NX_TXR_KIND_ROOM_ACOUSTIC: i64 = 13 // room itself as transducer 77 // (reverb characterization) 78const NX_TXR_KIND_COMPOSITE_CHAIN: i64 = 14 // multi-stage, user-defined 79 80func nx_txr_kind_name(k: i64) -> *u8 { 81 if k == NX_TXR_KIND_AUDIO_OUTPUT { return "AUDIO_OUTPUT" } 82 if k == NX_TXR_KIND_AUDIO_INPUT { return "AUDIO_INPUT" } 83 if k == NX_TXR_KIND_VIBRATION_OUTPUT { return "VIBRATION_OUTPUT" } 84 if k == NX_TXR_KIND_VIBRATION_INPUT { return "VIBRATION_INPUT" } 85 if k == NX_TXR_KIND_VISUAL_OUTPUT { return "VISUAL_OUTPUT" } 86 if k == NX_TXR_KIND_VISUAL_INPUT { return "VISUAL_INPUT" } 87 if k == NX_TXR_KIND_THERMAL_OUTPUT { return "THERMAL_OUTPUT" } 88 if k == NX_TXR_KIND_THERMAL_INPUT { return "THERMAL_INPUT" } 89 if k == NX_TXR_KIND_PRESSURE_INPUT { return "PRESSURE_INPUT" } 90 if k == NX_TXR_KIND_CHEMICAL_INPUT { return "CHEMICAL_INPUT" } 91 if k == NX_TXR_KIND_CHEMICAL_OUTPUT { return "CHEMICAL_OUTPUT" } 92 if k == NX_TXR_KIND_ELECTRICAL_LOOPBACK { return "ELECTRICAL_LOOPBACK" } 93 if k == NX_TXR_KIND_ROOM_ACOUSTIC { return "ROOM_ACOUSTIC" } 94 if k == NX_TXR_KIND_COMPOSITE_CHAIN { return "COMPOSITE_CHAIN" } 95 return "UNKNOWN_KIND" 96} 97 98// ===== Stimulus type sealed enum ================================== 99// 100// Different transducer kinds accept different stimuli; substrate selects 101// appropriate stimulus generator per kind, but caller can override. 102 103const NX_TXR_STIM_LOG_SWEPT_SINE: i64 = 1 // audio + vibration default 104const NX_TXR_STIM_LIN_SWEPT_SINE: i64 = 2 105const NX_TXR_STIM_MLS: i64 = 3 // Schroeder 1979 106const NX_TXR_STIM_PINK_NOISE: i64 = 4 107const NX_TXR_STIM_WHITE_NOISE: i64 = 5 108const NX_TXR_STIM_TONE_BURST: i64 = 6 109const NX_TXR_STIM_KNOWN_REFERENCE: i64 = 7 // bit-identical reference signal 110const NX_TXR_STIM_TEST_PATTERN: i64 = 8 // visual transducer: gradient, 111 // color bars, checkerboard, etc. 112const NX_TXR_STIM_STEP_RESPONSE: i64 = 9 // thermal default 113const NX_TXR_STIM_GAS_BOLUS: i64 = 10 // chemical: known 114 // concentration injection 115const NX_TXR_STIM_PRESSURE_RAMP: i64 = 11 // pressure transducer 116 117func nx_txr_stim_name(s: i64) -> *u8 { 118 if s == NX_TXR_STIM_LOG_SWEPT_SINE { return "LOG_SWEPT_SINE" } 119 if s == NX_TXR_STIM_LIN_SWEPT_SINE { return "LIN_SWEPT_SINE" } 120 if s == NX_TXR_STIM_MLS { return "MLS" } 121 if s == NX_TXR_STIM_PINK_NOISE { return "PINK_NOISE" } 122 if s == NX_TXR_STIM_WHITE_NOISE { return "WHITE_NOISE" } 123 if s == NX_TXR_STIM_TONE_BURST { return "TONE_BURST" } 124 if s == NX_TXR_STIM_KNOWN_REFERENCE { return "KNOWN_REFERENCE" } 125 if s == NX_TXR_STIM_TEST_PATTERN { return "TEST_PATTERN" } 126 if s == NX_TXR_STIM_STEP_RESPONSE { return "STEP_RESPONSE" } 127 if s == NX_TXR_STIM_GAS_BOLUS { return "GAS_BOLUS" } 128 if s == NX_TXR_STIM_PRESSURE_RAMP { return "PRESSURE_RAMP" } 129 return "UNKNOWN_STIM" 130} 131 132// ===== Characterization verdicts ================================== 133 134const NX_TXR_VERDICT_PASS: i64 = 0 135const NX_TXR_VERDICT_MARGINAL: i64 = 1 // measurable but compensable 136const NX_TXR_VERDICT_FAIL_REPAIRABLE: i64 = 2 // diagnostic emitted a fix 137const NX_TXR_VERDICT_FAIL_UNRECOVERABLE: i64 = 3 // transducer physically broken 138const NX_TXR_VERDICT_REFERENCE_MISSING: i64 = 4 // no calibrated reference loaded 139const NX_TXR_VERDICT_DEPENDENCY_MISSING: i64 = 5 // PARTIAL_WIRED default 140 141func nx_txr_verdict_name(v: i64) -> *u8 { 142 if v == NX_TXR_VERDICT_PASS { return "PASS" } 143 if v == NX_TXR_VERDICT_MARGINAL { return "MARGINAL" } 144 if v == NX_TXR_VERDICT_FAIL_REPAIRABLE { return "FAIL_REPAIRABLE" } 145 if v == NX_TXR_VERDICT_FAIL_UNRECOVERABLE { return "FAIL_UNRECOVERABLE" } 146 if v == NX_TXR_VERDICT_REFERENCE_MISSING { return "REFERENCE_MISSING" } 147 if v == NX_TXR_VERDICT_DEPENDENCY_MISSING { return "DEPENDENCY_MISSING" } 148 return "UNKNOWN_VERDICT" 149} 150 151// ===== Top-level entry stubs ====================================== 152 153// nx_transducer_characterize -- drive a stimulus through the named transducer 154// and return a verdict. Full implementation persists measured response 155// curve + diagnostics to nx_provenance_curve_store. Stub returns 156// DEPENDENCY_MISSING until supporting layer lands. 157 158func nx_transducer_characterize(name_ptr: *u8, name_len: i64, 159 kind: i64, stimulus: i64, 160 range_lo: i64, range_hi: i64) -> i64 { 161 if name_len <= 0 { return NX_TXR_VERDICT_FAIL_UNRECOVERABLE } 162 if kind < NX_TXR_KIND_AUDIO_OUTPUT { return NX_TXR_VERDICT_FAIL_UNRECOVERABLE } 163 if kind > NX_TXR_KIND_COMPOSITE_CHAIN { return NX_TXR_VERDICT_FAIL_UNRECOVERABLE } 164 if stimulus < NX_TXR_STIM_LOG_SWEPT_SINE { return NX_TXR_VERDICT_FAIL_UNRECOVERABLE } 165 if stimulus > NX_TXR_STIM_PRESSURE_RAMP { return NX_TXR_VERDICT_FAIL_UNRECOVERABLE } 166 if range_lo < 0 { return NX_TXR_VERDICT_FAIL_UNRECOVERABLE } 167 if range_hi <= range_lo { return NX_TXR_VERDICT_FAIL_UNRECOVERABLE } 168 // PARTIAL_WIRED: dependencies not yet landed. 169 return NX_TXR_VERDICT_DEPENDENCY_MISSING 170} 171 172// nx_transducer_apply_reference_calibration -- load a stored calibration 173// curve for the reference transducer (e.g., the verification mic that 174// characterizes the speaker; or the calibrated gray-card that 175// characterizes the camera). 176 177func nx_transducer_apply_reference_calibration(ref_name_ptr: *u8, 178 ref_name_len: i64) -> i64 { 179 if ref_name_len <= 0 { return 0 } 180 return 0 181} 182 183// nx_transducer_get_last_verdict -- inspector for the most recent 184// characterization run. nx_signal_compensator queries this before 185// applying compensation. 186 187func nx_transducer_get_last_verdict(name_ptr: *u8, name_len: i64) -> i64 { 188 if name_len <= 0 { return NX_TXR_VERDICT_REFERENCE_MISSING } 189 return NX_TXR_VERDICT_REFERENCE_MISSING 190} 191 192// nx_transducer_default_stimulus_for_kind -- helper picking the 193// substrate-recommended stimulus for a given transducer kind. 194// User can override at call time. 195 196func nx_transducer_default_stimulus_for_kind(kind: i64) -> i64 { 197 if kind == NX_TXR_KIND_AUDIO_OUTPUT { return NX_TXR_STIM_LOG_SWEPT_SINE } 198 if kind == NX_TXR_KIND_AUDIO_INPUT { return NX_TXR_STIM_LOG_SWEPT_SINE } 199 if kind == NX_TXR_KIND_VIBRATION_OUTPUT { return NX_TXR_STIM_LOG_SWEPT_SINE } 200 if kind == NX_TXR_KIND_VIBRATION_INPUT { return NX_TXR_STIM_LOG_SWEPT_SINE } 201 if kind == NX_TXR_KIND_VISUAL_OUTPUT { return NX_TXR_STIM_TEST_PATTERN } 202 if kind == NX_TXR_KIND_VISUAL_INPUT { return NX_TXR_STIM_TEST_PATTERN } 203 if kind == NX_TXR_KIND_THERMAL_OUTPUT { return NX_TXR_STIM_STEP_RESPONSE } 204 if kind == NX_TXR_KIND_THERMAL_INPUT { return NX_TXR_STIM_STEP_RESPONSE } 205 if kind == NX_TXR_KIND_PRESSURE_INPUT { return NX_TXR_STIM_PRESSURE_RAMP } 206 if kind == NX_TXR_KIND_CHEMICAL_INPUT { return NX_TXR_STIM_GAS_BOLUS } 207 if kind == NX_TXR_KIND_CHEMICAL_OUTPUT { return NX_TXR_STIM_GAS_BOLUS } 208 if kind == NX_TXR_KIND_ELECTRICAL_LOOPBACK { return NX_TXR_STIM_LOG_SWEPT_SINE } 209 if kind == NX_TXR_KIND_ROOM_ACOUSTIC { return NX_TXR_STIM_MLS } 210 if kind == NX_TXR_KIND_COMPOSITE_CHAIN { return NX_TXR_STIM_LOG_SWEPT_SINE } 211 return NX_TXR_STIM_LOG_SWEPT_SINE 212}