--- title: "Morse rev2" id: 55122 type: "computer_media" slug: "morse-rev2" url: "http://localhost/computer_media/morse-rev2/" markdown_url: "http://localhost/computer_media/morse-rev2.md" published_at: "2024-06-16T23:27:23+00:00" modified_at: "2026-03-30T21:44:09+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "Type any letter or digit and hear its Morse code beep out in dots and dashes, with a user-chosen pitch — all in under 50 lines of BASIC." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Ham Radio" slug: "ham-radio" taxonomy: "genre" url: "http://localhost/type/ham-radio/" media_contents: - id: 54965 title: "ISTUG Public Domain Library 5" type: "computer_media" url: "http://localhost/computer_media/istug-public-domain-library-5/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/06/SCR-20260329-nddm.png" media_type_tags: "Ham Radio" --- 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: 1. **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 variables `short` and `long`. 2. **Input and dispatch loop (lines 70–440):** Waits for a keypress via `INPUT INKEY$`, then a linear chain of `IF INKEY$="x" THEN ...` statements routes to the correct sequence of dot/dash subroutine calls followed by a final `BEEP`. `GO TO 70` at line 440 restarts the loop. 3. **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 short` then `BEEP .5` for dash, but the final BEEP duration of .5 is the same as a dash — correct. - **Line 160 (i = · ·):** Only one `GO SUB short` plus final `BEEP .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 long` then `BEEP .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 inline `BEEP` mid-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 PI` at line 20: `PI` evaluates to approximately 3.14159, which is truncated to 3 (magenta) by the PAPER attribute handler — a valid but unusual way to write `PAPER 3`. - `CLEAR` at 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. ## 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 ```