IMD 1.12: 12/12/2009 12:39:52 MDKEY605.ASM XASM48.COM MD-3 Format 1!"̀)À>A Not a SYSTEM Diskette (01!"̀)À>A Not a SYSTEM Diskette (0MDKEY605ASM MDKEY605ASMc !XASM48 COM^"#$%&' ; ; ROM REVISION - The value defined in the ; equate ROM.REV will be returned as the ; NMI status in the initial fetch which ; is used to enable NMIs. ; ; ARROW KEYS - Select shifted function on ; RS only. Release RS and/or NUM LOCK ; before sending scan code and remake ; after. On a key break, send the make ; code with the break bit set independent ; of the current state of RS. Do not ; interrupt RS or NUM LOCK on the break ; code. Also used for INSERT/DELETE. ; ; ARROW KEYS - Revised to send NUM LOCK ; make/break pulse before and after key ; code if required. ; ; BREAK NUM LOCK FOR + AND - ; ; Create two bytes of ram by chopping ; off the start of the FIFO. ; ; Extend MACROES by above two bytes. Adjust ; lengths of MACROES and FIFO everywhere. ; ; Write new key type MATH sharing parts ; of arrow to implement macroes. ; ; Add cursor NMI disable based on cursor style. ; No cursor on BP = 01, R10 > 7 or R10 > R11. ; between macro characters. ; ; .HF 7/29 Keep BLINK bit active, even if blink is disabled. ; ; .DB 8/1 Changed RSTAT to feed back all 4 possible combinations ; of Display Enable and Sync. The pattern cycles every ; four reads. ; ; .DB 8/5 Added seperate power fail interrupt for LoBat1 if on ; AC. Changed keys (Row.Col) 6.6, 8.6, and 9.7 to be ; conditional on NumLock State. ; ; .DB 8/6 Added the SCROLL/NUM LOCK key to the macro handler. ; ; .JZ 8/7 Changed Rom.Rev from 2 to 3 ; ;============================================================================== ; Release 6.05 (NOT RELEASED) ;======================== ; ; .HF 11/12 Keyboard scan changed to read the value of FDC-ON ; before each row, to reduce the chances of the 80C39 ; turning off the FDC when it shouldn't. ; ; .DB 12/26 Changed structure of how HSYNC and DISPENBL are ; handled. ; ; .HF 1/15 Improved Blink and E.L. Timeout bit processing, and ; fixed bug where ints.were not disabled long enough. ; ; . TITLE "MORROW DESIGNS PIVOT - KEYBOARD PROCESSOR FIRMWARE" SBTTL "REVISION 8/8/85 1:00 PM 6.04" WIDTH 96 ;************************************************ ;* * ;* Morrow Designs Pivot * ;* Keyboard Processor Firmware * ;* * ;* Author: Michael Stolowitz * ;* Revision: 6.05 * ;* Date: 1/03/86 * ;* Time: 17:00 * ;* * ;************************************************ ; ; Revision History: ;============================================================================== ; Release 6.00 (14_Jul_85) ;========================= ; 6/14 ROM DISK - To read the disk, request an NMI ; with an ofset of 20H added to the sector ; number. Once the NMI has been returned, ; data bytes may be fetched from the MODE ; register. The address will auto-increment. ; This function may be aborted after any ; number of bytes have been transferred by ; acknowledging the NMI. ; ; ALT ICON FUNCTIONS - Added new NMI codes ; for ALT versions of Icon Keys. ;============================================================================== ; Release 6.02 (7_Jul_85) ;======================== ; 7/5 SETEL routine added, which sets both bytes of ; the EL time out counter to the initial values. ; The initial values are dependent upon AC-ON. ; All places that used to set this counter now ; use this routine. ; ; Incorrect mask values in the cursor on - off ; routines were corrected. ; ; Changes were made in the SENDSCAN and SCANCODE ; routines to swallow the first typed character ; when the EL is off. ; ; The EL time out counters were changed to count ; in 1/2 minute incrememnts. ; ;============================================================================== ; Release 6.04 (8_Aug_85) ;======================== ; 7/17 Added register 27 to accept a keyboard ; state from the host processor. Revised ; internal state byte to correspond to bit ; structure of system keyboard state byte. ; ; 7/24 Added 1 frame time delay HF 1/20 Suppress repeat of NUMLOCK. ; ;************************************************ ;* * ;* Program Structure: * ;* * ;* COLD Code Executed On Reset * ;* MAIN Main Loop ( See MAIN: ) * ;* STALL Interrupt ( See STALL: ) * ;* TIMER Interrupt ( See TIMER: ) * ;* * ;************************************************ ; ;************************************************ ;* * ;* Other References: * ;* * ;* KBHRD.DOC Hardware Description * ;* KB.DOC Functional Description * ;* KBSCAN.DOC Keyboard Description * ;* * ;************************************************ ; ; BANK 0 REGISTER UTILIZATION ; ; KB RED DELTA CODE SEND ; -------------------------------------------------------------- ; R0 ; R1 KEY-ARRAY KEY-ARRAY KEY-ARRAY KEY-ARRAY ; R2 ROW CNT ROW CNT ROW CNT ROW-CNT ; R3 DELTA DELTA ; R4 ROTATE ROTATE ; R5 PWR-STAT PWR-STAT PWR-STAT PWR-STAT ; R6 BIT-CNT BIT-CNT ; R7 KEYSTATE KEYSTATE KEYSTATE KEYSTATE ; ; BANK 1 Data Enable AUX.ENA EQU 02H ;Extra Port Enable PA.ENA EQU 03H ;Processor Address Enable ; ; ROM.REV EQU 03H ;INITIAL NMI STATUS ; DSP.DFLT EQU 0C4H ;DEFAULT DISPLAY CONTROL ; ; RAM BASED DATA STRUCTURES ; ; CRT.REG : Array[0..17] Of 6845 Registers Absolute 20H ; CRT.REG: EQU 20H ;START OF 6845 REGISTERS ; ; Single Byte Variables: ; ELTIME0: EQU 32H ;EL PANEL TIMEOUT LSB ELTIME1: EQU 33H ;EL PANLE TIMEOUT MSB NMIREQ: EQU 34H ;NMI REQUEST PAGE: EQU 35H ;ROM DISK SECTOR REGISTER SAVE1: EQU 36H ;OP SYS ADDR SAVE SAVE2: EQU 37H ;NMI ADDR SAVE BLINK: EQU 38H ;BLINK COUNTER BOUNCE: EQU 39H ;DEBOUNCE VARIABLE REPEAT: EQU 3AH ;REPEAT REGISTER SWBRK: EQU 3BH ;BREAK TO SWALLOW DLYCNT: EQU 3CH ;COUNTER FOR WHEN TO CHANGE DISP. STATUS ;---------------------------------------------------------- ; KARRAY : Array[Row1..Row12] of [NewData,OldData] ; KARRAY: EQU 3DH ;KB DATA ARRAY ;---------------------------------------------------------- ; MACROES : Array[1..8] COUNTER FOR WHEN TO CHANGE DISPEN AND VSYNC DISPDLY: EQU 5H ;NMI STATUS CODES LOBAT1$: EQU 2 ;LO BATT 1 CURSOR$: EQU 4 ;CURSOR UPDATED LOBAT2$: EQU 6 ;LO BATT 2 CHANGED IACALC$: EQU 8 ;ALT-CALC ICON ICLOCK$: EQU 10 ;CLOCK ICON IPHONE$: EQU 12 ;PHONE ICON IDISK$: EQU 14 ;DISK ICON ICALC$: EQU 16 ;CALC ICON ACCHG$: EQU 18 ;AC CHANGED ; IACLOCK$: EQU 22 ;ALT-CLOCK ICON IAPHONE$: EQU 24 ;ALT-PHONE ICON IADISK$: EQU 26 ;ALT-DISK ICON CUROFF$: EQU 28 ;CURSOR OFF BADAC$ EQU 30 ;LOBAT1 ON AC ROM.ORG: EQU 00H ;FOR SIMULATION ORG ROM.ORG ;RESET ADDRESS ; ; RESET - The 80C39 vectors here following a reset. ; RESET: JMP COLD ;RESET ENTRY NOP JMP STALL ;INT INTERRUPT NOP NOP JMP TIMER ;TIMER INTERRUPT ; ; COLD - Code executed one time at reset. ; COLD: ;STROBES OFF MOV A,#KBDAV.N ;ALL STROBES OFF OUTL P2,A ;TO STROBE PORT ;INITIALIZE DISPLAY SEL RB1 ;BANK 1 REGISTERS MOV A,#DSP.DFLT ;DEFAULT DISP CTL MOV R0,#DS.STB ;SET NDX REGISTER UTILIZATION ; ; R0 WORKING INDEX REGISTER ; R1 6845 ADDRESS REGISTER ; R2 FIFO INPUT POINTER ; R3 FIFO OUTPUT POINTER ; R4 NMI STATUS ; R5 DISPLAY STATUS ; Bit 0 Display Enable ; Bit 1 FDC-OFF ; Bit 2 EL Timeout Inhibit ; Bit 3 Vertical Sync ; Bit 4 Drive Off 0 ; Bit 5 Drive Off 1 ; Bit 6 Attribute Enable Static ; Bit 7 Curser Updated ; R6 SAVED ACCUMULATOR ; R7 DISP CTL SHADOW ; ; F0 NO CURSOR UPDATE ; F1 NOT END-FRAME ; ; PORT 1 KEYBOARD SCAN CODES TO 8255 ; PORT 2 STROBE OUTPUT PORT ; ; ; PORT 2 BIT ASSIGNMENTS ; KBDAV.N: EQU 10000000B ;SET DAV LATCH PACK.P: EQU 01000000B ;PROCESSOR ACKNOWLEDGE NMIRQ.P: EQU 00100000B ;ASSERT PROCESSOR NMI ATENA.P: EQU 00010000B ;ATTRIBUTE ENABLE ; ; DATA BUS 8084 LOCAL BUS FACILITIES ; KB.STB EQU 00H ;Key Board Strobe PD.STB EQU 01H ;Processor Data Strobe FDC.STB EQU 02H ;Floppy Disk Enable DS.STB EQU 03H ;Display Strobe KB.ENA EQU 00H ;Key Board Enable PD.ENA EQU 01H ;ProcessorOf MACRO ; MACRO : Record ; Control, ScanCode : Byte ; CONTROL { By Precidence } ; B6 Send NMLK Make ; B5 Send NMLK Break ; B1 Send RS Break ; B2 Send Data ; B0 Send RS Make ; B4 Send NMLK Make ; B3 Send NMLK Break ; NUMMACRO EQU 8 ;NUMBER OF MACROES MACROES EQU 55H ;FIRST MACRO ;---------------------------------------------------------- ; FIFO : Array[0..30] Of ScanCode Absolute 62H ; ; E1 is used so that overflow will set CRY ; FIFO: EQU 0E5H ;FIFO - 1CH BYTES TO END RAM ; ;BUF.LEN: EQU 1BH ;FIFO LENGTH ; ;CUR.REG EQU 0EH ;CURSOR REGISTER PAIR ;DISPLAY BLINK CONSTANTS K.BLINK: EQU 37 ;75/74 CYCLES PER SECOND BLINK.B: EQU 20H ;BLINK BIT OF DISP CTL ;DISPLAY EL PANEL TIMEOUT CONSTANTS EL.K0 EQU -60 ;60 BLINK PERIODS = 1/2 MIN EL.K10 EQU -20 ;10 MINUTES EL.K1 EQU -3 ;1.5 MINUTE EL.B EQU 04H ;EL ENABLE BIT OF DISP CTL ;DEBOUNCE CONSTANTS KBDB.S: EQU 2H ;SHORT - 2 FRAME TIMES KBDB.L: EQU 8H ;LONG - 8 FRAME TIMES ; DISPLAY STATUS  TO DISP MOVX @R0,A ;AND SET THE PORT MOV R7,A ;COPY TO SHADOW REG ; SEL RB0 ;BANK 0 REGISTERS ; ; ; ;INITIALIZE KEYBOARD DATA ARRAY MOV R0,#KARRAY ;SET NDX TO ARRAY MOV R1,#24 ;LENGTH OF ARRAY CLR A ;KEYS OPEN COLD1: MOV @R0,A ;CLEAR BYTE INC R0 ;BUMP INDEX DJNZ R1,COLD1 ;DCR CNT UNTIL ZERO ;INITIALIZE BANK 0 REGISTERS MOV R0,A ;WORKING MOV R1,A ;KEY ARRAY POINTER MOV R2,A ;ROW CNT MOV R3,A ;DELTA DATA MOV R4,A ;ROTATED DATA MOV R5,A ;PWR-STATUS MOV R6,A ;BIT COUNT MOV R7,A ;KB STATE ;INITIALIZE BLINK MOV R0,#BLINK ;SET NDX TO CNTR MOV @R0,#K.BLINK ;AND LOAD INIT VALUE ;INITIALIZE EL PANEL TIMEOUT CALL SETEL ;INITIALIZE DELAY VALUE FOR DISPLAY STATUS CHANGES MOV R0,#DLYCNT MOV @R0,#DISPDLY ; ;INITIALIZE NMI REQUEST MOV R0,#NMIREQ ;SET NDX TO REGISTER MOV @R0,#0 ;AND CLEAR REQUEST ;INITIALIZE SWALLOW BREAK MOV R0,#SWBRK ;SET NDX TO REGISTER MOV @R0,#0 ;AND CLEAR ;INITIALIZE BANK 1 REGISTERS CALL KBan keyboard ; Skip if in debounce FRAME3 ; If FIFO is not full FRAME35 ; If MACRO is active ; Send Next Macro Code ; Else ; Read keyboard FRAME4 ; Process Changes ; 5. Auto Repeat ; ; MAIN: JF1 SENDOUT ;SKIP IF NOT END FRAME CPL F1 ;CLR END FRAME FLAG JMP FRAME1 ;EXECUTE END FRAME CODE ; ; SEND OUT - If the 8255 is not already busy, and if the FIFO ; is not empty, the next scan code in the buffer is sent to ; the 8255, the keyboard data available latch is set, and the ; output pointer is advanced. If the end of the FIFO is reached, ; the address is wraped forming a ring buffer. If either the ; FIFO is empty, or the 8255 is busy, this routine simply returns. ; ; Bank 1 Register Usage: ; R2 = FIFO Input Pointer ; R3 = FIFO Output Pointer - Updated ; Bank 0 Register Usage: ; R0 = Data is lost ; SENDOUT: JT0 DRVOFF ;IF 8255 BUSY SEL RB1 ;BANK 1 REGISTERS MOV A,R3 ;FETCH FIFRVOFF0: MOVX @R0,A ;PULSE NEW FDC STATE ;PROCESS DRIVE OFF 0 XCH A,R0 ;SWAP FOR ADDR ADD A,#34H ;OFFSET TO ROW 13 XCH A,R0 ;SWAP BACK JB4 DRVOFF1 ;SKIP IF NOT DRV 0 MOVX @R0,A ;PULSE DRV OFF 0 ;PROCESS DRIVE OFF 1 DRVOFF1: XCH A,R0 ;SWAP WITH ADDR ADD A,#4 ;OFFSET TO ROW 14 XCH A,R0 ;SWAP BACK JB5 PWRFAIL ;SKIP IF NOT DRV 1 MOVX @R0,A ;PULSE DRV OFF 1 ; ; POWER FAIL - Test the extra port for Low Batt 1. ; If true, send an NMI 2 and once acknowledged, ; hang forever. Save the new power status. If AC-ON ; has just set, send an NMI 18. ; PWRFAIL: SEL RB0 ;BANK 0 REGISTERS MOV R0,#AUX.ENA ;SET NDX TO EXTRA PORT MOVX A,@R0 ;READ IN THE PORT JB2 PWRFAIL1 ;SKIP IF LOW BATT 1 XCH A,R5 ;NEW VALUES TO PWR STAT ;CHECK FOR AC-ON RISING JB0 NMIRQ ;SKIP IF AC WAS ON MOV A,R5 ;RECALL NEW STATE JB0 PWRFAIL3 ;AC-ON NOW SET JMP NMIRQ ;ELSE DONE ;LO BATT 1 PWRFAIL1: JB0 PWRFAIL2 ;IF ON AC, THEN LOAD AC BAD CODE MOV A,#LOBAT1$ ;LOAD BATTERINIT ;INITIALIZE THE KB (SELECTS BANK 1) ;INITIALIZE NMI STATUS MOV R4,#80H ;SET NMI STATUS ;OTHER BANK 1 REGISTERS CLR A ;ZERO MOV R1,A ;6845 ADDR REG MOV R5,A ;DISP STATUS MOV R6,A ;ACCUM SAVE ;SETUP THE FLAGS CPL F1 ;CLR END OF FRAME CPL F0 ;CLR CURSOR UPDATE ;SETUP THE EVENT COUNTER MOV A,#0FFH ;OVFL LESS ONE MOV T,A ;TO EVENT CNTR STRT CNT ;ENABLE CNTR ;ENABLE INTERRUPTS EN TCNTI ;ENABLE TIMER INT EN I ;ENABLE STALL INT ; ; THE MAIN LOOP ; ; WHILE NOT END OF FRAME ; 1. SEND OUT scan codes in FIFO ; 2. Process Drive Off ; 3. Poll power status port ; Process Lo Batt 1 if set ; Check for AC-ON rising ; 4. Poll NMI request register ; ; AT END OF FRAME: ; 1. Clear end of frame flag. ; 2. Send NMI if cursor updated ; 3. Update blink counter. On overflow: ; Update display blink if enabled ; Pulse attribute if mode enabled ; Update EL panel timeout if enabled ; Send Lo Batt 2 NMI if true and AC-OFF ; 4. ScO-OUT XRL A,R2 ;CMPR FIFO-IN JZ DRVOFF ;SKIP IF FIFO EMPTY MOV A,R3 ;FETCH IT AGAIN INC A ;AND BUMP IT JNZ SENDOUT1 ;SKIP IF NO OVFL MOV A,#FIFO ;WRAP THE FIFO SENDOUT1: MOV R3,A ;RESTORE THE PTR SEL RB0 ;BANK ZERO MOV R0,A ;TO NDX VIA A MOV A,@R0 ;READ BUF TO A OUTL P1,A ;AND THEN TO 8255 ANL P2,#NOT KBDAV.N ;ASSERT CPU INT1 ORL P2,#KBDAV.N ;NEGATE STROBES ; ; DRIVE OFF FUNCTION ; DRVOFF: SEL RB0 ;BANK 0 REGISTERS ;READ CURRENT STATE OF FDC MOV R0,#AUX.ENA ;SET NDX TO AUX PORT MOVX A,@R0 ;READ PORT TO A ANL A,#40H ;MASK TO FDC ON MOV R0,A ;HOLD IN R0 ;READ DRIVE AND FDC OFF FROM DISP-STAT, CLR IN STAT SEL RB1 ;BANK 1 REGISTERS DIS I ;BLOCK INTERRUPTS MOV A,R5 ;COPY DISPLAY STATUS ANL A,#0CDH ;CLR DRIVE OFF BITS XCH A,R5 ;SWAP WITH ORIGINAL EN I ;ENABLE INTERRUPTS SEL RB0 ;BANK 0 REGISTERS XRL A,#32H ;CMPL THE OFF BITS ;PROCESS FDC-OFF JB1 DRVOFF0 ;SKIP IF NOT FDC OFF MOV R0,#00H ;CLR FDC STATE DY NMI CODE JMP PWRFAIL4 PWRFAIL2: MOV A,#BADAC$ ;LOAD AC NMI CODE PWRFAIL4: CALL NMI ;SET STATUS AND PULSE NMI DIS I ;DISABLE EXT INTERRUPT DIS TCNTI ;DISABLE CNTR INTERRUPT MOV A,#0 MOV R0,#00H ;CLR FDC STATE MOVX @R0,A ;PULSE NEW FDC STATE MOV R0,#DS.STB ;SET NDX TO DISP CTL MOV A,#(EL.B OR 90H) ;A = ELEN,40 COL & CURE OFF MOVX @R0,A ;AND THE DISP CTL PORT DB 1H ;IDLE OP-CODE HANG FOREVER ;AC-ON RISING PWRFAIL3: MOV A,#ACCHG$ ;NMI CODE OF AC-ON CALL NMI ;NMI TO CPU ; ; NMI REQUEST - Test the NMIREQ variable. If it is ; non-zero, send the content to the NMI routine and ; clear the variable. ; NMIRQ: SEL RB0 ;BANK 0 REGISTERS MOV R0,#NMIREQ ;SET NDX TO NMI REQ MOV A,@R0 ;AND READ THE VARIABLE JNZ NMIRQ1 ;SKIP IF CODE PRESENT JMP MAIN ;OTHERWISE DONE NMIRQ1: MOV @R0,#00H ;CLEAR THE VARIABLE CALL NMI ;SET THE CODE SEL RB0 ;RESTORE BANK JMP MAIN ;AND DONE ; ; ; TIMER INTERRUPT - A sync pulse has been received from ; the LR0,A ;RESTORE JMP MAIN ;DONE FOR NOW ;SPEED 1 RPT1: MOV R6,#07H ;FOR 10 CPS JMP RPT4 ; RPT2: JB6 RPT3 ;IF SPEED 3 ;SPEED 2 MOV R6,#03H ;FOR 20 CPS JMP RPT4 ; ;SPEED 3 RPT3: MOV R6,#01H ;FOR 40 CPS INC A ;BUMP ORL A,#0F0H ;LATCH HI BITS JMP RPT5 ;CONT RPT4: INC A ;BUMP RPT5: MOV @R0,A ;RESTORE ANL A,R6 ;MASK LSBS JNZ RPT6 ;NOT TIME YET SEL RB1 ;TO FIFO BANK MOV A,R2 ;FETCH FIFO-OUT SEL RB0 ;RESTORE BANK MOV R0,A ;ADDR TO NDX MOV A,@R0 ;LAST SCAN CODE JB7 RPT6 ;EXIT IF BREAK ADD A,#0BBH ;ADD COMPLEMENT OF NUMLOCK JZ RPT6 ;SKIP IF NUMLOCK MOV A,@R0 ;RESTORE ACC CALL SENDSCAN ;DATA TO FIFO RPT6: JMP MAIN ;AND DONE PAGE ; ; START OF SECOND PAGE ; ORG ROM.ORG+100H ; ; STALL INTERRUPT - This interrupt is invoked whenever the ; CPU accesses an I/O port in the range reserved for the ; IBM Color / Graphics adapter. The hardware features of ; these boards which will be emulated by this code inlT ;R0 READ 6845 ADDR DB RCRTDATA ;R1 READ 6845 DATA DB EXIT ;R2 READ 6845 ADDR DB RCRTDATA ;R3 READ 6845 DATA DB RCRTADDR ;R4 READ 6845 ADDR DB RCRTDATA ;R5 READ 6845 DATA DB EXIT ;R6 READ 6845 ADDR DB RCRTDATA ;R7 READ 6845 DATA DB RMODE ;R8 READ MODE REG DB EXIT ;R9 READ SELECT DB RSTAT ;RA READ STATUS DB EXIT ;RB LIGHT PEN CLEAR DB EXIT ;RC READ MODE REG DB EXIT ;RD READ SELECT DB EXIT ;RE READ STATUS DB EXIT ;RF LIGHT PEN CLEAR DB WCRTADDR ;W0 WRITE 6845 ADDR DB WCRTDATA ;W1 WRITE 6845 DATA DB WCRTADDR ;W2 WRITE 6845 ADDR DB WCRTDATA ;W3 WRITE 6845 DATA DB WCRTADDR ;W4 WRITE 6845 ADDR DB WCRTDATA ;W5 WRITE 6845 DATA DB WCRTADDR ;W6 WRITE 6845 ADDR DB WCRTDATA ;W7 WRITE 6845 DATA DB WMODE ;W8 WRITE MODE REG DB EXIT ;W9 WRITE COLOR SELECT DB EXIT ;WA WRITE STATUS DB EXIT ;WB LIGHT PEN CLEAR DB EXICD display causing the event counter to overflow ; and generate an interrupt. Reset the counter to -1 ; and re-arm the timer interrupt. Clear F1 to indicate ; that end of frame has been reached. ; ; F1 Cleared ; TIMER: ;TIMER INT CLR F1 ;ENABLE END OF FRAME SEL RB1 ;FOR CORRECT R6 MOV R6,A ;SAVE A IN R6 MOV A,#0FFH ;ONE SHORT OF OVFL MOV T,A ;TO RE-ARM THE TIMER MOV A,R6 ;RESTORE A RETR ;AND DONE ; ; AUTO REPEAT - SENDSCAN clears REPEAT. This ; routine will increment repeat. Once bit 7 ; is set, it latches 6 & 7. Based on the MSBs: ; 00 Delay - No Output ; 01 Repeat - 5 cps ; 10 Repeat - 10 cps ; 11 Repeat - 15 cps ; The output rate is controlled by the LSBs: ; 0000 5 cps ; d000 10 cps ; dd00 20 cps ; The character at FIFO-IN is sent unless ; it is a break code. ; FRAME4: SEL RB0 ;BANK 0 REGISTERS MOV R0,#REPEAT ;SET NDX TO CNTR MOV A,@R0 ;AND FETCH IT JB7 RPT2 ;SPEED 2 OR 3 JB6 RPT1 ;SPEED 1 INC A ;DELAYING MOV @cude ; the 6845, the MODE register, and the STATUS register. ; Accesses of the SELECT register and the light pen latch ; will be ignored. The interrupt response time must be ; minimized as the CPU is held in a wait state inhibiting ; refresh cycles until it is released. The interrupt ; response time for a port write operation is 18 cycles. ; ; ; THE PORT TABLE: ; The least significant four bits of the CPU address ; and the state of the IORS (I/O Read Status) line are ; read through a port and a 32 entry table is then used ; to call potentially unique routines for reading or ; writing any of the sixteen port addresses associated ; with the color graphics boars. ; ; Processor Address Port: A2 /IOR A3 A1 A0 ; ; The table will dispatch the code to: ; EXIT Illegal or Ignored Access ; WCRTADDR Write 6845 address register ; RCRTDATA Read 6845 data register ; WCRTDATA Write 6845 data register ; WMODE Write MODE register ; RSTAT Read STATUS register ; PORT.TBL: DB EXIT ;WC LIGHT PEN SET DB EXIT ;WD NOT USED DB EXIT ;WE NOT USED DB EXIT ;WF NOT USED ; ; 6845 ADDRESS TABLE: ; The 6845 requires only two addresses in its ; interface while its internal structure proivides ; eighteen bytes of registers. The first accessable ; address is a pointer register used to select which ; of the internal registers is to be accessable through ; the second. This table is used to dispatch on the ; data which the CPU is attempting to write to the ; 6845's address register. ; ; A number of hardware features unique to the PIVOT have ; been concealed in registers added to the emulated 6845. ; Since these features may be accessed by the operating ; system or within an NMI, and the accesses requires a ; pair of cycles (one to set the address register and ; one to access the data register), mechanisms are ; provided for preserving address pointers of lower ; levels as higher levels are accessed. ; ; This table will dispatch to: ; WADDR Load Addr19-21 make transient use of the address ; register in that its value prior to selection of ; one of these registers is restored (from SAVE1) ; following the next data register access. Setting ; the address register to R18 indicates the start ; of an NMI routine causing the current state of ; the address register to be saved in SAVE2. Any ; write to R18 will clear the NMI state and restore ; the address register from SAVE2. Within an NMI, ; any number of other address or data accesses may ; be made. ; ; This table will dispatch to: ; RD.REG Read Register ; EXIT Return FFh - Illegal ; RD.18 Return NMI status code ; RD.20 Display Control Shadow ; RD.21 Return Extra, Pop SAVE1* ; ; * SAVE1 is popped only if NMI is off ; RD.TBL DB RD.REG ;R0 DB RD.REG ;R1 DB RD.REG ;R2 DB RD.REG ;R3 DB RD.REG ;R4 DB RD.REG ;R5 DB RD.REG ;R6 DB RD.REG ;R7 DB RD.REG ;R8 DB RD.REG ;R9 DB RD.REG ;R10 DB RD.REG ;R11 DB RD.REG ;R12 DB RD.REG ;R13L BIT 0 JB1 WMODE1 ;SKIP IF GRAPHIC JB0 WMODE2 ;SKIP IF 40X25 ALPHA CLR A ;80X25 ALPHA JMP WMODE3 ;CLR HI-RES WMODE1: JB4 WMODE2 ;SKIP IF 640X200 CLR A ;320X200 GRAPHIC JMP WMODE3 ;CLR HI-RES WMODE2: MOV A,#10H ;SET HI-RES WMODE3: XCH A,R0 ;SWAP WITH MODE ANL A,#01000010B ;KEEP BITS 1 & 6 ORL A,R0 ;ADD HI-RES, BIT 4 MOV R0,A ;HOLD IN R0 MOV A,R7 ;FETCH SHADOW ANL A,#10101101B ;KEEP THE REST ORL A,R0 ;MERGE NEW BITS MOV R7,A ;UPDATE SHADOW MOV R0,#DS.STB ;SET NDX TO DISP MOVX @R0,A ;UPDATE DISP CTL REG JMP EXIT1 ;AND EXIT RMODE: MOV A,R4 ;FETCH NMI STATUS JB7 RMODE1 ;SKIP IF NMI ACTIVE JMP EXIT ;NOT ALLOWED RMODE1: JMP ROM.DSK ;FETCH A BYTE RSTAT: JMP GSTAT ; GOTO DIFFERENT PAGE RDATA: MOV R0,#PD.STB ;SET NDX TO CPU DATA MOVX @R0,A ;AND OUTPUT THE DATA ORL P2,#PACK.P ;RELEASE HOST PROC ANL P2,#NOT PACK.P ;NEGATE STROBE RET WCRTADDR: CALL WDATA ;FETCH THE CPU DATA ANL A,#1FH ;MASK TO FIVE BITes ; EXIT Ignore Address - Illegal ; NMIADR Push to SAVE2 - Load ; TRANADR Push to SAVE1 - Load ; ADDR.TBL: DB WADDR ;A0 DB WADDR ;A1 DB WADDR ;A2 DB WADDR ;A3 DB WADDR ;A4 DB WADDR ;A5 DB WADDR ;A6 DB WADDR ;A7 DB WADDR ;A8 DB WADDR ;A9 DB WADDR ;A10 DB WADDR ;A11 DB WADDR ;A12 DB WADDR ;A13 DB WADDR ;A14 DB WADDR ;A15 DB WADDR ;A16 DB WADDR ;A17 DB NMIADR ;A18 DB EXIT ;A19 DB TRANADR ;A20 DB TRANADR ;A21 DB TRANADR ;A22 DB TRANADR ;A23 DB TRANADR ;A24 DB TRANADR ;A25 DB TRANADR ;A26 DB TRANADR ;A27 DB EXIT ;A28 DB EXIT ;A29 DB EXIT ;A30 DB EXIT ;A31 ; ; 6845 DATA REGISTER TABLE: ; The routines which this table passed execution to ; will normally read or write the 6845 register ; indicated by the current value in the address ; register. ; ; There are two types of accesses permitted to the ; added registers. Operating system accesses of ; registers  DB RD.REG ;R14 DB RD.REG ;R15 DB RD.REG ;R16 DB RD.REG ;R17 DB RD.18 ;R18 DB EXIT ;R19 DB RD.20 ;R20 DB RD.21 ;R21 DB EXIT ;R22 DB EXIT ;R23 DB EXIT ;R24 DB EXIT ;R25 DB EXIT ;R26 DB EXIT ;R27 DB EXIT ;R28 DB EXIT ;R29 DB EXIT ;R30 DB EXIT ;R31 STALL: SEL RB1 ;BANK 1 REGISTERS MOV R6,A ;SAVE A IN R6 MOV R0,#PA.ENA ;PROC ADDR TO NDX MOVX A,@R0 ;ADDR TO A ANL A,#1FH ;MASK TO 5 BITS ; ADD A,#PORT.TBL AND 0FFH ;TABLE ADDR IS ZERO JMPP @A ;JUMP THROUGH TABLE EXIT: ORL P2,#PACK.P ;RELEASE HOST PROC ANL P2,#NOT PACK.P ;NEGATE STROBE EXIT1: CALL SETEL ;INITIALIZE EL TIME OUT COUNTER MOV A,R6 ;RESTORE A RETR ;AND RETURN WDATA: MOV R0,#PD.ENA ;DATA ADDR TO NDX MOVX A,@R0 ;DATA TO ACC ORL P2,#PACK.P ;RELEASE HOST PROC ANL P2,#NOT PACK.P ;NEGATE STROBE RET WMODE: CALL WDATA ;ACCEPT THE DATA ADD A,#20H ;BLINK ENA TO B6 MOV R0,A ;COPY TO R0 XRL A,#01H ;CMPS MOV R0,A ;HOLD COPY IN R0 ADD A,#ADDR.TBL AND 0FFH ;OFST TO TABLE BASE JMPP @A ;JMP INDIRECT WADDR: MOV A,R0 ;MOVE VIA A MOV R1,A ;TO R1 JMP EXIT1 ;AND EXIT NMIADR: MOV A,R4 ;FETCH NMI STATUS JB7 WADDR ;SKIP IF NMI SET JMP NMIADR1 ;SKIP NEXT PAGE TRANADR: MOV A,R4 ;FETCH NMI STATUS JB7 WADDR ;SKIP IF NMI SET MOV A,R0 ;RECALL NEW ADDR XCH A,R1 ;SWAP OLD WITH NEW MOV R0,#SAVE1 ;SET NDX TO SAVE1 TRANADR1: MOV @R0,A ;PUSH OLD R1 MOV A,R6 ;RESORE A RETR ;AND DONE RCRTADDR: JMP RADDR ;SKIP TO NEXT PAGE WCRTDATA: JMP WCRTDAT1 ;CHANGE PAGES RCRTDATA: MOV A,R1 ;FETCH THE ADDR ADD A,#RD.TBL AND 0FFH ;READ DATA TABLE JMPP @A ;INDIRECT THRU TABLE RD.REG: MOV A,R1 ;FETCH REG NUMBER ADD A,#CRT.REG ;ADD RAM OFST MOV R0,A ;COPY TO NDX MOV A,@R0 ;AND READ DATA CALL RDATA ;SEND DATA AND REL CPU MOV A,R4 ;FETCH NMI STATUS JB7 RD.REG1 ;SKIP IF ACTIVE JMP EXIT1 ;ELSE DONE RD.REG1: INC R1 ;BUMP ADDR REG address register to R18 indicates the start ; of an NMI routine causing the current state of ; the address register to be saved in SAVE2. Any ; write to R18 will clear the NMI state and restore ; the address register from SAVE2. Within an NMI, ; any number of other address or data accesses may ; be made. ; ; This table will dispatch to: ; WR.REG Write Register ; WEXIT Return FFh - Illegal ; WR.18 End NMI, Pop SAVE2 ; ; WR.20 Write Display, Pop SAVE1* ; WR.21 Write FDC ON, Pop SAVE1* ; WR.22 Set NMI request, Pop SAVE1* ; WR.23 Set EL Timer Disable, Pop SAVE1* ; WR.24 Set Attribute State, Pop SAVE1* ; WR.25 Drive Power Off, Pop SAVE1* ; WR.26 Keyboard Reset ; WR.27 Keyboard State ; ; * SAVE1 is popped only if NMI is off ; WR.TBL DB WR.REG ;W0 DB WR.REG ;W1 DB WR.REG ;W2 DB WR.REG ;W3 DB WR.REG ;W4 DB WR.REG ;W5 DB WR.REG ;W6 DB WR.REG ;W7 DB WR.REG ;W8 DB WR.REG ;W9 DB WR.STYL ;W10 DB WR.STYL ;W11 DB WR.RON CURSOR UPDATE MOV R5,A ;RESTORE DISP STAT WR.REG: MOV A,R1 ;FETCH REG NUMBER ADD A,#CRT.REG ;ADD BASE ADDR XCH A,R0 ;SWAP ADDR & DATA MOV @R0,A ;STORE DATA TO ADDR JMP WEXIT1 ;AND EXIT ;WRITE NMI STATUS REGISTER WR.18: MOV R4,#0 ;CLR NMI STATUS MOV R0,#SAVE2 ;SET NDX TO SAVE2 MOV A,@R0 ;AND RESTORE MOV R1,A ;VIA A MOV A,R6 ;RESTORE A RETR ;AND DONE ;WRITE DISPLAY CONTROL PORT WR.20: MOV A,#10001001B ;NEW BIT MASK ANL A,R0 ;ON NEW DATA XRL A,#80H ;TOGGLE CUR ENA MOV R0,A ;BACK ON HOLD MOV A,#01110110B ;OLD BIT MASK ANL A,R7 ;ON OLD DATA ORL A,R0 ;MERGE BITS MOV R7,A ;UPDATE SHADOW MOV R0,#DS.STB ;SET NDX TO DISP MOVX @R0,A ;AND UPDATE DISP JMP WR.EXIT ;TRANSIENT EXIT ;WRITE FDC-ON WR.21: MOV A,R0 ;RECALL NEW DATA JB6 WR.EXIT ;SKIP IF FDC-ON MOV A,#02H ;FDC OFF BIT ORL A,R5 ;MERGE DISP STAT MOV R5,A ;RESTORE STAT JMP WR.EXIT ;TRANSIENT EXIT ;WRITE NMI REQUEST WR.22: MOV A,R0 ;RECALL  JMP EXIT1 ;AND END INTERRUPT RD.18: MOV A,R4 ;FETCH NMI STATUS ANL A,#7FH ;MASK ACTIVE FLAG CALL RDATA ;RETURN DATA MOV A,R6 ;RESTORE A RETR ;AND DONE RD.20: MOV A,R7 ;COPY SHADOW TO A CALL RDATA ;RETURN DATA MOV A,R6 ;RESTORE A RETR ;AND DONE RD.21: MOV R0,#AUX.ENA ;SET NDX TO AUX PORT MOVX A,@R0 ;AND READ PORT CALL RDATA ;DATA TO CPU MOV A,R6 ;RESTORE A RETR ;AND DONE PAGE ; ; START OF THIRD PAGE OF ROM ; ORG ROM.ORG+200H ; ; 6845 DATA REGISTER TABLE: ; The routines which this table passed execution to ; will normally read or write the 6845 register ; indicated by the current value in the address ; register. ; ; There are two types of accesses permitted to the ; added registers. Operating system accesses of ; registers 19-21 make transient use of the address ; register in that its value prior to selection of ; one of these registers is restored (from SAVE1) ; following the next data register access. Setting ; the EG ;W12 DB WR.REG ;W13 DB WR.CUR ;W14 DB WR.CUR ;W15 DB WR.REG ;W16 DB WR.REG ;W17 DB WR.18 ;W18 DB WEXIT ;W19 DB WR.20 ;W20 DB WR.21 ;W21 DB WR.22 ;W22 DB WR.23 ;W23 DB WR.24 ;W24 DB WR.25 ;W25 DB WR.26 ;W26 DB WR.27 ;W27 DB WEXIT ;W28 DB WEXIT ;W29 DB WEXIT ;W30 DB WEXIT ;W31 WEXIT: ORL P2,#PACK.P ;RELEASE HOST PROC ANL P2,#NOT PACK.P ;NEGATE STROBE WEXIT1: CALL SETEL ;INITIALIZE EL TIME OUT COUNTER MOV A,R6 ;RESTORE A RETR ;AND RETURN WCRTDAT1: MOV R0,#PD.ENA ;DATA ADDR TO NDX MOVX A,@R0 ;DATA TO ACC ORL P2,#PACK.P ;RELEASE HOST PROC ANL P2,#NOT PACK.P ;NEGATE STROBE MOV R0,A ;HOLD IN R0 MOV A,R1 ;FETCH THE ADDR ; ADD A,#WR.TBL AND 0FFH ;WRITE DATA TABLE JMPP @A ;INDIRECT THRU TABLE WR.STYL: MOV A,R0 ;FETCH DATA ORL A,#80H ;SET UPDATE FLAG MOV R0,A ;REPLACE IN R0 JMP WR.REG ;AND USE WRITE REG WR.CUR: MOV A,R5 ;FETCH DISPLAY STATUS ORL A,#80H ;TURN NEW DATA MOV R0,#NMIREQ ;SET NDX TO NMI REQ MOV @R0,A ;AND STORE DATA JMP WR.EXIT ;TRANSIENT EXIT ;WRITE DISPLAY TIMEOUT WR.23: MOV A,R5 ;FETCH DISP STAT ANL A,#0FBH ;MASK KEEPERS MOV R5,A ;BACK ON HOLD MOV A,R0 ;FETCH NEW DATA ANL A,#04H ;BIT 2 ONLY ORL A,R5 ;MERGE KEEPERS MOV R5,A ;AND RESTORE JB2 WR.231 ;SKIP IF TIME INH JMP WR.EXIT ;OTHERWISE EXIT WR.231: MOV A,R7 ;FETCH SHADOW ANL A,#0FBH ;MASK OUT EL PANEL XCH A,R0 ;SWAP WITH NEW DATA RL A ;SHIFT UP BIT 1 ANL A,#04H ;MASK TO BIT 2 ORL A,R0 ;MERGE OLD DATA MOV R7,A ;AND RESTORE SHADOW JMP WR.EXIT ;AND DONE ;WRITE DISPLAY CONTROL PORT WR.24: JB0 WR1.24 ;STATE TO HIGH ANL P2,#NOT ATENA.P ;CLEAR ATENA JMP WR2.24 ;AND CONT WR1.24: ORL P2,#ATENA.P ;SET ATENA WR2.24: MOV A,#01000000B ;MASK TO PULSE MODE ANL A,R0 ;INHIBIT ON NEW DATA MOV R0,A ;HOLD IN R0 MOV A,R5 ;FETCH DISP STATUS ANL A,#10111111B ;OLD BIT MASK ORL A,R0 ;MERGE ADDR: MOV A,R4 ;FETCH NMI STATUS JB7 ENDNMI ;SKIP IF NMI ACTIVE JNZ RADDR1 ;IF (NO NMI REQUEST) MOV A,#0 CALL RDATA ; ACKNOWLEDGE JMP WR.EXIT1 ; RETURN RADDR1: ANL P2,#NOT NMIRQ.P ;NEGATE THE NMI REQUEST CALL RDATA ;RETURN VALUE TO HOST ORL A,#80H ;ASSERT ACTIVE MOV R4,A ;TO STATUS REGISTER MOV R0,#SAVE2 ;SET NDX TO SAVE2 MOV A,R1 ;PUSH R1 TO MOV @R0,A ;SAVE2 VIA A MOV A,R4 ;RECALL NMI CODE JB5 RADDR2 ;SKIP IF ROM DISK XRL A,#CURSOR$+80H ;CURSOR UPDATE ? JNZ WR.EXIT1 ;QUIT IF NOT MOV R1,#0EH ;SET ADDR TO CUR REG MOV A,R7 ;FETCH DISP SHADOW ANL A,#7FH ;ENABLE CURSOR RAM MOV R0,#DS.STB ;SET NDX TO DISP CTL MOVX @R0,A ;AND WRITE DISP REG JMP WR.EXIT1 ;DONE FOR NOW ; RADDR2: JMP ROM.DSK2 ;ACCESS THE DISK ; ENDNMI: MOV A,R7 ;FETCH DISP SHADOW ORL A,#80H ;DISABLE CURSOR RAM MOV R0,#DS.STB ;SET NDX TO DISP CTL MOVX @R0,A ;AND WRITE DISP REG MOV A,#ROM.REV ;A:= CURRENT ROM REVISION CALL RDATA ;VALUE TO HOST elta ; R6 = Save Bit Counter ; R7 = Current Keyboard State ; ORG ROM.ORG+300H ;TABLE AT X00 ; BIT 0 1 2 3 4 5 6 7 SCANTBL: DB 3BH,3DH,3FH,42H,44H,X09,X08,00H ;ROW12 DB 3CH,3EH,40H,41H,43H,X0A,X07,00H ;ROW11 DB 0EH,X1C,X05,X12,X0F,X0C,X13,X14 ;ROW10 DB X06,1CH,X0D,X11,X0E,X0B,X10,X1E ;ROW9 DB 1AH,00H,X15,07H,15H,23H,X1F,31H ;ROW8 DB X03,2BH,X16,06H,14H,22H,X17,30H ;ROW7 DB 0FH,X19,0CH,04H,12H,20H,X20,2EH ;ROW6 DB X04,1BH,X1B,03H,11H,1FH,X18,2DH ;ROW5 DB 3AH,X00,00H,05H,13H,21H,39H,2FH ;ROW4 DB 01H,00H,X01,02H,10H,1EH,X1A,2CH ;ROW3 DB 00H,00H,00H,00H,00H,00H,00H,X02 ;ROW2 DB 00H,00H,00H,00H,00H,00H,00H,X1D ;ROW1 SCANCODE: MOV R6,#8 ;INITIATE CNT SC1: RLC A ;NEXT BIT TO CRY JNC SC8 ;SKIP IF NOT SET MOV R4,A ;SAVE ROTATED DELTA MOV A,R2 ;GET ROW INDEX DEC A ;ADJUST TO 11-0 RL A ;AND SHIFT UP - 1 RL A ; - 2 RL A ; - 3 ADD A,R6 ;MERGE THE BIT NUMBER DEC A ;DECR FOR 8-1 TO 7-0 MOVP A,@A WITH NEW MOV R5,A ;AND RESTORE STATUS JMP WR.EXIT ;TRANSIENT EXIT ;WRITE DRIVE OFF BITS OF DISPLAY STATUS REGISTER WR.25: MOV A,R0 ;FETCH NEW DATA ANL A,#32H ;MASK DRV OFF BITS MOV R0,A ;HOLD IN R0 MOV A,R5 ;FETCH DISP STATUS ANL A,#0CDH ;MASK OLD BITS ORL A,R0 ;MERGE NEW BITS MOV R5,A ;RESTORE STATUS JMP WR.EXIT ;TRANSIENT EXIT ;SOFTWARE RESET OF KEYBOARD WR.26: CALL KBINIT ;RESET KEYBOARD JMP WR.EXIT ;TRANSIENT EXIT ;WRITE KEYBOARD STATE WR.27: MOV A,R0 ;FETCH NEW DATA ANL A,#2FH ;MASK TO SIG BITS SEL RB0 ;TO REG BANK 0 MOV R7,A ;AND SET STATE SEL RB1 ;BANK IN BANK 1 JMP WR.EXIT ;TRANSIENT EXIT ;NMIADR from last page NMIADR1: ORL A,#80H ;IF NOT, SET IT MOV R4,A ;RESTORE NMI STATUS ANL P2,#NOT NMIRQ.P ;NEGATE THE NMI REQ MOV A,R0 ;RECALL NEW ADDR XCH A,R1 ;SWAP WITH OLD MOV R0,#SAVE2 ;SET NDX TO SAVE2 MOV @R0,A ;PUSH OLD R1 MOV A,R6 ;RESTORE A RETR ;AND DONE ;RCRTADDR from previous page. R CLR A ;CLEAR ACC MOV R4,A ;AND TO NMI STATUS MOV R0,#SAVE2 ;SET NDX TO SAVE2 MOV A,@R0 ;AND POP SAVED MOV R1,A ;VALUE OF R1 VIA A JMP WR.EXIT1 ;AND DONE ;TRANSIENT EXIT WR.EXIT: MOV A,R4 ;FETCH NMI STATUS JB7 WR.EXIT1 ;SKIP IF NMI SET MOV R0,#SAVE1 ;SET NDX TO SAVE1 MOV A,@R0 ;AND RESTORE R1 MOV R1,A ;VIA A ;NORMAL EXIT WR.EXIT1: MOV A,R6 ;RESTORE A RETR ;AND DONE PAGE ; ; START OF FOURTH PAGE OF ROM ; ; ; LOOKUP SCAN CODE - A scan code is looked up for each ; bit set in the accumulator assuming that R1 indicates ; the matrix row from which the data was obtained. If ; bit 7 is set in the located code, an NMI is generated ; using the balance of the code as a status. Otherwise, ; 80H is added to the locaed code if F0 was set and the ; result is placed in the FIFO. ; ; Bank 0 Register Usage: ; A = Image of Changed Keys ; R2 = 13 - Matrix Row Number ; F0 = Generate Break Codes ; ; A = Scan Code or NMI Status ; R4 = Save Rotated D ;AND FETCH THE CODE JB7 SC.CONV ;SKIP IF EXEC CODE JF0 SC.BRK ;SKIP IF BREAK CALL SENDSCAN ;DATA TO FIFO SC5: MOV R0,#BOUNCE ;SET NDX TO BOUNCE MOV A,R2 ;GET ROW NUMBER ADD A,#-3 ;LOOP CNT > 2 ? JNC SC6 ;YES, USE SHORT DLY MOV @R0,#KBDB.S ;LOAD SHORT DELAY JMP SC7 ;AND CONT SC6: MOV @R0,#KBDB.L ;LOAD LONG DELAY SC7: MOV A,R4 ;RESTORE ROTATED DATA SC8: DJNZ R6,SC1 ;REPEAT FOR 8 BITS CALL SETEL ;INITIALIZE EL TIME OUT COUNTER MOV R0,#REPEAT ;SET NDX TO RERPEAT MOV @R0,#0 ;AND RESET IT RET ;AND DONE SC.CONV: CALL CONVERT ;SKIP TO NEXT PAGE JF0 SC7 ;NO DEBOUNCE ON BREAK JMP SC5 ;SET DEBOUNCE SC.BRK: ORL A,#80H ;ADD BREAK BIT MOV R0,#SWBRK ;SET NDX TO SWALLOW BREAK XCH A,@R0 ;SWAP DATA JZ SC9 ;JUMP IF NO BREAK TO SWALLOW XRL A,@R0 ;SEE IF THE SAME JZ SC10 ;JUMP IF MATCH XRL A,@R0 ;RESTORE DATA SC9: XCH A,@R0 ;SWAP BACK CALL SENDSCAN ;DATA TO FIFO JMP SC7 ;NO DEBOUNCE SC10: MOV @R0,A ;CLEAR SWBRK JMP XRL A,R3 ;CMP FIFO-OUT JZ SNDSCAN2 ;SKIP IF BUF FULL XRL A,R3 ;RESTORE ADDR MOV R2,A ;UPDATE FIFO-IN SEL RB0 ;RESTORE BANK XCH A,R0 ;SWAP ADDR & DATA MOV @R0,A ;SEND DATA TO FIFO RET ;AND DONE SNDSCAN2: MOV A,R2 ;FETCH OLD VALUE SEL RB0 ;RESTORE BANK XCH A,R0 ;SWAP ADDR & DATA MOV @R0,A ;SEND DATA TO FIFO RET ; ; NMI - If NMI is not already set, the status code from ; A is place in the NMI status register and the CPU's ; NMI request line is set. The routine then waits for ; the status register to be cleared through the STALL ; interrupt routine and then exits with A clear. If ; NMI is already active on entry, exit the routine ; immediately with the new code in A. ; ; A = NMI Status Code ; NMI: SEL RB1 ;IN REGISTER BANK 0 XCH A,R4 ;SWAP NEW & OLD JB7 NMI2 ;IF ALREADY NMI ON ORL P2,#NMIRQ.P ;ASSERT NMI REQUEST NMI1: MOV A,R4 ;FETCH NMI STATUS JNZ NMI1 ;LOOP UNTIL CLEARED RET NMI2: XCH A,R4 ;RESTORE OLD CODE RET ; ; KBe will convert keyboard ; column/row information to either a PC equivalent scan ; code or to a special conversion code which will be ; indicated by bit 7 being a 1. This routine will ; further decode this information. ; ; A = Output of scan code table with B7 = 1 ; ; F0 = 1 for break, 0 for make. ; ; The keyboard state is held in R7 of bank 0: ; ; ORG ROM.ORG+400H ;TABLE AT X00 ; NL.B EQU 20H ;NUM LOCK SET SCRL.B EQU 10H ;SCROLL LOCK SENT ALT.B EQU 08H ;ALT DOWN CTL.B EQU 04H ;CTL DOWN LS.B EQU 02H ;LS DOWN RS.B EQU 01H ;RS DOWN CONVERT: MOV R0,A ;HOLD ENTRY IN R0 JMPP @A ;INDIRECT THRU TBL ; ; STATE KEYS - This routine will maintain the states ; of LS, RS, CTL and NUM LOCK. ; CONV.LS: MOV A,R7 ;FETCH STATE JF0 CONV.LS1 ;SKIP IF BREAK ORL A,#LS.B ;SET LS BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CONV.LS1: ANL A,#NOT LS.B ;CLR LS BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CONV.RS: MOV A,R7 ;FETCH STATE  SC7 ;CONTINUE ; ; SEND SCAN - This routine will return the address of ; the next available FIFO-IN location. If the FIFO is ; full, this location will be the same as the previous ; location and the pointer will not be incremented. ; ; Called By SCANCODE and REPEAT, Returns in RB0 ; ; Bank 1 Register Usage: ; R2 = FIFO Input Pointer - Updated ; R3 = FIFO Output Pointer ; Bank 0 Register Usage: ; SENDSCAN: MOV R0,A ;HOLD IN R0 SEL RB1 ;BANK 1 REGISTERS MOV A,R7 ;GET DISP CTL SHADOW JB2 SNDSCAN0 ;SKIP IF EL ON DIS I ;LOCK OUT INTERRUPTS ORL A,#EL.B ;SET EL ON BIT MOV R7,A ;UPDATE SHADOW MOV R0,#DS.STB ;SET NDX TO DISP CTL MOVX @R0,A ;AND UPDATE PORT EN I ;UNLOCK INTERRUPTS SEL RB0 ;BANK 0 REGISTERS MOV A,R0 ;GET SCAN CODE ORL A,#80H ;MAKE BREAK CODE MOV R0,#SWBRK ;SET NDX TO MEM MOV @R0,A ;SAVE BREAK CODE RET SNDSCAN0: MOV A,R2 ;FETCH FIFO-IN INC A ;BUMP PTR JNZ SNDSCAN1 ;SKIP IF NOT OVFL MOV A,#FIFO ;WRAP THE FIFO SNDSCAN1: INIT - Initialize the keyboard ; KBINIT: SEL RB0 ;BANK 0 REGISTERS MOV R7,#0 ;CLEAR KB STATE SEL RB1 ;BANK 1 REGISTERS ;Clear all outstanding macroes CLR A ;CLEAR ACCUM MOV R2,#NUMMACRO*2 ;LENGTH IN BYTE MOV R0,#MACROES ;START OF STRUCTURE KBINIT1: MOV @R0,A ; CLEAR A BYTE INC R0 ; BUMP ADDR DJNZ R2,KBINIT1 ; FOR COUNT ; MOV R2,#FIFO ;CLR FIFO-IN MOV R3,#FIFO ;CLR FIFO-OUT MOV R0,#FIFO ;SET NDX TO FIFO-OUT MOV @R0,#80H ;STUFF A BREAK CODE RET ;THAT'S IT ; ; SETEL - Check the status of AC-ON and initialize the ; EL time out counter. ; SETEL: MOV R0,#AUX.ENA ;SET NDX TO EXTRA PORT MOVX A,@R0 ;READ IN THE PORT MOV R0,#ELTIME1 ;SET NDX TO EL TIMER MSB JB0 SETEL1 ;CHECK AC-ON MOV @R0,#EL.K1 ;SET TO BATTERY VALUE JMP SETEL2 SETEL1: MOV @R0,#EL.K10 ;SET TO AC VALUE SETEL2: DEC R0 ;SET NDX TO EL TIMER LSB MOV @R0,#EL.K0 ;AND RESET IT RET ; ; START OF FIFTH PAGE OF ROM ; ; ; CONVERT - The SCANCODE routin JF0 CONV.RS1 ;SKIP IF BREAK ORL A,#RS.B ;SET RS BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CONV.RS1: ANL A,#NOT RS.B ;CLR RS BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CONV.CTL: MOV A,R7 ;FETCH STATE JF0 CNV.CTL1 ;SKIP IF BREAK ORL A,#CTL.B ;SET CTL BIT MOV R7,A ;RESTOEE STATE JMP ARG1 ;AND SEND FIRST ARG CNV.CTL1: ANL A,#NOT CTL.B ;CLR CTL BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CONV.LCK: MOV A,R7 ;FETCH STATE JF0 CNV.LCK2 ;SKIP IF BREAK JB0 CNV.LCK1 ;SKIP IF RS JB2 ARG1 ;SND NUM LOCK IF CTL XRL A,#NL.B ;TOGGLE NUM LOCK MOV R7,A ;RESTORE STATE JMP ARG1 ;SEND NUM LOCK CNV.LCK1: ORL A,#SCRL.B ;SET SCROLL BIT MOV R7,A ;RESTORE STATE JMP ARROW ;SEND SCROLL CNV.LCK2: JB4 CNV.LCK3 ;BREAK SCROLL LOCK JMP ARG1 ;BREAK NUM LOCK CNV.LCK3: ANL A,#NOT SCRL.B ;CLR SCROLL BIT MOV R7,A ;RESTORE STATE JMP ARROW ;BREAK SCROLL LOCK CONV.ALT: MOV A,R7 ;FETCH STATE JF0 CNV.ALT1 ;SK3: JMP SENDSCAN ;SEND THE BREAK ; ; ARROW KEYS - From the rom table in this page, select an ; fetch a scan code based on the state of RS. Fetch ; argument three which is the macro address for the key. ; With this data in registers, depart to another ; page with more space to resolve this situation. ; ARROW: INC R0 ;BUMP TO ARG1 MOV A,R7 ;FETCH STATE JB0 ARROW1 ;SKIP IF RS MOV A,R0 ;ADDR BACK TO A MOVP A,@A ;FETCH ARG1 XCH A,R0 ;SWAP DATA & ADDR INC A ;TO ARG2 JMP ARROW2 ;AND CONTINUE ARROW1: INC R0 ;TO ARG2 MOV A,R0 ;RECALL ADDR MOVP A,@A ;FETCH ARG2 XCH A,R0 ;SWAP DATA & ADDR ARROW2: INC A ;DUMP TO ARG3 MOVP A,@A ;FETCH ARG3 JMP MACSET ;SETUP MACRO, NEW PAGE ; ; ICON KEYS - Icon keys will execute this code. If ; processing a key make, unique NMI status codes are ; generated for ALT and non-ALT versions of the key. ; No Scan Codes are placed in the FIFO. ; ICONS: JF0 ICONS3 ;SKIP IF BREAK MOV A,R7 ;FETCH STATE JB3 ICONS1 ;SK ;= DB 046H ;SCROLL LOCK X06: DB CTLKEYS ;PRINTER ON, 9.0 DB 028H ;' DB 019H ;^P X07: DB ICONS ;CLOCK ICON, 11.6 DB ICLOCK$ ;NMI STATUS CODE DB IACLOCK$ ;ALT-CLOCK X08: DB ICONS ;PHONE ICON, 12.6 DB IPHONE$ ;NMI STATUS CODE DB IAPHONE$ ;ALT-PHONE X09: DB ICONS ;DISK ICON, 12.5 DB IDISK$ ;NMI STATUS CODE DB IADISK$ ;ALT-DISK X0A: DB ICONS ;CALCULATOR ICON, 11.5 DB ICALC$ ;CALC DB IACALC$ ;ALT-CALC X0B: DB NUMPAD ;FUNCTION OF NUM LOCK, 9.5 DB 024H ;J - Alpha Key Board DB 04FH ;1 - Numeric Key Pad X0C: DB NUMPAD ; 10.5 DB 025H ;K DB 050H ;2 X0D: DB NUMPAD ; 9.2 DB 026H ;L DB 051H ;3 X0E: DB NUMPAD ; 9.4 DB 016H ;U DB 04BH ;4 X0F: DB NUMPAD ; 10.4 DB 017H ;I DB 04CH ;5 X10: DB NUMPAD ; 9.6 DB 018H ;O DB 04DH ;6 X11: DB NUMPAD ; 9.3 DB 008H ;7 DB 047H ;7 X12: DB NUMPAD ; 10.3 DB 009H ;8 DB 048H ;8 X13: DB NUMPAD ; 10.6 DB 00AH ;9 DB IP IF BREAK ORL A,#ALT.B ;SET ALT BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CNV.ALT1: ANL A,#NOT ALT.B ;CLR CTL BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG ; ; CONTROL FUNCTIONS - This routine handles "Prt On" ; which will send a CTL-P, and "Break" which will send a ; CTL-SCROLL LOCK. "Pause" is handled by CONV.LOCK: ; CTLKEYS: MOV A,R7 ;FETCH STATE JB2 ARG2 ;SKP IF CTL TO 2ND ARG JMP ARG1 ;JMP TO FIRST ARG ; ; NUMERIC KEYPAD - Keys in the range of the numeric ; keypad will come through here. If NUM LOCK is false ; the normal key function will be transmitted. If NUM LOCK ; is true, the numeric keypad equivalent will be transmitted. ; NUMPAD: MOV A,R7 ;FETCH STATE JB5 ARG2 ;SKIP IF NUM LOCK JMP ARG1 ;SEND FIRST ARG ARG2: INC R0 ;BUMP ONE ARG ARG1: INC R0 ;BUMP ONE ARG MOV A,R0 ;RECALL ADDR ARGS: MOVP A,@A ;FETCH THE ARG JF0 ARGS2 ;SKIP IF KEY BREAK JMP ARGS3 ; ARGS2: ADD A,#80H ;ADD BREAK BIT ARGSIP IF ALT MOV A,R0 ;RECALL ADDR INC A ;FIRST ARG JMP ICONS2 ;AND FETCH ICONS1: MOV A,R0 ;RECALL ADDR INC A ;SKIP FIRST ARG INC A ;USE SECOND ARG ICONS2: MOVP A,@A ;FETCH NMI STATUS CALL NMI ;SEND THE CODE SEL RB0 ;RESTORE REG BANK ICONS3: RET ;AND DONE ; ; MATH KEYS - Send alpha-key first argument if NUM LOCK ; if off. Otherwise fetch the second argument and depart ; to another page to setup a macro. ; MATH: MOV A,R7 ;RECALL STATE JB5 MATH1 ;SKIP IF NUM LOCK JMP ARG1 ;USE ALPHA KEY MATH1: INC R0 ;T0 ARG1 JMP ARROW1 ;TO FINISH UP X00: DB CONV.LS ;LEFT SHIFT KEY, 4.1 DB 02AH X01: DB CONV.RS ;RIGHT SHIFT KEY, 3.2 DB 036H X02: DB CONV.CTL ;CONTROL KEY, 2.7 DB 01DH X03: DB CONV.LCK ;LOCK KEY, 7.0 DB 045H ;NUM LOCK DB 046H ;SCROLL LOCK DB MACROES+15 ;Macro-8,Data X04: DB ARROW ;DELETE KEY, 5.0 DB 053H ;DELETE DB 052H ;INSERT DB MACROES+9 ;Macro-5,Data X05: DB CTLKEYS ;BREAK, 4.4 DB 00DH 049H ;9 X14: DB NUMPAD ; 10.7 DB 033H ;, DB 052H ;0 X15: DB MATH ; 8.2 DB 035H ;/ DB 04EH ;+ DB MACROES+11 ;Macro-6,Data X16: DB MATH ; 7.2 DB 027H ;; DB 04AH ;- DB MACROES+13 ;Macro-7,Data X17: DB NUMPAD ; 7.6 DB 34H ;. DB 53H ;. X18: DB ARROW ;FUNCTION OF SHIFT, 5.6 DB 4BH ;< DB 47H ;Home DB MACROES+3 ;Macro-2,Data X19: DB ARROW ; 6.1 DB 4DH ;> DB 4FH ;End DB MACROES+1 ;Macro-1,Data X1A: DB ARROW ; 3.6 DB 48H ;^ DB 49H ;Page Up DB MACROES+7 ;Macro-4,Data X1B: DB ARROW ; 5.2 DB 50H ;V DB 51H ;Page Down DB MACROES+5 ;Macro-3,Data X1C: DB CTLKEYS ;Print Screen, 10.1 DB 29H ;` DB 37H ;* X1D: DB CONV.ALT ;ALTKEY, 1.7 DB 38H ; X1E: DB NUMPAD ;9.7 DB 32H ;M DB 0DH ;= X1F: DB NUMPAD ;8.6 DB 19H ;P DB 37H ;* / PRTSCR SCAN CODE X20: DB NUMPAD ;6.6 DB 0BH ;0 DB 35H ;/ ; ; START OF SIXTH PAGE OF ROM ; ; FRAME - This page of the romX TO R11 MOV R2,A ; SAVE CRT.R10 IN R2 MOV A,@R0 ; FETCH R11 CPL A ; COMPLEMENT ADD A,R2 ; AND ADD JC STYL3 ;R10>R11 ;Cursor is on, generate cursor update NMI DEC R0 ;BACK TO R10 MOV A,@R0 ;FETCH REG ORL A,#40H ;SET BIT 6 MOV @R0,A ;AND RESTORE JMP FRAME18 ;Cursor is now off, generate cursor off NMI STYL3: MOV A,#CUROFF$ JMP FRAME19 ;End of frame test if r10 and r11 unchanged FRAME17: SEL RB1 ;BANK1 REGISTERS DIS I ;BLOCK INTERRUPTS MOV A,R5 ;FETCH DISPLAY STATUS ANL A,#7FH ;CLEAR UPDATE FLAG XCH A,R5 ;SWAP WITH ORIGINAL EN I ;ENABLE INTERRUPTS XRL A,#80H ;INVERT UPDATE FLAG JB7 FRAME2 ;SKIP IF NOT UPDATED FRAME18: MOV A,#CURSOR$ ;LOAD NMI STATUS CODE FRAME19: CALL NMI ;AND SEND NMI ; ; BLINK - Increment the BLINK variable. If no overflow, ; go on to FRAME3. Otherwise, re-initialize the counter. ; If blink is enabled, toggle the blink bit in the display ; control shadow register, otherwise, turn off the blink ; bit in thNT VALUE ANL A,#EL.B ;MASK TO EL BIT JMP FRAME25 ;SKIP TO BLINK FRAME22: SEL RB0 ;IN BANK 0 MOV R0,#ELTIME1 ;SET NDX TO TIMER MSB MOV A,@R0 ;FETCH CURRENT VALUE JZ FRAME23 ;DISPLAY OFF DEC R0 ;SET NDX TO LSB INC @R0 ;BUMP THE COUNT MOV A,@R0 ;FETCH NEW VALUE JNZ FRAME24 ;DISPLAY ON MOV @R0,#EL.K0 ;SET TO ONE MINUTE INC R0 ;SET NDX TO MSB INC @R0 ;BUMP THE COUNT JMP FRAME24 ;DISPLAY ON ;TURN EL PANEL OFF FRAME23: MOV A,#0 ;NEW VALUE TO ACC JMP FRAME25 ; ;TURN EL PANEL ON FRAME24: MOV A,#EL.B ;NEW VALUE IN ACC ;PROCESS BLINK CONTROL FRAME25: SEL RB0 ;BANK 0 MOV R0,#DS.STB ;SET NDX TO DISP CTL SEL RB1 ;IN BANK 1 XRL A,R7 ;GET CHANGE FOR EL BIT ANL A,#EL.B ;MASK OUT EL BIT ORL A,#BLINK.B ;OR IN BLINK BIT ;UPDATE SHADOW AND CONTROL PORT WITH DATA IN ACC DIS I ;LOCK OUT INTERRUPTS XRL A,R7 ;CHANGE BITS MOV R7,A ;UPDATE SHADOW SEL RB0 ;BANK 0 MOVX @R0,A ;AND UPDATE PORT EN I ;UNBLOCK INTERRUPTS ;PROCESS L contains all of the ; routines which execute at the end of each frame ; time of the display. These include the cursor ; update NMI, blink and EL timeouts, keyboard ; debouncing and keyboard scanning. ; ORG ROM.ORG+500H ;TABLE AT X00 ; ; FRAME1 - Generate CPU NMI if cursor register has ; been updated since the last end of frame. ; FRAME1: MOV R0,#CRT.REG+11 ;NDX TO 6845 REG 11 MOV A,@R0 ; AND FETCH JB7 STYL1 ;SKIP IF UPDATED DEC R0 ;BUMP NDX TO R10 MOV A,@R0 ; AND FETCH JB7 STYL1 ;SKIP IF UPDATED JB6 FRAME17 ;CURSOR IS ON JMP FRAME2 ;CURSOR IS OFF ;r10 or r11 changed STYL1: MOV R0,#CRT.REG+11 ;NDX TO 6845 REG 11 MOV A,@R0 ; AND FETCH ANL A,#1FH ;MASK TO FIVE BITS MOV @R0,A ;AND RESTORE DEC R0 ;NDX TO REG 10 MOV A,@R0 ;FETCH REG ANL A,#1FH ;MASK TO FIVE BITS XCH A,@R0 ;AND RESTORE JB6 STYL2 ;SKIP IF BLINK JB5 STYL3 ;CURSOR OFF STYL2: JB4 STYL3 ;=>16 JB3 STYL3 ;=>8 ANL A,#07H ;MASK TO THREE BITS INC R0 ;NDe shadow register. If attribute enable pulsing ; mode is enabled in the display status register, pulse ; attribute enable. Increment the EL panel ; least significant byte. If overflow, reset and increment ; the EL panel most significant byte. If it overflows, ; set it back to -1 so that it will overflow next time and ; clear the EL panel enable bit in the shadow. ; Copy the shadow to the control register. ; FRAME2: SEL RB0 ;BANK 0 REGISTERS MOV R0,#BLINK ;SET NDX TO BLINK INC @R0 ;BUMP IT MOV A,@R0 ;FETCH NEW VALUE JNZ FRAME20 ;SKIP IF NOT ZERO JMP FRAME200 FRAME20: JMP FRAME3 ;RE-INITIALIZE BLINK TIMER FRAME200: MOV @R0,#-K.BLINK ;RE-INIT THE CNTR ;PULSE ATTRIBUTE ENABLE IS MODE ACTIVE SEL RB1 ;IN BANK 1 MOV A,R5 ;FETCH DISP STATUS JB6 FRAME21 ;SKIP IF INHIBITED ANL P2,#NOT ATENA.P ;PULSE LOW ORL P2,#ATENA.P ;AND THEN HIGH ;PROCESS EL TIMEOUT FRAME21: XRL A,#04H ;TOGGLE TIMEOUT DISABLE JB2 FRAME22 ;SKIP IF NOT DISABLED MOV A,R7 ;FETCH CURREO BATT 2 NMI MOV A,R5 ;FETCH PWR STAT JB0 FRAME20 ;SKIP IF AC-ON JB1 FRAME28 ;SKIP IF LO BAT 2 JMP FRAME3 ;ELSE DONE FRAME28: MOV A,#LOBAT2$ ;LOAD NMI CODE CALL NMI ;AND SEND TO CPU JMP FRAME3 ;SKIP TO NEXT PAGE ;********************************************************** ;* GSTAT - The following code is used when the CGA status ;* port is read. It will cause the display enable (bit 0), ;* and VSYNC (bit 3) to cycle, giving all possible values ;* that can be read from the status port of a CGA. ;********************************************************* GSTAT: MOV R0,#DLYCNT ;GET DELAY COUNTER MOV A,@R0 DEC A ;UPDATE DELAY VALUE MOV @R0,A ;RESTORE NEW VALUE JNZ GS6 ;IF TIME IS UP MOV @R0,#DISPDLY ; THEN RESTORE NEW DELAY COUNT MOV A,R5 ; CALCULATE NEW VALUE JB3 GS1 ; IF VSYNC THEN CLEAR ALL JB0 GS2 ; IF ONLY DISPENBL THEN SET VSYNC ORL A,#1 ; ELSE SET DISPENBL JMP GS3 ; AND SEND DATA GS1: ANL A,#0F6H ; CLEAR BOTH BI******************** FRAME3: ; ; DEBOUNCE - If there is debounce time remaining, ; decrement the time and skip reading the keyboard ; for this frame time of the display. ; SEL RB0 ;BANK ZERO REGISTERS MOV R0,#BOUNCE ;SET NDX TO BOUNCE MOV A,@R0 ;FETCH DEBOUNCE JZ FRAME35 ;SKIP IF ZERO DEC A ;DECR BALANCE MOV @R0,A ;AND RESTORE JMP MAIN ;TILL NEXT FRAME FRAME35: ; ; MACRO EXECUTION - These routines will poll the eight ; macroes, executing any active macroes in place of ; normal keyboard scanning. This routine will poll for ; active macroes and transmit scan codes as required. ; RS EQU 036H ;SCAN CODE RS RSBRK EQU 0B6H ;SCAN CODE RS BREAK NMLK EQU 045H ;SCAN CODE NUM LOCK NMLKBRK EQU 0C5H ;SCAN CODE NMLK BREAK ;Don't bother to scan macroes or keyboard if FIFO is full. SEL RB1 ;BANK 1 REGISTERS MOV A,R2 ;FETCH FIFO-IN INC A ;BUMP PTR JNZ MACX0 ;SKIP IF NOT OVFL MOV A,#FIFO ;WRAP THE FIFO MACX0: XRL A,R3 ;CMP FIFO-OUT SEL RB0 ;BMP TO DATA MOV A,@R0 ;FETCH JMP MACX11 ; AND SEND ;Send RS MACX8: ANL A,#0FEH ;CLEAR BIT 0 MOV @R0,A ;TO CTL BYTE MOV A,#RS ;LOAD RS JMP MACX11 ;SEND SCANCODE ;Send NMLK Make MACX9: ANL A,#0EFH ;CLEAR BIT 4 MOV @R0,A ;TO CTL BYTE MOV A,#NMLK ;LOAD NMLK MACX11: CALL SENDSCAN ;SEND SCANCODE ;***** MOV R0,#BOUNCE ;DELAY 1 FRAME PER CHARACTER EXPANSION MOV @R0,#1 JMP MAIN ;AND DONE ;Loop for five macroes MACX12: INC R0 ;BUMP ADDR TO DATA INC R0 ;BUMP ADDR TO NEXT CTL DJNZ R1,MACX2 ;LOOP FOR EIGHT MACROES ; ; READ KEY MATRIX - The twelve rows of the key matrix ; are read into the corresponding even byte locations ; in the 24 byte structure KEY-ARRAY. The current state ; of FDC-ENA which is controlled by PAD6 must be main- ; tained. Turn off the KB decoder when done. ; KBSCAN1: MOV R1,#KARRAY ;FIRST KEY ARRAY BYTE MOV R2,#12 ;FOR TWELVE ROWS MOV R3,#04 ;FIRST KB ROW KBSCAN2: MOV R0,#AUX.ENA ;SET NDX TO AUX PORT MOVX A,@R0 ;READ PORTS JMP GS3 ; AND SEND DATA GS2: ORL A,#8 ; SET VSYNC GS3: MOV R5,A ;SAVE NEW STATUS GS4: ANL A,#09H ;MASK OFF OTHER DATA CALL RDATA ; RELEASE PROCESSOR WITH DATA JNZ GS5 ; IF DATA WAS ZERO THEN MOV A,R5 ; GET BACK THE DATA ORL A,#1 ; SET DISPENBL MOV R5,A ; AND SAVE DATA GS5: JMP EXIT1 ; RETURN TO WHENCE ENTERED FROM GS6: MOV A,R5 ; GET DATA SENT LAST TIME JMP GS4 ; AND SEND IT AGAIN ; ; START OF SEVENTH PAGE OF ROM ; ORG ROM.ORG+600H ;********************************************************** ;* KEYBOARD SCAN - The following code sequence will ;* scan the key matrix for changes once per frame ;* time of the LCD display. Key operations are ;* translated into scan codes and loaded into the ;* FIFO for tranmission to the CPU. ICON keys ;* assert NMI and present status codes. Detection ;* of the simultaneous assertion of CTL, ALT and DEL ;* will result in a RESET of the CPU. ;**************************************ACK TO BANK 0 JNZ MACX1 ;IF NOT FULL JMP MAIN ;IF FIFO IS FULL ;Scan for active macroes MACX1: MOV R0,#MACROES ;SET NDX TO MACROES MOV R1,#NUMMACRO ;FOR NUMBER MACROES MACX2: MOV A,@R0 ;FETCH CTL BYTE JZ MACX12 ;SKIP IF INACTIVE ;Play it again, Sam: JB6 MACX4 ;NMLK JB5 MACX5 ;NMLK BREAK JB1 MACX6 ;RS BREAK JB2 MACX7 ;DATA JB0 MACX8 ;RS MAKE JB4 MACX9 ;NUM LOCK MAKE ; JB3 MACX10 ;NUM LOCK BREAK ;Send Num Lock Break MACX3: ANL A,#0F7H ;CLEAR 3 BIT MOV @R0,A ; TO CTL BYTE MOV A,#NMLKBRK ; JMP MACX11 ;Send Num Lock Make MACX4: ANL A,#0BFH ;CLEAR BIT 6 MOV @R0,A ;TO CTL BYTE MOV A,#NMLK ; JMP MACX11 ;Send Num Lock Break MACX5: ANL A,#0DFH ;MASK BIT 5 MOV @R0,A ;TO CTL BYTE MOV A,#NMLKBRK ; JMP MACX11 ;Send RS Up MACX6: ANL A,#0FDH ;CLEAR BIT 1 MOV @R0,A ;TO CTL BYTE MOV A,#RSBRK ;LOAD RS BRK JMP MACX11 ;SEND SCANCODE ;Send Data MACX7: ANL A,#0FBH ;CLEAR BIT 2 MOV @R0,A ;TO CTL BYTE INC R0 ;BUT TO A ANL A,#40H ;MASK TO FDC-ON ORL A,R3 ;OR IN KB ROW MOV R0,A ;AND MOVE TO NDX MOVX @R0,A ;SELECT KB ROW MOV R3,#8 ;A COUNT OF 8 KBSCAN21: DJNZ R3,KBSCAN21 ;WASTE 16 CYCLES MOVX A,@R0 ;READ KB ROW DATA MOV @R1,A ;AND SAVE IN ARRAY INC R0 ;ADVANCE KB ROW INC R0 ;BY FOUR TO INC R0 ;NEXT KB INC R0 ;COLUMN MOV A,R0 ;KB ROW ANL A,#0BFH ;CLEAR FDC-ON MOV R3,A ;SAVE IN R3 INC R1 ;ADVANCE ARRAY NDX BY INC R1 ;TWO TO NEXT ENTRY DJNZ R2,KBSCAN2 ;DECR ROW CNT MOV A,R0 ;COPY R0 TO A ANL A,#40H ;MASK FDC ON MOV R0,A ;AND REPLACE MOVX @R0,A ;KB OFF, KEEP FDC ; ; LOCATE CHANGED KEYS - The current state of the ; key matrix is compared with the previous state. ; Changes are processed. The new data for rows ; eleven and twelve is ignored if more than one ; key is active between the two rows. ; KBSCAN3: MOV R1,#KARRAY+20 ;NDX TO ROW 11 MOV A,@R1 ;FETCH NEW DATA JNZ KBSFN2 ;SKIP IF R11 KEYS MOV R1,#KARRAY+22 ;NDX TO ROF NEW DATA WITH ANL A,R3 ;WITH CHANGES TO JZ KBSCAN6 ;FIND BREAKS - ANY? CPL F0 ;INDICATE BREAKS CALL SCANCODE ;PROCESS BREAKS KBSCAN6: INC R1 ;BUMP TO NEXT NEW DJNZ R2,KBSCAN4 ;LOOP FOR ALL ROWS JMP FRAME4 ;TO CHANGE PAGE ; ; START OF EIGHTH PAGE OF ROM ; ORG ROM.ORG+700H ; ROM DISK - The following code is used to upload 'sectors' ; of the keyboard processors rom to the host. The host processor ; requests a sector by writing the sector number with an ofset ; of 32 as an NMI Request. When the processor responds to the ; NMI, the sector number will be translated to a pointer into ; the following rom page table. This pointer will be held in ; the variable PAGE between accesses. The data is obtained by ; reading the Mode register. The first byte obtained will be ; byte 2 of the sector in order to skip the header. Each ; access will auto-increment the byte offset so that the entire ; sector may be read Subsequent ; ; In RADDR, test for a RAM DISK access afterP OFST JMP 200H ;IN BANK 1 PG3: MOV A,R1 ;COPY OFST FROM R1 INC R1 ;BUMP OFST JMP 300H ;IN BANK 1 PG4: MOV A,R1 ;COPY OFST FROM R1 INC R1 ;BUMP OFST JMP 400H ;IN BANK 1 PG5: MOV A,R1 ;COPY OFST FROM R1 INC R1 ;BUMP OFST JMP 500H ;IN BANK 1 PG6: MOV A,R1 ;COPY OFST FROM R1 INC R1 ;BUMP OFST JMP 600H ;IN BANK 1 PG7: MOV A,R1 ;COPY OFST FROM R1 INC R1 ;BUMP OFST JMP 700H ;IN BANK 1 ; ; ROM DISK is called for each data fetch of the rom disk. ; ROM.DSK: MOV R0,#PAGE ;SET NDX TO PAGE MOV A,@R0 ;AND RECALL PAGE DIS I DIS TCNTI CALL ROM.DSK3 ;ENABLE BANK 1 SELECT CALL ROM.DSK1 ;FETCH THE DATA SEL MB0 ;RESELECT ROM BANK 1 CALL RDATA ;SEND TO HOST MOV A,R6 ;RESTORE A FROM R6 EN TCNTI EN I RETR ;AND DONE ; ROM.DSK1: SEL MB1 ;IN ROM BANK 1 JMPP @A ;INDIRECT VIA PAGE TBL ; ROM.DSK2: MOV R0,#PAGE ;SET NDX TO PAGE MOV A,R4 ;FETCH NMI STATUS ANL A,#1FH ;CLR ACTIVE AND DISK MOV @W 12 MOV A,@R1 ;FETCH NEW DATA JZ KBSFN4 ;SKIP IF NO KEYS KBSFN5: CLR C ;CLEAR FOR ROTATE KBSFN1: RLC A ;ROTATE LEFT JNC KBSFN1 ;UNTIL FIRST BIT FOUND JZ KBSFN4 ;PROCESS 12 IF UNIQUE JMP KBSFN3 ;ELSE USE ONLY 10 ROWS KBSFN2: MOV R4,A ;HOLD R11 DATA IN R4 MOV R1,#KARRAY+22 ;NDX TO ROW 12 MOV A,@R1 ;FETCH NEW DATA JNZ KBSFN3 ;SKIP IF R11 AND R12 KEYS MOV A,R4 ;RECALL R11 DATA JMP KBSFN5 ;AND CHECK FOR MULTI ;USE ONLY 10 ROWS OF NEW DATA KBSFN3: MOV R2,#10 ;PROCESS ONLY 10 ROWS JMP KBSFN6 ;THIS SCAN ;USE ALL 12 ROWS OF NEW DATA KBSFN4: MOV R2,#12 ;PROCESS TWELVE ROWS KBSFN6: MOV R1,#KARRAY ;START OF KARRAY KBSCAN4: MOV A,@R1 ;FETCH NEW DATA INC R1 ;NDX TO OLD DATA XCH A,@R1 ;XCHG NEW WITH OLD XRL A,@R1 ;LOCATE CHANGES JZ KBSCAN6 ;SKIP IF NONE CLR F0 ;SET KEY MAKE MOV R3,A ;SAVE A COPY ANL A,@R1 ;FIND THE MAKES JZ KBSCAN5 ;SKIP IF NONE CALL SCANCODE ;PROCESS MAKES KBSCAN5: MOV A,@R1 ;XOR COMPLEMENT CPL A ;O testing for cursor ; update access. If found, set R0 to 2* (NMI - 32) and place ; a 2 in register R1. ; ; Add a RMODE in which, if NMI is active, a byte of ROM DISK ; data is returned. ; ; The RMODE function will be disabled by the NMI acknowledge, ; i.e. reading RADDR again. ; ; PAGE.TBL - This table has one entry for each page ; of a bank of rom. Each entry copies the contents ; of R1 which is the target ofset within the page. ; The is followed by the incrementing of R1 which ; brings the entry size up to four bytes. The entry ; ends with a "long jump" to the destination in the ; new bank. ; PAGE.TBL: DB PG0 - PAGE.TBL DB PG1 - PAGE.TBL DB PG2 - PAGE.TBL DB PG3 - PAGE.TBL DB PG4 - PAGE.TBL DB PG5 - PAGE.TBL DB PG6 - PAGE.TBL DB PG7 - PAGE.TBL PG0: MOV A,R1 ;COPY OFST FROM R1 INC R1 ;BUMP OFST JMP 0 ;IN BANK 1 PG1: MOV A,R1 ;COPY OFST FROM R1 INC R1 ;BUMP OFST JMP 100H ;IN BANK 1 PG2: MOV A,R1 ;COPY OFST FROM R1 INC R1 ;BUMR0,A ;AND STORE IN PAGE MOV R1,#2 ;BYTE OFST TO 2 MOV A,R6 ;RESTORE A RETR ;AND DONE ROM.DSK3: RETR ;ALLOW BANK 1 TO BE SELECTED ; ; Each Sector of the Rom Disk must be formatted with the ; following header: ; ; MOVP A,@A ;FETCH DATA ; RET ;AND RETURN ; ; ; MACRO SETUP - Hold the data in the macro while determining ; the break status. Then offset data as required. Build the ; control byte and store it in the macro. Note that normal ; arrow key usage will result in a single key invocation of ; the macro. Exit back to SCANCODE to debounce and to ; restore the keyboard scan state. ; MACSET: XCH A,R0 ;SWAP ADDR TO R0 JF0 MACSET1 ;SKIP IF BREAK JMP MACSET2 ;USE NEW DATA MACSET1: MOV A,#80H ;ADD BREAK BIT TO ORL A,@R0 ; PREV MAKE CODE MACSET2: MOV @R0,A ;STORE THE DATA ;Setup Macro Control Word CLR A ;CLEAR ACCUM JF0 MACSET4 ;SKIP IF BREAK MOV A,R7 ;RECALL STATE ANL A,#21H ;KEEP RS & NUM JB0 MACSET5 ;SKIP IF RS MACSET3: JB5 MA! yG! Jȱ!  JF!8 y8Gɰ!<‡(F!H  ɱ!  yOJɱO>yF!p y(! #G:ҷ x ((y2x :J 7 C 7FyFxFR F!X\(>FBYOJ(ȱF**{z0{~#"^O:ҷ y<88AOXy :ҷD-X:O!\ NX#2fGƐ'@'OXxƐ'@'OXNX# Xz8̇O! NX#NX XX G:ҷOx( yWOXSXPXy*|} XXs:ȷ(!"< <2*× :!~(~_͐~ #Ú ͐_͐! 6͐! 6͐͐͐͐͐͐~# x"#!y6 . x/Gy/O>)b)O, Z=D33=D)i, =D|}*p·!"**"‘!"*~#"/:_<2!~: CSET6 ;SKIP IF NMLK MACSET4: ADD A,#04H ;SET DATA DEC R0 ;BUMP ADDR TO CTL MOV @R0,A ;AND STORE BYTE RET ;BACK TO KEYSCAN MACSET5: XRL A,#02H ;CLR RS, SET 0 & 1 JMP MACSET3 ;AND CONTINUE MACSET6: XRL A,#58H ;CLR NUM, SET 6, 5, 4, & 3 JMP MACSET4 ;AND CONTINUE ORG 7FFH ; DB 0H ; END et data as required. Build the ; control byte and store it in the macro. Note that normal ; arrow key usage will result in a single key invocation of ; the macro. Exit back to SCANCODE to debounce and to ; restore the keyboard scan state. ; MACSET: XCH A,R0 ;SWAP ADDR TO R0 JF0 MACSET1 ;SKIP IF BREAK JMP MACSET2 ;USE NEW DATA MACSET1: MOV A,#80H ;ADD BREAK BIT TO ORL A,@R0 ; PREV MAKE CODE MACSET2: MOV @R0,A ;STORE THE DATA ;Setup Macro Control Word CLR A ;CLEAR ACCUM JF0 MACSET4 ;SKIP IF BREAK MOV A,R7 ;RECALL STATE ANL A,#21H ;KEEP RS & NUM JB0 MACSET5 ;SKIP IF RS MACSET3: JB5 MA1ê>zCOPYRIGHT (C) 1981, AVOCET SYSTEMS, INC.1 Úéïöp&v> r ;Í Ï × g." [x( {š~#o}oҤ=ÊK[ ** K  j+qpERt{!6!"y?X{*"{sH"ȯ2͋OY , ? X X; (g(!6 # !w;g(# (: ;(0 ̈́(! ~ (ͷkb))))_y BK{(80 # # ( [{ #z+++ ̈́(!6  y{- [{ͷ_z;W{0 D2>(!~W(((2>̈́(!( y2>ͥ(ͥ(=ɯ2F:>(>F2F8:F!w#  (w!6( y*w#"; :͇(! "!p E ! EE! #E`iR+| }(F<(ȵ( ! EF! EFxF! JG@Jɱ " ͩ_<2!w OUTPUT FILE WRITE ERROR $:b a " ͩ_<2!wǴ x ڈ 0w#> w#Ð !͏ O :· y@ù ++ . > + ¼ ~.# > + ~#!{ 7ɘ fO>G |}!Ṕ'/7?v^VFEMgoDO_GWK[{**CSs""80( "*2:EXAFEXX EI SPHLDI XCHGPCHLXTHLRET HLT CMC STC CMA DAA RAR RAL RRC RLC NOP SPIXSPIYXTIXXTIYPCIXPCIYLDAISTAIDARSTARNEG RLD RRD RETIRETNIM0 IM1 IM2 LDI LDIRLDD LDDRCCI x9 G*lö <8q TDRSIYDSIXDSSPDSDEDSBCDLIYDLIXDLMODANDORXORNOTSHLSHRHIGHLOWEQNELTLEGTGE2< 2? !q "o  ͞" :<  >U23 2 2 * | G G * |5 ?b !ͼG * |z ?z * |e ͒ ?͒ * |} ͪ ?ͪ * |Õ  !ͼ?ͪ * | !ͼ? * |(  ) ?>S23 ͞4 " " >S23 " >S23 ɯ!ly!\!X: F!,X!\!X!/X!\!X!2XmC:2 ʴ:E ʜ!5XIRC:D IRC!"222!8! 8 SOURCE FILE NOT FOUND $ UNABLE TO CREATE OUTPUT FILE $ASMHEXPRNMIK=:2 OFI:1 j:D jFI2E 2D <22 2C 21 <22!F##~ ʝ#‘#~ ʝO#~:y@22#~ ʻ+~OXYD LCN"#ɯ21 2C 21 2C >2D 22 >2D >2M ~O*8 *{z!V8*8 X"8 6+++ SYMBOL TABLE FULL $*: ʳ2= G[ʓO qO ~ ‡===Obk ɯ2" n"*"&*H }_|W!s"(*&}:J <_*(a*&}o|gڸ"&*&!"&:J <2" ****)"*Ï",".+)"0:(O!s{#)%2: w#: w#6*F ": ! ] !-": "@ ": gI>M23 Î:ʎ* _ʎ>P23 Î:t@Ž2Î*8 "!Z "@ Q : %! ] ʪ>O23 %~2- #~2. := 2*"~#~%+~%#~>O23 %=_!^#V"-k3t Q" S23 >R23 Mc @|#ʜPʭRc RQc 0ʖʖWoN f * tc 080_k>S23 c 080_k*" N f * * ~#  ,; ȯ<ɯ22!""]y2":3 p* ~,V>2* #" ]y2":3 p|R23 >S23 >J23 ڣң7:o&N:!3 ~ 6W!" ::>2 %>2 2 >2  >S23 | }͞DM͞ց, _!4 ^#V>S23 (Z _ h q z   4{ozg4{ozg4{ozg4{ozg4x/gy/o4xҘ 7î x4 )Ø xҮ 7Ø x4 |g}o4!s4!s4PYa4h&4i&4x(y(.x.y.({z.(yx.(yx.({z.(!4!4üO>Gɯ2= 0P:$Ad[9.9'ʨ"ʨ+-*/@"%3g" * ͼ&" |*o !ҳV+^+"o >S23 !*o !q#s#r"o !8 EVALUATION STACK FULL $ GÑ* ~0:AG* " Ñ!%!"6 >2 QÑ!%  ! ": ! lʙ*F ": ! l!-": ˆ~2 #~2! +*@ }|ґ:? 2? Ñ!" :< 2< ÑV#^!-": " |* ~2 #F#2! " Ñ: 2! x2 #" Ñ.&.&.&.&" |ů2> > 2 !  X! A/[/w#:> <2> * ~#" .$0C:! "6 2 * "4 0چ:zAچHʓQʓG҆* ~#" \+" +: »~H¡!"6 ûQ¯!"6 ûB»!"6 * *4 " "4  x * ~#" A *6 a_*}27:(_a*,"2*.}ʂ>24! "5*,*2{zi*0}|]͕*.+".:(G:4]> ̓!44*7,*56 #6 ! #*,##",*5ʑ6 #=Š"5^#V*5~Gxʯ#~ñ>  ¤6 #pp"5{z}O|G{ozg}|++++N#F+{zd^#V`is-++{zd^#V`isJ-{zdO~q#O~q+O~q#O~qG~Oxʓyʙ #ɹȯ<7ɯ<*K #"9*F ~*+{z}|~O ç++";=7 NO ROOM FOR SYMBOL-TABLE SORT $ͬ FROM ""&11 AVOCET SYSTEMS 8048 CROSS-ASSEMBLER, VERSION 1.62 ${…!&{7sr*~wN(:wz!&{7 >*͜*m0"*" *F#!!7=!-": *-"8 W :J <2" 2 2B 2 !" "*-"F !B+vU,!B+XX+~ A#6.#X!B+z%!+y)2 2, 2' 2< 2<2!"# > 23 ` §: ›},=,! X: ʎ ʘ& ʎ;ʘ&Q c !6:6f >2*"~ʎ! ~ #x >L23 %2 :2 >2 ͥ%2 :2 >2 ͥ%%: …:MZeÅ:- G::- G::. %: 8G:…x ʍʚÅ>2:- H>2:- HG:ʲ}%:…: …:͕}G:- %:…:…* :- }|ʍʍ*:|"|}|G:- %:…:' g gO>2yggÅ:- xq%:…:G:. …:- %:…: ʫʱÅ:- >2:. G:%:…:G:- …>2xÅ:- :. >>%:…:…* }<2|ʍʍ$|G:O}y}:- G:%: …: lwÅ>2:- :ʄŒG:. …>2Ä%:…: ʹʾÅ>::%: …: …>%:…:…:}* }< |ʍʍ$:}:- %: I ʌ ʞ ʾ   Å:h m w  ʇ Å>#>2>::>B: …>2>: ʮ ʶ Å:::  Å::: …>b: …>2>%f N :" G:J <* &:J <2" &: '!B+v!B+z%:H OB+`%': '!+y:H O+`%'c G* ~ # i%*H >Gy!%4*"~%N * |ʡ%>ͧ%%G!$~ ں%>C23 %4*"#""p:%ʲ%G:$%*"~/w%!%~ʲ%5!$%5*"+""%: ':< &>U23 2< :3 &&:1 &:&:3 2 5&!4> 2 !  X:' €&* ! zp{p# : Gw&pw& j&! *&*( ! zp{p! *&: ':< ʯ&>U23 2< :3 &:1 ':':3 2 ! v! *': 'G * "4 *4 4)*4 #"4 &*# : O * " w(:, d: /2 n'!&""62$2%!6C!6!"2, 2!" "@ >2:J <2" d:2 ': '͎):E ¨'!( ~m#‹'>m–'F'>Sm>9m> m> m>m¾'F:C '!+y!+g,X*8 "K :D  (>g'F*!(zp{p(=*8 !(zp{p(=:n(G2L( dL( y2)x'G02)x02) )=(=ڌ({*{z"!" LAST ADDRESS USED IN THIS ASSEMBLY IS: XXXX$ NEXT SYMBOL ADDRESS IS: XXXX$ 8048 ASSEMBLY COMPLETE $:00/ADD`ADDCpXRLANLPSORL@CANLDORLDCALLJMPCLRCPLDAW ENT0uNOPRETxRETI(RETRRL RLC RRw RRCg STOPeSWAPG JMPPwRADDEC7DIS5 6EN% DJNZ IN" INC INS 'JB0'JB12'JB2R'JB3r'JB4'JB5'JB6'JB7JC'JF0'JF1vJNCJNI8JNT0&JNT1FJNZJTF7JT06JT1VJZYJNIBFXJOBFMOVMOVDMOVP)MOVP3MOVXWOUTOUTLSELSTRTXCHXCHDEQUDSDBDWENDORGPAGEIFELSE  ENDIF SET  OPSYN  PGLEN  WIDTH TITLE SBTTL INCLUD MOD21 MOD22 MOD41 MOD41ALIST NOLIST,0,1 DB 9,'TITLE',15,0,1 DB 9,'SBTTL',16,0,1 DB 10,'INCLUD',17,0,1 DB 9,'MOD21',18,0,1 DB 9,'MODJB7',0F2H,0,14 DB 6,'JC',0F6H,0,14 DB 7+CODE2,'JF0',0B6H,0,14 DB 7+C PAGE SOURCE FILE NAME: ---- SYMBOL TABLE ---- END STATEMENT MISSING $ END ;***** *** DB 8,'JNT1',046H,0,14 DB 7,'JNZ',096H,0,14 DB 7,'JTF',016H,0,14 DB 7+CO: !&!Å:…:͕} : …:͕}<%: …:…:- %: h!x!Å:…:: …:%: …: …>%:ʳ! !Å: …:!!8: …>2>}>2>%:…:6"6"O>2y6"6"O>2y6"6"Åx%:…:UY"E Y"Åx%: …:x"ʀ"Å:(: %: …:…:0:- =_!"^#V###Z$$$$%%%###+#%C%N#""##""2'!6:J <2" '> #> #> #>22 %N * &}$#.}=2J 'N * |F#&} @#. >H#."H ':B x#c * +|Cx#>2>2B Ø&>I23 Ø&:ʢ#N * *@ s#r* "( >2' %>S23 %:#:ʢ#*~@wÇ#>M23 %:ʢ#Q ! ] #*@ XØ&>U23 %N * "# %! 2 c '0$"0$f N : <2 : w#,$%* G: <2 ~#~ %5$#" c ,$%! 2 N * r#s#: 2 ,a$%:B $c !$ʜ$f N * "* "( !)zp{p##>/2' 2, %2B Ø&; ȷȯ2' %c $%000001FF *****XXX LINES CONTAINED ERRORS ***** $G:2 x:!G2!xY)*#^a)͎)"2 ": ~)͎)*"2 <2 =_! w:!): OG! 6:#xp:O:p:O:pp Op)y/<2" ! *:D =*=*:~_~ #*~g~ #* AVOCET SYSTEMS 8048 CROSS-ASSEMBLER - VERSION 1.62 SOURCE FILE NAME: AME: ',32H,0,14 DB 7+CODE2,'JB2',52H,0,14 DB 7+CODE2,'JB3',72H,0,14 DB 7+CODE2,'JB4',92H,0,14 DB 7+CODE2 5', 2H,0,14 DB 7+CODE2,'JB6',0D2H,0,14 DB 7+CODE2,'JB7',0F2H,0,14 DB 6,'JC',0F6H,0,14 DB 7+CODE2,'JF0',0B6H,0,14 DB 7+C PAGE SOURCE FILE NAME: ---- SYMBOL TABLE ---- END STATEMENT MISSING $ END ;***** *** DB 8,'JNT1',046H,0,14 DB 7,'JNZ',096H,0,14 DB 7,'JTF',016H,0,14 DB 7+CO            !!""##$$%%&&''