Notes on PCW I/O ports

The information herein is entirely empirical and completely unofficial; it is gathered from (ahem) 'experiments' of my own, posts to various newsgroups, and information published in 8000 Plus and PCW Plus in times past. I accept no responsibility for anything.

The bits which I've investigated are true for the PCW8256/8512, at the very least; I have no access to other models. However I've marked the ones that (IMO) are least likely to work on all of them (such as anything related to the dot-matrix printer). It goes without saying that very little of this is likely to be of relevance to the PcW16.

To the best of my knowledge the PCW doesn't take advantage of the 'extended' port addressing scheme offered by setting B as well as C. Some peripherals might, though.

Cliff Lawson has released Amstrad's definitive specification docs for the PCW I/O system.

Any corrections, additions, or updates will be more than welcome.

Built-in ports

Ports #00-#7F (0-127 decimal)

Ports #00 and #01 are the 'official' FDC status and data ports respectively (see the specification). However since A7 from the Z80 is tied to the (active low) CS line of the FDC, all of #00-#7F are taken up by the FDC.

I don't know of any comprehensive guides to the 765 on the web (that would allow one to write a device driver from scratch, say), although I'd like to hear of one. There's something approaching documentation at the Unofficial Amstrad resource (although it's been written with CPCs in mind).

Ports #F0-#F3 (240-243 decimal)

Output: Memory map control registers. Control which memory banks are in context in each address range. See section 8.1 of the spec.

'Expansion block' values output correspond to the following blocks under CP/M:

#80: CP/M hidden stuff (inc BIOS jumpblock) here
#81: more CP/M, first part of default screen memory
#82: second part of default screen memory, character matrices, roller-RAM
#83: CP/M stuff (BDOS & BIOS), keyboard memory-mapped I/O
#84: TPA #0000-#3FFF
#85: TPA #4000-#7FFF
#86: TPA #8000-#BFFF
#87: TPA #C000-#FFFF (common memory)
#88: more CP/M (CCP, buffers, parts of BIOS)
#89 onwards: used for M: drive

Banks under CP/M selected using the BIOS function SELMEM are made up as follows:

  0: #80 #81 #83 #87 (hidden bank)
  1: #84 #85 #86 #87 (TPA bank)
  2:     #88     #87 (extra)
  3 onwards: ?
SCR: #80 #81 #82 #87 (see SCR RUN below)

See also:

Port #F4 (244 decimal)

Input: 'timer interrupt counter'; see section 4 of the spec. The lower four bits are a count of 'missed' timer interrupts; the upper four 'undefined' bits have been those of port #F8 every time I've looked at them. Reading from this port will reset the counter on bits 0-3.

Output: 'memory map read/write control'; see section 8.2 of the spec.

Port #F5 (245 decimal)

Output: controls the base location of the roller-RAM to a resolution of two pages (512 bytes) within the first 128k of memory. See section 7.2.1 of the spec. Under CP/M the usual setting is #5B (91 decimal) corresponding to a base address of #B600 in the screen environment.

Port #F6 (246 decimal)

Output: controls the vertical screen origin; see section 7.2.2 of the spec. 0 is the normal value; 1 puts screen line 1 (counting from the top) at the top of the screen, and so on.

Port #F7 (247 decimal)

Output: controls ink colours; see section 7.1 of the spec. Bits 7 and 6 (respectively) have the following effects:

0 0  background black   foreground black
0 1  background black   foreground bright  (normal)
1 0  background bright  foreground bright
1 1  background bright  foreground normal
This is much the same as TE SET BORDER except that bit 6 is inverted.

In order to manage flashing colours, CP/M maintains its own values for these, and outputs them every so often; hence outputting a value will result in a brief flash. I believe the same is true for Locoscript.

See also:

Port #F8 (248 decimal)

Input: 'system status': timers, counters, bits and bobs. See section 3.1 of the spec. On the machines I tested bits 0-3 contain the timer interrupt counter from port #F4; however when you read from #F8 the counter is not reset. I can't say whether this is true across all models, since it's undocumented.

Output: 'system control': random PCW functions. See section 3.2 of the spec.

See also:

Ports #FC-#FD (252-253 decimal)

The following is valid for the 8000 series PCWs with their dot-matrix printer. I would imagine it's also valid for the 9256, but certainly not for the 9512 or 9512+.

Unfortunately there is no documentation available on driving the printer, and the interface is proprietary, so anyone wanting to drive it at this level is probably going to have to reverse-engineer CP/M. Good places to start are probably Michael Keys' books PCW Machine Code and PCW Super Code, in (one of) which he grovels around in the bowels of the printing system in a most unseemly fashion.

Port #FD input: Printer status. Bits 0-7 as follows:

