: Labeling for configuration switch mux ? ; ALS version of the oscillator ? ; Download handshake if scan code on bus and interrupt set ? TITLE "MORROW DESIGNS PIVOT - KEYBOARD PROCESSOR FIRMWARE" SBTTL "REVISION 1/7/85 2.00" WIDTH 80 ; Author: Michael Stolowitz ; ; This firmware shall include the following functions: ; ; KEYBOARD SCANNING - The firmware shall pole an 8 x 12 keyboard ; matrix consisting of two rows of membrane function switches and ; ten rows of diode isolated mechanical switches. IBM PC equivalent ; make and break codes shall be generated for all detected activity. » Î keù rolloveò shalì bå implementeä foò thå diode isolated keys. ; Scan codes will be stored in a FIFO to host transmission. The ; keyboard will be scanned at the frame rate of the LCD display ; when the display is enabled and at an interval determined by the ; processor's internal real time clock when the display is off. ; ; SCAN CODE TRANSMISSION TO THE HOST - As a background task, the ; firmware shall poll the FIFO and the host's 8255 status, uploading ; scan codes whenever posssible. ; ; COLOR GRAPHICS BOARD SIMULATION - This firmware will respond to ; interrupts caused by CPU access of the non-existent Color Graphics ; board. This firmware will analyze the state of the ready line ; held CPU and release the processor with an appropriate response ; simulating the 6845, the MODE register, and the STATUS register ; as required. Changes to the MODE register will invoke similar ; states of the LCD display when available. Updating the 6845's ; curser register will result in a CPU NMI interrupt at end of frame ; so that the LCD's software controlled curser may be updated. ; ; HARDWARE CONTROL FUNCTIONS - The firmware shall implement a down ; load procedure for data from the CPU via the 8255 on the keyboard ; data bus. Using this mechanism, the CPU will control/monitor ; hardware not found on a standard IBM PC. This includes control ; of the LCD display, the non-volatile ram & clock, and the floppy ; disk motors. It will also be able to enable and disable access ; to the LCD display, write the virtual configuration switch and ; monitor the state of the low battery and ac on detectors. ; ; ; INTERNAL PORT MAPPED FUNCTIONS ; ; Port 1 8255 Keyboard Data Bus ; ----------------------------------------- ; P17 PA7 ; P16 PA6 ; P15 PA5 ; P14 PA4 ; P13 PA3 ; P12 PA2 ; P11 PA1 ; P10 PA0 ; ; Port 2 Program Memory Address / Misc Strobes ; ----------------------------------------- ; P27 Set Keyboard Interrupt ; P26 Acknowledge CPU LCD Access ; P25 Assert CPU NMI ; P24 Keyboard Clock - 8255 Handshake ; P23 PAD11 - Not Used ; P22 PAD10 ; P21 PAD9 ; P20 PAD8 ; ; ; EXTERNAL MEMORY MAPPED FUNCTIONS ; ; WRITE PORTS ; ; Port 0 Keyboard Column Strobe ; ----------------------------------------- ; Addr 5 ROW3 ; 4 ROW2 ; 3 ROW1 ; 2 ROW0 ; ; Port 1 Processor Data Strobe ; ----------------------------------------- ; Data 7 AD7 ; 6 AD6 ; 5 AD5 ; 4 AD4 ; 3 AD3 ; 2 AD2 ; 1 AD1 ; 0 AD0 ; ; Port 2 Switch Register Strobe ; --------------------------------------- ; Addr 6 FDC ENA ; Data 7 SW8 ; 6 SW7 ; 5 SW6 ; 4 SW5 ; 3 SW4 ; 2 SW3 ; 1 SW2 ; 0 SW1 ; ; Port 3 Display Strobe ; ----------------------------------------- ; 7 A/N Bank 0 ; 6 Color Adapater Board Installed ; 5 Blink ; 4 High Resolution Graphics ; 3 Reset the CPU ; 2 LCD Display Enable ; 1 Graphics/Alpha-Numeric ; 0 Non-Volitile Ram & Clock Enable ; ; READ PORTS ; ; Port 0 Processor Data Enable ; ----------------------------------------- ; Data 7 AD7 ; 6 AD6 ; 5 AD5 ; 4 AD4 ; 3 AD3 ; 2 AD2 ; 1 AD1 ; 0 AD0 ; ; Port 1 Keyboard Data Enable ; ----------------------------------------- ; Data 7 COL8 ; 6 COL7 ; 5 COL6 ; 4 COL5 ; 3 COL4 ; 2 COL3 ; 1 COL2 ; 0 COL1 ; ; Port 2 Processor Address Enable ; ----------------------------------------- ; Data 4 IOR* ; 3 A3 ; 2 A2 ; 1 A1 ; 0 A0 ; ; Port 3 Extra Port Enable ; ----------------------------------------- ; Data 3 FDC ENA * ; 2 LO BATT1 * ; 1 LO BATT2 * ; 0 AC ON * ; * * * * * ; ; BANK 0 REGISTER UTILIZATION ; ; R0 WORKING INDEX REGISTER ; R1 DISPLAY ADDR 1..12 ; R2 CURRENT ROW 1..12 OR 0 IF NO ACTIVE KEY ; R3 CURRENT KEY KEYBOARD DATA IF R2 <> 0 ; R4 CURRENT CTL 00 OR 80H ; R5 CURRENT ALT 00 OR 80H ; R6 CURRENT LSRS 00 OR 02H ; R7 DEBOUNCE DELAY ; ; BANK 1 REGISTER UTILIZATION ; ; R0 WORKING INDEX REGISTER ; R1 6845 ADDRESS REGISTER ; R2 FIFO INPUT POINTER ; R3 FIFO OUTPUT POINTER ; R4 BLINK COUNTER ; R5 DISPLAY STATUS REGISTER ; R6 HOLD A DURING INT ROUTINE ; R7 DISP CTL SHADOW ; ; F1 NOT END-FRAME ; ; PORT 1 KEYBOARD SCAN CODES TO 8255 ; ; PORT 2 STROBE OUTPUT PORT - BIT ASSIGNMENTS ; KBDAV.P: EQU 10000000B ;SET DAV LATCH CRQC.N: EQU 01000000B ;RELEASE PROCESSOR NMIRQ.P: EQU 00100000B ;ASSERT PROCESSOR NMI ; ; DATA BUS 8084 LOCAL BUS FACILITIES ; KB.STB EQU 00H ;Key Board Strobe PD.STB EQU 01H ;Processor Data Strobe DS.STB EQU 03H ;Display Strobe ; KB.ENA EQU 00H ;Key Board Enable PD.ENA EQU 01H ;Processor Data Enable PA.ENA EQU 02H ;Processor Address Enable ; ; DATA MEMORY MAP ; 20 - 31H 18 REGISTERS OF 6845 ; 32 - 3FG 14 BYTES OF FIFO ; CRT.REG EQU 20H ;6845 DATA REG BASE CUR.REG EQU 0EH ;CURSER REGISTER PAIR FIFO EQU 0F2H ;FIFO BASE ADDR ;DISPLAY BLINK CONSTANTS K.BLINK EQU 10 ;75/20 CYCLES PER SECOND BLINK.B EQU 20H ;BLINK BIT OF DISP CTL ;SCAN CODES SCAN.ALT: EQU 56 SCAN.CTL: EQU 29 SCAN.LS: EQU 42 SCAN.RS: EQU 54 ;DEBOUNCE CONSTA ; ; WHILE NOT END OF FRAME - UNLOAD THE FIFO ; ; AT END OF FRAME: ; 1. CLEAR END FRAME FLAG ; 2. SEND NMI TO HOST IF CURSER MOVED ; 3. UPDATE BLINK ; 4. SCAN KEYBOARD ; MAIN: JF1 SENDOUT ;SKIP IF NOT END FRAME CPL F1 ;CLR END FRAME FLG MAIN1: SEL RB1 ;BANK1 REGISTERS MOV A,R5 ;FETCH DISPLAY STATUS ANL A,#80H ;MASK CURSER UPDATE JZ MAIN2 ;SKIP IF NOT SET XRL A,R5 ;CLR UPDATE BIT MOV R5,A ;AND RESTORE STATUS ORL P2,#NMIRQ.P ;ASSERT PROC NMI ANL P2,#NOT NMIRQ.P ;NEGATE PROC NMI MAIN2: DJNZ R4,MAIN3 ;BUMP BLINK, AND TEST MOV A,R7 ;FETCH CONTROL BYTE MOV R0,#DS.STB ;POINT TO DISP REG MOVX @R0,A ;AND MOVE OUT ACC XRL A,#BLINK.B ;TOGGLE BLINK BIT MOV R7,A ;RESTORE TO REG MOV R4,#K.BLINK ;RESET COUNTER ; ; KEYBOARD SCAN ROUTINE ; MAIN3: SEL RB0 ;SELECT BANK 0 MOV A,R7 ;FETCH DEBOUNCE JZ TESTCTL ;SKIP IF ZERO DEC R7 ;ELSE DECR DELAY JMP MAIN ;WAIT ANOTHER FRAME TESTCTL: MOV R1,#1 ;MATRIX ROW 1 CALL KBOUTIN ;OUT ROW / IN DATA XRL A,R4 ;COMPARE NEW/OLD JZ TESTALT ;SKIP IF NO CHANGE XRL A,R4 ;RESTORE DATA XCH A,R4 ;SWAP NEW WITH OLD ADD A,#SCAN.CTL ;ADD CTL SCAN CODE JMP SENDSCAN ;SEND SCAN CODE TESTALT: INC R1 ;MAXTRIX ROW 2 CALL KBOUTIN ;OUT ROW / IN DATA XRL A,R5 ;COMPARE NEW/OLD JZ TESTOLD ;IF NO CHANGE XRL A,R5 ;RESTORE DATA XCH A,R5 ;SWAP NEW WITH OLD ADD A,#SCAN.ALT ;ADD ALT SCAN CODE JMP SENDSCAN ;SEND SCAN CODE TESTOLD: MOV A,R2 ;GET CURRENT ROW JZ TESTSHTR ;NO CURRENT KEY MOV R1,A ;COPY TO ROW POINTER CALL KBOUTIN ;OUT ROW / IN DATA ANL A,R3 ;MASK TO OLD BIT JNZ MAIN ;STILL DOWN MOV R2,A ;CLEAR CURRENT ROW XCH A,R3 ;SWAP ZERO WITH DATA CALL SCANCODE ;GET SCAN CODE ORL A,#80H ;ADD BREAK BIT JMP SENDSCAN ;SEND BREAK CODE TESTSHTR: MOV R1,#3 ;KB ROW 3 CALL KBOUTIN ;OUT ROW / IN DATA XRL A,R6 ;COMPARE WITH CURRENT ANL A,#RS.BIT ;MASK TO RIGHT SHIFT JZ TESTSHTL ;SKIP IF UNCHANGED MOV A,R6 ;COPY R6 TO ACC JB2 TESTSR1 ;SKIP IF KEY BREAK ORL A,#RS.BIT ;SET RS BIT MOV R6,A ;AND REPLACE R6 CLR A ;NO BREAK BIT JMP TESTSR2 ;AND SKIP TESTSR1: ANL A,#NOT RS.BIT ;CLR RS BIT MOV R6,A ;AND REPLACE R6 MOV A,#80H ;SET BREAK BIT TESTSR2: ADD A,#SCAN.RS ;OR SCAN CODE JMP SENDSCAN ;AND SEND TESTSHTL: INC R1 ;KB ROW 4 CALL KBOUTIN ;OUT ROW / IN DATA XRL A,R6 ;COMPARE WITH CURRENT ANL A,#LS.BIT ;MASK TO RIGHT SHIFT JZ SCAN ;SKIP IF UNCHANGED MOV A,R6 ;COPY R6 TO ACC JB1 TESTSL1 ;SKIP IF KEY BREAK ORL A,#LS.BIT ;SET LS BIT MOV R6,A ;AND REPLACE R6 CLR A ;NO BREAK BIT JMP TESTSL2 ;AND SKIP TESTSL1: ANL A,#NOT LS.BIT ;CLR LS BIT MOV R6,A ;AND REPLACE R6 MOV A,#80H ;SET BREAK BIT TESTSL2: ADD A,#SCAN.LS ;OR SCAN CODE JMP SENDSCAN ;AND SEND SCAN: MOV R1,#3 ;START WITH ROW 3 CALL KBOUTIN ;KB ADDR OUT / DATA IN ANL A,#NOT RS.BIT ;MASK OUT RSBIT JNZ SCAN2 ;SKIP IF KEY FOUND INC R1 ;STEP TO ROW 4 CALL KBOUTIN ;KB ADDR OUT / DATA IN ANL A,#NOT LS.BIT ;MASK OUT LSBIT JNZ SCAN2 ;SKIP IF KEY FOUND MOV R3,#8 ;INIT CNT FOR TEN ROWS SCAN1: INC R1 ;BUMP ROW NUMBER CALL KBOUTIN ;KB ADDR OUT / DATA IN JNZ SCAN2 ;JUMP IF KEY FOUND DJNZ R3,SCAN1 ;CONTINUE IF CNT > 0 JMP MAIN ;ELSE DONE SCAN2: MOV R3,A ;SAVE AS CURRENT KEY MOV A,R1 ;GET ROW ADDR ADDR MOV R2,A ;AND SAVE AS CURRENT ROW MOV A,R3 ;RECALL THE DATA CALL SCANCODE ;GET SCAN CODE JMP SENDSCAN ;SEND SCAN CODE ; ; FIFO BUFFER UNLOAD ROUTINE ; SENDOUT: JT0 MAIN ;IF 8255 BUSY SEL RB1 ;BANK 1 REGISTERS MOV A,R3 ;FETCH FIFO OUT PTR MOV R0,A ;COPY TO INDEX REG XRL A,R2 ;COMPARE WITH FIFO IN JZ MAIN ;RETURN IF FIFO EMPTY MOV A,@R0 ;FETCH DATA FROM BUF OUTL P1,A ;OUTPUT TO 8255 ORL P2,#KBDAV.P ;ASSERT DAV SET ANL P2,#NOT KBDAV.P ;NEGATE THE SET MOV A,R3 ;FETCH THE PTR ADD A,#1 ;BUMP IT JNC SNDOUT1 ;SKIP IF NO OVFL MOV A,#FIFO ;OTHERWISE RESET SNDOUT1: MOV R3,A ;RESTORE OUT PTR SEL RB0 ;AND BANK 0 JMP MAIN ; ; KEYBOARD WRITE ADDRESS / READ DATA ; ; R1 = ROW ADDRESS ; A = RETURNED DATA ; KBOUTIN: MOV R0,#KB.STB ;KB STB TO NDX MOV A,R1 ;ROW TO A MOVX @R0,A ;AND A TO KB MOVX A,@R0 ;KB DATA TO A RET ;AND RETURN DATA ; ; SCAN CODE - CONVERT KEY ADDRESS TO PC SCAN CODE ; ; ENTRY: ; A = KEYBOARD DATA ; R0 = TEMP ; R1 = ROW NUMBER ; ; EXIT: ; A = SCAN CODE ; ORG ROM.ORG+100H ;TABLE AT X00 SCANTBL: DB 1,0,0,2,16,30,72,44 DB 255,0,0,5,19,33,57,47 DB 43,27,80,3,17,31,75,45 DB 15,77,12,4,18,32,11,46 DB 255,43,39,6,20,34,52,48 DB 26,0,53,7,21,35,25,49 DB 40,28,38,8,22,36,24,50 DB 14,41,13,9,23,37,10,51 DB 60,62,64,65,67,0,0,0 DB 59,61,63,66,68,0,0,0 SCANCODE: MOV R0,#8 ;INITIATE CNT SC1: DEC R0 ;DECR BIT POS RLC A ;ROTATE NEXT BIT TO CRY JNC SC1 ;REPEAT IF ZERO BIT MOV A,R1 ;GET ROW NUMBER ADD A,#-3 ;ADJUST TO 0-9 RL A ;AND SHIFT LEFT RL A ;THREE RL A ;BITS ORL A,R0 ;OR THE DATA BIT NUMBER MOVP A,@A ;AND FETCH FROM TABLE RET ; ; FIFO BUFFER LOAD ROUTINE ; ; A = SCAN CODE ; SENDSCAN: SEL RB1 ;BANK 1 REGISTERS MOV R0,A ;HOLD DATA IN R0 MOV A,R2 ;FETCH FIFO IN PTR XCH A,R0 ;SWAP DATA AND ADDR MOV @R0,A ;DATA TO FIFO MOV A,R0 ;RESTORE THE ADDR ADD A,#01H ;BUMP THE PTR JNC SNDSCAN1 ;SKIP IF NO OVFL MOV A,#FIFO ;WRAP THE RING SNDSCAN1: XRL A,R3 ;COMPARE FIFO OUT JZ SNDSCAN2 ;SKIP IF BUF FULL XRL A,R3 ;RESTORE NEW VALUE MOV R2,A ;UPDATE FIFO IN SNDSCAN2: MOV A,@R0 ;RECALL SCAN CODE SEL RB0 ;BANK 0 JB7 SNDSCAN4 ;SKIP TO MAIN IF BREAK MOV A,#-11 ;IF ROW => 11 ADD A,R1 ;THEN CARRY WILL SET JC SNDSCAN3 ;SKIP IF 11 OR 12 MOV R7,#KBDB.S ;ELSE DEBOUNCE SHORT JMP MAIN ;AND DONE SNDSCAN3: MOV R7,#KBDB.L ;SET DEBOUNCE LONG SNDSCAN4: JMP MAIN ;AND DONE ; ; STALL INTERRUPT ; PROC ACCESSING COLOR GRAPHICS BOARD ; ; PROC ADDR = /IOR A3 A1 A0 ; ; ROUTINE FUNCTION (DECODES THRU JUMP TABLE): ; A. ILLEGAL READS OR WRITES REL PROC ; B. WRITES ACCEPT DATA AND REL PROC ; 1. 6845 ADDR SETS R1 ; 2. 6845 DATA GOES TO RAM @R1 ; A. CURSER REG CLRS F0 ; 3. MODE SETS R7 AND DISP CTL PORT ; 4. SELECT AND LIGHT PEN IGNORED ; C. READ OF 6845 RETURNS RAM VALUE @R1 ; D. READ OF STATUS RETURNS R5 ; 1. VSYNC IS TOGGLED AFTER READ ; ORG ROM.ORG+200H ; TABLE: 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 ;R8 READ MODE REG DB EXIT ;R9 READ SELECT DB RSTAT ;RA READ STATUS DB EXIT ;RB 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 WMODE ;W8 WRITE MODE REG DB EXIT ;W9 WRITE SELECT DB EXIT ;WA WRITE STATUS DB EXIT ;WB LIGHT PEN CLEAR STALL: SEL RB1 ;B ÿÿ ýÿ ÿÿ ÿÿÿÿ ÿÿ ÿÿ @ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿÿ¿ ÿÿ ÿÿ ÿÿ ûÿ ÿÿ ÿÿ ÿÿ ÿ¿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿÿÿ ÿÿ ÿþ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿþ ÿÿ ÿ¿ ÿÿ ÿÿ ÿÿ ÿ¿ ÿÿÿÿ ÿÿ ÿÿ ÿÿ û¿ ÿÿ ÿ¿ ÿÿ ÿ¿ ÿÿ ÿÿ ÿÿ ÿ¿ ÿÿ ÿÿ ÿÿÿÿ ÿÿ ÿÿ ÿÿ ÿ¿ ÿ¿ ÿ¿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ýÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ýÿ ÿÿ ÿÿ ýÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿýÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿ¿ ÿÿ ÿÿ ÿÿ ÿÿÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿ¿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿ¿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿÿÿ ÿÿ ûÿ ÿÿ ÿÿ ÿÿ ÿ¿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿ¿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿýÿ ÿÿ ý ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ýÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿÿÿ ÿÿ ýÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿUPDATE BIT MOV R5,A ;AND REPLACE STATUS WRCRT1: MOV A,R6 ;RESTORE A RETR ;AND DONE WMODE: CALL WDATA ;ACCEPT THE DATA MOV R7,A ;SAVE MODE IN R7 ANL A,#01101010B ;BITS 6, 5, 3, AND 1 XCH A,R7 ;SAV BITS - GET MODE JB1 WMODE2 ;WILL NOT NEED BIT 0 JB0 WMODE1 ;BIT 0 SHOULD BE 0 INC R7 ;SET BIT 0 WMODE1: MOV A,R7 ;GET THE DISP BYTE MOV R0,#DS.STB ;DISP ADDR TO NDX MOVX @R0,A ;A TO DISP MOV A,R6 ;RESTORE A RETR ;AND DONE WMODE2: JB4 WMODE3 ;SKIP TO SET BIT 4 JMP WMODE1 ;BIT 4 NOT NEEDED WMODE3: MOV A,#10H ;MASK FOR BIT 4 ADD A,R7 ;ADD DISP CTL BYTE MOV R7,A ;COPY BACK TO SAVE JMP WMODE1+1 ;GO SET THE LATCH RCRTDATA: MOV A,@R1 ;FETCH ADDRESSED DATA JMP RSTAT1 ;AND RETURN TO PROC RSTAT: MOV A,R5 ;STATUS REG TO A RSTAT1: MOV R0,#PD.STB ;PROC DATA ADDR TO NDX MOVX @R0,A ;A TO PROC DATA ANL P2,#NOT CRQC.N ;RELEASE PROCESSOR ORL P2,#CRQC.N ;NEGATE RELEASE XRL A,#08H ;TOGGLE VERT SYNC MOV R5,A ;RESTORE STATUS MOV A,R6 ;RESTORE A RETR ;END OF INTERRUPT ; ; TIMER INTERRUPT - SYNC PULSE FROM DISPLAY ON T1 ; ; CLEARS F1 ENABLING END OF FRAME PROCESSING ; TIMER: 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 END The Pivot Keyboard Matrix Address\data 7 6 5 4 3 2 1 0 ± ctì nã nã nã nã nã nã nc ² alô nã nã nã nã nã nã nc 3 rs nc 4 nc ls 5 6 7 8 9 10 11 function keys ------------------------------------- 12 function keys ------------------------------------- Notå thaô CTÌ anä ALÔ arå unique® RÓ anä LÓ arå not® Thå scaî � algorithí musô handlå keyó overlappeä witè SHIFT® Wheî lookinç � foò á key¬ wå musô noô stoð iæ thå closurå founä ió thå shift® � Wå coulä tesô botè shifts¬ theî masë theí ofæ oæ additionaì � tests.