MZ-800 course Chapter 6 6. Musical applications In this chapter we shall discuss the musical functions of the SHARP. The SHARP has 3 chords and 6 octaves, so there are more than enough possibilities. All instructions that have something to do with making sounds or music will also be discussed in this chapter. An instruction like BEEP shall also come to the attention, because this instruction produces a short beep. 6.1 Port \$F2 The port responsible for making your SHARP produce sound and music is port \$F2. It is also known as the PSG-port, in which PSG stands for programmable sound generator. This generator consists of three normal, independent generators and one noise generator. Each generator also has a reducer with a range of 28 dB. From page A-7 up to A-9 of the manual you can also find a bit of information about the PSG. The way the PSG is discussed in the manual is not the most straight forward one, that is why we will discuss this port thoroughly in this chapter. Many books on the SHARP MZ-800 cover the PSG. We got our information from the manual, Alles ueber den MZ-800 from BBG, the book Programmeren in de Toongenerator from SCCE and the Technical Reference Manual from SHARP itself. Controlling port \$F2 is not straightforward. Most of the times some calculation is necessary to control this port properly. Each of the three tone generators contains a 10-bit wide counter that is software controllable and is used as a variable frequency divider. We can use a formula to convert the frequency to values that are usable by the PSG. The output of the formula consists of two values. One must be added to a value and then be sent to port \$F2 and the other one must be sent to port \$F2 directly. For each tone generator there is a default value to which the output of the formula must be added, these initial values are: 128 for tone generator 1. 160 for tone generator 2. 192 for tone generator 3. Now we will give a program which you can use to convert the frequency to the values used by the PSG. This program is from the book Alles ueber den MZ-800 from BBG. ```10 CLS 20 INPUT "Frequency in Hertz? "; FR 30 F0=11094/(FR/10) 40 B6=INT(F0/16) 50 B4=FRAC(F0/16)*16 60 IF FRAC(B4)>=.5 THEN B4=INT(B4)+1:ELSE B4=INT(B4) 70 IF FRAC(F0)>=.5 THEN F0=INT(F0)+1:ELSE F0=INT(F0) 80 PRINT "6 Bit part: "; B6 90 PRINT "4 Bit part: "; B4 100 PRINT "F0: "; F0 110 PRINT:PRINT:GOTO 20``` As you can see, a 4-bit and a 6-bit part are calculated. They add up to 10 bits which makes the 10 bit counter. The value of the 4 bits part is added to the initial value of the tone generator end the value of the 6 bits part is sent to port \$F2 separately. An example: You want to get a frequency of 442 Hz from tone generator 1. You use the program to calculate the 4 bits and the 6 bits part. Then you sent the calculated values to port \$F2 in the correct way and you will hear a tone with a frequency of 442 Hz. If you have done everything right, the 4 bits part will be 11 and the 6 bits part will be 15. Send the values to port \$F2 in the following manner: `OUT@\$F2,160+11:OUT@\$F2,15` You have sent a tone with a frequency of 442 Hz to tone generator 2, but you do not hear anything yet. This is because you still have to set the volume. For each tone generator there is a unique domain. Tone generator 1 : 144 - 159 Tone generator 2 : 176 - 191 Tone generator 3 : 208 - 223 Noise generator : 240 - 255 In this table the minimum value is the maximum volume for a tone generator. If for example you want to hear the tone of 442 Hz as loud as possible, you must enter: `OUT@\$F2,176` If you do not want to hear the tone at all, you enter: `OUT@\$F2,191` You can vary the volume of the tone from loud to inaudible in the following way: `OUT@\$F2,160+11:OUT@\$F2,15:FOR A=176 TO 191:OUT@\$F2,A:WAIT 150:NEXT A` You can also make a wave pattern by varying the volume from loud to soft, then from soft to loud and by repeating this. You will encounter this later on in this chapter. There is another important thing worth knowing and that is that it is not possible to use more than 3 generators at the same time. This means that you can produce 3 tones or 2 tones and one noise. With the NOISE instruction you can only produce 1 tone and 1 noise. By addressing port \$F2 directly you can do more than with a BASIC-instruction. As you see, addressing port \$F2 is not as difficult as it might seem at first glance. To play a piece of music by addressing port \$F2 is very difficult, for this end the BASIC-instruction MUSIC or a machine code routine is far more suitable. Both the MUSIC-instruction as well as the machine code solution will be discussed further on in this chapter. First we will discuss a whole scale of options for port \$F2. You can do about everything with this port, from the sound of a laser gun sounds to speech. Can the SHARP talk? Of course it can. It is just a matter of addressing port \$F2 in the right way and that is not easy. We shall not go in to the talking capabilities of the SHARP. Those who want to hear the SHARP talk are directed to programs like SPRACHUHR. Here are a couple of examples of all sorts of sounds we can make. Sometimes a short explanation will be present. Example 1: Launch This program produces the sound of a launching rocket. ```10 REM LAUNCH 20 INIT "CRT:M1":PAL 0,1:CURSOR 0,24 30 IF PEEK(\$4DCF)>1 THEN PO=\$4DD0 ELSE PO=\$4DCF 40 POKE PO,\$1:SYMBOL 152,184,CHR\$(60),2,2:POKE PO,\$0 50 P=242:REM P=port \$F2 60 GOSUB "DELETE" 70 FOR A=0 TO 15 80 OUT@P,231:OUT@P,240 90 PRINT 100 FOR A=192 TO 207 110 OUT@P,A:OUT@P,L 120 NEXT A:PRINT 130 OUT@P,(L+240) 140 NEXT L 150 END 160 LABEL "DELETE" 170 OUT@P,159:OUT@P,191 180 OUT@P,223:OUT@P,255 190 RETURN``` In line 80 the noise that is to be used is defined. You see that this program produces a tone and a noise that both get lower in frequency, this results in the desired effect. In the subroutine denoted by LABEL "DELETE" all sound volumes are set to 0. After calling this routine nothing will be audible anymore. You get the same effect with USR(0071). Nothing will be audible either after this USR. Example 2: Tick of a gas station ```10 REM TICK 20 INIT "CRT:M1" 30 P=242:REM P=port \$F2 40 GOSUB "DELETE" 50 OUT@P,131:OUT@P,10 60 OUT@P,175:OUT@P,9 70 FOR T=0 TO 11:CURSOR 0,0:PRINT T 80 FOR A=144 TO 159 90 OUT@P,A:OUT@P,(A+32) 100 WAIT 60 110 NEXT A 120 NEXT T 130 END 140 LABEL "DELETE" 150 OUT@P,159:OUT@P,191 160 OUT@P,223:OUT@P,255 170 RETURN``` This program uses the two tone generators and the noise generator is not used. Example 3: Two tones against each other This program makes two tones audible that have an opposite frequency. The frequency of one tone gets higher while the other one gets lower. At a certain point in time both frequencies will be equal. ```10 INIT "CRT:M1" 20 USR(71):P=242 30 FOR A=15 TO 0 STEP -1 40 FOR B=175 TO 160 STEP -1 50 OUT@P,B:OUT@P,A 60 OUT@P,367-B:OUT@P,15-A 70 OUT@P,176:OUT@P,208 80 NEXT B,A 90 USR(71)``` Example 4: Increasingly faster running wave This program will make a soft tone loud and vice versa and does this increasingly faster. ```10 INIT "CRT:M1":USR(71):P=242:OUT@P,176:OUT@P,171:OUT@P,5 20 FOR A=25 TO 0 STEP -1 30 FOR B=177 TO 190 40 OUT@P,B:WAIT A*4 50 NEXT B 60 FOR B=189 TO 176 STEP -1 70 OUT@P,B:WAIT A*4 80 NEXT B 90 NEXT A 100 USR(71)``` Example 5: Explosion ```1 INIT "CRT:M1":X=20:C=3 2 USR(71):OUT@\$F2,228 3 PAL 0,7:CURSOR X,12:PRINT [2]CHR\$(200):WAIT 2000 4 IF PEEK(\$4DCF)>1 THEN PO=\$4DD0 ELSE PO=\$4DCF 5 POKE PO,1:CURSOR X,12:PRINT [0]CHR\$(200):SYMBOL [1]X*8,96,CHR\$(141),1,1 :SYMBOL [1]X*8-8,88,CHR\$(188),3,3 6 OUT@\$F2,\$C8:FOR A=\$F0 TO \$FF:OUT@\$F2,A:WAIT 200:GOSUB 8:NEXT A 7 POKE PO,0:END 8 C=C+2:CLS 9 SYMBOL [1]X*8-4*(C-1),88-4*(C-3),CHR\$(188),C,C 10 SYMBOL [1]X*8-2*(C-3),96-2*(C-3),CHR\$(141),C/2,C/2:RETURN``` Example 6: 3 variable tones This program produces two tones and one noise sound which you can alter yourself with the 1 - 6 and A - F keys. The pitch of the tones can be adjusted with the 1 - 6 keys and with the A - F keys you can reduce the volume. Reducing the sound for 30 dB means that you will no longer hear the tone. You can end the program by pressing the CR-key. ```1 USR(71) 2 INIT "CRT:M1":PAL 1,12:PAL 2,24 3 PRINT "1=PITCH PORT 1 UP" 4 PRINT "2=PITCH PORT 1 DOWN" 5 PRINT "3=PITCH PORT 2 UP" 6 PRINT "4=PITCH PORT 2 DOWN" 7 PRINT "5=PITCH NOISE PORT UP" 8 PRINT "6=PITCH NOISE PORT DOWN" 9 PRINT:PRINT "A=VOLUME PORT 1 UP" 10 PRINT "B=VOLUME PORT 1 DOWN" 11 PRINT "C=VOLUME PORT 2 UP" 12 PRINT "D=VOLUME PORT 2 DOWN" 13 PRINT "E=VOLUME NOISE PORT UP" 14 PRINT "F=VOLUME NOISE PORT DOWN" 15 COLOR 1 16 PRINT:PRINT:PRINT TAB(13) "freq. (Hz)";:PRINT TAB(27)"reduce (dB)":PRINT 17 PRINT " PORT 1" 18 PRINT:PRINT " PORT 2" 19 PRINT:PRINT " NOISE PORT" 20 COLOR 2 21 BOX 0,132,319,147 22 BOX 0,147,319,162 23 BOX 0,162,319,177 24 BOX 88,132,204,147 25 COLOR 3 26 CURSOR 0,24:PRINT "CR=END (C)1990 by NEPTUNES SOFTWARE."; 27 F1=400:M1=144 28 F2=500:M2=176 29 FN=600:MN=240 30 CURSOR 12,17:PRINT F1;" ":PRINT:PRINT TAB(12)F2;" ":PRINT:PRINT TAB(12)FN;" " 31 CURSOR 26,17:PRINT (M1-144)*2;" ":PRINT:PRINT TAB(26)(M2-176)*2;" ":PRINT :PRINT TAB(26)(MN-240)*2;" " 32 FQ=F1:ME=M1:GOSUB CALCULATE 33 FQ=F2:ME=M2:GOSUB CALCULATE 34 FQ=FN:ME=MN:GOSUB CALCULATE 35 GET A\$:A=PEEK(4965):IF A=13 THEN USR(71):CLS:END 36 IF A<49 OR A>70 THEN 35 37 IF A>54 AND A<65 THEN 35 38 F1=F1+(5 AND A=49 AND F1<10000)-(5 AND A=50 AND F1>30) 39 F2=F2+(5 AND A=51 AND F2<10000)-(5 AND A=52 AND F2>30) 40 FN=FN+(5 AND A=53 AND FN<10000)-(5 AND A=54 AND FN>30) 41 M1=M1+(1 AND A=66 AND M1<159)-(1 AND A=65 AND M1>144) :M2=M2+(1 AND A=68 AND M2<191)-(1 AND A=67 AND M2>176) 42 MN=MN+(1 AND A=70 AND MN<255)-(1 AND A=69 AND MN>240):GOTO 30 43 LABEL "CALCULATE":F0=11094/(FQ/10):B6=INT(F0/16):B4=FRAC(F0/16)*16 44 IF FRAC(B4)>.5 THEN B4=INT(B4)+1:ELSE B4=INT(B4) 45 IF FRAC(F0)>.5 THEN F0=INT(F0)+1:ELSE F0=INT(F0) 46 OUT@\$F2,DE-16+B4:OUT@\$F2,B6 47 OUT@\$F2,DE:RETURN```

last updated March 22, 2006
Arjan Habing, Mark de Rover, Jeroen F. J. Laros, sharpmz@sharpmz.org