S100 Computers

HomeS-100 Boards HistoryNew BoardsSoftwareBoards For Sale
ForumOther Web SitesNewsIndex   
  
An S-100 Bus Dual SD Card Board. 
  Dual SD card Board
Introduction
Our Dual IDE/CF card board first done back in 2011 has turned out to be a popular and reliable board. Over 300 of them have gone out world wide over the years.
However CF cards are now not often used these days. more common are the smaller SD cards.  This board utilizes two SD cards instead of two CF cards.
The board is driven by an onboard ESP32 S3 module.

Instead of the now rare HEX LED displays used on the CF Card Board, I have switched over to the now common OLED displays to show CPM Track/Sector etc.
Like our FPGA disk controller boards (e.g. the FPGA_DC Boards) all access to the SD cards is done via a few one byte commands sent to the board.
These commands are processed by the ESP32 and send/receive sector data to the S100 bus over two parallel ports. 
The two ports are completely configurable to any 8 or 16 bit port number with two dip switches. The default ports are status
80H and data 81H.
The following one byte commands control all SD card R/W sector access:-

CMD$INIT$DRIVE_A EQU 80H             ;Initilized drive A:
CMD$INIT$DRIVE_B EQU 81H             ;Initilized drive B:
CMD$SEL$DRIVE_A EQU 82H              ;**** (Re)select an already Initilized drive A:
CMD$SEL$DRIVE_B EQU 83H              ;**** (Re)select an already Initilized drive B:
CMD$SET$TRK$SEC EQU 84H              ;Set new current TRACK+SECTOR on current drive (new)
CMD$READ$SECTOR EQU 85H              ;**** Read data from the CURRENT sector (on current sector, drive).
CMD$WRITE$SECTOR EQU 86H             ;**** Write data to the CURRENT sector (on current sector, drive).
CMD$FORMAT$SECTOR EQU 87H            ;Format the CURRENT sector with E5's.
CMD$RESET$ESP32 EQU 88H              ;Reset the ESP32 CPU

It should be noted that we are accessing the sector directly. There are numerous examples of reading and writing to SD cards using MSDOS file names.  However such an arrangement really complicates
things for CPM. It would require a n MSDOS "disk file" be setup on the SD card and 512 byte sections of that file would be accessed using a file pointer.
Instead we directly access the sector using the Arduino ESP32 functions.

While on the surface accessing two SD cards would appear to require only a small change in the ESP32 software we used for the IDE-2CF+1SD card board,
it turns out the SD.readRAW(sector_buffer, sector) and SD.writeRAW(sector_buffer,sector) functions used there will not work with two separate SD cards.
I went through numerous hardware and software prototypes to solve this.  I then thought of asking ChatGTP to write for me a Arduino ESP32 program that would
allow two SD cards to be independently accessed by one ESP32.  To my amazement the example program I got back worked.
The key contribution was instead of using the SdFat library by Bill Greiman (not the default SD library).
I then incorporate the example code in my main runtime Arduino code.  It worked flawsley allowing me to access the two SD cards independent of each other.
So CPM drives A: and B: are the "regular IDE-CF cards" and C: and D: are the SD cards,
I supply below both a Non-banked and Banked CF card image to run CPM2 with these 4 drives.
I have not got around yet to writing a CPM3 image that will boot directly from SD card C:. 
Writing the CPM3.SYS is fairly straight forward but the Z80 master monitor (already quite full) would need a boot menu option.


ESP32 Module

The ESP32 modules we will use need to have plenty of GPIO pins since we need two parallel ports and status lines to and from the S100 bus.
Here are two examples. The first is a common Chinese "generic" version on Amazon.  The second is the well known Waveshare company module:-
   
  ESP32 module 2

There are quite a few others on Amazon etc. but it is very important to be sure the same GPIO pins on these modules (which are the same) is exactly the same on any other ESP32 module
you use (or else alter the Arduino.ino file, see below). Here are diagrams of the pinouts of the two modules I used here:-
 

  ESP32 S3 Pinout
   
Waveshare Pinout

