High Speed Reader

The High speed Reader is a parallel interface, with handshaking.
Typical tetetype age equipment!

It is activated with the .H command (toggle switch)

8 parallel data connected to Port A.

Used in LH command to read from High Speed Reader instead of serial input.

0659   733D AD 02 6E    RDHSR  LDA MPB           ; LOOP ON DATA AVAIL
0660   7340 29 08              AND #DAVAIL
0661   7342 F0 F9              BEQ RDHSR
0662   7344             ;
0663   7344 AE 00 6E           LDX MPA           ; READ DATA
0664   7347 AD 02 6E           LDA MPB           ; SEND GOT-DATA PULSE
0665   734A 09 04              ORA #GOTDAT
0666   734C 8D 02 6E           STA MPB
0667   734F 29 FB              AND #%11111011
0668   7351 8D 02 6E           STA MPB
0669   7354 8A                 TXA
0670   7355 29 7F              AND #$7F
0671   7357 60                 RTS

0381   716F E6 E8       HSP    INC HSROP         ; TOGGLE BIT C
0382   7171 4C 86 70           JMP START

0598   72E9             ;
0599   72E9             ;  OUTPUT  RETURNS CHAR IN A
0600   72E9             ;
0601   72E9 A5 E7       RDT    LDA HSPTR         ; TEST HS PTR OPTION
0602   72EB 4A                 LSR A
0603   72EC B0 4F              BCS RDHSR

0383   7174             ;
0384   7174 20 E9 72    LH     JSR RDOC          ; READ SECOND CMD CHAR
0385   7177 20 8A 72           JSR CRLF
0386   717A A6 E8              LDX HSROP         ; ENABLE HSR OPTION IF SET
0387   717C 86 E7              STX HSPTR
0388   717E 20 E9 72    LH1    JSR RDOC        

0397   718F A2 00              LDX #0            ; CLEAR HS RDR FLAG
0398   7191 86 E7              STX HSPTR
0399   7193 F0 9F              BEQ BEQS1       

What is happening here?

RDHSR

  • PB3 is input DAT-Avail is a strobe, made high by the reader if data is available (659-661).
  • PB2 is output GOT-Data. made high to indicate the data has been read into X (664-668) and cleared (667-668)
  • The reader should end the strobe if GOT_Data is strobed.
  • 8 bits are read in X, transferred to A, the highest bit is stripped of (670-671)

HSP

    When .H is entered the HSROP flag is incremented, as toggle switch, odd is enabled (381 -382)

RDT = RDOC

    Check if odd, then branch to RDHSR read high speed reader)

WB BNPF dump of TIM

BNPF notation (Begin-Negative-Positive-Finish) is an old ASCII-based text file format created by Intel to specify memory contents and program PROMs and EPROMs.

BNPF (Begin-Negative-Positive-Finish), also written as BPNF (Begin-Positive-Negative-Finish).
In BNPF encoding, a single byte (8 bits) would be represented by a highly redundant character framing sequence starting with a single uppercase ASCII “B”, eight ASCII characters where a “0” would be represented by a “N” and a “1” would be represented by a “P”, followed by an ending ASCII “F”. These ten-character ASCII sequences were separated by one or more whitespace characters, therefore using at least eleven ASCII characters for each byte stored (9% efficiency). The ASCII “N” and “P” characters differed in four bit positions, providing excellent protection from single punch errors.

Structure of BNPF Format

  • Brackets: Every data word field begins with the letter B (Begin) and ends with F (Finish/Final).
  • Bit Values: Characters between B and F represent data bits using P (Positive) for high/1 or N (Negative) for low/0, ordered from most to least significant.
  • Don’t Care: An X character can be used inside the sequence to represent a wildcard or “don’t care” bit.
  • Repetition: The syntax BPNF allows a number N to repeat the previous word field multiple times.
  • Comments: Any text or comments outside of the B…F blocks (provided they do not contain the letters B or F) are ignored by the programmer

