QUEST Super ELF, Netronics ELF II Cassette tape support


This document last edited Oct 10 2019 HRJ (c) Herb Johnson. Content by other authors as noted.

Introduction

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

QUEST Copyright and terms

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

QUEST Super ELF Cassette Format

[superelf tape image]

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

Disassembled program listing

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

Commentary on Super ELF cassette

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

[WAV of Super BASIC]

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

Netronics Elf II cassette standards

[giant board cassette schematic]

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

Further description of Netronics cassette signal

[giant board cassette schematic]

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).

Update 2016, commentary on Elf II code

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


Herb Johnson
New Jersey, USA
follow this link to email @ me

Copyright © 2019 Herb Johnson except for content as identified by source.