Note the actual modules on the board are upside down for convenient access to the USB at the top for programming/monitoring  the module.
In the case of the dual USB port module the USB port on the LHS is used for programming.

OLED Module

The are numerous small OLED displays these days. I use here a 1.54 Inch OLED Module 12864 128x64 SSD1309 LCD Display. It is available from a number of suppliers.  I got mine from Amazon.
The ESP32 uses an I2C interface using pins
GPIO9 and GPIO8.  Programming these displays is quite complicated. Fortunately there is an ESP32 Arduino library to interface the units and send ASCII text.
  
   OLED Display

   
There seems to be a two types where the four connecting pins are GND,VCC,SCL,SDA and VCC,GND,SCL,SDA.  There is a jumper on the board (P3) to accommodate the power for both types. 
Check the voltage on pins P1 and P2 and jumper P25 to match. Only then add the OLED unit.

Note there are also other similar size OLED displays that have more pins and are not I2C driven.  They will not work with this board.
There are however larger versions of the 4 pin OLED displays. I have had mixed results getting these to display text completely correctly.

SD CARD Modules

The SD cards themselves are controlled by SD card adaptors.
There are two popular types shown here that are well tested on previous S100Computers boards. The interface will be described below.
  
SD Card Asdaptors

The Adafruit has a 5V to 3.3V level shifter so it could be run with just a 5V interface. However the SparkFun does not. All its pins must be 3.3V.
For safety we will drive both boards using
74LVC245 voltage level shifters.

The rest of the boards components are standard -- available from Jameco, Mouser, Digi-Key etc. For prototype boards I generally use "double swipe" IC sockets.
For a critical board like this I prefer to use "Machine Tooled" IC sockets.  However they are more expensive and you have to be particularly careful not to bend the actual IC pins. 
There is a slight complication for the ESP32 module socket.  The spacing between the two rows of 22 pins for both units above is slightly different.
The Waveshare module pins are about 0.1" closer.  So depending on your module use the appropriate board pin holes.
 
   ESP32 Sockets

  
You can either solder the ESP32 module directly to the board or cut to size single row 0.1"" sockets such as the Jameco #2168173 socket
.
          
  Socket

However if you use these headers the  ESP32 module sits high on the board preventing you from having another S100 card in the next S100 bus slot.
Fortunately the holes on the board can accommodate the ESP32 tight enough for good contacts. It is tricky however to seat them properly.
Of course when the board is finished you should solder the pins.


Board Construction
There is nothing particular special about constructing this board.  Use the normal construction process we have in the past. Be careful with LED and electrolytic cap orientations.
The longer lead goes into the square hole. Check also the orientation of resistor networks.
 
The Pololu 5V exist in a few forms. While the older ones (D24V25F5) are still available and uses
P6, it seems Pololu is suggesting users use the newer D24V22F5
(5V, 2.5 Amp) units, it has a different pinout, use this one in P4
The ESP32 S3 module supplies enough current to drive all the 3.3V board chips.
   
Without any chips on the board pop the board into the S100 bus and check you are getting 5V going to each IC socket that uses 5V.
If this is OK install all IC's to the board, including the ESP32_S3 module  (in sockets
P2+P5). As mentioned above, there is a second socket P15 to accommodate some ESP32 modules that have a slightly wider spacing. (P15 + P5).

Note the ESP32-S3 is mounted on the board upside down so the USB port connection is easily available when the board is in the S100 bus.

Jumper K1 1-2 for an 8 bit port address. Set the two dip switches as shown here to select ports 80H and 81H.
  
  Dip Switches

  
Jumper P1 1-2 and 3-4 (vertical).
The most common OLED displays use P3 4-6 and 1-3.
K2 (board reset), is normally is 1-2.
Jumper K1 1-2 for 16 bit port addressing and 2-3 for 8 bit addressing.
The small push-button switch is only used to restart the ESP32 program. used for example if you change an SD card.
The toggle switch determines if SD card info is displayed on the OLED display.
Displaying on the OED display does slow down board sector access. Normally its to the right (off).

There are 10 single pin jumpers that may be used for signal analysis (see below).  Normally they are not used.