Example of BNPF output

.M  7000 85 F9 A9 23 D0 55 A9 16

85 = 10000101 
    BPNNNNPNPF 

.WB 7000 7100
7000 BPNNNNPNPF BPPPPPNNPF BPNPNPNNPF BNNPNNNPPF
     ^^^^^^^^^^
.WH 7000 7100
;18700085F9A923D055A9168D036EA208BDF7739DF7FFCAD0F786EA0F19
       ^^

More examples: notice the removal of the B character from the address. According to the specification, also the F character should be removed, but the routine responsible (ASCI in Write hex routines) only checks for B.

.WB B000 B100
 000 BNNNNNNNNF BNNNNNNNNF BNNNNNNNNF BNNNNNNNNF
 004 BNNNNNNNNF BNNNNNNNNF BNNNNNNNNF BNNNNNNNNF
 008 BNNNNNNNNF BNNNNNNNNF BNNNNNNNNF BNNNNNNNNF
 00C BNNNNNNNNF BNNNNNNNNF BNNNNNNNNF BNNNNNNNNF

.WB 70B0  7100
70 0 BNNNNNNPPF BNNPNNNNNF BNPPPNPNNF BNPPPNNPPF
.

Here the official definition of BNPF code from the Intel Memory Design handbook 1975, page 8-28 and 8-29.

0481   723B E6 FD       WB     INC SAVX          ; SAVX TO = NCMDS FOR ASCII SUB/R
0482   723D A5 E4       WB1    LDA WRAP          ;IF ADDR HAS WRAPPED AROUND
0483   723F D0 F7              BNE BCCST         ;THEN TERMINATE WRITE OPERATION
0484   7241             ;
0485   7241 A9 04              LDA #4
0486   7243 85 EC              STA ACMD
0487   7245 20 8A 72           JSR CRLF
0488   7248 20 9A 72           JSR WROA          ; OUTPUT HEX ADR
0489   724B             ;
0490   724B 20 77 73    WBNPF  JSR SPACE
0491   724E A2 09              LDX #9
0492   7250 86 FE              STX TMPC          ; LOOP CNT =9
0493   7252 A1 E5              LDA (TMP0-9,X)
0494   7254 85 FF              STA TMPC2         ; BYTE TO TMPC2
0495   7256 A9 42              LDA #'B'
0496   7258 D0 08              BNE WBF2          ; WRITE B
0497   725A             ;
0498   725A A9 50       WBF1   LDA #'P'
0499   725C 06 FF              ASL TMPC2
0500   725E B0 02              BCS WBF2
0501   7260 A9 4E              LDA #'N'
0502   7262             ;
0503   7262 20 C6 72    WBF2   JSR WROC          ; WRITE N OR P
0504   7265 C6 FE              DEC TMPC
0505   7267 D0 F1              BNE WBF1          ; LOOP
0506   7269 A9 46              LDA #'F'
0507   726B 20 C6 72           JSR WROC          ; WRITE F
0508   726E             ;
0509   726E 20 97 73           JSR INCTMP
0510   7271             ;
0511   7271 C6 EC              DEC ACMD          ; TEST FOR MULTIPLE OF FOUR
0512   7273 D0 D6              BNE WBNPF
0513   7275             ;
0514   7275 20 C1 70           JSR DCMP
0515   7278 B0 C3              BCS WB1           ; LOOP WHILE EA GT OR = SA
0516   727A 90 BC              BCC BCCST
0517   727C             ;
0518   727C 48          CADD   PHA               ; SAVE A
0519   727D 18                 CLC
0520   727E 65 F2              ADC TMP4
0521   7280 85 F2              STA TMP4
0522   7282 A5 F3              LDA TMP4+1
0523   7284 69 00              ADC #0
0524   7286 85 F3              STA TMP4+1
0525   7288 68                 PLA               ; RESTORE A
0526   7289 60                 RTS

