Author: Andre Adrian
Date: 2025-01-16
My XMAS present to myself was a 68k-MBC
single board computer. Next to the solder yourself kit you need
only the following:
I got the kit from SAS ELABORATEC. Just google "ebay elaboratec
68K-MBC". Note: The kit needs the files from the hackaday.io
page.
The 68k-MBC is the brain child of "Just For Fun".
Picture: My 68k-MBC. Left module is microSD, right module is USB to UART. This is full system with 1MByte RAM and CP/M 68K from microSD card without GPIO chip.
The 68k-MBC uses a micro SD card module and a micro SD card as
replacement for floppy drives, floppy disks and hard drives. The hackaday.io
page has file "SD-S310121-R231021-v3.zip". Unpack this zip file
into the micro SD card. Put the micro SD card into the SD card
module and the SD card module into the 68k-MBC. Installation
complete.
The 68k-MBC kit has no user manual. The Z80-MBC2
page has an user manual "Z80-MBC2 User Manual -
D081023-R280424.pdf". This is helpful for the 68k-MBC, too.
The 68k-MBC has two serial ports with RS232 +/-12V level signals
at the J4 AUX connector. The first serial port is available with
TTL level for an USB to UART module on the J2 SER1 connector. The
USB to UART module is provided with the kit. The host computer
(e.g. a PC running MS-Windows) is connected to the first serial
port through the USB to UART module in most cases.
As terminal emulator program I use TeraTerm.
Note: This TeraTerm program is not the original TeraTerm from the
1990s. Let's configure TeraTerm for 68k-MBC with USB UART module.
The menu Setup|Serial Port... pop-up is:
The menu Setup|Terminal... pop-up is:
Save the TeraTerm setup with menu Setup|Save setup...
After we connect the 68k-MBC board through the USB to UART module
with the host computer running TeraTerm we see the 68k-MBC boot
message:
68k-MBC - A091020-R140221 IOS - I/O Subsystem - S310121-R231021 IOS: Full HW configuration detected IOS: CP/M Autoexec is OFF IOS: Current Disk Set 0 (CP/M-68K v1.3) IOS: Loading boot program (CPM68.BIN)... done IOS: 68008 CPU is running from now 68k-MBC CP/M-68K BIOS - S150321-R311021 - 1024KB CP/M-68K Version 1.3 Copyright (c) 1985 Digital Research Inc. |
If you press RESET key together with USER key on the 68k-MBC and
then release only RESET key, you get the boot menu:
68k-MBC - A091020-R140221 IOS - I/O Subsystem - S310121-R231021 IOS: Full HW configuration detected IOS: CP/M Autoexec is OFF IOS: Select boot mode or system parameters: 0: No change (4) 1: sLoad 2: Enhanced 68K Basic 3: Autoboot 4: Load OS from Disk Set 0 (CP/M-68K v1.3) 5: Change Disk Set 0 (CP/M-68K v1.3) 6: Change serial ports speed 7: Change CP/M Autoexec (->ON) Enter your choice > |
We need option 4, load OS from disk set 0. Leave boot menu with
choice 0.
The CP/M 68k files are on drive A: to E:.
The contents of drive A:, C: and D: are (your entry is in bold
face):
A>dir A: DDT68000 68K : README TXT : SETPRINT 68K : SPP 68K : AUTOEXEC TXT A: AUTOEXEC SUB : CP68 68K : DDT 68K : USERLED 68K : DUMP 68K A: ED 68K : FIND 68K : LO68 68K : MORE 68K : NM68 68K A: SENDC68 68K : SIZE68 68K : STAT 68K : RELOC 68K : PIP 68K A: XM68 68K A>c: C>dir C: AR68 68K : AS68 68K : C068 68K : C168 68K : LINK68 68K C: CP68 68K : LO68 68K : NM68 68K : SENDC68 68K : SIZE68 68K C: AS68INIT : C SUB : CLINK SUB : CE SUB : MORE C C: SETJMP H : MORE O : README TXT : XFLDBIOS H : C OUT C: CLIB : AS68SYMB DAT : CLINKF SUB : CLINKE SUB : S O C: BDOS S : CPMLIB : ASSERT H : BIOSTYPS H : CTYPE H C: ERRNO H : LOADBIOS H : NORMBIOS H : OPTION H : OSATTR H C: OSIF H : OSIFERR H : PORTAB H : SIGNAL H : STDIO H C: XFNMBIOS H : XLOADBIO H : XNORMBIO H : BDOS O : MORE 68K C: LIBF A : LIBE A C>d: D>dir D: ANNOUNCE : CGK SUB : COPYING : GCMDLINE C : GKERMIT C D: GKERMIT DIF : GKERMIT H : GKERMIT NR : GKERMIT REL : GPROTO C D: GPROTO W : GUNIXIO C : GWART C : GWART REL : LOGK SUB D: LOGW SUB : MAKEFILE : README : README 68K : GKERMIT 68K D: README TXT |
Sometimes the AS68YMB.DAT file is missing or wrong. Create this
file with:
C>as68 -I as68init 68000 assembler initialized |
The CP/M 68k 1.3 C compiler has bugs. The floating point
libraries LIBF.A and LIBE.A from version 1.3 are buggy. Use the
version 1.2 files. The C compiler produces buggy floating point
constants. Use long constants as replacement for float constants
or use strings and atof() function to create correct float
constants.
Look for "This is the
binary for CP/M-68K version 1.2" file 68kv1_2.zip. In folder
DISK4 you find LIBF.A, in folder DISK5 you find LIBE.A. Use
program GKERMIT to transfer these files through the serial port
from host computer to 68k-MBC. First copy the LIBF.A and LIBE.A
files on the host computer to a directory for file transfers like
C:\kermit. Use TeraTerm menu File|Change Directory... to inform
TeraTerm about this directory:
Change to CP/M drive C: and execute GKERMIT from drive D: to
receive file LIBF.A:
C>d:gkermit -r -w G-Kermit CU-1.00, Columbia University, 1999-12-25 Escape back to your local Kermit and give a SEND command. KERMIT READY TO RECEIVE... |
Start KERMIT file transfer in TeraTerm with menu
File|Transfer|Kermit|Send...
Repeat the same procedure with file LIBE.A.
Check file transfer with command STAT:
C>a:stat *.a DRIVE C: USER : 0 RECS BYTES FCBS ATTRIBUTES NAME 199 28K 1 DIR RW C:LIBE .A 160 20K 1 DIR RW C:LIBF .A ---------------------------------------------- TOTAL: 48K 2 C: RW, FREE SPACE: 7,388K |
The column RECS show the file size in 128 Bytes records. 160 is
correct for LIBF.A from CP/M 68k 1.2.
The file name is a.c:
// a.c // CP/M68k 1.3 Alcyon C Compiler + CP/M68k 1.2 LIBF.A or LIBE.A #include <stdio.h> extern float atof(); static float cf[] = { // fail -9.9999999E-01 , -1.00000011E00 , -1.0000002E00 , 0 , 9.9999999E-01 , 1.00000011E00 , 1.0000002E00 , -1e-19, -7e18, 1e-19, 7e18, }; static long cl[] = { // okay 0xFFFFFFC0, 0x800000C1, 0x800001C1, 0, // libf 0xFFFFFF40, 0x80000041, 0x80000141, 0x80000081, 0xFFFFFFFF, 0x80000001, 0xFFFFFF7F, }; static char cs[][16] = { // okay "-9.9999999E-01", "-1.00000011E00", "-1.0000002E00", "0", "9.9999999E-01", "1.00000011E00", "1.0000002E00", "-1e-19", "-7e18", "1e-19", "7e18", }; // floating point simple "pocket calculator" void calculator() { char c; float f1, f2, f3; printf("\nEnter float op float, e.g. 0.6 + 0.7\n"); for (;;) { scanf("%f %c %f", &f1, &c, &f2); switch(c) { case '+': f3 = f1 + f2; break; case '-': f3 = f1 - f2; break; case '*': f3 = f1 * f2; break; case '/': f3 = f1 / f2; break; default: printf("wrong op: %c\n", c); return; break; } printf("%14.7e %c %14.7e = %14.7e\n", f1, c, f2, f3); printf("0x%08lx %c 0x%08lx = 0x%08lx\n", f1, c, f2, f3); } } int main(argc, argv) int argc; char *argv[]; { int i; long l; float f; double d; printf("sizeof int %d\n", sizeof(i)); printf("sizeof long %d\n", sizeof(l)); printf("sizeof float %d\n", sizeof(f)); printf("sizeof double %d\n", sizeof(d)); printf("\nfloat constants: fail\n"); for (i = 0; i < sizeof(cf)/sizeof(cf[0]); ++i) { printf("0x%08lx %14.7e\n", cf[i], cf[i]); } printf("\nstring constants used as float constants: okay\n"); for (i = 0; i < sizeof(cs)/sizeof(cs[0]); ++i) { f = atof(cs[i]); printf("%15s 0x%08lx %14.7e\n", cs[i], f, f); } printf("\nlong constants used as float constants: okay\n"); for (i = 0; i < sizeof(cl)/sizeof(cl[0]); ++i) { printf("0x%08lx %14.7e\n", cl[i], cl[i]); } calculator(); } |
I use copy and paste to transfer the source code from host computer to 68k-MBC. First erase an old version of a.c, then start the editor ED in insert mode with i:
C>era a.c No file C>a:ed a.c NEW FILE : *i 1: |
Then copy the source code on the host computer into the clipboard (e.g. CTRl-A, CTRL-C) and paste it into the TeraTerm window with right mouse buttom (RMB). Leave ED insert mode with CTRL-Z, write file to disk with W and terminate ED with E:
75:
printf("0x%08lx %14.7e\n", cl[i], cl[i]); 76: } 77: calculator(); 78: } 79: : *w : *e C> |
Now compile and link the program with C A and CLINKF A:
C>c a C>CP68 -I 0: A.C A.I C>C068 A.I A.1 A.2 A.3 -F C>ERA A.I C>C168 A.1 A.2 A.S C>ERA A.1 C>ERA A.2 C>AS68 -L -U -S 0: A.S C>ERA A.S C>clinkf a C>LO68 -R -O A.68K 0:S.O A.O .O .O .O .O .O .O .O .O 0:CLIB 0:LIBF.A : Undefined symbol(s) __optoff |
Check file sizes with STAT:
C>a:stat a.* DRIVE C: USER : 0 RECS BYTES FCBS ATTRIBUTES NAME 335 44K 2 DIR RW C:A .68K 19 4K 1 DIR RW C:A .C 28 4K 1 DIR RW C:A .O ---------------------------------------------- TOTAL: 52K 4 C: RW, FREE SPACE: 7,388K |
Run floating point test program A.68K. User input is bold face.
C>a sizeof int 2 sizeof long 4 sizeof float 4 sizeof double 4 float constants: fail 0x000074C0 -0.0000692E-01 0x000076C0 -0.0000704E-01 0x000078C0 -0.0000718E-01 0x00000000 0.0000000E00 0x00007440 0.0000692E-01 0x00007640 0.0000704E-01 0x00007840 0.0000718E-01 0x27260884 -1.3264052E-19 0x36DD1EFB -1.2354214E17 0x27260804 1.3264052E-19 0x36DD1E7B 1.2354214E17 string constants used as float constants: okay -9.9999999E-01 0xFFFFFEC0 -9.9999990E-01 -1.00000011E00 0x800000C1 -1.0000000E00 -1.0000002E00 0x800001C1 -1.0000001E00 0 0x00000000 0.0000000E00 9.9999999E-01 0xFFFFFE40 9.9999990E-01 1.00000011E00 0x80000041 1.0000000E00 1.0000002E00 0x80000141 1.0000001E00 -1e-19 0xEC1E4A81 -1.0000000E-19 -7e18 0xC249FFFF -7.0000014E18 1e-19 0xEC1E4A01 1.0000000E-19 7e18 0xC249FF7F 7.0000014E18 long constants used as float constants: okay 0xFFFFFFC0 -9.9999990E-01 0x800000C1 -1.0000000E00 0x800001C1 -1.0000001E00 0x00000000 0.0000000E00 0xFFFFFF40 9.9999990E-01 0x80000041 1.0000000E00 0x80000141 1.0000001E00 0x80000081 -5.4210114E-20 0xFFFFFFFF -9.2233715E18 0x80000001 5.4210114E-20 0xFFFFFF7F 9.2233715E18 Enter float op float, e.g. 0.6 + 0.7 0.6 + 0.7 6.0000004E-01 + 7.0000000E-01 = 1.2999999E00 0x99999A40 + 0xB3333340 = 0xA6666641 6e-1 - 7e-1 6.0000004E-01 - 7.0000000E-01 = -9.9999961E-02 0x99999A40 - 0xB3333340 = 0xCCCCC8BD 6 * 7 6.0000000E00 * 7.0000000E00 = 4.1999998E01 0xC0000043 * 0xE0000043 = 0xA8000046 6e1 / 7e1 6.0000000E01 / 7.0000000E01 = 8.5714282E-01 0xF0000046 / 0x8C000047 = 0xDB6DB740 ^C |
On "hard disc" B: of the 68k-MBC microSD, there is a Mandelbrot
source code "ASCIIART.BAS" for the BASIC compiler. I converted the
BASIC source code into C source code to compare BASIC compiler
performance and C compiler performance.
// m.c // MANDLEBRT.BAS #include <stdio.h> #ifdef CPM float atof(); #else #include <stdlib.h> #endif // CPM int main() { int X, Y, I; float CA, CB, A, B, T; //MANDLEBRT.BAS float cx=atof("0.0458"); //workaround Alycon C bugs float cy=atof("0.08333"); float c2=atof("2"); float c4=atof("4"); for (Y= -12; Y<=12; ++Y) { //10 FOR Y=-12 TO 12 for (X= -39; X<=39; ++X) { //20 FOR X=-39 TO 39 CA=X*cx; //30 CA=X*0.0458 CB=Y*cy; //40 CB=Y*0.08333 A=CA; //50 A=CA B=CB; //60 B=CB for (I=0; I<=15; ++I) { //70 FOR I=0 TO 15 T=A*A-B*B+CA; //80 T=A*A-B*B+CA B=c2*A*B+CB; //90 B=2*A*B+CB A=T; //100 A=T if ((A*A+B*B)>c4) break; //110 IF (A*A+B*B)>4 GOTO200 } //120 NEXT I if (I>15) { printf(" "); //130 PRINT " "; } else { //140 GOTO 210 if (I>9) I=I+7; //200 IF I>9 THEN I=I+7 printf("%c", 48+I); //205 PRINT CHR$(48+I); } } //210 NEXT X printf("\n"); //220 PRINT } //230 NEXT Y } |
To compile the C program enter:
c m
clinkf m
The BASIC source code is not (completely) structured. One
additional if() statement makes the C source code structured.
There is a little price to pay for structured source code.
There are four floating point constants. I use the atof()
workaround. The C program has a runtime of 25 seconds. The
BASIC program needs 5 minutes, 32 seconds. The C program executes
13 times faster then the BASIC program.
Program output is identical:
000000011111111111111111122222233347E7AB322222111100000000000000000000000000000 000001111111111111111122222222333557BF75433222211111000000000000000000000000000 000111111111111111112222222233445C 643332222111110000000000000000000000000 011111111111111111222222233444556C 654433332211111100000000000000000000000 11111111111111112222233346 D978 BCF DF9 6556F4221111110000000000000000000000 111111111111122223333334469 D 6322111111000000000000000000000 1111111111222333333334457DB 85332111111100000000000000000000 11111122234B744444455556A 96532211111110000000000000000000 122222233347BAA7AB776679 A32211111110000000000000000000 2222233334567 9A A532221111111000000000000000000 222333346679 9432221111111000000000000000000 234445568 F B5432221111111000000000000000000 864332221111111000000000000000000 234445568 F B5432221111111000000000000000000 222333346679 9432221111111000000000000000000 2222233334567 9A A532221111111000000000000000000 122222233347BAA7AB776679 A32211111110000000000000000000 11111122234B744444455556A 96532211111110000000000000000000 1111111111222333333334457DB 85332111111100000000000000000000 111111111111122223333334469 D 6322111111000000000000000000000 11111111111111112222233346 D978 BCF DF9 6556F4221111110000000000000000000000 011111111111111111222222233444556C 654433332211111100000000000000000000000 000111111111111111112222222233445C 643332222111110000000000000000000000000 000001111111111111111122222222333557BF75433222211111000000000000000000000000000 000000011111111111111111122222233347E7AB322222111100000000000000000000000000000 |
The hackaday.io
page file "CPM-68k Manuals.zip" contains the following
documentation: CPM-68K_Users_Guide, CPM-68K_System_Guide,
CPM-68K_Programmers_Guide and
CPM-68K_C_Language_Programming_Guide.
A later Digital Research C
Language Programming Guide for CP/M-68K you find
in section Software Manuals.
The Gem DOS Programmers'
Tools (command, as68, ar68, dump, size68)
you find in section Software Manuals.