Rename crt → osc throughout

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
rolandnsharp
2026-04-05 13:43:15 +10:00
parent 7ceac6c91f
commit 94d5b2cf63
9 changed files with 31 additions and 10 deletions

86
src/osc.nim Normal file
View File

@@ -0,0 +1,86 @@
## CRT Oscilloscope — terminal-based oscilloscope with phosphor physics.
##
## Features:
## - CRT boot/shutdown animations (ported from AetherTune)
## - Y-T (time-domain) and X-Y (Lissajous) display modes
## - Phosphor persistence with bloom and decay
## - Half-block rendering for 2× vertical resolution
## - Live audio capture via ffmpeg/PulseAudio or demo signal
import illwill, os
import osc/[effects, phosphor, scope, audio]
proc exitProc() {.noconv.} =
illwillDeinit()
showCursor()
quit(0)
proc main() =
illwillInit(fullscreen = true)
setControlCHook(exitProc)
hideCursor()
let w = terminalWidth()
let h = terminalHeight()
var tb = newTerminalBuffer(w, h)
crtTurnOn(tb, w, h)
var scope = initScope(w, h)
var audio = startAudio()
var running = true
while running:
if not scope.frozen:
audio.readSamples(scope)
scope.phosphor.decay()
if not scope.frozen:
scope.renderTrace()
tb = newTerminalBuffer(w, h)
scope.phosphor.render(tb)
drawGraticule(tb, w, h, scope.grid)
drawHUD(tb, w, h, scope, audio.sourceLabel)
tb.display()
let key = getKey()
case key
of Key.Q, Key.Escape:
running = false
of Key.M:
scope.mode = if scope.mode == ModeYT: ModeXY else: ModeYT
of Key.Plus, Key.Equals:
scope.gain = min(scope.gain * 1.3, 20.0)
of Key.Minus:
scope.gain = max(scope.gain / 1.3, 0.5)
of Key.RightBracket:
scope.timeDiv = min(scope.timeDiv * 1.5, 16.0)
of Key.LeftBracket:
scope.timeDiv = max(scope.timeDiv / 1.5, 0.25)
of Key.Space:
scope.frozen = not scope.frozen
of Key.G:
scope.grid = case scope.grid
of gsGrid: gsCross
of gsCross: gsOff
of gsOff: gsGrid
of Key.D:
audio.cyclePreset()
else:
discard
sleep(16)
audio.stop()
crtTurnOff(tb, w, h)
tb = newTerminalBuffer(w, h)
tb.display()
sleep(100)
illwillDeinit()
showCursor()
when isMainModule:
main()