YM, DSP & DMA Sound
===========#==#=======#===============================================#=====
----------------------|YM2149/AY-3-8910 Sound Chip |-----
===========#==#=======#===============================================#=====
$FFFF8800.B|R-|PSG_SEL|Read Data | |-W| |Register Select |
$FFFF8800 PSG_SEL YM2149 register select (W) / read data (R)
Write a register number 0-15 here, then read or write the
value at $FFFF8802. The register set:
0 Channel A tone period, fine (8 bits)
1 Channel A tone period, coarse (4 bits)
2 Channel B tone period, fine
3 Channel B tone period, coarse
4 Channel C tone period, fine
5 Channel C tone period, coarse
6 Noise generator period (5 bits)
7 Mixer control and I/O port direction
8 Channel A amplitude
9 Channel B amplitude
10 Channel C amplitude
11 Envelope period, fine
12 Envelope period, coarse
13 Envelope shape (4 bits)
14 I/O Port A (floppy select, printer, RS232)
15 I/O Port B (Centronics data)
Register 7, mixer control:
Bit 7 Port B direction, 1 = output
Bit 6 Port A direction, 1 = output
Bit 5 Noise off, channel C
Bit 4 Noise off, channel B
Bit 3 Noise off, channel A
Bit 2 Tone off, channel C
Bit 1 Tone off, channel B
Bit 0 Tone off, channel A
Note the enable bits are inverted: a 0 enables that source.
Registers 8-10, amplitude:
Bits 3-0 fixed volume level 0-15
Bit 4 1 = use envelope instead of fixed volume
Register 13, envelope shape, bits 3-0:
Bit 3 CONT continue after first cycle
Bit 2 ATT attack, 1 = rising
Bit 1 ALT alternate direction each cycle
Bit 0 HOLD hold at final level
Register names verified against Hatari src/includes/psg.h.
Mixer and port-direction bit masks verified against EmuTOS
bios/psg.h (PSG_PORTB_OUTPUT 0x80, PSG_PORTA_OUTPUT 0x40,
PSG_NOISE_MASK 0x38, PSG_TONE_MASK 0x07).
$FFFF8802.B|rW|PSG_DAT|Write Data | | | | PSG Register 14 - Port A %RICDPBAS | | | | Reset IDE 0:no,1:reset (slow down)---+||||||| |F | | | Internal Speaker 0:on,1:off-----------+|||||| |F | | | Centronics Strobe----------------------+||||| | | | | Reset DSP 0:no,1:reset------------------+|||| |F | | | Printer Select In------------------------+||| | | | | Drive B select 0:on,1:off-----------------+|| | | | | Drive A select 0:on,1:off------------------+| | | | | Side select 0:side1,1:side0-----------------+ | | | | PSG Register 15 - Port B %xxxxxxxx | | | | Centronics Data Port-----------------++++++++ |
$FFFF8802 PSG_DAT YM2149 data register
Reads or writes the register previously selected at $FFFF8800.
PORT A, register 14, is the one that matters on the ST. It
carries the floppy drive and side select lines:
Bit 7 Reset IDE 0 = no, 1 = reset Falcon
Bit 6 Internal speaker 0 = on, 1 = off Falcon
Bit 5 Centronics strobe
Bit 4 Reset DSP 0 = no, 1 = reset Falcon
Bit 3 Printer select in
Bit 2 Drive B select 0 = selected
Bit 1 Drive A select 0 = selected
Bit 0 Side select 1 = side 0, 0 = side 1
Note the side select polarity: the bit SET selects side 0.
This is not a typo in the listing, it is how the hardware works.
Bits 3-7 carry RS232 RTS and DTR, the Centronics strobe and a
general purpose output. Always read the port, modify only the
bits you need and write it back. Writing a whole byte will
disturb the serial and printer lines.
Disable interrupts around any access to this register, or the
floppy VBL routine can deselect the drive underneath you. Set
flock at $0000043E to a non-zero value first.
Register layout verified against Hatari and EmuTOS.
===========#==#=======#===============================================#=====
----------------------|DMA, CODEC, ADC, DAC, DSP-Transmit/Receive |-----
===========#==#=======#===============================================#=====
$FFFF8900.W|RW|SND_DMA|Sound-DMA-Control %____RPRP F_EL__EL |F,STE | | | Timer A after Record/Play-------++|| | || || |F | | | MFP I/O 7 after Record/Play-------++ | || || |F | | | Frame Registers 0:play,1:record------+ || || |F | | | DMA record Enable/Loop-----------------++ || |F | | | DMA play Enable/Loop-----------------------++ |F,STE
$FFFF8900 SND_DMA Sound DMA control
Bits 1-0, DMA play:
Bit 1 loop: 0 = play once, 1 = repeat from frame start
Bit 0 enable: 0 = stop, 1 = start playback
Bits 5-4, DMA record (Falcon only), same enable/loop pair.
Bit 7 frame register select: 0 = play frame, 1 = record
Bits 11-8 and 15-12 select what happens at the end of a
record or play frame: Timer A event and MFP I/O 7 event.
On the STE only bits 1-0 exist. The record path and the event
bits are Falcon additions.
Playback reads from the frame start address at $FFFF8903-07
and continues to the frame end at $FFFF890F-13. The current
position can be read from $FFFF8909-0D while playing.
$FFFF8903.B|RW|SND_FSH|Frame Start Hi |F,STE
$FFFF8905.B|RW|SND_FSM|Frame Start Mi |F,STE
$FFFF8907.B|RW|SND_FSL|Frame Start Lo |F,STE
$FFFF8909.B|RW|SND_FCH|Frame Count Hi |F,STE
$FFFF890B.B|RW|SND_FCM|Frame Count Mi |F,STE
$FFFF890D.B|RW|SND_FCL|Frame Count Lo |F,STE
$FFFF890F.B|RW|SND_FEH|Frame End Hi |F,STE
$FFFF8911.B|RW|SND_FEM|Frame End Mi |F,STE
$FFFF8913.B|RW|SND_FEL|Frame End Lo |F,STE
$FFFF8920.W|RW|SND_SMC|Sound Mode Control %__SS__PP MB____FF |F,STE | | | DAC to track %SS--------------++ || || || |F | | | Play %PP+1 tracks-----------------++ || || |F | | | 0:Stereo,1:Mono----------------------+| || |F | | | 0:8bit,1:16bit------------------------+ || |F | | | Falcon:(unused)--STE: 6258 Hz--------------00 |F,STE | | | Falcon:12292 Hz--STE:12517 Hz--------------01 |F,STE | | | Falcon:19668 Hz--STE:25033 Hz--------------10 |F,STE | | | Falcon:49170 Hz--STE:50066 Hz--------------11 |F,STE
$FFFF8920 SND_SMC Sound mode control
This is a word register, but the two halves are separate:
$FFFF8920 is the track control byte and $FFFF8921 the mode
control byte. Hatari and EmuTOS treat them separately.
$FFFF8921, mode control:
Bit 7 0 = stereo, 1 = mono
Bit 6 0 = 8 bit, 1 = 16 bit
Bits 1-0 sample rate:
Falcon: 00 unused, 01 12292Hz, 10 19668Hz, 11 49170Hz
STE: 00 6258Hz, 01 12517Hz, 10 25033Hz, 11 50066Hz
$FFFF8920, track control (Falcon only):
Bits 5-4 which track the DAC monitors
Bits 1-0 number of tracks to play, minus one
The mono/stereo bit was previously printed on this page with
both states as 0. Corrected from EmuTOS bios/dmasound.c, which
does modectrl |= 0x80 with the comment 'Select mono', and from
Hatari src/falcon/crossbar.c, which reads isStereo as the
inverse of bit 7 and is16Bits from bit 6.
$FFFF8922.B|RW| - |Microwire Data Register |STE
$FFFF8924.B|RW| - |Microwire Mask Register |STE
===========#==#=======#===============================================#=====
----------------------|Falcon Sound Matrix and CODEC |-----
===========#==#=======#===============================================#=====
$FFFF8930.W|RW|SND_CBO|Crossbar Output Select Controller |F
$FFFF8930 SND_CBO Crossbar source (input) select
Word register, four 4-bit fields, one per source device.
Bit layout from Hatari src/falcon/crossbar.c:
Bits 15-12 A/D Converter
Bits 13-12 clock: 00 = 25.175MHz, 01 = external,
10 = 32MHz (do not use)
Bits 11-8 External Input
Bit 11 0 = DSP IN, 1 = all others
Bits 10-9 clock, as above
Bit 8 0 = handshake on, 1 = handshake off
Bits 7-4 DSP transmit
Bit 7 0 = tristate and disconnect DSP (external SSI
use only), 1 = connect DSP to multiplexer
Bits 6-5 clock, as above
Bit 4 0 = handshake on, 1 = handshake off
Bits 3-0 DMA playback
Bit 3 0 = handshaking on, destination DSP receive
1 = destination is not DSP receive
Bits 2-1 clock, as above
Bit 0 0 = handshake on, 1 = handshake off
Verified against Hatari src/falcon/crossbar.c, which reads
dspXmit tristate from bit 7, handshake from bit 4, and the
two frequency fields from bits 6-5 and 2-1.
$FFFF8932.W|RW|SND_CBI|Crossbar Input Select Controller |F
$FFFF8932 SND_CBI Crossbar destination (output) select
Word register, four 4-bit fields, one per destination.
Bit layout from Hatari src/falcon/crossbar.c:
In each field the two-bit source selector means:
00 = DMA output 01 = DSP output
10 = External input 11 = ADC input
Bits 15-12 D/A Converter
Bits 13-12 source, as above
Bits 11-8 External output
Bit 11 0 = DSP out, 1 = all others
Bits 10-9 source, as above
Bit 8 0 = handshake on, 1 = handshake off
Bits 7-4 DSP receive
Bit 7 0 = tristate and disconnect DSP (external SSI
use only), 1 = connect DSP to multiplexer
Bits 6-5 source, as above
Bit 4 0 = handshake on, 1 = handshake off
Bits 3-0 DMA record
Bit 3 0 = handshaking on, destination DSP transmit
1 = all
Bits 2-1 source, as above
Bit 0 0 = handshake on, 1 = handshake off
Verified against Hatari src/falcon/crossbar.c.
$FFFF8934.B|RW|SND_FDE|Frequency Divider, External Sync |F
$FFFF8935.B|RW|SND_FDI|Frequency Divider, Internal Sync |F
$FFFF8936.B|RW|SND_RTS|Record Tracks Select |F
$FFFF8937.B|RW|SND_CIS|CODEC Input Source |F
$FFFF8938.B|RW|SND_CAD|CODEC ADC Input |F
$FFFF8939.B|RW|SND_GAI|Gain settings %LLLLRRRR |F
$FFFF893A.W|RW|SND_ATT|Attenuation settings %LLLLRRRR |F
$FFFF893C.W|R-|SND_CST|CODEC Status |F
$FFFF8940.W|RW|SND_GPD|GPIO Data Direction |F
$FFFF8942.W|RW|SND_GPI|GPIO Data |F