mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 14:11:48 -06:00
Run time adjustement of tone frequencies for different cpu frequencies with the limitation that rounded down frequency is used. i.e. 4Mhz clock measured at 3.988Mhz will setup tone frequencies based on 3MHz cpu.
264 lines
6.4 KiB
NASM
264 lines
6.4 KiB
NASM
;
|
||
;======================================================================
|
||
; I/O BIT DRIVER FOR CONSOLE BELL FOR SBC V2 USING BIT 0 OF RTC DRIVER
|
||
;======================================================================
|
||
;
|
||
SPK_INIT:
|
||
CALL NEWLINE ; FORMATTING
|
||
PRTS("SPK: IO=0x$")
|
||
LD A,RTCIO
|
||
CALL PRTHEXBYTE
|
||
CALL SPK_SETTBL
|
||
CALL SPK_BEEP ; PLAY A NOTE
|
||
XOR A
|
||
RET
|
||
;
|
||
; SETUP THE SPEAKER NOTE TABLE ACCORDING TO THE CPU SPEED.
|
||
; FREQUENCY ACCURACY DECREASES AS CLOCK SPEED MULITPLIER INCREASES.
|
||
; 1MHZ ERROR MAY OCCUR IF CPU CLOCK IS UNDER. I.E 3.999 = 3MHZ
|
||
|
||
SPK_SETTBL:
|
||
LD A,(CB_CPUMHZ) ; GET CPU SPEED.
|
||
LD C,A
|
||
|
||
LD B,SPK_NOTCNT ; SET NUMBER OF NOTES TO
|
||
LD HL,SPK_TUNTBL+2 ; ADJUST AND START POINT
|
||
|
||
SPK_SETTBL2:
|
||
PUSH HL
|
||
LD A,(HL) ; READ
|
||
LD E,A ; IN
|
||
INC HL ; THE
|
||
LD A,(HL) ; 1MHZ
|
||
LD D,A ; NOTE
|
||
|
||
PUSH BC
|
||
LD B,C
|
||
LD HL,0 ; MULTIPLY
|
||
SPK_SETTBL1: ; 1MHZ NOTE
|
||
ADD HL,DE ; VALUE BY
|
||
DJNZ SPK_SETTBL1 ; SYSTEM MHZ
|
||
POP BC
|
||
;
|
||
LD DE,30 ; ADD OVEREAD
|
||
ADD HL,DE ; COMPENSATION
|
||
;
|
||
POP DE ; RECALL NOTE
|
||
EX DE,HL ; ADDRESS
|
||
;
|
||
LD (HL),E ; SAVE
|
||
INC HL ; THE
|
||
LD (HL),D ; NEW
|
||
INC HL ; NOTE
|
||
INC HL ; AND MOVE
|
||
INC HL ; TO NEXT
|
||
|
||
DJNZ SPK_SETTBL2 ; NEXT NOTE
|
||
RET
|
||
|
||
SPK_BEEP:
|
||
LD HL,SPK_NOTE_C8 ; SELECT NOTE
|
||
;
|
||
LD A,(HL) ; LOAD 1ST ARG
|
||
INC HL ; IN DE
|
||
LD E,A
|
||
LD A,(HL)
|
||
INC HL
|
||
LD D,A
|
||
;
|
||
LD A,(HL) ; LOAD 2ND ARG
|
||
INC HL ; IN BC
|
||
LD C,A
|
||
LD A,(HL)
|
||
INC HL
|
||
LD B,A
|
||
PUSH BC ; SETUP ARG IN HL
|
||
POP HL
|
||
;
|
||
CALL SPK_BEEPER ; PLAY
|
||
;
|
||
RET
|
||
;
|
||
; The following SPK_BEEPER routine is a modification of code from
|
||
; "The Complete SPECTRUM ROM DISSASSEMBLY" by Dr Ian Logan & Dr Frank O’Hara
|
||
;
|
||
; https://www.esocop.org/docs/CompleteSpectrumROMDisassemblyThe.pdf
|
||
;
|
||
; DE Number of passes to make through the sound generation loop
|
||
; HL Loop delay parameter
|
||
;
|
||
SPK_BEEPER:
|
||
PUSH IX
|
||
DI ; Disable the interrupt for the duration of a 'beep'.
|
||
LD A,L ; Save L temporarily.
|
||
SRL L ; Each '1' in the L register is to count 4 T states, but take INT (L/4) and count 16 T states instead.
|
||
SRL L
|
||
CPL ; Go back to the original value in L and find how many were lost by taking 3-(A mod 4).
|
||
AND $03
|
||
LD C,A
|
||
LD B,$00
|
||
LD IX,SPK_DLYADJ ; The base address of the timing loop.
|
||
ADD IX,BC ; Alter the length of the timing loop. Use an earlier starting point for each '1' lost by taking INT (L/4).
|
||
LD A,(RTCVAL) ; Fetch the present border colour from BORDCR and move it to bits 2, 1 and 0 of the A register.
|
||
;
|
||
; The HL register holds the 'length of the timing loop' with 16 T states being used for each '1' in the L register and 1024 T states for each '1' in the H register.
|
||
;
|
||
SPK_DLYADJ:
|
||
NOP ; Add 4 T states for each earlier entry point that is used.
|
||
NOP
|
||
NOP
|
||
INC B ; The values in the B and C registers will come from the H and L registers - see below.
|
||
INC C
|
||
BE_H_L_LP:
|
||
DEC C ; The 'timing loop', i.e. BC*4 T states. (But note that at the half-cycle point, C will be equal to L+1.)
|
||
JR NZ,BE_H_L_LP
|
||
LD C,$3F
|
||
DEC B
|
||
JP NZ,BE_H_L_LP
|
||
;
|
||
; The loudspeaker is now alternately activated and deactivated.
|
||
;
|
||
XOR %00000100 ; Flip bit 2.
|
||
OUT (RTCIO),A ; Perform the 'OUT' operation, leaving other bits unchanged.
|
||
LD B,H ; Reset the B register.
|
||
LD C,A ; Save the A register.
|
||
BIT 4,A ; Jump if at the half-cycle point.
|
||
JR NZ,BE_AGAIN
|
||
;
|
||
; After a full cycle the DE register pair is tested.
|
||
;
|
||
LD A,D ; Jump forward if the last complete pass has been made already.
|
||
OR E
|
||
JR Z,BE_END
|
||
LD A,C ; Fetch the saved value.
|
||
LD C,L ; Reset the C register.
|
||
DEC DE ; Decrease the pass counter.
|
||
JP (IX) ; Jump back to the required starting location of the loop.
|
||
;
|
||
; The parameters for the second half-cycle are set up.
|
||
;
|
||
BE_AGAIN:
|
||
LD C,L ; Reset the C register.
|
||
INC C ; Add 16 T states as this path is shorter.
|
||
JP (IX) ; Jump back.
|
||
BE_END:
|
||
EI
|
||
POP IX
|
||
RET
|
||
;
|
||
; STANDARD ONE SECOND TONE TABLES AT 1MHZ (UNCOMPENSATED). FOR SPK_BEEPER, FIRST WORD LOADED INTO DE, SECOND INTO HL
|
||
;
|
||
; EXCEL SPREADSHEET FOR CALCULATION CAN BE FOUND HERE:
|
||
;
|
||
; https://www.retrobrewcomputers.org/lib/exe/fetch.php?media=boards:sbc:sbc_v2:sbc_v2-004:spk_beep_tuntbl.xlsx
|
||
;
|
||
SPK_TUNTBL:
|
||
.DW $13, $191A ; D
|
||
.DW $14, $17B3 ; E0
|
||
.DW $15, $165E ; F0
|
||
.DW $17, $151E ; F
|
||
.DW $18, $13EE ; G0
|
||
.DW $19, $12CF ; G
|
||
.DW $1B, $11C1 ; A0
|
||
.DW $1D, $10C1 ; A
|
||
.DW $1E, $FD1 ; B0
|
||
.DW $20, $EEE ; C1
|
||
.DW $22, $E17 ; C
|
||
.DW $24, $D4D ; D1
|
||
.DW $26, $C8E ; D
|
||
.DW $29, $BD9 ; E1
|
||
.DW $2B, $B2F ; F1
|
||
.DW $2E, $A8E ; F
|
||
.DW $31, $9F7 ; G1
|
||
.DW $33, $968 ; G
|
||
.DW $37, $8E0 ; A1
|
||
.DW $3A, $861 ; A
|
||
.DW $3D, $7E8 ; B1
|
||
.DW $41, $777 ; C2
|
||
.DW $45, $70B ; C
|
||
.DW $49, $6A6 ; D2
|
||
.DW $4D, $647 ; D
|
||
.DW $52, $5EC ; E2
|
||
.DW $57, $597 ; F2
|
||
.DW $5C, $547 ; F
|
||
.DW $62, $4FB ; G2
|
||
.DW $67, $4B3 ; G
|
||
.DW $6E, $470 ; A2
|
||
.DW $74, $430 ; A
|
||
.DW $7B, $3F4 ; B2
|
||
.DW $82, $3BB ; C3
|
||
.DW $8A, $385 ; C
|
||
.DW $92, $353 ; D3
|
||
.DW $9B, $323 ; D
|
||
.DW $A4, $2F6 ; E3
|
||
.DW $AE, $2CB ; F3
|
||
.DW $B9, $2A3 ; F
|
||
.DW $C4, $27D ; G3
|
||
.DW $CF, $259 ; G
|
||
.DW $DC, $238 ; A3
|
||
.DW $E9, $218 ; A
|
||
.DW $F6, $1FA ; B3
|
||
.DW $105, $1DD ; C4
|
||
.DW $115, $1C2 ; C
|
||
.DW $125, $1A9 ; D4
|
||
.DW $137, $191 ; D
|
||
.DW $149, $17B ; E4
|
||
.DW $15D, $165 ; F4
|
||
.DW $171, $151 ; F
|
||
.DW $188, $13E ; G4
|
||
.DW $19F, $12C ; G
|
||
.DW $1B8, $11C ; A4
|
||
.DW $1D2, $10C ; A
|
||
.DW $1ED, $FD ; B4
|
||
.DW $20B, $EE ; C5
|
||
.DW $22A, $E1 ; C
|
||
.DW $24B, $D4 ; D5
|
||
.DW $26E, $C8 ; D
|
||
.DW $293, $BD ; E5
|
||
.DW $2BA, $B2 ; F5
|
||
.DW $2E3, $A8 ; F
|
||
.DW $30F, $9F ; G5
|
||
.DW $33E, $96 ; G
|
||
.DW $370, $8E ; A5
|
||
.DW $3A4, $86 ; A
|
||
.DW $3DB, $7E ; B5
|
||
.DW $416, $77 ; C6
|
||
.DW $454, $70 ; C
|
||
.DW $496, $6A ; D6
|
||
.DW $4DC, $64 ; D
|
||
.DW $526, $5E ; E6
|
||
.DW $574, $59 ; F6
|
||
.DW $5C7, $54 ; F
|
||
.DW $61F, $4F ; G6
|
||
.DW $67D, $4B ; G
|
||
.DW $6E0, $47 ; A6
|
||
.DW $748, $43 ; A
|
||
.DW $7B7, $3F ; B6
|
||
.DW $82D, $3B ; C7
|
||
.DW $8A9, $38 ; C
|
||
.DW $92D, $35 ; D7
|
||
.DW $9B9, $32 ; D
|
||
.DW $A4D, $2F ; E7
|
||
.DW $AE9, $2C ; F7
|
||
.DW $B8F, $2A ; F
|
||
.DW $C3F, $27 ; G7
|
||
.DW $CFA, $25 ; G
|
||
.DW $DC0, $23 ; A7
|
||
.DW $E91, $21 ; A
|
||
.DW $F6F, $1F ; B7
|
||
SPK_NOTE_C8:
|
||
.DW $105A, $1D ; C8
|
||
.DW $1152, $1C ; C
|
||
.DW $125A, $1A ; D8
|
||
.DW $1372, $19 ; D
|
||
.DW $149A, $17 ; E8
|
||
.DW $15D3, $16 ; F8
|
||
.DW $171F, $15 ; F
|
||
.DW $187F, $13 ; G8
|
||
.DW $19F4, $12 ; G
|
||
.DW $1B80, $11 ; A8
|
||
.DW $1D22, $10 ; A
|
||
.DW $1EDE, $F ; B8
|
||
|
||
SPK_NOTCNT .EQU ($-SPK_TUNTBL) / 4
|