Skip to the content
PCBKitNew board
4 layers71.1 × 68.6 mmAPEDSK AU, the printed circuit board in 3D

Arduino DSKx / 32K / FTP / NTP shield for the TI99/4a

Size
71.1 × 68.6 mm
Copper layers
4
Thickness
1.6 mm
Parts
26
Nets
77
Pads
248
Tracks, vias
884, 0
Pours
1
Routed
Yes
KiCad
KiCad 7 (file 20221018)
Created
25 Jul 2019
Updated
10 Jun 2025

Overview

APEDSK AU is an open-source printed circuit board by jambuur, from the jambuur/APEDSK99 repository on GitHub. It is a 4-layer board of 71.1 × 68.6 mm with 26 parts on 77 nets, routed with 884 tracks and 0 vias.

It is built around the 74LS245SC and 74HC595. Its parts include 7 capacitors, 7 ICs, 5 resistors, 5 connectors and 2 diodes. It belongs with the FPGA and CPLD boards of this library.

Main components

2

README

README.md

APEDSK99 (Arduino Peripheral Expansion for the TI-99/4a)

July 2025 Newsflash: WiFi suggestion

I did get a number of questions regarding a WiFi option using the Arduino WiFi shield. Initial investigation suggested a lack of memory so to make it fit I had to reduce other functionality. This I didn't want to do. However, there is a simple solution. There are devices that accept a wired Ethernet connection and bridges this to a WiFi network of your choice. It works a treat. Check out IOGEAR etc.

July 2024 Newsflash: IDEDSR adaption

I am currently trying to adapt Fred Kaal's version of the DSR for Thierry Nouspikel's IDE card to APEDSK99. Not sure of a successful outcome yet as there are major design and hardware differences to take into account; the first experiments are encouraging though. If it works it will be a valuable addition to APEDSK99 as you would be able to mount and use existing MAME HD images on your TI. It will also save me from the big headache of trying to define APEDSK99 as a new device in MDOS (see below).

January 2024 Newsflash: Case 3D design files available

With the help of an Industrial Design student I have finalised a case for APEDSK99, (loosely) following the style of the Speech Synthesizer. On a side note, I have been able to lay my hands on a Myarc Geneve card. As I don't have a PE Box I am building a standalone system including a modified APEDSK99 for booting and floppy / HD emulation.

February 2023 Newsflash: Major Update in progress

Check the TI Italian User Club for a review of the new version: https://www.ti99iuc.it/web/index.php?pagina=articoli&artid=219#.Y-gqDi9BxaS

Currently working on updating this Github page, Youtube channel etc. Biggest takeaway is that APEDSK99 is now pretty much plug and play. I am thinking of either supplying pre-assembled APEDSK99 shields, leaving it to you to source a cheap Arduino UNO + Ethernet Shield combo from Ebay, AliExpress etc. Alternatively, I could supply complete kits; I have also been approached by a web shop interested in the same. Stay tuned :-)

Arduino-based DSKx emulator / 32K / FTP / NTP shield for the TI99/4a

APEDSK99 is an Arduino shield that emulates 3 DS/SD/80T floppy drives for the TI99/4a home computer. Combined with a Arduino UNO and an Ethernet / SD shield it allows you to load, save and use disk floppy images (DOAD) on a SD card or FTP server. It includes the necessary 32K RAM expansion and adds NTP date and time to BASIC. The APEDSK99 shield plugs directly into the side port and is powered separately from a USB cable.

KiCAD 3D view

Like the TI, APEDSK99 is based on good old through-hole technology. The TI<->shield interface is the familiar design, with 74HCT541 buffers for address lines and a bi-directional 74LS245 buffer for the databus. A 64Kx8 RAM stores the DSR code and provides the 32K RAM expansion. CRU is emulated through memory mapped addresses, simplifying shield design. A user-selectable binary DSR file is loaded into RAM at >4000 by the Arduino at powerup / reset.

The Arduino UNO controls the TI interface, has R/W access to RAM, can halt the TI and tries to act as a FD1771. As GPIO pins are in rather short supply, Arduino RAM addressing is serial-to-parallel through 74HC595 shift registers.

A status LED indicates APEDSK99 access as well as showing possible error codes.

The DSR is still very much the original TI Disk Controller ROM, but adapted to interface with a reliable SD card instead of wonky floppies. DSR code optimisation made enough RAM available to include some useful BASIC CALL routines. I think it's rather nice that most of the orginal programmers' blood, sweat and tears lives on.

How does it work?

