tranZPUter SW

Foreword

The tranZPUter and tranZPUter SW are actively being developed and changes are reflected in the documentation on a regular basis.

The tranZPUter SW is an offshoot from the tranZPUter project and utilises a Freescale K64F processor as the IO Control processor as opposed to the ZPU in the original tranZPUter project.

During testing of the tranZPUter v1.0 and with the advent of the RFS v2.0 upgrade with CP/M it was noticed that the tranZPUter should be updated so that the Z80 had additional memory and was able to run at higher clock frequencies. It should also run independent of the controlling IO processor, ie. the ZPU Evo on FPGA fabric or the K64F.

V1.0 of the tranZPUter had design restrictions which in all honesty make the project much harder to complete, for example, because of my lack of experience soldering BGA (Ball Grid Array) IC’s, I chose the next best thing, a pre-fab FPGA board, the CYC1000 with the FPGA already soldered. This device and all other possibilities for the given size and FPGA ALM requirements had too few general I/O pins. This meant that multiplexing had to be used with tri-state register latches. KISS comes back to mind, Keep It Simple Stupid! So in order to further the concept and design I took a step back, looked at what was needed at the Z80 side to realise the CP/M requirements and looked at what was needed for the controlling IO Processor. As I am still not happy about soldering a 30+ pound IC where only an X-Ray machine can validate that it was soldered correctly, I opted for a powerful mini-development board, the Teensy 3.5 which has more than enough general I/O pins and is 5V tolerant, hence this interim design (which is actually better for anyone who is a software programmer and is not happy with electronics or VHDL yet wants to enhance a Z80 machine).

Everything will be written in C/C++ (FLW - Famous Last Words - I had to write the interrupt service routines in ARM Thumb assembler as the K64F isnt quite powerful enough using compiled C) and once working, I can take the bold step into speccing a tranZPUter v2.0 with a BGA knowing that the ZPU will run all the software just written.



Overview

The Sharp MZ80A is based on the Z80 CPU running at 2MHz. It is vintage (albeit the Z80 is still widely used in new industrial designs clocking at 33MHz and above)) and under powered compared with modern computers (or a Raspberry Pi). Besides being part of history, it has a software base that is useful from time to time and still has followers. A software Emulator could be written to prolong the usage of the software but there is something special about using original hardware and this is an alternative to keep the machine original yet provide an upgrade that can power the machine with additional processing capabilities, storage and with multiple different CPU’s based in software like the PiCoPro on the BBC Micro. This is all made possible with bus mastering where the original CPU is tri-stated and the K64F takes control of the bus and the underlying original mainboard peripherals, when needed.

The upgrade also extends the Z80 hardware capabilities by providing additional RAM to allow for a 64K version of CP/M and to increase the speed of the processor whilst maintaining the original speed when accessing the Sharp MZ80A motherboard peripherals.

This design is a work in progress, working in tandem with the tranZPUter. The C/C++ control software written for the tranZPUter SW is intended to work on the tranZPUter under the ZPU.

As the design replaces a Z80 in-situ it is not limited to the MZ80A but can be used in any Z80 based computer with the right software adaptations, ie. the MZ-700 or MZ-80B.



tranZPUter SW

The tranZPUter gets its name from: A TRANsformable ZPU compuTER as the base CPU in the original tranZPUter is the ZPU Evo. The ZPU Evo provides the intended Menu, SD, Video Overlay services to the Sharp MZ80A by tri-stating the original Z80 and accessing the MZ80A memory and peripherals as though they were ZPU devices.

The tranZPUter SW follows on from the tranZPUter design in it’s goals and makes an improvement on the underlying Z80 hardware at the same time. It uses a Freescale K64F ARM Cortex-M4 in place of the ZPU Evo as the tranZPUter SW is more a software solution to the requirement rather than the ZPU Evo which is based on VHDL on an FPGA. The project adds the suffix SW for SoftWare to distinguish the two designs.

To provide different CPU’s it is just a matter of taking existing CPU emulators, for example those used in the PiCoPro and adapting them to use the CPU signals on the MZ80A bus via this designs interface. The program memory could either be that on the MZ80A or the faster K64F memory. ie. There is no real need to use the MZ80A memory when using a soft CPU. The benefits of using a soft CPU is potentially better performance albeit this is yet to be determined as the K64F only runs at 120MHz. The design of the tranZPUter SW upgrades the Z80 hardware and can clock the processor, detached from the Sharp MZ80A motherboard, at much higher clock rates, potentially to 20MHz using the Z8400 20MHz CPU. Higher CPU performance will be a benefit to programs such as CP/M or databases such as DBase II.

In the gallery are pictures of the current design and files uploaded onto github are relatively stable, WIP files wont be uploaded as they are in constant flux.



Hardware

The basics of this design lie in Z80 bus mastering, ie. the ability to switch the Z80 out of circuit and control the remaining computer hardware as required. Bus mastering was typically used by devices such as DMA for fast transfer of data from an I/O device to memory, or memory to memory for applications such as video/graphics. The device taking control of the Z80 bus could transfer data much faster than the Z80 running a program to perform the same action, hence the benefit.

Bus mastering is used to take control of the Z80 bus and to transfer data between main memory and an SD Card or between the I/O processor and the Video display buffer for presentation of menu’s. It is also used where a soft processor completely idle’s the hard Z80 and acts as the main computer CPU. ie. using a soft CPU emulator, it can process applications in local memory and slow down to access I/O and the Video buffer on the host machine as needed presenting a completely different computing experience. Imagine, a 6809 or a 68000 based Sharp MZ80A!

The design centres around lifting the original Z80 onto a daughter card and rerouting several of its signals such that they can be controlled as needed.



v1.0 Z80 Upgrade Schematic

Sheet 1

In order to be able to run programs for other Sharp models (ie.MZ-700) or 64K CP/M the design adds a 512KB Static RAM device with necessary paging logic. As the design needs to be flexible at this stage on memory remapping (ie. mapping blocks of the underlying Sharp MZ80A address space out and mapping in blocks of the 512Kbyte static RAM), a programmable decoder in the form of a Flash RAM is used. This allows maximum flexibility during development to settle on a final set of memory maps for required functionality and a v2.0 of this project can use hardwired logic in a PAL/GAL rather than the Flash RAM to save cost and board space.

The above schematic has been designed such that the basic board can be installed without an IO processor, just plug this board into the Z80 socket on the Sharp MZ80A and it runs as standard and the additional features can be accessed programaticaly in BASIC/Assembler. If the RFS board has been installed then an update to the RFS software will make use of the additional enhanced hardware features. If the RFS board has not been installed and you add the IO Control processor (a Teensy 3.5) then a whole new range of options becomes available which match and exceed those available with the RFS board. Using this design it will be easier to use an FPGA in place of the Teensy 3.5 for the final tranZPUter project.

As the project has progressed small changes have been made to the first cut PCB to reflect fixes and enhancements. The above revision, 1.0d adds extra logic which on the prototype PCB is realised with p-p wiring and piggyback IC’s. The design fully works now and version 1.1 will see logic reduction as far as possible but keep the use of discrete logic rather than a GAL/PAL. Version 1.1 will also use more SMD devices to shrink the PCB size such that it will fit inside the casing of the MZ-80A, MZ-80B and MZ-700. A future version 2 will see the removal of all discrete logic and the 512KB Flash RAM decoder and be replaced with a CPLD.



v1.0 Teensy 3.5 Schematic

Sheet 2

The second schematic is the Teensy 3.5 development board which comes in a 48pin DIL package (with further contact pads on the underside for additional GPIOs) and is ideal to place onto a project board such as the tranZPUter. It contains the Freescale K64F processor, an SD card and USB logic to upload programs into its memory. Very little supporting hardware is needed to enable the Teensy3.5 to control the Z80 in this project due to it’s 5V tolerant core.



v1.0 PCB

As per previous schematics and PCB boards, this project has been designed with KiCad Schematic Capture and PCB Layout. Below are the finished boards awaiting components and assembly.

PCB TopSide

PCB UnderSide


v1.1


Z80 Upgrade Schematic

Sheet 1

