From 5d969888fc1970b7e2c04ef770edb62e6f49c246 Mon Sep 17 00:00:00 2001 From: DIvan2000 Date: Fri, 24 Apr 2026 19:10:29 +0400 Subject: [PATCH] runtime config via CLI instead of consts --- src/osc.nim | 228 ++++++++++++++++++++++++++++++++++---------- src/osc_braille.nim | 226 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 361 insertions(+), 93 deletions(-) diff --git a/src/osc.nim b/src/osc.nim index e021e21..df8bccb 100644 --- a/src/osc.nim +++ b/src/osc.nim @@ -1,28 +1,83 @@ ## Terminal oscilloscope with CRT phosphor physics. ## Zero dependencies beyond Nim stdlib + libav (dlopen at runtime). -import os, strutils +import os, strutils, parseopt import posix/termios as ptermios from posix import read import osc/canvas/[term, effects] import osc/[scope, audio] # ── Configuration ──────────────────────────────────────────────────── -# Edit these to tune the look. -const - # Phosphor physics - Decay = 0.85 # persistence per frame (0.0–1.0) - Beam = 0.4 # intensity at beam impact - Bloom = 0.08 # horizontal glow spread +type Config = object + decay: float + beam: float + bloom: float + hotGlow: float + warmGlow: float + coolGlow: float + palette: string - # Phosphor glow thresholds - HotGlow = 0.7 # white-hot beam core - WarmGlow = 0.4 # bright phosphor - CoolGlow = 0.15 # dim persistence trail +proc defaultConfig(): Config = + Config( + decay: 0.85, + beam: 0.4, + bloom: 0.08, + hotGlow: 0.7, + warmGlow: 0.4, + coolGlow: 0.15, + palette: "green" + ) - # Palette: green, amber, cyan, blue, white, red - Palette = "green" +proc usage() = + echo """ +Terminal oscilloscope + +Options: + -p, --palette:NAME Palette name, default: green + -d, --decay:FLOAT Phosphor decay, default: 0.85 + --beam:FLOAT Beam intensity, default: 0.4 + --bloom:FLOAT Bloom intensity, default: 0.08 + --hot:FLOAT Hot glow, default: 0.7 + --warm:FLOAT Warm glow, default: 0.4 + --cool:FLOAT Cool glow, default: 0.15 + -h, --help Show this help + +Palettes: + green, amber, cyan, blue, white, red + +Example: + ./oscilloscope --palette:amber --decay:0.92 --beam:0.6 --bloom:0.12 +""" + +proc parseConfig(): Config = + result = defaultConfig() + + for kind, key, val in getopt(): + case kind + of cmdLongOption, cmdShortOption: + case key + of "h", "help": + usage() + quit 0 + of "palette", "p": + result.palette = val + of "decay", "d": + result.decay = parseFloat(val) + of "beam": + result.beam = parseFloat(val) + of "bloom": + result.bloom = parseFloat(val) + of "hot": + result.hotGlow = parseFloat(val) + of "warm": + result.warmGlow = parseFloat(val) + of "cool": + result.coolGlow = parseFloat(val) + else: + quit "Unknown option: " & key + else: + discard # ── Audio thread via Channel ───────────────────────────────────────── @@ -66,94 +121,171 @@ proc readKey(): char = # ── Phosphor ───────────────────────────────────────────────────────── -proc plotDot(c: var Canvas, fx, fy: float) = - let x = int(fx); let y = int(fy) - c.addPixel(x, y, Beam) - c.addPixel(x - 1, y, Bloom) - c.addPixel(x + 1, y, Bloom) +proc plotDot(c: var Canvas, fx, fy: float, cfg: Config) = + let x = int(fx) + let y = int(fy) -proc plotLine(c: var Canvas, x0, y0, x1, y1: float) = + c.addPixel(x, y, cfg.beam) + c.addPixel(x - 1, y, cfg.bloom) + c.addPixel(x + 1, y, cfg.bloom) + +proc plotLine( + c: var Canvas, + x0, y0, x1, y1: float, + cfg: Config +) = let steps = max(int(max(abs(x1 - x0), abs(y1 - y0))), 1) + for i in 0..steps: let t = i.float / steps.float - c.plotDot(x0 + (x1 - x0) * t, y0 + (y1 - y0) * t) -proc renderTrace(c: var Canvas, scope: Scope) = - if scope.sampleCount < 2: return - let w = c.pixW; let h = c.pixH - let cy = h.float / 2.0; let gain = scope.gain + c.plotDot( + x0 + (x1 - x0) * t, + y0 + (y1 - y0) * t, + cfg + ) + +proc renderTrace(c: var Canvas, scope: Scope, cfg: Config) = + if scope.sampleCount < 2: + return + + let w = c.pixW + let h = c.pixH + let cy = h.float / 2.0 + let gain = scope.gain case scope.mode of ModeYT: let visible = max(int(scope.sampleCount.float / scope.timeDiv), 2) - var px, py: float; var first = true + + var px, py: float + var first = true + for col in 0..