This program plays “Jingle Bells” using the TS2068’s AY-3-8912 sound chip, combining BEEP for the melody with SOUND commands that program the AY chip’s three tone channels to produce harmonic chords underneath. Song data is stored as triplets (duration, pitch, chord) in DATA statements beginning at line 1000, with each chord value dispatching via computed GO SUB to one of eight chord subroutines (D major, G major, F major, B♭ major, C major, C7, G7, A major) at lines 9010–9082. Negative duration values are used as PAUSE signals, and a sentinel value of -99 triggers a loop back to restart the song continuously. The AY chip registers are set directly: registers 0–5 control the three channel tone periods, register 7 sets the mixer, and registers 8–10 set channel amplitudes.
Program Structure
The program is divided into four clearly delineated sections:
- Main loop (lines 100–170): RESTOREs to line 1000 and iterates through DATA triplets, dispatching chord subroutines and issuing BEEP calls.
- Song data (lines 1000–1120): Packed DATA statements encoding every note as a
(duration, pitch, chord)triplet. - Chord subroutines (lines 9000–9084): Eight named subroutines each programming the AY-3-8912 via
SOUNDfor a specific chord. - Stop-chords subroutine (line 9900): Silences the AY chip by setting register 7 to 63 (all channels off) and register 13 to 0.
Data Encoding
Each note is represented as a triplet read into duration, pitch, and chord. The encoding uses several conventions:
- A
chordvalue of0means no chord change; values 10–90 (multiples of 10) select a chord subroutine viaGO SUB 9000+chord. - A negative
durationthat is not-99triggers aPAUSEofABS durationinterrupt units — used here for rests. - The sentinel triplet
-99,-99,900restarts the song (line 140 catchesduration=-99) while thechordvalue of900calls the stop-chords subroutine at line 9900 first, cleanly silencing the AY before looping.
Computed GO SUB Dispatch
The idiom GO SUB 9000+chord at line 130 routes execution to the appropriate chord subroutine purely arithmetically, avoiding a lookup table or IF/THEN chain. Chord index values used in the data are multiples of 10 (10, 30, 40, 60, 70, 80, 90), each mapping directly to a subroutine at lines 9010, 9030, 9040, 9060, 9070, 9080, 9090 respectively. The value 900 dispatches to the stop-chords subroutine at line 9900.
AY-3-8912 Register Programming
Each chord subroutine uses SOUND to write directly to AY chip registers. The register assignments are consistent across all chord subroutines:
| Registers | Function |
|---|---|
0,1 | Channel A tone period (low/high byte) |
2,3 | Channel B tone period (low/high byte) |
4,5 | Channel C tone period (low/high byte) |
7 | Mixer control — value 56 (binary 00111000) enables tone on all three channels, noise off |
8,9,10 | Amplitude for channels A, B, C — all set to 12 (fixed level, no envelope) |
The stop-chords routine sets register 7 to 63 (binary 00111111), disabling all tone and noise output, and clears register 13.
Melody via BEEP
The melody is played through the built-in speaker using the standard BEEP duration,pitch statement. Pitch is expressed as semitones above middle C. While SOUND sustains the AY chord in the background, BEEP provides the foreground melodic line, producing a two-layer musical texture.
Notable Techniques and Idioms
- Using
RESTORE 1000at line 110 rather than a bareRESTOREtargets the data section precisely, allowing the song loop to restart cleanly. - Fractional duration constants (e.g.,
.125,.128) are used directly in DATA —BEEPaccepts floating-point duration in seconds, so.128≈ one thirty-second note at a typical tempo and.125= exactly one-eighth of a second. - The chord value
900in the terminal sentinel record cleverly reuses the dispatch mechanism to call the silence subroutine before the loop restarts, avoiding a separate cleanup step.
Content
Source Code
10 REM Jingle Bells
20 REM Spera (P.M.) style!
100 REM ==> MAIN PROGRAM <==
110 RESTORE 1000
120 READ duration,pitch,chord
130 IF chord>0 THEN GO SUB 9000+chord
140 IF duration=-99 THEN GO TO 100
150 IF duration<0 THEN PAUSE (ABS duration): GO TO 120
160 BEEP duration,pitch
170 GO TO 120
1000 REM ==> SONG DATA <==
1010 DATA .25,0,0,.25,0,30,.25,9,0,.25,7,0,.25,5,0,.75,0,0,.128,0,0,.128,0,0
1020 DATA .25,0,30,.25,9,0,.25,7,0,.25,5,0,.75,2,40,.25,2,0,.25,2,0,.25,10,0,.25,9,0,.25,7,0
1030 DATA .75,4,60,.25,12,0,.25,14,0,.25,12,0,.25,10,0,.25,7,0,.75,9,30,.25,0,0
1040 DATA .25,0,30,.25,9,0,.25,7,0,.25,5,0,.75,0,0,.128,0,0,.128,0,0
1050 DATA .25,0,30,.25,9,0,.25,7,0,.25,5,0,.75,2,40,.25,2,0,.25,2,0,.25,10,0,.25,9,0,.25,7,0
1060 DATA .25,12,60,.25,12,0,.25,12,0,.25,12,0,.25,14,0,.25,12,0,.25,10,0,.25,7,0,1,5,30
1070 DATA .25,9,30,.25,9,0,.50,9,0,.25,9,0,.25,9,0,.50,9,0,.25,9,0,.25,12,0,.25,5,0,.25,7,0,1,9,0
1080 DATA .25,10,60,.25,10,0,.25,10,0,.25,10,0,.25,10,30,.25,9,0,.25,9,0,.125,9,0,.125,9,0
1090 DATA .25,9,70,.25,7,0,.25,7,0,.25,9,0,.50,7,60,.50,12,0
1100 DATA .25,9,30,.25,9,0,.50,9,0,.25,9,0,.25,9,0,.50,9,0,.25,9,0,.25,12,0,.25,5,0,.25,7,0,1,9,0
1110 DATA .25,10,60,.25,10,0,.25,10,0,.25,10,0,.25,10,30,.25,9,0,.25,9,0,.125,9,0,.125,9,0
1120 DATA .25,12,60,.25,12,0,.25,10,0,.25,7,0,1,5,30,-99,-99,900
9000 REM ==> CHORDS <==
9010 REM D maj. chord
9012 SOUND 0,248;1,0;2,186;3,0;4,147;5,0;7,56;8,12;9,12;10,12
9014 RETURN
9020 REM G maj. chord
9022 SOUND 0,23;1,1;2,221;3,0;4,139;5,0;7,56;8,12;9,12;10,12
9024 RETURN
9030 REM F maj. chord
9032 SOUND 0,248;1,0;2,209;3,0;4,156;5,0;7,56;8,12;9,12;10,12
9034 RETURN
9040 REM Bb maj. chord
9042 SOUND 0,234;1,0;2,186;3,0;4,156;5,0;7,56;8,12;9,12;10,12
9044 RETURN
9050 REM C maj. chord
9052 SOUND 0,23;1,1;2,209;3,0;4,165;5,0;7,56;8,12;9,12;10,12
9054 RETURN
9060 REM C 7th chord
9062 SOUND 0,234;1,0;2,209;3,0;4,165;5,0;7,56;8,12;9,12;10,12
9064 RETURN
9070 REM G 7th chord
9072 SOUND 0,23;1,1;2,221;3,0;4,156;5,0;7,56;8,12;9,12;10,12
9074 RETURN
9080 REM A maj. chord
9082 SOUND 0,248;1,0;2,197;3,0;4,165;5,0;7,56;8,12;9,12;10,12
9084 RETURN
9900 REM ==> STOP CHORDS <==
9902 SOUND 7,63;13,0
9904 RETURN
9990 STOP
9999 SAVE "jingle" LINE 100
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
