The Programmable Sound Generator (PSG) is able to output three separate sound channels (named Channel A, B and C). Each channel can be used to output tones and/or white noise.
The PSG has 16 read/writeable data registers, and a write-only index register. Both the index and data registers are accessed through PIO Port A, depending on the current setting of the BC1 and BDIR bits in PPI Port C. The four possible combinations are:
0=inactive 2=write data 1=read data 3=write index
The procedure to write data to a specific register is as follows: Write the register number to PPI Port A, set BC1/BDIR to Write Index - and back to Inactive. Now write the data to PIO Port A, set BC1/BDIR to Write Data - and back to Inactive.
00h - Channel A Tone Frequency Low (8bit)
01h - Channel A Tone Frequency High (4bit)
02h - Channel B Tone Frequency Low (8bit)
03h - Channel B Tone Frequency High (4bit)
04h - Channel C Tone Frequency Low (8bit)
05h - Channel C Tone Frequency High (4bit)
The tone (square wave) frequency in Hertz is calculated as follows:
F = 4MHz / 64 / nn ;with nn in range 1..4095 (nn=0 acts as nn=1)
Possible frequencies are in range from 62500Hz (nn=1) down to approx. 15.26Hz (nn=4095).
06h - Noise Frequency (5bit)
The noise frequency in Hertz is calculated as follows:
F = 4MHz / 64 / nn ;with nn in range 1..31 (nn=0 acts as nn=1)
Noise can be output on all 3 channels, but there is only one noise generator (so all channels share the same noise frequency). The noise generator consists of 17bit shift register, and a 1bit noise level (0=LOW or 1=HIGH). These are updated at the selected frequency as follows:
noise_level = noise_level XOR shiftreg.bit0 newbit = shiftreg.bit0 XOR shiftreg.bit3 shiftreg = (shiftreg SHR 1) + (newbit SHL 16)
Note that level isn't set equal to bit0, instead, it toggles when bit0=1.
07h - Mixer Control Register
The control register enables or disables the sound channels. Each channel can output a Tone and/or Noise.
Bit 0 Channel A Tone (1=off, 0=on) Bit 1 Channel B Tone (1=off, 0=on) Bit 2 Channel C Tone (1=off, 0=on) Bit 3 Channel A Noise (1=off, 0=on) Bit 4 Channel B Noise (1=off, 0=on) Bit 5 Channel C Noise (1=off, 0=on) Bit 6 Port A Direction (1=output, 0=input) (should be always 0 for CPC) Bit 7 Port B Direction (1=output, 0=input) (not used in CPC)
If both Tone and Noise are disabled on a channel, then a constant HIGH level is output (useful for digitized speech). If both Tone and Noise are enabled on the same channel, then the signals are ANDed (the signals aren't ADDed) (ie. HIGH is output only if both are HIGH).
08h - Channel A Volume (0-0Fh=volume, 10h=use envelope instead)
09h - Channel B Volume (0-0Fh=volume, 10h=use envelope instead)
0Ah - Channel C Volume (0-0Fh=volume, 10h=use envelope instead)
Defines the volume, 0=off, 15=max. If bit4=1, then the volume is taken from the envelope generator. The volume is non-linear. Below formula does comply with the PSG datasheet, and does more or less match the voltages measured on the CPCs speaker (the voltages on the CPCs stereo connector seem to be slightly different though).
amplitude = max / sqrt(2)^(15-nn) eg. 15 --> max/1, 14 --> max/1.414, 13 --> max/2, etc.
The volume affects only HIGH levels. LOW levels are always NULL. Ie. sound output toggles between +VOL and NULL (not between +VOL and -VOL).
Digitized samples can be written to the volume registers (mind that volume is non-linear). When doing that, it's best to switch the channel to constant HIGH level (by disabling both Tone and Noise). Another method would be to set tone frequency to 000h or 001h (the resulting frequency is too high to be audible, so the HIGH/LOW levels sound like a constant HALF level).
0Bh - Volume Envelope Frequency Low (8bit)
0Ch - Volume Envelope Frequency High (8bit)
Envelope step frequency (tone or noise) calculated as follows:
F = 4MHz / 64 / nn ;with nn in range 1..65535 (nn=0 acts as nn=1)
Depending on the envelope shape, the volume is incremented from 0 to 15, or decremented from 15 to 0. In either case it takes 16 steps to complete, the completion time for 16 steps is therefore:
T = nn*1024 / 4MHz ;with nn in range 1..65535 (256us .. 16.7 seconds)
0Dh - Volume Envelope Shape (4bit)
Writing to this register (re-)starts the envelope. Additionally, the written value specifies the envelope shape, the four bits have the following meaning:
Bit 0 Hold (1=stop envelope past first cycle) Bit 1 Alternate (1=reverse direction at end of each cycle) Bit 2 Attack (1=initial direction increase) Bit 3 Continue (0=same as if Bit0=1 and Bit1=Bit2)
The possible combinations and resulting shapes are:
Binary Hex Shape 00XX 00h-03h \_________ (same as 09h) 01XX 04h-07h /_________ (same as 0Fh) 1000 08h \\\\\\\\\\ 1001 09h \_________ (volume remains quiet) 1010 0Ah \/\/\/\/\/ 1011 0Bh \""""""""" (volume remains high) 1100 0Ch ////////// 1101 0Dh /""""""""" (volume remains high) 1110 0Eh /\/\/\/\/\ 1111 0Fh /_________ (volume remains quiet)
When using the volume envelope generator, the volume is always increased from 00h to 0Fh (or vice versa), it is not possible to specify a starting/ending point (like from 00h to 07h).
0Eh - External Dataregister Port A
This register receives data from the CPC keyboard (or joystick), for more information read the chapter about the CPC Keyboard Matrix. This register can be also used as output port by setting bit 6 of the PSG control register to 1 (that would allow to use the six data pins of the joystick connector to output data to external hardware).
0Fh - External Dataregister Port B
This register is not used in CPC computers. In detail, a AY-3-8910 sound chip would have external connectors for this register, so that it could be used as a further IO port, but the CPC's sound chip (AY-3-8912, in 28 pin package) doesn't have such connectors, even though the register still does exist internally. The Aleste 520EX (russian CPC clone) is a special case: does have a 8910 chip, with PSG Port B being used as 8bit printer port data.
Mono and Stereo Output
When using the CPC's external stereo jack, channel A is output to the right, channel C is output left, and channel B is output to both left and right, in that case channel B is output through a bigger resistor to prevent that this channel appears loader than the others.
Otherwise (when using the built-in speaker), all three channels are mixed at the same intensity. This signal appears to be also sent to the Tape output line also, so a connected Data Recorder could be used to record CPC music also.