How the Board Works
Before going further open the board schematic (see below) and study it to understand how the board works.

In summary:-
In the default configuration the four S100 bus ports are
80H (IN & OUT) for status bits and 81H (IN & OUT) for data ports.
 
   Scamatic 1
       

Because the ESP32 CPU is running at 120MHz data transfer and handshaking have to be bullet proof and simple!
 

Whenever the S100 bus writes a byte to port 81H the bus D00-D07 lines are latched into U9.
At the same time S100_WRITE_ENABLE  clocks the Flip Flop U6A which ends up as a high on the ESP32 GPIO20 pin.
The EESP32 continuously looks at GPIP_20. If it is high it realizes S100 bus data is available.
After the ESP32 reads the 8 bits on U8 it pulses its GPIO_2 pin low. This resets the U6A Flip Flop and now lowers GPIO20 indicating to the ESP32 the byte of data has been read.
This process is done reputedly for all data coming to the ESP32.

Whenever the S100 bus reads a byte send by the ESP32 to port 81H the U15 input lines (GPIO_35-GPIO_42) are held steady with the 8 bits of data.
The ESP32 GPIO_1 pin also sets the Flip Flop U6B  which goes on to raise bit 7 of status port 80H (DI7) of U14.
Once the S100 bus sees this it reads the data from U15 (S100_READ_ENABLE). This also resets the Flip Flop U6B (using U17B).
The ESP32 also looks at pin GPIO_21 on U10 which tracks when the data on U15 was read by the S100 bus.
Another byte of data from the ESP32 is never sent until the previous byte was read by the S100 bus.


This handshaking has to be rock solid because every sector (512 bytes) of data passes back and forth between the SD card and the S100 bus.
Because the ESP32 has a clock of up to 240MHz even with the overhead of Arduino code (see below) the data transfer process is very fast.
Note. there are no (slowing) resetting bits on the S100 bus side is required.

The rest of the board is fairly straightforward, The OLED display uses an I2C interface from the ESP32 (pins GPIO_8 and GPIO_9).


The Arduino ESP32 Code

One very nice thing about these ESP32 modules is that the popular Arduino IDE interface can be used to program them.
With this board you need to configure the Arduino interface/tools/board to be an
ESP32 S3 Module.
Hookup USB connection to your computer. You need to also let the Arduino IDE which computer "COM" port is connected to your ESP32.
The Arduino code utilizes a few libraries and .h files:-
 
#include "FS.h"
#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include "fonts\TimesNewRoman16.h"
#include "fonts\X11fixed7x14B.h"

If your current Arduino IDE does not have them you need to download them from the web.
If you are not familiar with using the Arduino IDE and the ESP32 you should first see a few YouTube demos. For example here.

The one tricky part is writing code to read and write to the S100 bus 8 bit parallel ports. (The ESP32 does not have a direct port input).
Here is the code:-

void Output_PARALLEL_Port(char PARALLEL_value){
gpio_set_level(GPIO_NUM_42, (PARALLEL_value & 0x80) >> 7);
gpio_set_level(GPIO_NUM_41, (PARALLEL_value & 0x40) >> 6);
gpio_set_level(GPIO_NUM_40, (PARALLEL_value & 0x20) >> 5);
gpio_set_level(GPIO_NUM_39, (PARALLEL_value & 0x10) >> 4);
gpio_set_level(GPIO_NUM_38, (PARALLEL_value & 0x08) >> 3);
gpio_set_level(GPIO_NUM_37, (PARALLEL_value & 0x04) >> 2);
gpio_set_level(GPIO_NUM_36, (PARALLEL_value & 0x02) >> 1);
gpio_set_level(GPIO_NUM_35, (PARALLEL_value & 0x01));
gpio_set_level(GPIO_NUM_1,HIGH);                                               // pulse U15 LE high
gpio_set_level(GPIO_NUM_1,LOW);                                                // return U15 LE low
}


