; ;================================================================================================== ; DSKY NEXT GENERATION TEST APPLICATION ;================================================================================================== ; ; TO BUILD: ; ; TASM -t80 -g3 -fFF TSTDSKNG.ASM TSTDSKNG.COM TSTDSKNG.LST ; ; PIO 82C55 I/O IS DECODED TO PORT $60-$67 (ADJUST BELOW AS NEEDED) ; ASSUMES UART AT PORT $68 (ADJUST BELOW AS NEEDED) ; ; THIS CODE IS BELIEVED TO BE COMPATIBLE WITH PPIDE OR PPISD ; RUNNING ON SAME PPI BUS. ; FALSE: .EQU 0 TRUE: .EQU !FALSE ; DSKY_OSC: .EQU 3000000 ; OSCILLATOR FREQ IN HZ ; BDOS: .EQU TRUE ; BDOS OR DIRECT TO 8250ISH DSKY_PROTO: .EQU FALSE ; SET FOR DSKYNG PROTOTYPE ; UART_BASE: .EQU $68 ; UART BASE IO ADDRESS PPI_BASE_DEF: .EQU $60 ; PPI BASE IO PORT ; ; 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 CONTROL ; ; LED BIT MAP (BIT VALUES) ; ; $08 $09 $0A $0B $0C ; --- --- --- --- --- ; 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 ; PPIA: .EQU 0 ; PORT A OFFSET PPIB: .EQU 1 ; PORT B OFFSET PPIC: .EQU 2 ; PORT C OFFSET PPIX: .EQU 3 ; PIO CONTROL PORT OFFSET ; DSKY_PPIX_RD: .EQU %10010010 ; PPIX VALUE FOR READS DSKY_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 ; ; #IF (DSKY_PROTO) ; DSKY_PPI_IDLE: .EQU %01100000 ; DSKY_RDBIT .EQU 6 DSKY_WRBIT .EQU 5 ; #ELSE ; DSKY_PPI_IDLE: .EQU %00000110 ; DSKY_RDBIT .EQU 2 DSKY_WRBIT .EQU 1 ; #ENDIF ; DSKY_CMD_CLR: .EQU %11011111 ; CLEAR (ALL OFF) DSKY_CMD_CLRX: .EQU %11010011 ; CLEAR (ALL ON) DSKY_CMD_WDSP: .EQU %10010000 ; WRITE DISPLAY RAM DSKY_CMD_RDSP: .EQU %01110000 ; READ DISPLAY RAM DSKY_CMD_CLK: .EQU %00100000 ; SET CLK PRESCALE DSKY_CMD_FIFO: .EQU %01000000 ; READ FIFO ; DSKY_PRESCL: .EQU DSKY_OSC / 100000 ; PRESCALER ; .ORG $100 ; ; SAVE PREVIOUS STACK POINTER, AND SWITCH TO OUR STACK LD (STACKSAV),SP LD SP,STACK ; CALL PRTSTRD .DB "\r\nNextGenDSKY$" ; #IF (DSKY_PROTO) CALL PRTSTRD .DB " Prototype$" #ENDIF ; CALL PRTSTRD .DB " Test Program, v1.4a, 2021-07-18$" ; CALL GET_BASE JP NZ,EXIT ; CALL PRTSTRD .DB "\r\nDSKYng PPI base port: 0x$" LD A,(PPI_BASE) CALL PRTHEXBYTE CALL NEWLINE ; CALL DSKY_INIT CALL DSKY_READ ; CALL PRTSTRD .DB "\r\nCLEAR Command (all ON)$" LD A,DSKY_CMD_CLRX CALL DSKY_CMD CALL WAITKEY CALL DSKY_READ ; CALL PRTSTRD .DB "\r\nCLEAR Command (all OFF)$" LD A,DSKY_CMD_CLR CALL DSKY_CMD CALL WAITKEY CALL DSKY_READ ; CALL PRTSTRD .DB "\r\nIndividual segments and LEDs$" LD HL,PAT1 LD B,PAT1LN LD C,0 CALL DSKY_PUTSTR CALL WAITKEY CALL DSKY_READ ; CALL PRTSTRD .DB "\r\nIncrementing segments and LEDs$" LD HL,PAT2 LD B,PAT2LN LD C,0 CALL DSKY_PUTSTR CALL WAITKEY CALL DSKY_READ ; CALL PRTSTRD .DB "\r\nOmit individual segments and LEDs$" LD HL,PAT3 LD B,PAT3LN LD C,0 CALL DSKY_PUTSTR CALL WAITKEY CALL DSKY_READ ; ; DISPLAY HEX DIGITS 0-7 ; CALL PRTSTRD .DB "\r\nHex digits 0-7$" LD HL,HEX1 LD B,HEX1LN LD C,0 CALL DSKY_PUTENCSTR CALL WAITKEY CALL DSKY_READ ; CALL PRTSTRD .DB "\r\nHex digits 8-F$" LD HL,HEX2 LD B,HEX2LN LD C,0 CALL DSKY_PUTENCSTR CALL WAITKEY CALL DSKY_READ ; CALL DSKY_BLANK ; ; WAIT FOR KEY THEN DISPLAY FIFO CONTENTS CALL PRTSTRD .DB "\r\nPress keys on pad (console key to end)...$" ; ; CLEAR BUFFER LD HL,DSPBUF LD A,$10 LD B,8 M1: LD (HL),A INC HL DJNZ M1 ; ; DISPLAY INIITAL BUFFER LD B,8 LD C,0 LD HL,DSPBUF CALL DSKY_PUTENCSTR ; M2: CALL CST ; CONSOLE STATUS JP NZ,M4 ; ABORT IF KEY PRESSED CALL DSKY_STAT AND $3F ; DUMP 2 HIGH BITS JR Z,M2 ; LOOP IF STATUS ZERO CALL PRTSTRD .DB "\r\nFIFO status=$" CALL PRTHEXBYTE AND $0F ; ISOLATE THE CUR FIFO LEN JR Z,M2 ; LOOP IF NOTHING THERE PUSH AF LD A,DSKY_CMD_FIFO CALL DSKY_CMD POP BC ; B := CUR FIFO LEN CALL PRTSTRD .DB ", key code(s)=$" M3: PUSH BC CALL DSKY_DIN XOR %11000000 ; FLIP CONTROL & SHIFT MODIFIERS CALL PRTHEXBYTE CALL PC_SPACE ; SHIFT BUFFER LD HL,DSPBUF+5 LD DE,DSPBUF+7 LD BC,6 LDDR ; PUT NEW VALUE AT START PUSH AF RRCA RRCA RRCA RRCA AND $0F LD (DSPBUF),A POP AF PUSH AF AND $0F LD (DSPBUF+1),A ; UPDATE THE DISPLAY LD B,8 LD C,0 LD HL,DSPBUF CALL DSKY_PUTENCSTR POP AF ; TOGGLE LED, KEY CODE: CSCCCRRR PUSH AF AND $07 ; ISOLATE ROW LD B,A ; SAVE IN B POP AF RRCA RRCA RRCA AND $07 ; ISOLATE COLUMN LD C,A ; SAVE IN C CALL DSKY_TOGLED ; TOGGLE LED AT ROW/COL POP BC ; INSIDE LOOP COUNTER DJNZ M3 JP M2 ; LOOP M4: CALL CIN ; DUMP PENDING CONSOLE KEY ; ; DANCING LIGHTS CALL PRTSTRD .DB "\r\nDance, Baby, Dance (console key to end)...$" LD A,DSKY_CMD_CLR CALL DSKY_CMD ; LD E,$01 ; STARTING VALUE M5: CALL CST ; CONSOLE STATUS JR NZ,M8 ; ABORT IF KEY PRESSED LD B,16 ; NUMBER OF BYTES LD C,$00 ; STARTING LOCATION (BYTE) M6: LD A,E CALL DSKY_PUTBYTE INC C ; NEXT LOCATION DJNZ M6 ; INNER LOOP FOR ALL BYTES RLC E ; ROTATE THE VALUE LD B,0 ; DELAY LOOP M7: CALL DLY64 DJNZ M7 JR M5 ; REPEAT OUTER LOOP M8: CALL CIN ; DUMP PENDING CONSOLE KEY ; ; CLEAR ALL LD A,DSKY_CMD_CLR CALL DSKY_CMD ; EXIT: ; GOODBYE CALL PRTSTRD .DB "\r\nThank you, please call again\r\n$" ; ; CLEAN UP AND RETURN TO OS LD SP,(STACKSAV) ; RET ; ; SETUP PPI FOR WRITING: PUT PPI PORT A IN OUTPUT MODE ; AVOID REWRTING PPIX IF ALREADY IN OUTPUT MODE ; DSKY_PPIWR: PUSH AF PUSH BC ; LD A,(PPI_BASE) ADD A,PPIX LD C,A ; ; CHECK FOR WRITE MODE LD A,(PPIX_VAL) CP DSKY_PPIX_WR JR Z,DSKY_PPIWR1 ; ; SET PPI TO WRITE MODE LD A,DSKY_PPIX_WR OUT (C),A LD (PPIX_VAL),A ; ; RESTORE PORT C (MAY NOT BE NEEDED) LD A,DSKY_PPI_IDLE DEC C OUT (C),A ; DSKY_PPIWR1: ; POP BC POP AF RET ; ; SETUP PPI FOR READING: PUT PPI PORT A IN INPUT MODE ; AVOID REWRTING PPIX IF ALREADY IN INPUT MODE ; DSKY_PPIRD: PUSH AF PUSH BC ; LD A,(PPI_BASE) ADD A,PPIX LD C,A ; ; CHECK FOR READ MODE LD A,(PPIX_VAL) CP DSKY_PPIX_RD JR Z,DSKY_PPIRD1 ; ; SET PPI TO READ MODE LD A,DSKY_PPIX_RD OUT (C),A LD (PPIX_VAL),A ; ; RESTORE PORT C (MAY NOT BE NEEDED) LD A,DSKY_PPI_IDLE DEC C OUT (C),A ; DSKY_PPIRD1: POP BC POP AF RET ; ; RELEASE USE OF PPI ; DSKY_PPIIDLE: JR DSKY_PPIRD ; SAME AS READ MODE ; ; ; DSKY_INIT: ; RESET DSKY CALL DSKY_RES ; SET CLOCK SCALER TO 20 LD A,DSKY_CMD_CLK | DSKY_PRESCL CALL DSKY_CMD LD A,%00001000 ; dan CALL DSKY_CMD ; RET ; ; HARDWARE RESET 8279 BY PULSING RESET LINE ; DSKY_RES: ; PUSH BC LD A,(PPI_BASE) ADD A,PPIC LD C,A ; SETUP PPI CALL DSKY_PPIRD ; INIT 8279 VALUES TO IDLE STATE LD A,DSKY_PPI_IDLE OUT (C),A ; PULSE RESET SIGNAL ON 8279 SET 7,A OUT (C),A RES 7,A OUT (C),A ; DONE CALL DSKY_PPIIDLE POP BC RET ; ; COMMAND IN A ; TRASHES BC ; DSKY_CMD: LD B,$01 JR DSKY_DOUT2 ; ; DATA VALUE IN A ; TRASHES BC ; DSKY_DOUT: LD B,$00 ; DSKY_DOUT2: ; ; SAVE INCOMING DATA BYTE PUSH AF ; ; SET PPI LINE CONFIG TO WRITE MODE CALL DSKY_PPIWR ; ; SETUP LD A,(PPI_BASE) ADD A,PPIC LD C,A ; ; SET ADDRESS FIRST LD A,DSKY_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 DEC C DEC C POP AF OUT (C),A INC C INC C ; ; PULSE /WR RES DSKY_WRBIT,B OUT (C),B NOP ; MAY NOT BE NEEDED SET DSKY_WRBIT,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 DSKY_PPIIDLE RET ; ; STATUS VALUE IN A ; TRASHES BC ; DSKY_STAT: LD B,$01 JR DSKY_DIN2 ; ; DATA VALUE RETURNED IN A ; TRASHES BC ; DSKY_DIN: LD B,$00 ; DSKY_DIN2: ; SET PPI LINE CONFIG TO WRITE MODE CALL DSKY_PPIRD ; ; SETUP LD A,(PPI_BASE) ADD A,PPIC LD C,A ; ; SET ADDRESS FIRST LD A,DSKY_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 DSKY_RDBIT,B OUT (C),B ; ; GET VALUE DEC C DEC C IN A,(C) INC C INC C ; ; DEASSERT /RD SET DSKY_RDBIT,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 DSKY_PPIIDLE RET ; ; BLANK THE DISPLAY (WITHOUT USING CLEAR) ; DSKY_BLANK: LD A,DSKY_CMD_WDSP CALL DSKY_CMD LD B,16 DSKY_BLANK1: PUSH BC LD A,$FF CALL DSKY_DOUT POP BC DJNZ DSKY_BLANK1 RET ; ; WRITE A RAW BYTE VALUE TO DSKY DISPLAY RAM ; AT LOCATION IN REGISTER C, VALUE IN A. ; DSKY_PUTBYTE: PUSH BC PUSH AF LD A,C ADD A,DSKY_CMD_WDSP CALL DSKY_CMD POP AF XOR $FF CALL DSKY_DOUT POP BC RET ; ; READ A RAW BYTE VALUE FROM DSKY DISPLAY RAM ; AT LOCATION IN REGISTER C, VALUE RETURNED IN A ; DSKY_GETBYTE: PUSH BC LD A,C ADD A,DSKY_CMD_RDSP CALL DSKY_CMD CALL DSKY_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. ; DSKY_PUTSTR: PUSH BC LD A,C ADD A,DSKY_CMD_WDSP CALL DSKY_CMD POP BC ; DSKY_PUTSTR1: LD A,(HL) XOR $FF INC HL PUSH BC CALL DSKY_DOUT POP BC DJNZ DSKY_PUTSTR1 RET ; ; READ A STRING OF RAW BYTE VALUES FROM DSKY DISPLAY RAM ; AT LOCATION IN REGISTER C, LENGTH IN B, ADDRESS IN HL. ; DSKY_GETSTR: PUSH BC LD A,C ADD A,DSKY_CMD_RDSP CALL DSKY_CMD POP BC ; DSKY_GETSTR1: PUSH BC CALL DSKY_DIN POP BC XOR $FF LD (HL),A INC HL DJNZ DSKY_GETSTR1 RET ; ; HL IS ADR OF ENCODED STRING OF BYTES ; B IS LEN OF STRING (BYTES) ; C IS POSITION IN DISPLAY RAM TO WRITE ; DSKY_PUTENCSTR: PUSH BC LD A,C ADD A,DSKY_CMD_WDSP CALL DSKY_CMD POP BC EX DE,HL DSKY_PUTENCSTR1: LD A,(DE) INC DE LD HL,HEXMAP CALL ADDHLA LD A,(HL) XOR $FF PUSH BC CALL DSKY_DOUT POP BC DJNZ DSKY_PUTENCSTR1 RET ; ; TOGGLE LED AT ROW (B) AND COLUMN (C) ; DSKY_TOGLED: ; CONVERT B (ROW) TO BIT VALUE XOR A INC B SCF DSKY_TOGLED1: RLA DJNZ DSKY_TOGLED1 LD B,A ; LED COLS START AT 8 LD A,8 ADD A,C LD C,A ; FLIP THE BIT CALL DSKY_GETBYTE ; GET CURRENT COL BITMAP XOR B ; FLIP DESIRED BIT CALL DSKY_PUTBYTE ; WRITE VLAUE BACK TO COLUMN RET ; ; READ AND PRINT DISPLAY RAM (RAW BYTES) ; DSKY_READ: CALL PRTSTRD .DB "\r\nRead display RAM: $" LD B,16 ; 16 BYTES LD C,0 ; POSITION 0 LD HL,DSPBUF CALL DSKY_GETSTR LD B,$10 LD HL,DSPBUF DSKY_READ1: LD A,(HL) INC HL CALL PC_SPACE CALL PRTHEXBYTE DJNZ DSKY_READ1 RET ; ; ; GET_BASE: CALL PRTSTRD .DB "\r\nDSKYng PPI base port [0x$" LD A,(PPI_BASE) CALL PRTHEXBYTE CALL PRTSTRD .DB "]: $" LD A,(PPI_BASE) CALL GETHEXBYTE JR C,GET_BASE1 LD (PPI_BASE),A XOR A RET ; GET_BASE1: CALL PRTSTRD .DB "\r\nInvalid DSKYng PPI base port value!$" JR GET_BASE ; ; OUTPUT CHARACTER FROM A ; COUT: PUSH AF ; PUSH BC ; PUSH DE ; PUSH HL ; #IF (BDOS) LD C,2 ; BDOS FUNC: CONSOLE OUTPUT LD E,A ; CHARACTER TO E CALL $0005 ; CALL BDOS #ELSE LD C,A COUT1: IN A,(UART_BASE + 05H) ; READ LINE STATUS REGISTER AND 20H ; TEST IF UART IS READY TO SEND JP Z,COUT1 ; IF NOT REPEAT LD A,C ; GET TO ACCUMULATOR OUT (UART_BASE),A ; THEN WRITE THE CHAR TO UART (UART0 = 068h + $00) #ENDIF POP HL ; POP DE ; POP BC ; POP AF ; RET ; DONE ; ; INPUT CHARACTER TO A ; CIN: PUSH BC ; PUSH DE ; PUSH HL ; #IF BDOS CIN1: LD C,6 ; BDOS FUNC: DIRECT CONSOLE I/O LD E,$FF ; SET FOR INPUT CALL $0005 ; CALL BDOS, CHARACTER TO A OR A ; CHECK FOR NO CHAR, $00 JR Z,CIN1 ; LOOP TIL WE GET A CHAR #ELSE CIN1: CALL CST ; IS A CHAR READY TO BE READ FROM UART? CP 00H ; JP Z,CIN1 ; NO? TRY AGAIN IN A,(UART_BASE) ; YES? READ THE CHAR FROM THE UART (UART0 = 068h + $00) #ENDIF POP HL ; POP DE ; POP BC ; RET ; DONE ; ; RETURN INPUT STATUS IN A (0 = NO CHAR, !=0 CHAR WAITING) ; CST: PUSH BC ; PUSH DE ; PUSH HL ; #IF BDOS LD C,$0B ; BDOS FUNC: GET CONSOLE STATUS CALL $0005 ; CALL BDOS OR A ; SET FLAGS #ELSE ; CONSOLE STATUS, RETURN 0FFH IF CHARACTER READY, 00H IF NOT IN A,(UART_BASE + 05H) ; READ LINE STATUS REGISTER (UART5 = 068h + $05) AND 01H ; TEST IF DATA IN RECEIVE BUFFER ; IS THERE A CHAR READY? 0=NO, 1=YES JP Z,CST1 ; LD A,0FFH ; YES, PUT 0FFh IN A AND RETURN CST1: ; ; NO, LEAVE 000h IN A AND RETURN #ENDIF POP HL ; POP DE ; POP BC ; RET ; DONE ; ; WAIT FOR A KEY ; WAITKEY: PUSH AF CALL PRTSTRD .DB ", press a key to continue...$" CALL CIN CP $1B JP Z,EXIT POP AF RET ; ;================================================================================================== ; UTILITY FUNCTIONS ;================================================================================================== ; ; CHR_BEL: .EQU 07H CHR_CR: .EQU 0DH CHR_LF: .EQU 0AH CHR_BS: .EQU 08H CHR_ESC: .EQU 1BH ; ;__________________________________________________________________________________________________ ; ; UTILITY PROCS TO PRINT SINGLE CHARACTERS WITHOUT TRASHING ANY REGISTERS ; PC_SPACE: PUSH AF LD A,' ' JR PC_PRTCHR PC_PERIOD: PUSH AF LD A,'.' JR PC_PRTCHR PC_COLON: PUSH AF LD A,':' JR PC_PRTCHR PC_COMMA: PUSH AF LD A,',' JR PC_PRTCHR PC_LBKT: PUSH AF LD A,'[' JR PC_PRTCHR PC_RBKT: PUSH AF LD A,']' JR PC_PRTCHR PC_LT: PUSH AF LD A,'<' JR PC_PRTCHR PC_GT: PUSH AF LD A,'>' JR PC_PRTCHR PC_LPAREN: PUSH AF LD A,'(' JR PC_PRTCHR PC_RPAREN: PUSH AF LD A,')' JR PC_PRTCHR PC_ASTERISK: PUSH AF LD A,'*' JR PC_PRTCHR PC_CR: PUSH AF LD A,CHR_CR JR PC_PRTCHR PC_LF: PUSH AF LD A,CHR_LF JR PC_PRTCHR PC_PRTCHR: CALL COUT POP AF RET NEWLINE2: CALL NEWLINE NEWLINE: CALL PC_CR CALL PC_LF RET ; ; PRINT A CHARACTER REFERENCED BY POINTER AT TOP OF STACK ; USAGE: ; CALL PRTCH ; DB 'X' ; PRTCH: EX (SP),HL PUSH AF LD A,(HL) CALL COUT POP AF INC HL EX (SP),HL RET ; ; PRINT A STRING AT ADDRESS SPECIFIED IN HL ; STRING MUST BE TERMINATED BY '$' ; USAGE: ; LD HL,MYSTR ; CALL PRTSTR ; ... ; MYSTR: DB "HELLO$" ; PRTSTR: LD A,(HL) INC HL CP '$' RET Z CALL COUT JR PRTSTR ; ; PRINT A STRING DIRECT: REFERENCED BY POINTER AT TOP OF STACK ; STRING MUST BE TERMINATED BY '$' ; USAGE: ; CALL PRTSTRD ; DB "HELLO$" ; ... ; PRTSTRD: EX (SP),HL PUSH AF CALL PRTSTR POP AF EX (SP),HL RET ; ; PRINT A STRING INDIRECT: REFERENCED BY INDIRECT POINTER AT TOP OF STACK ; STRING MUST BE TERMINATED BY '$' ; USAGE: ; CALL PRTSTRI(MYSTRING) ; MYSTRING DB "HELLO$" ; PRTSTRI: EX (SP),HL PUSH AF LD A,(HL) INC HL PUSH HL LD H,(HL) LD L,A CALL PRTSTR POP HL INC HL POP AF EX (SP),HL RET ; ; PRINT THE HEX BYTE VALUE IN A ; PRTHEXBYTE: PUSH AF PUSH DE CALL HEXASCII LD A,D CALL COUT LD A,E CALL COUT POP DE POP AF RET ; ; PRINT THE HEX WORD VALUE IN BC ; PRTHEXWORD: PUSH AF LD A,B CALL PRTHEXBYTE LD A,C CALL PRTHEXBYTE POP AF RET ; ; PRINT THE HEX WORD VALUE IN HL ; PRTHEXWORDHL: PUSH AF LD A,H CALL PRTHEXBYTE LD A,L CALL PRTHEXBYTE POP AF RET ; ; CONVERT BINARY VALUE IN A TO ASCII HEX CHARACTERS IN DE ; HEXASCII: LD D,A CALL HEXCONV LD E,A LD A,D RLCA RLCA RLCA RLCA CALL HEXCONV LD D,A RET ; ; CONVERT LOW NIBBLE OF A TO ASCII HEX ; HEXCONV: AND 0FH ;LOW NIBBLE ONLY ADD A,90H DAA ADC A,40H DAA RET ; ; ; GETHEXBYTE: PUSH AF ; SAVE INCOMING VALUE LD C,0AH ; BDOS READ CONSOLE BUFFER LD DE,CONBUF CALL 5 ; GET EDITED STRING CALL NEWLINE POP DE ; RESTORE INCOMING TO D ; OK WE SHOULD NOW HAVE A STRING WITH A HEX NUMBER LD HL,CONBUF INC HL LD A,(HL) ; GET CHARACTER COUNT INC HL CP 3 JR C,GHB0 ; OK IF <= 2 CHARS SCF ; SIGNAL ERROR RET ; AND RETURN GHB0: OR A ; SET FLAGS JR NZ,GHB1 ; GOT CHARS, GO AHEAD LD A,D ; RESTORE INCOMING VALUE OR A ; SIGNAL SUCCESS RET ; AND DONE GHB1: LD B,A ; COUNT TO B LD C,0 ; INITIAL VALUE GHB2: LD A,(HL) ; GET NEXT CHAR INC HL CALL ISHEX RET C ; ABORT ON NON-HEX CHAR ; OK WE ARE HERE WHEN WE HAVE A VALID CHARACTER (0-9,A-F,A-F) NEED TO CONVERT TO BINARY ; CHARACTER IS STILL IN A CP 3AH ; TEST FOR 0-9 JP M,GHB2C CP 47H ; TEST FOR A-F JP M,GHB2B CP 67H ; TEST FOR A-F JP M,GHB2A GHB2A: SUB 20H ; CHARACTER IS A-F GHB2B: SUB 07H ; CHARACTER IS A-F GHB2C: SUB 30H ; CHARACTER IS 0-9 RLC C ; MULTIPLY CUR VALUE BY 16 RLC C RLC C RLC C ADD A,C ; ADD TO ACCUM LD C,A ; PUT BACK IN C DJNZ GHB2 ; LOOP THRU ALL CHARS LD A,C ; INTO A FOR RETURN OR A ; SIGNAL SUCCESS RET ; DONE ISHEX: CP 30H ; CHECK IF LESS THAN CHARACTER 0 JP M,NOTHEX CP 3AH ; CHECK FOR > 9 JP M,ISHX1 ; OK, CHARACTER IS 1-9 CP 41H ; CHECK FOR CHARACTER LESS THAN A JP M,NOTHEX CP 47H ; CHECK FOR CHARACTERS > F JP M,ISHX1 CP 61H ; CHECK FOR CHARACTERS < A JP M,NOTHEX CP 67H ; CHECK FOR CHARACTER > F JP M,ISHX1 NOTHEX: SCF ; SET CARRY TO INDICATE FAIL RET ISHX1: SCF CCF RET ; ; SHORT DELAY FUNCTIONS. NO CLOCK SPEED COMPENSATION, SO THEY ; WILL RUN LONGER ON SLOWER SYSTEMS. THE NUMBER INDICATES THE ; NUMBER OF CALL/RET INVOCATIONS. A SINGLE CALL/RET IS ; 27 T-STATES ON A Z80, 25 T-STATES ON A Z180 ; ; ; Z80 Z180 ; ; ---- ---- DLY64: CALL DLY32 ; 1728 1600 DLY32: CALL DLY16 ; 864 800 DLY16: CALL DLY8 ; 432 400 DLY8: CALL DLY4 ; 216 200 DLY4: CALL DLY2 ; 108 100 DLY2: CALL DLY1 ; 54 50 DLY1: RET ; 27 25 ; ; ADD HL,A ; ; A REGISTER IS DESTROYED! ; ADDHLA: ADD A,L LD L,A RET NC INC H RET ; ; STORAGE ; PPI_BASE: .DB PPI_BASE_DEF ; CONBUF: .DB 8 ; MAXIMUM CHARS .DB 0 ; COUNT .FILL 8 ; SIZE OF BUFFER ; PPIX_VAL: .DB 0 ; DSPBUF: .FILL 16,0 ; PAT1: .DB $01,$02,$04,$08,$10,$20,$40,$80 .DB $11,$22,$44,$88,$00,$00,$00,$00 PAT1LN: .EQU $ - PAT1 PAT2: .DB $01,$03,$07,$0F,$1F,$3F,$7F,$FF .DB $11,$33,$77,$FF,$00,$00,$00,$00 PAT2LN: .EQU $ - PAT2 PAT3: .DB $FE,$FD,$FB,$F7,$EF,$DF,$BF,$7F .DB $77,$BB,$DD,$EE,$00,$00,$00,$00 PAT3LN: .EQU $ - PAT3 BLANK: .DB $00,$00,$00,$00,$00,$00,$00,$00 .DB $00,$00,$00,$00,$00,$00,$00,$00 BLNKLN: .EQU $ - BLANK HEX1: .DB $0,$1,$2,$3,$4,$5,$6,$7 HEX1LN: .EQU $ - HEX1 HEX2: .DB $8,$9,$A,$B,$C,$D,$E,$F HEX2LN: .EQU $ - HEX2 ; HEXMAP: ; '0' '1' '2' '3' '4' '5' '6' '7' .DB $3F, $06, $5B, $4F, $66, $6D, $7D, $07 ; '8' '9' 'A' 'B' 'C' 'D' 'E' 'F' .DB $7F, $67, $77, $7C, $39, $5E, $79, $71 ; .DB $00 ; STACKSAV: .DW 0 STACKSIZ: .EQU $100 ; WE ARE A STACK PIG .FILL STACKSIZ,0 STACK: .EQU $ ; .END