Skip to content
RetrogamingDeep Dive Published Updated 5 min readViews unavailable

Atari 520ST YM2149: PSG Register Access Without Port Collisions

Understand the 520ST's PSG select/data interface, mixer direction bits, and the system I/O that makes careless sound writes disruptive.

On an Atari 520ST, the Yamaha YM2149 is both a three-channel programmable sound generator and part of the computer’s peripheral interface. A sound routine that treats every PSG register as private audio state can therefore change more than a note. The 520ST service manual documents the chip’s role in the parallel-printer path, while Atari’s BIOS documentation warns that system code updates Port A. The safe mental model is one shared device with explicit ownership, not a sound chip that an application may freely rewrite.

This discussion is deliberately limited to the 520ST-family evidence in the cited service manual and to Hatari’s STF-specific implementation notes. Atari ST, STe, TT, and Falcon models do not all have identical surrounding hardware behavior. Verify the service reference and emulator model for the actual machine before carrying a register assumption across revisions.

Select a register, then transfer its data

The PSG contains sixteen internal registers. The Atari memory interface uses a select access and a data access: software chooses a register, then transfers its value. Hatari’s implementation records that $FF8800 selects the register and $FF8802 carries the data. Its comments also document real-STF testing for reads: reading $FF8800 returns selected-register data, while reads from $FF8801, $FF8802, and $FF8803 return $FF in the tested STF behavior.

That detail is a useful emulator test case, not a license to generalize address mirroring to every Atari model or access width. The same source warns that shadow-address writes and multi-byte 68000 instructions can interact: a word or longword access may touch both the even and odd aliases, while a byte write or MOVEP follows a different path. Keep the actual model, address, and instruction width in a hardware trace. If an emulator accepts a write that real software relies on, the resulting audio can sound plausible while the bus behavior remains wrong.

The register set divides responsibility cleanly. R0 and R1 hold channel A’s tone period, R6 controls the noise period, and R8 controls channel A amplitude. Register R7 combines the tone/noise mixer bits with the direction controls for the two parallel I/O ports. R14 and R15 are the Port A and Port B data registers. Yamaha’s datasheet specifies that a zero in a tone or noise mixer bit allows that source to reach the output; a one disables it. For the two I/O direction bits, zero selects input and one selects output.

The mixer register is also an I/O direction register

For channel A, R7 bit 0 controls tone and bit 3 controls noise. If a sound test sets the tone bit without preserving the upper bits of R7, it can unintentionally change Port A or Port B direction. Changing direction can change the electrical behavior of a port connected to another device. The Atari 520ST service manual identifies the YM2149 as the source of printer data and strobe signals and notes that printer busy is read through the MFP. These are system-visible signals, not spare audio pins.

Port A is especially sensitive to concurrent access. Atari’s Hitchhiker’s Guide to the BIOS says the sound-chip registers are not shadowed, that BIOS code frequently updates Port A, and that a read-modify-write of Port A must be atomic. It supplies Offgibit and Ongibit for atomic single-bit changes. A program that reads Port A, alters one bit, and writes an old snapshot later can undo a newer BIOS update. Prefer the documented operating-system primitive for those shared Port A bits; reserve bulk PSG register writes for a sound owner that has explicit control of the device.

Hatari’s code reinforces why this should be model-specific: its PSG path routes Port A writes through floppy drive/side handling and contains separate checks for later machine types. Emulator source is an implementation reference, not a substitute for a board manual, but it helps identify which side effects a test should observe.

Register setup and restoration for a tone test

In a disposable 520ST/520STF emulator profile, a diagnostic that has exclusive PSG ownership can save the four registers it will touch, program channel-A tone registers, and restore the old state. The following C-like pseudocode shows only the register transaction; an audio test needs a separate, bounded capture step between setup and restoration. It uses Atari’s XBIOS Giaccess(data, register) rather than direct memory writes. For a write, the register argument has bit 7 set; without that bit, Giaccess reads the selected register.

/* Hold the sound subsystem's lock for the complete save/test/restore. */
uint8_t old0 = (uint8_t)Giaccess(0, 0);
uint8_t old1 = (uint8_t)Giaccess(0, 1);
uint8_t old7 = (uint8_t)Giaccess(0, 7);
uint8_t old8 = (uint8_t)Giaccess(0, 8);

/* Preserve both port directions; enable only tone A, with its noise off. */
uint8_t test7 = (old7 & 0xC0) | 0x3E;
Giaccess(test7, 0x87);
Giaccess(0xD0, 0x80);  /* R0: low part of a test period */
Giaccess(0x05, 0x81);  /* R1: high four bits, period 0x5D0 */
Giaccess(0x08, 0x88);  /* R8: fixed channel-A amplitude */

/* Insert a bounded capture step here in an audio test; this snippet does not capture. */
/* Restore while the same lock is held. */
Giaccess(old8, 0x88);
Giaccess(old1, 0x81);
Giaccess(old0, 0x80);
Giaccess(old7, 0x87);

The period is a register value, not a promised musical pitch; the fundamental depends on the PSG input clock and divider convention, while the analog path changes its level and timbre. Do not run this transaction over a live desktop, printer operation, disk-control code, or another program that owns sound. Its purpose is to prove the register and mixer path in an isolated fixture. On a real system, use the platform’s sound driver and its ownership rules instead of treating an XBIOS read-modify-write as a global lock.

For emulator regression tests, record the machine model, selected register, access address, instruction width, old and new register values, and any peripheral state. Test the STF read behavior independently from sound rendering, then test R7 direction changes with ports disconnected or in an instrumented fixture. A passing audio sample does not prove that Port A, Port B, or bus aliases were handled correctly.

Related:

Sources:

Comments