char Input_PARALLEL_Port() {
char PARALLEL_value;
PARALLEL_value =
digitalRead(GPIO_NUM_4) +
(digitalRead(GPIO_NUM_5) << 1) +
(digitalRead(GPIO_NUM_6) << 2) +
(digitalRead(GPIO_NUM_7) << 3) +
(digitalRead(GPIO_NUM_15) << 4) +
// (digitalRead(GPIO_NUM_16) << 5) +
(digitalRead(GPIO_NUM_19) << 5) +
(digitalRead(GPIO_NUM_17) << 6) +
(digitalRead(GPIO_NUM_18) << 7);
gpio_set_level(GPIO_NUM_2,LOW);                                                // pulse U15 LE high
gpio_set_level(GPIO_NUM_2,HIGH);                                               // return U15 LE low
return(PARALLEL_value);
}

Once setup, the ESP32 sits in a continuous loop waiting for 8 bit commands coming from the S100 bus. They are:-
 
CMD$INIT$DRIVE_A EQU 80H             ;Initilized drive A:
CMD$INIT$DRIVE_B EQU 81H             ;Initilized drive B:
CMD$SEL$DRIVE_A EQU 82H              ;**** (Re)select an already initilized drive A:
CMD$SEL$DRIVE_B EQU 83H              ;**** (Re)select an already initilized drive B:
CMD$SET$TRK$SEC EQU 84H              ;Set new current TRACK+SECTOR on current drive (new)
CMD$READ$SECTOR EQU 85H              ;**** Read data from the CURRENT sector (on current sector, drive).
CMD$WRITE$SECTOR EQU 86H             ;**** Write data to the CURRENT sector (on current sector, drive).
CMD$FORMAT$SECTOR EQU 87H            ;Format the CURRENT sector with E5's.
CMD$RESET$ESP32 EQU 88H              ;Reset the ESP32 CPU

 
Each command has a specific format of an initial 33H byte, then a one byte command listed above and for sector R/W the sector number (0-FFFFH).
The hardware above clocks each byte back and forth between the S100 bus and the ESP32/SD card.
The two byte command with the first byte always being 33H is for safety. You don't want  an noise/incorrect byte getting by.
I never had this problem here however.

If you look are the Arduino code you will see that I initilize the two SD cards in
setup() rather than later in loop(). 
I found this approach to be faster and more reliable.
Here is an extract of the SD card initialization routine.

 
SpiSD1.begin(SD1_SCK, SD1_MISO, SD1_MOSI, SD1_CS);
SdSpiConfig config1(SD1_CS, DEDICATED_SPI, SPI_SPEED, &spiSD1);
if (!card1.begin(config1))
      {
      display.clear();
      display.setCursor(0,0);
      display.print("SD1 Init Error"); // verify OLED display is functional
      SetErrorLED();
      SD1_valid = 0;
      }
      else
      {
      display.setCursor(0,0);
      display.print("SD1 Init OK"); // verify OLED display is functional
      current_drive = 3;
      current_drive_letter = 0x43; // C:
      SD1_valid = 1;
      }
delay(1000);

Please take a moment to study the Arduino ESP32 .ino code available at the bottom of this page.


S100 Bus Test programs

In order to test this board I have written two short Z80 programs (
SD_IO_Z80 & SD_CARD.Z80) to run at 100H in RAM.


SD_IO.Z80
In order to test this board I have written two short Z80 programs that run at 100H in RAM.
They are
SD_IO.Z80 and SD_CARD.Z80. The ESP32 also needs to be programed.
For
SD_IO.Z80 the ESP32 Arduino program is ESP32_SD_Boards_IO_Tests.ino
For
SD_CARD.Z80 the ESP32 Arduino program is Dual_SD_cards_ESP32_Runtime.ino

First lets try the simplest program SD_IO.Z80. This program is assembled using the Altair PC program see
here.  
The .COM file is send over to the S100 bus with a program like Tara Term or Absolute Telnet being received via  the Master Z80 Master monitor "X' menu option


So we load SD_IO.COM (see below), to RAM at 100H with the Master monitor with the Master monitor "X" command.
Then type G100, you should see:-
   

  
 
  SD IO Z80

