This program is a Morse code trainer that uses the BEEP command to audibly play the Morse code for any letter (a–z) or digit (0–9) typed by the user. The user first selects a tone frequency in the range 0 to 69 semitones, which is stored in variable `b` and passed to every BEEP call. Two subroutines at lines 450 and 460 implement the long (dash) and short (dot) elements, each followed by a brief PAUSE 2 gap to separate the beeps. Line numbers 460 and 450 are also used directly as numeric constants in `LET short=460` and `LET long=450`, so the subroutine destination doubles as a human-readable label value. The main input loop at line 70 uses `INPUT INKEY$` to capture a single keystroke, then a long chain of IF statements (lines 80–430) dispatches to the correct sequence of dot/dash subroutines before looping back.
Program Analysis
Program Structure
The program is organized into three logical sections:
- Setup (lines 10–60): Clears the screen, sets border and paper colors, prompts for a frequency value stored in
b, and initializes the subroutine pointer variablesshortandlong. - Input and dispatch loop (lines 70–440): Waits for a keypress via
INPUT INKEY$, then a linear chain ofIF INKEY$="x" THEN ...statements routes to the correct sequence of dot/dash subroutine calls followed by a finalBEEP.GO TO 70at line 440 restarts the loop. - Subroutines (lines 450–460): Line 450 produces a long (dash) beep (
BEEP .5,b) with a short pause; line 460 produces a short (dot) beep (BEEP .05,b) with a short pause.
Dual-Purpose Line Number Constants
A neat technique appears in line 60: LET short=460 and LET long=450. The variables short and long are set to the actual line numbers of the two subroutines. Although they are never used as GO SUB short — the dispatch lines call GO SUB short and GO SUB long using those variable names directly — this makes the code self-documenting. The value stored is exactly the destination line, so the variable name matches its numeric content, serving as a readable alias.
Input Idiom
INPUT INKEY$ at line 70 is used rather than the more common PAUSE 0: LET k$=INKEY$ idiom. This causes the interpreter to wait for a complete Enter-terminated input rather than a bare keypress, meaning the user must press a letter key followed by Enter. The PAUSE 10 immediately after provides a brief delay before the INKEY$ reads in the dispatch lines (80–430) are evaluated — but since INKEY$ is re-read live in each IF test rather than stored to a variable, there is a subtle bug: by the time lines 80–430 execute, the key may no longer be held, making INKEY$ return an empty string and silently skipping all branches before falling through to GO TO 70.
Morse Code Dispatch Table
Each character’s Morse pattern is encoded as a sequence of GO SUB short and GO SUB long calls. The final BEEP on each line acts as a trailing element with either a dot or dash duration, effectively encoding the last symbol without a subroutine call. The table covers the full 26 letters and digits 0–9.
| Character | Morse | Final BEEP duration |
|---|---|---|
| a | · – | .5 (dash) |
| b | – · · | .05 (dot) |
| e | · | .05 (dot, no subroutine calls) |
| t | – | .5 (dash, no subroutine calls) |
| 0 | – – – – | .5 (dash) |
| 5 | · · · · · | .05 (dot) |
Morse Code Accuracy Issues
Several letters have incorrect or incomplete Morse encodings:
- Line 80 (a = · –): Correctly calls
GO SUB shortthenBEEP .5for dash, but the final BEEP duration of .5 is the same as a dash — correct. - Line 160 (i = · ·): Only one
GO SUB shortplus finalBEEP .05— gives only two dots, which is correct. - Line 170 (j = · – – –): Calls
GO SUB short,GO SUB long,GO SUB long,BEEP .5— only three elements total; correct Morse for J is · – – –, so this is missing one dash. - Line 180 (k = – · –): Only
GO SUB long,GO SUB short,BEEP .5— three elements, which is correct for K. - Line 210 (n = – ·): Only
GO SUB longthenBEEP .05— correct. - Line 360 (digit 2 = · · – – –): The sequence is
GO SUB short,BEEP .05,b,GO SUB long,GO SUB long,BEEP .5,b— a stray inlineBEEPmid-sequence adds an extra dot, making it · · – – – rendered as · · · – –, which is incorrect. - Lines 340/430 (0 and 9): Both produce four elements (– – – –) instead of the standard five-element codes.
BEEP Frequency Parameter
The variable b is used as the pitch (in semitones relative to middle A) for every BEEP call throughout the program, including inside the subroutines at lines 450 and 460. Since b is a global variable, this works correctly. The prompt restricts input to 0–69, which spans roughly five octaves from middle A upward — a reasonable range for an audible tone.
Notable Anomalies
PAPER PIat line 20:PIevaluates to approximately 3.14159, which is truncated to 3 (magenta) by the PAPER attribute handler — a valid but unusual way to writePAPER 3.CLEARat line 10 with no argument clears all variables, which is harmless here but noteworthy.- The
INKEY$re-read bug described above means the program will frequently require multiple attempts to register a character, since the key is unlikely to still be pressed by the time lines 80–430 scan through their conditions.
Content
Image Gallery
Source Code
10 CLS : CLEAR
20 BORDER 2: PAPER PI: CLS
30 PRINT " ENTER YOUR TONE FREQUENCY."
40 PRINT " ****** 0 TO 69 ******"
50 INPUT b
60 LET short=460: LET long=450: PRINT AT 9,0;"Press any key to hear it's code"
70 INPUT INKEY$: PAUSE 10
80 IF INKEY$="a" THEN GO SUB short: BEEP .5,b
90 IF INKEY$="b" THEN GO SUB long: GO SUB short: GO SUB short: BEEP .05,b
100 IF INKEY$="c" THEN GO SUB long: GO SUB short: GO SUB long: BEEP .05,b
110 IF INKEY$="d" THEN GO SUB long: GO SUB short: BEEP .05,b
120 IF INKEY$="e" THEN BEEP .05,b
130 IF INKEY$="f" THEN GO SUB short: GO SUB short: GO SUB long: BEEP .05,b
140 IF INKEY$="g" THEN GO SUB long: GO SUB long: BEEP .05,b
150 IF INKEY$="h" THEN GO SUB short: GO SUB short: GO SUB short: BEEP .05,b
160 IF INKEY$="i" THEN GO SUB short: BEEP .05,b
170 IF INKEY$="j" THEN GO SUB short: GO SUB long: GO SUB long: BEEP .5,b
180 IF INKEY$="k" THEN GO SUB long: GO SUB short: BEEP .5,b
190 IF INKEY$="l" THEN GO SUB short: GO SUB long: GO SUB short: BEEP .05,b
200 IF INKEY$="m" THEN GO SUB long: BEEP .5,b
210 IF INKEY$="n" THEN GO SUB long: BEEP .05,b
220 IF INKEY$="o" THEN GO SUB long: GO SUB long: BEEP .5,b
230 IF INKEY$="p" THEN GO SUB short: GO SUB long: GO SUB long: BEEP .05,b
240 IF INKEY$="q" THEN GO SUB long: GO SUB long: GO SUB short: BEEP .5,b
250 IF INKEY$="r" THEN GO SUB short: GO SUB long: BEEP .05,b
260 IF INKEY$="s" THEN GO SUB short: GO SUB short: BEEP .05,b
270 IF INKEY$="t" THEN BEEP .5,b
280 IF INKEY$="u" THEN GO SUB short: GO SUB short: BEEP .5,b
290 IF INKEY$="v" THEN GO SUB short: GO SUB short: GO SUB short: BEEP .5,b
300 IF INKEY$="w" THEN GO SUB short: GO SUB long: BEEP .5,b
310 IF INKEY$="x" THEN GO SUB long: GO SUB short: GO SUB short: BEEP .5,b
320 IF INKEY$="y" THEN GO SUB long: GO SUB short: GO SUB long: BEEP .5,b
330 IF INKEY$="z" THEN GO SUB long: GO SUB long: GO SUB short: BEEP .05,b
340 IF INKEY$="0" THEN GO SUB long: GO SUB long: GO SUB long: GO SUB long: BEEP .5,b
350 IF INKEY$="1" THEN GO SUB short: GO SUB long: GO SUB long: GO SUB long: BEEP .5,b
360 IF INKEY$="2" THEN GO SUB short: BEEP .05,b: GO SUB long: GO SUB long: BEEP .5,b
370 IF INKEY$="3" THEN GO SUB short: GO SUB short: GO SUB short: GO SUB long: BEEP .5,b
380 IF INKEY$="4" THEN GO SUB short: GO SUB short: GO SUB short: GO SUB short: BEEP .5,b
390 IF INKEY$="5" THEN GO SUB short: GO SUB short: GO SUB short: GO SUB short: BEEP .05,b
400 IF INKEY$="6" THEN GO SUB long: GO SUB short: GO SUB short: GO SUB short: BEEP .05,b
410 IF INKEY$="7" THEN GO SUB long: GO SUB long: GO SUB short: GO SUB short: BEEP .05,b
420 IF INKEY$="8" THEN GO SUB long: GO SUB long: GO SUB long: GO SUB short: BEEP .05,b
430 IF INKEY$="9" THEN GO SUB long: GO SUB long: GO SUB long: GO SUB long: BEEP .05,b
440 GO TO 70
450 BEEP .5,b: PAUSE 2: RETURN : REM long
460 BEEP .05,b: PAUSE 2: RETURN : REM short
470 SAVE "MORSE rev2" LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.