; ;================================================================================================== ; DSKY V3 TEST APPLICATION ;================================================================================================== ; ; BUILD WITH TASM: ; tasm -t80 -g3 -fFF tstdsky.asm tstdsky.com tstdsky.lst ; ; z80asm -itstdsky.asm -ltstdsky.lst -otstdsky.com ; ; 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. ; DSKY_OSC: EQU 2000000 ; OSCILLATOR FREQ IN HZ ; BDOS: EQU FALSE ; BDOS OR DIRECT TO 8250ISH ; UART: EQU $68 ; UART BASE IO ADDRESS PPI_BASE: EQU $60 ; PPI BASE IO PORT ; ; LED SEGMENTS (BIT VALUES) ; ; +--01--+ ; 20 02 ; +--40--+ ; 10 04 ; +--08--+ 80 ; ; KEY CODE MAP (KEY CODES) --CCCRRR ; ; 00 08 10 18 ; 01 09 11 19 ; 02 0A 12 1A ; 03 0B 13 1B ; 04 0C 14 1C ; 05 0D 15 1D ; ; LED BIT MAP (BIT VALUES) ; ; $08 $09 $0A $0B ; --- --- --- --- ; 01 01 01 01 ; 02 02 02 02 ; 04 04 04 04 ; 08 08 08 08 ; 10 10 10 10 ; 20 20 20 20 ; FALSE: EQU 0 TRUE: EQU ~FALSE ; PPIA: EQU PPI_BASE + 0 ; PORT A PPIB: EQU PPI_BASE + 1 ; PORT B PPIC: EQU PPI_BASE + 2 ; PORT C PPIX: EQU PPI_BASE + 3 ; PIO CONTROL PORT ; 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 /RD /WR CS CS 0 0 A0 ; ; SETTING BITS 3 & 4 WILL ASSERT /CS ON 3279 ; CLEAR BITS 5 OR 6 TO ASSERT READ/WRITE ; DSKY_PPI_IDLE: EQU %01100000 ; 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 Test Program, v1.2, 2021-06-26$" CALL PRTSTRD DB "\r\nPPI 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 JR 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 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: --CCCRRR 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 E,$01 ; STARTING VALUE M5: CALL CST ; CONSOLE STATUS JR NZ,M8 ; ABORT IF KEY PRESSED LD B,12 ; 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 ; EXIT: ; ; CLEAR ALL LD A,DSKY_CMD_CLR CALL DSKY_CMD ; ; 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 ; ; CHECK FOR WRITE MODE LD A,(DSKY_PPIX_VAL) CP DSKY_PPIX_WR JR Z,DSKY_PPIWR1 ; ; SET PPI TO WRITE MODE LD A,DSKY_PPIX_WR OUT (PPIX),A LD (DSKY_PPIX_VAL),A ; ; RESTORE PORT C (MAY NOT BE NEEDED) LD A,DSKY_PPI_IDLE OUT (PPIC),A ; ; ; DIAGNOSTIC ; LD A,'W' ; CALL COUT ; DSKY_PPIWR1: ; 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 ; ; CHECK FOR READ MODE LD A,(DSKY_PPIX_VAL) CP DSKY_PPIX_RD JR Z,DSKY_PPIRD1 ; ; SET PPI TO READ MODE LD A,DSKY_PPIX_RD OUT (PPIX),A LD (DSKY_PPIX_VAL),A ; ; ; DIAGNOSTIC ; LD A,'R' ; CALL COUT ; DSKY_PPIRD1: 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: ; ; SETUP PPI CALL DSKY_PPIRD ; INIT 8279 VALUES TO IDLE STATE LD A,DSKY_PPI_IDLE OUT (PPIC),A ; PULSE RESET SIGNAL ON 8279 SET 7,A OUT (PPIC),A RES 7,A OUT (PPIC),A ; DONE CALL DSKY_PPIIDLE 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 C,PPIC ; ; 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 POP AF OUT (PPIA),A ; ; PULSE /WR RES 5,B OUT (C),B NOP ; MAY NOT BE NEEDED SET 5,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 C,PPIC ; ; 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 6,B OUT (C),B ; ; GET VALUE IN A,(PPIA) ; ; DEASSERT /RD SET 6,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 ; ; 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 + 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),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) ; 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 + 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 POP AF RET ; ; ; USEDELAY: EQU FALSE INCLUDE "./SOFTWARE/util.asm" ; ; STORAGE ; DSKY_PPIX_VAL: DB 0 ; DSPBUF: DS 16,0 ; PAT1: DB $01,$02,$04,$08,$10,$20,$40,$80 DB $11,$22,$44,$88,$FF,$FF,$FF,$FF 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 DS STACKSIZ,0 STACK: EQU $ ; END