Rev L Interrupt Handler


Introduction

[rev l CPU]

[rev L front panel]

Page last updated Aug 13 2022.This Web page provides Jack Noble's interrupt handler and examples for the 1802 Membership Card Rev L front-panel. See the linked Web page for the Rev L support page on this Web domain. That page includes the manual and descriptions and schematics for the display hardware and the 1802 Membership Card CPU. - Herb Johnson

For documentation on the 1802 interrupts, I’m afraid you’ll have to go directly to the RCA 1802 manuals. Few 1802 programs use the interrupt and they don’t explain how they work. The original document is in RCA's COSMAC User's Manual MPM-201B, as I’ve exerpted on this linked page. That document refers to “RCABUG”, an old 1802 monitor, described on this linked Web page. - Herb Johnson

Jack Noble provides interrupt code

In mid-July 2022, Jack Noble built the Rev L 1802 Membership card, and produced an interrupt handler and examples for use with the 6-digit 7-segment display. These notes and the code of the examples, were published by Jack on the cosmacelf groups.io email list; in the thread "New Rev. L 1802MC front panel built"). Jack was assisted by Lee Hart and Chuck Yakym, I've been told.

The Rev L digit display is scanned by a hardware clock which enables each digit and also produces a pulse for each digit-time, and a pulse for the first (last?) digit. The digit-time pulse is an interrupt, and the first/last digit pulses the EF2 line. A ROM decodes the outputs of OUT 4, into bits that drive each LED segment (and decimal point). As the hardware clock enables each LED digit, whatever software puts out on OUT 4 is decoded by the ROM, and drives that digit's segments. Without software, the display can be set to show OUT 4 content as two hex digits.

In practice, the resistor/capacitor timing on the hardware clock needed adjustment, as did the width of the interrupt pulse. Lee Hart in private correspondence described those changes, as below. Following his description, I show Jac Noble's code examples. Jack's code did not have comments. I incorporated his posted comments plus my code interpretations, as coding comments. Please contact me if any code or comments are in error. - Regards, Herb Johnson

From Lee Hart, mid-Aug 2022:

You may have noticed the animated GIF on my 1802 Membership Card Web page. It's running Jack Noble's scrolling message program. :-) To make it work, I changed R17 from 3.3k to 1.5k, and changed Q4 and Q6 from FJN335 back to FJN3303.

The original values worked to provide a ~80 usec /INT low pulse. Jack's and Chuck Yakym's interrupt handlers were faster than that, so they had to "pad out" the interrupt handler so /INT had gone back high by the time the interrupt handler returned.

I reduced R17 to shorten the /INT low time to 40 usec. But the 4071 OR gate U9B didn't have enough drive for the 1.5k + 4.7k + 4.7k base resistors in the two transistors. The OR gate output wasn't going high enough to cleanly disable the EPROM /CE pin, so there was "ghosting" in the LEDs as it stepped to the next digit.

So, I went back to the FJN3303 (used on earlier revs) because it has 22k base resistors. That reduced the load on the OR gate, so everything works nicely again. :-)

Jack Noble's codes

In the programs below, the INCL "1802reg.asm" establishes R0 as 0, R1 as 1, etc to designate the registers. Syntax for the A18 1802 cross assembler is assumed but it's a common 1802 syntax. For A18 you’ll have to replace the "LOAD” pseudoop with conventional 1802 MOV instructions as below. - Herb

         LOAD Rx, VALUE

         LDI low VALUE
         PLO Rx
         LDI high VALUE
         PHI Rx

The Jack Noble interrupt handler

