home.social

#programmers-development-system — Public Fediverse posts

Live and recent posts from across the Fediverse tagged #programmers-development-system, aggregated by home.social.

fetched live
  1. PDS – the Programmers Development System – Part 8

    I thought it time to take a proper look at the Amstrad Target board, seeing as I’ve managed to find myself an Amstrad CPC 464. But first I have a short diversion into loading from audio files.

    • Part 1 – Introduction, background and some initial reverse engineering.
    • Part 2 – A closer look at the PC ISA Interface card.
    • Part 3 – Remaking the target interfaces.
    • Part 4 – Building the boards.
    • Part 5 – Getting everything running (first, unsuccessful attempt).
    • Part 6 – Some serious diagnostics and a breakthrough (at last)!
    • Part 7 – Diagnostic module PCB.
    • Part 8 – Audio loading and the Amstrad target board.
    • Find it on GitHub here: https://github.com/diyelectromusic/PDS_Remake

    TAP to Real Audio Files

    I wanted to produce an audio file of the TAP file for use with the ZX Spectrum and producing a WAV file was relatively straight forward. But finding a way to play it was a lot more tricky than I expected…

    Initially I figured I’d just play the file using TZXduino and record it using a phone or something and that did work, but it was a bit noisy. And it wouldn’t load.

    But then I discovered https://www.igormaznitsa.com/tap2wav/index.html

    This is great and generates a really clean signal. The first utility I found didn’t centre the “zero” point in the wave properly, so I thought that might cause problems, but this one does everything really clearly and when the signal is opened in an Audio editor, we can see how precise everything is.

    But this still doesn’t load. So far I’ve tried the following:

    • Use a smartphone with a USB-C to 3.5mm jack adaptor.
    • Use a dumbphone with a physical headphone jack.
    • Use old, otherwise essentially useless, AAA powered MP3 players (several tried).

    In terms of the files themselves, I’ve tried the following:

    • WAV and MP3.
    • Boosting, halving, otherwise adjusting the volume of signals.
    • Using a noise-gate filter.

    But nothing I’ve tried works. At one point I got the first stage loader to register as far as the filename on the screen, but then R Tape Loading Error.

    Asking online, I got some answers. It turns out that modern digital players do not have the kinds of output levels that will drive a ZX Spectrum. A system with a significant volume range may do it, but chances are nothing will compare to a “vintage” small tape recorder.

    Stewart Russell on Mastodon sent me to this link which has a really elegant solution: https://retrocomputing.stackexchange.com/questions/773/loading-zx-spectrum-tape-audio-in-a-post-cassette-world

    The basic idea is to use a battery powered player, so it has no common GND to the Spectrum, and then create a differential stereo signal. Then using a stereo jack, it will connect to the mono jack in the Spectrum with one channel being GND and the other channel being signal. This has the effect of doubling the signal. That is really lateral thinking!

    I’ve not tried it at this stage, and really I’d like to find a bit of a more conventional solution, but really at the end of the day it is hard to compete with the TZXDuino/MaxDuino type solution.

    Amstrad CPC Target Board

    I really wanted to try to get the Amstrad board running, but to do that, I was missing a rather vital piece of equipment. I don’t have an Amstrad 8-bit computer. Until now. At a recent retro sale at The Retro Collective I managed to pick up an Amstrad CPC 464 with a colour monitor, and it appears to work, which is amazing.

    So I set about repeating some of the steps I took in Part 5 with the Spectrum board.

    Key points:

    • There are Amstrad equivalents of the DL0, DL1 and DL2 monitor code for the Amstrad CPC.
    • The Amstrad target board usings ports &FBEC-&FBEF for the PIO data and control channels.
    • Otherwise, everything should be essentially the same as the Spectrum version.

    The steps to get the monitor code into something usable for me are:

    • Make the same adjustments (JPs, labels and removing PDS specific instructions) to the source.
    • Assemble it using an online Z80 assembler.
    • Take the HEX or Binary output and turn it into something I can use with the Amstrad.

    And here I hit the first problem. The Amstrad CPC 464 does not have an external tape port, so I can’t use it with my TZXDuino. The TZXDuino does support the CDT tape format that many Amstrad images use, but there is no where to plug it in. There are a number of projects online that show how to add a typical (for later models) Amstrad 5-pin DIN cassette port socket, but so far I don’t have that.

    So another option was to use some of the previous techniques to produce an audio file I could actually et onto a tape. But whilst my tape drive (the “datacorder”) has working FF and REV, it seems that Play does not engage the transport to move the spindles. So that is something I’ll need to sort out at some point.

    So for now, if I want to try it, I’m back to typing in a BASIC machine code loader.

    The Amstrad BASIC is a bit more sophisticated than the Spectrum, so I can use HEX values directly. This means it is fairly trivial to take the HEX record format and with a bit of repetitive cut-and-pasting get the values as HEX codes in a BASIC program as follows.

    :108000003EFF01EEFBED79ED790CED790EEDED79AA
    :108010000EEF3E3FED791640F3CD60807BFEB4CA93
    :108020004380FEB7CA3980FEB5C21980CD60806337
    :10803000CD60806B011980C5E9CD6080067F4BED76
    :108040004918D6CD608063CD60806BCD608043CD14
    :1080500060804BCD608073230B78B1C2538018B918
    :10806000C501EDFBED78AA0FDA64800DED580C7AAE
    :07807000ED79EE8157C1C953
    :00000001FF

    5 SYMBOL AFTER 256: MEMORY &7FFF: SYMBOL AFTER 240
    10 LET a=&8000
    20 READ n: POKE a,n
    30 LET a=a+1
    40 GOTO 20
    100 DATA &3E,&FF,&01,&EE, &FB,&ED,&79,&ED
    105 DATA &79,&0C,&ED,&79, &0E,&ED,&ED,&79
    110 DATA &0E,&EF,&3E,&3F, &ED,&79,&16,&40
    115 DATA &F3,&CD,&60,&80, &7B,&FE,&B4,&CA
    120 DATA &43,&80,&FE,&B7, &CA,&39,&80,&FE
    125 DATA &B5,&C2,&19,&80, &CD,&60,&80,&63
    130 DATA &CD,&60,&80,&6B, &01,&19,&80,&C5
    135 DATA &E9,&CD,&60,&80, &06,&7F,&4B,&ED
    140 DATA &49,&18,&D6,&CD, &60,&80,&63,&CD
    145 DATA &60,&80,&6B,&CD, &60,&80,&43,&CD
    150 DATA &60,&80,&4B,&CD, &60,&80,&73,&23
    155 DATA &0B,&78,&B1,&C2, &53,&80,&18,&B9
    160 DATA &C5,&01,&ED,&FB, &ED,&78,&AA,&0F
    165 DATA &DA,&64,&80,&0D, &ED,&58,&0C,&7A
    170 DATA &ED,&79,&EE,&81, &57,&C1,&C9

    RUN
    CALL &8000

    In the above, we can see the HEX record for DL0 (with the PDS specific details removed) with an ORIGIN of 0x8000. Then there is the equivalent BASIC loader with the data statements for the HEX values less the line headers and checksums. This is followed by the two instructions I need to RUN the loader and then CALL the code.

    That first line of the BASIC programme is apparently how one limits the memory used by BASIC and reserves space for user machine code programmes.

    I typed all this in and checked as I was going, and then double checked at the end. But then – nothing. The PC end is exactly the same as before and I was going to attempt to fill some screen memory again (which apparently starts at 0xC000) but when I tried to link with the target I got the dreaded “computer is not receiving” error. Reluctantly I had to reset the Amstrad and attempt to figure out what was going on.

    Following the same process I took in Part 5 (and using my diagnostics board from Part 6) I first tried to write directly to the Z80 PIO from Amstrad BASIC using OUT instructions:

    OUT &FBEF, 255  : REM Port B Control
    OUT &FBEF, 63 : REM Port B bits 6,7 as OUTPUT
    OUT &FBED, 128 : REM Port B Data bit 7
    OUT &FBED, 0

    This should have turned the Target->PC LED on then off. But I got nothing.

    At this point I went back and verified the schematic and address decoding to make sure I knew what was supposed to be happening. The relevant part of the schematic is shown below:

    For address decoding, A0 and A1 have the same function as before – they select between ports A and B and control and data. The IO address is determined by A4 and A10 via an OR gate into /CE. This has the following decoding:

    A10A4/CE000011101111

    We can see that the only combination that results in /CE being LOW (so activating the Z80 PIO) is when A4 and A10 are both 0. Once again though this leads to very slopping address decoding as, ignoring A0 and A1, any of the other 10 address lines could be any value and the decoding will still trigger.

    The convention appears to be to use “all HIGH” addresses, which gives us the prefix used 0xFBEC as follows:

    0xFBEC = b1111 1011 1110 11xx

    The other things I pondered where how the enable switch connects the /IORQ line of the PIO HIGH in both cases but once with a direct 10K pull-up and once with a 1M pull-up and then on to the edge connector /IORQ. Also I noted that the CLOCK is connected to CLK4 on the edge connector; and how only /RD is connected (i.e. not /WR) alongside /M1. But otherwise there was nothing particularly odd going on.

    At this point I grabbed the oscilloscope and started to probe things as I ran the OUT instructions. At one point I knocked the card and had a pile of gibberish appear on the screen as if I’d typed random characters on the keyboard, so I wondered if it was seated properly.

    Power off and reseating the board and trying the OUTs again and this type I actually got some LEDs being controlled. Perhaps it just wasn’t physically connected properly.

    At this point I sealed myself to retyping in the BASIC loader once again.

    I still didn’t seem to get any response to my attempts to fill the screen from the PC PDS, but critically I also wasn’t getting the “computer not receiving” errors either. When I put a scope on the PC to Target and Target to PC control lines, I can see them both toggling in response to the communications happening.

    So at this point I can say pretty confidently that the Amstrad CPC Target board is working, but for some reason (probably due to my lack of knowledge about how the Amstrad works) I’ve not been able to induce an observable effect in the CPC by poking memory.

    I’ve looked over the monitor code and I can’t see any reason why it wouldn’t do the same as the Spectrum code. I did notice that it appears to disable interrupts near the start, but then so did the Spectrum version. But would this stop the display updating? More research is needed.

    Conclusion

    I think I’ve shown that the card itself, and probably the provided code, does work which was my main aim.

    Unfortunately at this point I don’t know enough about the Amstrad to figure out quite how to drive the PDS in a useful way so on that front I still have some work to do.

    But I’m going to leave this here for now. If I figure anything else out, I’m come back and update things.

    Kevin

    #amstradCpc #pds #programmersDevelopmentSystem
  2. Right, the PDS repository is now public and the blog series should now be up to date with where I've got to with it all so far.

    Series starts here: emalliab.wordpress.com/2026/05

    #PDS #ProgrammersDevelopmentSystem #RetroComputing

  3. PDS – the Programmers Development System – Part 6

    This series of posts looks at the Programmers Development System (PDS).

    • Part 1 – Introduction, background and some initial reverse engineering.
    • Part 2 – A closer look at the PC ISA Interface card.
    • Part 3 – Remaking the target interfaces.
    • Part 4 – Building the boards.
    • Part 5 – Getting everything running (first, unsuccessful attempt).
    • Part 6 – Some serious diagnostics and a breakthrough (at last)!

    This part gets serious about attempting to debug eveything and find out why it isn’t working…

    PDS Diagnostic Breakout

    The starting point is trying to figure out what is going on with the signals on the link. To do that, I’ve built a simple breakout which can be used to probe the signal lines or, as in my case, attach some LEDs.

    I initially thought I could use some of those “cobbler” breakout boards that expand out Raspberry Pi GPIO to solderless breadboards. But unfortunately, they aren’t a direct 2×13, 2×20 mapping to the breadboard, as the GND pins are all linked together and would short some of the PDS connections.

    Instead I went with building something simple myself using protoboard:

    It is a straight, simple breakout from the 2×8 way header to two sets of 8-way header pins suitable for plugging into a solderless breadboard.

    I’m wiring it up as a “straight through” connection to the target board, mostly to save me having to make more PDS cables – doing it this way means a simple Euro rack 2×8 power ribbon will do (and I have quite a few of those kicking around).

    This is the wiring I’m using for the board. Recall the target connector has the following pinouts:

    N/CN/CN/CN/CN/CZX->PCPC->ZXGNDD7D6D5D4D3D2D1D0

    Assuming I have it all right of course.

    This now allows me to attach some 8-way LED breakout boards that connect to 8 signals plus ground to allow for easy observations.

    Testing the ZX Spectrum Board

    At this point I can confirm that the ZX Spectrum target board can still talk to its Z80 PIO using the following BASIC code:

    10 OUT 127,255
    20 OUT 127,63
    30 FOR n=0 TO 100: NEXT n
    40 OUT 63,128
    50 FOR n=0 TO 100: NEXT n
    60 OUT 63,0
    70 GOTO 30

    This is basically a ZX Spectrum/Z80 PIO/PDS “blink” application using the “ZX to PC” pin.

    https://makertube.net/w/kQNKyii3R9gYu2iiW6r2f5

    So what is going on here? Recall from Part 1 that the IO ports used are as follows:

    IO PORTFunctionNotes31Port A DataUsed for the D0-D7 lines (via a buffer)63Port B DataUsed for the ZX<->PC control95Port A ControlUsing Z80 PIO “Mode 3”127Port B ControlUsing Z80 PIO “Mode 3”

    The mapping of Port B Data to PDS control pins isn’t as one might expect however, again from Part 1, we have noted:

    76543210   PORT B DATA BITS
    0-- Pin 3: PC to ZX
    4321--- Not used
    5------- Pin 7: Function unknown
    6-------- Data buffer direction control (0=OUT; 1=IN)
    7--------- Pin 5: ZX to PC

    Armed with this knowledge, we can explain the BASIC program as follows:

    OUT 127,255  : PORT B Control = b11111111 MODE 3: bidirectional
    OUT 127,63 : PORT B Control = b00111111 Bits 6,7=OUTPUT, 0-5=INPUT

    OUT 63, 128 : PORT B Data = b10000000
    OUT 63, 0 : PORT B Data = b00000000

    The data lines go via a buffer, so can also be driven if the DIR pin (bit 6 of PORT B) is set appropriately prior to use (LOW = OUTPUT):

    10 OUT 127,255 : REM Mode 3
    20 OUT 127,63 : REM b6,7=OUT, b0-5=IN
    30 OUT 95,255 : REM Mode 3
    40 OUT 95,0 : REM b0-7=OUT
    50 OUT 63,128 : REM b7=HIGH
    60 FOR n=0 TO 100: NEXT n
    70 OUT 63,0 : REM b7=LOW
    80 FOR n=0 TO 255
    90 OUT 31,n : D0-7 = n
    95 FOR f=0 TO 10: NEXT f
    100 NEXT n
    110 OUT 31,0 : D0-7 = 0
    120 GOTO 50

    At this point I can see all data lines counting and the ZX to PC pin being toggled as expected.

    Whilst I’m on the topic, I should probably check the input side too.

    10 OUT 127,255 : REM Mode 3
    20 OUT 127,63 : REM b6,7=OUT, b0-5=IN
    30 OUT 95,255 : REM Mode 3
    40 OUT 95,255 : REM b0-7=IN
    50 OUT 63,192 : REM b7=HIGH, b6=HIGH
    60 FOR n=0 TO 10
    70 PRINT IN 31
    80 NEXT n
    90 OUT 63,64 : REM b7=LOW, b6=HIGH
    100 FOR n=0 TO 10
    110 PRINT IN 31
    120 NEXT n
    130 GOTO 50

    With this, I can connect the single OUTPUT pin to any of the data lines and see if the values change as the OUTPUT pin state changes. The pins do indeed change, but the state is often inverted, so when the OUTPUT is connected to D1 (for example) the value toggles between 255 and 253, but this is basically because the other input lines are floating when not connected and in this case are reading HIGH.

    All good so far. Next is to see what happens when I fire up the PC end.

    Testing the PC Board

    Making sure the Spectrum PDS is in INPUT mode, I can try some commands from the PC (I’m still not running the monitor at this stage):

    10 OUT 127,255  : REM Mode 3
    20 OUT 127,63 : REM OOIIIIII
    30 OUT 95,255 : REM Mode 3
    40 OUT 95,255 : REM IIIIIIII
    50 OUT 63,192 : DIR PC->ZX (plus setting b7 so I can see something)

    When I run the F(ill) command in the Monitor (F4):

    F 32768,16,255

    I can see one of the control lines and some of the data lines flash, so that is an encouraging sign that the PC card has a working 8255 IO device and is able to at least try to send data to the target.

    Catching it on video, it is just about possible to make out the binary value put on the data lines reading 10110011 which is 179 in decimal. Looking at the PDS protocol description in the PDS Z80 Manual, we can see that 179 is used a lot at the start of commands, as it is the padding byte.

    Changing the command to 183 (change bank “Z 1”) which doesn’t have a padding byte, I can indeed see a different pattern on the data bus for b10110111 or for the register command (184, “R”) b10111000.

    I can also see the “PC to ZX” control bit changing as the commands are happening, so this gives me confidence that the 8255 on the PC card is at least outputting ok.

    Of course at this point nothing is responding so I continue to get “other end is not receiving” errors.

    Tape Loading via TZXDuino

    At present it is looking like the hardware is probably working, which does seem to point therefore to the target monitor application. Typing the code in was never really a reliable option, so I need to find a way to load it in directly. That is the next task.

    I’ve just acquired a TZXDuino. I must admit I was seriously considering just building one, but then decided I wouldn’t be learning much new by doing so and would rather have a neater unit so I bought one from MyRetroStore (link here). There is even an option of 3D printing a case, which I’ll look into a some point.

    The more modern way to get games loaded is something like the DivMMC but that is a lot more expensive. Another option could be the Dandanator, but that requires reprogramming memory every time something changes. Possibly something for the future. I particularly wanted to go back to that “tape loading” experience initially (but without going on a side-quest to get my old tape player working again – this project has had enough side questions already!) so the TZXDuino is a great option for me.

    It will take TAP and TZX files only though with is a bit of a limitation, but games can be found if you hunt around enough (although many sites seem to have stopped publishing downloadable TAP or TGZ files). It also has the ability to load up AY sound tracks, so that will be something to explore in the future when I get one of my 128Ks running again.

    It requires a micro SD card, a mini-USB power lead and a mono 3.5 to 3.5 jack to plug into the Spectrums EAR socket (the Spectrum sockets are labelled for the thing they need to plug into).

    One downside of the composite video mod is that there is no audio through the monitor/TV anymore. But the MIC socket provides an audio out that can be fed into an external amp or even the audio companion sockets to the composite video again using a mono 3.5mm jack lead.

    This is a sight and experience I haven’t had for a long time. And given (waves hands around), perhaps it was from “a more civilized age” too…

    The Spectrum Monitor

    The biggest issue I have is how to bootstrap everything, but now I can load in TAP files, I “just” need to figure out how to create a TAP file from my pds binaries from Part 5. I spent a bit of time looking at the format of a TAP file and could probably write something to hard-code one out – it is basically a wrapper format for a string of binary chunks of data normally created from the Spectrum SAVE command – but then I found http://zeroteam.sk/bin2tap.html which does exactly that and has a Windows command line tool pre-built.

    I used the following command to create a TAP file for the PDS DL0 binary created in Part 5:

    bin2tap(vs3008).exe -a 32768 -r 32760 pdsdl0.bin

    This sets the load address to 32768 ($8000) which is the origin used in the assembler. It also sets the start address to 32760 ($7FF8) which apparently is where execution will start (I don’t really understand why at this stage). This creates the file pdsdl0.tap by default.

    This can now be transferred to the TZXDuino and loading in using LOAD “” in the usual way. Except that it seems to drop out before fully loading.

    After experimenting with some more options (the source code for the tool has a really good readme) I settled on:

    bin2tap(vs3008).exe -a 32768 -r 32760 -b pdsdl0.bin

    This adds the “-b” option which creates a BASIC bootloader program. I haven’t seen the produced code directly myself, but the readme suggests it will create the following BASIC loader (there is a good explanation of how this works here):

    10 REM loader by bin2tap1.3
    20 BORDER VAL "0": PAPER VAL "0": INK VAL "7"
    30 CLEAR VAL "24575"
    40 POKE VAL "23739", CODE "o"
    50 LOAD "name_of_file" CODE
    60 RANDOMIZE USR VAL "32768"

    This still seems to drop out, so I wondered if the code was a bit small. I opened the pdsdl0.bin file in Notepad++ and used the HEX viewer plugin to pad the code out to address $200 with 0s. Then re-running the convertion this now does indeed seem to load. The screen goes black after showing the pdsdl0 code string and everything seems to hang – but I think this is just the PDS code running.

    When I attempt a fill command now from the PDS, I’m no longer getting “not receiving” errors, so this sounds hopeful. The basic downloader DL0 though doesn’t really let me do very much, so I’m now repeating the above with the DL1 code.

    Here is my full procedure to create a DL1 bootloader running on a real ZX Spectrum:

    • Use https://beta.asm80.com/.
    • Create a new file called pdsdl1.z80 and paste in spec.dl1 from the PDS\Demos area.
    • Add “:” to all the code labels.
    • Expand all shortcut jump instructions to their full versions – e.g. JZ LABEL becomes JP Z,LABEL
    • Comment out the last section which has PDS specific commands to load and run.
    • There is one s1 label that needs to be changed to upper case S1.
    • Build -> Compile.
    • On the resultant HEX file, right click and then select HEX -> BIN.
    • Open the resultant, downloaded, pdsdl1.bin file in a hex editor and pad it with zeros out to address $1FF and save.
    • Run the following command to create the TAP file:
    bin2tap(vs3008).exe -a 32768 -r 32760 -b pdsdl1.bin -o pdsdl1.tap
    • Save the pdsdl1.tap file to the TZXDuino and load onto the ZX Spectrum using LOAD “”. The screen will eventually go blank and the border will stop changing, leaving just Bytes: pdsdl1 at the top.

    Test using the PDS Monitor (F4). A good command to use is the following which writes directly to the Spectrum display so the effect can be seen straight away:

    F 16384,256,45

    I now need to do some work on my GitHub repository and start writing some of this up over there. I’ll also upload the TAP file as a “getting started” file. When I’ve done all that, I’ll revisit this post and add some links to everything.

    I really need to prove that I can now use the PDS to upload and run code, but this is an excellent step forward. It shows the basic systems is working!

    Future Directions

    In 2026 there are a number of ways of getting code developed for and running on a ZX Spectrum: emulators, ROM simulators, tape emulators, even online web tools.

    Given all that, the idea that it is worth updating something like the PDS is a little redundant, but I have been wondering about a few things that might make the system a little more accessible to modern technology.

    The following possible improvements will increasingly take the PDS further and further away from being a PDS though and more towards some of the other more modern techniques, but for completeness, these are the things I’ve been contemplating.

    Design improvements to the system “as is”:

    • Make the target cards taller or put components on back so they can plug in vertically.
    • A full-sized ISA card size with connectors in the same position as the original card.

    Upgrades to avoid the problems sourcing components:

    • Replace 8255 and Z80 PIO with a microcontroller emulation to keep the same register interface.
    • Rewire the PC side IDC sockets to make ribbon cables non-mirrored – i.e. so it can be used with ready-made cables. This is a breaking compatibility change of course.

    Design changes that make it a lot less a PDS:

    • Create a Pico/USB interface directly to the same target board interface. Ideally there would be some kind of software ISA-over-USB type emulation at the PC end which means the PC software doesn’t need updating (not sure this is even possible tbh).
    • Include a small boot ROM on the target board with the monitor program already installed to save having to load it from tape.

    I now need to get back to the RetroCollective where there are people who actually know how to use a PDS to see if we can get them up and running and doing something useful with it!

    Fingers crossed, we’re nearly there (famous last words?).

    Kevin

    #pds #programmersDevelopmentSystem #tzxduino #zxSpectrum
  4. I think I'm making some progress on the PDS once again. I have a PC that seems to recognise the PDS PC ISA card which is great news.

    You don't get screens like this in software these days of course...

    #ProgrammersDevelopmentSystem #RetroComputing

  5. PDS – the Programmers Development System – Part 4

    This series of posts looks at the Programmers Development System (PDS).

    • Part 1 – Introduction, background and some initial reverse engineering.
    • Part 2 – A closer look at the PC ISA Interface card.
    • Part 3 – Remaking the target interfaces.
    • Part 4 – Building the boards.

    This part goes through the build of the three boards I have so far.

    PC Interface

    The design information and BOM can be found in Part 2. Building the card is relatively straight forward, being mostly DIP sockets, capacitors and connectors. Getting hold of an Intel 8255 might be a little tricky, but they do exist. I’ve ended up with a D8255A, rather than the more typical P8255A, which I think might be an “industrial” version? I’m not sure, information about it doesn’t seem very easy to find.

    I’ve got hold of some latching IDE connectors, which are very similar to those used with the original as far as I can see.

    Some notes and observations at this stage:

    • The connectors are perhaps a little close together for the latches, but I think they’ll be ok.
    • The 8255’s capacitor is located under the footprint for the 40-way DIP. It can go on either side of the board.
    • As you can see, I’ve used DIP sockets throughout.

    Amstrad CPC Interface

    The design notes and BOM for the target interfaces can be found in Part 3. There are more components, but building should again be relatively straight forward. Again getting the Z80 PIO is probably the most difficult part of the whole thing.

    I figured that given the technology of the time, I’d need a NMOS part that can go to at least 4MHz. I initially went with using a GS Z8420B, which I thought was the 4MHz part, but I was mistaken. With a GS part the speeds go as follows (ref SGS Z80 Family Databook):

    • Z8420B – 2.5MHz
    • Z8420AB – 4MHz
    • Z8420BB – 6MHz

    So I need the AB or BB version. The Zilog parts will be Z842004 or Z842006 for the NMOS variants. It will be Z84C2006, and so on, for the CMOS versions.

    After a first build using a straight-through, 50-way edge connector socket, I figured there probably wasn’t enough spacing between the edge connector and the Z80 PIO, so I doubt it would fit as a vertical card. Consequently I built a second card using a right-angled edge connector and will have the interface sitting horizontally. Assuming I actually find a CPC to try it with of course (as I don’t have one myself).

    I added a switch for the enable function, but then realised that the switch is obscuring the on/off indication. With hindsight, I suspect pin headers and a jumper would be more useful here as I don’t expect this to be used a lot? I could be wrong.

    ZX Spectrum Interface

    The majority of this is the same as the Amstrad version, and again design details and BOM can be found in Part 3.

    The key difference, naturally (apart from one less chip), is the edge connector itself. The ZX Spectrum requires a keyed 56-way connector, with both ends cut off. Really – it has to have connectors flush with the ends of the connector.

    The typical way to obtain one of these seems to be to buy a standard 56-way connector, remove the pins from the 5th slot and cut off the edges to make them flush with the connectors.

    Then the vacated slot needs filling with something to act as the positioning key. There is a 3D printed design here: https://www.thingiverse.com/thing:6556638 which I tried but didn’t seem to stay in very well. Well, for me, when I plugged it into a Spectrum, on removing the key was left behind. I guess it would need gluing in place.

    Alternatively, I had more luck with the parts I cut off the edge connector – just cutting them down and pushing them into place, being careful not to let them force the edge connector to splay out.

    Once again I started with straight through connectors but that is unlikely to fit on anything other than an original rubber-keyed Spectrum, and even then I’m not convinced it would be secure, so I also rebuilt this one with a right-angled connector too.

    Link Cable

    The pinouts for the cable have to reflect the original and from the information and as noted in Part 1, and from the photos on the CPC wiki, we can see that the two IDC sockets at each end of the cable have opposite pinouts – i.e. pins 1-16 at one end are wired to pins 16-1 at the other.

    The target connection has to be made to the top connector on the PC card for the information I have about the PDS to make sense. Some of the connections on the second connector are reversed, so I don’t know how that works.

    Next Steps

    I can do some basic electrical connectivity tests, but at present: I don’t have an ISA PC; I don’t have an Amstrad CPC; and right at this point in time I don’t have a working machine among my ZX Spectrums.

    The latter I’m working on. I do want to get at least one of them up and running, so that side might be solvable in a basic capacity shortly. I have verified the GND and 5V connections on the PCB with an actual edge connector though.

    The other two might be a bit more problematic.

    But there is some good news. The Retro Collective reached out to Andy Glaister about recreating the designs and received the response: “You absolutely have my permission to reproduce the boards, the designs and the software. I will see if I can dig up stuff to help. It would be good to see all the code again.”

    This means I can open up the GitHub repository once I gain a little confidence the boards have a fighting chance of functioning.

    Kevin

    #amstradCpc #pcb #pds #programmersDevelopmentSystem #zxSpectrum
  6. PDS – the Programmers Development System – Part 3

    This series of posts looks at the Programmers Development System (PDS).

    • Part 1 – Introduction, background and some initial reverse engineering.
    • Part 2 – A closer look at the PC ISA Interface card.
    • Part 3 – Remaking the target interfaces

    ZX Spectrum Interface

    Here are the remade schematic and PCB for the ZX Spectrum target interface.

    This is simply reproducing the schematic found on the CPC wiki, but now in KiCAD. There are a few extras, such as capacitors for the ICs and a pull-up resistor for the unused inverter. The equivalent PCB is shown below.

    The PCB uses the ZX Spectrum Edge connector symbol and footprint from https://github.com/alvaroalea/8bits_kicad_libraries.

    The jumpers in the top centre of the board use a custom footprint that mirrors the original PCB, but they can easily be replaced with standard pin-headers or even just a simple wire link.

    Bill of Materials

    • PDS Remake ZX Spectrum PCB
    • Z8420 Z80 PIO (NMOS is currently assumed given it has to work with a Z80A at 3.5MHz)
    • 74LS245 octal bus transciever
    • 74LS04 hex inverter
    • Resistors: 1K, 4K7, 10K
    • Capacitors: 3x 100nF
    • 6x6x6mm tactile button switch
    • SPDT slider switch 2.54mm pitch OR 2.54mm header pins and jumper
    • 16-way 2×8 shrouded pin header socket
    • ZX Spectrum edge connector (straight)

    I’m using a standard/common 56-pin edge connector socket which will have to be “doctored” to turn it into a ZX Spectrum compatible socket. There are notes on how to do this online, but I’ve not experimented yet.

    Amstrad CPC Interface

    This is very similar to the ZX Spectrum, but the address decoding gives it a different address (see part 1 for details).

    The PCB is using a custom 2×25-way edge connector taken from the ZX Spectrum one used previously. It also uses the same custom jumpers as the ZX Spectrum version.

    Bill of Materials

    • Z8420 Z80 PIO (NMOS is currently assumed given it has to work with a Z80A at 3.5MHz)
    • 74LS245 octal bus transciever
    • 74LS04 hex inverter
    • 74LS032 quad 2-input OR gate
    • Resistors: 1K, 4x 4K7, 10K, 1M
    • Capacitors: 4x 100nF
    • 6x6x6mm tactile button switch
    • SPDT slider switch 2.54mm pitch OR 2.54mm header pins and jumper
    • 16-way 2×8 shrouded pin header socket
    • 50-pin (2×25) edge connector (straight)

    I think the edge connector will be a standard 2×25 way, 2.54mm pitch, edge connector socket that will look something like this:

    But someone who knows about the Amstrad CPC will have to confirm this is the right one!

    Conclusion

    These boards come with a HUGE CAVEAT: they are completely untested and in the case of the Amstrad CPC version, a whole pile of ignorance, as I know effectively nothing about the machines.

    I think I’ve got the edge connector in the correct orientation for both, but that is still to be verified.

    I’ll probably build the spectrum version, but there is little reason for me to build the Amstrad one unless I can find a machine to try it on!

    For now, these are just documenting the current state of play with remaking these boards.

    All files are currently in a private GitHub directory as I’m not sure what the licensing issues are going to be. But if you’d like to collaborate with me on getting them built and tested, drop me an email and we can chat.

    Kevin

    #amstradCpc #pds #programmersDevelopmentSystem #z80Pio #zxSpectrum
  7. PDS – the Programmers Development System – Part 2

    This series of posts looks at the Programmers Development System (PDS).

    • Part 1 – Introduction, background and some initial reverse engineering.
    • Part 2 – A closer look at the PC ISA Interface card.

    Having now got a bit of an idea of how the PDS appears to work in my previous post (PDS – the Programmers Development System) I’m now taking another look at the PC interface and starting to think about the possibility of recreating the system.

    The PC Interface

    Having decided I couldn’t rely on the schematic on the CPC wiki, I’ve taken the printout-versions of the PCB traces and started tracing them through to see what is really going on. It was greatly helped by the PCB view that can be found here: https://lemmings.info/pds-programmers-development-system/

    Of course, I am assuming here that the remade PC card does actually work.

    It turns out the ISA to Intel 8255 part was fine, including the address decoding, but the three 8255 IO ports, through the octal line buffers, to the two PDS links are fundamentally missing some key links.

    Essentially the three 74LS244s are configured for half in A->Y form and half in Y->A. The three IO ports (PORT A, B, C) are also split in half. This means that most of this circuit is working in 4-bit chunks.

    The high level linkages are shown below.

    So here we can see how the A halves of each of the 244s handles OUTPUT and the B halves handle INPUT. We can also see that U5 (sticking with the original schematic numbering for now) handles the control signals, U4 is D4-7 and U3 is D0-3. PORTC drives U5 and thus also handles all control signals.

    We can also see that the data lines are now fully bidirectionally connected so that each can be connected to an OUTPUT or an INPUT depending on the state of the PC2 line. PORTB handles the OUTPUT and PORTA is the input.

    The control signals are still mirrored as determined in the first part, but now we can see that some are OUTPUTs and some are INPUTs. The mappings from PC0-7 through to the link pins is shown below (note I’ve reverted to using the same PDS connector pin numbers as the ZX Spectrum schematic in the diagram above and table below).

    PIODirectionLink 1 PinLink 2 PinPC0OUT313PC1OUT133PC2OUT1111PC3OUT99PC4IN515PC5IN155PC6IN7N/CPC7INN/C7

    There are two swapped pairs of connections, two common, and one unique to each.

    As mentioned previously, the ZX Spectrum interface does not connect to pins 9,11,13,15 so that implies to me that it would not work out of link 2 without remapping in the software for the alternative pinout.

    From working through the ZX Spectrum monitor code in part 1, we can infer the following functions:

    • Pin 3 (OUT): PC to Target CLOCK
    • Pin 5 (IN): Target to PC CLOCK/ACK

    We can also note the following:

    • Pin 11 (OUT): Direction based on PC2. HIGH = PC to Target; LOW = Target to PC

    From this point I can now fully recreate the schematic and start to think about recreating the PCB.

    The PC Hardware

    One slight sticking point in remaking the PCB was getting useful dimensions for an XT era ISA card. Two useful references I found were:

    The actual spec wasn’t massively useful to me. I don’t know if the ends of cards was slightly different in PC XT systems, but it doesn’t seem to match the photos of the PDS PC card. The second link was very well researched and complete however, so I went with that.

    One compromise though was trying to keep the card within a 100x100mm footprint, so I’ve not extended completely to what I believe will be long enough to have an end plate.

    The Schematic

    The updated schematic is shown above. I’ve added a few things I’d expect to see on a modern design – additional 100nF capacitors (one for each IC), and a resistor network to pull up all unused inputs to the 74LS04.

    I originally went with the ZX Spectrum version of the 16-way connector, but then when it came to assigning footprints, to get a right-angled IDC connector meant pin one was now in the wrong place, so I had to revert to the alternative pin numbering as per the original schematic.

    The PCB

    I’ve followed the original layout used on the PC card remake as far as possible, reasoning that the person who did this almost certainly knows a lot more about electronics than I do.

    One thing I wasn’t sure about was a GND fill. I initially created a fill zone, but then decided I’d follow the original lead and use explicit GND connections. If someone advises that a fill will be better then it is pretty trivial to add in.

    Other points to note:

    • A already mentioned I’ve kept this within the 100x100mm footprint. This leaves two unknowns: will it be tall enough to be useful; and will it extend to the edge of a PC case?
    • The two connectors extend beyond the edge of the PCB, so they hopefully will be available at the edge of a PC.
    • The dimensions are such that more of the PCB is off to the right compared to the photos of the remade board I’ve seen.

    This will do for now, but I think it is highly likely there will need to be some physical adjustments for this to be usable.

    Conclusion

    I believe I’ve got an accurate schematic for the board based on the photos available and I now have design for a candidate PCB. The problem is that I don’t know anything about what the software is expecting when it drives the Intel 8255 to work the PDS interface.

    There is also the small matter of needing an ISA bus in a PC…

    I’m hoping to get these boards published somewhere but right now, I’m not clear what the licensing issues would be. These boards are not available anymore, but at some point this was a company’s IPR.

    For now, I’ll keep blogging observations and see what the interest is.

    Next up will be some remake of the target PCBs.

    Kevin

    #intel8255 #ISA #pcXt #pds #programmersDevelopmentSystem
  8. PDS – the Programmers Development System

    I was directed towards this recently – it is a means of developing for 8-bit computers using early PCs or an Atari ST developed by Andy Glaister. Information about it seems quite sparse online, the main references seem to be:

    As far as I can tell the original system was developed in the 1980s and there have been two attempts at recreating it since, as listed above.

    The original reimplementation is from the Spanish site and provides a schematic and Eagle files. The next link was an attempt at using these design files by importing into KiCAD and getting Gerber files built which seemed to be pretty successful.

    I must admit that when I first heard about it, I wondered if it was the same one that Dean Belfield was using with his Tatung Einstein at the 2025 RetroFest, but having read a bit more about it, there are definitely similarities, but I’m not sure its the same. Details of Dean’s setup here:

    It uses a similar principle to the PDS, in that development is performed on the Tatung and then code is transferred across to the target system using a combination of hardware and code running on both sides.

    Basic Operation

    As I understand things, with the PDS there was an interface card for the PC which linked via a 16-wire IDC cable to another interface card for the target computer. There were versions for the ZX Spectrum, Amstrad CPC, C64 and MSX (and possibly others). I’m only really interested in the ZX Spectrum version.

    The PC card is based around the Intel 8255 parallel IO chip sitting on an 8-bit ISA bus. The target interface is usually based around the Z80 PIO (Z84C20) interfacing to the bus of the host system. The PC card supports two target interfaces and both cards include some logic chips to handle addressing and the IO interface.

    Details of the 16-way IO link seem very sparse and will probably have to be worked through and inferred from the source code that has been uncovered.

    From what I can tell, most of the protocol handling is done in the code and the interfaces are essentially IO “passthroughs”. The target has to run some monitor code to react to PDS commands and interface with the memory as required, setting, reading, updating, and so on.

    The CPC wiki seems to be the most complete source of information so far, and includes photos of the remade boards and schematics for the PC card and ZX Spectrum interface.

    The PDS Link

    The PDS link itself is via a 16-way IDC ribbon cable and 2×8 IDC connectors. Unfortunately I’ve not found a pin-out anywhere so far, but from various sources, this is what I know so far.

    GND12DATA 0PC to Target Clock34DATA 1Target to PC Clock/Ack56DATA 2Unknown78DATA 3Not used910DATA 4Not used1112DATA 5Not used1314DATA 6Not used1516DATA 7

    This is using the pin numbering from the ZX Spectrum schematic.

    Unfortunately the schematic labelling of the two PDS sockets for the PC card is backwards compared to the ZX Spectrum card. Pin 16 for the PC version is GND, but that is pin 1 for the ZX Spectrum version. It would also appear that the socket shroud is also reversed. This means that D0 is pin 15 for the PC and pin 2 for the Spectrum.

    The CPC wiki has a photo of the cable used, showing how pins 1-16 are wired to pins 16-1:

    The PC Card

    The schematic for the PC card can be found on the CPC wiki here: https://www.cpcwiki.eu/index.php/PDS_development_system

    Main Components required:

    • Intel 8255 Programmable Peripheral Interface (PPI).
    • 74LS138 – 3 to 8 line decoder (for the addressing).
    • 3x 74LS244 – 8 channel non-inverting buffers.
    • 74LS04 – Hex Inverter (only one inverter is used).

    It probably goes without saying for this era technology, but everything is 5V TTL levels.

    The Intel 8255 PPI

    The Intel 8255 Programmable Peripheral Interface (PPI) device provides access to 3 bidirectional 8-bit IO ports. There is a good summary here.

    From https://en.wikipedia.org/wiki/Intel_8255:

    The 8255 gives a CPU or digital system access to programmable parallel I/O. The 8255 has 24 input/output pins. These are divided into three 8-bit ports (A, B, C). Port A and port B can be used as 8-bit input/output ports. Port C can be used as an 8-bit input/output port or as two 4-bit input/output ports or to produce handshake signals for ports A and B.

    The three ports are further grouped as follows:

    1. Group A consisting of port A and upper part of port C.
    2. Group B consisting of port B and lower part of port C.

    There are two address lines that are used to select one of four registers as follows:

    A1A0Register00Port A01Port B10Port C11Control Register

    The device is selected on the bus when CS is active. It also uses RD and WR to know if it is reading from or writing to the registers.

    Things get a bit complicated pretty quickly, but there is a good summary of the various modes of operation on the Wikipedia page, and of course, a comprehensive datasheet.

    PC PDS Interface

    According to the schematic, this is how the three 8255 IO ports map onto the two PDS connections:

    8255 IO PortPDS Connection74LS244 UsedEnabled byPORT A 0-3Link 2: Data 0-3IC 3B/PC2PORT A 4-7Link 1: Data 0-3IC 4B/PC2PORT B 0-3Link 1: Data 4-7IC 3APC2PORT B 4-7Link 2: Data 4-7IC 4APC2PORT C 0-3Link 1 and 2: ControlIC 5AAlways OnPORT C 4-7Link 1 and 2: ControlIC 5BAlways On

    It is also worth noting that the three 74LS244 buffers are enabled in different ways according to the state of PC2. Also, as the enable is active LOW, the inverter on PC2 generates a “NOT PC2” signal, which itself must be LOW to activate IC3A/IC4A – i.e. it is a “active on NOT NOT PC2” signal. PC2 appears to be used to decide which nibble of the data port should be active. It is also passed through to the link control pins (see below).

    The 8 control lines map onto the two links in an interesting way. Note this is using “PC interface” pin numbering which as previously mentioned is different to the ZX Spectrum side.

    Link 1 PinsLink 2 PinsPC0144PC1414PC266PC388PC4122PC5212PC610N/CPC7N/C10

    So we can see that PC2 and PC3 are common; that PC0/PC1, PC4/PC5 are swapped; and that PC6 is link 1 only; and PC7 is link 2 only. Recall PC2 appears to select which nibble is active.

    When mapped onto the ZX Spectrum card, anything on pins 2,4,6,8 are mapped onto unused pins.

    I must say I’m struggling to make sense of this. This seems to be implying that when data is written to one of the PPI IO PORTs, it is striped across both link 1 and 2. Surely it would make more sense to select one or the other and write all 8 data values in one go?

    I did wonder if this was related to the different IO modes of the 8255, but on re-reading how the modes work, this still doesn’t make much sense to me.

    Unfortunately there doesn’t appear to be any source code for the PC end of things to see what it is doing.

    Ok, so finding a print of the traces for the PCB and overlaying them on a light box gives me the following:

    I’ve highlighted the connection for D0. We can clearly see that on the PCB D0 for both links is connected, and not only that, it is connected to both input side 2A1 and output side 1Y4 on the /same/ IC. This would make sense for a bi-directional bus, but it is quite a long way from the schematic.

    At this point I have to conclude that the schematic is just plain wrong so I’m leaving the PC card for now.

    The ZX Spectrum Card

    The spectrum side is based on the Z80 PIO (Z8420/Z84C20). There is also a schematic and PCB for that on the CPC wki, but after the experiences with the PC card, I’m now treating it with a little skepticism…

    Z80 PIO

    There is a lot of information about using the Z80 PIO around. Key references:

    Key features:

    • Two fully bidirectional 8-bit IO ports.
    • Handshaking (not used for the PDS).
    • Close compatibility with Z80 control signals (most not used for the PDS).
    • Four modes of operation:
      • Byte output
      • Byte input
      • Byte bidirectional (port A only)
      • Bit control
    • Six registers addressable via 4 IO ports in the Z80 IO map.

    The signals involved in address decoding are:

    ZX BusPIOFunctionA5PORTSELSelects PORT A or PORT BA6CONTSELSelects DATA or CONTROLA7/CEEnables the device/M1/M1Z80 control signal/IORQ/IORQIO access in progress/RD/RDRead in progressCLOCKCLKZ80 clock

    The use of A5-A7 means that any IO address (IORQ must be active) with A7 clear (CE is active LOW) will be received by the PIO and then A5 and A6 determine the type of access. This gives an IO address of the following:

    b000x xxxx$xx0x or $xx1xPORT A DATAb001x xxxx$xx2x or $xx3xPORT B DATAb010x xxxx$xx4x or $xx5xPORT A CONTROLb011x xxxx$xx6x or $xx7xPORT B CONTROL

    This equates to some pretty lazy IO address decoding, in that there are many, many equivalent IO addresses that would be decoded by the PIO.

    Note that the CPC wiki lists port addresses in the range 0xFBEC-0xFBEF. These are the addresses used with the Amstrad CPC not the ZX Spectrum.

    Looking at the provided source code for the ZX Spectrum, it appears to be using IO instructions (OUT, IN) using ports 31 ($1F), 63 ($3F), 95 ($5F), and 127 ($7F).

    The schematic shows that /IORQ from the PIO is connected to /IORQ from the Z80 via a SPDT switch which allows selection between Z80 /IORQ and fixed pulled HIGH. This allows the PIO to be inhibited by stopping it responding to /IORQ.

    The interrupt control lines for the PIO are not used. INT and IEO are not connected and IEI is pulled HIGH. The hand-shake signals (ARDY, ASTB, BRDY, BSTB) are not used either.

    ZX Spectrum PDS Interface

    The ZX Spectrum side of the PDS interface has the following:

    • PIO PORT A – goes via the 74LS245 octal buffer to the 8 data lines of the PDS link.
    • PIO PORT B – goes via the 74LS04 for certain control signals from the PDS link, and the direction control for the 74LS245.
      • Bit 0 – Pin 2 of the PDS interface
      • Bit 1-4 – not used
      • Bit 5 – Pin 7 of the PDS interface
      • Bit 6 – 245 direction control
      • Bit 7 – Pin 5 of the PDS interface

    Note that half the PDS control signals are not used for the Spectrum interface. From the previous discussion we can interpret bits 2 and 7 to be the two clock/ack signals. Bit 5’s use is currently unknown. I’ll have to go to the code to see what is going on there.

    ZX Spectrum PDS Monitor

    I’ve not been able to find any source code for the PC side of things, some assembler has been issued for the target machines, which can be assembled into the run-time PDS monitor for that system.

    The PDS Manual does have this to say:

    “The software is designed to be machine independent, so the same protocols can be
    used regardless of the target machines processor or make. All the communication is basically
    the same, there are four major routines, SEND BYTE, GET BYTE and two direction
    swapping routines.”

    There are three versions of the monitor code for the ZX Spectrum:

    • DL0 – the most minimal implementation, providing assembling and downloading only.
    • DL1 – the long downloader, providing support for everything apart from the “analyze” command, which requires interrupts.
    • DL2 – the full interrupt driven downloader.

    The PDS manual contains some information about the ZX Spectrum downloader. Section 6.2 details the three versions of the code and then goes on to describe the available commands.

    To get a feel for how the monitor functions, and some insights into how the hardware works, I’m looking at some extracts of DL0.

    Code initialisation

    START DI
    LD A,255
    OUT (127),A ; $7F=CB=$FF Mode 3
    OUT (63),A ; $3F=DB=$FF PORT B=$FF (B0-7=HIGH)
    LD A,63
    OUT (127),A ; $7F=CB=$3F B6/B7=OUTPUT B0-B5=INPUT
    LD A,255
    OUT (95),A ; $5F=CA=$FF Mode 3
    OUT (95),A ; $5F=CA=$FF A0-A7=INPUT

    CTRL = $FF means all bits of the control register are set. The Z8020 datasheet lists the control register as follows:

    76543210M1M0xx1111

    Where M1/M0 signify which of the four modes is to be used. In this case both PORTs are set to Mode 3, which allows for either IN or OUT on a per bit basis. I am guessing the writing of $FF to DB (PORT B DATA) happens to ensure that when then ports are configured as 2 OUT and 6 IN, the OUT lines are already HIGH, giving a known starting point.

    Note: Setting B6 to HIGH means that the direction control for the 74LS245 will be LOW as it goes through an inverter. This sets the 74LS245 to work in the direction “B to A” which would correspond to when PORT A is set to all INPUTs later in the code.

    GETBYTE

    This is the lowest level function and it retrieves a single byte of data from over the PDS interface. This is used during the main protocol handling to both obtain commands over PDS and then receive data.

    The essential function is as follows:

    • Ensure PORT A setup for INPUT
    • WAIT for a change in the PC->TARGET CLOCK
    • Read the data from PORT A
    • WRITE the TARGET->PC CLOCK/ACK
    • Toggle the two CLOCK signals ready for next time
    • Return
    ;On first entry D=64=b0100 0000
    GETBYTE IN A,(63) ;Read DB - control values
    XOR D ;Toggle FLAGS
    RRCA ;Pushes B0->Carry
    JC GETBYTE ;Wait for B0 to have changed
    IN A,(31) ;Read data from DA
    LD E,A ;And store in E
    LD A,D ;Reload FLAGS
    OUT (63),A ;And write them out ie write B7
    XOR 129 ;Toggle B0+B7 (129, $81) for next time
    LD D,A ;And store back in D
    RET

    So I think the key features for this are:

    • Control FLAGS are stored in the D register. Only B0, B6, B7 are significant. B0 is what we’re looking for on reception; B7 is what we will send in acknowledgement; B6 is the DIRection and is preset to INPUT for this.
    • FLAGS are initialised to 64 i.e. B0=B7=0; B6=1.
    • Every pass through the GETBYTE function toggles B0 and B7 between b0xxxxxx0 and b1xxxxxx1.
    • Read data is stored in the E register.
    • RRCA is used to take the read in control value and shift B0 into the carry flag so it can be checked with JC (JP C).
    • Nothing else in the code works with the D register so it will always reflect the required status of the required PORT B CTRL word flags.

    So this shows how the flags change through several passes of the function:

    D=64               D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)
    CALL GETBYTE D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)

    The PDS Manual describes the protocol as follows:

    “Note that the protocol does not set the control lines directly, but toggles the lines to
    communicate. All the protocols are designed so one computer can never get ahead of the
    other, even if there is a big speed difference. There are no error checking protocols, as the
    interfaces are very reliable, and error checking will slow down processes, and no real action
    can be taken, even if an error was detected.”

    Main Loop

    The main loop essentially reads a byte from the interface and treats it as a control command. It will keep doing this until it finds a command it can process.

    MAINLOOP CALL GETBYTE ;Get 'command byte'
    LD A,E
    CP 180 ;Download code into aabb, len=ccdd
    JZ DLOAD
    CP 183 ;Select bank aa
    JZ SBANK
    CP 181 ;Execute code from aabb?
    JNZ MAINLOOP ;Not recognised - keep looping.

    The comments are the original comments. There is a not a function for command 181, as this relies on “fall through”. It is the next function in the code.

    The commands have values 180-187 as follows:

    • 180: Download code
    • 181: Jump to an address
    • 182: Upload memory
    • 183: Select bank
    • 184: Send all registers to the main computer
    • 185: Get registers from the main computer
    • 186: Trace code buffer
    • 187: Return analyze address

    The various functions and message protocol layer are described in the PDS manual, so I won’t go into them in detail here, but by way of example, here is the description for 181:

    The corresponding code is as follows:

    ;
    ; Function 181, Execute code from aabb
    ;
    CALL GETBYTE
    LD H,E ;Get address of routine
    CALL GETBYTE
    LD L,E
    LD BC,MAINLOOP
    PUSH BC ;Put return address on stack and jump to routine
    JP (HL)

    It is interesting to note that in the PDS manual, some commands appear to start with a padding byte (179). Apparently this is to ensure that all command messages are an even number of bytes long.

    Any variable length commands (e.g. download) include an expected length field.

    To retrieve data from the target, the protocol has the concept of “reverse ports”. After receiving upload command, ports are reversed to allow the sending of the appropriate amount of data before being reversed once again to restore the original direction ready for the next command.

    Uploading is not supported in the simple D0 downloader. That requires the more complete D1 or D2 implementations. I’ve not gone into more detail here.

    Conclusion

    I’m going to leave this here for now. I think I’ve got a reasonable grasp of what is going on and I’d like to see if I can recreate the interfaces used at some point.

    The ZX Spectrum one should be relatively straight forward. To do something with the PC end though is going to require a lot of work as I just don’t believe I can rely on that schematic.

    I have to question though whether it would be worth it though. Given that an Intel 8255 is no longer available I’ll be using reclaimed parts and I also don’t have a PC with ISA anymore. I must admit I am wondering if an alternative PC end would be possible using a microcontroller to implement the PDS protocol and connect to the PC over USB (for example).

    In fact, with something like a Raspberry Pi Pico, it would be quite possible to implement the entire target interface through to emulating the Z80 PIO on the ZX Spectrum board and potentially have a replacement system that is “USB direct to Spectrum”.

    At this point of course, this is not really the PDS anymore and I’m sure there are already many modern alternatives to getting code running on a ZX Spectrum from a modern system, so that too might be a little pointless. And that is before we get into emulation.

    But for its time, this is a really interesting system and it is a shame that information about it seems to have slowly disappeared.

    I am still quite keen to recreate it though, so I might be on the look out for an old PC with ISA…

    Oh, and as always, if you know about the PDS and are able to confirm or refute anything I’ve said here, do let me know in the comments!

    Kevin

    #intel8255 #pds #programmersDevelopmentSystem #z80 #z80Pio #zxSpectrum