Retrochallenge 2010
      Winter Warmup
      Mark Wickens

                             Motorola Educational Computer Board

      So, logically after yesterdays Amiga excursion we come to the MECB. It's a
      single board computer using the MC68000 processor (the same as the Amiga). My
      board is actually a clone of the original one produced by Motorola, but apart
      from more memory and some different peripheral addresses it's almost identical.
      The clone manual specifies the following features:

      a. 8 MHz 68000 16-bit MPU
      b. 16K SRAM (6264 x 2) or 64K SRAM (256 x 2)
      c. 64K EPROM (27256 x 2) or 128K EPROM (27512 x 2)
      d. Two RS-232e serial ports (9600 or 19200 baud)
      e. One timer/counter and one 24-bit parallel port
      f. Self-contained operating firmware that provides monitor and debug function
      g. Individual LEDs indicate: 68000 free-run, DTACK, RAM/EPROM chip enable volt
         only operation
      i. Size 8" x 5"

      The board looks like this:

      MECB Clone

      The board was shipped with a copy of the Tutor firmware as developed for the
      original MECB. This is a sophisticated application that provides you with a
      command line interface for interacting with the board, running programs, dumping
      memory and assembling/disassembling source code. The board connects to a host
      computer via a serial cable.

      The ROMs supplied with the clone board had an assembly error embedded which
      corrupts the TRAP #14 function table. The TRAP #14 table is table of functions
      which can be called using the TRAP assembler instruction. This is similar to an
      MS-DOS int call - specifying different arguments allows interaction with the
      boards 'bios' to do things like output characters to the terminal, read input,
      send data to an attached printer, and perform simple conversions.

      In order to get the board working I had to correct the assembly error by using a
      copy of the MECB tutor code formatted for the excellent windows-based Easy68k
      assembler [1], split the resulting binary file into high and low byte blocks,
      burn two EPROMS and replace the supplied EPROMS. Unbelievably, all that worked!

      Easy68k Screenshot

      Having done a project last time in assembly language I thought I'd see if I
      could find a C compiler to speed any development. I searched high and low
      without much success then when I'd almost given up I found ide68k[2]. This is a
      Windows application developed by Peter J. Fondse which couldn't have been a
      better fit for what I need. The compiler assumes very little about the
      underlying hardware. It uses a very simple assembler cstart file (anyone who's
      delved into C under-the-hood will know it or something similar) which is the
      bootstrap file to setup the  environment for a program before jumping into the
      main() function.

      IDE68K About

      By altering the cstart file to use TRAP #14 functions I was able to define basic
      input and output. For example, I defined the __putch() function as follows:
              __putch:                           ; Basic character output routine
                     link      A6,#0
                     move.l    8(A6),D0
                     movem.l   D7,-(A7)          ; Push D7 onto stack
                     move.b    #248,D7           ; trap #14 function 248 - OUTCH
                     trap      #14
                     movem.l   (A7)+,D7          ; restore D7
                     unlk      A6

      The key lines of interest are highlighted in the middle of the function. The
      first line puts the character supplied to the function into the register D0. The
      second line stores the TRAP #14 function call number, in this case 248 (which is
      defined as 'OUTCH - Output single character to Port 1' and then TRAP #14 is
      called. This enters the Tutor 'bios' routine to output a single character.

      The __getch() function is similarly defined:

              __getch:                           ; Basic character input routine
                     movem.l   D7,-(A7)
                     move.b    #247,D7
                     trap      #14
                     ext.w     D0
                     ext.l     D0
                     movem.l   (A7)+,D7

      In this case the TRAP #14 function call number 247, 'INCHE - Input single
      character from Port 1' is called, the result of the call being the lower byte of
      D0. This is extended to a word then a long. The compiler is defined to return
      the result of a function in D0, so it's all ready to use in the return.

      So I created the familiar Hello World example:

              #include <stdio.h>

              void main()
                  printf("Hello world!\n");

      but this didn't work, and once I'd traced the code through I decided to try a
      simpler test, as the printf() statement above was pulling in lots of functions
      (it is after all a fairly powerful function).

      So, as an example, the slightly simpler code below:

              #include <stdio.h>

              void main()

      results in the following assembly language source code (I've omitted code not
      directly relevant, and once I'd worked out (by reading the help system!) that
      the order of files as defined in the ide68k project defines the order in which
      the code appears in the resulting binary output I managed to get the code to run
      successfully on the MECB.

              ; CSTART.ASM  -  C startup-code for SIM68K

              lomem  equ       $1000            ; Lowest usable address
              himem  equ       $8000            ; Highest memory address + 1
              stklen equ       $1000            ; Default stacksize

                     org       lomem
                     move.l    #-1,__ungetbuf
                     clr.l     __allocp
                     lea       himem,A7
                     jsr       _main
                     bra.s     __exit

                     movem.l   A2,-(A7)
                     lea       _putch,A2
              ; putch('H');
                     pea       72
                     jsr       (A2)
                     addq.w    #4,A7
              ; putch('e');
                     pea       101
                     jsr       (A2)
                     addq.w    #4,A7


              ; putch('\n');
                     pea       10
                     jsr       (A2)
                     addq.w    #4,A7
                     movem.l   (A7)+,A2
              ; }

      To run the code on the MECB it needs to be loaded via the serial cable. Motorola
      defined a standard for this - the S-record standard, which is a way of encoding
      a binary file in plain ASCII. The ide68k program outputs such a file:


      I've added the first line manually - this tells the MECB to load a program from
      port 1 (the one connected to the PC). The S-record format is pretty
      straightforward, the digit after the initial S is the record type. The 'meat' of
      the program is stored in type 1 records. Taking the first line as an example we


      This can be broken down as follows:

      S1 | 13 | 1000 | 23FCFFFFFFFF0000110E42B90000111284

      S1 - record type
      13 - number of two-character (one byte) records to follow
      1000 - address to which data should be stored
      23FC... - the actual data

      The data can be machine code or program data - the MECB doesn't care what it is
      as it's being loaded, only when you try and run it.

      On an operational level, I use Tera Term VT as my terminal onto the MECB because
      it allows you to set a delay when sending data to the MECB (if the delay isn't
      present the MECB experiences buffer overflow):

      Tera Term Serial Options

      Once the S-records have been loaded the Motorola returns to the Tutor prompt.
      The Tutor firmware accepts uppercase-only commands, the following command does a
      memory dump from 1000 to 1030 using the disassembly option:

              TUTOR  1.3 > MD 1000 30;DI
              001000    23FCFFFFFFFF0000110E MOVE.L  #-1,$0000110E
              00100A    42B900001112         CLR.L   $00001112
              001010    4FF900008000         LEA.L   $00008000,A7
              001016    4EB90000109E         JSR.L   $0000109E
              00101C    6010                 BRA.S   $00102E
              00101E    4E560000             LINK    A6,#0
              001022    202E0008             MOVE.L  8(A6),D0
              001026    4E5E                 UNLK    A6
              001028    DFFC0000000A         ADD.L   #10,A7
              00102E    1E3C00E4             MOVE.B  #228,D7

              TUTOR  1.3 >

      I can then run the program by loading the start address into the program counter
      register and either using the G command to GO or the T command to trace:

              TUTOR  1.3 > .PC 1000

              TUTOR  1.3 > G
              PHYSICAL ADDRESS=00001000

              TUTOR  1.3 >

      There is the magic word 'Hello' output to the terminal! Hurrah! Tracing the
      program results in a full register dump after each instruction is executed:

              TUTOR  1.3 > .PC 1000

              TUTOR  1.3 > T
              PHYSICAL ADDRESS=00001000
              PC=0000100A SR=2708=.S7.N... US=FFFFFFFF SS=00007FDC
              D0=000010CE D1=00004D3B D2=00000048 D3=00000000
              D4=00000000 D5=00000030 D6=FFFFFFFF D7=FFFFFFF8
              A0=000211C2 A1=00020350 A2=0000054E A3=0001094D
              A4=0001090E A5=00000540 A6=00007FDC A7=00007FDC
              --------------------00100A    42B900001112         CLR.L   $00001112

              TUTOR  1.3 :> T
              PHYSICAL ADDRESS=0000100A
              PC=00001010 SR=2704=.S7..Z.. US=FFFFFFFF SS=00007FDC
              D0=000010CE D1=00004D3B D2=00000048 D3=00000000
              D4=00000000 D5=00000030 D6=FFFFFFFF D7=FFFFFFF8
              A0=000211C2 A1=00020350 A2=0000054E A3=0001094D
              A4=0001090E A5=00000540 A6=00007FDC A7=00007FDC
              --------------------001010    4FF900008000         LEA.L   $00008000,A7

              TUTOR  1.3 :>

      After I'd fixed the putch() function I recompiled the original Hello World
      program and sure enough although the binary was much larger it worked fine:

              TUTOR  1.3 > .PC 1000

              TUTOR  1.3 > G
              PHYSICAL ADDRESS=00001000
              Hello World!

      I guess that's probably enough for the first installment. I'm not sure what I
      can get done in the time available to me this month, so I'm certainly open to
      suggestions! I was going to make a large multi-digit seven-segment display, but
      that will have to wait for now. Something slightly simpler - I might have a go
      at a VT terminal based game. Any ideas?


      1. Easy 68K Assembler

      2. IDE68k