Version 1.1 is very similar in functionality to v1.0d, just reducing some of the gates, using existing gate count and adding ENIOWAIT, a control to enable the wait state generator (so original software wont be affected unless it is explicitly enabled).

Teensy 3.5 Schematic

Sheet 2

Version 1.1 is very similar to v1.0d, just adding of ENIOWAIT to detect when the wait state generator is enabled.

PCB

Version 1.1 of the PCB compacts the design a little. I was hoping to make 1 board to fit both the Sharp MZ-80A and MZ-700 but the restrictions placed on the PCB by the MZ-700 (opposite way Z80, gap to insert/remove SD card, clearance etc) means two boards will need to be designed.

The board below is the Kicad image of the Sharp MZ-80A board which is currently being manufactured, the version 1.1 design and PCB is just an iterative design given all the changes needed from v1.0 -> v1.0d.

PCB TopSide

PCB UnderSide


v2.0


Version 2.0 is currently in analysis and design, replacing the discrete logic with a CPLD. The design uses too much discrete logic to manufacture a small PCB to fit into the MZ-700 so the aim is to reduce component count and increase potential functionality along with shrinking the board size to better suit the MZ-700. Looking at the MZ-80B the clearance distance between the Z80B, 8255 and the connectors such as CN6 means the board has a max size of 50x100mm. The CPU faces the same direction as the MZ-700 so hopefully one board will service both machines.

This version and design will be used to forward the ZPU tranZPUter board, replacing the Teensy 3.5 K64F board with an FPGA.



Design Detail

This section provides internal design information for understanding how the tranZPUter functions and its interactions between the Host (the original conputer, currently tested on a Sharp MZ-80A and an MZ-700), the tranZPUter SW daughter board and the K64F processor.



K64F Z80 Host API

The API is based on a common block of RAM within the 64K memory space of the Z80 through which interprocessor communications take place. On the K64F this is declared in C as a structure and on the Z80 as an assembler reference to memory variables.

// Structure to contain inter CPU communications memory for command service processing and results.
// Typically the z80 places a command into the structure in it's memory space and asserts an I/O request,
// the K64F detects the request and reads the lower portion of the struct from z80 memory space, 
// determines the command and then either reads the remainder or writes to the remainder. This struct
// exists in both the z80 and K64F domains and data is sync'd between them as needed.
//
typedef struct __attribute__((__packed__)) {
    uint8_t                          cmd;                                // Command request.
    uint8_t                          result;                             // Result code. 0xFE - set by Z80, command available, 0xFE - set by K64F, command ack and processing. 0x00-0xF0 = cmd complete and result of processing.
    union {
        uint8_t                      dirSector;                          // Virtual directory sector number.
        uint8_t                      fileSector;                         // Sector within open file to read/write.
    };
    uint16_t                         trackNo;                            // For virtual drives with track and sector this is the track number
    uint16_t                         sectorNo;                           // For virtual drives with tracl and sector this is the sector number.
    uint8_t                          fileNo;                             // File number of a file within the last directory listing to open/update.
    union {
        uint16_t                     loadAddr;                           // Load address for ROM/File images which need to be dynamic.
        uint16_t                     cpuFreq;                            // Frequency at which the alternative Z80 clock should be set.
    };
    uint16_t                         loadSize;                           // Size for ROM/File to be loaded.
    uint8_t                          directory[TZSVC_DIRNAME_SIZE];      // Directory in which to look for a file. If no directory is given default to MZF.
    uint8_t                          filename[TZSVC_FILENAME_SIZE];      // File to open or create.
    uint8_t                          wildcard[TZSVC_WILDCARD_SIZE];      // A basic wildcard pattern match filter to be applied to a directory search.
    uint8_t                          sector[TZSVC_SECTOR_SIZE];          // Sector buffer generally for disk read/write.
} t_svcControl;

Communications are all instigated by the Z80. When it needs a service, it will write a command into the svcControl.cmd field and set the svcControl.result field to REQUEST. The Z80 then writes to an output port (configurable but generally 0x68) which in turn sends an interrupt to the K64F. The K64F reads the command and sets the svcControl.result to PROCESSING - the Z80 waits for this handshake, if it doesnt see it after a timeout period it will resend the command. The Z80 then waits for a valid result, again if it doesnt get a result in a reasonable time period it retries the sequence and after a number of attempts gives up with an error.

Once the K64F has processed the command (ie. read directory) and stored any necessary data into the structure, it sets the svcControl.result to a valid result (success, fail or error code) to complete the transaction.

API Command List

Command Cmd# Description
TZSVC_CMD_READDIR 0x01 Open a directory and return the first block of entries.
TZSVC_CMD_NEXTDIR 0x02 Return the next block in an open directory.
TZSVC_CMD_READFILE 0x03 Open a file and return the first block.
TZSVC_CMD_MEXTREADFILE 0x04 Return the next block in an open file.
TZSVC_CMD_CLOSE 0x05 Close any open file or directory.
TZSVC_CMD_LOADFILE 0x06 Load a file directly into tranZPUter memory.
TZSVC_CMD_SAVEFILE 0x07 Save a file directly from tranZPUter memory.
TZSVC_CMD_ERASEFILE 0x08 Erase a file on the SD card.
TZSVC_CMD_CHANGEDIR 0x09 Change active directory on the SD card.
TZSVC_CMD_LOAD40BIOS 0x20 Request 40 column version of the SA1510 BIOS is loaded.
TZSVC_CMD_LOAD80BIOS 0x21 Request 80 column version of the SA1510 BIOS is loaded.
TZSVC_CMD_LOAD700BIOS40 0x22 Request 40 column version of the 1Z-013A MZ-700 BIOS is loaded, change frequency to match the Sharp MZ-700 and action memory page commands.
TZSVC_CMD_LOAD700BIOS80 0x23 Request 80 column version of the 1Z-013A MZ-700 BIOS is loaded, change frequency to match the Sharp MZ-700 and action memory page commands.
TZSVC_CMD_LOAD80BIPL 0x24 Request the loading of the MZ-80B IPL, switch frequency and enable Sharp MZ-80B compatible mode.
TZSVC_CMD_LOADBDOS 0x30 Reload CPM BDOS+CCP.
TZSVC_CMD_ADDSDDRIVE 0x31 Attach a CPM disk to a drive number.
TZSVC_CMD_READSDDRIVE 0x32 Read an attached SD file as a CPM disk drive.
TZSVC_CMD_WRITESDDRIVE 0x33 Write to a CPM disk drive which is an attached SD file.
TZSVC_CMD_CPU_BASEFREQ 0x40 Set the tranZPUter to use the mainboard frequency for the Z80.
TZSVC_CMD_CPU_ALTFREQ 0x41 Switch the Z80 to use the K64F generated clock, ie. alternative frequency.
TZSVC_CMD_CPU_CHGFREQ 0x42 Change the Z80 frequency generated by the K64F to the Hertz value given in svcControl.cpuFreq, the Z80 will be clocked at the nearest timer resolution of this frequency.

API Result List

Command Result# Description
TZSVC_STATUS_OK 0x00 The K64F processing completed successfully.
TZSVC_STATUS_FILE_ERROR 0x01 A file or directory error.
TZSVC_STATUS_REQUEST 0xFE Z80 has posted a request.
TZSVC_STATUS_PROCESSING 0xFF K64F is processing a command.


GPIO Organisation

In this design the K64F works in a supervisory and service role. The Z80 can function standalone without the K64F being present which leaves the host machine completely original and in addtion, the tranZPUter board also offers some new upgrades such as 512K Static RAM which the Z80 can make use of as needed.

If advanced services are needed such as SD card access or hardware emulation then it needs the K64F to provide these services, the Z80 see’s the K64F as a hardware extension, it makes an I/O request and gets functionality in return.

If the Z80 for example requests a BIOS load, it generates an I/O out request which interrupts the K64F, the K64F puts the Z80 into tri-state bus mastered mode and then reads the BIOS from the SD card and operates the Z80 lines to write the BIOS data into the Z80 RAM. Additionally, if the tranZPUter is emulating a machine such as the MZ-700, the K64F needs to read all Z80 I/O transactions to intercept a memory mode change request, tri-state the Z80, write the correct memory mode to the memory mode latch on the tranZPUter then release the Z80 therefore adding hardware emulation.

