; ;================================================================================================== ; DSKY V1 ICM7218 (DISPLAY AND KEYBOARD) ROUTINES ;================================================================================================== ; ; THE ICM MAY COINCIDE ON THE SAME PPI BUS AS A PPISD. IT MAY NOT ; SHARE A PPI BUS WITH A PPIDE. SEE PPI_BUS.TXT FOR MORE INFORMATION. ; ; LED SEGMENTS (BIT VALUES) ; ; +--40--+ ; 02 20 ; +--04--+ ; 08 10 ; +--01--+ 80 ; ; ICM SCAN CODES ARE ONE BYTE: CCRRRRRR ; BITS 7-6 IDENTFY THE COLUMN OF THE KEY PRESSED ; BITS 5-0 ARE A BITMAP, WITH A BIT ON TO INDICATE ROW OF KEY PRESSED ; ; ____PC0________PC1________PC2________PC3____ ; PB5 | $20 [D] $60 [E] $A0 [F] $E0 [BO] ; PB4 | $10 [A] $50 [B] $90 [C] $D0 [GO] ; PB3 | $08 [7] $48 [8] $88 [9] $C8 [EX] ; PB2 | $04 [4] $44 [5] $84 [6] $C4 [DE] ; PB1 | $02 [1] $42 [2] $82 [3] $C2 [EN] ; PB0 | $01 [FW] $41 [0] $81 [BK] $C1 [CL] ; ; ICM_PPIA .EQU ICMPPIBASE + 0 ; PORT A ICM_PPIB .EQU ICMPPIBASE + 1 ; PORT B ICM_PPIC .EQU ICMPPIBASE + 2 ; PORT C ICM_PPIX .EQU ICMPPIBASE + 3 ; PPI CONTROL PORT ; ;__ICM_INIT__________________________________________________________________________________________ ; ; CONFIGURE PARALLEL PORT AND CLEAR KEYPAD BUFFER ;____________________________________________________________________________________________________ ; ICM_PREINIT: LD A,(DSKY_DISPACT) ; DSKY DISPATCHER ALREADY SET? OR A ; SET FLAGS RET NZ ; IF ALREADY ACTIVE, ABORT ; OR $FF ; SIGNAL TO WAIT FOR KEY RELEASE LD (ICM_KEYBUF),A ; SET IT ; ; PPI PORT B IS NORMALLY SET TO INPUT, BUT HERE WE ; TEMPORARILY SET IT TO OUTPUT. WHILE IN OUTPUT MODE, WE ; WRITE A VALUE OF $FF WHICH WILL BE PERSISTED BY THE PPI ; CHIP BUS HOLD CIRCUIT IF THERE IS NO ICM PRESENT. SO, ; WE CAN SUBSEQUENTLY TEST FOR PPIB=$FF TO SEE IF THERE IS ; NO ICM AND PREVENT PROBLEMS WITH PHANTOM ICM KEY PRESSES. ; IF A ICM IS PRESENT, IT WILL SIMPLY OVERPOWER THE PPI ; BUS HOLD CIRCUIT. LD A,$80 ; PA OUT, PB OUT, PC OUT OUT (ICM_PPIX),A LD A,$FF ; SET PPIB=$FF, BUS HOLD OUT (ICM_PPIB),A ; LD A,$82 ; PA OUT, PB IN, PC OUT OUT (ICM_PPIX),A ; ;IN A,(ICM_PPIB) ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* ; IN A,(ICM_PPIB) ; READ PPIB XOR $FF ; INVERT RESULT ; CALL ICM_RESET ; RET Z ; BAIL OUT NOW IF NOT PRESENT ; ; RECORD HARDWARE PRESENT LD A,$FF LD (ICM_PRESENT),A ; ; REGISTER DRIVER WITH HBIOS LD BC,ICM_DISPATCH CALL DSKY_SETDISP ; RET ; ICM_INIT: CALL NEWLINE ; FORMATTING PRTS("ICM:$") ; FORMATTING ; PRTS(" IO=0x$") ; FORMATTING LD A,ICMPPIBASE ; GET BASE PORT CALL PRTHEXBYTE ; PRINT BASE PORT ; LD A,(ICM_PRESENT) ; PRESENT? OR A ; SET FLAGS RET NZ ; YES, ALL DONE PRTS(" NOT PRESENT$") ; NOT PRESENT ; RET ; ; ICM DEVICE FUNCTION DISPATCH ENTRY ; A: RESULT (OUT), 0=OK, Z=OK, NZ=ERR ; B: FUNCTION (IN) ; ICM_DISPATCH: LD A,B ; GET REQUESTED FUNCTION AND $0F ; ISOLATE SUB-FUNCTION JP Z,ICM_RESET ; RESET DSKY HARDWARE DEC A JP Z,ICM_STAT ; GET KEYPAD STATUS DEC A JP Z,ICM_GETKEY ; READ A KEY FROM THE KEYPAD DEC A JP Z,ICM_SHOWHEX ; DISPLAY A 32-BIT BINARY VALUE IN HEX DEC A JP Z,ICM_SHOWSEG ; DISPLAY SEGMENTS DEC A JP Z,ICM_KEYLEDS ; SET KEYPAD LEDS DEC A JP Z,ICM_STATLED ; SET STATUS LED DEC A JP Z,ICM_BEEP ; BEEP DSKY SPEAKER DEC A JP Z,ICM_DEVICE ; DEVICE INFO SYSCHKERR(ERR_NOFUNC) RET ; ; ; ICM_RESET: PUSH AF LD A,$70 ; PPISD AND 7218 INACTIVE OUT (ICM_PPIC),A POP AF RET ; ; CHECK FOR KEY PRESS, SAVE RAW VALUE, RETURN STATUS ; ICM_STAT: LD A,(ICM_KEYBUF) ; GET CURRENT BUF VAL CP $FF ; $FF MEANS WE ARE WAITING FOR PREV KEY TO BE RELEASED JR Z,ICM_STAT1 ; CHECK FOR PREV KEY RELEASE OR A ; DO WE HAVE A SCAN CODE BUFFERED ALREADY? RET NZ ; IF SO, WE ARE DONE JR ICM_STAT2 ; OTHERWISE, DO KEY CHECK ICM_STAT1: ; WAITING FOR PREVIOUS KEY RELEASE CALL ICM_KEY ; SCAN JR Z,ICM_STAT2 ; IF ZERO, PREV KEY RELEASED, CONTINUE XOR A ; SIGNAL NO KEY PRESSED RET ; AND DONE ICM_STAT2: CALL ICM_KEY ; SCAN LD (ICM_KEYBUF),A ; SAVE RESULT RET ; RETURN WITH ZF SET APPROPRIATELY ; ; WAIT FOR A ICM KEYPRESS AND RETURN ; ICM_GETKEY: CALL ICM_STAT ; CHECK STATUS JR Z,ICM_GETKEY ; LOOP IF NOTHING READY LD A,(ICM_KEYBUF) LD B,24 ; SIZE OF DECODE TABLE LD C,0 ; INDEX LD HL,ICM_KEYMAP ; POINT TO BEGINNING OF TABLE ICM_GETKEY1: CP (HL) ; MATCH? JR Z,ICM_GETKEY2 ; FOUND, DONE INC HL INC C ; BUMP INDEX DJNZ ICM_GETKEY1 ; LOOP UNTIL EOT ICM_GETKEY1A: LD A,$FF ; NOT FOUND ERR, RETURN $FF RET ICM_GETKEY2: LD A,$FF ; SET KEY BUF TO $FF LD (ICM_KEYBUF),A ; DO IT ; RETURN THE INDEX POSITION WHERE THE SCAN CODE WAS FOUND LD E,C ; RETURN INDEX VALUE XOR A ; SIGNAL SUCCESS RET ; ; ; ICM_SHOWHEX: XOR A ; SIGNAL SUCCESS RET ; ; ICM SHOW BUFFER ; HL: ADDRESS OF BUFFER ; ICM_SHOWSEG: LD A,82H ; SETUP PPI OUT (ICM_PPIX),A CALL ICM_COFF LD A,$F0 ; 7218 -> (DATA COMING, NO DECODE) OUT (ICM_PPIA),A CALL ICM_STROBEC ; STROBE COMMAND LD B,DSKY_BUFLEN ; NUMBER OF DIGITS LD C,ICM_PPIA ICM_HEXOUT2: LD A,(HL) CALL ICM_XLAT ; MAP SEGMENTS XOR $80 ; FIX DOT POLARITY OUT (C),A INC HL DEC B JP Z,ICM_STROBE ; DO FINAL STROBE AND RETURN CALL ICM_STROBE ; STROBE BYTE VALUE JR ICM_HEXOUT2 ICM_STROBEC: ; COMMAND STROBE LD A,80H | 30H JP ICM_STROBE0 ICM_STROBE: ; DATA STROBE LD A,00H | 30H ; SET WRITE STROBE ICM_STROBE0: OUT (ICM_PPIC),A ; OUT TO PORTC CALL DLY2 ; DELAY ICM_COFF: LD A,40H | 30H ; QUIESCE OUT (ICM_PPIC),A ; OUT TO PORTC XOR A ; SIGNAL SUCCESS RET ; ; ; ICM_KEYLEDS: ICM_STATLED: ICM_BEEP: XOR A ; PRETEND SUCCESS RET ; ; DEVICE INFORMATION ; ICM_DEVICE: LD D,DSKYDEV_ICM ; D := DEVICE TYPE LD E,0 ; E := PHYSICAL DEVICE NUMBER LD H,0 ; H := MODE LD L,ICMPPIBASE ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS RET ; ;__ICM_KEY___________________________________________________________________________________________ ; ; CHECK FOR KEY PRESS W/ DEBOUNCE ;____________________________________________________________________________________________________ ; ICM_KEY: CALL ICM_SCAN ; INITIAL KEY PRESS SCAN LD E,A ; SAVE INITIAL SCAN VALUE ICM_KEY1: ; MAX BOUNCE TIME FOR OMRON B3F IS 3MS PUSH DE ; SAVE DE LD DE,300 ; ~3MS DELAY CALL VDELAY ; DO IT CALL ICM_SCAN ; REPEAT SCAN POP DE ; RESTORE DE RET Z ; IF NOTHING PRESSED, DONE CP E ; SAME? JR ICM_KEY2 ; YES, READY TO RETURN LD E,A ; OTHERWISE, SAVE NEW SCAN VAL JR ICM_KEY1 ; AND LOOP UNTIL STABLE VALUE ICM_KEY2: OR A ; SET FLAGS BASED ON VALUE RET ; AND DONE ; ;__ICM_SCAN__________________________________________________________________________________________ ; ; SCAN KEYPAD AND RETURN RAW SCAN CODE (RETURNS ZERO IF NO KEY PRESSED) ;____________________________________________________________________________________________________ ; ICM_SCAN: LD B,4 ; 4 COLUMNS LD C,$01 ; FIRST COLUMN LD E,0 ; INITIAL COL ID ICM_SCAN1: LD A,C ; COL TO A OR $70 ; KEEP PPISD AND 7218 INACTIVE OUT (ICM_PPIC),A ; ACTIVATE COL IN A,(ICM_PPIB) ; READ ROW BITS AND $3F ; MASK, WE ONLY HAVE 6 ROWS, OTHERS UNDEFINED JR NZ,ICM_SCAN2 ; IF NOT ZERO, GOT SOMETHING RLC C ; NEXT COL INC E ; BUMP COL ID DJNZ ICM_SCAN1 ; LOOP THROUGH ALL COLS XOR A ; NOTHING FOUND, RETURN ZERO JP ICM_RESET ; RETURN VIA RESET ICM_SCAN2: RRC E ; MOVE COL ID RRC E ; ... TO HIGH BITS 6 & 7 OR E ; COMBINE WITH ROW JP ICM_RESET ; RETURN VIA RESET ; ; ; CONVERT FORM STANDARD SEGMENT ENCODING TO ICM ENCODING ; ; From: To: ; +--01--+ +--40--+ ; 20 02 02 20 ; +--40--+ +--04--+ ; 10 04 08 10 ; +--08--+ 80 +--01--+ 80 ; ICM_XLAT: PUSH BC PUSH HL LD C,A ; ORIG VALUE TO C XOR A ; INIT RESULT VALUE LD B,8 LD HL,ICM_XTBL ICM_XLAT1: RRC C ; SHIFT NEXT BIT TO CF JR NC,ICM_XLAT2 ; SKIP IF BIT NOT SET OR (HL) ICM_XLAT2: INC HL DJNZ ICM_XLAT1 POP HL POP BC RET ; ICM_XTBL .DB $40, $20, $10, $01, $08, $02, $04, $80 ; ;_ _TABLE_____________________________________________________________________________________________________________ ; ICM_KEYMAP: ; POS $00 $01 $02 $03 $04 $05 $06 $07 ; KEY [0] [1] [2] [3] [4] [5] [6] [7] .DB $41, $02, $42, $82, $04, $44, $84, $08 ; ; POS $08 $09 $0A $0B $0C $0D $0E $0F ; KEY [8] [9] [A] [B] [C] [D] [E] [F] .DB $48, $88, $10, $50, $90, $20, $60, $A0 ; ; POS $10 $11 $12 $13 $14 $15 $16 $17 ; KEY [FW] [BK] [CL] [EN] [DE] [EX] [GO] [BO] .DB $01, $81, $C1, $C2, $C4, $C8, $D0, $E0 ; ; KBD WORKING STORAGE ; ICM_KEYBUF .DB 0 ; ;================================================================================================== ; UTILTITY FUNCTIONS ;================================================================================================== ; ; ;================================================================================================== ; STORAGE ;================================================================================================== ; ; SEG DISPLAY WORKING STORAGE ; ICM_PRESENT .DB 0