0262   70C1 38          DCMP   SEC               ; TMP2-TMP0 DOUBLE SUBTRACT
0263   70C2 A5 F0              LDA TMP2
0264   70C4 E5 EE              SBC TMP0
0265   70C6 85 E5              STA DIFF
0266   70C8 A5 F1              LDA TMP2+1
0267   70CA E5 EF              SBC TMP0+1
0268   70CC A8                 TAY               ; RETURN HIGH ORDER PART IN Y
0269   70CD 05 E5              ORA DIFF          ; OR LO FOR EQU TEST
0270   70CF 60                 RTS

0478   7238 4C 86 70    BCCST  JMP START

What is happening here?
This routine is called from the W command handler if after the W the character B is typed by the user. So the command paraneters start and end addresa re already parsed
– start address in TMP0
– end address in TMP0+2

  • save this command in NCMDS for ASCI routine, called from WROB write byte as two hex characters (481)
  • loop address range
    • if address wrap around we rare finished, return to START (482-483)
    • ACMD = 4 to have four bytes per line (485-487)
    • loop ACMD 4 times
      • CRLF + print address via WROA, see hex routines (487-488)
        • print space
        • TMPC = 9 characters to print (491-492)
        • TMPC2 is byte to print as BNPF format
        • print B
        • loop TMPC
          • shift TMPC2 bit in to carry (499)
          • if carry set print P else print N (498-505)
        • print F (506)
      • next address (514)
  • jump to start (516, 478)

Note WROA calls ASCII, to perform the byte to ASCII conversion, There the command code in NCMDS is ued to suppress the B in the address, the address is considered to be a comment to the PROM programmer device.

Memory map

This is the memory map after RESET.

Bill Mensch on the creation of the 6530

Letter from Bill Mensch on the creation of the 6530

Bill Mensch wrote:
I would be happy to contribute some commentary concerning the creation of the 6530 at MOS.

What are you interested in other than it was the second chip for the combination of the 6502 for use in control systems.
The KIM-1 was a reference design/use case for bothe the 6502 and the 6530, actually two of them.
One 6530 was for the “Teletype Input Monitor (TIM)” and the other one was for the “Keypad Input Monitor (KIM)”.

It was first demonstrated along with the 6501/6502 at the WESCON ’75.
The 6502 and 6530 were ment to compete with the $29 Intel 4040 two chip controller combo.

The actual design was important for the introduction of the 6502.
I and a team of three mask designers Harry Bawcom, Mike Jaynes and Sid Holdt created the 6530.
The timer design was patented and used on the 6530, 6531 and 6532 chips.

Chuck Peddle and Wil Mathys contributed the system level applications concepts and requested the features.
We were a small team. I was the semiconductor design and architect engineer.
The 6530 followed many of the design concepts of the 6820/6520/6821/6520 concepts for IO and interrupt features.

The 6522 followed the 6520/6530/6532 designs at MOS.

Ray Hirt was the project lead on the 6532.
The 6532 RIOT design was basically to remove the ROM and add another 64 bytes of RAM for a total of 128 bytes.
I was the microprocessor design manager at this time replacing Rod Orgill who had left MOS to work at NCR in Colorado Springs, CO.
Rod didn’t work on any of the IO chips, just the 6501/6502.

Ray, Rod, sometimes Wil and I shared many a pitcher of beer at many lunches after the 6502 and 6530/32 were completed before Rod left for Colorado.
These are fond memories of my time at MOS.

Let me know if you have any questions.

Best,
-Bill

RESET of TIM

The RESET of a system with a 6530-004 TIM is a bit special. The RESET code comes from the OTIM ROM, after the RESET the memory map is restored to the documented one.

0084   0000             MDBK   =%00010110        ; X,X,X,PCR,DATA-AVAIL,GOT-DATA,SERIAL-OUT,IN

0095   0000             UINT   =$FFF8  