When the TI issues disk controller commands by writing to the various FD1771 registers, the Arduino receives an interrupt on one of its GPO pins. This interrupt is generated by a GAL which monitors A0, A13, A14, A15, WE* and MEMEN* sideport signals. On receiving an interrupt, the Arduino then:

  1. halts the TI by making READY low; this simultaneously enables the shift registers
  2. disables the sideport interface buffers
  3. enables the Arduino RAM control bus
  4. executes the command including updating the relevant FD1771 and CRU "registers"
  5. executes the opposite of steps 3, 2 and 1

The GAL also does the memory decoding for the 32K memory expansion.

DOAD's

DOAD's are stored in root folders on the SD card or on a FTP server. Default APEDSK99 files include a DISKS folder with a bunch of useful images to get you started. DOAD filenames must follow the DOS 8.3 format and have a ".DSK" extension. At powerup or reset the Arduino looks for optional _APEDSK1.DSK / _APEDSK2.DSK / _APEDSK3.DSK_ files and maps them accordingly so you can have your favourite apps ready to go. The DSR includes all necessary CALL's for DOAD and DSK management.

Once a DOAD is mapped to a particular DSK, it behaves very much like a normal (but rather speedy) floppy.

Regarding FTP, on my setup (a Linux server with VSFTP within the same LAN segment) I get about ~22Kbyte upload / download speed. In practice it means 6-7 seconds between the TI-BASIC FTP CALL for a SS/SD image and back to the friendly flashing cursor.

BASIC support

The DSR includes some 15 additional BASIC CALL's but there is really only one to remember, CALL AHLP:

CALL ARST resets APEDSK99 including reloading the current DSR. It is a handy way to get your DOAD mappings to their default state. It is functionally the same as pressing the Arduino reset button and sort of the same but not really as power cycling.

CALL LDIR list the DOAD's in the current selected directory on the SD card, displaying the DOAD name, TI DISK name and DSK characteristics:

CALL SMAP shows the current DSKx -> DOAD mappings, extended info and the available directories on the SD Card:

CALL TIME gets the current date and time from an NTP server. If you define a BASIC variable NTP$ of exactly 16 characters before the CALL, the NTP data will be stored for use in your programs:

NTP is also used in the background to update a DSK's timestamp when creating/changing files or formatting.

CALL ACHR redefines the "lower capital" character definitions to true lower case. It's a bit of a bummer that BASIC constantly reloads the original definitions in command mode so you can really only enjoy lower case characters while running a BASIC program. What has this feature to do with DSK's I hear you ask? Well, nothing really but it gives you an example of developing useful CALL's with APEDSK99:

CALL LDSK list the files on a DSK; I always thought that was a really nice feature of the C64 so here it is. LDSK uses the last DSK# that was accessed if you ommit the [1-3] parameter:

CALL PDSK and CALL UDSK apply or remove a virtual "sticker tab" (remember those?). With the "tab" applied, APEDSK99 can't write to the DSK. Under the hood the Protected flag at 0x10 in the Volume Information Block is set/reset:

CALL MDSK maps DSK[1-3] to a DOAD. The DOAD file name is the DOS max 8 character part without the extension (see CALL LDIR above).

CALL NDSK renames a mapped DOAD. The TI DISK name is set to match the DOAD 8 character name. With renaming the DSK, the current mapping is deleted as the DOAD has now a new name. This command is handy for quickly creating a freshly formatted DSK. Just FGET a clean image (I use either FLOPPYSS.DSK or FLOPPYDS.DSK) and rename accordingly.

CALL CDIR changes the working directory. The SD Card image contains a /DISKS folder with lots of goodies and a /BLANK directory with the abovementioned clean images. One restriction is that you have to create additional directories on an external system as there is no CALL for that.

CALL RDSK removes a DOAD from the SD card. In line with BOFH standards no confirmation is required but the DSK in question needs to be UNprotected.

CALL FGET and CALL FPUT load or save a DOAD from your FTP server of choice. Similar to RDSK, to overwrite an existing DSK on the SD card it needs to be UNprotected. To prevent overwriting images on your FTP server simply make them read-only.

CALL ADSR loads a DSR file from the SD card and resets APEDSK99. If the DSR file doens't exist or is invalid the default file APEDSK99.DSR will be loaded instead. The current DSR filename is stored in EEPROM so will survive resets and powerdowns. After loading a DSR, a soft-reset may be required to execute any DSR powerup routines.

NB: LDIR and LDSK can generate multiple screens of info. A ">" will show up at the bottom right for you to press either <SPACE> for the next screen or <ENTER> to go back to the BASIC prompt.

APEDSK99 configuration

