Beep

## VERA PSG

The PSG on the VERA chip provides 16 channels, accessible through VRAM addresses $1F9C0 through $1F9FF, and consequently very easy to use with VPOKE. For now, we'll analyze channel 0, which uses VRAM addresses $1F9C0 through $1F9C3.

The registers of channel 0 look as follows:

 $1F9C1
 $1F9C2
 $1F9C3

**Frequency word** specifies the frequency of the wave, in intervals of 0.373 Hz (derived as 25 MHz / 226). To convert from MIDI note to frequency word, use the following formula:

```
FW = INT(EXP(N*0.0577622651)*21.9467431+0.5)

```

(derived as exp(n \* ln 2 / 12) \* (1 / exp(69 \* ln 2 / 12) \* 440 \* 226 / 2.5e7))

**Left** and **Right** specify whether you want to use the left channel, right channel or both.

**Volume** is a simple volume slider going from 0 to 63.

**Waveform** controls the waveform of the sound:

 1
 2
 3

**Pulse width** only matters when the waveform is 0 (pulse), and controls the duty cycle of the pulse waveform. A value of 63 will give a 50% duty cycle or square wave, 0 will give a very narrow pulse.

The very basic requirements to play sound on the VERA PSG are:

1. Load the properties of the note into VRAM ($1F9C0, $1F9C1, $1F9C3)
2. Load the volume into VRAM ($1F9C2)
3. (wait)
4. Reset the volume to 0 in VRAM ($1F9C2)

Example program that plays Twinkle Twinkle Little Star, and demonstrates how you would do things such as tempo control and volume decay in BASIC:

```
10 REM SINGLE CHANNEL PLAYBACK DEMO

```

```
20 REM MAIN FLOW - WHICH SEGMENTS TO PLAY AND HOW FAST

```

```
30 TEMPO = 120

```

```
40 RESTORE : S = 0 : GOSUB 500

```

```
50 RESTORE : S = 1 : GOSUB 500

```

```
60 RESTORE : S = 1 : GOSUB 500

```

```
70 RESTORE : S = 0 : GOSUB 500

```

```
80 END

```

```
500 REM SUBROUTINE FOR PLAYING A SEGMENT

```

```
510 TD = 7272/TEMPO-14

```

```
520 CS = 0

```

```
530 READ SL

```

```
540 FOR NL = 1 TO SL

```

```
550 READ N

```

```
560 READ VOL

```

```
570 READ ND

```

```
580 IF CS = S THEN GOSUB 1000 : REM SKIPS UNWANTED SEGMENTS

```

```
590 NEXT NL

```

```
600 IF CS = S THEN RETURN

```

```
610 CS = CS + 1

```

```
620 GOTO 530

```

```
1000 REM SUBROUTINE FOR PLAYBACK OF A SINGLE NOTE

```

```
1010 REM ARGUMENTS

```

```
1020 REM N - MIDI VALUE OF NOTE TO PLAY FROM 0 TO 127 ($7F)

```

```
1030 REM VOL - VOLUME OF NOTE TO PLAY FROM 0 TO 63 ($3F)

```

```
1040 REM ND - DURATION OF NOTE TO PLAY IN SIXTEENTHS

```

```
1100 REM CONVERT MIDI NOTE TO FREQWORD

```

```
1110 FW = INT(EXP(N*0.0577622651)*21.9467431+0.5)

```

```
1120 REM SPLIT FREQWORD TO HIGH AND LOW BYTES

```

```
1130 HB = INT(FW/$100)

```

```
1140 LB = FW-HB*$100

```

```
1150 REM SPECIFY THE FREQWORD AND INSTRUMENT WE WANT

```

```
1160 VPOKE 1,$F9C0,LB

```

```
1170 VPOKE 1,$F9C1,HB

```

```
1180 VPOKE 1,$F9C3,$80 : REM TRIANGLE AS DEMO

```

```
1190 REM PLAY THE NOTE

```

```
1200 FOR I = 0 TO ND*8-1

```

```
1210 VPOKE 1,$F9C2,VOL+$C0

```

```
1220 VOL = VOL - INT((VOL+$F)/$10) : REM CONTROLS VOLUME DECAY

```

```
1230 FOR J = 0 TO TD : NEXT J

```

```
1240 NEXT I

```

```
1250 VPOKE 1,$F9C2,$00

```

```
1260 RETURN

```

```
1500 REM DATA POWERING PLAYBACK - TWINKLE TWINKLE LITTLE STAR

```

```
2000 DATA 14 : REM SEGMENT 0

```

```
2010 DATA 60,$3F,4

```

```
2020 DATA 60,$3F,4

```

```
2030 DATA 67,$3F,4

```

```
2040 DATA 67,$3F,4

```

