Prev: 00819 Up: Map Next: 01016
00949: THE 'BEEPER' SUBROUTINE
Used by the routines at BEEP, EDITOR, ED_ERROR and ED_COPY.
The loudspeaker is activated by having D4 low during an 'OUT' instruction that is using port 254. When D4 is high in a similar situation the loudspeaker is deactivated. A 'beep' can therefore be produced by regularly changing the level of D4.
Consider now the note 'middle C' which has the frequency 261.63 Hz. In order to get this note the loudspeaker will have to be alternately activated and deactivated every 1/523.26th of a second. In the Spectrum the system clock is set to run at 3.5 MHz. and the note of 'middle C' will require that the requisite 'OUT' instruction be executed as close as possible to every 6689 T states. This last value, when reduced slightly for unavoidable overheads, represents the 'length of the timing loop' in this subroutine.
This subroutine is entered with the DE register pair holding the value 'f*t', where a note of given frequency 'f' is to have a duration of 't' seconds, and the HL register pair holding a value equal to the number of T states in the 'timing loop' divided by 4, i.e. for the note 'middle C' to be produced for one second DE holds 261 (INT(261.3*1)) and HL holds 1642 (derived from 6689/4-30.125).
Input
DE Number of passes to make through the sound generation loop
HL Loop delay parameter
BEEPER 00949 DI Disable the interrupt for the duration of a 'beep'.
00950 LD A,L Save L temporarily.
00951 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.
00953 SRL L
00955 CPL Go back to the original value in L and find how many were lost by taking 3-(A mod 4).
00956 AND 3
00958 LD C,A
00959 LD B,0
00961 LD IX,977 The base address of the timing loop.
00965 ADD IX,BC Alter the length of the timing loop. Use an earlier starting point for each '1' lost by taking INT (L/4).
00967 LD A,(23624) Fetch the present border colour from BORDCR and move it to bits 2, 1 and 0 of the A register.
00970 AND 56
00972 RRCA
00973 RRCA
00974 RRCA
00975 OR 8 Ensure the MIC output is 'off'.
Now enter the sound generation loop. DE complete passes are made, i.e. a pass for each cycle of the note.
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.
00977 NOP Add 4 T states for each earlier entry point that is used.
00978 NOP
00979 NOP
00980 INC B The values in the B and C registers will come from the H and L registers - see below.
00981 INC C
BE_H_L_LP 00982 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.)
00983 JR NZ,BE_H_L_LP
00985 LD C,63
00987 DEC B
00988 JP NZ,BE_H_L_LP
The loudspeaker is now alternately activated and deactivated.
00991 XOR 16 Flip bit 4.
00993 OUT (254),A Perform the 'OUT' operation, leaving the border unchanged.
00995 LD B,H Reset the B register.
00996 LD C,A Save the A register.
00997 BIT 4,A Jump if at the half-cycle point.
00999 JR NZ,BE_AGAIN
After a full cycle the DE register pair is tested.
01001 LD A,D Jump forward if the last complete pass has been made already.
01002 OR E
01003 JR Z,BE_END
01005 LD A,C Fetch the saved value.
01006 LD C,L Reset the C register.
01007 DEC DE Decrease the pass counter.
01008 JP (IX) Jump back to the required starting location of the loop.
The parameters for the second half-cycle are set up.
BE_AGAIN 01010 LD C,L Reset the C register.
01011 INC C Add 16 T states as this path is shorter.
01012 JP (IX) Jump back.
Upon completion of the 'beep' the maskable interrupt has to be enabled.
BE_END 01014 EI Enable interrupt.
01015 RET Finally return.
Prev: 00819 Up: Map Next: 01016