Retro Computing

Finally, data (Fun with Transputers)

I finally managed to get data into and out of the transputer module (TRAM).

To do this I used an Arduino Micro I had (as it’s 5V) and some breadboard. Now the TRAM pulls 800mA at 5V and the breadboard struggles with this, so I ended up using 4 links for 0V and 4 links for 5V and pushing the power supply to 5.5V to get 5V on the TRAM (not a problem on a PCB).

Arduino micro, an Inmos TRAM and a whole bunch of wires.

I added some LEDs to various signals just so I had some confirmation that it was actually doing something.
I also ran the transputer links at 10Mbps rather than 20 as I was concerned about signal integrity ono a broadboard (let’s be honest, they’re not great at the best of times).

The next step is to try the same with QBASIC in DOS and see if that works, now I know what a correct behaviour is.

Here is the output of the code;

RESETTING C011
RESETTING TRAM
Read memory location power up contents
INPUT STATUS:0
OUTPUT STATUS:1
send: 0x1
send: 0x0
send: 0xF0
send: 0x0
send: 0x80
READ: 0xFF
READ: 0xFF
READ: 0xFF
READ: 0xFF
Write new value
send: 0x0
send: 0x0
send: 0xF0
send: 0x0
send: 0x80
send: 0xAA
send: 0x55
send: 0xAA
send: 0x55
send: 0x1
send: 0x0
send: 0xF0
send: 0x0
send: 0x80
READ: 0xAA
READ: 0x55
READ: 0xAA
READ: 0x55
INPUT STATUS:0
OUTPUT STATUS:1

The transputer is little endian, which is why the address seems backwards, and yes the start of RAM is at 0x80000000, internal transputer ram is 0x80000000 to 0x80000FFF and external starts at 0x80001000 and goes up to whatever you have on the TRAM (1MByte, or 256K words in my case).

  • So the code sends a read command (0x01) followed by the 32bit address.
  • Then reads 4 bytes back
  • Next it sends a write command (0x00) followed by the same 32bit address
  • Then we send 4 bytes of data (0x55AA55AA)
  • Then we send a read command again, address and four reads!

My Arduino code is here;

/*
  C011 test
  */

#define nCS 12      // D12 is nCS
#define RnW 11      // D11 is R/nW
#define RS0 18      // D18 is RS0
#define RS1 19      // D19 is RS1
#define RST 15      // D15 is RESET (active HIGH)

#define DB0 10      // D10 is data bus 0
#define DB1 9       // D9 is data bus 1
#define DB2 8       // D8 is data bus 2
#define DB3 7       // D7 is DB3
#define DB4 6       // D6 is D4
#define DB5 5
#define DB6 4
#define DB7 3

#define TRAM_RST 14        // D14 for TRAM reset (active HIGH)
#define TRAM_ANALYSE 16    // D16 TRAM ANALYSE
#define TRAM_nERROR 17     // D17 for TRAM nERROR

// Send data to the C011
//   sets the pinmode to outputs, toggle CS and WR, set back to input
void SendData(uint8_t data)
{
  pinMode(DB7, OUTPUT);
  pinMode(DB6, OUTPUT);
  pinMode(DB5, OUTPUT);
  pinMode(DB4, OUTPUT);
  pinMode(DB3, OUTPUT);
  pinMode(DB2, OUTPUT);
  pinMode(DB1, OUTPUT);
  pinMode(DB0, OUTPUT);

  digitalWrite(DB7, data & 0x80);
  digitalWrite(DB6, data & 0x40);
  digitalWrite(DB5, data & 0x20);
  digitalWrite(DB4, data & 0x10);
  digitalWrite(DB3, data & 0x08);
  digitalWrite(DB2, data & 0x04);
  digitalWrite(DB1, data & 0x02);
  digitalWrite(DB0, data & 0x01);

  delay(1);
  digitalWrite(RnW, LOW);
  delay(1);
  digitalWrite(nCS, LOW);
  delay(1);
  digitalWrite(RnW, HIGH);
  delay(1);
  digitalWrite(nCS, HIGH);
  delay(1);

  pinMode(DB7, INPUT);
  pinMode(DB6, INPUT);
  pinMode(DB5, INPUT);
  pinMode(DB4, INPUT);
  pinMode(DB3, INPUT);
  pinMode(DB2, INPUT);
  pinMode(DB1, INPUT);
  pinMode(DB0, INPUT);

  delay(10);
}

// Read data from the C011
//   sets the pinmode to input, toggle CS and DR, leave pins as input
//   return read value
uint8_t ReadData(void)
{
  uint8_t temp;
  pinMode(DB7, INPUT);
  pinMode(DB6, INPUT);
  pinMode(DB5, INPUT);
  pinMode(DB4, INPUT);
  pinMode(DB3, INPUT);
  pinMode(DB2, INPUT);
  pinMode(DB1, INPUT);
  pinMode(DB0, INPUT);

  delay(1);
  digitalWrite(RnW, HIGH);
  delay(1);
  digitalWrite(nCS, LOW);
  delay(1);

  temp = digitalRead(DB7);
  temp <<= 1;
  temp += digitalRead(DB6);
  temp <<= 1;
  temp += digitalRead(DB5);
  temp <<= 1;
  temp += digitalRead(DB4);
  temp <<= 1;
  temp += digitalRead(DB3);
  temp <<= 1;
  temp += digitalRead(DB2);
  temp <<= 1;
  temp += digitalRead(DB1);
  temp <<= 1;
  temp += digitalRead(DB0);


  digitalWrite(RnW, HIGH);
  delay(1);
  digitalWrite(nCS, HIGH);
  delay(1);
  
  delay(10);

  return temp;
}


