1. Move down all of the ram variables to the top of the 6845's registers to create a few more available bytes. 2. Add Insert/Delete to the arrow key functions assuming that its code word is simply insuring that the correct break code is sent. 3. Modify MACSET to simply add 80H to the existing data on a break. 4. Add the cursor disable functions. 5. Inhibit AUTO REPEAT following a macro. Since the correct scan code is being sent on the break, does the RS and NUMLOCK status really have to be correct at this time ? If not, why not just send the break code without bracketing it with RS and NMLK. This will end the process with a break and prevent AUTO REPEAT. Note that whatever solution is used, AUTO REPEAT will not work. The character repeated with be the RS make at the end of the macro. 6. Add the + and - keys to the ARROW functions. * * * * * WIDTH 96 ;************************************************ ;* * ;* Morrow Designs Pivot * ;* Keyboard Processor Firmware * ;* * ;* Author: Michael Stolowitz * ;* Revision: 6.00 * ;* Date: 6/14/85 * ;* Time: 4:30 P.M. * ;* * ;************************************************ ; ; Revision History: ; ; .00 6/14 ROM DISK - To read the disk, request an NMI ; with an ofset of 40H 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. ; ; PROPOSED: ; ; Generate a Cursor Off NMI an inhibit ; cursor update interrupts if: ; R10 BP = 01 ; R10 > R9 ; R10 > R11 ; Generate Cursor update NMI is situation ; is cleared. Assume that R9 is written ; first. Also, multiple off NMIs if both ; R10 and R11 are written. ; ; Added shifted arrow functions - WHAT IF ; MULTIPLE MAKES OR BREAKS ON A SINGLE SCAN ? ; ; ;************************************************ ;* * ;* 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 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 ;Processor Data Enable AUX.ENA EQU 02H ;Extra Port Enable PA.ENA EQU 03H ;Processor Address Enable ; ; DSP.DFLT EQU 0C5H ;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: ; 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 ELTIME0: EQU 3BH ;EL PANEL TIMEOUT LSB ELTIME1: EQU 3CH ;EL PANLE TIMEOUT MSB NMIREQ: EQU 3DH ;NMI REQUEST PAGE: EQU 3EH ;ROM DISK SECTOR REGISTER ; ; KARRAY : Array[Row1..Row12] of [NewData,OldData] ; KARRAY: EQU 40H ;KB DATA ARRAY ; ; FIFO : Array[0..31] Of ScanCode Absolute 60H ; ; E0 is used so that overflow will set CRY ; FIFO: EQU 0E0H ;FIFO - 20H BYTES TO END RAM ; ;BUF.LEN: EQU 20h ;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 -120 ;120 BLINK PERIODS = 1 MIN EL.K1 EQU -10 ;10 MINUTES 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 ;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 20 ;ALT-CLOCK ICON IAPHONE$: EQU 22 ;ALT-PHONE ICON IADISK$: EQU 24 ;ALT-DISK ICON 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 ; ; KB INIT - Initialize the keyboard ; KBINIT: SEL RB0 ;BANK 0 REGISTERS MOV R7,#0 ;CLEAR KB STATE SEL RB1 ;BANK 1 REGISTERS 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 ; ; 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 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 MOV R0,#ELTIME1 ;SET NDX TO CNTR MOV @R0,#EL.K1 ;AND LOAD INIT VALUE ;INITIALIZE NMI REQUEST MOV R0,#NMIREQ ;SET NDX TO REGISTER MOV @R0,#0 ;AND CLEAR REQUEST ;INITIALIZE BANK 1 REGISTERS CALL KBINIT ;INITIALIZE THE KB ;INITIALIZE NMI STATUS MOV R4,#0FFH ;TURN ON 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. Scan keyboard ; Skip if in debounce ; Read keyboard ; 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 FIFO-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 DRVOFF0: 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: MOV A,#LOBAT1$ ;LOAD NMI STATUS CODE CALL NMI ;SET STATUS AND PULSE NMI SEL RB0 ;IN BANK 0 MOV R0,#34H ;KB ENCD ROW 13 MOVX @R0,A ;TURN OFF FDC & DRV 0 MOV R0,#38H ;KB ENCD ROW 14 MOVX @R0,A ;TURN OFF DRV 1 MOV R0,#DS.STB ;SET NDX TO DISP CTL MOV A,#EL.B ;A = ELEN ONLY MOVX @R0,A ;AND THE DISP CTL PORT PWRFAIL2: DIS I ;DISABLE EXT INTERRUPT DIS TCNTI ;DISABLE CNTR INTERRUPT JMP PWRFAIL2 ;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 JMP MAIN ;AND DONE ; ; TIMER INTERRUPT - A sync pulse has been received from ; the LCD 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 @R0,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 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 inlcude ; 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 ;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 EXIT ;R8 READ MODE REG DB EXIT ;R9 READ SELECT DB RSTAT ;RA READ STATUS DB EXIT ;RB LIGHT PEN CLEAR DB RMODE ;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 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 Addres ; 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 EXIT ;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 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 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 ;R13 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: MOV R0,#ELTIME1 ;SET NDX TO EL TIMER MOV @R0,#EL.K1 ;AND RESET IT 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 ;CMPL 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: MOV A,R5 ;STATUS REG TO A XRL A,#09H ;TGL SYNC & ENABLE MOV R5,A ;RESTORE STATUS ANL A,#09H ;MASK TO ENA & SYNC CALL RDATA ;REL CPU WITH DATA JMP EXIT1 ;AND EXIT 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 BITS 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 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 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 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 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 ; ; * 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.REG ;W10 DB WR.REG ;W11 DB WR.REG ;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 WEXIT ;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: MOV A,R6 ;RESTORE A MOV R0,#ELTIME1 ;SET NDX TO EL TIMER MOV @R0,#EL.K1 ;AND RESET IT 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.CUR: MOV A,R5 ;FETCH DISPLAY STATUS ORL A,#80H ;TURN ON 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 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 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 ;RCRTADDR from previous page. RADDR: 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 JB7 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 CLR A ;CLEAR ACC CALL RDATA ;VALUE TO HOST 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 ; ; 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,R2 ;FETCH FIFO-IN INC A ;BUMP PTR JNZ SNDSCAN1 ;SKIP IF NOT OVFL MOV A,#FIFO ;WRAP THE FIFO SNDSCAN1: 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 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 Delta ; 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,32H ;ROW9 DB 1AH,00H,X15,07H,15H,23H,19H,31H ;ROW8 DB X03,2BH,X16,06H,14H,22H,X17,30H ;ROW7 DB 0FH,X19,0CH,04H,12H,20H,0BH,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 ;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 MOV R0,#REPEAT ;SET NDX TO RERPEAT MOV @R0,#0 ;AND RESET IT MOV R0,#ELTIME1 ;SET NDX TO EL TIMER MOV @R0,#EL.K1 ;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 CALL SENDSCAN ;DATA TO FIFO JMP SC7 ;NO DEBOUNCE ; ; 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 ; ; START OF FIFTH PAGE OF ROM ; ; ; CONVERT - The SCANCODE routine 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: ; ; b7 b6 b5 b4 b3 b2 b1 ; ls rs ctl num ins scroll alt ; ; The Rom Bios will handle: ; ; Left Arrow / Home ; Right Arrow / End ; Up Arrow / Page Up ; Down Arrow / Page Down ; Print Screen ; ORG ROM.ORG+400H ;TABLE AT X00 CONVERT: JMPP @A ;INDIRECT THRU TBL ; ; STATE KEYS - This routine will maintain the states ; of LS, RS, CTL and NUM LOCK. ; CONV.LS: MOV R0,A ;HOLD ENTRY IN R0 MOV A,R7 ;FETCH STATE JF0 CONV.LS1 ;SKIP IF BREAK ORL A,#80H ;SET LS BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CONV.LS1: ANL A,#7FH ;CLR LS BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CONV.RS: MOV R0,A ;HOLD ENTRY IN R0 MOV A,R7 ;FETCH STATE JF0 CONV.RS1 ;SKIP IF BREAK ORL A,#40H ;SET RS BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CONV.RS1: ANL A,#0BFH ;CLR RS BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CONV.CTL: MOV R0,A ;HOLD ENTRY IN R0 MOV A,R7 ;FETCH STATE JF0 CNV.CTL1 ;SKIP IF BREAK ORL A,#20H ;SET CTL BIT MOV R7,A ;RESTOEE STATE JMP ARG1 ;AND SEND FIRST ARG CNV.CTL1: ANL A,#0DFH ;CLR CTL BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CONV.LCK: MOV R0,A ;HOLD ENTRY IN R0 MOV A,R7 ;FETCH STATE JB5 ARG1 ;SND NUM LOCK IF CTL JF0 CNV.LCK2 ;SKIP IF BREAK JB7 CNV.LCK1 ;SEND SCROLL LOCK JB6 CNV.LCK1 ; IF EITHER SHIFT ANL A,#0FBH ;CLR SCROLL BIT XRL A,#10H ;TOGGLE NUM LOCK MOV R7,A ;RESTORE STATE JMP ARG1 ;SEND NUM LOCK CNV.LCK1: ORL A,#04H ;SET SCROLL BIT MOV R7,A ;RESTORE STATE JMP ARG2 ;SEND SCROLL CNV.LCK2: JB2 ARG2 ;BREAK SCROLL LOCK JMP ARG1 ;BREAK NUM LOCKLOCK CONV.DEL: MOV R0,A ;HOLD ENTRY IN R0 MOV A,R7 ;FETCH STATE JF0 CNV.DEL2 ;SKIP IF BREAK JB7 CNV.DEL1 ;SEND INSERT IF JB6 CNV.DEL1 ; EITHER SHIFT ANL A,#0F7H ;CLR INS BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;SEND DELETE CNV.DEL1: ORL A,#08H ;SET INS BIT MOV R7,A ;RESTORE STATE JMP ARG2 ;SEND INSERT CNV.DEL2: JB3 ARG2 ;BREAK INSERT JMP ARG1 ;BREAK DELETE CONV.ALT: MOV R0,A ;HOLD ENTRY IN R0 MOV A,R7 ;FETCH STATE JF0 CNV.ALT1 ;SKIP IF BREAK ORL A,#02H ;SET ALT BIT MOV R7,A ;RESTORE STATE JMP ARG1 ;AND SEND FIRST ARG CNV.ALT1: ANL A,#0FDH ;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 R0,A ;HOLD ENTRY IN R0 MOV A,R7 ;FETCH STATE JB5 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 R0,A ;HOLD ENTRY IN R0 MOV A,R7 ;FETCH STATE JB4 ARG2 ;SKIP IF NUM LOCK ARG1: MOV A,R0 ;RECALL ENTRY INC A ;ADDR FIRST ARG JMP ARGS ;AND CONTINUE ARG2: MOV A,R0 ;RECALL ENTRY ADD A,#2 ;ADDR SECOND ART ARGS: MOVP A,@A ;FETCH THE ARG JF0 ARGS2 ;SKIP IF KEY BREAK JMP ARGS3 ; ARGS2: ADD A,#80H ;ADD BREAK BIT ARGS3: JMP SENDSCAN ;SEND THE BREAK ; ; ARROW KEYS - If NUM LOCK is active, these keys ; send the arrow key scan code. If not, they ; send either the arrow key or function key ; depending on the shift stat. ; ARROW: MOV R0,A ;HOLD ENTRY IN R0 MOV A,R7 ;FETCH STATE JB4 ARG1 ;IF NUM LOCK JB7 ARG2 ;IF LEFT SHIFT JB6 ARG2 ;IF RIGHT SHIFT JMP ARG1 ;IF UN-SHIFTED ; ; 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 R0,A ;HOLD IN R0 MOV A,R7 ;FETCH STATE JB1 ICONS1 ;SKIP 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 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 X04: DB CONV.DEL ;DELETE KEY, 5.0 DB 053H ;DELETE DB 052H ;INSERT X05: DB CTLKEYS ;BREAK, 4.4 DB 00DH ;= 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 049H ;9 X14: DB NUMPAD ; 10.7 DB 033H ;, DB 052H ;0 X15: DB NUMPAD ; 8.2 DB 035H ;/ DB 04EH ;+ X16: DB NUMPAD ; 7.2 DB 027H ;; DB 04AH ;- X17: DB NUMPAD ; 7.6 DB 34H ;. DB 53H ;. X18: DB ARROW ;FUNCTION OF SHIFT, 5.6 DB 4BH ;< DB 47H ;Home X19: DB ARROW ; 6.1 DB 4DH ;> DB 4FH ;End X1A: DB ARROW ; 3.6 DB 48H ;^ DB 49H ;Page Up X1B: DB ARROW ; 5.2 DB 50H ;V DB 51H ;Page Down X1C: DB CTLKEYS ;Print Screen, 10.1 DB 29H ;` DB 37H ;* X1D: DB CONV.ALT ;ALTKEY, 1.7 DB 38H ; ; ; START OF SIXTH PAGE OF ROM ; ; FRAME - This page of the rom 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 is cursor register has ; been updated since the last end of frame. ; FRAME1: 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 MOV A,#CURSOR$ ;LOAD NMI STATUS CODE 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 the 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 FRAME3 ;SKIP IF NOT ZERO ;RE-INITIALIZE BLINK TIMER 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 CURRENT VALUE ANL A,#EL.B ;MASK TO EL BIT SEL RB0 ;IN BANK 0 MOV R0,A ;HOLD OLD VALUE IN R0 JMP FRAME25 ;SKIP TO BLINK FRAME22: SEL RB0 ;IN BANK 0 MOV R0,#ELTIME1 ;SET DNX 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 MOV A,@R0 ;FETCH NEW VALUE JNZ FRAME24 ;DISPLAY ON ;TURN EL PANEL OFF FRAME23: MOV R0,#0 ;NEW VALUE TO R0 JMP FRAME25 ; ;TURN EL PANEL OFF FRAME24: MOV R0,#EL.B ;NEW VALUE IN R0 JMP FRAME25 ; ;PROCESS BLINK CONTROL FRAME25: SEL RB1 ;BANK 1 REGISTERS MOV A,R7 ;FETCH DISPLAY CTL SEL RB0 ;BANK 0 REGISTERS XRL A,#BLINK.B+40H ;INVERT BLINK AND ENABLE JB6 FRAME26 ;SKIP IF DISABLED ANL A,#BLINK.B ;MASK TOGGLED BLINK ORL A,R0 ;MERGE NEW EL BIT JMP FRAME27 ;GO UPDATE FRAME26: MOV A,R0 ;FETCH NEW EL BIT ;UPDATE SHADOW AND CONTROL PORT WITH DATA IN R0 FRAME27: SEL RB1 ;IN BANK 1 DIS I ;LOCK OUT INTERRUPTS XCH A,R7 ;SWAP NEW WITH SHADOW ANL A,#NOT(EL.B+BLINK.B) ;MASK TO KEEPERS ORL A,R7 ;MERGE NEW BITS MOV R7,A ;UPDATE SHADOW EN I ;UNBLOCK INTERRUPTS SEL RB0 ;IN BANK 0 MOV R0,#DS.STB ;SET NDX TO DISP CTL MOVX @R0,A ;AND UPDATE PORT ;PROCESS LO BATT 2 NMI MOV A,R5 ;FETCH PWR STAT JB0 FRAME3 ;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 ;********************************************************** ;* 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. ;********************************************************** 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 KBSCAN1 ;SKIP IF ZERO DEC A ;DECR BALANCE MOV @R0,A ;AND RESTORE JMP MAIN ;TILL NEXT FRAME ; ; 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 R0,#AUX.ENA ;SET NDX TO AUX PORT MOVX A,@R0 ;READ PORT TO A ANL A,#40H ;MASK TO FDC-ON ADD A,#04 ;ADD FIRST KB ROW MOV R0,A ;AND MOVE TO NDX MOV R1,#KARRAY ;FIRST KEY ARRAY BYTE MOV R2,#12 ;FOR TWELVE ROWS KBSCAN2: MOVX @R0,A ;SELECT KB ROW NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP ; MOV A,#-2 ;FETCH ROWS LEFT ; ADD A,R2 ;COMPARE WITH 2 ; JC KBSCAN12 ;SKIP IF GREATER ; MOV R3,#40H ;LOAD DLY COUNT ;KBSCAN11: DJNZ R3,KBSCAN11 ;LOOP FOR DLY CNT KBSCAN12: MOVX A,@R0 ;READ KB ROW DATA MOV @R1,A ;AND SAVE IN ARRAY INC R0