This document last edited Oct 10 2019 HRJ (c) Herb Johnson. Content by other authors as noted.
Microcomputers of the 1970's, often used audio cassettes to store and recall programs and data, before floppy diskette drives became available and affordable. Binary data was represented by a few cycles of audio tones, under various schemes or methods. See the linked document for discussion of audio tape cassette formats. This Web page discusses the data and encoding of data for the QUEST Super ELF, a microcomputer based on the COSMAC 1802. A Web page with similar information is is about the COSMAC VIP microcomputer from RCA.
If the 1802 interests you, Check my support of the 1802 Membership Card. - Herb Johnson
The following emailed note, from the copyright owner, accompanied some of the Quest Super ELF documentation on the cosmacelf site. Quote: "All information regarding the Super Elf developed and copyrighted by Quest Electronics is hereby released to the public domain for noncommercial use only. No commercial use of this software and related material including manuals and applications is permitted without the express written consent of Quest Electronics. - Roger Pitkin 11/12/10" - end quote
The following is a "Super ELF Cassette Format" article from an issue of Questdata COSMAC Club magazine, pages 13-14. A copy of this document can be found in the files archives at the Yahoo or groups.io group "cosmacelf" as of 2012. OCR'd by Herb Johnson Dec 2012 and again Oct 2019.Here's a PDF of the newsletter document. - Herb
The Super Elf Super Monitor and Super Basic use the following cassette format.
This approach allows automatic loading into memory since the starting address is on the tape. A test can be made to see if there is enough space in memory for the file prior to loading because the file also contains the mmmber of bytes. Each byte includes a parity bit which is used for error checking. The rate of recording and playback is apprmclmately 1200 bytes per second with a 1.79 MHz clock. Reliable operation has been achieved (with a recommended recorder) at 2000 bytes per second using a 3.0 MHz clock.
The read software used ln the Super Monitor and Super Basic allows starting the recorder with the cassette fully rewound. The plastic leader/tape splice does not cause problems and it is not necessary to advance the cassette past the leader prior to starting In fact there are no level adjustments or tape positioning required (when using one of the recommended recorders). Just load, set volume and tone to max and go. This format is self clocking and insensitive to speed variations of over +/-15%.
The Format Consists of:
1. A 10 second leader of all 'ones' terminated with a zero bit.
2. Data bytes.
3. A 5 sec trailer of all 'zeros'.
The Data Section Consists of:
1. Starting address 2 bytes Hi/Low. (0000 TO FFFF HEX)
2. Number of bytes 2 bytes Hi/low. (0000 TO FF00 HEX)
3. Data bytes 8 bits with the most significant (MSB) first with an added parity bit. (For a total of 9 bits). Even parity is used, i.e. the sum of the ones in the data plus the parity bit is always an even mumber.
DATA 0111 01 01 PARlTY=1 (6 '1's) DATA 0011 00 11 PAR1TY=0 (4 '1's)
A bit is defined as a high level followed by and equal length low level. A zero bit is three times the length of a one bit. The end of a bit is the beginning of the next bit.
The following bit times are for a 1.79 MHz clock. The effects of other clock frequencies are discussed later.
1. A ONE bit has a 206 microsec ON time and a
609 to 627 microsec OFF time.
2. A ZERO bit has a 618 microsec ON time and a 609 to 627 microsec OFF time. But see the comment below.
The standard Super Elf with a 1.79 MHz clock and either Super Basic or the Super Monitor uses this format. If your system uses a different clock frequency, make the following changes to
For Different Clock rates, Solve this equation: VALUE = 8 X clock rate in MHz - 1.3
Round off VALUE, convert to hexadecimal and patch into location 8193 in the Super Monitor Vl.1 or 2.0; and location 2947 in Super Basic 1.4; QKOC is the location in the cassette read routine.
Super Elf owners may ignore this section. Non Super Elf owners must use the listed cassette read routine and may need to use the schematic for read hardware. Elf II owners usually can successfully read with their own hardware. The following table lists the changes required for the different sense lines.
EF1 EF2 EF3 EF4 QKl6 34 35 36 37 QK1D 3C 3D 3E 3F QK2C 3C 3D 3E 3F QK41 34 35 36 37 QK48 3C 3D 3E 3F QK53 3C 3D 3E 3F
Where QK is the Quarter K of memory in which the cassette read routine is loaded. NOTE: Do not load the read routine in a page which will be written into by the read routine.
If you have trouble reading you may have the signal inverted (all recorders are not the same even the same brand and model). This software usually but not always accepts either normal or inverted data, it depends upon the amount of distortion introduced by the recorder. The following table inverts the data.
EF1 EF2 EF3 EF4 QKI6 3C 3D 3E 3F QK1D 34 35 36 37 QK2C 34 35 36 37 QK41 3C 3D 3E 3F QK48 34 35 36 37 QK53 34 35 36 37
To use the cassette read routine (non Super Elf owners only), follow the following instructions.
1. Load program per this load listing. QK refers to your page of memory where you want the program to reside:
2. Branch into the program from register O into location QK00. If you wish to branch into the program from any other register (but not register 2 or 5) then change the "90" instruction at location QK00 to "9P" where P ls the same as the register designation which you are using. Then branch into QK00.
3. After starting the program, load the cassette at the beginning, start recorder in playback with maximum volume and treble on the tone control. There is a 10 second leader and then the low address of the current location of memory being loaded off the cassette will be displayed. The rate is about 1200 baud. At the end of loading, an "AA" will show up on the display (If you have a hex display at output port 64).
4. If a parity error is detected, an "EE" will be displayed (on the hex display). Check the program for Loading errors and try re-running the playback. Also check your hardware setup. Future articles will discuss: (a. The Elf II format and how non Elf II owners can read Elf II cassettes. (b. The Super Elf write/read software source listings.
QK00 90B3 E2B5 82F8 72A2 F812 A5F8 0DB6 F83E OK10 A3D3 F808 A6A7 3616 96FF 013B 223E 1927 QK20 302E F800 FC01 3B2C F8EE 306F 3E24 8632 QK30 3797 7EB7 2630 1687 F633 2897 3011 F80A QK40 B436 4196 FF01 3B50 3E44 9432 4124 3041 QK50 943A 3E3E 53D5 B8D5 A8D5 B9D5 A929 99FC QK60 01B9 D558 8852 6422 1829 993A 62F8 AA52 QK70 6400
On Oct 9 2019, I (Herb) hand-disassembled the hex codes above into an 1802 program with some comments. In the process I confirmed carefully the hex codes above against the printed copy; and examined the program for consistency. Confusion between 0 and D, and B and 8 were resolved. If you find errors please inform me. - Herb Johnson
;enter with PC = R0 QK00 90 GHI R0 ;address of this page B3 PHI R3 E2 SEX R2 ;X->R2 B5 PHI R5 B2 PHI R2 F8 72 LDI 72H A2 PLO R2 ;R2-> QK72 F8 12 LDI 12H A5 PLO R5 ;R5-> QK12 F8 0D LDI 0DH B6 PHI R6 F8 3E LDI 3EH QK10 A3 PLO R3 ;R3-> QK3E to read tape QK11 D3 SEP R3 ;R3 is PC QK12 F8 08 LDI 08H ;subroutine to get a byte A6 PLO R6 ;low R6 counts A7 PLO R7 QK16 36 16 B3 16H ;branch here 96 GHI R6 QK19 FF 01 SMI 01H 3B 22 BL 22H ;exit when 3E 19 BN3 19H 27 DEC R7 QK20 30 2E BR 2EH QK22 F8 00 LDI 00H QK24 FC 01 ADI 01H 3B 2C BL 2CH QK28 F8 EE LDI 0EEH ;parity error msg 30 6F BR 6FH ;display & exit loader QK2C 3E 24 BN3 24H 86 GLO R6 32 37 BZ 37H QK31 97 GHI R7 7E SHLC ;shift bit left B7 PHI R7 26 DEC R6 ;countdown 30 16 BR 16H QK37 87 GLO R7 F6 SHR 33 28 BGE 28H ;parity error 97 GHI R7 30 11 BR 11H ;return byte OK QK3E F8 0A LDI 0AH ;read tape now QK40 B4 PHI R4 36 41 B3 41H ; branch here 96 GHI R6 FF 01 SMI 01H 3B 50 BL 50H 3E 44 BN3 44H 94 GHI R4 32 41 BZ 41H 24 DEC R4 30 41 BR 41H QK50 94 GHI R4 3A 3E BNZ 3EH 3E 53 BN3 53H ; branch here D5 SEP R5 ;call KQ12 B8 PHI R8 D5 SEP R5 ;call KQ12 A8 PLO R8 ;R8 = start addr D5 SEP R5 ;call KQ12 B9 PHI R9 D5 SEP R5 ;call KQ12 A9 PLO R9 ;R9 = # of bytes 29 DEC R9 99 GHI R9 FC 01 ADI 01H QK61 B9 PHI R9 ; tape data read routine QK62 D5 SEP R5 ;call KQ12 to get byte 58 STR R8 ;save byte 88 GLO R8 52 STR R2 ;storage address 64 OUT4 ;display it 22 DEC R2 ;OUT increments R2 18 INC R8 ;next byte addr 29 DEC R9 ;countdown bytes 99 GHI R9 ;test R9 3A 62 BNZ 62H ;get more F8 AA LDI 0AAH QK6F 52 STR R2 QK70 64 OUT4 ;display 00 IDL ;wait here, loading done QK72 ;X points here, RAM buffer
Richard cpd1861 posted in cosmacelf Yahoo group on Dec 2 2018:
[About] "1. A ONE bit has a 206 microsec ON time and a 609 to 627 microsec OFF time."
"I think the 609 to 627 microsecond OFF time is wrong. It should probably be similar to the 206 microsecond ON time, judging from what I see in the WAV files. But I would like to confirm this by looking at a recording that definitely comes from a Super Elf." - Richard
In early Oct 2019, I did in fact digitize some ELF II audio cassette programs, including Super BASIC itself. Her's an Audacity display of a few cycles of 1 and 0 bits. Note there's a full cycle of each, positive and negative; no half-cycles of different frequencies. If you count the samples at 44,100 Hertz (22.67 usec), you get something close to 206 and 618 usec per half-cycle; in pairs. I also noticed, the leader was all ones (no zero bits) and the trailer (if any) was all zeros. On trailers: the loader above simply stops loading after the last byte of program/data.
I discussed these observations with Marcel van Tongeren, developer of the EMMA 02
emulator which accepts audio files as cassette data input. He said: "The COMX format [I looked at
35 years ago] is very similar to the Super BASIC as it was based on the same code. Also the COMX format had full cycles for both one and zero; i.e. as you state a one has 206 ms ON and 206 ms OFF. So I agree with your conclusion!"- Herb Johnson
Chris Wardell posted in cosmacelf Yahoo on Dec 2012: "The cosmacelf files section contains a "Giant Board HTML" folder that has the Netronics documentation for the [Neutronics brand] "Giant Board" which is [the add-on board which] added cassette I/O to the ELF II. You will find the schematic which includes the cassette circuits and the binary code for the monitor program that includes cassette read and write routines." From 2012 that link is http://groups.yahoo.com/group/cosmacelf/files/Giant%20Board%20HTML/ . In 2019 the link is https://groups.io/g/cosmacelf/files/Giant%20Board%20HTML More information was founds at at an ELF archive at this Web link. The ELF II schematic there suggests the ELF II ran the 1802 at 1/2 the 3.58MHz crystal in use. Since 1802 instruction time determines cassete timing, this is important.
One of those documents (the HTML document) describes the cassette as follows: "CASSETTE: Serial data transfer from the processor to a cassette tape utilizes the Q output on the 1802. A program located in the ROM A10 will set and reset the Q producing signals similar to the Kansas City standard. [Not so, read the note below. - herb] It is important whether or not your tape recorder inverts the polarity of the output compared to the input signal. This is not important for music, but is extremely important when transferring data. Most of the machines we have checked do not invert the data. However, we have heard reports that even the same brand may change from run to run. It is largely a function of the tape head connections." Either "connect J1 and J3 leaving J2 open"; or "disconnect J1 and J3, and connect J2".
Monitor source code says "Netronics ELF II monitor program from the Giant board...based on the Popular Electronics EHOP and ETOP monitor programs published in the original COSMAC ELF articles." A snip of the write code, slightly modified by me for clarity, is below. Entry to the routine is at WRITE+1, the SEP R3 amounts to an 1802 "return" from subroutine. LIkewise entry to the READ routine is at READ+2 (or RE2), return at READ. If I'm correct, this VIC II 1802 is clocked at 1.79MHz, or .559 microseconds per clock, or 4.47 microseconds per instruction/memory cycle of 8 clocks. MOst 1802 instructions take 2 instruction/memory cycles.
000303 0064 ; WRITE - Write data to the cassette tape 000304 0064 ; 000305 0064 ; DF=0, write a 0 to the tape 000306 0064 ; DF=1, write a 1 to the tape 000307 0064 ; 000308 0064 D3 WRITE: SEP R3 ; (return) Modulate the Q line to write 1's & 0's on tape 000309 0065 7B SEQ ; (entry) Shorter pulse widths are 0's 000310 0066 F81D LDI H'1D ; Longer pulse widths are 1's 000311 0068 3B6D BNF WR9 000312 006A F807 LDI 7 000313 006C 1D INC RD 000314 006D 52 WR9: STR R2 000315 006E FF01 WR10: SMI 1 000316 0070 336E BDF WR10 000317 0072 3964 BNQ WRITE ;amounts to "return" branch 000318 0074 7A REQ 000319 0075 02 LDN R2 000320 0076 306E BR WR10
000391 00B8 ; READ - Read data from the cassette tape 000392 00B8 ; 000393 00B8 1D READ: INC RD 000394 00B9 D3 RE1: SEP R3 ; (return point) 000395 00BA F80D RE2: LDI H'0D ; (entry point) 000396 00BC 35BC B2 * ; Wait for *EF2 to go low 000397 00BE 35B8 RE6: B2 READ ; Return if *EF2 is low 000398 00C0 FF01 SMI 1 000399 00C2 33BE BDF RE6 000400 00C4 3DC4 BN2 * ; Wait for *EF2 to go high 000401 00C6 30B9 BR RE1 ;amounts to "return" branch
Issue 20 of Ipso Facto, found in the cosmacelf.com file archives, has an article by Keenneth Mantei titled "ELF II Cassette I/O" of Dec 1978 which says: "By studying the Netronics monitor program or putting an oscilloscope on an Elf II, some bit/byte details can be seen. One cycle of 2400 Hz (0.43 mS) represents a "1" bit. One cycle of 800Hz (1.25mS) is a "0" bit. the pre-program header is a continuous tone of "1" bits. Each of the 8-bit program bytes is....one "0" start bit, the 8-bit byte [from most to least signifigant bit], and a parity bit. the parity bit is "1" if there are an even number of "1" bits in the byte, "0" if odd." The byte 3B needs a 0 parity bit, 3A a 1 parity bit.
This is NOT not not the Kansas City standard. The KC standard uses different many cycles per bit, at different frequencies, and with a different "frame" (start/data/end bits).
I had correspondence in May 2016, on Yahoo group cosmacelf, with Norman Hurst and others, about the VIP cassette interface. But it began as a "thread" titled "I need help reading a bunch of Netronics Elf II tapes". In the course of cosmacelf disucssion, Norman referenced this Web page, and wrote some supporting code and did some tests, and posted his results. I've copied his post as below. Copies of that yahoo group are available since 2019 in the groups.io "cosmacelf" discussion. - Herb
I recently wrote a bytes-to-tones converter script for the VIP tape format, so I am intrigued by this thread. If you can capture an example tape to a .wav or .mp3 file and post it, I could try to create a demodulator script to make bytes from it. I parsed the assembly code from Herb Johnson's post and commented it heavily. It seems clear that the code generates ~50% duty cycle square waves with one cycle per bit. A short cycle (high frequency) is used for a '1', a long cycle is used for a '0': /Norm
000303 0064 ; WRITE - Write one bit (DF) to the cassette tape using Q output 000304 0064 ; 000305 0064 ; DF=0, write a 0 to the tape 000306 0064 ; DF=1, write a 1 to the tape 000306 0064 ; The Q line is used as the output to tape 000307 0064 ; 000308 0064 D3 WRITE: SEP R3 ; (return) ; Writes one cycle of a 50% duty cycle square wave. ; Cycle period depends on value of DF. ; DF=1 makes a short cycle (high frequency); DF=0 makes a long cycle. ; STARTS HERE: ; First half is high, Q=1: 000309 0065 7B SEQ ; Take Q line high ; Set up the timer value in D: 29 for a '0', 7 for a '1': ; This value determines the duration of each half-cycle of the square wave. ; Set as if DF=0: 000310 0066 F81D LDI H'1D ; set D=29. This will change later if DF=1. 000311 0068 3B6D BNF DELAY ; if the bit is zero, goto DELAY, else... ; The bit (DF) is a '1': 000312 006A F807 LDI 7 ; The bit is '1': set D=7 (it was 29) 000313 006C 1D INC RD ; Incr Reg D. (parity counter?) 000314 006D 52 DELAY: STR R2 ; save the timer value for use on the 2nd half of the cycle ; Half-cycle timer loop: 7 times for a '1', 29 times for a '0': 000315 006E FF01 LOOP: SMI 1 ; decrement D. (This operation overwrites the bit in DF) 000316 0070 336E BDF LOOP ; if DF==1, goto decrement D again ; We get here twice: ; The first time is after the first half-cycle (Q=1). ; The second time is after the second half-cycle (Q=0). ; Return after second half-cycle (if Q=0): 000317 0072 3964 BNQ WRITE ; ; Set up for second half-cycle: ; Take the output line low, get the saved timer value and do the Loop again: 000318 0074 7A REQ ; clear the output line 000319 0075 02 LDN R2 ; get the saved timer value 000320 0076 306E BR WR10 ; go to the loop again ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 000391 00B8 ; READ - Read one bit from the cassette tape 000392 00B8 ; Input line is EF2. Output is in RD. 000392 00B8 ; Assumes input EF2 is high when we start. ;; works by timing the 'low' duration of the input ;; duration < timer means '1' ;; duration > timer means '0' ; ENDS HERE if '1': ; Increment RD if the cycle was short, then return: 000393 00B8 1D READ: INC RD ; fall through to return... ; ENDS HERE if '0': just return without incrementing RD: 000394 00B9 D3 RE1: SEP R3 ; (return point) ; ** STARTS HERE: ** ; Set D as a timer value = 13 000395 00BA F80D RE2: LDI H'0D ; (entry point) Set timer value in D=13 ; The input is high; Wait for it to go low: 000396 00BC 35BC B2 * ; Wait for *EF2 to go low ; input just went low. Start timing... ; if *EF2 goes high before timer expires, it's a short cycle which means the bit=1 000397 00BE 35B8 RE6: B2 READ ; went high before timer expired: goto increment RD & return 000398 00C0 FF01 SMI 1 ; decrement D (timer) 000399 00C2 33BE BDF RE6 ; if timer not expired, check input & loop ; Timer expired while input remained low: it's a long cycle, which means the bit = 0. 000400 00C4 3DC4 BN2 * ; Wait for *EF2 to go high 000401 00C6 30B9 BR RE1 ; Return WITHOUT incrementing RD
Copyright © 2019 Herb Johnson except for content as identified by source.