Implementing ACSI on the Raspberry Pi Pico
A developer-friendly guide for building virtual disks on the Atari ST
This article explains how to implement an ACSI device using a Raspberry Pi Pico / Pico W, including:
- electrical concepts
- bus timing
- implementing READ/WRITE
- essential commands
- virtual block device design
- testing
- common pitfalls
It is written for developers who want to build:
- virtual hard drives
- network-based TNFS drives
- flash-based configuration disks
- RAM disks
- floppy emulation layers
ACSI is simple, and the Pico is more than fast enough to implement a full ACSI target.
1. What is ACSI?
ACSI (Atari Computer System Interface) is the hard-disk interface of the Atari ST series.
Internally, it is a simplified version of SCSI-1, using:
- an 8-bit bidirectional data bus
- only a few control signals
- simple 6-byte command blocks
- 512-byte block transfers
Unlike full SCSI, ACSI has:
- no arbitration
- no bus mastering
- no complex selection phase
- no status phase
This makes emulation ideal for small microcontrollers.
2. Electrical Basics
ACSI is a 5V TTL bus.
The Pico (3.3V) must not connect directly to it — level shifting is mandatory.
Recommended level shifting
- 74LVC245
Bidirectional level shifter for D0–D7 - 74LVC245 or 74AHCT245
For ST → Pico control lines - 74LS07 / 74HCT07
Open-collector output for_DRQ(and_IRQ)
Signal directions
| Signal | Direction | Meaning |
|--------|---------------|-----------------------------|
| D0-D7 | Bidirectional | 8-bit data bus |
| _CS | ST -> Pico | Chip select |
| A1 | ST -> Pico | 0 = command, 1 = data |
| R/W | ST -> Pico | 1 = read from device |
| _ACK | ST -> Pico | Handshake per byte |
| _DRQ | Pico -> ST | Data ready (open collector) |
| _IRQ | Pico -> ST | Optional |
| GND | | Ground |
Keep traces short, ground plane solid, and the 245 close to the connector.
3. Pico Software Architecture
A clean structure:
ACSI Command Handler
→ Block Device (512-byte sectors)
→ Optional FAT Layer
→ Backend (TNFS, Flash, RAM, Disk image)
3.1 ACSI Front-End
Responsible for:
- detecting
_CS - reading command bytes using
_ACK - decoding opcodes
- sending or receiving data
- asserting
_DRQ - maintaining sense codes
3.2 Block Device Layer
Implements:
- read_sector(LBA, buffer)
- write_sector(LBA, buffer)
- always 512-byte sectors
3.3 Optional FAT Layer
Used if you want the virtual disk to appear as FAT16.
4. ACSI Command Handling
ACSI uses 6-byte SCSI command blocks.
TEST UNIT READY (0x00)
Reports "OK" if device is ready.
REQUEST SENSE (0x03)
Returns last error.
INQUIRY (0x12)
Returns vendor/product identification.
READ(6) (0x08)
Reads N × 512-byte sectors.
WRITE(6) (0x0A)
Writes sectors.
Return WRITE PROTECT sense code if read-only.
MODE SENSE(6) (0x1A)
Returns basic settings (block size, write protect flag).
Vendor commands (0xC0–0xFF)
For your own configuration protocol, e.g.:
- GET_CONFIG
- SET_SERVER
- SET_WIFI
- SAVE_CONFIG
- RESET_DEVICE
5. Handshake Overview
Command Phase (A1 = 0, R/W = 0)
_CSlow- 6 command bytes written
- each byte strobed by
_ACK
Data-In Phase (device → ST)
- device drives D0–D7
- device asserts
_DRQlow - ST pulses
_ACKto read each byte
Data-Out Phase (ST → device)
- ST drives D0–D7
- ST pulses
_ACK - device reads on
_ACKedges
6. Example: READ(6)
void handle_read6(uint8_t *cmd) {
uint32_t lba = ((cmd[1] & 0x1F) << 16) | (cmd[2] << 8) | cmd[3];
uint32_t count = cmd[4] ? cmd[4] : 256;
for (uint32_t i = 0; i < count; i++) {
read_sector(lba + i, buffer);
send_sector_over_acsi(buffer);
}
}
7. Example: WRITE(6)
void handle_write6(uint8_t *cmd) {
if (readonly) {
set_sense_write_protect();
return CHECK_CONDITION;
}
uint32_t lba = ...;
uint32_t count = ...;
for (i = 0; i < count; i++) {
receive_sector_over_acsi(buffer);
write_sector(lba + i, buffer);
}
}
8. Virtual Disks from Flash
You can embed a read-only FAT16 filesystem directly in the Pico’s flash.
Useful for a configuration tool.
Typical files:
- CONFIG.PRG
- README.TXT
- SETTINGS.CFG
Advantages:
- works without TNFS
- instant boot
- safe (read-only)
- no SD card needed
9. Backend Options
TNFS
Perfect for network-backed storage.
Flash
For built-in configuration disks.
RAM
Ultra fast, fully volatile.
Disk images
Raw .img or .st files mapped on LBA basis.
10. Testing with an Oscilloscope
Check:
_CSlow → device selected_ACKpulses during command/data_DRQlow when sending data- A1 toggles correctly
- R/W matches direction
- D0–D7 stable before
_ACK
Trigger on falling edge of _CS.
11. Common Pitfalls
- Wrong 245 direction → bus contention → ST freezes
- DRQ not open-collector
- INQUIRY wrong size (must be 36 bytes)
- Missing REQUEST SENSE implementation
- Bad timing on data bus
- Weak or missing pull-ups
12. Conclusion
Using:
- Raspberry Pi Pico
- 74LVC245
- 74HCT07 / 74LS07
- Simple firmware
You can emulate:
- multiple hard disks
- TNFS network drives
- flash configuration disks
- RAM disks
- floppy images
ACSI is simple, robust, and perfect for modern retro-storage devices.