4.9. Sound interrupt
All routines listed in the previous chapters, there is one
common drawback: while they are playing the main program
execution is suspended. This can be corrected, albeit with
difficulty, using the second interrupt mode. Those who know
what it is, may safely skip The following few paragraphs.
As mentioned earlier, fifty-
times per second the processor receives a signal
the need to call an interrupt. At the same time
He raises some routine after
which continues to handle the main program.
There are three different modes of interrupts: 0, 1 and 2,
which are selected teams IM 0, IM 1 and IM 2. Standard Mode is
number 1. About it has already been discussed in Chapter 3, but
just in case recall that in this mode as an interrupt handler
is used for routine ROM at 56 (# 38), which monitors keyboard
and a time counter. Mode 0 we do not interesting, since the
ZX-Spectrum it is similar to mode 1. But mode 2 is the fun
part!
In the second mode interrupt fifty
times per second the following occurs: the microprocessor reads
the data bus bytes called interrupt vectors. He transferred to
the low byte address bus, and byte written to the contents of
register I. By thus obtained at the processor reads from the
memory of two bytes, which is interpreted as address
Interrupt handling routine.
ZX-Spectrum is designed so that the vector
interruption is usually equal to 255 (# FF), but some external
device, such as, AMXmouse, may generate other vector. In
addition, some low-quality Spectrum interrupt vector can vary
completely randomly.
Based on the foregoing, it is possible
propose the following sequence
Action to set its own interrupt routines:
1. Disable interrupts.
2. Written in the memory address of the handler
interrupts.
3. Set in the I register high byte of the address pointer to
the handler.
4. Install a second interrupt mode.
5. Enable interrupts.
But to return to standard mode
interrupt handling must comply with such
steps:
1. Disable interrupts.
2. I write to the register number 63.
3. Set the first trap mode.
4. Enable interrupts.
Since the interrupt vector can be changed, instead of
writing two bytes at a specified address built up an entire
table of 257 bytes in size so as that for any value of the
vector is read the same address. Clearly, for this table all
the bytes must be identical.
In drawing up procedures for handling interrupts should
adhere to certain rules. First, the interrupt handler
should be carried out in a relatively short
period of time. Secondly, all the registers used in the handler
before return should take the values that were in them before
calling an interrupt. In therefore not recommended access
ROM routines, at least until
as long as you do not know exactly,
what they use and what registers
system variables at the same time can be
changed. Subroutine call ROM is not desirable also because some
of them permit termination, which does not
permissible to avoid the call handler
from itself. Each handler must
work with interruptions prohibited.
However, use the DI in the
beginning of the procedure is not necessary, since
This is done automatically and you need to think only about the
resolution of the interrupt before exiting.
If you do not want to lose the opportunities offered by the
standard interrupt handler, you can use its sub command RST 56.
And when using interrupts in BASIC programs is a must,
otherwise it will the keypad is locked.
Now understand, what we may be
useful interruption.
If you specify a sequence of sounds and each is interrupted
play a short part of it, you get a pretty good effect in
parallel with program sound. Each part should be really short
otherwise the good of the interrupt will not be.
We agree that the sequence of sounds will be given a block
of data in the following format: for each note in the block
Data should be two bytes. The first B - frequency (1 ... 253),
and the second byte - duration (0 ... 255). Additionally, you
may meet these control codes:
0 - to switch the tone / noise
254 - beginning of the cycle
255 - end of block
Initially, the program is configured to output a pure tone,
but if you need get noise, you can switch it
to reproduce the noise by inserting data
byte is equal to 0. To re-switch on the tone of byte 0 shall
meet again times.
When the program meets B 255, audio output, or cease, either
the entire sequence repeated again - depending on the specified
number of repetitions.
If the data block to meet code, 254
then for the next repetition effect will not start, and from
the place where this code met.
Now the program itself. It is a complete complex and can be
translated assembler without any changes: 1415.
10 ORG 60000
20 JP SINIT; connection interrupt
30 JP SSTOP; disabling interrupts
40 JP NEWFX; initialization effect
50 MUTE LD (COUNT), A; "Stub"
60 RET
70 SINIT XOR A
80 LD (COUNT), A
90 LD A, 24; command code JR
100 LD (65535), A
110 LD A, 195; instruction code JP
120 LD (65524), A
130 LD HL, INTR; HL = address of handler
140 LD (65525), HL
150 LD HL, 65024
160 LD DE, 65025
170 LD BC, 256
180 LD (HL), 255; address interrupt - 65535
190 LD A, H
200 LDIR; filling tables
210 DI
220 LD I, A
230 IM 2
240 EI
250 RET
260 SSTOP DI; disabling interrupts
270 LD A, 63
280 LD I, A
290 IM 1
300 EI
310 RET
320 NEWFX DI; initialization effect
330 LD (COUNT), A
340 XOR A
350 LD (FLAG), A
360 LD (ADDR), HL
370 LD (CURADD), HL
380 EI
390 RET
400 ADDR DEFW 0; starting address of the data block
410 CURADD DEFW 0; current address in the data
420 COUNT DEFB 0; reps
430 FLAG DEFB 0; flag tone / noise
440 INTR PUSH AF; interrupt handler
450 PUSH BC; preservation registers
460 PUSH DE
470 PUSH HL
480 TEST LD A, (COUNT); A = repeat count
490 OR A; have something to play?
500 JR Z, EXIT
510 LD HL, (CURADD); HL = current address
520 NEXT LD A, (HL)
530 INC HL
540 CP 254; A = 254? (Beginning of the cycle)
550 JR NZ, CONT1
560 LD (ADDR), HL; change the start address
570 JR NEXT
580 CONT1 CP 255; A = 255? (End)
590 JR NZ, CONT2
600 LD HL, (ADDR); recovery of the initial
610 LD (CURADD), HL; address data block
620 LD HL, COUNT
630 DEC (HL); decrease counter
repetitions
640 JR TEST
650 CONT2 OR A; A = 0? (Switch)
660 JR NZ, CONT3
670 LD A, (FLAG)
680 CPL; inverting A
690 LD (FLAG), A
700 JR NEXT
710 CONT3 LD B, A; B = frequency
720 LD C, (HL); C = duration
730 INC HL
740 LD (CURADD), HL; Save your current address
750 LD A, (FLAG); A = flag
760 OR A; A = 0?
770 LD A, 7; A = Border color
780 JR NZ, NOISE
790 TONE XOR 16; tone reproduction
800 OUT (254), A
810 PUSH BC
820 PAUSE DJNZ PAUSE
830 POP BC
840 DEC C
850 JR NZ, TONE
860 JR EXIT
870 NOISE LD HL, 1000; playback noise
880 LD D, A
890 NOIS2 LD A, (HL)
900 AND 248
910 OR D
920 OUT (254), A
930 PUSH BC
940 PAUS2 DJNZ PAUS2
950 POP BC
960 INC HL
970 DEC C
980 JR NZ, NOIS2
990 EXIT POP HL; restore registers
1000 POP DE
1010 POP BC
1020 POP AF
1030 RST 56; call standard
Handler
1040 RET; Returns
2
The procedure for using this package should be as follows.
At the beginning of the need call subroutine SINIT, which will
include the second interrupt mode. At that time, when you need
to get the sound to put in the HL register block address data
into register A - number of repetitions and call a subroutine
NEWFX. Then, if you for whatever reason, turn off the sound or
extend its sound, is entered in the register A new number of
reps, and call the subroutine MUTE. In addition, this
subroutine can be used to enable the latter sounding effect.
Upon completion of the work (or if the program provides
treatment to the floppy disk) should be call subroutine SSTOP,
which will restore the default mode interrupts.
JP Series teams at the beginning of the package is designed
for convenience. Thanks to her, all the routines in this
package can be caused by nearby locations:
SINIT - 60,000 (# EA60)
SSTOP - 60,003 (# EA63)
NEWFX - 60,006 (# EA66)
MUTE - 60,009 (# EA69)
Unfortunately, with the help of an interrupt can not get
enough of a pure tone. Therefore, and because the music is not
a data format, this program is unlikely can be used to create
music. But for the sound effects it just right.
Here is an example given
Program:
1415.
10 ORG 50000
CALL 20 60 000
30 LD HL, SNDFX
40 LD A, 3
CALL 50 60 006
60 RET
70 SNDFX DEFB 200,5,250,4,200,5,100,10,75,13,50,20,255
2
Line 70 can be replaced by the following:
1415.
70 SNDFX DEFB 50,20,75,13,100,10,200,5,250,4,50,20,255
2
And the last. If your program does not
a lot of moving objects on the screen
and the duration of the sound effect is quite small (about half
a second or less), then it can be used without interruption -
the delay will not be noticeable.