0793   73F8 00 70       INTVEC .WORD NMINT       ; DEFAULT USER INTRO TO NMINT
0794   73FA 00 70              .WORD NMINT
0795   73FC 06 70              .WORD RESET
0796   73FE 52 70              .WORD INTRQ
	
0144   7006 A9 16       RESET  LDA #MDBK         ; INIT DIR REG, PCR TO 1 RELOCATES
0145   7008             ;
0146   7008 8D 03 6E           STA MDB
0147   700B             ;
0148   700B A2 08              LDX #8            ; X=0
0149   700D BD F7 73    R1     LDA INTVEC-1,X    ; INITALIZE INT VECTORS
0150   7010 9D F7 FF           STA UINT-1,X
0151   7013 CA                 DEX
0152   7014 D0 F7              BNE R1
0153   7016             ;
0154   7016 86 EA              STX MAJORT        ; INIT MAJOR T COUNT TO ZERO
0155   7018 86 E7              STX HSPTR         ; CLEAR HSPTR FLAGS
0156   701A 86 E8              STX HSROP
0157   701C CA                 DEX               ; X=FF
0158   701D 9A                 TXS               ; SP=FF

The Chip Select equations for the 6530-004

What is happening here?

The address decoding is a bit course, the ROM of the 6530-004 is not only at $7000, but also mirrored at $7400, $7800 and $7C00. So $73FF is also $7FFF.

The PB4 circuit from the TIM manual


The PB4 circuit in the Jolt, note the pullup resistor.

After power PB4 is an input, the default for a 6530 port. So the inverter input is seen as high (on the Jolt a pullup resistor makes that certain) , so the output of the inverter is low. This blocks the 7400 port input, the other input is A15. So the ROM address $7FFF is mirrored to $FFFF. And so the RESET vector of the 6502 is read from the ROM the 6530-004, and the program counter is set to $7006, the RESET code in the ROM.

The Data Direction register or Port B is loaded with MDBK =%00010110

  • 0 PB0 input serial in
  • 1 PB1 output serial out
  • 1 PB2 is output GOT-Data High speed reader
  • 0 PB3 is input DAT-Avail High Speed reader
  • 1 PB4 is output PCR this makes PB4 low and A15 reaches the CS of the 6530-004.
  • 0 PB5 is input unused
  • 0 PB6 is input unused
  • 0 PB7 is input unused

By making PB4 an output, PB4 becomes low, the output of the 7400 high, and A15 reaches the 6530, so the ROM is not seen at FFFF. Teh default memory map is now active.

The 8 vector bytes from the ROM are now loaded into the RAM of the 6430-004 at upper memory (location UINT) in a loop with X as down counter to zero (148-152)

Some counters and flags are now initialized to zero with X (High speed reader, serial T count) (154 to 156)

As last the stack pointer is set to $FF (157-158)

JOLT TIM DEMON explained

The Jolt and SuperJolt computers use the 6530-004 RRIOT TIM IC. The Jolt is in fact just a board with a 6502 with a TIM RRIOT + some RAM and a PIA 6520 and some decoding logic.
The program in the TIM is called DEMON by Micro Associates (Ray Holt and Manny Lemas).

So understanding how the Jolt works starts with understanding how the TIM RRIOT hard- and software works.

The TIM RRIOT, 6530-004,contains the ROM (1K), timers, 128 byte RAM, 16 I/O) and 64 bytes RAM.

TIM DeMon Manuals

MOS TIM folder with pricelist
MOS TIM manual Rev 6500-20
Jolt DeMon software manual, the same as TIM
(this manual has an alternative listing of the TIM 6530-004 monitor), only the first page is different.
Jolt Replica User manual

TIM sources

Here the machine readable and ready to assemble source, listing and binary  of TIM (Thanks Martin Hoffmann-Vetter)
Note that this contains a corrected version, version 2026! While testing the TIM Simulator I found an error in the papertape loader LH command, the ‘;’ start of a record seems to be OCR’ed to ‘:’ . In 2026, during the deep dive into explaining the TIM, many OCR errors in the comments were corrected.
The resulting binary is identical to the ROM dumped from a real 6530-004.
The source listing is used on the next pages to explain the software.

