Audio Graph

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Sound

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 1 to 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 tone as 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)MnemonicDescription
01 00 FFLD BC, FF00hB=255 (loop count), C=0 (accumulator)
11 00 00LD DE, 0000hDE not used directly
DB FEIN A, (FEh)Read port 254 (EAR/MIC/keyboard)
CB 77BIT 6, ATest EAR bit (bit 6)
20 01JR NZ, +1If set, skip next instruction
13INC DECount high half-cycles (unused directly)
10 F7DJNZ -9Loop 255 times
42LD B, DMove high byte of DE count to B
4BLD C, EMove low byte to C
C9RETReturn 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 tone calls the machine code each iteration and stores the 16-bit return value in a.
  • IF a=255 OR a=0 THEN GO TO 90 filters 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 23678 reads the system variable COORDS (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:

  1. Pixel (P): Uses PLOT OVER 1 to toggle individual pixels. The double-plot at q(a) and q(a)-1 creates a slightly thicker trace while still using XOR logic for auto-erasure.
  2. 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.
  3. Continuous line (C): A real-time streaming mode where step (1–5) controls horizontal resolution. Samples are taken every step pixels 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 step is 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

Appears On

Library tape of the Indiana Sinclair Timex User’s Group.

Related Products

Related Articles

Related Content

Image Gallery

Audio Graph

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.

People

No people associated with this content.

Scroll to Top