First step with Turbo C 2.0 on Atari ST

Yes I know, you may think I'm crazy: what the heck programming on the Atari ST? Why Turbo C?

Context

Atari STe and Soundpool SO4

I use my Atari STe since the 90s, almost exclusively to make music with Cubase. The Atari STe has 2 MIDI sockets (IN and OUT), which allows to drive 16 MIDI channels. But some of synths use all 16 channels (Roland SC55, Kurzweil 1000PX). To drive more synths, I purchased a MIDI extension, the Soundpool MO4, providing 4 extra MIDI outs, for a total of 80 channels. The MO4 is connected on the parallel port (printer port), and comes with a driver for Cubase. This configuration worked for years.

The problem

Quite recently, my wife and I have decided to move closer to downtown Montreal. I packed all my studio, including the Atari, moved, and reinstalled my studio; this took, of course, almost a year before I unpacked and reinstalled my Atari. When I tried to use the Soundpool MO4, I had nothing on any MIDI out. However, the MO4 is still recognized by Cubase.

How the MO4 works?

In the Soundpool MO4, all the logic is driven by one component, a ispLSI 1016 from Lattice; this is a CPLD (Complex Programmable Logic Device) with a flash RAM to hold the "program". The datasheet says the data retention of the flash is 20 years; however, the MO4 PCB was design in 1995, 24 years ago. The program might be flashed latter, but we're near the limit. I want to test if this is the case.

On the Atari, the parallel port is based on Centronics: a 8-bits data bus (OUT), the STROBE signal (OUT) and the BUSY signal (IN). All signals are managed by the CPLD.

Testings

When I monitor the signals on the CPLD, nothing moves; the clock is ticking, but the signals from the Atari are steady. So the problem can be:

  1. The clock on the MO4: tested OK
  2. The CLPD on the MO4
  3. The cable between the MO4 and the Atari: tested OK
  4. The parallel port on the Atari
  5. The driver in Cubase: I reinstalled it from a copy I had, no change

So, I now need to test the parallel port on the Atari. To do so, I built a very simple protoboard with 9 leds and resistors (8 data bits + strobe), connected on the parallel port. I now need to drive programmatically the parallel port. Here enters...

Turbo C

I did a lot of C programming, but mainly on UNIX and Linux systems. Very few on the Atari, and this was during my years at university in the late 80s. However, this is the language I know best, and easiest to use among the languages I have on my Atari. The version I have is Turbo C 2.0; it was distributed by Borland, originally named Pure C. It comes with a small IDE: editor, compiler, linker and debugger.

Hello world

I did a hello world:

#include <stdio.h>
#include <errno.h>

void main()
{
  printf("Hello world!\n");
}
Turbo C requires a project (.PRJ)
* = HELLO.O TCSTDLIB.LIB, TCEXTLIB.LIB
; Notes:
; TCSTDLIB.LIB = Turbo C Standard Library
; TCEXTLIB.LIB = Turbo C Extended Library
Compiled without problem. I ran it and ... bang! Two bombs, which means "Bus error" in the Atari world. What? A bus error for that? Oh yes: I compiled it as a .PRG, which means using the GUI (GEM, see below), and I obviously did not. I should have compiled as .TOS (text mode) or .TTL (text mode with parameters on the command line).

TOS

The Atari ST has its OS in Read-Only memory (ROM). It is called The Operating System (TOS) and contains several parts:

  • BIOS (Basic Input/Output System) the lowest level
  • XBIOS (Extended BIOS)
  • GEMDOS the highest level
  • GEM, the Graphic Environment Manager developed by Digital Research back in 1984, which contains:
    • VDI (Virtual Device Interface) which provides the graphical objects
    • AES (Application Environment Services) which manages the windows and signals

The Atari ST uses a specific instruction of the Motorola 68000 CPU to "jump" to the libraries: the traps. There are 16 traps (0 to 15), each corresponding to a absolute address (0x080 to 0x0bc). The CPU load the content of that address (32 bits) into the Program Counter (PC) to jump. The overall principle is very similar to call the UNIX kernel: the caller push the parameters onto the stack, push the opcode of the function you want to call, then call the trap instruction. Once back from the call, pop the results from the stack.

  • BIOS: trap 13, address 0x0b4
  • XBIOS: trap 14, address 0x0b8
  • GEMDOS: trap 1, address 0x084
  • VDI and AES: trap 2, address 0x088

More fun to come...

Comments

Popular Posts