; ;================================================================================================== ; DSKY NEXT GENERATION PKD (DISPLAY AND KEYBOARD) ROUTINES ;================================================================================================== ; ; A PKD CAN SHARE A PPI BUS WITH EITHER A PPIDE OR PPISD. ; SEE PPI_BUS.TXT FOR MORE INFORMATION. ; ; LED SEGMENTS (BIT VALUES) ; ; +--01--+ ; 20 02 ; +--40--+ ; 10 04 ; +--08--+ 80 ; ; KEY CODE MAP (KEY CODES) CSCCCRRR ; |||||||| ; |||||+++-- ROW ; ||+++----- COL ; |+-------- SHIFT ; +--------- CONTROL ; ; 00 08 10 18 23 ; 01 09 11 19 22 ; 02 0A 12 1A 21 ; 03 0B 13 1B 20 ; 04 0C 14 1C SHIFT ; 05 0D 15 1D CTRL ; ; LED BIT MAP (BIT VALUES) ; ; $08 $09 $0A $0B $0C $0D $0E $0F ; --- --- --- --- --- --- --- --- ; 01 01 01 01 01 ; 02 02 02 02 02 ; 04 04 04 04 04 ; 08 08 08 08 08 ; 10 10 10 10 10 ; 20 20 20 20 20 L1 L2 BUZZ ; PKD_PPIA .EQU PKDPPIBASE + 0 ; PORT A PKD_PPIB .EQU PKDPPIBASE + 1 ; PORT B PKD_PPIC .EQU PKDPPIBASE + 2 ; PORT C PKD_PPIX .EQU PKDPPIBASE + 3 ; PPI CONTROL PORT ; PKD_PPIX_RD: .EQU %10010010 ; PPIX VALUE FOR READS PKD_PPIX_WR: .EQU %10000010 ; PPIX VALUE FOR WRITES ; ; PIO CHANNEL C: ; ; 7 6 5 4 3 2 1 0 ; RES 0 0 CS CS /RD /WR A0 ; ; SETTING BITS 3 & 4 WILL ASSERT /CS ON 3279 ; CLEAR BITS 1 OR 2 TO ASSERT READ/WRITE ; PKD_PPI_IDLE .EQU %00000110 ; PKD_CMD_CLR .EQU %11011111 ; CLEAR (ALL OFF) PKD_CMD_CLRX .EQU %11010011 ; CLEAR (ALL ON) PKD_CMD_WDSP .EQU %10010000 ; WRITE DISPLAY RAM PKD_CMD_RDSP .EQU %01110000 ; READ DISPLAY RAM PKD_CMD_CLK .EQU %00100000 ; SET CLK PRESCALE PKD_CMD_FIFO .EQU %01000000 ; READ FIFO ; PKD_PRESCL .EQU PKDOSC/100000 ; PRESCALER ; ;__PKD_PREINIT_______________________________________________________________________________________ ; ; CONFIGURE PARALLEL PORT AND INITIALIZE 8279 ;____________________________________________________________________________________________________ ; ; ; HARDWARE RESET 8279 BY PULSING RESET LINE ; PKD_PREINIT: LD A,(DSKY_DISPACT) ; DSKY DISPATCHER ALREADY SET? OR A ; SET FLAGS RET NZ ; IF ALREADY ACTIVE, ABORT ; ; CHECK FOR PPI CALL PKD_PPIDETECT ; TEST FOR PPI HARDWARE RET NZ ; BAIL OUT IF NOT THERE ; ; SETUP PPI TO IDLE STATE CALL PKD_PPIIDLE LD A,PKD_PPI_IDLE OUT (PKD_PPIC),A ; ; PULSE RESET SIGNAL ON 8279 SET 7,A OUT (PKD_PPIC),A RES 7,A OUT (PKD_PPIC),A ; ; INITIALIZE 8279 CALL PKD_REINIT ; ; NOW SEE IF A PKD IS REALLY THERE... LD A,$71 LD C,0 CALL PKD_PUTBYTE LD C,0 CALL PKD_GETBYTE CP $71 RET NZ ; BAIL OUT IF MISCOMPARE ; ; RECORD HARDWARE PRESENT LD A,$FF LD (PKD_PRESENT),A ; ; REGISTER DRIVER WITH HBIOS LD BC,PKD_DISPATCH CALL DSKY_SETDISP ; RET ; PKD_REINIT: CALL PKD_PPIIDLE ; SET CLOCK SCALER TO 20 LD A,PKD_CMD_CLK | PKD_PRESCL CALL PKD_CMD JP PKD_RESET ; ;__PKD_INIT__________________________________________________________________________________________ ; ; DISPLAY DSKY INFO ;____________________________________________________________________________________________________ ; PKD_INIT: CALL NEWLINE ; FORMATTING PRTS("PKD:$") ; FORMATTING ; PRTS(" IO=0x$") ; FORMATTING LD A,PKDPPIBASE ; GET BASE PORT CALL PRTHEXBYTE ; PRINT BASE PORT ; LD A,(PKD_PRESENT) ; PRESENT? OR A ; SET FLAGS RET NZ ; YES, ALL DONE PRTS(" NOT PRESENT$") ; NOT PRESENT RET ; DONE ; ; DSKY DEVICE FUNCTION DISPATCH ENTRY ; A: RESULT (OUT), 0=OK, Z=OK, NZ=ERR ; B: FUNCTION (IN) ; PKD_DISPATCH: LD A,B ; GET REQUESTED FUNCTION AND $0F ; ISOLATE SUB-FUNCTION JP Z,PKD_RESET ; RESET DSKY HARDWARE DEC A JP Z,PKD_STAT ; GET KEYPAD STATUS DEC A JP Z,PKD_GETKEY ; READ A KEY FROM THE KEYPAD DEC A JP Z,PKD_SHOWHEX ; DISPLAY A 32-BIT BINARY VALUE IN HEX DEC A JP Z,PKD_SHOWSEG ; DISPLAY SEGMENTS DEC A JP Z,PKD_KEYLEDS ; SET KEYPAD LEDS DEC A JP Z,PKD_STATLED ; SET STATUS LED DEC A JP Z,PKD_BEEP ; BEEP DSKY SPEAKER DEC A JP Z,PKD_DEVICE ; DEVICE INFO SYSCHKERR(ERR_NOFUNC) RET ; ; RESET DSKY -- CLEAR RAM AND FIFO ; PKD_RESET: LD A,PKD_CMD_CLR CALL PKD_CMD ; ; 8259 TAKES ~160US TO CLEAR RAM DURING WHICH TIME WRITES TO ; DISPLAY RAM ARE INHIBITED. HIGH BIT OF STATUS BYTE IS SET ; DURING THIS WINDOW. TO PREVENT A DEADLOCK, A LOOP COUNTER ; IS USED TO IMPLEMENT A TIMEOUT. LD B,0 ; TIMEOUT LOOP COUNTER PKD_RESET1: PUSH BC ; SAVE COUNTER CALL PKD_ST ; GET STATUS BYTE POP BC ; RECOVER COUNTER BIT 7,A ; BIT 7 IS DISPLAY RAM BUSY JR Z,PKD_RESET2 ; MOVE ON IF DONE DJNZ PKD_RESET1 ; LOOP TILL TIMEOUT ; PKD_RESET2: RET ; ; CHECK FOR KEY PRESS, SAVE RAW VALUE, RETURN STATUS ; PKD_STAT: LD A,(PKD_PRESENT) ; DOES IT EXIST? OR A ; SET FLAGS RET Z ; ABORT WITH A=0 IF NOT THERE CALL PKD_ST AND $0F ; ISOLATE THE CUR FIFO LEN RET ; ; WAIT FOR A DSKY KEYPRESS AND RETURN ; PKD_GETKEY: LD A,(PKD_PRESENT) ; DOES IT EXIST? OR A ; SET FLAGS JR Z,PKD_GETKEY1A ; ABORT IF NOT PRESENT CALL PKD_STAT JR Z,PKD_GETKEY ; LOOP IF NOTHING THERE LD A,PKD_CMD_FIFO CALL PKD_CMD CALL PKD_DIN XOR %11000000 ; FLIP POLARITY OF SHIFT/CTL BITS PUSH AF ; SAVE VALUE AND $3F ; STRIP SHIFT/CTL BITS FOR LOOKUP LD B,28 ; SIZE OF DECODE TABLE LD C,0 ; INDEX LD HL,PKD_KEYMAP ; POINT TO BEGINNING OF TABLE PKD_GETKEY1: CP (HL) ; MATCH? JR Z,PKD_GETKEY2 ; FOUND, DONE INC HL INC C ; BUMP INDEX DJNZ PKD_GETKEY1 ; LOOP UNTIL EOT POP AF ; FIX STACK PKD_GETKEY1A: LD A,$FF ; NOT FOUND ERR, RETURN $FF RET PKD_GETKEY2: ; RETURN THE INDEX POSITION WHERE THE SCAN CODE WAS FOUND ; THE ORIGINAL SHIFT/CTRL BITS ARE RESTORED POP AF ; RESTORE RAW VALUE AND %11000000 ; ISOLATE SHIFT/CTRL BITS OR C ; COMBINE WITH INDEX VALUE LD E,A ; PUT IN E FOR RETURN XOR A ; SIGNAL SUCCESS RET ; ; DISPLAY HEX VALUE FROM DE:HL ; PKD_SHOWHEX: LD BC,DSKY_HEXBUF ; POINT TO HEX BUFFER CALL ST32 ; STORE 32-BIT BINARY THERE LD HL,DSKY_HEXBUF ; FROM: BINARY VALUE (HL) LD DE,DSKY_BUF ; TO: SEGMENT BUFFER (DE) CALL DSKY_BIN2SEG ; CONVERT LD HL,DSKY_BUF ; POINT TO SEGMENT BUFFER ; AND FALL THRU TO DISPLAY IT ; ; ; PKD_SHOWSEG: LD C,0 ; STARTING DISPLAY POSITION LD B,DSKY_BUFLEN ; NUMBER OF CHARS CALL PKD_PUTSTR ; DO IT XOR A ; SIGNAL SUCCESS RET ; ; ; PKD_KEYLEDS: CALL PKD_PUTLED ; DO IT XOR A ; SIGNAL SUCCESS RET ; ; ; PKD_STATLED: LD A,$0D ; PORT FOR FIRST LED ADD A,D ; ADD LED NUM LD C,A ; PUT IN C LD A,E ; LED STATE INDICATOR OR A ; SET FLAGS JR NZ,PKD_STATLED1 ; HANDLE "ON" ; ; TURN LED OFF PUSH BC ; SAVE LED NUM CALL PKD_GETBYTE ; GET CUR VALUE AND ~$20 ; BIT 5 OFF JR PKD_STATLED2 ; FINISH UP ; PKD_STATLED1: ; TURN LED ON PUSH BC ; SAVE LED NUM CALL PKD_GETBYTE ; GET CUR VALUE OR $20 ; BIT 5 ON ; PKD_STATLED2: POP BC ; RECOVER LED NUM CALL PKD_PUTBYTE ; PUT NEW VALUE XOR A ; SIGNAL SUCCESS RET ; ; BEEP THE SPEAKER ON THE PKD ; PKD_BEEP: PUSH BC LD C,$0F CALL PKD_GETBYTE OR $20 LD C,$0F CALL PKD_PUTBYTE ; ; TIMER PUSH HL LD hl,$8FFF PKD_BEEP1: DEC HL LD A,H CP 0 JR NZ,PKD_BEEP1 POP HL LD C,$0F CALL PKD_GETBYTE AND $DF LD C,$0F CALL PKD_PUTBYTE POP BC XOR A ; SIGNAL SUCCESS RET ; ; DEVICE INFORMATION ; PKD_DEVICE: LD D,DSKYDEV_PKD ; D := DEVICE TYPE LD E,0 ; E := PHYSICAL DEVICE NUMBER LD H,0 ; H := MODE LD L,PKDPPIBASE ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS RET ; ;__PKD_PPIDETECT_____________________________________________________________________________________ ; ; PROBE FOR PPI HARDWARE ;____________________________________________________________________________________________________ ; PKD_PPIDETECT: ; ; TEST FOR PPI EXISTENCE ; WE SETUP THE PPI TO WRITE, THEN WRITE A VALUE OF ZERO ; TO PORT A (DATALO), THEN READ IT BACK. IF THE PPI IS THERE ; THEN THE BUS HOLD CIRCUITRY WILL READ BACK THE ZERO. SINCE ; WE ARE IN WRITE MODE, AN IDE CONTROLLER WILL NOT BE ABLE TO ; INTERFERE WITH THE VALUE BEING READ. CALL PKD_PPIWR ; LD C,PKD_PPIA ; PPI PORT A XOR A ; VALUE ZERO OUT (C),A ; PUSH VALUE TO PORT IN A,(C) ; GET PORT VALUE OR A ; SET FLAGS RET ; AND RETURN ; ;_KEYMAP_TABLE_____________________________________________________________________________________________________________ ; PKD_KEYMAP: ; POS $00 $01 $02 $03 $04 $05 $06 $07 ; KEY [0] [1] [2] [3] [4] [5] [6] [7] .DB $0D, $04, $0C, $14, $03, $0B, $13, $02 ; ; POS $08 $09 $0A $0B $0C $0D $0E $0F ; KEY [8] [9] [A] [B] [C] [D] [E] [F] .DB $0A, $12, $01, $09, $11, $00, $08, $10 ; ; POS $10 $11 $12 $13 $14 $15 $16 $17 ; KEY [FW] [BK] [CL] [EN] [DE] [EX] [GO] [BO] .DB $05, $15, $1D, $1C, $1B, $1A, $19, $18 ; POS $18 $19 $1A $1B ; KEY [F4] [F3] [F2] [F1] .DB $23, $22, $21, $20 ; ;================================================================================================== ; PKD OUTPUT ROUTINES ;================================================================================================== ; ; SEND DSKY COMMAND BYTE IN REGISTER A ; TRASHES BC ; PKD_CMD: LD B,$01 JR PKD_DOUT2 ; ; SEND DSKY DATA BYTE IN REGISTER A ; TRASHES BC ; PKD_DOUT: LD B,$00 ; PKD_DOUT2: ; ; SAVE INCOMING DATA BYTE PUSH AF ; ; SET PPI LINE CONFIG TO WRITE MODE CALL PKD_PPIWR ; ; SETUP LD C,PKD_PPIC ; ; SET ADDRESS FIRST LD A,PKD_PPI_IDLE OR B OUT (C),A ; ; ASSERT 8279 /CS SET 3,A SET 4,A OUT (C),A ; ; PPIC WORKING VALUE TO REG B NOW LD B,A ; ; ASSERT DATA BYTE VALUE POP AF OUT (PKD_PPIA),A ; ; PULSE /WR RES 1,B OUT (C),B NOP ; MAY NOT BE NEEDED SET 1,B OUT (C),B ; ; DEASSERT /CS RES 3,B RES 4,B OUT (C),B ; ; CLEAR ADDRESS BIT RES 0,B OUT (C),B ; ; DONE CALL PKD_PPIIDLE RET ; ;================================================================================================== ; PKD INPUT ROUTINES ;================================================================================================== ; ; RETURN DSKY STATUS VALUE IN A ; TRASHES BC ; PKD_ST: LD B,$01 JR PKD_DIN2 ; ; RETURN NEXT DATA VALUE IN A ; TRASHES BC ; PKD_DIN: LD B,$00 ; PKD_DIN2: ; SET PPI LINE CONFIG TO READ MODE CALL PKD_PPIRD ; ; SETUP LD C,PKD_PPIC ; ; SET ADDRESS FIRST LD A,PKD_PPI_IDLE OR B OUT (C),A ; ; ASSERT 8279 /CS SET 3,A SET 4,A OUT (C),A ; ; PPIC WORKING VALUE TO REG B NOW LD B,A ; ; ASSERT /RD RES 2,B OUT (C),B ; ; GET VALUE IN A,(PKD_PPIA) ; ; DEASSERT /RD SET 2,B OUT (C),B ; ; DEASSERT /CS RES 3,B RES 4,B OUT (C),B ; ; CLEAR ADDRESS BIT RES 0,B OUT (C),B ; ; DONE CALL PKD_PPIIDLE RET ; ;================================================================================================== ; PKD UTILITY ROUTINES ;================================================================================================== ; ; BLANK PKD DISPLAY (WITHOUT USING CLEAR) ; PKD_BLANK: LD A,PKD_CMD_WDSP CALL PKD_CMD LD B,16 PKD_BLANK1: PUSH BC LD A,$FF CALL PKD_DOUT POP BC DJNZ PKD_BLANK1 RET ; ; WRITE A RAW BYTE VALUE TO DSKY DISPLAY RAM ; AT LOCATION IN REGISTER C, VALUE IN A. ; PKD_PUTBYTE: PUSH BC PUSH AF LD A,C ADD A,PKD_CMD_WDSP CALL PKD_CMD POP AF XOR $FF CALL PKD_DOUT POP BC RET ; ; READ A RAW BYTE VALUE FROM DSKY DISPLAY RAM ; AT LOCATION IN REGISTER C, VALUE RETURNED IN A ; PKD_GETBYTE: PUSH BC LD A,C ADD A,PKD_CMD_RDSP CALL PKD_CMD CALL PKD_DIN XOR $FF POP BC RET ; ; WRITE A STRING OF RAW BYTE VALUES TO DSKY DISPLAY RAM ; AT LOCATION IN REGISTER C, LENGTH IN B, ADDRESS IN HL. ; PKD_PUTSTR: PUSH BC LD A,C ADD A,PKD_CMD_WDSP CALL PKD_CMD POP BC ; PKD_PUTSTR1: LD A,(HL) XOR $FF INC HL PUSH BC CALL PKD_DOUT POP BC DJNZ PKD_PUTSTR1 RET ; ; READ A STRING OF RAW BYTE VALUES FROM DSKY DISPLAY RAM ; AT LOCATION IN REGISTER C, LENGTH IN B, ADDRESS IN HL. ; PKD_GETSTR: PUSH BC LD A,C ADD A,PKD_CMD_RDSP CALL PKD_CMD POP BC ; PKD_GETSTR1: PUSH BC CALL PKD_DIN POP BC XOR $FF LD (HL),A INC HL DJNZ PKD_GETSTR1 RET ; ; UPDATE THE KEYPAD KEY LEDS. HL POINTS TO AN 8 BYTE BITMAP BUFFER ; THAT DEFINES ALL KEYPAD LED VALUES. THE ENTIRE MATRIX IS UPDATED. ; PKD_PUTLED: PUSH AF PUSH BC LD C,8 PKD_PUTLED_1: LD A,(HL) PUSH BC CALL PKD_PUTBYTE POP BC INC C INC HL LD A,C CP $10 JP NZ,PKD_PUTLED_1 POP BC POP AF RET ; ;================================================================================================== ; PKD LINE CONTROL ROUTINES ;================================================================================================== ; ; SETUP PPI FOR WRITING: PUT PPI PORT A IN OUTPUT MODE ; AVOID REWRTING PPIX IF ALREADY IN OUTPUT MODE ; PKD_PPIWR: PUSH AF ; ; CHECK FOR WRITE MODE LD A,(PKD_PPIX_VAL) CP PKD_PPIX_WR JR Z,PKD_PPIWR1 ; ; SET PPI TO WRITE MODE LD A,PKD_PPIX_WR OUT (PKD_PPIX),A LD (PKD_PPIX_VAL),A ; ; RESTORE PORT C (MAY NOT BE NEEDED) LD A,PKD_PPI_IDLE OUT (PKD_PPIC),A ; PKD_PPIWR1: ; POP AF RET ; ; SETUP PPI FOR READING: PUT PPI PORT A IN INPUT MODE ; AVOID REWRTING PPIX IF ALREADY IN INPUT MODE ; PKD_PPIRD: PUSH AF ; ; CHECK FOR READ MODE LD A,(PKD_PPIX_VAL) CP PKD_PPIX_RD JR Z,PKD_PPIRD1 ; ; SET PPI TO READ MODE LD A,PKD_PPIX_RD OUT (PKD_PPIX),A LD (PKD_PPIX_VAL),A ; PKD_PPIRD1: POP AF RET ; ; RELEASE USE OF PPI ; PKD_PPIIDLE: JR PKD_PPIRD ; SAME AS READ MODE ; ;================================================================================================== ; UTILTITY FUNCTIONS ;================================================================================================== ; ; ;================================================================================================== ; STORAGE ;================================================================================================== ; PKD_PPIX_VAL .DB 0 ; PPIX SHADOW REG PKD_PRESENT .DB 0 ; HARDWARE PRESENT FLAG