close to finishing claude.md file

This commit is contained in:
2026-04-18 22:43:10 -07:00
parent 7e70b1eaab
commit ec8495cc54
3 changed files with 674 additions and 6 deletions

254
CLAUDE.md
View File

@@ -105,9 +105,10 @@ Also not that when the radar exhibit starts, the very first option will
be on the screen. Then the screen will advance through the scopes by two means;
the pressing of the s key by the user, or automatically at every 120 seconds. You will
need to emphasize in the first desciption that you can advance without waiting
for the automatic advancing by pressing the s key. This should be articulated for the
for the automatic advancing by pressing the s key. You can reverse by hitting the S key
(upper case s) This should be articulated for the
discrition window for each scope. When the main exhibit descriptor screen comes up, it's
important to highlight the feature that the user can press the s key any time to 'hurry up'
important to highlight the feature that the user can press the s key or the S key any time to 'hurry up'
the scope advancement.
Also ensure that the timeout clock will reset when the user changes to a new scope, or presses
@@ -143,6 +144,20 @@ should be articulated in the descriptive text
In addition to the blips for targets, there would be a floor of noise (signal received by
rain and waves. This needs to be shown.
Graticule swap simulation: In the period, changing maximum range required the operator
to physically slide the glass graticule panel upward and out from in front of the CRT,
then slide the replacement graticule (calibrated for the new range) downward into position.
This must be simulated when the operator presses u or d to change range.
The graticule swap animation uses four states:
NORMAL - graticule in place, scope operating normally
SLIDING_OUT - old graticule translates upward off screen (~0.5 seconds)
BARE_CRT - no graticule visible; CRT trace and noise floor still running
SLIDING_IN - new graticule (correct lines for new range) slides down into position (~0.5 seconds)
After SLIDING_IN completes, state returns to NORMAL with the new range active.
The u and d keys are ignored during the swap animation (operator's hands are busy).
The graticule remains incandescent color throughout — it is edge-lit glass.
3. Chain Home A Scope There is a second use of the a-scope.
That is for the early world war 2 chain home
radar. This operated very differently. You have a large array of high power transmitters
@@ -158,7 +173,7 @@ should be articulated in the descriptive text
as this is a bit advanced. I need your advise to how to do this for children and those
who never heard of chain home.
The goniometer vert and h switch could be keys [ and ] and the gonometer tuning
The goniometer vertical and horizontal switch could be key [ for toggling. The gonometer tuning
would be 9 and 0 to avoid using the shift key. The tuning keys should have one unit
for single press, but a slow build of of speed if key is held down. This has to stay
slow due to the sudden appearance of the null.
@@ -325,8 +340,96 @@ should be articulated in the descriptive text
Sweep rate: approximately 30 Hz alternating between azimuth and
elevation planes so that each will scan 1/15 th of a second.
THREADS
[remove modularity and threads; will work this out later before implementation]
These are the threads of processes:
1. Display initiation and operation (anything that 'touches' the display and the shaders) Thread 1
2. Software that receives data for targets. Thread 2 (this is the traffic cop that polls the
raspberry pis. and the Simulator. This needs mutex access to shared data with thread 1. It will
also need mutex access to shared data with thread 4 (the simulator)
3. Knob panel - thread 3 - uses a mutex to write shared state variables that thread 1 reads
to send to the shaders.
4. Simulator, thread 4. It is polled by the traffic cop
Threads 2,3, need mutex access to shared data that is read by thread 1.
Thread 2 needs mutex access for shared data with thread 4, the simulator
SUMMARY OF Controls:
● ┌─────┬─────────────────────────────────────┬───────┬──────────┬──────────────┬────────────┬─────────┬─────┐
│ Key │ Function │ Intro │ Marine A │ Chain Home A │ Marine PPI │ ATC PPI │ PAR │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ s │ Advance to next scope │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ S │ back to previous scope │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ c │ Bearing clockwise │ │ ✓ │ │ │ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ v │ Bearing counterclockwise │ │ ✓ │ │ │ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ u │ Max range up │ │ ✓ │ │ ✓ │ ✓ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ d │ Max range down │ │ ✓ │ │ ✓ │ ✓ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ r │ Cursor bearing right │ │ │ │ ✓ │ ✓ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ l │ Cursor bearing left │ │ │ │ ✓ │ ✓ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ t │ Cursor range increase │ │ │ │ ✓ │ ✓ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ y │ Cursor range decrease │ │ │ │ ✓ │ ✓ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ k │ Antenna bearing offset right (boat) │ │ │ │ ✓ │ ✓ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ j │ Antenna bearing offset left (boat) │ │ │ │ ✓ │ ✓ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ [ │ Goniometer H/V switch │ │ │ ✓ │ │ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ 9 │ Goniometer tune left │ │ │ ✓ │ │ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ 0 │ Goniometer tune right │ │ │ ✓ │ │ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ . │ Toggle PRF (25/12.5 Hz) │ │ │ ✓ │ │ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ n │ Calibrator shrink │ │ │ ✓ │ │ │ │
├─────┼─────────────────────────────────────┼───────┼──────────┼──────────────┼────────────┼─────────┼─────┤
│ m │ Calibrator stretch │ │ │ ✓ │ │ │ │
└─────┴─────────────────────────────────────┴───────┴──────────┴──────────────┴────────────┴─────────┴─────┘
SUMMARY of target handling:
The traffic cop handles anything that is coming from the simulator as well as the raspberry pi's
It will use pollnig to find if anything is available from the raspberry pis and the simulator. It will
poll each source once per beam update
The raspberry pi receiver pulls the data from each raspberry pi. If nothing, it does nothing else
for this sweep. If there is data, it will provide data to the traffic cop upon poll.
Each raspberry pi, after boot-up, will respond to poles from the raspberry pi receiver (thread 2)
The Simulator will run all fake targets. It will provide data to the traffic cop upon traffic cop poll.
It can run as a separate thread. It will not write data to anywhere except when polled by the traffic cop.
CONTROLS
Things to note about the keyboard type controls.
The letter on the keyboard are temporary. When I get around to making
the operators panel, this all will go away.
Implementation of controls:
1. For keyboard controls. Those are run as thread one where The keyboard callback
belongs to GLFW (glfwSetKeyCallback)
They will manipulate the shaders only.
2. The control desk controls will have to mutex to access the state variables that
thread 1 sends to the shaders.
3. If the control does not yet exist, we still want stubs for receiving control
data for that control. It's just that nothing will call it.
Scope and left window arrangement.
For each scope, put the scope itself on the right hand of the window.
On the left hand of the window will be a text description of that scope.
@@ -351,6 +454,145 @@ different radars. Range and bearing for the precision aproach radar will be diff
than any other radar as that radar is located at the end of the runway and scan both
horizontal and vertical.
[other scopes to be defined later]
Please analyze and comment. Please do not generate any code file nor shader files.
==================================================================
CLASS DESIGN AND FILE LAYOUT
==================================================================
Class Hierarchy:
Scope (abstract base)
├── ExhibitIntro
├── AScope (abstract)
│ ├── MarineAScope
│ └── ChainHomeAScope
├── PPIScope (abstract)
│ ├── MarinePPIScope
│ └── ATCPPIScope
└── PARScope
Scope (abstract base) — everything all scopes share:
- Left panel text rendering
- s / S key handling (scope advance / reverse)
- Auto-advance timer reset on any key or control input
- Pure virtual: render(), handleKey(), getDescription()
ExhibitIntro : public Scope
- Text-only rendering, no radar display
- Header: "WELCOME TO MUSEUM VINTAGE RADAR EXHIBIT" (all caps)
AScope : public Scope (abstract) — shared A-scope behavior:
- Horizontal range axis, vertical amplitude axis
- Noise floor rendering (rain/wave clutter)
- Incandescent graticule (three horizontal amplitude lines + vertical range lines)
- Bearing control with key-hold acceleration
- Phosphor type as parameter (P1 or P7)
MarineAScope : public AScope
- P1 phosphor (green)
- Range settings: 2, 4, 6 miles
- Graticule swap animation state machine (NORMAL/SLIDING_OUT/BARE_CRT/SLIDING_IN)
when operator changes max range — see Marine A-Scope section above for full detail
- Keys: c (bearing CW), v (bearing CCW), u (range up), d (range down)
u and d ignored during graticule swap animation
ChainHomeAScope : public AScope
- P7 phosphor (early implementation)
- Goniometer state: H/V mode toggle, azimuth angle, elevation angle
- PRF toggle: 25 Hz / 12.5 Hz
- Calibrator stretch/shrink scale factor
- Fixed 100-mile range
- Keys: [ (goniometer H/V toggle), 9/0 (tune), . (PRF), n/m (calibrator)
PPIScope : public Scope (abstract) — shared PPI behavior:
- Clockwise sweep with P7 phosphor persistence (blue strike, green/yellow decay)
- Incandescent bearing graticule (1-degree ticks, 15-degree labels, inner/outer rings)
- Yellow cursor: 10-degree arc + bearing crossline
- Cursor range/bearing readout under scope (white text)
- Bearing offset for boat mode (k/j)
- Cursor range clamped to max range
MarinePPIScope : public PPIScope
- Sweep time: 4 seconds
- Max range: 2, 4, 6 miles with correct ring sets
- Keys: u (range up), d (range down) — this scope only
ATCPPIScope : public PPIScope
- Sweep time: 5 seconds
- Max range: 5, 10, 15, 20 miles with correct ring sets
- Keys: u (range up), d (range down) — this scope only
PARScope : public Scope
- Two stacked sub-scopes: azimuth (top, ~1/3 larger) and elevation (bottom)
- 30 Hz alternating scan between planes (~15 Hz each)
- Fixed 10-mile range, non-linear scale (inner 5 miles = 70% width)
- P7 phosphor; incandescent etched glass graticules
- All targets simulated; no cursor or bearing controls
Supporting classes:
ScopeManager Thread 1 — owns scope list, s/S switching, 120s auto-advance timer
PhosphorRenderer Thread 1 — P1 and P7 decay/persistence; shared dependency
Graticule Thread 1 — incandescent graticule lines/text; parameterized per scope
LeftPanel Thread 1 — scope description text panel (left side of window)
SharedRenderState Threads 1,2,3 — Mutex A; state vars Thread 1 reads each frame for shader uniforms
TargetBuffer Threads 2,4 — Mutex B; target data handoff between TrafficCop and Simulator
TrafficCop Thread 2 — polls Simulator and RPi receivers; writes to SharedRenderState
Simulator Thread 4 — runs fake targets; returns data to TrafficCop when polled
KnobPanel Thread 3 — future hardware stub; writes to SharedRenderState under Mutex A
RPiReceiver Thread 2 — stub; one per Raspberry Pi; called by TrafficCop
File layout:
src/
main.cpp
scope_manager.h / scope_manager.cpp
scope.h / scope.cpp — abstract Scope base
scope_intro.h / scope_intro.cpp
scope_ascope.h / scope_ascope.cpp — abstract AScope
scope_marine_a.h / scope_marine_a.cpp
scope_chain_home.h / scope_chain_home.cpp
scope_ppi.h / scope_ppi.cpp — abstract PPIScope
scope_marine_ppi.h / scope_marine_ppi.cpp
scope_atc_ppi.h / scope_atc_ppi.cpp
scope_par.h / scope_par.cpp
phosphor.h / phosphor.cpp
graticule.h / graticule.cpp
left_panel.h / left_panel.cpp
shared_render_state.h / shared_render_state.cpp
target_buffer.h / target_buffer.cpp
traffic_cop.h / traffic_cop.cpp
simulator.h / simulator.cpp
knob_panel.h / knob_panel.cpp
rpi_receiver.h / rpi_receiver.cpp
settings.h — all tunable constants; no .cpp needed
shaders/
phosphor.vert / phosphor.frag — parameterized for P1 and P7 via uniforms
graticule.vert / graticule.frag
text.vert / text.frag
sweep.vert / sweep.frag
settings.h — tunable constants:
All magic numbers live here. Every source file that needs a tunable value
includes settings.h. No values are hardcoded elsewhere.
Categories planned:
- Phosphor P1 color
- Phosphor P7 strike color, persistence color, decay times (PPI and Chain Home)
- Sweep line width, brightness, fade trail, periods per scope
- PAR scan rate; Chain Home PRF high and low
- Graticule incandescent color, line widths
- PPI bearing ring tick lengths, label interval, font size
- PPI range ring line width, label size, label color
- Cursor color, line width, arc span
- Noise floor amplitude and variation (Marine A-Scope)
- Graticule swap animation durations (slide out, bare CRT, slide in)
- Key-hold acceleration (initial step, rate, max) — separate for goniometer
- Auto-advance timer interval (120 seconds)
- Window size and panel layout fractions
- PAR azimuth/elevation height fractions
- UI text color and size; cursor readout text size
- Graticule label color (incandescent)