TIM/Jolt explained

Bug in the TTY KIM-1 monitor?

The KIM-1 monitor surprises me every time I dive into it.
The KIM-1 Explained is nearing completion. The KIM-1 explained

There is a bug in the TTY CLI, it accepts characters as ‘;’ and ‘:’ as valid hex and translates to A..F.

KIM
0200 A9 ;;
00BB 00 ::
00AA 00 ????
FFFF 1C

More about this innocent feature here: PRTBYT, GETBYT and PACK

PRTBYT, GETBYT and PACK

PRTBYT takes a byte and sends it to the serial TY as two hex ascii characters
The byte is entered in A, two characters are printed and A is saved.

0914   1E3B             ;		
0915   1E3B             ;       PRINT 1 HEX BYTE AS 2 ASCII CHAR'S
0916   1E3B             ;   
0917   1E3B 85 FC       PRTBYT  STA   TEMP                             
0918   1E3D 4A                  LSR   A           ; SHIFT CHAR RIGHT 4 BITS
0919   1E3E 4A                  LSR   A
0920   1E3F 4A                  LSR   A
0921   1E40 4A                  LSR   A
0922   1E41 20 4C 1E            JSR   HEXTA       ; CONVERT TO HEX AND PRINT
0923   1E44 A5 FC               LDA   TEMP        ; GET OTHER HALF
0924   1E46 20 4C 1E            JSR   HEXTA       ; CONVERT TO HEX AND PRINT
0925   1E49 A5 FC               LDA   TEMP        ; RESTORE BYTE IN A AND RETURN
0926   1E4B 60                  RTS   
0927   1E4C             ;
0928   1E4C 29 0F       HEXTA   AND   #$0F        ; MASK HI 4 BITS
0929   1E4E C9 0A               CMP   #$0A
0930   1E50 18                  CLC   
0931   1E51 30 02               BMI   HEXTA1
0932   1E53 69 07               ADC   #$07        ; ALPHA HEX
0933   1E55 69 30       HEXTA1  ADC   #$30        ; DEC HEX
0934   1E57 4C A0 1E            JMP   OUTCH       ; PRINT CHAR