In order to provide this functionality, the K64 needs to be able to read/write ALL of the Z80 signals when needed. One of the advantages of the K64F is that it has an abundance of digitial I/O ports which are 5V tolerant, therefore connection and operation of a 5V Z80 system is relatively straight forward. Unfortunately the Teensy 3.5 (the small dev board containing the K64F processor) doesnt use a linear allocation of port/pin which is further complicated by the K64F not instantiating certain bits depending on the model. This leads to a disjointed allocation of Z80 signal to GPIO Port/Pin and makes it more time consuming for software to piece together a 16bit address or 8bit data value which it needs to decode realtime in order to detect and act on an event and provide a service if necessary.

The allocation of Z80 pins to GPIO Port/Pins led to some headaches in the interrupt service routine but these have now been solved by the addition of a hardware wait state generator. When an I/O operation is made to the Sharp I/O system range of 0xE0-0xFF a WAIT signal is automatically asserted and cancelled when the ISR raises the BUSRQ signal. Under most situations there is no actual WAIT state inserted, when a delay is created due to a competing interrupt (thread scheduler, millisecond timer) then the mechanism adds a WAIT which keeps the signals valid until the ISR can process them.

In order to understand the issues, the following tables have been created to show Z80 signals to their associated K64F pins. The signals are spread across 5 x 32bit internal K64F registers.

K64F Port and Bit allocation
BIT / PORT 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
A                             Z80_A0 Z80_A11 Z80_A12 Z80_A13 Z80_D4 Z80_D3               Z80_A14        
B                 CTL_RFSH Z80_INT Z80_MEM0 Z80_NMI Z80_A9 Z80_A10 Z80_D1 Z80_D0         Z80_A7 Z80_A8         Z80_MEM4 Z80_MEM3 CTL_HALT CTL_CLKSLCT Z80_BUSACK CTL_BUSACK
C                                         Z80_A1 Z80_A2 Z80_A3 Z80_A4 Z80_RD SYSCLK Z80_WAIT Z80_WR Z80_MREQ Z80_A16 Z80_A17 Z80_BUSRQ
D                                 Z80_RESET       TZ_BUSACK   Z80_MEM2 Z80_MEM1 Z80_D5 Z80_A18 CTL_M1 Z80_D6 Z80_IORQ Z80_D7 CTL_CLK Z80_D2
E           Z80_A15 Z80_A5 Z80_A6                         SYSREQ SVCREQ                    
GPIO bits to Z80 Address Line mapping
ADDR 18 ADDR 17 ADDR 16 ADDR 15 ADDR 14 ADDR 13 ADDR 12 ADDR 11 ADDR 10 ADDR 9 ADDR 8 ADDR 7 ADDR 6 ADDR 5 ADDR 4 ADDR 3 ADDR 2 ADDR 1 ADDR 0
PORT D:6 PORT C:1 PORT C:2 PORT E:26 PORT A:4 PORT A:14 PORT A:15 PORT A:16 PORT B:18 PORT B:19 PORT B:10 PORT B:11 PORT E:24 PORT E:25 PORT C:8 PORT C:9 PORT C:10 PORT C:11 PORT A:17
                                     
GPIO bits to Z80 Data Line mapping
DATA 7 DATA 6 DATA 5 DATA 4 DATA 3 DATA 2 DATA 1 DATA 0
PORT D:2 PORT D:4 PORT D:7 PORT A:13 PORT A:12 PORT D:0 PORT B:17 PORT B:16


Memory Modes

One of the features of the tranZPUterSW hardware design is the ability to create memory maps freely within the 512K Flash RAM. These maps are assigned to a Memory Mode and are selected by the Memory Mode Latch. They define how tranZPUter SW Memory is mapped into the Z80 memory address space along with the original mainboard components. This ability is put to good use in order to realise TZFS, CP/M and the compatible modes of the Sharp MZ-700 and MZ-80B.

Modes which have beed defined are in the table below leaving a few available slots for further expansion.

Mode Target Range Block   Function DRAM Refresh Description
0 Original 0000:0FFF Main MROM Yes Default, normal Sharp MZ80A operating mode, all memory and IO (except tranZPUter control I/O block) are on the mainboard
    1000:CFFF Main D-RAM    
    D000:D7FF Main VRAM    
    D800:DFFF Main ARAM    
    E000:E7FF Main MM I/O    
    E800:EFFF Main User ROM    
    F000:FFFF Main FDC ROM    
1 Orig+ UROM 0000:0FFF RAM 0 MROM Yes As 0 except User ROM is mapped to tranZPUter RAM and used for loadable BIOS images.
    1000:CFFF Main D-RAM    
    D000:D7FF Main VRAM    
    D800:DFFF Main ARAM    
    E000:E7FF Main MM I/O    
    E800:EFFF Main User ROM    
    F000:FFFF Main FDC ROM    
2 TZFS 0000:0FFF RAM 0 MROM No Boot mode for TZFS or any other software requiring use of the tranZPUter RAM. User ROM appears as ROM to the Monitor so it will call the entry point at 0xE800 as part of it’s normal startup procedure. The software stored at 0xE800 can switch out the mainboard and run in tranZPUter RAM as required. Two small holes at F3FE and F7FE exist for the Floppy disk controller (which have to be 64 bytes from F3C0 and F7C0 due to the granularity of the address lines into the Flash RAM), these locations need to be on the mainboard. The floppy disk controller uses them as part of its data read/write as the Z80 isnt fast enough to poll the FDC.
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF Main VRAM    
    D800:DFFF Main ARAM    
    E000:E7FF RAM 0 MM I/O    
    E800:EFFF RAM 0 User ROM    
    F000:FFFF RAM 0 FDC ROM    
3 TZFS 0000:0FFF RAM 0 MROM No Page mode for TZFS, all RAM in tranZPUter Block 0 except F000:FFFF which is in Block 1, this is page bank2 of TZFS.
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF RAM 0 VRAM    
    D800:DFFF RAM 0 ARAM    
    E000:E7FF RAM 0 MM I/O    
    E800:EFFF RAM 0 User ROM    
    F000:FFFF RAM 1 FDC ROM    
4 TZFS 0000:0FFF RAM 0 MROM No As mode 3 but F000:FFFF is in Block 2, this is page bank3 of TZFS.
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF RAM 0 VRAM    
    D800:DFFF RAM 0 ARAM    
    E000:E7FF RAM 0 MM I/O    
    E800:EFFF RAM 0 User ROM    
    F000:FFFF RAM 2 FDC ROM    
5 TZFS 0000:0FFF RAM 0 MROM No As mode 3 but F000:FFFF is in Block 3, this is page bank4 of TZFS.
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF RAM 0 VRAM    
    D800:DFFF RAM 0 ARAM    
    E000:E7FF RAM 0 MM I/O    
    E800:EFFF RAM 0 User ROM    
    F000:FFFF RAM 3 FDC ROM    
6 CP/M 0000:FFFF RAM 4 Main RAM No CP/M, all memory on the tranZPUter board. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
7 CP/M 0000:0100 RAM 4 CP/M Vectors No CP/M main CBIOS area, 48K + 2K available for the CBIOS and direct access to mainboard hardware. F000:FFFF remains in bank 4 and used as the gateway between this memory mode and mode 6.
    0100:CFFF RAM 5 Main RAM    
    D000:D7FF Main VRAM    
    D800:DFFF Main ARAM    
    E000:E7FF Main MM I/O    
    E800:EFFF RAM 5 User ROM    
    F000:FFFF RAM 4 FDC ROM    
10 MZ-700 0000:0FFF RAM 6 Main RAM No MZ-700 mode (OUT $E0) - Monitor RAM replaced with Main RAM
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF Main VRAM    
    D800:DFFF Main ARAM    
    E000:E7FF Main MM I/O    
    E800:EFFF Main User ROM    
    F000:FFFF Main FDC ROM    
11 MZ-700 0000:0FFF RAM 0 MROM No MZ-700 mode (OUT $E0 + $E1) - I/O and Video block replaced with Main RAM
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF RAM 6 VRAM    
    D800:DFFF RAM 6 ARAM    
    E000:E7FF RAM 6 MM I/O    
    E800:EFFF RAM 6 User ROM    
    F000:FFFF RAM 6 FDC ROM    