void ShowInputStatus(void)
{
  // read input status
  digitalWrite(RS0,0);
  digitalWrite(RS1,1);
  uint8_t data = ReadData();
  Serial.print("INPUT STATUS:");
  Serial.println(data);
  delay(10);
}

void ShowOutputStatus(void)
{
  // read OUTPUT status
  digitalWrite(RS0,1);
  digitalWrite(RS1,1);
  uint8_t data = ReadData();
  Serial.print("OUTPUT STATUS:");
  Serial.println(data);
  delay(10);
}


void WriteTRAMData(uint8_t data)
{
  // Write Data
  Serial.print("send: 0x"); Serial.println(data,HEX);
  digitalWrite(RS0,1);
  digitalWrite(RS1,0);
  SendData(data);
}

uint8_t ReadTRAMData(void)
{
  // READ data
  digitalWrite(RS0,0);
  digitalWrite(RS1,0);
  uint8_t data = ReadData();
  Serial.print("READ: 0x"); Serial.println(data, HEX);
}



//*************************************************************************
// the setup function runs once when you press reset or power the board
void setup() 
{
  Serial.begin(115200);
  delay(500);

  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  while(!Serial.available())      // wait for a character from serial, as the monitor doesn't load quick after programming and I Want to follow the progress
  {
    Serial.print("Waiting ");
    delay(300);
  };
  Serial.println("");

  // data control setup
  pinMode(nCS, OUTPUT);
  digitalWrite(nCS, HIGH);
  pinMode(RnW, OUTPUT);
  digitalWrite(RnW, LOW);
  pinMode(RST, OUTPUT);
  digitalWrite(RST, LOW);

  // Databus setup
  pinMode(DB7, INPUT);
  pinMode(DB6, INPUT);
  pinMode(DB5, INPUT);
  pinMode(DB4, INPUT);
  pinMode(DB3, INPUT);
  pinMode(DB2, INPUT);
  pinMode(DB1, INPUT);
  pinMode(DB0, INPUT);

  // RS setup
  pinMode(RS0, OUTPUT);
  pinMode(RS1, OUTPUT);
  digitalWrite(RS0, LOW);
  digitalWrite(RS1, LOW);

  // TRAM pins
  pinMode(TRAM_ANALYSE, OUTPUT);
  pinMode(TRAM_RST, OUTPUT);
  pinMode(TRAM_nERROR, INPUT);

  // init things
  delay(100);
  Serial.println("RESETTING C011");
  digitalWrite(RST, HIGH);
  delay(10);
  digitalWrite(RST, LOW);
  delay(100);
  
  Serial.println("RESETTING TRAM");
  digitalWrite(TRAM_RST, HIGH);
  delay(500);
  digitalWrite(TRAM_ANALYSE, HIGH);
  delay(500);
  digitalWrite(TRAM_RST, LOW);
  delay(500);
  digitalWrite(TRAM_ANALYSE, LOW);
  delay(500);

  // Write input status   (disable interrupts)
  digitalWrite(RS0,0);
  digitalWrite(RS1,1);
  SendData(0x00);
  delay(10);

  // Write OUTPUT status   (disable interrupts)
  digitalWrite(RS0,1);
  digitalWrite(RS1,1);
  SendData(0x00);
  delay(10);


  delay(500);
}

// the loop function runs over and over again forever
void loop() 
{
  digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)

  Serial.println("Read memory location power up contents");

// read from address 0x8000F000  (Transputer external RAM)
  ShowInputStatus();
  ShowOutputStatus();   
  WriteTRAMData(0x01);
  WriteTRAMData(0x00);
  WriteTRAMData(0xF0);
  WriteTRAMData(0x00);
  WriteTRAMData(0x80);
  
  delay(10);

  ReadTRAMData();
  ReadTRAMData();
  ReadTRAMData();
  ReadTRAMData();

  delay(10);

  Serial.println("Write new value");

// write a value to 0x80000F00
  WriteTRAMData(0x00);
  WriteTRAMData(0x00);
  WriteTRAMData(0xF0);
  WriteTRAMData(0x00);
  WriteTRAMData(0x80);
  WriteTRAMData(0xAA);
  WriteTRAMData(0x55);
  WriteTRAMData(0xAA);
  WriteTRAMData(0x55);

  delay(10);

// read from address 0x8000F000  (Transputer external RAM)
  WriteTRAMData(0x01);
  WriteTRAMData(0x00);
  WriteTRAMData(0xF0);
  WriteTRAMData(0x00);
  WriteTRAMData(0x80);
  delay(10);

  ReadTRAMData();
  ReadTRAMData();
  ReadTRAMData();
  ReadTRAMData();

  ShowInputStatus();
  ShowOutputStatus();   

  Serial.println("done");

  digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW


  while(1)    // just a little loop so I know it's still alive.
  {
    Serial.print(".");
    digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
    delay(500);
    Serial.print("o");
    digitalWrite(LED_BUILTIN, HIGH);   // turn the LED off by making the voltage LOW
    delay(500);
  };

}

electronics and synth nerd.