What is happening here?

  • The byte in A is saved (917)
  • the high nibble is shifted to the lower nibble (918-921)
  • the nibble is converted to hex (922, calls hexta)
  • the byte is restored and the low nibble converted to hex
  • A is restored
    • hexta masks off low nibble (928)
    • convert A..F to ascii (929-932)
    • convert hex to ascii and print(933-934)

    GETBYT and PACK

    1148   1F9D             ;		
    1149   1F9D             ;       GET 2 HEX CHAR'S AND PACK 
    1150   1F9D             ;       INTO INL AND INH
    1151   1F9D             ;       X PRESERVED Y RETURNED = 0
    1152   1F9D             ;       NON-HEX WILL BE LOADED AS NEAREST HEX EQU
    1153   1F9D             ;
    1154   1F9D 20 5A 1E    GETBYT  JSR   GETCH
    1155   1FA0 20 AC 1F            JSR   PACK
    1156   1FA3 20 5A 1E            JSR   GETCH
    1157   1FA6 20 AC 1F            JSR   PACK
    1158   1FA9 A5 F8               LDA   INL
    1159   1FAB 60                  RTS
    1160   1FAC             ;		
    1161   1FAC             ;       SHIFT CHAR IN A INTO
    1162   1FAC             ;       INL AND INH 
    1163   1FAC             ;
    1164   1FAC C9 30       PACK    CMP   #$30       ; CHECK FOR HEX 
    1165   1FAE 30 1B               BMI   UPDAT2
    1166   1FB0 C9 47               CMP   #$47       ; NOT HEX EXIT
    1167   1FB2 10 17               BPL   UPDAT2
    1168   1FB4 C9 40               CMP   #$40       ; CONVERT TO HEX
    1169   1FB6 30 03               BMI   UPDATE
    1170   1FB8 18                  CLC   
    1171   1FB9 69 09               ADC   #$09
    1172   1FBB 2A          UPDATE  ROL   A
    1173   1FBC 2A                  ROL   A
    1174   1FBD 2A                  ROL   A
    1175   1FBE 2A                  ROL   A
    1176   1FBF A0 04               LDY   #$04       ; SHIFT INTO I/O BUFFER
    1177   1FC1 2A          UPDAT1  ROL   A
    1178   1FC2 26 F8               ROL   INL
    1179   1FC4 26 F9               ROL   INH
    1180   1FC6 88                  DEY   
    1181   1FC7 D0 F8               BNE   UPDAT1
    1182   1FC9 A9 00               LDA   #$00       ; A=0 IF HEX NUM
    1183   1FCB 60          UPDAT2  RTS
    

    What is happening here?

    GETBYT
    The GETBYT routine is used in the TTY part of the KIM-1 monitor to enter two hex characters (0..9 and A..F) and pack it into one byte.

    • read the first character (1154)
    • pack it into INL lower nibble (1155)
    • read the second character (1156)
    • pack it into INL, shifting the lower nibble to high and shifting in the second nibble (1157)
    • return byte from INL to A

    PACK

    • check if < '0' and error out with A > 0 (1164-1165)
    • check if > ‘F’ and error out with A > 0 (1166-1167)
    • if A..F add $09 (1168-1171)
    • shift in nibble via INH and INL
    • return zero if valid hex but with invalid Z flag

    Note that the range between ‘9’ and ‘A’ is not checked, so those are taken as valid hex characters.
    The PACK routine accepts ‘:’– ‘?’, $3A .. $3F as valid hex characters A ..F.

    KIM
    0200 A9 ;;
    00BB 00 ::
    00AA 00 ????
    FFFF 1C
    

    The ASCII encoding is arranged so that adding 9 to ‘A’–’F’ aligns them perfectly with the desired hexadecimal nibble after four left rotates. This avoids a separate subtraction of ‘A’ and addition of 10.

    The following demo with PRTBYT and GETBYT illustrates how this could be done in a user program.

    0001   0000             ;
    0002   0000             ; GETBYTC with error checking
    0003   0000             ; illustrates shortcomings in PACK
    0004   0000             ; - G and ; and possibly more accepted without error
    0005   0000             ;
    0006   0000             ;
    0007   0000             ; KIM
    0008   0000             ; 0000 00 200
    0009   0000             ; 0200 A9 G
    0010   0000             ; >12=12
    0011   0000             ; >33=33
    0012   0000             ; >H?
    0013   0000             ; >G?
    0014   0000             ; >::=AA
    0015   0000             ; >;;=BB
    0016   0000             ; >AB=AB
    0017   0000             ; >CD=CD
    0018   0000             ; >EE=EE
    0019   0000             ; >
    0020   0000             
    0021   0000             ; KIM-1 defines
    0022   0000             ;
    0023   0000             PACK 	= 	$1FAC		; pack hex character into INL, shift in
    0024   0000             PRTBYT	= 	$1E3B		; print byte as 2 hex characters
    0025   0000             GETCH	=	$1E5A		; receive character from TTY serial
    0026   0000             OUTCH	= 	$1EA0		; send character via TTY serial
    0027   0000             INL		= 	$F8	
    0028   0000             INH		= 	$F9
    0029   0000             ;
    0030   0200             	.org $0200
    0031   0200             
    0032   0200             ; demo code
    0033   0200             ;
    0034   0200 A9 00       LOOP 	LDA	#$00
    0035   0202 85 F8       		STA INL			; zero hex byte
    0036   0204 85 F9       		STA	INH
    0037   0206 20 42 02    		JSR CRLF
    0038   0209 A9 3E       		LDA #'>'		; prompt
    0039   020B 20 A0 1E    		JSR OUTCH
    0040   020E 20 28 02    		JSR GETBYTC
    0041   0211 90 08       		BCC	OK 
    0042   0213 A9 3F       		LDA #'?'		; error
    0043   0215 20 A0 1E    		JSR OUTCH
    0044   0218 4C 00 02    		JMP LOOP
    0045   021B             ;		
    0046   021B 48          OK		PHA
    0047   021C A9 3D       		LDA	#'='
    0048   021E 20 A0 1E    		JSR OUTCH
    0049   0221 68          		PLA
    0050   0222 20 3B 1E    		JSR PRTBYT
    0051   0225 4C 00 02    		JMP LOOP		; repeat	
    0052   0228             ;
    0053   0228             ; subroutine GETBYTC
    0054   0228             ; read 2 hex characters from TTY input
    0055   0228             ; pack into one byte
    0056   0228             ; Returns: carry clear if hex OK, A == hex byte
    0057   0228             ; clobbers X and Y
    0058   0228             ;
    0059   0228             
    0060   0228             
    0061   0228 20 5A 1E    GETBYTC	JSR	GETCH		; read character
    0062   022B 20 AC 1F    		JSR	PACK		; pack into INL
    0063   022E C9 00       		CMP #$00		; restore z flag
    0064   0230 D0 0E       		BNE EGETB		; A = 0 if hex number
    0065   0232 20 5A 1E    		JSR	GETCH		; read second character
    0066   0235 20 AC 1F    		JSR	PACK		; pack into INL
    0067   0238 C9 00       		CMP #$00		; restore z flag
    0068   023A D0 04       		BNE EGETB		; A = 0 if hex number
    0069   023C A5 F8       		LDA	INL
    0070   023E 18          		CLC
    0071   023F 60          		RTS
    0072   0240 38          EGETB	SEC
    0073   0241 60          		RTS
    0074   0242             		
    0075   0242 A9 0D       CRLF	LDA 	#$0D
    0076   0244 20 A0 1E    		JSR 	OUTCH
    0077   0247 A9 0A       		LDA 	#$0A
    0078   0249 20 A0 1E    		JSR		OUTCH 
    0079   024C 60          		RTS
    0080   024D             
    0081   024D             		.END
    0082   024D             		
    0083   024D             
    tasm: Number of errors = 0
    

