Albireo

From CPCWiki - THE Amstrad CPC encyclopedia!
Revision as of 10:17, 26 August 2017 by PulkoMandy (Talk | contribs) (Update with info and changes from hw revision 1.1.)

Jump to: navigation, search

General

Intro

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.

Board revisions

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.

Initial prototypes

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.

Version 0.9

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.

Version 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.

Version 1.1

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.

Hardware

I/O ports

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.

CH376 registers

  • FE80: "DATA" port (read/write)
  • FE81: "COMMAND" (write) and "STATUS" (read) port

SC16C650B registers

Some of the registers are sharing the same address. A register bit (DLAB) is used to switch between the two groups.

Address DLAB Description
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

DIP switches

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!

Interrupts

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)

Interrupt routing

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.

Interrupt identification

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.


External interrupts

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.

Other resources

Test programs to check that the Albireo boards are working fine:

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)

Albireo interface homepage

Software

Software supporting the Albireo

Upcoming software

  • Serial communication to communicate with a PC
  • Disk ROM to use the mass storage from BASIC