Changes to accommodate SW700 board

This commit is contained in:
Philip Smart
2020-11-02 01:20:50 +00:00
parent add502f1c7
commit 6bf804771b
9 changed files with 134 additions and 98 deletions

View File

@@ -382,7 +382,7 @@ static void restoreIRQ(void)
// The OS millisecond counter address is passed into this library to gain access to time without the penalty of procedure calls.
// Time is used for timeouts and seriously affects pulse width of signals when procedure calls are made.
//
void setupZ80Pins(uint8_t initTeensy, volatile uint32_t *millisecondTick)
void setupZ80Pins(uint8_t initK64F, volatile uint32_t *millisecondTick)
{
// Locals.
//
@@ -393,7 +393,7 @@ void setupZ80Pins(uint8_t initTeensy, volatile uint32_t *millisecondTick)
//
if(firstCall == 1)
{
if(initTeensy)
if(initK64F)
_init_Teensyduino_internal_();
// Setup the pointer to the millisecond tick value updated by K64F interrupt.
@@ -543,7 +543,7 @@ void resetZ80(void)
//
__disable_irq();
pinOutputSet(Z80_RESET, LOW);
for(volatile uint32_t pulseWidth=0; pulseWidth < 200; pulseWidth++);
for(volatile uint32_t pulseWidth=0; pulseWidth < DEFAULT_RESET_PULSE_WIDTH; pulseWidth++);
pinHigh(Z80_RESET);
pinInput(Z80_RESET);
__enable_irq();
@@ -617,7 +617,7 @@ uint8_t reqMainboardBus(uint32_t timeout)
pinLow(Z80_RD);
pinLow(Z80_WR);
// On a Teensy3.5 K64F running at 120MHz this delay gives a pulsewidth of 760nS.
// On a K64F running at 120MHz this delay gives a pulsewidth of 760nS.
for(volatile uint32_t pulseWidth=0; pulseWidth < 1; pulseWidth++);
// Immediately return the RD/WR to HIGH to complete the ENABLE_BUS latch action.
@@ -794,7 +794,7 @@ uint8_t writeZ80Memory(uint16_t addr, uint8_t data)
// Start the write cycle, MREQ and WR go low.
pinLow(Z80_WR);
// On a Teensy3.5 K64F running at 120MHz this delay gives a pulsewidth of 760nS.
// On a K64F running at 120MHz this delay gives a pulsewidth of 760nS.
for(volatile uint32_t pulseWidth=0; pulseWidth < 4; pulseWidth++);
// Another wait loop check as the Z80 can assert wait at the time of Write or anytime before it is deasserted.
@@ -804,7 +804,7 @@ uint8_t writeZ80Memory(uint16_t addr, uint8_t data)
// Start the write cycle, MREQ and WR go low.
pinLow(Z80_WR);
// On a Teensy3.5 K64F running at 120MHz this delay gives a pulsewidth of 760nS.
// On a K64F running at 120MHz this delay gives a pulsewidth of 760nS.
// With the tranZPUter SW v2 boards, need to increase the write pulse width, alternatively wait until a positive edge on the CPU clock.
for(volatile uint32_t pulseWidth=0; pulseWidth < 3; pulseWidth++);
}
@@ -855,7 +855,7 @@ uint8_t readZ80Memory(uint16_t addr)
//
if(z80Control.ctrlMode == MAINBOARD_ACCESS)
{
// On a Teensy3.5 K64F running at 120MHz this delay gives a pulsewidth of 760nS. This gives time for the addressed device to present the data
// On a K64F running at 120MHz this delay gives a pulsewidth of 760nS. This gives time for the addressed device to present the data
// on the data bus.
for(volatile uint32_t pulseWidth=0; pulseWidth < 4; pulseWidth++);
@@ -910,7 +910,7 @@ uint8_t writeZ80IO(uint16_t addr, uint8_t data)
// Start the write cycle, MREQ and WR go low.
pinLow(Z80_WR);
// On a Teensy3.5 K64F running at 120MHz this delay gives a pulsewidth of 760nS.
// On a K64F running at 120MHz this delay gives a pulsewidth of 760nS.
for(volatile uint32_t pulseWidth=0; pulseWidth < 2; pulseWidth++);
// Another wait loop check as the Z80 can assert wait at the time of Write or anytime before it is deasserted.
@@ -953,12 +953,16 @@ uint8_t readZ80IO(uint16_t addr)
//
if(z80Control.ctrlMode == MAINBOARD_ACCESS)
{
// On a Teensy3.5 K64F running at 120MHz this delay gives a pulsewidth of 760nS. This gives time for the addressed device to present the data
// On a K64F running at 120MHz this delay gives a pulsewidth of 760nS. This gives time for the addressed device to present the data
// on the data bus.
//for(volatile uint32_t pulseWidth=0; pulseWidth < 2; pulseWidth++);
for(volatile uint32_t pulseWidth=0; pulseWidth < 2; pulseWidth++);
// A wait loop check as the Z80 can assert wait during the Read operation to request more time. Set a timeout in case of hardware lockup.
while((*ms - startTime) < 100 && pinGet(Z80_WAIT) == 0);
} else
{
// With the tranZPUter SW v2 boards, need to increase the read pulse width as the latch is synchronous, alternatively wait until a positive edge on the CPU clock.
for(volatile uint32_t pulseWidth=0; pulseWidth < 8; pulseWidth++);
}
// Fetch the data before deasserting the signals.
@@ -2032,7 +2036,7 @@ uint8_t loadBIOS(const char *biosFileName, uint8_t machineMode, uint32_t loadAdd
void loadTranZPUterDefaultROMS(void)
{
// Locals.
FRESULT result;
FRESULT result = 0;
// Start off by clearing active memory banks, the AS6C4008 chip holds random values at power on.
fillZ80Memory(0x000000, 0x10000, 0x00, 0); // TZFS and Sharp MZ80A mode.
@@ -2045,6 +2049,10 @@ void loadTranZPUterDefaultROMS(void)
result = loadBIOS(MZ_ROM_1Z_013A_40C, MZ700, MZ_MROM_ADDR);
break;
case MZ800:
//result = loadBIOS(MZ_ROM_1Z_013A_40C, MZ700, MZ_MROM_ADDR);
break;
case MZ80B:
result = loadBIOS(MZ_ROM_MZ80B_IPL, MZ700, MZ_MROM_ADDR);
break;
@@ -3509,7 +3517,7 @@ void processServiceRequest(void)
// Update the service control record address according to memory mode.
//
z80Control.svcControlAddr = getServiceAddr();
// Get the command and associated parameters.
copyFromZ80((uint8_t *)&svcControl, z80Control.svcControlAddr, TZSVC_CMD_SIZE, 0);
@@ -3594,92 +3602,63 @@ void processServiceRequest(void)
break;
// Load the 40 column version of the default host bios into memory.
case TZSVC_CMD_LOAD40BIOS:
switch(z80Control.hostType)
case TZSVC_CMD_LOAD40ABIOS:
loadBIOS(MZ_ROM_SA1510_40C, MZ80A, MZ_MROM_ADDR);
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != MZ80A)
{
case MZ700:
loadBIOS(MZ_ROM_1Z_013A_40C, MZ700, MZ_MROM_ADDR);
break;
case MZ80B:
loadBIOS(MZ_ROM_MZ80B_IPL, MZ700, MZ_MROM_ADDR);
break;
case MZ80A:
default:
loadBIOS(MZ_ROM_SA1510_40C, MZ80A, MZ_MROM_ADDR);
break;
// Change frequency to match Sharp MZ-80A
setZ80CPUFrequency(MZ_80A_CPU_FREQ, 1);
}
break;
// Load the 80 column version of the default host bios into memory.
case TZSVC_CMD_LOAD80BIOS:
switch(z80Control.hostType)
case TZSVC_CMD_LOAD80ABIOS:
loadBIOS(MZ_ROM_SA1510_80C, MZ80A, MZ_MROM_ADDR);
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != MZ80A)
{
case MZ700:
loadBIOS(MZ_ROM_1Z_013A_80C, MZ700, MZ_MROM_ADDR);
break;
case MZ80B:
loadBIOS(MZ_ROM_MZ80B_IPL, MZ700, MZ_MROM_ADDR);
break;
case MZ80A:
default:
loadBIOS(MZ_ROM_SA1510_80C, MZ80A, MZ_MROM_ADDR);
break;
// Change frequency to match Sharp MZ-80A
setZ80CPUFrequency(MZ_80A_CPU_FREQ, 1);
}
break;
// Load the 40 column MZ700 1Z-013A bios into memory for compatibility switch.
case TZSVC_CMD_LOAD700BIOS40:
if((status=loadZ80Memory((const char *)MZ_ROM_1Z_013A_40C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK)
loadBIOS(MZ_ROM_1Z_013A_40C, MZ700, MZ_MROM_ADDR);
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != MZ700)
{
printf("Error: Failed to load %s into tranZPUter memory.\n", MZ_ROM_1Z_013A_40C);
// Change frequency to match Sharp MZ-700
setZ80CPUFrequency(MZ_700_CPU_FREQ, 1);
}
// Change frequency to match Sharp MZ-700
setZ80CPUFrequency(MZ_700_CPU_FREQ, 1);
// Set the machine mode according to BIOS loaded.
z80Control.machineMode = MZ700;
// setup the IRQ's according to this machine.
setupIRQ();
break;
// Load the 80 column MZ700 1Z-013A bios into memory for compatibility switch.
case TZSVC_CMD_LOAD700BIOS80:
if((status=loadZ80Memory((const char *)MZ_ROM_1Z_013A_80C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK)
{
printf("Error: Failed to load %s into tranZPUter memory.\n", MZ_ROM_1Z_013A_80C);
}
loadBIOS(MZ_ROM_1Z_013A_80C, MZ700, MZ_MROM_ADDR);
// Change frequency to match Sharp MZ-700
setZ80CPUFrequency(MZ_700_CPU_FREQ, 1);
// Set the machine mode according to BIOS loaded.
z80Control.machineMode = MZ700;
// setup the IRQ's according to this machine.
setupIRQ();
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != MZ700)
{
// Change frequency to match Sharp MZ-700
setZ80CPUFrequency(MZ_700_CPU_FREQ, 1);
}
break;
// Load the MZ-80B IPL ROM into memory for compatibility switch.
case TZSVC_CMD_LOAD80BIPL:
if((status=loadZ80Memory((const char *)MZ_ROM_MZ80B_IPL, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK)
{
printf("Error: Failed to load %s into tranZPUter memory.\n", MZ_ROM_MZ80B_IPL);
}
loadBIOS(MZ_ROM_MZ80B_IPL, MZ80B, MZ_MROM_ADDR);
// Change frequency to match the Sharp MZ-80B
setZ80CPUFrequency(MZ_80B_CPU_FREQ, 1);
// Set the machine mode according to BIOS loaded.
z80Control.machineMode = MZ80B;
// setup the IRQ's according to this machine.
setupIRQ();
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != MZ80B)
{
// Change frequency to match Sharp MZ-80B
setZ80CPUFrequency(MZ_80B_CPU_FREQ, 1);
}
break;
// Load the CPM CCP+BDOS from file into the address given.
@@ -3753,7 +3732,7 @@ void processServiceRequest(void)
printf("WARNING: Unrecognised command:%02x\n", svcControl.cmd);
break;
}
// Update the status in the service control record then copy it across to the Z80.
//
svcControl.result = status;
@@ -3790,29 +3769,56 @@ uint8_t testTZFSAutoBoot(void)
void setHost(void)
{
// Locals.
uint8_t buf[4];
uint8_t cpldInfo;
// Copy the ID value from the host monitor so that we can identify the host type.
// Request the correct bus.
//
copyFromZ80(buf, HOST_MON_TEST_VECTOR, 1, 1);
if( reqTranZPUterBus(DEFAULT_BUSREQ_TIMEOUT) == 0)
{
// Setup the pins to perform an IO read operation.
//
setupSignalsForZ80Access(READ);
// Copy the ID value from the CPLD information register so that we can identify the host type.
//
cpldInfo = readZ80IO(IO_TZ_CPLDINFO);
// Release the bus to continue.
//
releaseZ80();
} else
{
printf("Failed to access tranZPUter bus to read CPLDINFO, defaulting to MZ80A\n");
cpldInfo = MZ80A;
}
// Setup the control variable to indicate type of host. This will affect processing of interrupts, BIOS loads etc.
//
switch(buf[0])
switch(cpldInfo & 0x07)
{
case MZ700_MONITOR_ID:
case MZ700:
z80Control.hostType = MZ700;
z80Control.machineMode = MZ700;
printf("Host Type: MZ-700\n");
break;
case MZ80B_MONITOR_ID:
case MZ800:
z80Control.hostType = MZ800;
z80Control.machineMode = MZ800;
printf("Host Type: MZ-800\n");
break;
case MZ80B:
case MZ2000:
z80Control.hostType = MZ80B;
z80Control.machineMode = MZ80B;
printf("Host Type: MZ-80B\n");
break;
case MZ80A_MONITOR_ID:
case MZ80A:
case MZ80K:
case MZ80C:
case MZ1200:
default:
z80Control.hostType = MZ80A;
z80Control.machineMode = MZ80A;
@@ -3820,6 +3826,17 @@ void setHost(void)
break;
}
// Report on video hardware.
//
if(cpldInfo & VIDEO_FPGA)
{
printf("FPGA video hardware detected.\n");
}
// Report on CPLD version.
//
printf("CPLD Version: %d\n", (cpldInfo & CPLD_VERSION) >> 5);
return;
}

View File

@@ -40,7 +40,8 @@
#define REFRESH_BYTE_COUNT 8 // This constant controls the number of bytes read/written to the z80 bus before a refresh cycle is needed.
#define RFSH_BYTE_CNT 256 // Number of bytes we can write before needing a full refresh for the DRAM.
#define HOST_MON_TEST_VECTOR 0x4 // Address in the host monitor to test to identify host type.
#define DEFAULT_BUSREQ_TIMEOUT 1000 // Timeout for a Z80 Bus request operation in milliseconds.
#define DEFAULT_BUSREQ_TIMEOUT 5000 // Timeout for a Z80 Bus request operation in milliseconds.
#define DEFAULT_RESET_PULSE_WIDTH 1000 // Pulse width of a reset signal in |K4F clock ticks.
// tranZPUter Memory Modes - select one of the 32 possible memory models using these constants.
//
@@ -76,8 +77,19 @@
#define IO_TZ_CLKSELRD 0x66 // Read the status of the clock select, ie. which clock is connected to the CPU.
#define IO_TZ_SVCREQ 0x68 // Service request from the Z80 to be provided by the K64F.
#define IO_TZ_SYSREQ 0x6A // System request from the Z80 to be provided by the K64F.
#define IO_TZ_CPLDCFG 0x6E // Version 2.1 CPLD configuration register.
#define IO_TZ_CPLDSTATUS 0x6E // Version 2.1 CPLD status register.
#define IO_TZ_CPLDINFO 0x6F // Version 2.1 CPLD version information register.
#define IO_TZ_SYSCTRL 0xF0 // System board control register. [2:0] - 000 MZ80A Mode, 2MHz CPU/Bus, 001 MZ80B Mode, 4MHz CPU/Bus, 010 MZ700 Mode, 3.54MHz CPU/Bus.
#define IO_TZ_GRAMMODE 0xF4 // MZ80B Graphics mode. Bit 0 = 0, Write to Graphics RAM I, Bit 0 = 1, Write to Graphics RAM II. Bit 1 = 1, blend Graphics RAM I output on display, Bit 2 = 1, blend Graphics RAM II output on display.
#define IO_TZ_VMCTRL 0xF8 // Video Module control register. [2:0] - 000 (default) = MZ80A, 001 = MZ-700, 010 = MZ800, 011 = MZ80B, 100 = MZ80K, 101 = MZ80C, 110 = MZ1200, 111 = MZ2000. [3] = 0 - 40 col, 1 - 80 col.
#define IO_TZ_VMGRMODE 0xF9 // Video Module graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), 5=GRAM Output Enable, 4 = VRAM Output Enable, 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), 1/0=Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
#define IO_TZ_VMREDMASK 0xFA // Video Module Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMGREENMASK 0xFB // Video Module Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMBLUEMASK 0xFC // Video Module Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMPAGE 0xFD // Video Module memory page register. [1:0] switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. Bits [1:0] = page, 00 = off, 01 = Red, 10 = Green, 11 = Blue. This overrides all MZ700/MZ80B page switching functions. [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF.
// Sharp MZ80A constants.
// Sharp MZ constants.
//
#define MZ_MROM_ADDR 0x0000 // Monitor ROM start address.
#define MZ_MROM_STACK_ADDR 0x1000 // Monitor ROM start stack address.
@@ -141,8 +153,8 @@
#define TZSVC_CMD_SAVEFILE 0x09 // Service command to save a file directly from tranZPUter memory.
#define TZSVC_CMD_ERASEFILE 0x0a // Service command to erase a file on the SD card.
#define TZSVC_CMD_CHANGEDIR 0x0b // Service command to change active directory on the SD card.
#define TZSVC_CMD_LOAD40BIOS 0x20 // Service command requesting that the 40 column version of the SA1510 BIOS is loaded.
#define TZSVC_CMD_LOAD80BIOS 0x21 // Service command requesting that the 80 column version of the SA1510 BIOS is loaded.
#define TZSVC_CMD_LOAD40ABIOS 0x20 // Service command requesting that the 40 column version of the SA1510 BIOS is loaded.
#define TZSVC_CMD_LOAD80ABIOS 0x21 // Service command requesting that the 80 column version of the SA1510 BIOS is loaded.
#define TZSVC_CMD_LOAD700BIOS40 0x22 // Service command requesting that the MZ700 1Z-013A 40 column BIOS is loaded.
#define TZSVC_CMD_LOAD700BIOS80 0x23 // Service command requesting that the MZ700 1Z-013A 80 column patched BIOS is loaded.
#define TZSVC_CMD_LOAD80BIPL 0x24 // Service command requesting the MZ-80B IPL is loaded.
@@ -405,20 +417,24 @@ enum VIDEO_FRAMES {
WORKING = 1
};
// Values in the host monitor ROM to identify a machine type.
//
enum MACHINE_MONITOR_ID {
MZ80A_MONITOR_ID = 0xa8,
MZ700_MONITOR_ID = 0xe6,
MZ80B_MONITOR_ID = 0x03
};
// Possible machines the tranZPUter can be hosted on and can emulate.
//
enum MACHINE_TYPES {
MZ80A = 0,
MZ700 = 1,
MZ80B = 2
MZ80K = 0x00, // Machine = MZ-80K.
MZ80C = 0x01, // Machine = MZ-80C.
MZ1200 = 0x02, // Machine = MZ-1200.
MZ80A = 0x03, // Machine = MZ-80A.
MZ700 = 0x04, // Machine = MZ-700.
MZ800 = 0x05, // Machine = MZ-800.
MZ80B = 0x06, // Machine = MZ-80B.
MZ2000 = 0x07 // Machine = MZ-2000.
};
// Get and Set flags within the CPLD config and status registers.
//
enum CPLD_FLAGS {
VIDEO_FPGA = 0x08, // Bit to test for available functionality or enabling of the FPGA video hardware.
CPLD_VERSION = 0xE0 // CPLD version mask bits.
};
// Types of file which have handlers and can be processed.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -253,6 +253,9 @@ void tranZPUterControl(void)
//
if(isZ80Reset())
{
// Reset Z80 - This is to extend the reset signal to allow all the CPLD's/FPGA's to sync.
resetZ80();
// Reload the memory on the tranZPUter to boot default.
loadTranZPUterDefaultROMS();