12 MZ-700 0000:0FFF RAM 6 Main RAM No MZ-700 mode (OUT $E1 + $E2) - Monitor RAM replaced with RAM and I/O and Video block replaced with Main RAM
    1000:CFFF RAM 0 Main RAM    
    D000:D7FF RAM 6 VRAM    
    D800:DFFF RAM 6 ARAM    
    E000:E7FF RAM 6 MM I/O    
    E800:EFFF RAM 6 User ROM    
    F000:FFFF RAM 6 FDC ROM    
13 MZ-700 0000:0FFF RAM 0 MROM No MZ-700 mode (OUT $E5) - Upper memory locked out, Monitor ROM paged in.
    1000:CFFF RAM 0 Main RAM    
    D000:FFFF n/a Undefined    
14 MZ-700 0000:0FFF RAM 6 Main RAM No MZ-700 mode (OUT $E6) - Monitor RAM replaced with RAM and Upper memory locked out.
    1000:CFFF RAM 0 Main RAM    
    D000:FFFF n/a Undefined    
24 K64F Access 0000:FFFF RAM 0 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 0 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
25 ”” 0000:FFFF RAM 1 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 1 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
26 ”” 0000:FFFF RAM 2 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 2 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
27 ”” 0000:FFFF RAM 3 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 3 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
28 ”” 0000:FFFF RAM 4 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 4 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
29 ”” 0000:FFFF RAM 5 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 5 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
30 ”” 0000:FFFF RAM 6 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 6 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.
31 ”” 0000:FFFF RAM 7 Main RAM Yes/No All memory and IO are on the tranZPUter board, 64K block 7 selected. Mainboard DRAM is refreshed by the tranZPUter library when using this mode.

Key:
MROM = Monitor ROM, the original boot firmware ie. SA-1510
D-RAM = Dynamic RAM on the mainboard.
VRAM = Video RAM on the mainboard.
ARAM = Colour Attribute RAM on the mainboard.
MM I/O = Memory Mapped I/O controllers on the mainboard.
RAM 0 .. 7 = 64K RAM Block number within the 512K Static RAM chip.
Main = Host computer mainboard, ie the Sharp MZ-80A mainboard.



Z80 CPU Frequency Switching

In order to make the tranZPUter SW compatible with other machines it is necessary to clock the CPU at the speed of that machine. It is also desirable to clock the CPU as fast as possible when using software such as CP/M for maximum performance.

One of the main issues with frequency switching is that the underlying host cannot have its frequency changed, the host is generally generating the clock and it’s circuits have been designed to operate within it’s clock tolerances.

To fulfil the requirement to have a switchable Z80 CPU frequency a positive edge triggered frequency switch has been implemented which takes the host frequency as one input and a square wave generator from the K64F as its second input. The switching mechanism is tied to the bus control logic and so any access to the host will see the frequency of the CPU being changed to that of the host which ensures continued reliable operation. Under startup conditions, the Z80 is always clocked by the host clock to ensure original specifications of the machine are met.

A second frequency can be selected if the K64F is present as it has the ability using its onboard timers to generate a programmable square wave output. The K64F sets the frequency of this second clock source and the Z80 can select it via an I/O OUT command. This gives the software running on the Z80 to opportunity to change it’s own frequency, albeit to a fixed set one. An extension to the K64F Host API allows the Z80 to make a request of the K64F to set the Z80 CPU frequency to any possible value, this is useful in TZFS or CP/M so a user can select their own frequency.

Current testing on a CMOS Z84C0020 20MHz CPU has the following observations:

  • tranZPUTer reliable in the range 100KHz to 10MHz for all functionality.
  • tranZPUter reliable @ 17.2MHz without mainboard access (frequency resolution by the K64F timer only allows 17.2 or 20MHz). Initial analysis shows the clock switching circuit where the clock goes from 17.2MHz to 2MHz for bus access needs additional work to overcome this restriction. The propogation delay of the IC’s at frequencies > 10MHz sees only 3 clock cyles per mainboard access as opposed to the 4 it needs to operate reliably. This is caused by the 512k Flash RAM decode time coupled with the additional discrete gates which sees the clock circuit missing a rising edge and the clock being held posiive for 1 additional clock cycle. The tranZPUter doesnt crash at higher speeds whilst accessing the mainboard so as long as no mainboard access is made, then switching to the higher speed and slowing down for mainboard (screen) access is practical. Still, better to enhance the clock switch circuit.

It is also possible to slow down the CPU for training or debugging purposes albeit access to the host circuitry will always run at the host clock frequency,

On the Z80, the following table outlines the I/O ports to which it must read/write in order to switch frequencies. As mentioned, changing the second frequency value can only be done by the K64F and this requires the Z80 to make a service request.

Port Function
0x62 Switch Z80 CPU frequency to the second source, ie. the frequency generated by the K64F.
0x64 Switch Z80 CPU frequency to default host source. This is the default on RESET.


Sharp MZ-700 Mode

One of the aims of the tranZPUter was to be able to run, as much as possible, software from other models on the host. The original host is an MZ-80A and the aim was to run software for an MZ-700/MZ-800/MZ-80B on this machine. The tranZPUter itself can be plugged into a real Sharp MZ-700 or MZ-80B and the tranZPUter has been tested on these machines, so additionally the design aim has been extended such that the tranZPUter, when hosted on a 700 or 80B is able run MZ-80A software as well.

First port of call, the Sharp MZ-700 on an MZ-80A. My initial design thoughts intended that the K64F would read real-time Z80 bus transactions and intercept them as needed to ‘fake’ any differences in hardware. For example the Sharp MZ-700 has 64K RAM but accesses it in banks via OUT commands. After spending quite some time on ARM assembler code it became apparent that the K64F just wasnt fast enough even when overclocked. I therefore updated the hardware to add a WAIT state generator, if an IN/OUT command was made in the Sharp reserved area of 0xE0-0xFF then the WAIT line on the Z80 would be asserted and only cleared by a RESET or a BUSRQ signal. The K64F is interrupted when an IO transaction takes place but depending on the run state a thread or timer interrupt could delay processing of the IO transaction. With the WAIT state active this is no longer a problem, once the K64F begins to service the IO interrupt it immediately asserts BUSRQ which releaes the WAIT state and the Z80 continues on to the end of it’s current instruction. This gives time for the K64F to decipher what was on the bus and make appropriate hardware updates before releasing the tri-stated Z80 bus. In practise, viewing on an oscilloscope, the WAIT state is rarely active long enough for the Z80 to action it, thus the host sees no WAIT delay and only minimal delay due to tri-stating of the bus.

The addition of the wait state generator, the 5 memory maps and selectable CPU frequency makes an MZ-700 mode possible. Using TZFS you can enter the MZ-700 mode via a command which loads the 1Z-013A BIOS, sets the CPU frequency to 3.58MHz and installs the correct interrupt drivers on the K64F. This results in the host, for all intents and purposes, behaving like a Sharp MZ-700. Loading S-BASIC sees the venerable ‘BASIC INTERPRETER 1Z-013B’ signon appear, 36439 Bytes free and the Ready prompt. Doesnt sound so impressive but when you realise that S-BASIC is paging in/out various memory blocks just to run it is quite a step forward.

Other than the memory paging and the CPU frequency, there are two main differences between the Sharp MZ-80A and MZ-700, the keyboard and the colour display. On my MZ-80A fitted with the MZ80A COLOUR BOARD the display is not a problem just the keyboard. On a standard MZ-80A the display will function normally it just wont see the colour extensions which the Sharp MZ-700 provides. To remedy the keyboard, for the 1Z-013A BIOS I had the source code so I updated the keyscan mappings which allows it to operate correctly on the MZ-80A keyboard but for other software it is not so easy. Depending on the software being run, the keyscan mappings are either performed in the BIOS in which case my updates will resolve the issue or the software incorporates its own keyboard functionality, ie. S-BASIC. On analysis the software which incorporates its own keyboard functionality is using the same mapping table logic as the BIOS. My intention is to detect this in the K64F and overlay the mapping table which will allow more MZ-700 software to function correctly.



