The Sound Chip inside the Oric is the AY-3-8912. This was a very popular sound chip back in the early 80's which was used in the Intellivision, Vectrex, MSX, Colour-Genie, Sinclair Spectrum 128/+2/+3, Amstrad CPC and Atari-ST.
The hardware consists of an 8 bit bus which is connected (on the Oric) to Port A of the VIA 6522 Chip. This appears at location $030F in the Oric memory map and for labeling conventions known as via_porta.
Port A also appears as the Printer Port which was also used for many Joystick Interfaces.
The 8-Bit bus may hold the AY Register number, AY Register Write, AY Register Read or Inactive/Disabled depending on the states of the two control lines. These control lines are known as CA2/CB2 in the VIA 6522 and BC1/BDIR on the AY-3-8912.
|CA2||CB2||AY Data State|
|0||1||Write AY Register Data|
|1||0||Read AY Register Data|
|1||1||Write AY Register Number|
CA2/CB2 logic levels may be set in the Peripheral Control Register or via_pcr at location $030C.
|Bit Pattern||Operation||Effective Output|
|000||Input Negative Active Edge||1|
|001||Independant Interrupt Input Negative Active Edge||1|
|010||Input Positive Active Edge||1|
|011||Independant Interrupt Input Positive Active Edge||1|
|101||Pulse Output(Pulse Mode)||-|
For simple programming of these lines, only modes 110 and 111 will ever be used.
The AY expects the Register to be selected before any data is is sent to it. It remembers the last Register selected to know where to put the data.
So to write a Value to an AY register, we would use the following code.
;First place the register number onto VIA Port A LDA AYRegisterNumber STA via_porta ;Then set control lines to Register Number state LDA #ayc_Register STA via_pcr ;We have to set control lines to Inactive after LDA #ayc_Inactive STA via_pcr ;Before we place the Register data on the bus LDA AYRegisterValue STA via_porta ;The set control lines to Register Data State LDA #ayc_Write STA via_pcr ;And finally set control lines inactive again LDA #ayc_Inactive STA via_pcr
There are some ways we can optimise this code, both in the code itself and also through the way we access the control lines. See advanced_ay_access for the latter.
By using the X register we can reduce the lines by one row..
;First place the register number onto VIA Port A LDA AYRegisterNumber STA via_porta ;Then set control lines to Register Number state LDA #ayc_Register STA via_pcr ;We have to set control lines to Inactive after LDX #ayc_Inactive STX via_pcr ;Before we place the Register data on the bus LDA AYRegisterValue STA via_porta ;The set control lines to Register Data State LDA #ayc_Write STA via_pcr ;And finally set control lines inactive again STX via_pcr
The AY-3-8912 Sound Chip contains 15 Registers which are usually numbered from 0 to E (Hexadecimal).
|AY-3-8912 Register Array|
|0||Channel A Tone Period LSB||B7||B6||B5||B4||B3||B2||B1||B0|
|1||Channel A Tone Period MSB||B11||B10||B9||B8|
|2||Channel B Tone Period LSB||B7||B6||B5||B4||B3||B2||B1||B0|
|3||Channel B Tone Period MSB||B11||B10||B9||B8|
|4||Channel C Tone Period LSB||B7||B6||B5||B4||B3||B2||B1||B0|
|5||Channel C Tone Period MSB||B11||B10||B9||B8|
|8||Channel A Amplitude||EG||B3||B2||B1||B0|
|9||Channel B Amplitude||EG||B3||B2||B1||B0|
|A||Channel C Amplitude||EG||B3||B2||B1||B0|
|B||Envelope Period LSB||B7||B6||B5||B4||B3||B2||B1||B0|
|C||Envelope Period MSB||B7||B6||B5||B4||B3||B2||B1||B0|
|E||I/O Port A(Key Column)||B7||B6||B5||B4||B3||B2||B1||B0|
Whilst the EG has limited use in monostable (single shot) mode when set to Bistable a limited range of very low Periods permit the EG to become a waveform generator to produce Sawtooth and Triangle waveforms. When mixed with a chip channel the EG can produce some interesting sounds best suited to Bass sounds.
The range of notes available when using the EG in this way is shown in the next diagram. Each Note corresponds to the BASIC MUSIC octave, however the actual frequency has also been provided for reference.
|Note||Triangle Envelope Period||Sawtooth Envelope Period||Frequency (Herz)|
These registers provide 3 channels of Tone.
Each channel has a 12 bit Counter which provides enough resolution to produce smooth pitch bend between notes.
The lower the counter value the higher the frequency.
There are two methods to convert a musical note to pitch.
The first is to create a 12bit lookup table whose length corresponds to the number of notes required. This has the distinct advantage of consuming the least number of cycles to translate.
However altering the base frequency for tuning purposes is more difficult since any adjustment to the whole table will not be as accurate at higher frequencies.
For 96 notes (8 Octaves) a 192 byte table is required.
Note that this technique was used in Sonix 3.2
The code is included below and is based on 96 notes.
Note2Pitch LDX note LDA Pitch_lo,X STA ay_Pitch_A_Low LDA Pitch_hi,X STA ay_Pitch_A_High RTS
The other method is to create a 12bit 12 entry table whose length corresponds to the 12 notes within a single octave(Octave Zero). The other octaves can be located by shifting the table down through code.
This has the advantage of using less bytes(and the same number of bytes regardless the number of notes) but uses more cpu cycles.
Altering the base frequency for tuning purposes is also easier since we adjust just the 12 values.
Note this technique was used in Sonix version 3.42 and 4.00
The code is included below
Note2Pitch LDA note ;Convert Large Note to Octave(X) and 12 value Note(A) (Divide by 12) LDX #255 SEC .( loop1 INX SBC #12 BCS loop1 ADC #12 ;Fetch 12 Bit Base Note TAY LDA base_pitch_lo,Y STA ay_Pitch_A_Low LDA base_pitch_hi,Y ;Finish if Octave Zero CPX #00 BEQ finish ;Shift up for Octave loop2 LSR ROR ay_Pitch_A_Low DEX BNE loop2 finish .) STA ay_Pitch_A_High RTS
base_pitch_lo .byt $ee,$16,$4c,$8e,$d8,$2e,$8e,$f6,$66,$e0,$60,$e8 base_pitch_hi .byt $0e,$0e,$0d,$0c,$0b,$0b,$0a,$09,$09,$08,$08,$07
The AY-3-8912 contains a single Noise Generator whose pulsewidth may be adjusted from 0(Tinny) to 31(Bassy).
The Status Register holds a number of flags that control the link between Tone and Noise Generators to the A/D converters (Volume Registers). The Status Register also has a Data Direction Flag in Bit 6 (IOA) which should be kept set to set the Key Column register to output.
TnA,TnB and TnC correspond to Tone Channels A,B and C. When each bit is reset the corresponding Tone Period Generator is fed to the Volume Register.
NsA,NsB and NsC correspond to Channels A,B and C. When each bit is reset the Noise Generators output is attached to the corresponding Volume Register.
The Volume registers provide a control over the volume of the corresponding tone generators and Noise Generator.
The Volume may be controlled through software using the 4 lower bits of each register (Resetting Bit 4). Alternatively volume control may be passed to the Envelope generator by setting Bit 4 of the corresponding Volume Register.
Volume on the AY-3-8912 follows a Logarithmic scale. This means the difference in volume levels between 1 and 2 will sound very different to 14 and 15.
Note, Some Music on other machines such as the Spectrum 128K limited the volume to below 8 in order to achieve greater suttlety with volume levels.
There is just one Envelope Generator. So it has limited use when used in a melody. The Period Registers form a 16 bit value that defines the time between each successive volume step of the chosen waveform cycle.
The Envelope Cycle Register Sets the shape of the Volume Envelope. Each bit defines a particular attribute of the envelope which uses a very simplified ADSR formation. The table below illustrates only the values that correspond to unique envelope shapes.
|Cycle Bits||Value(Decimal)||Cycle||Envelope Shape||Waveform name|
|1000||8||Bistable||High Slope Low Repeating)||Sawtooth|
|1001||9||Monostable||High Slope Low|
|1010||10||Bistable||High Slope Low Slope High Repeating||Triangle|
|1011||11||Monostable||High Slope Low then High|
|1100||12||Bistable||Low Slope High Repeating||Sawtooth|
|1101||13||Monostable||Low Slope High|
|1110||14||Bistable||Low Slope High Slope Low Repeating||Triangle|
|1111||15||Monostable||Low Slope High then Low|