Programming tips

Some tips that I learned programming for the KIM-1 and the 6502.

ALWAYS CHECK YOU DO NOT FORGET IMMEDIATE ACCESS SYNTAX!
It so easy an common to forget the ‘#’ in your assembler code. Assemblers will not complain and make it absolute or zeropage addressing and you will search for hours!

TTY routines

Do not use the CRLF routine at $1E2F in the monitor

This routine sends the CR and LF to the TTY output vai OUTCH. Nice, you will need that often in a console program.
But if you read the page on printing a string you see this routine also sends out 6 Null ($00) characters, this takes a lot of wasted time!

Just make your own subroutine

LDA #$0D   ; CR
JSR OUTCH
LDA #$0A   ; LF
JSR OUTCH
RTS

Note that this destroys A and Y!

GETCH gets a character to serial TTY.
Blocking, it waits indefinitely for a character to arrive and A will have the value.
The routine also kills the Y register, returns with Y = $FF.
Also, in LED Display and Keyboard mode, it returns with A = $01 and X = 8.
Save Y before calling GETCH, and restore Y when it returns.

OUTCH sends a character to serial TTY
No handshaking, no hardware flow control, it just spits out the character.
A destroyed, Y=FF, X preserved.
Save at least Y, and saving A is recommended.

SPACE print a blank

This just calls OUTCH with A = $20, so read OUTCH for the side effects.

PRTBYT Print A as two hex characters

Uses OUTCH, so Y is lost. A is preserved.

GETBYT and GETBYTC

