ZX Forum #04
19 ноября 1997 |
|
world of sound Spectrum - Chapter 4.9: audio playback interrupt.
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.
Other articles:
Similar articles:
В этот день... 21 November