Sharp MZ-80B Mode

As per the MZ-700 mode, a design aim of the tranZPUter is to be able to run Sharp MZ-80B software on an MZ-80A host or additionally on an MZ-700 host.

The MZ-80B has many similarities with the MZ-80A/MZ-700 albeit the keyboard is different and the IO is not memory mapped but IO mapped. The 64K Main memory is also banked. The MZ-80A/MZ-80B/MZ-700 share common Character based Video hardware and also a common Floppy Disk Controller so this aids in running disk based software.

Studying the MZ-80B it is my intention to intercept IO transactions and convert them into memory mapped transactions with the help of the wait state generator. Memory, as per the MZ-700 will be accomodated by memory mappings in the 512K Flash RAM decoder. The Character based Video is common amongst all machines at 0xD000 so it should be possible to run most MZ-80B software on the MZ-80A/MZ-700. Graphics will be possible with the upcoming update of the MZ80A COLOUR BOARD but little steps first, get the IPL to boot and load cassette basic… WIP!



Software

The existing ZPU software, ZPUTA and zOS have been ported to the K64F platform for use with this design. zOS will be the integral OS platform on the K64F processor and the I/O processor specific operations will be handled within a thread of the OS and external applications.



zOS

Please see the section on zOS for details on the operating system. In addition to the standard features and tools, the following applications have been added:

Command Description
tzload Upload and Download files to the tranZPUter memory, grab a video frame or set a new frame.
TZLOAD v1.0

Commands:-
  -h | --help              This help text.
  -d | --download <file>   File into which memory contents from the tranZPUter are stored.
  -u | --upload   <file>   File whose contents are uploaded into the traZPUter memory.
  -U | --uploadset <file>:<addr>,...,<file>:<addr>
                           Upload a set of files at the specified locations. --mainboard specifies mainboard is target, default is tranZPUter.
  -V | --video             The specified input file is uploaded into the video frame buffer or the specified output file is filled with the video frame buffe.

Options:-
  -a | --addr              Memory address to read/write.
  -l | --size              Size of memory block to read. This option is only used when reading tranZPUter memory, for writing, the file size is used.
  -s | --swap              Read tranZPUter memory and store in <infile> then write out <outfile> to the same memory location.
  -m | --mainboard         Operations will take place on the MZ80A mainboard. Default without this flag is to target the tranZPUter memory.
  -z | --mzf               File operations are to process the file as an MZF format file, --addr and --size will override the MZF header values if needed.
  -v | --verbose           Output more messages.

Examples:
  tzload --download monitor.rom -a 0x000000      # Load the file monitor.rom into the tranZPUter memory at address 0x000000.
tzdump Dump tranZPUter memory to screen
TZDUMP v1.0

Commands:-
  -h | --help              This help text.
  -a | --start             Start address.

Options:-
  -e | --end               End address (alternatively use --size).
  -s | --size              Size of memory block to dump (alternatively use --end).
  -m | --mainboard         Operations will take place on the MZ80A mainboard. Default without this flag is to target the tranZPUter memory.
  -v | --verbose           Output more messages.

Examples:
  tzdump -a 0x000000 -s 0x200   # Dump tranZPUter memory from 0x000000 to 0x000200.
tzclear Clear tranZPUter memory.
TZCLEAR v1.0

Commands:-
  -h | --help              This help text.
  -a | --start             Start address.

Options:-
  -e | --end               End address (alternatively use --size).
  -s | --size              Size of memory block to clear (alternatively use --end).
  -b | --byte              Byte value to place into each cleared memory location, defaults to 0x00.
  -m | --mainboard         Operations will take place on the MZ80A mainboard. Default without this flag is to target the tranZPUter memory.
  -v | --verbose           Output more messages.

Examples:
  tzclear -a 0x000000 -s 0x200 -b 0xAA  # Clears memory locations in the tranZPUter memory from 0x000000 to 0x000200 using value 0xAA.
tzclk Set the alternative Z80 CPU frequency.
TZCLK v1.0

Commands:-
  -h | --help              This help text.
  -f | --freq              Desired CPU clock frequency.

Options:-
  -e | --enable            Enable the secondary CPU clock.
  -d | --disable           Disable the secondary CPU clock.
  -v | --verbose           Output more messages.

Examples:
  tzclk --freq 4000000 --enable  # Set the secondary CPU clock frequency to 4MHz and enable its use on the tranZPUter board.
tzreset Reset the tranZPUter.
TZRESET v1.0

Commands:-
  -h | --help              This help text.
  -r | --reset             Perform a hardware reset.
  -l | --load              Reload the default ROMS.

Options:-
  -v | --verbose           Output more messages.

Examples:
  tzreset -r        # Resets the Z80 and associated tranZPUter logic.


TranZputer Filing System

The TranZputer Filing System is a port of the Rom Filing System used on the RFS hardware upgrade board. It reuses much of the same software functionality and consequently provides the same services, the differences lie in the use of a different memory model. It’s purpose is to provide methods to manipulate files stored on the SD card and provide an extended command line interface, the TZFS Monitor. The command set includes SD file manipulation and backup along with a number of commands found on the MZ700/800 computers.

The SD card and ROM’s are managed by the K64F I/O processor. A service request API has been written where by a common shared memory block (640byte) is used in conjunction with a physical I/O request to pass commands and data between the Z80 and the K64F. ie. When the Z80 wants to read an SD file, it creates a request to open a file in the memory block, makes a physical I/O operation which the K64F detects via interrupt, it opens the file and passes the data back to the Z80 one sector at a time in the shared memory.

Under RFS the software had to be split into many ROM pages and accessed via paging as necessary, the same is true for TZFS but the pages are larger and thus less pages are needed. The Z80 software which forms the TranZputer Filing System can be found in the repository within the <software> directory.

The following files form the TranZputer Filing System:

Module Target Location Size Bank Description
tzfs.asm 0xE800:0xFFFF 6K 0 Primary TranZputer Filing System and MZ700/MZ800 Monitor tools.
tzfs_bank2.asm 0xF000:0xFFFF 4K 1 Message printing routines, static messages, ascii conversion and help screen.
tzfs_bank3.asm 0xF000:0xFFFF 4K 2 Unused.
tzfs_bank4.asm 0xF000:0xFFFF 4K 3 Unused.
monitor_SA1510.asm 0x00000:0x01000 4K 0 Original SA1510 Monitor for 40 character display loaded into 64K Bank 0 of tranZPUter memory.
monitor_80c_SA1510.asm 0x00000:0x01000 4K 0 Original SA1510 Monitor patched for 80 character display loaded upon demand into 64K Bank 0 of tranZPUter memory.
monitor_1Z-013A.asm 0x00000:0x01000 4K 0 Original 1Z-013A Monitor for the Sharp MZ-700 patched to use the MZ-80A keybaord and attribute RAM colours.
monitor_80c_1Z-013A.asm 0x00000:0x01000 4K 0 Original 1Z-013A Monitor for the Sharp MZ-700 patched to use the MZ-80A keybaord, attribute RAM colours and 80 column mode.
MZ80B_IPL.asm 0x00000:0x01000 4K 0 Original Sharp MZ-80B IPL firmware to bootstrap MZ-80B programs.

In addition there are several shell scripts to aid in the building of TZFS software, namely:

Script Description
assemble_tzfs.sh A bash script to build the TranZputer Filing System binary images.
assemble_roms.sh A bash script to build all the standard MZ80A ROMS, such as the SA-1510 monitor ROM needed by TZFS.
flashmmcfg A binary program to generate the decoding map file for the tranZPUter SW FlashRAM decoder.
glass-0.5.1.jar A bug fixed version of Glass release 0.5. 0.5 refused to fill to 0xFFFF leaving 1 byte missing, hence the bug fix.

CP/M

CPM v2.23 has been ported to the tranZPUter from the RFS project and enhanced to utilise the full 64K memory available as opposed to 48K under RFS. The Custom BIOS makes use of the tranZPUter memory and saves valuable CP/M TPA space by relocating logic into another memory bank.

The following files form the CBIOS and CP/M Operating System:

