;EL timeout set to ten minutes. TITLE "MORROW DESIGNS PIVOT - KEYBOARD PROCESSOR FIRMWARE" SBTTL "REVISION 4/29/85 6:00 PM 5.02" WIDTH 96 ;************************************************ ;* * ;* Morrow Designs Pivot * ;* Keyboard Processor Firmware * ;* * ;* Author: Michael Stolowitz * ;* Revision: 5.02 * ;* Date: 4/29/85 * ;* Time: 06:00 P.M. * ;* * ;************************************************ ; ; Revision History: ; ; .00 4/18 Removed switch port WR.19 ; ; Added NMI code for ALT-CALC ; ; Moved Blink Enable to Display Control Bit 6 ; ; Modified Display Control Bit 4 for Hi-Res ; asserted in 40x25 alpha-numeric mode. ; ; Swap CLOCK and PHONE NMI codes. ; ; Added WR.24 for attribute control. Bit 0 ; goes directly to ATENA, P24. Bit 6 goes to ; status register. If Bit 6 is low, ATENA is ; pulsed on blink timeout. Defaults to pulse ; mode enabled. ; ; Added WR.25 for Drive Off pulsing. Bits 4 & 5 ; will turn off drives 0 & 1 respectively. Bits ; are copied during interrupt to display status. ; They are cleared in the not end of frame loop, ; with the corresponding drives being pulsed if ; its bit was set. ; ; Added WR.26 - Keyboard Reset. Clears all of the ; keystates and empties the FIFO. ; ; Move EL Timeout inhibit to bit 2 of R23. Data ; is stored in bit 2 of display status. On RSTAT, ; data is now masked to bits 0 and 3. ; ; R21 works for FDC-OFF only. Access FDC to get ; it on. FDC-OFF also installed in drive off ; register WR.25, bit 1. ; ; .02 SET EL_K1 back to -10 (bjg) ; ;************************************************ ;* * ;* 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 CURSER 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 ; ; DATA MEMORY MAP ; 20 - 35H 22 Registers of 6845 ; 36H SAVE1 ; 37H SAVE2 ; 38H BLINK ; 39H DEBOUNCE ; 3AH REPEAT ; 3BH EL LSB ; 3CH EL MSB ; 3DH NMIREQ ; SPACE ; 40 - 57 24 Bytes of Key-Array ; 60 - 7FH 32 Bytes of FIFO ; CRT.REG: EQU 20H ;START OF 6845 REGISTERS 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 KARRAY: EQU 40H ;KB DATA ARRAY FIFO: EQU 0E0H ;FIFO - 20H BYTES TO END RAM ; ;BUF.LEN: EQU 20h ;FIFO LENGTH ; ;CUR.REG EQU 0EH ;CURSER 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 4H ;LONG - 4 FRAME TIMES ;NMI STATUS CODES BAT2.NMI: EQU 2 ;LO BATT 2 CUR.NMI: EQU 4 ;CURSER UPDATED BAT1.NMI: EQU 6 ;LO BATT 1 CHANGED AC.NMI: EQU 18 ;AC-ON CHANGED 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 CURSER 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. Poll power status port ; Process Lo Batt 2 if set ; Check for AC-ON rising ; 3. Poll NMI request register ; ; AT END OF FRAME: ; 1. Clear end of frame flag. ; 2. Send NMI if curser 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 1 NMI is 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 MOV A,R5 ;COPY DISPLAY STATUS ANL A,#0CDH ;CLR DRIVE OFF BITS XCH A,R5 ;SWAP WITH ORIGINAL 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 ;PROCESS DRIVE OFF 0 DRVOFF0: 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 2. ; 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 JB1 PWRFAIL3 ;SKIP IF LOW BATT 2 XCH A,R5 ;NEW VALUES TO PWR STAT ;CHECK FOR AC-ON RISING JB0 PWRFAIL2 ;AC WAS ON MOV A,R5 ;RECALL NEW STATE JB0 PWRFAIL1 ;AC-ON NOW SET JMP NMIRQ ;ELSE DONE PWRFAIL1: MOV A,#AC.NMI ;NMI CODE OF AC-ON CALL NMI ;NMI TO CPU PWRFAIL2: JMP NMIRQ ;AND DONE ;LO BATT 2 PWRFAIL3: MOV A,#BAT2.NMI ;LOAD NMI STATUS CODE CALL NMI ;SET STATUS AND PULSE NMI PWRFAIL4: DIS I ;DISABLE EXT INTERRUPT DIS TCNTI ;DISABLE CNTR INTERRUPT JMP PWRFAIL2 ;HANG FOREVER ; ; 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 ; ; 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 ; ; 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 EXIT ;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 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 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 TRANADR ;A19 DB TRANADR ;A20 DB TRANADR ;A21 DB TRANADR ;A22 DB TRANADR ;A23 DB EXIT ;A24 DB EXIT ;A25 DB EXIT ;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 ; WR.REG Write Register ; EXIT Return FFh - Illegal ; RD.18 Return NMI status code ; RD.21 Return Extra, Pop SAVE1* ; WR.18 End NMI, Pop SAVE2 ; ; WR.20 Write Display, Pop SAVE1* ; WR.21 Write FDC ON, 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 EXIT ;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 A,R6 ;RESTORE A MOV R0,#ELTIME1 ;SET NDX TO EL TIMER MOV @R0,#EL.K1 ;AND RESET IT 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 RSTAT: MOV A,R5 ;STATUS REG TO A ANL A,#09H ;MASK TO ENA & SYNC CALL RDATA ;REL CPU WITH DATA XRL A,#09H ;TGL SYNC & ENABLE MOV R5,A ;RESTORE STATUS 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 JMP EXIT1 ;AND EXIT 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 JMP EXIT1 ;AND EXIT 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 JMP EXIT1 ;AND END INTERRUPT RD.18: MOV A,R4 ;FETCH NMI STATUS ANL A,#7FH ;MASK ACTIVE FLAG CALL RDATA ;RETURN DATA JMP EXIT1 ;AND END INTERRUPT RD.21: MOV R0,#AUX.ENA ;SET NDX TO AUX PORT MOVX A,@R0 ;AND READ PORT CALL RDATA ;DATA TO CPU JMP WR.EXIT ;USE WRITE'S EXIT 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 CURSER 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 JMP WEXIT1 ;AND EXIT ;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,R0 ;RECALL NEW DATA ANL A,#04H ;MASK TIMEOUT DIS XCH A,R5 ;SWAP WITH DISP STAT ANL A,#0FBH ;CLEAR OLD BIT ORL A,R5 ;MERGE BITS MOV R5,A ;AND RESTORE STATUS JMP WR.EXIT ;TRANSIENT EXIT ;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: 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 ;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 MOV R0,#ELTIME1 ;SET NDX TO EL TIMER MOV @R0,#EL.K1 ;AND RESET IT 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,X07,00H ;ROW12 DB 3CH,3EH,40H,41H,43H,X0A,X08,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 ; ; 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.CTL1 ;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, the NMI status code for the ; key will be transmitted by the NMI routine. ; ICONS: JF0 ICONS2 ;SKIP IF BREAK ICONS1: INC A ;FIRST ARG MOVP A,@A ;FETCH NMI STATUS CALL NMI ;AND SEND CODE SEL RB0 ;RESTORE REG BANK ICONS2: RET ;AND DONE ; ; CALCULATOR ICON - Same as ICON KEYS except that ; a unique NMI code is generated for ALT-CALC ; CALCICON: JF0 ICONS2 ;SKIP IF BREAK MOV R0,A ;HOLD IN R0 MOV A,R7 ;FETCH STATE JB1 CALC2 ;IF ALT MOV A,R0 ;RECALL ADDR JMP ICONS1 ;NMI FIRST ARG CALC2: MOV A,R0 ;RECALL ADDR INC A ;BUMP ARG JMP ICONS1 ;NMI SECOND ARG 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, 12.6 DB 12 ;NMI STATUS CODE X08: DB ICONS ;PHONE ICON, 11.6 DB 10 X09: DB ICONS ;DISK ICON, 12.5 DB 14 X0A: DB CALCICON ;CALCULATOR ICON, 11.5 DB 16 ;CALC DB 20 ;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 curser ; update NMI, blink and EL timeouts, keyboard ; debouncing and keyboard scanning. ; ORG ROM.ORG+500H ;TABLE AT X00 ; ; FRAME1 - Generate CPU NMI is curser register has ; been updated since the last end of frame. ; FRAME1: SEL RB1 ;BANK1 REGISTERS MOV A,R5 ;FETCH DISPLAY STATUS ANL A,#80H ;MASK CURSER UPDATE JZ FRAME2 ;SKIP IF NOT SET XRL A,R5 ;CLR UPDATE BIT MOV R5,A ;AND RESTORE STATUS MOV A,#CUR.NMI ;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 ;UPDATE DISPLAY BLINK CONTROL SEL RB1 ;BANK 1 REGISTERS MOV A,R7 ;FETCH DISPLAY CTL JB6 FRAME21 ;SKIP IF BLINK ENABLED ANL A,#0DFH ;CLR BLINK BIT JMP FRAME22 ;AND CONT FRAME21: XRL A,#BLINK.B ;TOGGLE BLINK BIT FRAME22: MOV R7,A ;RESTORE CTL SHADOW ;PULSE ATTRIBUTE ENABLE IS MODE ACTIVE MOV A,R5 ;FETCH DISP STATUS JB6 FRAME225 ;SKIP IF INHIBITED ANL P2,#NOT ATENA.P ;PULSE LOW ORL P2,#ATENA.P ;AND THEN HIGH ;UPDATE EL PANEL TIMEOUT FRAME225: JB2 FRAME24 ;SKIP TIMEOUT DISABLED SEL RB0 ;BANK 0 REGISTERS MOV R0,#ELTIME1 ;SET NDX TO TIMER MSB MOV A,@R0 ;FETCH CURRENT VALUE JZ FRAME23 ;DISPLAY OFF DEC R0 ;SET NDX TO TIMER 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 EL TIMER MSB INC @R0 ;BUMP THE CNT MOV A,@R0 ;FETCH NEW VALUE JNZ FRAME24 ;DISPLAY ON ;TURN OFF DISPLAY FRAME23: SEL RB1 ;BANK 1 REGISTERS MOV A,R7 ;FETCH SHADOW ANL A,#NOT EL.B ;MASK EL PANEL OFF MOV R7,A ;AND RESTORE SHADOW JMP FRAME25 ;AND UPDATE SHADOW ;TURN ON DISPLAY FRAME24: SEL RB1 ;BANK 1 REGISTERS MOV A,R7 ;FETCH SHADOW ORL A,#EL.B ;SET EL PANEL ON MOV R7,A ;AND RESTORE SHADOW ;UPDATE DISPLAY CONTROL PORT FRAME25: MOV A,R7 ;FETCH SHADOW SEL RB0 ;BANK 0 REGISTERS MOV R0,#DS.STB ;SET NDX TO DISP CTL MOVX @R0,A ;COPY SHADOW TO CTL ;PROCESS LO BATT 1 NMI MOV A,R5 ;FETCH PWR STAT JB1 FRAME3 ;SKIP IF AC-ON JB2 FRAME26 ;SKIP IF LO BAT 1 JMP FRAME3 ;ELSE DONE FRAME26: MOV A,#BAT1.NMI ;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 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 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. ; KBSCAN3: MOV R1,#KARRAY ;START OF KARRAY MOV R2,#12 ;FOR EACH ROW 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 ;OF 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 END