This program is an audio oscilloscope that samples the EAR port (port 254) using a short machine code routine and plots the waveform on screen in three selectable modes: pixel graph, bar graph, and continuous line graph. The machine code, POKEd into address 65368, reads bit 6 of the EAR input in a tight loop with a DJNZ counter, returning a value proportional to the signal’s duty cycle. A 255-element array `q` accumulates sample values across multiple passes, and the line graph mode uses DRAW with PEEK 23678 (the current plot Y coordinate system reference) to connect successive points. The step variable controls the horizontal resolution of the continuous line graph mode, selectable between 1 and 5.
Program Analysis
Program Structure
The program is organized into several functional blocks:
- Lines 1–20: Initialization — sets display attributes, dimensions the sample array, loads machine code, and displays the mode menu.
- Lines 90–110: Pixel/OVER graph mode — plots samples using
PLOT OVER 1to toggle pixels, allowing a persistence-style display. - Lines 120–140: Bar graph mode — plots a single pixel per column without OVER, giving a filled-bar appearance.
- Lines 200–230: Line graph rendering — draws a connected line through all stored
q()values using DRAW, then pauses before returning to the menu. - Lines 300–330: Continuous real-time line graph — plots and draws in a live loop with configurable step size, never storing samples.
- Lines 500–510: Input handler for step size, feeding into the continuous mode.
- Lines 1000–1010: Machine code loader — READs 18 bytes into RAM at address 65368 and sets
toneas the entry point. - Lines 3000–3040: Menu subroutine — displays options and polls INKEY$ to branch to the selected mode.
Machine Code Routine
The 18 bytes POKEd starting at address 65368 implement the EAR sampling function called via USR tone. Disassembled, the bytes are:
| Bytes (hex) | Mnemonic | Description |
|---|---|---|
| 01 00 FF | LD BC, FF00h | B=255 (loop count), C=0 (accumulator) |
| 11 00 00 | LD DE, 0000h | DE not used directly |
| DB FE | IN A, (FEh) | Read port 254 (EAR/MIC/keyboard) |
| CB 77 | BIT 6, A | Test EAR bit (bit 6) |
| 20 01 | JR NZ, +1 | If set, skip next instruction |
| 13 | INC DE | Count high half-cycles (unused directly) |
| 10 F7 | DJNZ -9 | Loop 255 times |
| 42 | LD B, D | Move high byte of DE count to B |
| 4B | LD C, E | Move low byte to C |
| C9 | RET | Return BC to BASIC as USR result |
The routine samples the EAR port 255 times in rapid succession, counting how many times bit 6 is high using INC DE, then returns the DE value in BC. The result in the range 0–255 represents the duty cycle of the audio signal during the sampling window, which BASIC scales to a Y coordinate (0–175).
Key BASIC Idioms
LET a=USR tonecalls the machine code each iteration and stores the 16-bit return value ina.IF a=255 OR a=0 THEN GO TO 90filters out the extreme (saturated) values, avoiding screen boundary errors.PLOT OVER 1;a,q(a)uses OVER mode to XOR the pixel, enabling a “toggle” effect that erases the previous point before drawing the new one on the next pass — a flicker-free update technique.PEEK 23678reads the system variableCOORDS(Y component of the last PLOT), used to make DRAW relative coordinates correct when chaining samples in the line graph modes.DIM q(255)allocates one entry per possible X coordinate (0–254), storing the most recent Y value for each column.
Graph Modes
Three distinct visualization modes are offered:
- Pixel (P): Uses
PLOT OVER 1to toggle individual pixels. The double-plot atq(a)andq(a)-1creates a slightly thicker trace while still using XOR logic for auto-erasure. - Bar (B): Plots a single non-OVER pixel per column. Since
q(a)only increases (never resets within a run), this effectively fills in from the baseline upward over time. - Continuous line (C): A real-time streaming mode where
step(1–5) controls horizontal resolution. Samples are taken everysteppixels and connected with DRAW, then the screen is cleared and the process repeats.
Pressing L at any time during P or B mode triggers a snapshot line graph at line 200, drawing a connected waveform through all stored q() values before returning to the menu.
Notable Techniques
- The machine code is stored near the top of RAM (address 65368), well above the BASIC program area, avoiding conflicts with the heap.
- The use of
PEEK 23678(COORDS-Y system variable) to compute relative DRAW deltas is an efficient way to chain DRAW commands without tracking the previous Y value in a BASIC variable. - The continuous mode loop at lines 300–330 is entirely self-contained with no array storage, making it the lowest-memory and most responsive of the three modes.
Bugs and Anomalies
- In bar graph mode (lines 120–140),
q(a)only ever increments and is never reset between passes. This means the bar heights monotonically increase over time and never reflect decreasing signal amplitudes — a logical limitation rather than a crash-inducing bug. - The variable
stepis used in line 300 before it is defined (it is only set by line 500). If the user enters the continuous mode via line 500, this is fine; however, if line 300 were reached by any other path, an undefined variable error would occur. In practice, the only route to line 300 is through line 500, so this is safe. - The machine code increments DE but the BASIC code uses the full 16-bit USR return (which is BC = DE after the copy). Since the loop runs only 255 times and DE starts at 0, the result fits in a single byte (E/C), making B always 0. The value returned is thus always 0–255 as intended.
Content
Source Code
1 INK 7: PAPER 0: BORDER 0: CLS
5 DIM q(255)
10 GO SUB 1000
20 GO SUB 3000
90 LET a=USR tone: IF INKEY$="L" THEN GO TO 200
95 IF a=255 OR a=0 THEN GO TO 90
100 IF q(a)<175 THEN LET q(a)=q(a)+1: PLOT OVER 1;a,q(a): PLOT OVER 1;a,q(a)-1
110 GO TO 90
120 LET a=USR tone: IF INKEY$="L" THEN GO TO 200
125 IF a=255 OR a=0 THEN GO TO 120
130 IF q(a)<175 THEN LET q(a)=q(a)+1: PLOT a,q(a)
140 GO TO 120
200 CLS : PLOT 1,q(1)
205 FOR t=2 TO 254
210 DRAW 1,q(t)-PEEK 23678
220 NEXT t
230 PAUSE 200: GO TO 20
300 PLOT 0,175-USR tone/1.5: FOR t=0 TO 255-step STEP step
310 DRAW step,(175-(USR tone/1.5)-PEEK 23678)
320 NEXT t
330 CLS : GO TO 300
500 INPUT "Step length? (1-5) :";step
510 GO TO 300
999 STOP
1000 DATA 1,0,255,17,0,0,219,254,203,119,32,1,19,16,247,66,75,201
1010 LET tone=65368: FOR n=tone TO tone+17: READ d: POKE n,d: NEXT n: RETURN
3000 CLS : PRINT '''" Press P for pixel graph"'" B for bar graph"'" C for continuous line graph"
3010 PRINT ''''''"Press L at any time for a line graph"
3020 IF INKEY$="P" OR INKEY$="p" THEN CLS : GO TO 90
3030 IF INKEY$="B" OR INKEY$="b" THEN CLS : GO TO 120
3035 IF INKEY$="c" OR INKEY$="C" THEN CLS : GO TO 500
3040 GO TO 3020
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