Module Target Location Size Bank Description
cbios.asm 0xF000:0xFFFF 4K 0 CPM CBIOS stubs, interrupt service routines (RTC, keyboard etc) and CP/M disk description tables, buffers etc.
cbiosII.asm 0x0000:0xCFFF 48K 1 CPM CBIOS, I/O Processor Service API, SD Card Controller functions, Floppy Disk Controller functions, Screen and ANSI Terminal functions, Utilities and Audio functions.
  0xE800:0xEFFF 2K 1 Additional space for CBIOSII, currently not used.
cpm22.asm 0xDA00:0xEFFF 5K 0 The CP/M operating system comprised of the CCP (Console Command Processor) and the BDOS (Basic Disk Operating System). These components can be overwritten by applications that dont need CPM services and are reloaded when an application terminates.
cpm22-bios.asm     0 The Custom Bios is self contained and this stub no longer contains code.

Additionally there are several shell scripts to aid in the building of the CP/M software, namely:

Script Description
assemble_cpm.sh A shell script to build the CPM binary in the MZF format application for loading via TZFS.
make_cpmdisks.sh A bash script to build a set of CPM disks, created as binary files for use on the FAT32 formatted SD Card. CPC Extended Disk Formats for use in a Floppy disk emulator or copying to physical medium are also created.
glass-0.5.1.jar A bug fixed version of Glass release 0.5. 0.5 refused to fill to 0xFFFF leaving 1 byte missing, hence the bug fix.

Please refer to the CP/M section for more details,



TZFS Monitor

On power up of the Sharp MZ80A, a copmmand line interface called the monitor is presented to the user to enable basic actions such as bootstrapping a tape or manual execution of preloaded software. The TZFS monitor is an extension to the basic monitor and once the tranZPUter SW card has been inserted into the Z80 socket on the mainboard, entering the following command at the monitor prompt ‘*’ will start TZFS:

JE800<cr>

It is possible to automate the startup of the computer directly into TZFS. To do this create an empty file in the root directory of the SD card called:

'TZFSBOOT.FLG'

On startup of the K64F processor, it will boot zOS and then if zOS detects this file it will perform the necessary tasks to ensure TZFS is automatically started on the Sharp MZ80A.

Once TZFS has booted, the typical SA-1510 monitor signon banner will appear and be appended with “+ TZFS” postfix if all works well. The usual ‘*’ prompt appears and you can then issue any of the original SA-1510 commands along with a set of enhanced commands, some of which were seen on the MZ700/ MZ800 range and others are custom. The full set of commands are listed in the table below:

Command Parameters Description
4 n/a Switch to 40 Character mode if the 40/80 Column display upgrade has been added.
8 n/a Switch to 80 Character mode if the 40/80 Column display upgrade has been added.
80B n/a Switch to Sharp MZ-80B compatible mode.
700 n/a Switch to Sharp MZ-700 40 column BIOS and mode.
7008 n/a Switch to Sharp MZ-700 80 column BIOS and mode.
B n/a Enable/Disable key entry beep.
BASIC n/a Locates BASIC SA-5510 on the SD card, loads and runs it.
C [<8 bit value>] Initialise memory from 0x1200 to Top of RAM with 0x00 or provided value.
CPM n/a Locates CP/M 2.23 on the SD card, loads and runs it.
D <address>[<address2>] Dump memory from <address> to <address2> (or 20 lines) in hex and ascii. When a screen is full, the output is paused until a key is pressed.

Subsequent ‘D’ commands without an address value continue on from last displayed address.

Recognised keys during paging are:
‘D’ - page down, ‘U’ - page up, ‘X’ - exit, all other keys list another screen of data.
EC <name> or
<file number>
Erase file from SD Card. The SD Card is searched for a file with <name> or <file number> and if found, erased.
F [<drive number>] Boot from the given Floppy Disk, if no disk number is given, you will be prompted to enter one.
FREQ <frequency in KHz> Change the CPU frequency to the value given, 0 for default. Any frequency is possible, the CPU is the limiting factor. On a Z80H CPU frequencies are valid upto 8.5MHz.
H n/a Help screen of all these commands.
IC <wild card> Listing of the files stored on the SD Card. Each file title is preceded with a hex number which can be used to identify the file. A wildcard pattern can be given to filter the results, ie. ‘*BASIC*’ will list all files with BASIC in their name.
J <address> Jump (start execution) at location <address>.
L | LT n/a Load file into memory from Tape and execute.
LTNX n/a Load file into memory from Tape, dont execute.
LC <name> or
<file number>
Load file into memory from SD Card. The SD Card is searched for a file with <name> or <file number> and if found, loaded and executed.
LCNX <name> or
<file number>
Load file into memory from SD Card. The SD Card is searched for a file with <name> or <file number> and if found, loaded and not executed.
M <address> Edit and change memory locations starting at <address>.
P n/a Run a test on connected printer.
R n/a Run a memory test on main mmemory.
S <start addr> <end addr> <exec addr> Save a block of memory to tape. You will be prompted to enter the filename.

Ie. S120020001203 - Save starting at 0x1200 up until 0x2000 and set execution address to 0x1203.
SC <start addr> <end addr> <exec addr> Save a block of memory to the SD Card as an MZF file. You will be prompted to enter the filename which will be used as the name the file is created under on the SD card.
SDD <directory> Change directory on the SD card for future operations. The default is \MZF which can be changed to any legal FAT32 name.
SD2T <name> or
<file number>
Copy a file from SD Card to Tape. The SD Card is searched for a file with <name> or <file number> and if found, copied to a tape in the CMT.
T n/a Test the 8253 timer.
T2SD n/a Copy a file from Tape onto the SD Card. A program is loaded from Tape and written to a free position in the SD Card.
V n/a Verify a file just written to tape with the original data stored in memory

If the 40/80 column card is installed, typing ‘4’ switches to 40 Column display, typing ‘8’ switches to 80 Column display. For the directory listing commands, 4 columns of output will be shown when in 80 column mode.



Microsoft BASIC

The Sharp machines have several versions of BASIC available to use but unfortunately are not compatible with each other (ie. MZ80A SA5510 differs to the MZ-700 S-BASIC). Each machine can have several variants, ie. SA-6510 for disk drive use or third party versions such as OM-500. They all boot up fine on the tranZPUter but with one major drawback, access to files on the SD card. The source code isnt available for the original Sharp BASIC’s so picking one of the available versions and updating it at the binary level doesnt seem so appealing. In the end I decided to spend some time on the NASCOM v4.7b version of BASIC from Microsoft which has quite a large following in the retro world and has a number of useful programs.

There are two versions of the source code on the internet available, either the original NASCOM 4.7b or a version stripped of several hardware dependent commands such as LOAD/SAVE/SCREEN but tweaked to add binary/hex variables by Grant Searle. I took both versions to make a third, writing and expanding on available commands including the missing tape commands to access NASCOM tape images and BASIC script in ASCII form from SD card.

The original NASCOM Basic Manual should be consulted for the standard set of commands and functions. The table below outlines additions which I have added to better suite the tranZPUter.

Command Parameters Description
CLOAD ”<filename>” Load a cassette image from SD card, ie. tokenised BASIC program.
CSAVE ”<filename>” Save current BASIC program to SD card in tokenised cassette image format.
LOAD ”<filename>” Load a standard ASCII text BASIC program from SD card.
SAVE ”<filename>” Save current BASIC program to SD card in ASCII text format.
DIR <wildcard> List out the current directory using any given wildcard.
CD <FAT32 PATH> Change the working directory to the path given. All commands will now use this directory. On startup, CLOAD/CSAVE default to 0:\CAS and LOAD/SAVE default to 0:\BAS, this command unifies them to use the given directory. To return to using the defaults, type CD without a path.
FREQ <frequency in KHz> Set the CPU to the given KHz frequency, use 0 to switch to the default mainboard frequency. Tested ranges 100KHz to 10MHz, any slower or faster will cause display corruption.
ANSITERM 0 = Off, 1 = On Disable or enable (default) the inbuilt Ansi Terminal processor which recognises ANSI escape sequences and converts them into screen actions. This allows for use of portable BASIC programs which dont depend on specialised screen commands. FYI: The Star Trek V2 BASIC program uses ANSI escape sequences.

