Printer Slave port

Provides a quick and easy way of getting programs into the system. Simpler and faster than a serial port, and no RS232 buffers to fit.
This has been implemented and is much more convenient than re-typing or time-consuming compilation of assembly code into the FPGA itself.

It requires PD0-7, !STB, and BUSY. The rising edge of the !STB signal loads a register and automatically asserts BUSY. The target system reads this register and automatically asserts BUSY.


Connections

Pinout arranged to be compatible with the BurchEd printer port interface. I considered having the data lines sent through a '573 type latch to the CPU data bus. This would save seven FPGA pins but consume scarce PCB space and be less flexible. It could not be programmed to be a printer output port. Hence FPGA pins were used to retain flexibility.

Printer     PWR 1 2 182 185  
D25 Cable              
1 1 --> 100R lpt_n_stb 181 160 3 4 161 187 lpt_n_auto_lf
14 2 --> 100R ----------------------- -'      
2 3 --> 100R lpt_d<0> 188 162 5 6 163 189 lpt_error
15 4 <-- 100R ----------------------- -'      
3 5 --> 100R lpt_d<1> 191 164 7 8 165 192 lpt_n_init
16 6 --> 100R ----------------------- -'      
4 7 --> 100R lpt_d<2> 193 166 9 10 167 194 lpt_n_select
17 8 --> 100R ----------------------- -'      
5 9 --> 100R lpt_d<3> 195 168 11 12 169 199 lpt_d<4>
6 11 --> 100R ----------------------- -'      
7 13 --> 100R lpt_d<5> 200 173 13 14 174 201 lpt_d<6>
8 15 --> 100R ----------------------- -'      
9 17 --> 100R lpt_d<7> 202 175 15 16 176 203 lpt_ack
10 19 <-- 100R ----------------------- -'      
11 21 <-- 100R lpt_n_busy 204 178 17 18 179 205 lpt_paper
12 23 <-- 100R ----------------------- -'      
13 25 <-- 100R lpt_selected 206 180 19 20 GND    
18
to
25
10,12,
14,16,
18,20,
22,24
--- GND  

The 100R resistors damp reflections (and limit current if conflicts occur!).
Input signals require 4k7 pull up resistors.
Output signals should be open-collector.

During implementation the VHDL compiler pointed out there were not enough I/O blocks, so only !INIT, !STB and BUSY were implemented.


Software (Target system)

A short and simple BASIC program demonstrated the principles by polling the busy flag, then reading the data register and printing it to the screen. The transfer rate was only limited by speed of interpreter and printing/scrolling screen characters. Assembly code is much faster. Short routines were written to read incoming bytes from the slave port while !INIT is high.

I found a 1,363K text file (about a floppy full) took 21 mins to transfer with each byte written to the screen and the whole screen scrolled every 40 chars. This takes a lot of time, since it has to move the screen in software. I swapped the call for three nop codes, and the file transferred in 22 seconds. 2.35 seconds of that was the nop codes. So each byte took about 16 us to transfer. It is faster than copying a floppy. And much faster than tape (300 baud). Works out around 13.96 Mbaud! I have not got code to hand over lines to the interpreter yet but at that rate the transfer overhead is about one second per 64K. Any significant time delay is in processing the bytes in the target.

The Atom is easily programmed to accept ASCII text 'printed' to it by the PC, by changing the OSRDCH vector to point to the slave port. This has to be done in one go, to avoid a half-written vector. There is no 16-bit write command, but there is a 32-bit write which can be used like so:

!#0208=#A000FE55

to set the new OSRDCH to A000, and retaining the original OSWRCH. The latter could be changed to point to a null function so that the download is not slowed by writing to screen. Immediately after this command, the Atom's real keyboard is ignored. When the PC has finished 'typing' in a program, it has to return keyboard control back to the user. It does this by 'typing' in the command:

!#0208=#FE94FE55

to restore vectors. Immediately after this command, the Atom's real keyboard is enabled.

The Atom also has a vector for an OS Command Line Interpreter (OSCLI). This could be changed to point to a completely new OS interpreter, though not a trivial task. It would be simpler to change the filing system vectors (OSBGET, OSBPUT) from their normal tape cassette I/O to printer slave routines. This would allow the PC to appear as if it were a tape recorder, only very much faster. However, this requires the PC to understand the data structure of saved files. This is moderately simple but more complex than a simple keyboard replacement routine.


Software (PC)

This was easy to do, about 100 lines of C source file to send bytes from a hard disk file to the printer port. Direct i/o, so not legal in a stricter OS than Win98, but okay just to get started.

Text files require some 'filtering' because the interpreter expects CR from the keyboard but not LF, which it reports as an error. Windows Notepad puts CRLF at the end of lines, so my simple PC program simply discards LF.


File Formats

Atom software usually exists in Atom-specific file formats which include information about where to load the program and where to start executing code. NB: The multi-byte elements in the structures above are little endian (same as the PC).

Atom Standard format

atom_file_std = // 19 bytes
{
	UINT16	addr_to_load;	//
	UINT16	addr_to_exec;	//
	BYTE	reserved[12];
	BYTE	fixed[2];	// always 0x0d, 0x00
	BYTE	payload[size];
}

Atom-in-PC

atom_file_aipc = // 16 bytes
{
	UINT16	addr_to_load;	// 
	UINT16	addr_to_exec;	// 
	UINT32	size;		// way bigger than likely! :-)
	BYTE	reserved[11];
	BYTE	reserved[8];
	BYTE	payload[size];
}

Atom Emulator by Wouter Ras

atom_file_ras = // 22 bytes
{
	BYTE	name[16];
	UINT16	addr_to_load;	// 
	UINT16	addr_to_exec;	// 
	UINT16	size;		// 
	BYTE	payload[size];
}