;====================================================================== ; ; AY-3-8910 / YM2149 SOUND DRIVER ; ;====================================================================== ; #IF (AYMODE == AYMODE_SCG) AY_RSEL .EQU $9A AY_RDAT .EQU $9B AY_ACR .EQU $9C #ENDIF ; #IF (AYMODE == AYMODE_N8) AY_RSEL .EQU $9C AY_RDAT .EQU $9D AY_ACR .EQU N8_DEFACR #ENDIF ; #IF (AYMODE == AYMODE_RCZ80) AY_RSEL .EQU $D8 AY_RDAT .EQU $D0 #ENDIF ; #IF (AYMODE == AYMODE_RCZ180) AY_RSEL .EQU $68 AY_RDAT .EQU $60 #ENDIF ; ;====================================================================== ; ; REGISTERS ; AY_R0CHAP .EQU $00 AY_R1CHAP .EQU $01 AY_R2CHBP .EQU $02 AY_R3CHBP .EQU $03 AY_R7ENAB .EQU $07 AY_R8AVOL .EQU $08 AY_R9BVOL .EQU $09 ; ;====================================================================== ; ; DRIVER FUNCTION TABLE AND INSTANCE DATA ; AY_FNTBL: .DW AY_RESET .DW AY_VOLUME .DW AY_PERIOD .DW AY_NOTE .DW AY_PLAY .DW AY_QUERY #IF (($ - AY_FNTBL) != (SND_FNCNT * 2)) .ECHO "*** INVALID SND FUNCTION TABLE ***\n" !!!!! #ENDIF ; AY_IDAT .EQU 0 ; NO INSTANCE DATA ASSOCIATED WITH THIS DEVICE ; ;====================================================================== ; ; DEVICE CAPABILITIES AND CONFIGURATION ; SBCV2004 .EQU 1 ; USE SBC-V2-004 HALF CLOCK DIVIDER ; AY_TONECNT .EQU 3 ; COUNT NUMBER OF TONE CHANNELS AY_NOISECNT .EQU 1 ; COUNT NUMBER OF NOISE CHANNELS ; AY_CLKDIVIDER .EQU 2 AY_CLK .EQU CPUOSC / AY_CLKDIVIDER SN7RATIO .EQU AY_CLK * 100 / 32 AY_FIRST_NOTE .EQU 5827 ; A1# AY_LAST_NOTE .EQU 209300 ; C7 A1S .EQU SN7RATIO / AY_FIRST_NOTE C7 .EQU SN7RATIO / AY_LAST_NOTE .ECHO "AY-3-8910: range of A1# (period: " .ECHO A1S .ECHO ") to C7 (period: " .ECHO C7 .ECHO ")\n" AUDIOTRACE .SET TRUE #INCLUDE "audio.inc" ;====================================================================== ; ; DRIVER INITIALIZATION (THERE IS NO PRE-INITIALIZATION) ; ; ANNOUNCE DEVICE ON CONSOLE. ACTIVATE DEVICE IF REQUIRED. ; SETUP FUNCTION TABLES. SETUP THE DEVICE. ; ANNOUNCE DEVICE WITH BEEP. SET VOLUME OFF. ; RETURN SUCCESS STATUS ; AY38910_INIT: CALL NEWLINE ; ANNOUNCE PRTS("AY: IO=0x$") LD A,AY_RSEL CALL PRTHEXBYTE ; #IF ((AYMODE == AYMODE_SCG) | (AYMODE == AYMODE_N8)) ; ACTIVATE DEVICE LD A,$FF ; BIT 4 IS AY RESET CONTROL, BIT 3 IS ACTIVE LED OUT (AY_ACR),A ; SET INIT AUX CONTROL REG #ENDIF ; LD IY, AY_IDAT ; SETUP FUNCTION TABLE LD BC, AY_FNTBL ; POINTER TO INSTANCE DATA LD DE, AY_IDAT ; BC := FUNCTION TABLE ADDRESS CALL SND_ADDENT ; DE := INSTANCE DATA PTR ; CALL AY_RESET ; SET DEFAULT CHIP CONFIGURATION ; CALL AY_BEEP ; PLAY INITIALIZATION BEEP ; CALL AY_VOLUME_OFF ; MAKE QUIET ; RET ; ;====================================================================== ; SOUND DRIVER FUNCTION - RESET ;====================================================================== ; AY_RESET: AUDTRACE(TRACE_INIT) ; LD D,AY_R7ENAB ; SET MIXER CONTROL / IO ENABLE LD E,$F8 ; $F8 - 11 111 000 CALL AY_WRTPSG ; I/O PORTS = OUTPUT, NOISE CHANNEL C, B, A DISABLE, TONE CHANNEL C, B, A ENABLE ; CALL AY_VOLUME_OFF ; TURN VOLUME OFF ; RET ; AND RETURN SUCCESS AY_VOLUME_OFF: AUDTRACE(TRACE_VOLUME_OFF) LD B,AY_TONECNT ; NUMBER OF CHANNELS LD D,AY_R8AVOL ; BASE REGISTER FOR VOLUME LD E,$00 ; AMPLITUDE 0 AY_V: CALL AY_WRTPSG ; CYCLING THROUGH ALL CHANNELS INC D DJNZ AY_V ; XOR A ; SIGNAL SUCCESS RET ; ;====================================================================== ; SOUND DRIVER FUNCTION - VOLUME ;====================================================================== ; AY_VOLUME: AUDDEBUG("AY3VOL ") AUDTRACE_L AUDDEBUG("\r\n") LD A,L ; SAVE VOLUME LD (PENDING_VOLUME), A ; XOR A ; SIGNAL SUCCESS RET ; ;====================================================================== ; SOUND DRIVER FUNCTION - PERIOD ;====================================================================== ; AY_PERIOD: AUDDEBUG("AY3PRD ") AUDTRACE_HL AUDDEBUG("\r\n") LD A, H ; MAXIMUM TONE PERIOD IS 12-BITS CP $10 ; ALLOWED RANGE IS 0001-0FFF (4095) JP NC, AY_QUERY_PERIOD1 ; RETURN NZ IF NUMBER TOO LARGE LD (PENDING_PERIOD), HL ; SAVE AND XOR A ; SIGNAL SUCCESS RET AY_QUERY_PERIOD1: LD L, $FF LD H, L ; REQUESTED PERIOD IS LARGER LD (PENDING_PERIOD), HL ; THAN THE DEVICE CAN SUPPORT OR L ; SO SIGNAL FAILURE RET ; ;====================================================================== ; SOUND DRIVER FUNCTION - NOTE ;====================================================================== ; AY_NOTE: AUDDEBUG("AY3NOT ") AUDTRACE_L AUDDEBUG("\r\n") ADD HL, HL ; SHIFT RIGHT (MULT 2) -INDEX INTO AY3NOTETBL TABLE OF WORDS ; TEST IF HL IS LARGER THAN AY3NOTETBL SIZE OR A ; CLEAR CARRY FLAG LD DE, SIZ_AY3NOTETBL SBC HL, DE JR NC, AY_NOTE1 ; INCOMING HL DOES NOT MAP INTO AY3NOTETBL ADD HL, DE ; RESTORE HL LD E, L ; HL = AY3NOTETBL + HL LD D, H LD HL, AY3NOTETBL ADD HL, DE LD A, (HL) ; RETRIEVE PERIOD COUNT FROM AY3NOTETBL INC HL LD H, (HL) LD L, A JR AY_PERIOD ; APPLY PERIOD AY_NOTE1: OR $FF ; NOT IMPLEMENTED YET RET ; ;====================================================================== ; SOUND DRIVER FUNCTION - PLAY ;====================================================================== ; AY_PLAY: AUDDEBUG("AY3PLY ") AUDTRACE_D AUDDEBUG("\r\n") ; LD A, (PENDING_PERIOD + 1) ; CHECK THE HIGH BYTE OF THE PERIOD CP $FF JR Z, AY_PLAY1 ; PERIOD IS TOO LARGE, UNABLE TO PLAY CALL AY_APPLY_VOL CALL AY_APPLY_PRD ; XOR A ; SIGNAL SUCCESS RET ; AY_PLAY1: ; TURN CHANNEL VOL TO OFF AND STOP PLAYING LD A, (PENDING_VOLUME) PUSH AF XOR A LD (PENDING_VOLUME), A CALL AY_APPLY_VOL POP AF LD (PENDING_VOLUME), A ; OR $FF ; SIGNAL FAILURE RET ; ;====================================================================== ; SOUND DRIVER FUNCTION - QUERY AND SUBFUNCTIONS ;====================================================================== ; AY_QUERY: LD A, E CP BF_SNDQ_CHCNT ; SUB FUNCTION 01 JR Z, AY_QUERY_CHCNT ; CP BF_SNDQ_VOLUME ; SUB FUNCTION 02 JR Z, AY_QUERY_VOLUME ; CP BF_SNDQ_PERIOD ; SUB FUNCTION 03 JR Z, AY_QUERY_PERIOD ; CP BF_SNDQ_DEV ; SUB FUNCTION 04 JR Z, AY_QUERY_DEV ; OR $FF ; SIGNAL FAILURE RET ; AY_QUERY_CHCNT: LD B, AY_TONECNT ; RETURN NUMBER OF LD C, AY_NOISECNT ; TONE AND NOISE XOR A ; CHANNELS IN BC RET ; AY_QUERY_PERIOD: LD HL, (PENDING_PERIOD) ; RETURN 16-BIT PERIOD XOR A ; IN HL REGISTER RET ; AY_QUERY_VOLUME: LD A, (PENDING_VOLUME) ; RETURN 8-BIT VOLUME LD L, A ; IN L REGISTER XOR A LD H, A RET ; AY_QUERY_DEV: LD B, BF_SND_AY38910 ; RETURN DEVICE IDENTIFIER LD DE, (AY_RSEL*256)+AY_RDAT ; AND ADDRESS AND DATA PORT XOR A RET ; ;====================================================================== ; APPLY VOLUME TO CHANNEL IN D REGISTER ;====================================================================== ; AY_APPLY_VOL: PUSH DE PUSH BC PUSH AF ; LD A,D ; LIMIT CHANNEL 0-2 AND $3 ; AND INDEX TO THE ADD A,AY_R8AVOL ; CHANNEL VOLUME LD D,A ; REGISTER ; AUDTRACE(TRACE_REG_WR) AUDTRACE_A AUDTRACE(TRACE_NEWLINE) ; LD A, (PENDING_VOLUME) ; MAP THE VOLUME RRCA ; FROM 00-FF RRCA ; TO 00-0F RRCA RRCA AND $0F LD E,A ; CALL AY_WRTPSG ; SET VOL (E) IN CHANNEL REG (D) ; POP AF POP BC POP DE RET ; ;====================================================================== ; APPLY PERIOD TO CHANNEL IN D REGISTER ;====================================================================== ; AY_APPLY_PRD: PUSH DE PUSH BC PUSH AF ; LD A,D ; LIMIT CHANNEL 0-2 AND $3 ; AND INDEX TO THE ADD A,A ; CHANNEL REGISTER LD D,A ; FOR THE TONE PERIOD ; AUDTRACE(TRACE_REG_WR) AUDTRACE_A AUDTRACE(TRACE_NEWLINE) ; LD HL,(PENDING_PERIOD) ; WRITE THE LOWER LD E,L ; 8-BITS OF THE TONE PERIOD CALL AY_WRTPSG INC D LD E,H ; WRITE THE UPPER CALL AY_WRTPSG ; 8-BITS OF THE TONE PERIOD ; POP AF POP BC POP DE RET ; ;====================================================================== ; ; WRITE DATA IN E REGISTER TO DEVICE REGISTER D ; INTERRUPTS DISABLE DURING WRITE. WRITE IN SLOW MODE IF Z180 CPU. ; ;====================================================================== ; AY_WRTPSG: HB_DI #IF (SBCV2004) LD A,8 ; SBC-V2-004 CHANGE OUT (112),A ; TO HALF CLOCK SPEED #ENDIF #IF (CPUFAM == CPU_Z180) IN0 A,(Z180_DCNTL) ; GET WAIT STATES PUSH AF ; SAVE VALUE OR %00110000 ; FORCE SLOW OPERATION (I/O W/S=3) OUT0 (Z180_DCNTL),A ; AND UPDATE DCNTL #ENDIF LD A,D ; SELECT THE REGISTER WE OUT (AY_RSEL),A ; WANT TO WRITE TO LD A,E ; WRITE THE VALUE TO OUT (AY_RDAT),A ; THE SELECTED REGISTER #IF (CPUFAM == CPU_Z180) POP AF ; GET SAVED DCNTL VALUE OUT0 (Z180_DCNTL),A ; AND RESTORE IT #ENDIF #IF (SBCV2004) LD A,0 ; SBC-V2-004 CHANGE TO OUT (112),A ; NORMAL CLOCK SPEED #ENDIF HB_EI RET ; ;====================================================================== ; PENDING_PERIOD .DW 0 ; PENDING PERIOD (12 BITS) PENDING_VOLUME .DB 0 ; PENDING VOL (8 BITS) #IF AUDIOTRACE TRACE_INIT .DB "\r\nAY_INIT CALLED\r\n$" TRACE_VOLUME_OFF .DB "\r\nAY_VOLUME_OFF\r\n$" TRACE_VOLUME_SET .DB "\r\nAY_VOLUME_SET CH: $" TRACE_PLAY .DB "\r\nPLAY\r\n$" TRACE_VOLUME .DB ", VOL: $" TRACE_REG_WR .DB "\r\nOUT AY-3-8910 $" TRACE_PERIOD_SET .DB "\r\nAY_PERIOD_SET CH: $" TRACE_PERIOD .DB ", PERIOD: $" TRACE_NEWLINE .DB "\r\n$" #ENDIF ; THE FREQUENCY BY QUATER TONE STARTING AT A1# AY3NOTETBL: .DW A1S .DW SN7RATIO / 5912 .DW SN7RATIO / 5998 .DW SN7RATIO / 6085 .DW SN7RATIO / 6174 .DW SN7RATIO / 6264 .DW SN7RATIO / 6355 .DW SN7RATIO / 6447 .DW SN7RATIO / 6541 .DW SN7RATIO / 6636 .DW SN7RATIO / 6733 .DW SN7RATIO / 6831 .DW SN7RATIO / 6930 .DW SN7RATIO / 7031 .DW SN7RATIO / 7133 .DW SN7RATIO / 7237 .DW SN7RATIO / 7342 .DW SN7RATIO / 7449 .DW SN7RATIO / 7557 .DW SN7RATIO / 7667 .DW SN7RATIO / 7778 .DW SN7RATIO / 7891 .DW SN7RATIO / 8006 .DW SN7RATIO / 8122 .DW SN7RATIO / 8241 .DW SN7RATIO / 8361 .DW SN7RATIO / 8482 .DW SN7RATIO / 8606 .DW SN7RATIO / 8731 .DW SN7RATIO / 8858 .DW SN7RATIO / 8987 .DW SN7RATIO / 9118 .DW SN7RATIO / 9250 .DW SN7RATIO / 9385 .DW SN7RATIO / 9521 .DW SN7RATIO / 9660 .DW SN7RATIO / 9800 .DW SN7RATIO / 9943 .DW SN7RATIO / 10087 .DW SN7RATIO / 10234 .DW SN7RATIO / 10383 .DW SN7RATIO / 10534 .DW SN7RATIO / 10687 .DW SN7RATIO / 10843 .DW SN7RATIO / 11000 .DW SN7RATIO / 11160 .DW SN7RATIO / 11322 .DW SN7RATIO / 11487 .DW SN7RATIO / 11654 .DW SN7RATIO / 11824 .DW SN7RATIO / 11995 .DW SN7RATIO / 12170 .DW SN7RATIO / 12347 .DW SN7RATIO / 12527 .DW SN7RATIO / 12709 .DW SN7RATIO / 12894 .DW SN7RATIO / 13081 .DW SN7RATIO / 13271 .DW SN7RATIO / 13464 .DW SN7RATIO / 13660 .DW SN7RATIO / 13859 .DW SN7RATIO / 14061 .DW SN7RATIO / 14265 .DW SN7RATIO / 14473 .DW SN7RATIO / 14683 .DW SN7RATIO / 14897 .DW SN7RATIO / 15113 .DW SN7RATIO / 15333 .DW SN7RATIO / 15556 .DW SN7RATIO / 15782 .DW SN7RATIO / 16012 .DW SN7RATIO / 16245 .DW SN7RATIO / 16481 .DW SN7RATIO / 16721 .DW SN7RATIO / 16964 .DW SN7RATIO / 17211 .DW SN7RATIO / 17461 .DW SN7RATIO / 17715 .DW SN7RATIO / 17973 .DW SN7RATIO / 18234 .DW SN7RATIO / 18500 .DW SN7RATIO / 18769 .DW SN7RATIO / 19042 .DW SN7RATIO / 19319 .DW SN7RATIO / 19600 .DW SN7RATIO / 19885 .DW SN7RATIO / 20174 .DW SN7RATIO / 20468 .DW SN7RATIO / 20765 .DW SN7RATIO / 21067 .DW SN7RATIO / 21373 .DW SN7RATIO / 21684 .DW SN7RATIO / 22000 .DW SN7RATIO / 22320 .DW SN7RATIO / 22645 .DW SN7RATIO / 22974 .DW SN7RATIO / 23308 .DW SN7RATIO / 23647 .DW SN7RATIO / 23991 .DW SN7RATIO / 24340 .DW SN7RATIO / 24694 .DW SN7RATIO / 25053 .DW SN7RATIO / 25418 .DW SN7RATIO / 25787 .DW SN7RATIO / 26163 .DW SN7RATIO / 26544 .DW SN7RATIO / 26930 .DW SN7RATIO / 27321 .DW SN7RATIO / 27718 .DW SN7RATIO / 28121 .DW SN7RATIO / 28530 .DW SN7RATIO / 28945 .DW SN7RATIO / 29366 .DW SN7RATIO / 29793 .DW SN7RATIO / 30226 .DW SN7RATIO / 30666 .DW SN7RATIO / 31113 .DW SN7RATIO / 31566 .DW SN7RATIO / 32025 .DW SN7RATIO / 32490 .DW SN7RATIO / 32963 .DW SN7RATIO / 33442 .DW SN7RATIO / 33929 .DW SN7RATIO / 34422 .DW SN7RATIO / 34923 .DW SN7RATIO / 35431 .DW SN7RATIO / 35946 .DW SN7RATIO / 36469 .DW SN7RATIO / 36999 .DW SN7RATIO / 37537 .DW SN7RATIO / 38083 .DW SN7RATIO / 38637 .DW SN7RATIO / 39200 .DW SN7RATIO / 39770 .DW SN7RATIO / 40349 .DW SN7RATIO / 40936 .DW SN7RATIO / 41530 .DW SN7RATIO / 42134 .DW SN7RATIO / 42747 .DW SN7RATIO / 43369 .DW SN7RATIO / 44000 .DW SN7RATIO / 44640 .DW SN7RATIO / 45289 .DW SN7RATIO / 45948 .DW SN7RATIO / 46616 .DW SN7RATIO / 47294 .DW SN7RATIO / 47982 .DW SN7RATIO / 48680 .DW SN7RATIO / 49388 .DW SN7RATIO / 50106 .DW SN7RATIO / 50835 .DW SN7RATIO / 51575 .DW SN7RATIO / 52325 .DW SN7RATIO / 53086 .DW SN7RATIO / 53858 .DW SN7RATIO / 54642 .DW SN7RATIO / 55437 .DW SN7RATIO / 56243 .DW SN7RATIO / 57061 .DW SN7RATIO / 57891 .DW SN7RATIO / 58733 .DW SN7RATIO / 59587 .DW SN7RATIO / 60454 .DW SN7RATIO / 61333 .DW SN7RATIO / 62225 .DW SN7RATIO / 63130 .DW SN7RATIO / 64048 .DW SN7RATIO / 64980 .DW SN7RATIO / 65925 .DW SN7RATIO / 66884 .DW SN7RATIO / 67857 .DW SN7RATIO / 68844 .DW SN7RATIO / 69846 .DW SN7RATIO / 70862 .DW SN7RATIO / 71893 .DW SN7RATIO / 72938 .DW SN7RATIO / 73999 .DW SN7RATIO / 75075 .DW SN7RATIO / 76167 .DW SN7RATIO / 77275 .DW SN7RATIO / 78399 .DW SN7RATIO / 79539 .DW SN7RATIO / 80696 .DW SN7RATIO / 81870 .DW SN7RATIO / 83061 .DW SN7RATIO / 84269 .DW SN7RATIO / 85495 .DW SN7RATIO / 86738 .DW SN7RATIO / 88000 .DW SN7RATIO / 89280 .DW SN7RATIO / 90579 .DW SN7RATIO / 91896 .DW SN7RATIO / 93233 .DW SN7RATIO / 94589 .DW SN7RATIO / 95965 .DW SN7RATIO / 97361 .DW SN7RATIO / 98777 .DW SN7RATIO / 100214 .DW SN7RATIO / 101671 .DW SN7RATIO / 103150 .DW SN7RATIO / 104650 .DW SN7RATIO / 106172 .DW SN7RATIO / 107716 .DW SN7RATIO / 109283 .DW SN7RATIO / 110873 .DW SN7RATIO / 112486 .DW SN7RATIO / 114122 .DW SN7RATIO / 115782 .DW SN7RATIO / 117466 .DW SN7RATIO / 119175 .DW SN7RATIO / 120908 .DW SN7RATIO / 122667 .DW SN7RATIO / 124451 .DW SN7RATIO / 126261 .DW SN7RATIO / 128098 .DW SN7RATIO / 129961 .DW SN7RATIO / 131851 .DW SN7RATIO / 133769 .DW SN7RATIO / 135715 .DW SN7RATIO / 137689 .DW SN7RATIO / 139691 .DW SN7RATIO / 141723 .DW SN7RATIO / 143784 .DW SN7RATIO / 145876 .DW SN7RATIO / 147998 .DW SN7RATIO / 150151 .DW SN7RATIO / 152335 .DW SN7RATIO / 154550 .DW SN7RATIO / 156798 .DW SN7RATIO / 159079 .DW SN7RATIO / 161393 .DW SN7RATIO / 163740 .DW SN7RATIO / 166122 .DW SN7RATIO / 168538 .DW SN7RATIO / 170990 .DW SN7RATIO / 173477 .DW SN7RATIO / 176000 .DW SN7RATIO / 178560 .DW SN7RATIO / 181157 .DW SN7RATIO / 183792 .DW SN7RATIO / 186466 .DW SN7RATIO / 189178 .DW SN7RATIO / 191930 .DW SN7RATIO / 194722 .DW SN7RATIO / 197553 .DW SN7RATIO / 200426 .DW SN7RATIO / 203342 .DW SN7RATIO / 206299 .DW C7 SIZ_AY3NOTETBL .EQU $ - AY3NOTETBL .ECHO "SN76489 approx " .ECHO SIZ_AY3NOTETBL / 2 / 4 /12 .ECHO " Octaves. Last note index supported: " .ECHO SIZ_AY3NOTETBL / 2 .ECHO "\n"