bit 7: bail-bar (0 = bail-bar out)
    6: ?
    5: ?
    4: ?
    3: ?
    2: paper sensor (1 = paper found)
    1: ?
    0: ?

According to one source I've seen there are five usable signals here; I haven't worked out what the other three are yet.

Output: 'printer commands'. Probably pretty low-level.

Ports used by peripherals

Serial port - ports #E0-#E7 (224-231 decimal)

The 'ordinary' serial port on devices such as the CPS8256 which is compatible with unpatched CP/M lives here. Since I haven't got round to writing anything useful about it you'd best see Richard Fairhurst's information.

Fax Link interface - ports #C8-#CF (200-207 decimal)

Virtually the same as the CPS8256-type interface except for the baud-rate values.

Parallel port (CEN:) - ports #E3 & #E8 (227 & 232 decimal)

No more information at present - these appear to be what are used, from disassembling someone's souped-up CEN: driver. My guess is that #E3 is status and #E8 is data, but that's only a guess so far.

9512 parallel port (PAR:) - ports #FC-#FD (252-253 decimal)

No information yet, apart from port numbers. Nor is this strictly a peripheral, but never mind.

MasterScan scanner - port #DF (223 decimal)

Input: bit 0 is clear when the scanning head detects light (white paper) and is set otherwise. All other bits are 1.

Spectravideo joystick - port #E0 (224 decimal)

Input: bits are set as follows (if joystick is not connected, input value is all 1's):

bit 7: 0
    6: 1
    5: 1
    4: 1 if in E position
    3: 1 if N
    2: 1 if W
    1: 1 if fire pressed
    0: 1 if S

Values are additive; for instance 01101100 indicates that the joystick is in the NW position.

This information came from 8000 Plus (Apr 1987, p62, due to P Western of Southampton) and I can't vouch for it. It looks like the joystick would conflict with the serial port on a CPS8256, though.

AMX mouse - ports #A0-#A7 (160-167 decimal)

Input: according to the info I have only the first three ports are needed.

Port #A0 records vertical movement. It consists of two 4-bit counters. The counter in bits 0-3 is incremented when the mouse is moves up, and the counter in bits 4-7 is incremented when it is moved down. Port #A1 records horizontal movement in a similar fashion; the low nibble counter is for rightward movement and the high nibble counter for leftward movement.

Port #A2 shows button states (0 if button pressed, 1 otherwise):

bit 2: right button
    1: middle button
    0: left button

This information came from 8000 Plus (Jan 1990, p73, due to C Black of Oxford) and I can't vouch for it.

Kempston mouse - ports #D0-#D4 (208-212 decimal)

According to 8000 Plus this device is "similar" in use to the AMX mouse. While Joyce was under development the following information was found to be sufficient.

Input: ports #D0 and #D1 provide X and Y coordinates respectively. Port #D4 shows button status (0 if button pressed, 1 otherwise):

bit 1: left button
    0: right button

Nothing useful is known to be on #D2 and #D3.

EMR MIDI interface - ports #A2-#A3 (162-163 decimal)

This basically looks like a very fast serial interface (31250 baud). Port #A2 is the status port and #A3 is the I/O port. Bit 1 of the value from the status port is set if the interface is ready to receive data. My notes don't say what the corresponding bit on the status port for input is; this should be enough to get you going, though.

Programs written with the above information need to have the software supplied with the interface run before they will work reliably. There's some sort of initialisation code required which I've not yet been able to reconstruct. The box (perhaps surprisingly) doesn't contain one of the Z80 family serial chips so one can't use the usual reset code.

For information on actually talking to MIDI machinery you'll have to look elsewhere; I found Advanced MIDI User's Guide by Penfold very useful. I've no doubt there's some guide on the Web somewhere.

ASD PCWHD20 20Mb hard disc unit - ports #A0?-#A7? (160?-167? decimal)

Almost completely in the dark about this, despite having one sitting on my desk - all I know is that it conflicts with the EMR MIDI interface. (I no longer have any faith that the 'head parking' code I used to have here did anything useful.)

The unit itself is a big grey box that the PCW sits on top of; inside is a power supply and a half-height drive labelled 'Cogito Systems PT925', which looks like an ST225 clone to me.

Update: after looking over the ASD.FID driver that came with it, John Elliott offers this analysis:

Looks to me as if the interface used is ATA, with 8-bit transfers. I can't see a SET FEATURES command, so either the hardware is translating two successive reads/writes by the PCW to a single 16-bit transfer, or the drive has been forced (by a jumper?) to use 8-bit transfers.

The ATA registers are at 0A0h - 0A7h:

CP/M page. 2009 November 12; mail.