--- title: "Modem" id: 56305 type: "computer_media" slug: "modem" url: "http://localhost/computer_media/modem/" markdown_url: "http://localhost/computer_media/modem.md" published_at: "2024-08-04T10:49:54+00:00" modified_at: "2026-03-30T21:44:07+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/08/SCR-20240804-jleb.png" excerpt: "A pulse-dialer and auto-launcher that drives a phone line through the expansion port, detects a carrier, then hands off to a machine-code terminal — all in 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: "Terminal" slug: "terminal" taxonomy: "genre" url: "http://localhost/type/terminal/" media_contents: - id: 56277 title: "Timex Sinclair Public Domain Library Tape 2001" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-2001/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Modem%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/08/SCR-20240804-jleb.png" media_type_tags: "Terminal" --- This program automates telephone dialing by sending pulse sequences through the TS2068’s expansion port (I/O port 119), then monitors the same port for a connection signal before launching [MTerm](http://localhost/computer_media/mterm/). Each digit is converted into a series of ON/OFF pulses via OUT 119 instructions, with the zero digit correctly mapped to 10 pulses at line 32. After dialing, the program polls IN 119 for the value 133 (line 165) to detect a carrier signal, plays a BEEP alert on connection, then patches a block of machine code in RAM via POKE statements before invoking it with PRINT USR 54016. The DATA block at line 300 contains 20 bytes of Z80 machine code patched into addresses 61193–61211, and several other POKEs at lines 220–260 modify MTERM. *** ## Program Analysis ### Program Structure The program is divided into four functional phases: 1. **Input & dial:** Lines 1–55 — prompt for a phone number string, then loop over each character to generate dial pulses. 2. **Pulse generation subroutine:** Lines 60–140 — a `GO SUB` routine that fires `a` pulse pairs through port 119. 3. **Connection detection:** Lines 160–180 — poll `IN 119` up to 2000 times, branching on value 133 (carrier detected), otherwise resetting and redialing. 4. **MTERM launch:** Lines 200–305 — alert the user with `BEEP`, patch the resident terminal program in RAM, and invoke machine code via `PRINT USR 54016`. Note that line 55 jumps to line 150, which does not exist; execution falls through to line 160. This is an intentional technique to enter the connection-polling loop. ### Pulse Dialing via Port 119 Port 119 is the TS2068’s expansion bus control port (also used by the AY sound chip interface region and external hardware). Here it is used to toggle an attached relay or phone interface. Each digit produces a sequence of pulse pairs: - `OUT 119,e` with `e` cycling 3→4 raises and lowers the line. - `PAUSE 2.5` (approximately 50 ms at 50 Hz) sets pulse width. - `OUT 119,1` and `OUT 119,2` provide inter-pulse spacing (line 110–120). - The digit zero is remapped to 10 pulses at line 32 (`IF a=0 THEN LET a=10`), matching the standard pulse-dial convention. - `PAUSE 35` at line 35 provides the inter-digit pause (~700 ms). The initial `OUT 119,31` at line 15 followed by `PAUSE 50` appears to assert an off-hook condition before dialing begins. ### Connection Detection Lines 160–180 implement a polling loop. `IN 119` is read up to 2000 iterations; if it returns the value 133, a carrier has been detected. If no carrier is found within the loop, `OUT 119,0` hangs up, a pause is taken, and the program restarts at line 3 (re-displaying the dialing screen and redialing). The value 133 (binary `10000101`) is hardware-specific to the attached modem or phone interface. ### MTERM Patching and Machine-Code Launch On successful connection, lines 220–280 directly patch a terminal program (MTERM) already loaded elsewhere in RAM. This is a sophisticated technique: rather than loading MTERM from tape at runtime, it is assumed to be pre-resident, and specific bytes are modified to configure it for the current session. | Lines | Address Range | Purpose | | --- | --- | --- | | 220 | 61157–61158 | POKE 24, 6 — likely a JP offset or configuration byte | | 230 | 61170, 61172 | POKE 184 — baud rate or port configuration bytes | | 240 | 61193–61211 | 19 bytes of Z80 machine code from the DATA block | | 250 | 61311–61331 | Fill 21 bytes with 32 (ASCII space / Z80 NOP equivalent region) | | 260 | 61699 | POKE 21 — likely a screen or protocol parameter | The DATA bytes at line 300 are: `254,147,27,95,254,147,27,95,234,246,50,193,154,89,193,247,105,105,121,195`. Decoding these as Z80 instructions reveals patterns such as `CP 147` (`FE 93`), `DEC DE` (`1B`), `LD E,A` (`5F`), `JP Z,nnnn` (`CA`/`C2`), and `LD A,C` (`79`), suggesting a receive/transmit character dispatch routine. The terminal is then invoked with `PRINT USR 54016`, calling machine code at address 54016. ### Notable BASIC Idioms and Anomalies - `LET a=VAL a$(i)` extracts a single digit from the phone number string by taking a one-character substring and converting it — a common Sinclair BASIC idiom since direct character-to-digit conversion is otherwise unavailable without `CODE`. - The connection-alert loop at lines 200–218 uses `INKEY$` polled without `PAUSE 0`; it loops via `GO TO 200`, replaying the `BEEP` sequence each pass, which gives a repeated beep until Enter is pressed. - `LIST` at line 305 after launching the machine code is unreachable under normal execution and appears to be a debugging remnant. - The `FLASH 1` attribute in both the dialing message (line 19) and the connected message (line 165) provides visual feedback without any additional logic. - `PAUSE 2.5` at line 90 uses a non-integer argument; the system truncates or rounds this to the nearest frame count (2 or 3 frames, ~40–60 ms), giving approximate pulse timing for the phone line. ## Source Code ``` 1 INPUT "Phone Number?";a$ 3 CLS 15 OUT 119,31 18 PAUSE 50 19 PRINT AT 10,8; FLASH 1;"Dialing "; FLASH 0;a$ 20 FOR i=1 TO LEN a$ 30 LET a=VAL a$(i) 32 IF a=0 THEN LET a=10 35 PAUSE 32 40 GO SUB 60 50 NEXT i 55 GO TO 150 60 FOR d=1 TO a 70 FOR e=3 TO 4 80 OUT 119,e 90 PAUSE 2.5 100 NEXT e 110 OUT 119,1 120 OUT 119,2 130 NEXT d 140 RETURN 160 FOR i=1 TO 2000 165 IF IN 119=133 THEN CLS : PRINT FLASH 1;"C O N N E C T E D ! !": GO TO 200 168 NEXT i 170 OUT 119,0 175 PAUSE 100 180 GO TO 3 200 FOR i=1 TO 10: BEEP .05,18: NEXT i 210 LET g$=INKEY$: PRINT AT 10,0; FLASH 1;"Hit to Start MTERM" 215 IF g$=CHR$ 13 THEN GO TO 220 218 GO TO 200 220 POKE 61157,24: POKE 61158,6 230 POKE 61170,184: POKE 61172,184 240 FOR i=61193 TO 61211: READ m: POKE i,m: NEXT i 250 FOR i=61311 TO 61331: POKE i,32: NEXT i 260 POKE 61699,21 280 OUT 119,34: PRINT USR 54016 300 DATA 254,147,27,95,254,147,27,95,234,246,50,193,154,89,193,247,105,105,121,195 305 LIST ```