Configuring APEDSK99 is easy. All it takes is to run a BASIC program called ACFG from DSK1:

The program has to run from TI BASIC (why? see What about Extended BASIC below):

The programs shows the current configuration before asking for updates.

The new configuration is then applied to APEDSK99. If NTP is successfully configured the program shows the local date and time. The configuration is saved in EEPROM and used with every reset / powerup:

What about Extended BASIC

Yes, good question as I take it EXBAS is used over TI BASIC by the majority TI enthusiasts. Obviously I wanted to support vanilla console users (like the ones re-entering the hobby after xx years such as myself). But that doesn't explain why EXBAS couldn't be used to run the configuration program. Well, the problem is that EXBAS doesn't support external CALL's in programs, only from the command line. This would mean you have to type in a set of commands instead of a more or less automated setup. Not a good idea I thought.

UPDATE 16/1/2024: I now have provided EXBAS support through CALL LINK as an alternative to execute DSR CALL code, for example CALL LINK("MDSK",1,"ACFG"). Adapting the configuration program to EXBAS is left as an exercise to the reader.

Ignition sequence

The DSR containes a powerup routine (the original TI DISK Controller routine if fact) that needs to be executed before you can properly use DSK's. So switch on the TI first, apply power to APEDSK99, wait a second for APEDSK99 to load the DSR (short flash from the LED) and then soft-reset the TI with <FCTN>->QUIT> to execute the DSR powerup routine.

Error codes

The LED can flash in the following intricate error patterns:

  1. flash : SPI / SD Card fault/not ready
  2. flash-flash : can't read DSR binary image (/xxxxxxxx.DSR)
  3. flash-flash-flash: no valid DSR header (>AA) at DSR RAM >4000

Uploading Sketches

You should make sure APEDSK99 is idle or even better, switch off the TI before uploading the APEDSK99 sketch from the Arduino IDE. If you don't, there is a slight chance the Arduino bootloader gets corrupted and you'll need a second Arduino to restore it. Yes I have been there.

Alternatively you could connect Analog 1 to +5V with a jumper wire before uploading; this disables the APEDSK99 sideport buffer IC's so you can leave the TI powered on. In fact, if you intend to put APEDSK99 in some sort of case, plan a switch for this. It's not only handy for uploading sketches but also for temporarily circumventing TI Extended BASIC's LOAD feature.

Updating the DSR

I compile the DSR .a99 file with xtd99 TI99 cross development tools and then use this hex editor for padding the binary file with zero's to the full 8KB. After that it's just a matter of saving the binary file as APEDSK99.DSR in the root of the SD.

Feeling Brave - DIY from scratch

If you decide to build one yourself, I have compiled a handy document to get you started. Just ping me with any questions through Github, YouTube or AtariAge (JJB).

A suitable case

I have teamed up with an Industrial Design student from a local university and have come up with the design below. It (very) roughly follows the design of the Speech Synthesizer and has a handy hatch to access the SD card and reset button:

I know

Writing software is a hobby, not my profession. No doubt some gurus would achieve the same functionality with half the code. But I dare to say that at least the basic DSR I/O routines in the sketch are reasonably efficient, useful and fast. Anyway I am content with dusting off that stack of virtual floppies, have a beer and admire my work.

Feel free to improve and share!

Bugs

If a particular program or module behaves nicely by accessing disks solely through the regular DSR routines there shouldn't be any new ones (are there any existing disk controller bugs?) In other words, any funky index hole math or weird copy protection schemes will likely fail.

Not so much a bug but an annoyance is that the FAT format (as used on the SD Card) doesn't support any sorting whatsover; so if you have been actively FGET'ing images from your FTP server you might find the SDIR list slightly out of alphabetical order. There are a number of "FAT Sorter" programs for different OS's that can restore the order for you (the one I use is included in the repository).

And yes, if I had thought it through a bit more I would have designed APEDSK99 with the USB and Ethernet connectors facing backwards. Anyway what's done is done and unless there is a push for a major revision (unlikely) you'll (we) have to live with this minor inconvenience.

Future

After (of course) I came up with the name APEDSK99 I realised that DSK emulation is just a first application. The APEDSK99 shield is actually a generic interrupt-driven DSR interface to a substantial catalogue of available Arduino shields. Also, the Arduino has full access to the 32K RAM expansion and since it uses a 64Kx8 RAM chip there is an additional 24K available for additional DSR, program code or device data sharing.

Acknowledgements

This project owes a lot to Thierry Nouspikel's marvelous TI Tech Pages website which has a wealth of information on the TI Disk Controller, including a commented disassembly of its DSR ROM.