I have made two versions of this BASIC, a 48K MZ-80A version which can be used on a standard machine (ie. no tranZPUter) or an enhanced version which uses the full 64K available memory of the tranZPUter. It is also quite easy to change the memory mode commands so that it will operate on a Sharp MZ-700/MZ-800.

NASCOM Cassette Image Converter Tool

NASCOM BASIC programs can be found on the internet as Cassette image files. These files contain all the tape formatting data with embedded tokenised BASIC code. In order to be able to use these files I wrote a converter program which strips out the tape formatting data and reconstructs the BASIC code. In addition, as this version of BASIC has been enhanced to support new commands, the token values have changed and so this program will automatically update the token value during conversion.

The converter is designed to run on the command line and it’s synopsis is:

NASCONV v1.0

Required:-
  -i | --image <file>      Image file to be converted.
  -o | --output <file>     Target destination file for converted data.

Options:-
  -l | --loadaddr <addr>   MZ80A basic start address. NASCOM address is used to set correct MZ80A address.
  -n | --nasaddr <addr>    Original NASCOM basic start address.
  -h | --help              This help test.
  -v | --verbose           Output more messages.

Examples:
  nasconv --image 3dnc.cas --output 3dnc.bas --nasaddr 0x10fa --loadaddr 0x4341    Convert the file 3dnc.cas from NASCOM cassette format.


Memory Decoder Tool