```
2050 DATA 69,$3F,4

```

```
2060 DATA 69,$3F,4

```

```
2070 DATA 67,$3F,8

```

```
2080 DATA 65,$3F,4

```

```
2090 DATA 65,$3F,4

```

```
2100 DATA 64,$3F,4

```

```
2110 DATA 64,$3F,4

```

```
2120 DATA 62,$3F,4

```

```
2130 DATA 62,$3F,4

```

```
2140 DATA 60,$3F,8

```

```
2500 DATA 7 : REM SEGMENT 1

```

```
2510 DATA 67,$3F,4

```

```
2520 DATA 67,$3F,4

```

```
2530 DATA 65,$3F,4

```

```
2540 DATA 65,$3F,4

```

```
2550 DATA 64,$3F,4

```

```
2560 DATA 64,$3F,4

```

```
2570 DATA 62,$3F,8

```

## YM2151

The very basic requirements to play sound on the YM2151 chip are:

1. Load a patch into the YM2151 registers for one of the 8 voices (channels).
2. Set the note value for the channel
3. Send a KeyDown message to play the note
4. (wait)
5. Send a KeyUP message to release the note when it has played for the intended duration

When playing multiple notes, if you have not released the previous note (KeyUP) yet, then sending a second KeyDN will NOT play the new note. This would be like trying to press a piano key that you're already holding down.

To talk to the YM2151, you POKE information into one of its two I/O memory locations:

* Address Register ($9FE0) - tells the YM2151 which of its internal register addresses to use
* Data Register ($9FE1) - send the actual values to this register
* NOTE: These I/O addresses are very likely to change in the future, as they correspond to expansion port addresses, and if the YM2151 is approved for the system, it is likely to be built into the mainboard directly and will use a different IO address range than the expansion slots.

Example program to play two chime sounds in an ascending tone, which might serve as a positive audible feedback tone:

```
10 S=600               : REM NOTE SPEED

```

```
20 YA=$9FE0 : YD=$9FE1 : REM YM2151 ADDRESS/DATA PORTS

```

```
30 LN=$3A : HN=$44     : REM LN/HN = LO NOTE / HI NOTE

```

```
40 REM --- LOAD PATCH INTO VOICE 0 ---

```

```
50 FOR I=1 TO 5

```

```
60 READ A : READ D

```

```
70 POKE YA,A   : POKE YD,D

```

```
80 NEXT I

```

```
100 REM --- PLAY HAPPY SOUND ---

```

```
110 POKE YA,$28 : REM $28 IS VOICE 0 FREQ. SETTING

```

```
120 POKE YD,LN  : REM SET THE FREQ. TO LO NOTE VALUE

```

```
130 POKE YA,$08 : REM SELECT THE KEYUP/DN REGISTER

```

```
140 POKE YD,0   : REM RELEASE ANY PREVIOUS NOTE

```

```
150 POKE YD,$40 : REM PLAY THE NOTE

```

```
160 FOR I = 1 TO S : NEXT

```

```
170 POKE YD,0   : REM RELEASE THE NOTE

```

```
180 FOR I = 1 TO S : NEXT

```

```
190 POKE YA,$28

```

```
200 POKE YD,HN	: REM SET NEXT NOTE FREQ. TO HI-NOTE

```

```
210 POKE YA,$08

```

```
220 POKE YD,0

```

```
230 POKE YD,$40

```

```
240 FOR I = 1 TO S : NEXT

```

```
250 POKE YD,0   : REM RELEASE THE SECOND NOTE

```

```
260 END

```

```
1000 REM --- PATCH DATA ---

```

```
1010 DATA $20, $C0

```

```
1020 DATA $58, $01

```

```
1030 DATA $98, $1F

```

```
1040 DATA $B8, $0D

```

```
1050 DATA $F8, $F6

```

The patch data lines are arranged to make it easy to play around with them and see what they do.

The settings mean the following:

$20 = master channel configuration: $C0 = L & R volume ON, No Feedback, Use OP algorithm 0.

$58 = fine detuning / phase multiplier: $01 = no detune (hi nybble) / multiplier=1 (normal)

$98 = Key-scale / Attack Rate: $1F = no keyscale / max attack rate (keyscale = 3 MSB, attack = 5 LSB)

$B8 = Amplitude Mod ENA / 1st Decay Rate: $0D = no AM / Decay=13 (AM-ENA is 1 MSB / decay is 5 LSB)

$F8 = Sustain Level / Release Rate: $F6 = max sustain (0-F in hi nybble / release=6 .. 0-F in lo nybble)

Note that this patch is very simple, and only utilizes the 4th operator of voice 0. More advanced patches would require more settings to be made for each voice, which is beyond the scope of a simple "hello world" example for sound.