There are only 3 menu options. These test the handshaking signals between the ESP32 and the S100 bus.
You must comment in/out the appropriate section of  ESP32_SD_Boards_IO_Tests.ino  for each menu test.

Here is the relevant  ESP32 code for Test D:-

void loop() {
char cmd;
char data, data1, data2;
uint8_t cardType;
uint16_t sectorSize;
uint32_t sector_count;

gpio_set_level(GPIO_NUM_2,HIGH); // Set U4A LOW will set U6A reset high
gpio_set_level(GPIO_NUM_2,LOW); // Set U4A LOW will set U6A reset high
ClearErrorLED();
// COMMENT IN/OUT THE TEST REQUIRED
while(1)
           {
  
         // data = GetData(); // Get data Test
           // sprintf(string_buffer,"\r\nGot data (80H) = %x",data);
           // Serial.println(string_buffer);
           // data = GetData();
           // sprintf(string_buffer,"\r\nGot data (81H) = %x",data);
           // Serial.println(string_buffer);
          // data = GetData();
          // sprintf(string_buffer,"\r\nGot data (82H) = %x",data);
          // Serial.println(string_buffer);

          // data = GetData(); // Get String Test
          // sprintf(string_buffer,"\r\n(String test, Got data = %x",data);
          // Serial.println(string_buffer);
          // SendString(string_buffer);

         
data1 = GetCMD(); // Get CMD Test
          data2 = GetCMD();
          sprintf(string_buffer,"\r\n(String test, Got CMD1 = %x CMD2 = %x",data1,data2);
          Serial.println(string_buffer);
          SendString(string_buffer);
         }
}


You should see the following output on the S100 bus console:-
     
  IO test Output

Do not go further unless the above 3 tests work correctly.


SD_CARD.Z80

Next load the ESP32 resident program from  Dual_SD_cards_ESP32_Runtime.ino  
This is the "normal" runtime program that always resides within the ESP32 regardless of the CPM3 version.

Before going to CPM3 we need to test sector reads and writes.
Load
SD_CARD.COM (see below), to RAM at 100H with the Master monitor (see below), to RAM at 100H with the Master monitor "X" command.
Then type G100, you should see:-
  
    SD Card Z80
 

This program communicates directly with the ESP32 ports 80H and 81H.  It sends either commands and/or data in bytes.
The core I/O routines are:-
   
SD_CARD.Z80

GET_DATA:
      IN    A,(SD_CARD_STATUS)     ;Wait for character (GPIO_3 and GPIO_21)
      BIT  7,A
      JR   Z,GET_DATA
      IN    A,(SD_CARD_DATA)         ;S100 read enable will reset U6B GPIO_21
      LD    C,A
 GET_DATA1:
      IN A,(SD_CARD_STATUS)       ;Wait for character (GPIO_3 and GPIO_21)
      BIT 7,A
      JR NZ,GET_DATA1
      LD A,C
      RET


SEND_DATA:
      IN     A,(SD_CARD_STATUS)     ;Wait until any previous character has been read
      BIT    0,A 
      JR     NZ,SEND_DATA
      LD     A,C                    ;Send Data, this will raise GPIO_20
      OUT    (SD_CARD_DATA),A
SEND_DATA1:
      IN     A,(SD_CARD_STATUS)     ;Wait until the ESP32 has reset U6A with GPIO_2
      BIT    0,A
      JR     NZ,SEND_DATA1
      RET


Over on the ESP32 side the code is:-

ESP32_DUAL_SD_CARD.INO
Read/Write Data routine:-

char GetData(){                        //Get an S100 bus Command or byte
char data;
while(digitalRead(GPIO_NUM_20) == 0);  // wait for data
data=Input_PARALLEL_Port();            // get second CMD byte
return(data);
}


char SendData(char data){               //Send an S100 bus Data
while(digitalRead(GPIO_NUM_21) == 1);
Output_PARALLEL_Port(data);
return(data);
}

Initilization of Drive 1:-
  