; Interrupt Service Routine by Jack Noble July 19 2022 
; for 1802 Membership Card Rev L six-digit display
; commentary by Jack Noble, some edits by Herb Johnson
;
; To set up the ISR, in your program source define INTBUF and INTPTR 
; to be one each of registers R3-RF (doesn't matter). 
; Then disable interrupts, set R1 to point to the ISR (label "INT").
; Set R2 to point to some stack space. 
; Then set register INTBUF to point to 6 bytes of a default message in memory.
; The value in INTPTR does not need to be initialized. 
; Then re-enable interrupts, and you're good to go!
;
; R1, R2 and INTPTR must be preserved by all running programs.
; On interrupt, R1 is automatically the PC, and X is set to R2 automatically.
;
; In use: INTBUF is set to point to wherever in memory
; contains the 6-byte message to be displayed. 
; 
; INTPTR is used by the ISR to keep track of where it is in the message during display
; (So don't touch that register).
;
; issues:
;
; For the first refresh cycle after starting the ISR, the display will show garbage.  
; This is because INTPTR has not yet been set to point to the message pointed to by INTBUF. 
; But it's not really an issue as it just causes a small flicker on power-up.  
; If this is unacceptable, set INTPTR to the same address as INTBUF 
; and test/wait until EF2 goes high (logic zero) before enabling the interrupt.

        INCL "1802reg.asm"
        ;ORG ?????		;of course, handler must be in memory somewhere!

INTRET: RET			;usual 1802 return route, sets current PC=R1 to next instruction
					;meanwhile old X and P are restored as saved below
					; and you return to your running program

INT:    SEX R2			;.... which is the interrupt entry point
        DEC R2
        SAV			;save T state (old X and P) for RET to restore  
        DEC R2
        STXD

        LDN INTPTR
        STR R2			;set up RX=R2 to point to char to display
        OUT 4			;and OUT sends char to display latch

        NOP			;hang loose for some CPU clock time you have to determine...
        NOP			; past the length of the interrupt signal
        NOP			; to avoid double interrupts
        NOP
        NOP
        NOP

        INC INTPTR		;point to next char to display

        B2  NODSP6		;monitor EF2 for display reset timer (first char timer)
					;if not ready don't reset display pointer
        GHI INTBUF		;if ready then reset INTPTR to start of message
        PHI INTPTR
        GLO INTBUF
        PLO INTPTR

NODSP6: LDXA			;(not sure what this does....)
        BR INTRET		; setting up the return from interrupt

        ;END			;no end needed if embedded in user codes

Interrupt hander and example display programs

Jack Noble "hello" program

; simple program to establish and initialize interupt handler
; and display an initial message - and loop otherwise. 
; code and commentary by Jack Noble, some edits by Herb Johnson
; For this program to run, the interrupt handler MUST be in memory. 

        INCL "1802reg.asm"

INTBUF  EQU RF			;points to 6 byte message
INTPTR  EQU RE			;used by INT to scan message


        ORG $0000		;on reset 1802 goes to 0000H

        SEX R0			;may not be necessary on reset entry
        DIS			;but must disable interrupts until established
        DB $00			;also necessary after DIS

        LOAD R1, INT		;must set R1 ONCE for handler entry address
					;"INT" is the address of the interrupt handler!
        LOAD R2, $017F	;R2 is stack space set ONCE, this is application-specific
					;your stack address will be different!
        LOAD RF, MESG		;INTBUF set to initial/default message
					;INTPTR is in use by handler to scan message

        RET			;force interrupt enable
        DB $20			;this is necessary after RET
 
;running user programs *cannot modify* R1, R2, INTBUF, INTPTR

LOCK:   BR LOCK			;just a place to run between interrupts

MESG:   DB "HELLO!"		;initial six-byte ASCII message
 
        END

Jack Noble "banner" program

; program to initialize interrupt handler
; and display a message in "banner" or scrolling mode
; code and commentary by Jack Noble, some edits by Herb Johnson

        INCL "1802reg.asm"

INTBUF  EQU RF			;points to 6 byte message
INTPTR  EQU RE			;used by INT to scan message


        ORG $0000

        SEX R0			;may not be necessary on reset entry
        DIS			;must disable interrupts until established
        DB $00			;this is also necessary 

        LOAD R1, INT		;must set R1 ONCE for handler entry
        LOAD R2, $3FFF 	;R2 is stack space set ONCE this is use-specific
        LOAD RF, BANNER	;INTBUF set to start of banner message
					;INTPTR is in use by handler to scan message 

        RET			;force interrupt enable
        DB $20			;this is also necessary

;registers R1, R2, INTBUF and INTPTR *must* be preserved in user's programs


        LOAD R4, BANNERLEN	;length of banner message, less six bytes
					;remember, 6-character display

LOOP:
        LDI $40			;some delay time, using R3
        PHI R3			;put in high byte, clock low byte

DELAY:				;give time for human to read display before scroll
        DEC R3			;decr low byte 256 times to dec high byte
        GHI R3
        BNZ DELAY		;delay depends on CPU speed

        INC RF			;advance INTBUF to scroll to left
        				;int handler displays 6 chars following
        DEC R4
        GLO R4
        BNZ LOOP		;countdown with R4

        LOAD RF, BANNER
        LOAD R4, BANNERLEN

        BR LOOP

;note, for the above program, it doesn't know about the start or 
;the end of the message, so it must be padded with 6 spaces each end

BANNER: DB "      1802  MEMbErshIp  CArd            "
BANNEREND:

BANNERLEN EQU BANNEREND - BANNER - 6
 
        END

This page and edited content is copyright Herb Johnson (c) 2022, except for content provided by Lee Hart or Jack Noble. Contact Herb at www.retrotechnology.com, an email address is available on that page..