Another great source of information has been Monty Schmidt's excellent book Technical Drive. Monty went on to do great things, check out SoundForge. Monty has now made his book publically availabe: https://github.com/wuntusk/technical-drive

The Arduino's serial-to-parallel RAM addressing scheme is neither new or mine but I have gratefully used part of this excellent project by Mario Keller.

Last but not least I virtually stumbled across my old friend Frederik "Fred" Kaal who I hadn't seen for 30 years after moving to the other side of the globe. Long live the Web and places such as AtariAge. Fred was a TI wizzard back then and still very much is. His expert input has been of great help.

Parts

26
QtyValueFootprintReferences
7100NCapacitor_THT:C_Disc_D3.0mm_W1.6mm_P2.50mmC1, C2, C3, C4, C5, C6, C7
35.1KResistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_VerticalR1, R2, R3
274HC595Package_DIP:DIP-16_W7.62mmU5, U6
274LS541Package_DIP:DIP-20_W7.62mmU2, U3
11KResistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_VerticalR5
11N4148Diode_THT:D_DO-35_SOD27_P7.62mm_HorizontalD2
1240-44-44PinsConnector_PinHeader_2.54mm:PinHeader_2x22_P2.54mm_VerticalJ1
1330RResistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_VerticalR4
174LS245Package_DIP:DIP-20_W7.62mmU1
1AnalogSocket_Arduino_Uno:Socket_Strip_Arduino_1x06P2
1DigitalSocket_Arduino_Uno:Socket_Strip_Arduino_1x08P4
1DigitalSocket_Arduino_Uno:Socket_Strip_Arduino_1x10P3
1GAL16V8Package_DIP:DIP-20_W7.62mmU4
1IS61C512-20MPackage_DIP:DIP-32_W7.62mmU7
1PowerSocket_Arduino_Uno:Socket_Strip_Arduino_1x08P1
1~CELED_THT:LED_D1.8mm_W3.3mm_H2.4mmD1

Questions

How big is the APEDSK AU PCB?

It measures 71.1 × 68.6 mm and has 4 copper layers, 1.6 mm thick.

What parts does the APEDSK AU use?

26 parts, built around the 74LS245SC and 74HC595. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the APEDSK AU KiCad files?

From the jambuur/APEDSK99 repository on GitHub, at the commit this page was made from: the board is KiCAD/APEDSK-AU.kicad_pcb and its schematic KiCAD/APEDSK-AU.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the APEDSK AU design in my own project?

Its repository states no licence, so its author keeps all rights: ask jambuur before reusing the design.

Similar boards

  • 2 layers150.6 × 171.7 mmKraft80V2, the printed circuit board in 3D

    Kraft80V2

    ARMCoderBR/z80computer-release

    A Z80-based computer for nostalgic enthusiasts. With video output!

    175 parts5GPL-2.0
  • 2 layers100 × 115 mmZ80ESP, the printed circuit board in 3D

    Z80ESP

    lynchaj/nhyodyne

    Modular Backplane Computer

    63 parts31
  • 2 layers99.1 × 83.8 mmRC1 8K ExRAM, the printed circuit board in 3D

    RC1 8K ExRAM

    tebl/RC-ONE

    A recreation of the MOS KIM-1 microcomputer, the start of the Commodore-line of computers. Complete with hex keypad, six digit displays and a lot of 8-bit fun!

    36 parts25
  • 2 layers235 × 160 mmInput output.DualESP32, the printed circuit board in 3D

    Input output.DualESP32

    lynchaj/duodyne

    Duodyne is a hobbyist retrocomputer system designed to run ROMWBW. It is comprised of modules on a system bus

    74 parts15
  • 2 layers229.9 × 86.4 mm93c76 revision two, the printed circuit board in 3D

    93c76 revision two

    ethanjamesauto/modular_8bit_computer

    168 parts2
  • 2 layers231.1 × 106.7 mmSnark barker, the printed circuit board in 3D

    Snark barker

    schlae/snark-barker

    A 100% compatible replica of the famed SB 1.0 sound card

    199 parts687
  • 2 layers365.8 × 254 mmRaemixx500, the printed circuit board in 3D

    Raemixx500

    SukkoPera/Raemixx500

    Open Hardware Remake of the Commodore Amiga 500+ Mainboard

    372 parts316
  • 2 layers125 × 98 mm3-in-1, the printed circuit board in 3D

    3-in-1

    mudmin/AnotherMaker

    This is where I will store code snippets for AnotherMaker Videos

    44 parts258