// SPDX-License-Identifier: Apache-2.0
; specs/widgets/sqnr.t27 -- quantization noise: each bit buys about 6 dB
; Source of truth for public/widgets/sqnr/ (gHashTag/trinity): scripts/widget-pages-from-spec.mjs
; compiles this file, checks its constants, evaluates the tests below and writes the page; the page
; hands every constant to tool.js as window.T27_WIDGET. tool.js holds no English and NO FORMULA of
; its own: every value it draws comes from public/widgets/sqnr/logic.js -- the fn bodies of
; gHashTag/t27 specs/fpga/dsp/signals.t27 (t27#8985) compiled to wasm, beside its copy logic.t27.
; Lesson 9 of the course arithmetic-and-dsp. ASCII only (L3), English only (LANG-EN).

; WHAT IT DOES: the reader picks a quantizer width from 1 to 16 bits. A full-scale sine is drawn with its
; quantized staircase and the error between them; bars give, for every width, the SQNR the spec measures
; on 4096 samples holding 127 periods next to the formula 6.02 N + 1.76 dB.

; WHAT IT DOES NOT CLAIM: an ideal quantizer and a pure sine; dither, clipping and a real converter's nonlinearity are out.
; phi^2 + 1/phi^2 = 3 | TRINITY

module widget_sqnr;

pub const KIND : str = "widget-tool";
pub const ID : str = "sqnr";
pub const TITLE : str = "Quantization noise: each bit buys about 6 dB";
pub const DESCRIPTION : str = "Pick a quantizer width and see the staircase, its error, and the signal-to-noise ratio measured on a real sine next to the textbook 6.02 N + 1.76 dB.";
pub const IMAGE_ALT : str = "SQNR card: a sine quantized to 4 bits, its staircase and the sawtooth error, and bars for 1 to 16 bits where the measured SQNR climbs about 6 dB per bit, close to 6.02 N + 1.76 dB except at a bit or two.";
pub const HOOK : str = "Measured on a real sine, 12 bits give 74.0 dB, the formula says 74.0. At 1 bit the formula is off by 1.3 dB: the noise is not uniform there.";
pub const CATEGORY : str = "fpga";
pub const DATA_SOURCES : [2]str = ["gHashTag/t27 specs/fpga/dsp/signals.t27 (t27#8985): every value on the page is its fn bodies, compiled to wasm (logic.js)", "W. Kester, Analog Devices MT-001, Taking the mystery out of the infamous formula SNR = 6.02N + 1.76 dB"];
pub const READS_LOCAL_FILES : bool = false;
pub const SENDS_NOTHING : bool = true;

pub const K_CARD_WIDTH : u16 = 1200;
pub const K_CARD_HEIGHT : u16 = 630;

; --- Numbers: ranges, presets, and the logic spec's own constants (held equal by widget-logic.mjs)
pub const K_MAX_BITS : u8 = 16;
pub const K_SAMPLES : u16 = 4096;
pub const K_CYCLES : u16 = 127;
pub const K_DRAW_POINTS : u16 = 256;
pub const K_PRESET_BITS : [4]u8 = [1, 4, 8, 12];
pub const K_START_PRESET : u8 = 1;

; --- Words on screen ------------------------------------------------------------------------
pub const SAY_PRESETS_LABEL : str = "Start from";
pub const SAY_PRESET_NAMES : [4]str = ["1 bit", "4 bits", "8 bits", "12 bits"];
pub const SAY_BITS : str = "Quantizer bits";
pub const SAY_WAVE_LABEL : str = "One period of a full-scale sine and its quantized staircase";
pub const SAY_ERR_LABEL : str = "The quantization error over the period";
pub const SAY_BARS_LABEL : str = "SQNR measured and by the formula, for every width";
pub const SAY_ONE_PERIOD : str = "one period";
pub const SAY_ERROR_AXIS : str = "error: quantized minus sine";
pub const SAY_BITS_AXIS : str = "bits";
pub const SAY_DB : str = "dB";
pub const SAY_DB_VALUE : str = "{0} dB";
pub const SAY_MEASURED : str = "measured, 4096 samples";
pub const SAY_IDEAL : str = "6.02 N + 1.76";
pub const SAY_GAP : str = "formula minus measured";
pub const SAY_PER_BIT : str = "this bit adds";
pub const SAY_SOURCE : str = "Logic: t27 spec fpga/dsp/signals.t27, compiled";

test the_card_is_the_share_size {
    assert K_CARD_WIDTH == 1200;
    assert K_CARD_HEIGHT == 630;
    assert K_CARD_WIDTH * 21 == K_CARD_HEIGHT * 40;
}

test the_samples_hold_whole_periods {
    assert K_SAMPLES == 4096;
    assert K_CYCLES == 127;
    assert K_CYCLES % 2 == 1;
    assert K_DRAW_POINTS < K_SAMPLES;
}

test the_presets_climb {
    assert K_PRESET_BITS[0] == 1;
    assert K_PRESET_BITS[3] == 12;
    assert K_PRESET_BITS[3] <= K_MAX_BITS;
}