spiSD1.begin(SD1_SCK, SD1_MISO, SD1_MOSI, SD1_CS);
SdSpiConfig config1(SD1_CS, DEDICATED_SPI, SPI_SPEED, &spiSD1);
if (!card1.begin(config1))
    {
    display.clear();
    display.setCursor(0,0);
    display.print("SD1 Init Error"); // verify OLED display is functional
    SetErrorLED();
    SD1_valid = 0;
    }
else
    {
    display.setCursor(0,0);
    display.print("SD1 Init OK"); // verify OLED display is functional
    current_drive = 3;
    current_drive_letter = 0x43; // C:
    SD1_valid = 1;
    }
delay(1000);

 
For example with an SD card in A: the (LHS) Adafruit or Sparkfun adaptor and type "A".
This will allow the ESP32 to select the SD card type and initialize it.
You should see the following on the OLED display:-
  
  OLE Diaplay 1

This indicates the ESP32 has Initilized its library to interact directly with sectors on the SD card.
Next enter the "R" command.
You should see the following on the OLED display:-
  
  OLED display 2

and the actual 512 byte sector contents on the console.
   
  Sector Display

Hitting the space bar will display the next sector. Hit the ESC key to return to the main menu.

Note in the default configuration the board assumes a CPM disk of
0FFH CPM tracks with 0FFH sectors/track.

It is absolutely essential that this program runs correctly.
Do not go further until you have this program working correctly.
 

CPM likes to have its directory disk sectors Initilized with E5's.   The
"F" command will do this.
There is no need to format the whole disk, just enough for a disk directort table.
Here is a sector formatted with the "F" command.

  
 
  Formatted Sector
  

For any one SD card reading and writing sectors is fast and very reliable
Currently I'm also using the same SD cards in both drives.
   
  Gladstone 8GB SD Cards
 

Booting with CPM3 (Non-Banked & Banked).

First, CPM3 versions above can be booted using any of the old IDE/CF cards.  However Drive C: & D:  will not be recognized nor will the OLED Display show drive/sector info.
This is because the BIOS must send commands to the ESP32.

Likewise the CPM3 versions for this board (see below) will not run on the old IDE/CF boards, They are expecting feedback from an ESP32 module.
A modification to the BIOS to check for the ESP32 could be written but that is not done here.


A Non-Banked CPM3 System
This is the simplest arrangement and should work with most hardware. The only requirement being the BIOS Console I/O must be port 0H & 1H.  This can be easily modified (see below).
Our Propeller driven Console IO Board is normally used.

In order to get people up an running  I am supplying a Non-banked "CPM3 Image Disk"  These can be seen here.  It's under CPM3 CF+SD Card Image #14
If you are not familiar with booting up a CPM3 system you need to read that page and also here.

Making a Functional CPM3  CF Card.
These days one usually writes a CPM3 BIOS and makes a CPM3.SYS file on a PC using Peter Schorn's AltairZ80 Simulator.  The challenge is getting files on to your S100 disk system when you don't yet have a functional system.
We get  around this chicken and the egg problem by using a complete functional CPM3 "disk image" on a CF card and booting CPM3 directly in your S100system which has programs to download further files etc. from your PC. 
We don't need to dwell how the first S100 bus CF card was made here.  Suffice to say, with such a CF card you immediately have a fully functional CPM3 system from which you can developed more elaborate hardware and software.

We will use the program called
HDD Raw Copy Tool to make a fully functional CPM3 'disk' from a file that resides on your PC.  The program can be found here.  It can also be found at the bottom of this page.  There are a number of disk image files there. Here we need to copy the CF card image file #14.   Because they are actual sector by sector CF card copies they are quite large (typically 6-7MB).  Typically I use 4GB CF Cards.  This is way overkill for CPM3 (but not MSDOS etc.).  I found that  HDD Raw Copy Tool does not copy reliably with older small size CF cards.  Likewise the new high capacity cards caused me some problems.  If possible use Kingston or Verbatim 4GB cards.
Make sure to format a CF card with FAT32 first.

Here is a picture of
HHD Raw Copy being used to unpack the FPGA_DC_CPM_Image.imgc on to a CF card.  Actually since our CPM3 disk is only 0FFH tracks, with 0FFH Sectors/Track maximum,  you can probably stop the unpacking process after sector 0FFFFH (65,535).  Here is how the "unpacking" dialog looks:-
    
  CF card Copying  
  