X saved, Y = 0, A is hex character
Reads two hex characters (0..9 A..F) and tries to pack them in A.
See the page on PRTBYT,GETBYT and PACK for an error checking alternative GETBYTC to GETBYT.
Note that due to an incomplete check ‘:’– ‘?’, $3A .. $3F are accepted as valid hex characters A ..F.

KIM
0200 A9 ;;
00BB 00 ::
00AA 00 ????
FFFF 1C

The audio tape routines

The DUMPT and LOADT routines are OK to call interactively to dump and load KIM-1 files on tape.
The cannot be called as subroutines. when finished they return to the KIM-1 monitor.
DUMPT return with $0000 as current address pointer in the KIM-1 monitor.
LOADT returns it status via the current address pointer in the KIM-1 monitor, $0000 is success, $FFFF is a loading error.

What you can do is:
– Have code at $0000 to return to your program (Warm start entry), so the user just has to press G
– instruct the user what to do if DUMPT returns $FFFF

The better solution is to incorporate Hypertape as callable subroutine.

Return to the KIM-1 monitor

The preferred location to call to enter the KIM-1 monitor form a user program is START at $1C4F

Reading the keyboard and lighting the display

Fill F9, FA, FB with the values to show on the LED displays
Call SCAND
Call SCAND to debounce
CaLl GETKEY
Now check the key in A:
– above $14 : no key
– 14 = PC
– 13 = GO
– 12 = +
– 11 = DA
– 10 = AD
– 0 ..9 A – F keys
Handle key and loop back to the begin

TTY operation summary

KIM-1 TTY command summary

– Connect the application connector with a TTY switch
– Serial port in your terminal emulator settings 9600 bps (or less, 4800 or 2400 work best), 8N1
– Add character and line delay in your terminal emulator, see the TTY problems page
– Press Enter (or any key with odd ASCII value after Reset to initialize serial bit rate.

After startup give the NMI and IRQ/BRK vector a known value

NMI Initialization for Single Step and Stop
17FA 00
17FB 1C

IRQ Initialization for BRK
17FE 00
17FF 1C

Make sure you are not in decimal mode:
00F1 00

Machine Context saved/restored by ST/GO
00EF PC low
00F0 PC high
00F1 Status Register (flags)
00F2 Stack Pointer
00F3 A
00F4 Y
00F5 X

Breakpoints
– Write BRK instruction ($00) at desired address, program will be stopped here.
– ST button: Pressing will invoke NMI interrupt.
– Single Step: Set SST switch to on, type G to step one instruction from current location.

Cassette Load and Save

12 Volt power source is only required when reading tapes

Save to tape
– Store $00 in $00F1 (to ensure CPU is in binary mode).
– Save start address (low/high) in $17F5, $17F6.
– Save end address+1 (low/high) in $17F7, $17F8.
– Write tape ID ($01-$FE) in $17F9.
– Start tape in record mode.
– Run address $1800 (DUMPT) to save.

Load from tape
– Store $00 in $00F1 (to ensure CPU is in binary mode).
– Write tape ID ($01-$FE, $00 loads any ID, $FF loads using start address values (low/high) in $17F5, $17F6) to $17F9.
– Run address $1873 (LOADT) to load.
– success of load: current address is 0000, error is FFFF

TTY commands

<hex address>         Show data at current address 
                      (hex characters shifted in to the left) 
<hex data&>.          Write to current address 
<Return>              Next address 
<Line Feed>           Move to previous address  (CTRL/J)
L                     Load program from paper (error if ERR KIM is displayed)
Q                     Save memory to paper tape, saves from current address 
                      to end address stored at $17F7 (low), $17F8 (high) 
G                     Start program at current address 
                      (note: set F1 00 if not in SST mode) 
RUB OUT               restart the KIM-1 monitor

Note that pressing RUB OUT in current terminal emulators is not a standard key. I have done it with some customization in Teraterm for Windows.
In the KIM-1 Simulator the RUBOUT is patched to CTRL-G.