- 1 General
- 2 Hardware
- 2.1 I/O ports
- 2.2 DIP switches
- 2.3 Detecting the hardware
- 2.4 Interrupts
- 2.5 Other resources
- 3 Software
Albireo is an expansion for the Amstrad CPC computers (all models). Its main goal is to provide reliable, fast, cheap and large storage, which it achieves by using a MicroSD card. But the board has a lot of features packed in:
- USB host port, allowing to connect USB mass storage, mouse, and other USB peripherals
- USB device port, allowing to link the CPC to a modern computer with maximal link speed (faster than the z80 can handle, and with on-board buffer and hardware flow control).
The interface is based on the WCH CH376 chip and allows access to USB mass storage and other USB devices on CPC.
The CH376 chip implements FAT32 in hardware, which means no filesystem driver is needed on the CPC side. It also implements the lower level aspects of USB, making it relatively easy to write drivers for other USB devices (mouse, joystick, ...).
What's in it?
- SD and SDHC card mass storage support with fast (6 MHz) SPI link with the SD card. Hardware FAT32 support for easy file access. Raw sector access also possible for homegrown file-systems and other advanced applications.
- USB host support with built in mass storage driver, also with FAT32 and direct sector access.
- Generic USB host with direct control of USB endpoints, for connecting other kinds of USB devices.
- High-speed (1.5 Mbaud) serial link with built-in USB interface for linking with other computers for fast data exchange. Includes flow control, 16 byte FIFO on CPC side, and 512 byte FIFO on remote side, allowing fast buffered and interrupt-driven operation.
- Software configurable interrupt routing to either NMI or INT, or interrupt masking. Multiplexing of several interrupt sources: USB host controller, UART, remotely triggered, and CRTC CURSOR signal interrupts are gathered and easily accessible from a single interrupt status register.
The hardware went through multiple iterations before reaching final state. Each version identifies itself on the USB link and the version should be visible in Windows device manager or lsusb on Linux.
The first prototype was an hand-wired one. There were some changes to I/O ports used since then, so it is not usable anymore.
The first 5 boards were manufactured with an early PCB design, which required some wire-patches to get things working. With the wire-patches, this version behaves the same as 1.0.
About 20 boards were shipped with version 1.0. Unfortunately, as people started to write software using it it turned out that the serial port chip has compatibility problems with the z80 timings. As a result, this version of the board can use the serial port only with the FIFO disabled, which makes it impossible to reach high baudrates. The board is still perfectly usable if you are interested only in the microSD and USB host port.
This version of the board replaces the serial chip with a slightly different one. The board still reads "v1.0" as it is the same PCB, only the chip used has changed.
You can identify your board from the info it sends on the USB device port, or by checking the serial chip (square chip on the back of the board). Version 1.0 uses a TI TL16C550D chip. Version 1.1 uses a NXP SC16C650B chip.
How does it work?
- There are two main devices: the CH376 handles the USB host and SD card side of things, and is accessed at FE80 (data) and FE81 (command/status). The communication side is handled by a SC16C650B, mapped at FEB0-FEB7. This is similar to the chip used on most PC hardware and some Amiga expansions like the SilverSurfer.
- There is an FT230X chip to convert the UART to USB for connecting with a modern PC (standard serial ports are not that common anymore, and they wouldn't be fast enough anyway). The FT230X also generates 12MHz and 48MHz clocks for the two other chips.
- The 16C650 "modem control" lines are connected to various things (CH376 interrupt, FT230X general IO pin for remote control) and turns them into interrupts.
What is it useful for?
Not much currently because there is no software yet, but in the future:
- Use the USB key or SD card directly from BASIC and well-behaving apps (which support extra disk ROMs and a C drive). Load games and tools from the mass storage media
- Connect to another computer like the CPC Booster, load snapshot, DSK or other files from it and write them to floppies or the mass storage media. A snapshot of 128K could be loaded in 0.86 seconds, a snapshot of 64K in less than 0.43 seconds.
- Use SLIP (serial line IP) and a properly setup gateway (Linux machine or similar) to connect the CPC to the Internet.
There is a driver in SymbOS to use Albireo with an USB mouse.
The decoding is clean, this means there aren't any mirror ports or undecoded address bits. Just the addresses listed below are used.
The addresses are in the I/O range, which means you access them with the OUT and IN instructions. They are not memory mapped, and to match with the CPC address decoding, the address is decoded on 16 bytes. This makes using OTIR and similar looped instructions tricky, but is required for compatibility with the CPC.
- FE80: "DATA" port (read/write)
- FE81: "COMMAND" (write) and "STATUS" (read) port
Some of the registers are sharing the same address. A register bit (DLAB) is used to switch between the two groups.
|FEB0||0||RBR/THR: RX buffer (read), TX buffer (write)|
|FEB1||0||IER: Interrupt enable|
|FEB0||1||DLL: Divisor latch LSB|
|FEB1||1||DLM: Divisor latch MSB|
|FEB2||IIR/FCR: Interrupt status (read), FIFO control (write)|
|FEB3||LCR: Line control|
|FEB4||MCR: Modem control|
|FEB5||LSR: Line status|
|FEB6||MSR: Modem status|
|FEB7||SCR: Scratch register|
The board holds 4 DIP switches for configuration. From top to bottom:
S1 - CH376 interrupt enable
- When this switch is ON, the usb controller is allowed to generate interrupts to signal the CPC when it is done performing an operation.
- When this switch is OFF, the usb controller is not allowed to generate interrupts. The CPC must then poll the CH376 STATUS register to know wether the operation is finished.
S2 - CH376 reset enable
- When this switch is ON, the CH376 will be reset at the same time as the CPC (hardware reset only).
- When this switch is OFF, the CH376 will not be reset, and the CPC must initialize it using the reset command (software reset). In this case, the CH376 internal buffer may be used to store reset resident data (but I don't know if this is of any practical use, yet).
S3 - Remote reset enable
- When this switch is ON, the DTR signal from the remote side of the serial link is connected to the CPC reset. This means that the remote side computer can trigger the CPC reset by toggling that line.
- When the switch is OFF, such reset is not allowed and the CPC is safe.
S4 - Remote interrupt enable
- When this switch is ON, the DTR signal from the remote side of the serial link is plugged to the DSR line of the UART controller. It then generates an interrupt which the CPC can process.
Detecting the hardware
Detecting the CH376
You can use the CHECK_EXIST command for this. It gets one byte as argument, and returns the negation of it.
CH376_CMD EQU 0xFE81 CH376_DATA EQU 0xFE80 CMD_CHECK_EXIST EQU 0X06 ; Send the command LD BC, CH376_CMD LD E, CMD_CHECK_EXIST OUT (C), E ; Send one data byte LD BC, CH376_DATA OUT (C), E ; Get the result IN A, (C) ; Check that the result is the same as what we sent XOR E INC A JR NC, ERROR_NOT_DETECTED ; Here, we know that the CH376 is present!
Detecting the TL16C550D
The T16C550D can be detected using its scratch register. This is a read/write register with no effect on the chip. We can check that writing a value there and reading it back works.
SCR EQU 0xFEB7 LD BC, SCRATCH LD A, 0x55 OUT (C), A IN A, (C) CP 0x55 JP NZ, ERROR_NOT_DETECTED ; Here, we know the TL16C550D is present!
All interrupts on the board are handled by the TL16C550D. They can be configured to trigger either an INT or an NMI, or nothing at all.
Individual interrupts control
The SC16C650B manages several different interrupt sources. These can be individually configured using the interrupt enable register.
- Bit 0: data receive interrupt, triggered whenever a byte is received on the serial line
- Bit 1: TX register empty, when the UART has nothing to send.
- Bit 2: receiver line status, to detect RTS/CTS handshaking
- Bit 3: modem status, used for all other interrupts (CH376, remote control, raster interrupt from CRTC cursor)
The interrupts can also be routed to NMI or INT, or none of them if you don't want your code to be interrupted. This is done using the OUT1 and OUT2 bits of the modem control register (MCR).
- OUT1 (MCR bit 2) must be set to 0 to enable INT.
- OUT2 (MCR bit 3) must be set to 0 to enable NMI.
- If both bits are set to 1, interrupts are disabled.
- If both bits are set to 0, both INT and NMI will be triggered, which is probably useless.
When an interrupt occurs, the first step in the interrupt handler is to identify where it comes from. This board provides support only for Z80 interrupt mode 1.
You get information about interrupts by first reading the IIR register. If bit 0 is set, it means Albireo is not the one which generated the interrupt. You should turn to other hardware plugged to your CPC, or, if all else fails, to the gate array interrupt.
If the bit is cleared, there is a pending interrupt from Albireo. You then look at bits 1-3 of IIR to determine which interrupt it is.
- 3: Receive line interrupt, read the LSR register for more details and to clear the interrupt.
- 2: RX data waiting, read the RX register to get the data and clear the interrupt.
- 6: RX timeout, read the RX register as soon as possible to get the data and clear the interrupt.
- 1: TX register empty, this is cleared by reading the IIR or writing more data bytes.
- 0: "modem status", means one of the external interrupts was triggered, read the MSR to learn more and clear the interrupt.
The identification of the external interrupts in the MSR is as follows:
- Bit 0: CTS, used for flow control of serial line. It is recommended to use automatic flow control, in that case this bit is unused and can be ignored.
- Bit 1: Remote control interrupt, when it is enabled using switch S4. This can be triggered from the other side of the serial link using the DTR pin.
- Bit 2: CRTC CURSOR raster interrupt. This is triggered when the CRTC CURSOR signal is activated. When not in use, it is recommended to disable the CURSOR signal using CRTC register 10 to avoid parasite interrupts coming from here.
- Bit 3: Interrupt request from the CH376. Note that this bit will be set both when the CH376 triggers an interrupt, and also when the interrupt is acknowledged on the CH376 side. This means a double-acknowledge scheme is required.
Double acknowledge of interrupts
Due to the way the interrupts are wired, the TL16C550D will trigger an interrupt both when the CH376 triggers one, but also when it is cleared by software. This means after clearing the CH376 interrupt, the interrupt flags of the TL16C550D should be checked again to make sure there isn't any other pending interrupt.
This is not a problem when using the INT pin, because everything will happen with interrupts masked by the z80. However, when using the NMI, there is no masking and this would trigger a new entry into the NMI routine, which is probably not what you want.
To avoid this problem in NMI mode, it is recommended that the NMI handler masks the NMI by using the OUT2 bit in MCR, while it processes the interrupt. This allows to perform all tasks as required. Once all interrupts have been cleared (IIR bit 0 is set again), it is safe to enable the NMI again.
The same applies for the remote control interrupt, when clearing it on the remote side a new interrupt will be triggered. A similar approach can be used: mask out the NMI, tell the remote side the interrupt is handled and let it clear the bit, acknowledge that with the TL16C550D, and finally enable the NMI again.
The CURSOR interrupt is not subject to this, because it is edge triggered. You can use it as an NMI source without such problems. The interrupt is cleared simply by reading the MSR register.
Test programs to check that the Albireo boards are working fine:
- Mass storage tests for SD and USB (get disk capacity, read root directory).
- Complement of the above (load with MERGE), adding a test for HID mouse.
The datasheets of the chips used on the board may be useful:
- CH376: USB-Host and SD card controller (part 1 readily available as "CH376DS1.PDF", and part 2, with help from Google translate.
- SC16C650B: UART for hi-speed link (also used for interrupts control)
- FT231X: UART to USB converter for hi-speed link (also used for clock generation)
Software supporting the Albireo
- SymbOS (USB mouse support)
- Serial communication to communicate with a PC
- Disk ROM to use the mass storage from BASIC