Be real careful in picking the target drive. This program will esaily overwrite a valid widnows disk.

Modifying your CPM3 Image.
The above Non-Banked CPM CF card image should signon like this:-
     
    Non-banked CPM3

You should be able to move files around between disks with no problems. Use PIP + [V]

Should you wish to enhance your CPM3 image with Floppy disks etc. You will need to build a new CPM3.SYS file.
This is described in detail here. I am supplying below the complete folder to build a CPM3 Non-banked image for this board.
The goal is to make a new CPM3.SYS file.  Then after booting your current CF card CPM3
you can use the supplied PCGET.COM or USBGET.COM program (already on the CF card) to download the CPM3.SYS file
to your C: drive. The next time you reboot the new system will be active.

Remember however if there is a bug in the CPM3.SYS file your system may hang. Always have a second CF card with a working image.
Then just PIP the working CPM3.SYS file to the "bad" CF Card and try again.

One final thing to keep in mind.  CPM3 needs a bootloader file as well that resides on the first few sectors of any bootable CF card.
This bootloader can be non-banked or banked (see below).  The above image #12 has this bootloader on the CF card.
However if you use a new CF card (FAT32 formatted)  the loader needs to be placed on the card.

This can be done in a few ways:-
1. Just "burn"  the above image #12 to a new card.  Then with the card  in your B: drive erase *.*.  
    The copy all files across including CPM3.SYS.
2. Use the MYIDE.COM program (On the image #12 disk) and copy the first few tracks of A: to B:
    Then erase *.* on the B: drive. Then copy all files A: to B: across including CPM3.SYS.
3. Use the CPM3 Bootloader HSYSGEN.COM program described here and on the CF card image #12 disk.


A Banked CPM3 System

This is a bit more complex but the process is the same as for the non-banked version of CPM3.
Again the only requirement being the BIOS Console I/O must be port 0H & 1H.  This can be easily modified (see below).
Our Propeller driven Console IO Board is normally used.

In order to get people up an running I am supplying a Banked "CPM3 Image Disk"  These can be seen hereIt's under CPM3 CF+SD Card Image #13
Again if you are not familiar with booting up a CPM3 system you need to read that page and also here.


Here is what the Banked CPM3 signon looks like.
  
     Banked CPM3
 
Everything said above for the non-banked version of CPM3 is also true for the Banked version.
You just have a far larger TPA.

Notes/Bugs:-
None so far.

A Production S-100 Board.
Realizing that a number of people might want to utilize a board like this together with a group of people on the  Google Groups S100Computers Forum, a  "group purchases"is now open. 
Please see here
for more information on older boards.
   
    
The links below will contain the most recent schematic of this board.
Note, they may change over time and some IC part or pin numbers may not correlate exactly with the text in the article above.
 

MOST CURRENT  SD CARD_BOARD SCHEMATIC     
          (V2.3A     5/17/2025)
MOST CURRENT SD_CARD_BOARD  KiCAD Files                (V2.3     5/17/2025)
MOST CURRENT SD_CARD_BOARD GERBER Files               (V2.3    5/16/2025)
BOMM for SD_CARD_BOARD                                            
      (V2.3     5/16/2025)  
 

ESP32_Dual_Core_Test.ino                                                 Code to program the ESP32 S3 Module to R/W SD card sectors           (5/16/2025)

ESP32_Dual_SD Runtime .ino File  (as Text file)                  Code to program the ESP32 S3 Module to R/W SD card sectors            (5/16/2025)
SD_IO.Z80                                                                          Code to test the board data handshaking on the S100 bus                    (5/16/2025)
SD_Card.Z80                                                                       Code to Read/Write SD card sectors from the S100 bus                         (5/16/2025)
SD _Card _Z80.ZIP  Folder                                                  Complete Folder of Z80 files                                                                  (5/16/2025)


Other pages describing my S-100 hardware and software.

Please click here to continue...

This page was last modified on 05/17/2025