Adok's recent article and ICQ chat about Amiga emulators has got my brain ticking over again (I know, that is no easy task. *grin*). He mentioned about the problems of transferring data from one machine onto another and as most people go directly for a serial (null modem) link, I thought I would talk about my own parallel linkup method and some basic, easy-to-understand explanations about communication.
So if you have ever wondered about how to transfer data quickly using nothing more than an adapted parallel printer cable and a few lines of 80386 and 68000 assembly code, then read on...
Why bother and what is PDS?
Many years ago I wanted to create a simple development system, something along the lines of PDS (Programmer's Development System). A few years earlier PDS had been a very popular phrase and had coders drooling, mostly because it made writing code so much easier (especially for large projects on consoles or other ugly OS machines). Whereas proper PDS systems used a PC linked to the 'target' machine, I only had an Amiga A500 and an old Atari ST. Without ever reading a data communications book or having the vital electronics knowledge, I did manage to get a working PDS-like system up and run surpassingly quickly.
The basic idea behind PDS is that you only edit/compile your code on ONE machine and only ever EXECUTE the code on the other machine. The advantage is that you can look at your code while your program is being tested on the target machine. If the program crashes then your source code is unaffected, you don't need to reload your editor, compiler, IDE etc.. you only have to reboot the target machine and load the DOWNLOADER software.
The Parallel Port
I chose the parallel port because of its high speed and ease of access. A serial connection is okay, but on those 16-bit computers it would have taken ages to transfer anything larger than a 10kb file. Remember, parallel is more than 8 times faster than serial because you can send a whole byte at a time.
Firstly I took an old 2m printer cable and replaced the printer plug with another 25-pin D-type connector. You could build an entire cable from scratch, but it's quicker and cheaper to buy a printer cable and adapt it. The wiring below is pretty much the bare minimum (this is due to the basic Atari ST hardware). All you need are the 8 data-lines and swap the Strobe <--> Busy lines over so that the Strobe from one machine goes to the Busy of the other and vice-versa.
In fact the Atari ST port Busy signal line was totally screwed. But it was still possible to transfer 1 meg from the ST up to my PC in around 25 seconds.
busy <--------- data line -------> strobe 13 11 9 8 7 6 5 4 3 2 1 \ o o o o o o o o o o o o o / PC \ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ / \ o o ³ o o ³ o ³ o ³ o ³ o ³ o ³ o ³ o ³ o ³ / ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ÚÄÄÄ³ ÄÄ³ ÄÄ³ ÄÄ³ ÄÄ³ ÄÄ³ ÄÄ³ ÄÄ³ ÄÄÙ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄ³ ÄÄ³ ÄÄ³ ÄÄ³ ÄÄ³ ÄÄ³ ÄÄ³ ÄÄ³ ÄÄ¿ ÚÄÄÄÙ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ strobe 13 ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ 1 \ o o o o o o o o o o o o o / ST \ busy / \ o o o o o o o o o o o o /
Sync, Strobe and Busy
Okay, now you've got a modified printer cable you need to write the software. In order to do this you need to think about sync, handshake, strobe and busy (gee, sounds like a Freemason disco party game ;)). You need to think in terms of time. I will describe the one-way strobe method because its the easiest. It involves using the 8 Data-lines and the 1 Strobe-line. The Strobe line acts like a timing signal, like the red and green at the traffic lights. We need to tell the target machine when a new byte has been written to the 8 data-lines.
Sync byte 1 byte 2 byte 3 byte 4 a b c a b c a b c a b c hi ÚÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄ¿ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ lo ÄÄÙ ÀÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÙ À.... d d d time ---------------------->
The above time diagram shows the 4 stages of data transmission in terms of the Stobe-->Busy signal (the hi, lo). Stage 'a' 'b' and 'c' happen on the sender machine (in this case the Atari ST). Stage 'd' happens on the target receiver machine (in this case the PC).
Stage 'a' Sender: Set Strobe high ----> Target: sees Busy=high stage 'b' Sender: Write byte to Data-lines stage 'c' Sender: Set Strobe low ----> Target: sees Busy=low stage 'd' Target: Reads byte from Data-lines
As you can see we can keep both the Sender and Target machine in phrase by means of our 'sync' signal. The sync signal is sent from the Sender ('Strobe' pin #1) and is received by the Target ('Busy' pin #11). The job of the sync is to keep both machines in phase (so you know when a new data byte has been transmitted) and also to say when a valid byte is on the data-lines.
You should notice that the hi, lo states tell both sides when it is safe to write (sender) a new byte and when it is safe to read (target) a new byte. It's like the traffic lights at a junction, when one direction is red the other is green. This prevents any collision in terms of data.
Some nice 68000 code
Here is a snippet of 68000 source code which will transmit a block of data using the above strobe-busy sync method. It doesn't bother about checking if the target machine is ready or not. It was written for the Atari ST, which has its parallel port registers on the sound chip. The 'MOVEP' instruction does a similar thing to the 80x86 'OUT DX,AX' instruction, except the 68000 has NO ports, it is all memory based.
;* Download(A0) Length(d0) * download: sub.l a2,a2 move.w #$07c0,d1 movep.w d1,SNDCHIP(a2) ; Port A & B = output mode move.w #$0e07,d2 ; strobe HIGH - normal dl_LOOP: bsr.s dl_PULSE ;(a) strobe HIGH (busy) + delay move.w #$0F00,d1 move.b (a0)+,d1 movep.w d1,SNDCHIP(a2) ;(b) byte --> port B bsr.s dl_PULSE ;(c) strobe LOW (ready) + delay subq.l #1,d0 bne.s dl_LOOP ; final HIGH (I'm Busy...) dl_PULSE: movep.w d2,SNDCHIP(a2) ; SetStrobe(d2) rol.l #8,d1 ; a lame, short delay move.w d0,COLOR0(a2) ; some horrible turbo fx bchg #5,d2 ; toggle Strobe Hi/Lo value rts
Yep, that's about 48 bytes of 68000 code. It definitely works because I've used it to take a memory snapshot of a game and upload it onto the PC so I could run it using the PacifiST emulator.
Some 80386 pmode code
And here is the corresponding 80386 Protected-mode code to upload a block of data from the parallel port. If you have any problems reading data from your PC parallel port then try port+00h or port+03h.
PPORT equ 278h ; parallel port base PPORT_STATUS equ PPORT+1 PPORT_INPUT equ PPORT+3 ; was +3 KEY_PORT equ 60h ; keyboard data port SETBORDER MACRO colr mov dx,3C0h mov al,31h out dx,al mov al,colr out dx,al ENDM ;* Upload into[ES:EDI] length(ECX) * upload: mov dx,3DAh in al,dx ; clear flip-flop ;-------------------- wait for initial busy (HIGH) --------------------- SETBORDER 000111b ; grey mov dx,PPORT_STATUS up_SYNC: in al,KEY_PORT cmp al,81h jz short up_BREAK ; ESC ? in al,dx test al,80h jz short up_SYNC ; not busy ? ;------------------------- now begin upload ---------------------------- SETBORDER 010010b ; green up_LOOP: mov dx,PPORT_STATUS up_BUSY: in al,KEY_PORT cmp al,81h jz short up_BREAK ; ESC ? in al,dx test al,80h jnz short up_BUSY ; wait until ready ... mov dx,PPORT_INPUT in al,dx ; read byte from Data-lines stosb ; byte --> buffer mov ah,al SETBORDER ah ; nice turbs mov dx,PPORT_STATUS up_READY: in al,KEY_PORT cmp al,81h jz short up_BREAK ; ESC ? in al,dx test al,80h jz short up_READY ; wait until busy again ... dec ecx jnz short up_LOOP SETBORDER 000000b ; black = okay clc ret up_BREAK: lea edx,breaktxt call conmess ; display 'User break' message SETBORDER 100100b ; red = error/break stc ret
Getting started by yourself
Okay, so none of you will probably ever want to upload data from an ancient Atari-ST to the PC, but you might want to transfer data from the Amiga or another PC, in which can you should be able to adapt the method to suit your needs. Here are some tips which might help you create your own uploader and downloader software.
(1) Write a test program to display ALL the port registers.
(2) Write a test program to toggle the Strobe and place test values on the Data-lines to check your cable.
(3) Examine the default values (after reboot) of the busy signal.
(4) Keep read and write stages on opposite hi/lo states.
(5) When downloading PC --> Amiga write 00h to Data-lines when you have finished, otherwise when you reboot the Amiga will Guru because it thinks the parallel port is broken.
(6) Some old PCs don't allow reading of the Data-lines in which case you need to use a 'LapLink' style cable. This uses a nibble transfer method using 5 status lines instead of the data-lines to read data.
(7) Be careful of SPP, EPP and ECP parallel ports (try reading from port+03h if port+00h gives no data).
Oh well, this might be of interest to someone out there. You can have some fun with parallel cables and trying to optimise your machines for maximum transfer speed. With most new PCs you now have DMA driven ECP (Enhanced Character Port) ports which often some really nice speeds without having to bother the CPU too much. But then again, if you want speed then perhaps the USB is worth looking at for PC-2-PC communication.
And yeah, if you need to copy gigs of data from one PC to another, then please, remove the HD, plug it in place of a CD-ROM/DVD drive and watch those bits really zoom along.