The tranZPUter SW uses a 512KB Flash RAM as the active decoder. This was chosen intentionally to allow multiple different memory maps so as the development progressed the tranZPUter SW could run software from the MZ80K/C/B/700/800 machines as they all are very similar just with different memory maps (graphics can differ but the MZ80A Colour Board does a pretty good job at providing compatible video and it will be upgraded shortly with MZ80B/800 capable pixel graphics.

In order to generate the decoder bit map I have written a tool in C which creates the map based on Z80 signal logic. The logic uses Z80 signals so it is relatively straight forward to say ‘Memory map 5, Z80 WR and Addr:0xE800:EFFF has tranZPUter RAM mapped into it’.

An example of creating a decoder map using signals within the C program:

    // Pre transaction setup. The address lines contain the next address prior to the RD/WR/MREQ/IORQ signals being asserted. If a set
    // uses mixed resources, ie tranZPUter ond mainboard then their is a propogation delay from the FlashRAM being presented with the signals
    // to it outputting a signal plus additional delays for the 279 SR latch, 74HCT08 AND gate and the tristate buffers on the mainboard. This
    // action on the address to pre enable the mainboard or tranZPUter removes the propagation effect on the BUSACK signal on the main board.
    //
    switch(set)
    {
        // Set 3 - Monitor ROM 0000-0FFF, Main RAM area 0x1000-0xD000, User ROM 0xE800-EFFF are in tranZPUter memory block 0, Floppy ROM F000-FFFF are in tranZPUter memory block 1.
        // NB: Main DRAM will not be refreshed so cannot be used to store data in this mode.
        case 3:
            if( (Z80_ADDR >= 0x0000 && Z80_ADDR < 0xD000) || (Z80_ADDR >= 0xE800 && Z80_ADDR < 0xF000)) 
            {
                flashRAM[set].tranche[inSignals].DISABLE_BUS = 0;
                flashRAM[set].tranche[inSignals].ENABLE_BUS = 1;
            } else if ((Z80_ADDR >= 0xF000 && Z80_ADDR < 0xF3C0) || (Z80_ADDR >= 0xF400 && Z80_ADDR < 0xF7C0) || (Z80_ADDR >= 0xF800 && Z80_ADDR < 0x10000))
            {
                flashRAM[set].tranche[inSignals].DISABLE_BUS = 0;
                flashRAM[set].tranche[inSignals].ENABLE_BUS = 1;
                flashRAM[set].tranche[inSignals].A16 = 1;
                flashRAM[set].tranche[inSignals].A17 = 0;
                flashRAM[set].tranche[inSignals].A18 = 0;
            } else
            {
                flashRAM[set].tranche[inSignals].DISABLE_BUS = 1;
                flashRAM[set].tranche[inSignals].ENABLE_BUS = 0;
            } 
            break;

            ...

    // Specific mapping for Memory Writes.
    if(Z80_MEM_WRITE)
    {
        switch(set)
        {
            // Set 3 - Monitor ROM 0000-0FFF, Main RAM area 0x1000-0xD000, User ROM 0xE800-EFFF are in tranZPUter memory block 0, Floppy ROM F000-FFFF are in tranZPUter memory block 1.
            // NB: Main DRAM will not be refreshed so cannot be used to store data in this mode.
            case 3:
                if( (Z80_ADDR >= 0x0000 && Z80_ADDR < 0xD000) || (Z80_ADDR >= 0xE840 && Z80_ADDR < 0xF3C0) || (Z80_ADDR >= 0xF400 && Z80_ADDR < 0xF7C0) || (Z80_ADDR >= 0xF800 && Z80_ADDR < 0x10000)) 
                {
                    flashRAM[set].tranche[inSignals].DISABLE_BUS = 0;
                    flashRAM[set].tranche[inSignals].RAM_WE = 0;
                    flashRAM[set].tranche[inSignals].RAM_OE = 1;
                }
                break;

              ...

The decoder tool is designed to run on the command line and it’s synopsis is:

FLASHMMCFG v1.0

Options:-
  -h | --help              This help test.
  -i | --io-addr <addr>    Base address for the IO Control Registers.
  -o | --output <file>     Output the final binary image to the given file. This file is programmed into the Flash RAM.
  -v | --verbose           Output more messages.

Examples:
  flashmmcfg --output Decode1.bin --io-addr 0x20       Create the mapping binary using 0x20 as the base address for the IO Control Registers.


Building tranZPUter SW Software

The tranZPUter SW board requires several software components to function:

  • zOS - the integral operating system running on the K64F I/O processor
  • TZFS - the Z80 based operating or filing system running on the Sharp MZ80A
  • Memory decoder - the 512Kbyte map which forms the hardware decoder logic of the tranZPUter board
  • CP/M - A real operating system for Microcomputers which I ported to the Sharp MZ80A and it benefits from a plethora of applications.

Building the software requires different procedures and these are described in the sections below.



Paths

For ease of reading, the following shortnames refer to the corresponding path in this chapter. Two repositories are used, the primary one for the tranZPUter and zSoft for the operating system.

zSoft Repository (zOS)

Short Name  
[<ABS PATH>] The path where this repository was extracted on your system.
<zsoft> [<ABS PATH>]/zsoft/
<z-apps> [<ABS PATH>]/zsoft/apps
<z-build> [<ABS PATH>]/zsoft/build
<z-common> [<ABS PATH>]/zsoft/common
<z-libraries> [<ABS PATH>]/zsoft/libraries
<z-teensy3> [<ABS PATH>]/zsoft/teensy3
<z-include> [<ABS PATH>]/zsoft/include
<z-startup> [<ABS PATH>]/zsoft/startup
<z-iocp> [<ABS PATH>]/zsoft/iocp
<z-zOS> [<ABS PATH>]/zsoft/zOS
<z-zputa> [<ABS PATH>]/zsoft/zputa
<z-rtl> [<ABS PATH>]/zsoft/rtl
<z-docs> [<ABS PATH>]/zsoft/docs
<z-tools> [<ABS PATH>]/zsoft/tools

tranZPUter Repository

Short Name  
<cpu> [<ABS PATH>]/tranZPUter/cpu
<build> [<ABS PATH>]/tranZPUter/build
<devices> [<ABS PATH>]/tranZPUter/devices
<docs> [<ABS PATH>]/tranZPUter/docs
<pcb> [<ABS PATH>]/tranZPUter/pcb
<roms> [<ABS PATH>]/tranZPUter/software/roms
<schematics> [<ABS PATH>]/tranZPUter/schematics
<software> [<ABS PATH>]/tranZPUter/software
<tools> [<ABS PATH>]/tranZPUter/software/tools
<asm> [<ABS PATH>]/tranZPUter/software/asm
<srctools> [<ABS PATH>]/tranZPUter/software/src/tools
<cpm> [<ABS PATH>]/tranZPUter/software/CPM
<mzf> [<ABS PATH>]/tranZPUter/software/MZF


Tools

All development has been made under Linux, specifically Debian/Ubuntu. I use Windows for flashing the Flash RAM’s and using the GUI version of CP/M Tools but havent dedicated any time into building the TZFS under Windows. I will in due course create a Docker image with all necessary tools installed, but in the meantime, in order to assemble the Z80 code, the C programs and work with the CP/M software and CP/M disk images, you will need to obtain and install the following tools.

For the Teensy3.5/K64F the ARM compatible toolchain is currently stored in the repo within the build tree.

   
ZPU GCC ToolChain The GCC toolchain for ZPU development. Install into /opt or similar common area.
Arduino The Arduino development environment, not really needed unless adding features to the K64F version of zOS from the extensive Arduino library. Not really needed, more for reference.
Teensyduino The Teensy3 Arduino extensions to work with the Teensy3.5 board at the Arduino level. Not really needed, more for reference.
Z80 Glass Assembler A Z80 Assembler for converting Assembly files into machine code. I have had to fix a bug in the 0.5 release as it wouldnt create a byte at location 0xFFFF, this fixed version is stored in the <tools> directory in the repository.
samdisk A multi-os command line based low level disk manipulation tool.
cpmtools A multi-os command line CP/M disk manipulation tool.
CPMToolsGUI A Windows based GUI CP/M disk manipulation tool.
z88dk An excellent C development kit for the Z80 CPU.
sdcc Another excellent Small Device C compiler, the Z80 being one of its targets. z88dk provides an enhanced (for the Z80) version of this tool within its package.


Build zOS

To build zOS please refer to the zOS build section.

A typical buid line would be:

build.sh -C K64F -O zos  -N 0x10000 -d -T

This builds a zOS image for the K64F processor with a primary heap of 64K (-N 0x10000) and adds the tranZPUter extensions (-T).

The output file would be <z-zOS>/main.hex which can be uploaded into the Teensy 3.5 board.



Build TZFS

Building the software and final load image can be done by cloning the repository and running some of the shell scripts and binaries provided.

TZFS is built as follows:

  1. Make the TZFS binary using <tools>/assemble_tzfs.sh, this creates a ROM image <roms>/tzfs.rom which contains all the main and banked code.
  2. Make the original MZ80A monitor roms using <tools>/assemble_roms.sh, this creates <roms>/monitor_SA1510.rom and <roms>/monitor_80c_SA1510.rom.
  3. Copy and/or delete any required Sharp MZF files into the MZF directory.
  4. Copy files to the SD card.

See below for the typical build stages.



Build the Memory Decoder

To build the memory decoder map for flashing into a 512K Fash RAM clone the repository and follow the steps below:

  1. Change to directory and issue command: make make install
  2. Run the command: /flashmmcfg --output /tranZPUterDecoderMappingFile.bin
  3. Flash the file:/tranZPUterDecoderMappingFile.bin to a suitable 512KB Flash RAM.

Adding decoding logic is a matter of editting the file <software>/src/tools/flashmmcfg.c and adding suitable clauses in the setMap() method.



Build CPM

To build CP/M please refer to the CP/M build section for additional information.

The CP/M version for the tranZPUter is slightly simpler to build as it doesnt involve preparing a special SD card or compacted ROM images.

The CP/M system is built in 4 parts,

1. the cpm22.bin which contains the CCP, BDOS and a CBIOS stub.
2. the banked CBIOS which has its primary source in a 4K page located at 0xF000:FFFF and a
   larger, upto 48K page, located in a seperate 64K RAM block.
3. the concatenation of 1 + 2 + MZF Header into an MZF format file which TZFS can load.
4. creation of the CPM disk drives which are stored as 16MB FAT32 files on the K64F SD card.

All of the above are encoded into 2 bash scripts, namely ‘assemble_cpm.sh’ and ‘make_cpmdisks.sh’ which can be executed as follows:

cd <software>
tools/assemble_cpm.sh
tools/make_cpmdisks.sh

The CPM disk images can be found in <cpm>/1M44/RAW for the raw images or <cpm>/1M44/DSK for the CPC Extended format disk images. These images are built from the directories in <cpm>, each directory starting with CPM* is packaged into one 1.44MB drive image. NB. In addition, the directories are also packaged into all the other supported disks as images in a corresponding directory, ie <cpm>/SDC16M for the 16MB SD Card drive image.

The CPM disks which exist as files on the SD Card are stored in <CPM>/SDC16M/RAW and have the format CPMDSK<number>.RAW, where <number> is 00, 01 … n and corresponds to the disk drive under CP/M to which they are attached (ie. standard boot, 00 = drive A, 01 = drive B etc. If the Floppy Disk Controller has priority then 00 = drive C, 01 = drive D). Under a typical run of CP/M upto 6 disks will be attached (the attachment is dynamic but limited to available memory).



A Typical Build

A quick start to building the software, creating the SD card and installing it has been summarized below.

# Build zOS
cd <zsoft>
./build.sh -C K64F -O zos  -N 0x10000 -d -T
# Flash <z-zOS>/main.hex into the Teensy3.5

# Build TZFS
cd <software>
tools/assemble_tzfs.sh
# Build the required host (Sharp) ROMS.
tools/assemble_roms.sh
# Build CPM
tools/assemble_cpm.sh
# Build the CPM disks.
tools/make_cpmdisks.sh

# Place a FAT32 formatted SD card into your machine and copy the files.
mkdir -p <SD CARD DIR>/TZFS
mkdir -p <SD CARD DIR>/CPM
mkdir -p <SD CARD DIR>/MZF
cp roms/tzfs.rom <SD CARD DIR>/TZFS/
cp roms/monitor_SA1510.rom <SD CARD DIR>/TZFS/SA1510.rom
cp roms/monitor_80c_SA1510.rom <SD CARD DIR>/TZFS/SA1510-8.rom
cp MZF/CPM223.MZF <SD CARD DIR>/MZF/
cp CPM/SDC16M/RAW/* <SD CARD DIR>/CPM/
cp MZF/*.MZF <SD CARD DIR>/MZF/

# If you want TZFS to autostart, create an empty flag file as follows.
> <SD CARD DIR>/TZFSBOOT.FLG

# Eject the card and insert it into the Teensy3.5 reader on the tranZPUter board.
# Remove the Z80 from the Sharp MZ machine and install the tranZPUter board into the Z80 socket.
# Power on. If the autostart flag has been created, you should see the familiar monitor
# signon message followed by +TZFS. If the autostart flag hasnt been created, enter the command
# JE800 into the monitor to initialise TZFS.


Flash Teensy3.5

All the necessary files and executables to program the Teensy can be found in the <z-tools> directory within the zSoft repository,

To program the Teensy after an OS build, follow the steps below:

1. Connect the teensy 3.5 board to your PC with the USB cable.
2. Launch the Teensy programming application: 
   \<z-soft>/teensy 
3. In the Teensy application, select File->Open HEX file and navigate to the \<z-zOS> or \z<zputa> directory (depending on which OS your uploading) and select the file 'main.hex'.
4. Press the RESET button on the Teensy 3.5
5. In the Teensy application, select Operation->Program - this programs the onboard Flash RAM.
6. Ensure you have a terminal emulator open configured to the virtual serial device (if unsure, issue the 'dmesg' command from within Linux to see the latest USB attachment and its name). Normally the device is /dev/ttyACM0. There is no need to set the Baud rate or Bits/Parity, this is a virtual serial port and operates at USB speed.
7. In the Teensy application, select Operation->Reboot - this will now reboot the K64F and it will startup running zOS or ZPUTA.
8. Interact with the OS via the terminal emulator. 

For further information, see the Teensy basic usage guide.



Credits

Where I have used or based any component on a 3rd parties design I have included the original authors copyright notice. All 3rd party software, to my knowledge and research, is open source and freely useable, if there is found to be any component with licensing restrictions, it will be removed from this repository and a suitable link/config provided.



Licenses

This design, hardware and software, is licensed under the GNU Public Licence v3.

The Gnu Public License v3

The source and binary files in this project marked as GPL v3 are free software: you can redistribute it and-or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

The source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.