Commit before merge of v2
This commit is contained in:
@@ -123,6 +123,27 @@ void testSixtyBug(void)
|
||||
}
|
||||
}
|
||||
|
||||
void testVRAMLocation(void)
|
||||
{
|
||||
printf("Requesting Z80 BUS and Mainboard access\n");
|
||||
if(reqMainboardBus(100) == 0)
|
||||
{
|
||||
setupSignalsForZ80Access(READ);
|
||||
|
||||
for(uint32_t idx=0; idx < 0xFFFFFFFF; idx++)
|
||||
{
|
||||
uint8_t dataV = readZ80Memory(0xD000);
|
||||
uint8_t dataA = readZ80Memory(0xD800);
|
||||
printf("%02x %02x\r", dataV, dataA);
|
||||
}
|
||||
releaseZ80();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to obtain the Z80 bus.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Main entry and start point of a zOS/ZPUTA Application. Only 2 parameters are catered for and a 32bit return code, additional parameters can be added by changing the appcrt0.s
|
||||
// startup code to add them to the stack prior to app() call.
|
||||
@@ -148,6 +169,7 @@ uint32_t app(uint32_t param1, uint32_t param2)
|
||||
// _init_Teensyduino_internal_();
|
||||
// setupZ80Pins(1, G->millis);
|
||||
//
|
||||
testVRAMLocation();
|
||||
testSixtyBug();
|
||||
|
||||
printf("Loading Monitor ROM\n");
|
||||
|
||||
@@ -134,7 +134,6 @@ static void __attribute((naked, noinline)) irqPortE_dummy(void)
|
||||
asm volatile(" pop {r0-r1,pc} \n");
|
||||
|
||||
}
|
||||
#if 0
|
||||
static void __attribute((naked, noinline)) irqPortD_dummy(void)
|
||||
{
|
||||
// Save register we use.
|
||||
@@ -149,7 +148,6 @@ static void __attribute((naked, noinline)) irqPortD_dummy(void)
|
||||
asm volatile(" pop {r0-r1,pc} \n");
|
||||
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
static void __attribute((naked, noinline)) irqPortC_dummy(void)
|
||||
{
|
||||
@@ -965,6 +963,28 @@ static void setupIRQ(void)
|
||||
return;
|
||||
}
|
||||
|
||||
// Method to remove the IRQ vectors and disable them.
|
||||
// This method is called when the I/O processor goes 'silent', ie. not interacting with the host.
|
||||
//
|
||||
static void disableIRQ(void)
|
||||
{
|
||||
__disable_irq();
|
||||
|
||||
// Vectors to dummy routines.
|
||||
_VectorsRam[IRQ_PORTD + 16] = irqPortD_dummy;
|
||||
_VectorsRam[IRQ_PORTE + 16] = irqPortE_dummy;
|
||||
|
||||
// Remove the interrupts.
|
||||
removeIRQ(TZ_SVCREQ);
|
||||
removeIRQ(TZ_SYSREQ);
|
||||
removeIRQ(Z80_IORQ);
|
||||
removeIRQ(Z80_RESET);
|
||||
|
||||
__enable_irq();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Method to restore the interrupt vector when the pin mode is changed and restored to default input mode.
|
||||
//
|
||||
static void restoreIRQ(void)
|
||||
@@ -1136,6 +1156,7 @@ void setupZ80Pins(uint8_t initTeensy, volatile uint32_t *millisecondTick)
|
||||
z80Control.runCtrlLatch = readCtrlLatch();
|
||||
z80Control.ctrlMode = Z80_RUN;
|
||||
z80Control.busDir = TRISTATE;
|
||||
z80Control.hostType = MZ80A;
|
||||
z80Control.machineMode = MZ80A;
|
||||
|
||||
// Final part of first call initialisation, now that the pins are configured, setup the interrupts.
|
||||
@@ -1163,13 +1184,13 @@ void setupZ80Pins(uint8_t initTeensy, volatile uint32_t *millisecondTick)
|
||||
|
||||
// Debug to quickly find out addresses of GPIO pins.
|
||||
#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
|
||||
printf("%s, Set=%08lx, Clear=%08lx\n", "CTL_BUSRQ", digital_pin_to_info_PGM[(CTL_BUSRQ_PIN)].reg, digital_pin_to_info_PGM[(CTL_BUSRQ_PIN)].reg + 64 );
|
||||
printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_WAIT", digital_pin_to_info_PGM[(Z80_WAIT_PIN)].reg, digital_pin_to_info_PGM[(Z80_WAIT_PIN)].reg + 64 );
|
||||
printf("%s, Set=%08lx, Clear=%08lx\n", "CTL_BUSACK", digital_pin_to_info_PGM[(CTL_BUSACK_PIN)].reg, digital_pin_to_info_PGM[(CTL_BUSACK_PIN)].reg + 64 );
|
||||
printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_IORQ", digital_pin_to_info_PGM[(Z80_IORQ_PIN)].reg, digital_pin_to_info_PGM[(Z80_IORQ_PIN)].reg + 64 );
|
||||
printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_MREQ", digital_pin_to_info_PGM[(Z80_MREQ_PIN)].reg, digital_pin_to_info_PGM[(Z80_MREQ_PIN)].reg + 64 );
|
||||
printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_RD", digital_pin_to_info_PGM[(Z80_RD_PIN)].reg, digital_pin_to_info_PGM[(Z80_RD_PIN)].reg + 64 );
|
||||
printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_WR", digital_pin_to_info_PGM[(Z80_WR_PIN)].reg, digital_pin_to_info_PGM[(Z80_WR_PIN)].reg + 64 );
|
||||
//printf("%s, Set=%08lx, Clear=%08lx\n", "CTL_BUSRQ", digital_pin_to_info_PGM[(CTL_BUSRQ_PIN)].reg, digital_pin_to_info_PGM[(CTL_BUSRQ_PIN)].reg + 64 );
|
||||
//printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_WAIT", digital_pin_to_info_PGM[(Z80_WAIT_PIN)].reg, digital_pin_to_info_PGM[(Z80_WAIT_PIN)].reg + 64 );
|
||||
//printf("%s, Set=%08lx, Clear=%08lx\n", "CTL_BUSACK", digital_pin_to_info_PGM[(CTL_BUSACK_PIN)].reg, digital_pin_to_info_PGM[(CTL_BUSACK_PIN)].reg + 64 );
|
||||
//printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_IORQ", digital_pin_to_info_PGM[(Z80_IORQ_PIN)].reg, digital_pin_to_info_PGM[(Z80_IORQ_PIN)].reg + 64 );
|
||||
//printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_MREQ", digital_pin_to_info_PGM[(Z80_MREQ_PIN)].reg, digital_pin_to_info_PGM[(Z80_MREQ_PIN)].reg + 64 );
|
||||
//printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_RD", digital_pin_to_info_PGM[(Z80_RD_PIN)].reg, digital_pin_to_info_PGM[(Z80_RD_PIN)].reg + 64 );
|
||||
//printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_WR", digital_pin_to_info_PGM[(Z80_WR_PIN)].reg, digital_pin_to_info_PGM[(Z80_WR_PIN)].reg + 64 );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1398,6 +1419,23 @@ uint8_t writeZ80Memory(uint16_t addr, uint8_t data)
|
||||
// Locals.
|
||||
uint32_t startTime = *ms;
|
||||
|
||||
// Video RAM has a blanking circuit which causes the Z80 to enter a WAIT state. The K64F can only read the WAIT state and sometimes will miss it
|
||||
// so wait for the start of a blanking period and write.
|
||||
//
|
||||
//if(z80Control.ctrlMode == MAINBOARD_ACCESS && addr >= 0xD000 && addr < 0xE000)
|
||||
//{
|
||||
// uint8_t blnkDet, blnkDetLast;
|
||||
// blnkDet = 0x80;
|
||||
// setZ80Direction(READ);
|
||||
// do {
|
||||
// blnkDetLast = blnkDet;
|
||||
// blnkDet = readZ80Memory(0xE008) & 0x80;
|
||||
// } while(!(blnkDet == 0x80 && blnkDetLast == 0x00));
|
||||
// for(volatile uint32_t pulseWidth=0; pulseWidth < 10; pulseWidth++);
|
||||
// setZ80Direction(WRITE);
|
||||
// startTime = *ms;
|
||||
//}
|
||||
|
||||
// Set the data and address on the bus.
|
||||
//
|
||||
setZ80Addr(addr);
|
||||
@@ -1424,7 +1462,7 @@ uint8_t writeZ80Memory(uint16_t addr, uint8_t data)
|
||||
#if TZBOARD == 100 || TZBOARD == 110
|
||||
for(volatile uint32_t pulseWidth=0; pulseWidth < 4; pulseWidth++);
|
||||
#elif TZBOARD == 200 || TZBOARD == 210
|
||||
for(volatile uint32_t pulseWidth=0; pulseWidth < 5; pulseWidth++);
|
||||
for(volatile uint32_t pulseWidth=0; pulseWidth < 4; pulseWidth++);
|
||||
#endif
|
||||
|
||||
// Another wait loop check as the Z80 can assert wait at the time of Write or anytime before it is deasserted.
|
||||
@@ -1459,20 +1497,36 @@ uint8_t readZ80Memory(uint16_t addr)
|
||||
uint32_t startTime = *ms;
|
||||
uint8_t data;
|
||||
|
||||
// Video RAM has a blanking circuit which causes the Z80 to enter a WAIT state. The K64F can only read the WAIT state and sometimes will miss it
|
||||
// so wait for the start of a blanking period and read.
|
||||
//
|
||||
if(z80Control.ctrlMode == MAINBOARD_ACCESS && addr >= 0xD000 && addr < 0xE000)
|
||||
{
|
||||
uint8_t blnkDet, blnkDetLast;
|
||||
blnkDet = 0x80;
|
||||
do {
|
||||
blnkDetLast = blnkDet;
|
||||
blnkDet = readZ80Memory(0xE008) & 0x80;
|
||||
} while(!(blnkDet == 0x80 && blnkDetLast == 0x00));
|
||||
for(volatile uint32_t pulseWidth=0; pulseWidth < 10; pulseWidth++);
|
||||
startTime = *ms;
|
||||
}
|
||||
|
||||
// Set the address on the bus and assert MREQ and RD.
|
||||
//
|
||||
setZ80Addr(addr);
|
||||
|
||||
// Setup time before applying control signals.
|
||||
for(volatile uint32_t pulseWidth = 0; pulseWidth < 3; pulseWidth++);
|
||||
pinLow(Z80_MREQ);
|
||||
pinLow(Z80_RD);
|
||||
for(volatile uint32_t pulseWidth = 0; pulseWidth < 3; pulseWidth++);
|
||||
|
||||
// Different logic according to what is being accessed. The mainboard needs to uphold timing and WAIT signals whereas the Tranzputer logic has no wait
|
||||
// signals and faster memory.
|
||||
//
|
||||
if(z80Control.ctrlMode == MAINBOARD_ACCESS)
|
||||
{
|
||||
// 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);
|
||||
|
||||
// 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 the data bus.
|
||||
#if TZBOARD == 100 || TZBOARD == 110
|
||||
@@ -1481,6 +1535,9 @@ uint8_t readZ80Memory(uint16_t addr)
|
||||
#elif TZBOARD == 200 || TZBOARD == 210
|
||||
for(volatile uint32_t pulseWidth=0; pulseWidth < 4; pulseWidth++);
|
||||
#endif
|
||||
|
||||
// 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
|
||||
{
|
||||
// On the tranZPUter v1.1, because of reorganisation of the signals, the time to process is less and so the pulse width under v1.0 is insufficient.
|
||||
@@ -1712,7 +1769,7 @@ void setCtrlLatch(uint8_t latchVal)
|
||||
{
|
||||
// Gain control of the bus then set the latch value.
|
||||
//
|
||||
if(reqTranZPUterBus(100) == 0)
|
||||
if(reqTranZPUterBus(500) == 0)
|
||||
{
|
||||
// Setup the pins to perform a write operation.
|
||||
//
|
||||
@@ -1749,7 +1806,7 @@ uint32_t setZ80CPUFrequency(float frequency, uint8_t action)
|
||||
{
|
||||
// Gain control of the bus to change the CPU frequency latch.
|
||||
//
|
||||
if(reqTranZPUterBus(100) == 0)
|
||||
if(reqTranZPUterBus(500) == 0)
|
||||
{
|
||||
// Setup the pins to perform a write operation.
|
||||
//
|
||||
@@ -1779,7 +1836,7 @@ uint8_t copyFromZ80(uint8_t *dst, uint32_t src, uint32_t size, uint8_t mainBoard
|
||||
|
||||
// Request the correct bus.
|
||||
//
|
||||
if( (mainBoard == 0 && reqTranZPUterBus(100) == 0) || (mainBoard != 0 && reqMainboardBus(100) == 0) )
|
||||
if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) )
|
||||
{
|
||||
// Setup the pins to perform a read operation (after setting the latch to starting value).
|
||||
//
|
||||
@@ -1838,7 +1895,7 @@ uint8_t copyToZ80(uint32_t dst, uint8_t *src, uint32_t size, uint8_t mainBoard)
|
||||
|
||||
// Request the correct bus.
|
||||
//
|
||||
if( (mainBoard == 0 && reqTranZPUterBus(100) == 0) || (mainBoard != 0 && reqMainboardBus(100) == 0) )
|
||||
if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) )
|
||||
{
|
||||
// Setup the pins to perform a write operation.
|
||||
//
|
||||
@@ -1886,7 +1943,7 @@ void fillZ80Memory(uint32_t addr, uint32_t size, uint8_t data, uint8_t mainBoard
|
||||
// Locals.
|
||||
uint8_t upperAddrBits = 0;
|
||||
|
||||
if( (mainBoard == 0 && reqTranZPUterBus(100) == 0) || (mainBoard != 0 && reqMainboardBus(100) == 0) )
|
||||
if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) )
|
||||
{
|
||||
// Setup the pins to perform a read operation (after setting the latch to starting value).
|
||||
//
|
||||
@@ -1929,7 +1986,7 @@ void captureVideoFrame(enum VIDEO_FRAMES frame, uint8_t noAttributeFrame)
|
||||
{
|
||||
// Locals.
|
||||
|
||||
if(reqMainboardBus(100) == 0)
|
||||
if(reqMainboardBus(500) == 0)
|
||||
{
|
||||
// Setup the pins to perform a read operation (after setting the latch to starting value).
|
||||
//
|
||||
@@ -1976,7 +2033,7 @@ void refreshVideoFrame(enum VIDEO_FRAMES frame, uint8_t scrolHome, uint8_t noAtt
|
||||
{
|
||||
// Locals.
|
||||
|
||||
if(reqMainboardBus(100) == 0)
|
||||
if(reqMainboardBus(500) == 0)
|
||||
{
|
||||
// Setup the pins to perform a write operation.
|
||||
//
|
||||
@@ -2163,10 +2220,10 @@ FRESULT loadZ80Memory(const char *src, uint32_t fileOffset, uint32_t addr, uint3
|
||||
// Request the board according to the mainboard flag, mainboard = 1 then the mainboard is controlled otherwise the tranZPUter board.
|
||||
if(mainBoard == 0)
|
||||
{
|
||||
reqTranZPUterBus(100);
|
||||
reqTranZPUterBus(500);
|
||||
} else
|
||||
{
|
||||
reqMainboardBus(100);
|
||||
reqMainboardBus(500);
|
||||
}
|
||||
|
||||
// If successful, setup the control pins for upload mode.
|
||||
@@ -2350,7 +2407,7 @@ FRESULT saveZ80Memory(const char *dst, uint32_t addr, uint32_t size, t_svcDirEnt
|
||||
|
||||
if(!fr0)
|
||||
{
|
||||
if( (mainBoard == 0 && reqTranZPUterBus(100) == 0) || (mainBoard != 0 && reqMainboardBus(100) == 0) )
|
||||
if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) )
|
||||
{
|
||||
// Setup the pins to perform a read operation (after setting the latch to starting value).
|
||||
//
|
||||
@@ -2444,7 +2501,7 @@ int memoryDumpZ80(uint32_t memaddr, uint32_t memsize, uint32_t dispaddr, uint8_t
|
||||
|
||||
// Request the correct bus.
|
||||
//
|
||||
if( (mainBoard == 0 && reqTranZPUterBus(100) == 0) || (mainBoard != 0 && reqMainboardBus(100) == 0) )
|
||||
if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) )
|
||||
{
|
||||
// Setup the pins to perform a read operation (after setting the latch to starting value).
|
||||
//
|
||||
@@ -2631,6 +2688,31 @@ void convertSharpFilenameToAscii(char *dst, char *src, uint8_t size)
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// Method to load a BIOS into the tranZPUter and configure for a particular host type.
|
||||
//
|
||||
uint8_t loadBIOS(const char *biosFileName, uint8_t machineMode, uint32_t loadAddr)
|
||||
{
|
||||
// Locals.
|
||||
uint8_t result = FR_OK;
|
||||
|
||||
// Load up the given BIOS into tranZPUter memory.
|
||||
if((result=loadZ80Memory(biosFileName, 0, loadAddr, 0, 0, 0, 1)) != FR_OK)
|
||||
{
|
||||
printf("Error: Failed to load %s into tranZPUter memory.\n", biosFileName);
|
||||
} else
|
||||
{
|
||||
// Change frequency to default.
|
||||
setZ80CPUFrequency(0, 4);
|
||||
|
||||
// Set the machine mode according to BIOS loaded.
|
||||
z80Control.machineMode = machineMode;
|
||||
|
||||
// setup the IRQ's according to this machine.
|
||||
setupIRQ();
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Method to load the default ROMS into the tranZPUter RAM ready for start.
|
||||
// If the autoboot flag is set, perform autoboot by wiping the STACK area
|
||||
// of the SA1510 - this has the effect of JP 00000H.
|
||||
@@ -2644,10 +2726,21 @@ void loadTranZPUterDefaultROMS(void)
|
||||
fillZ80Memory(0x000000, 0x10000, 0x00, 0); // TZFS and Sharp MZ80A mode.
|
||||
fillZ80Memory(0x040000, 0x20000, 0x00, 0); // CPM Mode.
|
||||
|
||||
// Now load the necessary images into memory.
|
||||
if((result=loadZ80Memory((const char *)MZ_ROM_SA1510_40C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK)
|
||||
// Now load the default BIOS into memory for the host type.
|
||||
switch(z80Control.hostType)
|
||||
{
|
||||
printf("Error: Failed to load %s into tranZPUter memory.\n", MZ_ROM_SA1510_40C);
|
||||
case MZ700:
|
||||
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;
|
||||
|
||||
case MZ80A:
|
||||
default:
|
||||
result = loadBIOS(MZ_ROM_SA1510_40C, MZ80A, MZ_MROM_ADDR);
|
||||
break;
|
||||
}
|
||||
if(!result && (result=loadZ80Memory((const char *)MZ_ROM_TZFS, 0, MZ_UROM_ADDR, 0x1800, 0, 0, 1) != FR_OK))
|
||||
{
|
||||
@@ -2696,7 +2789,7 @@ uint8_t setZ80SvcStatus(uint8_t status)
|
||||
|
||||
// Request the tranZPUter bus.
|
||||
//
|
||||
if(reqTranZPUterBus(100) == 0)
|
||||
if(reqTranZPUterBus(500) == 0)
|
||||
{
|
||||
// Setup the pins to perform a write operation.
|
||||
//
|
||||
@@ -4188,41 +4281,45 @@ void processServiceRequest(void)
|
||||
status=svcCacheDir((const char *)svcControl.directory, svcControl.fileType, 0);
|
||||
break;
|
||||
|
||||
// Load the 40 column version of the SA1510 bios into memory.
|
||||
// Load the 40 column version of the default host bios into memory.
|
||||
case TZSVC_CMD_LOAD40BIOS:
|
||||
if((status=loadZ80Memory((const char *)MZ_ROM_SA1510_40C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK)
|
||||
switch(z80Control.hostType)
|
||||
{
|
||||
printf("Error: Failed to load %s into tranZPUter memory.\n", MZ_ROM_SA1510_40C);
|
||||
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 default.
|
||||
setZ80CPUFrequency(MZ_80A_CPU_FREQ, 2);
|
||||
|
||||
// Set the machine mode according to BIOS loaded.
|
||||
z80Control.machineMode = MZ80A;
|
||||
|
||||
// setup the IRQ's according to this machine.
|
||||
setupIRQ();
|
||||
break;
|
||||
|
||||
// Load the 80 column version of the SA1510 bios into memory.
|
||||
// Load the 80 column version of the default host bios into memory.
|
||||
case TZSVC_CMD_LOAD80BIOS:
|
||||
if((status=loadZ80Memory((const char *)MZ_ROM_SA1510_80C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK)
|
||||
switch(z80Control.hostType)
|
||||
{
|
||||
printf("Error: Failed to load %s into tranZPUter memory.\n", MZ_ROM_SA1510_80C);
|
||||
}
|
||||
|
||||
// Change frequency to default.
|
||||
setZ80CPUFrequency(MZ_80A_CPU_FREQ, 2);
|
||||
|
||||
// Set the machine mode according to BIOS loaded.
|
||||
z80Control.machineMode = MZ80A;
|
||||
case MZ700:
|
||||
loadBIOS(MZ_ROM_1Z_013A_80C, MZ700, MZ_MROM_ADDR);
|
||||
break;
|
||||
|
||||
// setup the IRQ's according to this machine.
|
||||
setupIRQ();
|
||||
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;
|
||||
}
|
||||
break;
|
||||
|
||||
// Load the 40 column MZ700 1Z-013A bios into memory.
|
||||
// Load the 40 column MZ700 1Z-013A bios into memory for compatibility switch.
|
||||
case TZSVC_CMD_LOAD700BIOS40:
|
||||
#if TZBOARD == 100 || TZBOARD == 110
|
||||
if((status=loadZ80Memory((const char *)MZ_ROM_1Z_013A_KM_40C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK)
|
||||
@@ -4243,7 +4340,7 @@ void processServiceRequest(void)
|
||||
setupIRQ();
|
||||
break;
|
||||
|
||||
// Load the 80 column MZ700 1Z-013A bios into memory.
|
||||
// Load the 80 column MZ700 1Z-013A bios into memory for compatibility switch.
|
||||
case TZSVC_CMD_LOAD700BIOS80:
|
||||
#if TZBOARD == 100 || TZBOARD == 110
|
||||
if((status=loadZ80Memory((const char *)MZ_ROM_1Z_013A_KM_80C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK)
|
||||
@@ -4264,7 +4361,7 @@ void processServiceRequest(void)
|
||||
setupIRQ();
|
||||
break;
|
||||
|
||||
// Load the MZ-80B IPL ROM into memory.
|
||||
// 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)
|
||||
{
|
||||
@@ -4327,6 +4424,27 @@ void processServiceRequest(void)
|
||||
svcControl.cpuFreq = (uint16_t)(actualFreq / 1000);
|
||||
break;
|
||||
|
||||
// Command to exit from TZFS and return machine to original mode.
|
||||
case TZSVC_CMD_EXIT:
|
||||
// Disable secondary frequency.
|
||||
setZ80CPUFrequency(0, 4);
|
||||
|
||||
// Set the memory model to ORIGinal.
|
||||
setCtrlLatch(TZMM_ORIG);
|
||||
|
||||
// Clear the stack and monitor variable area as DRAM wont have been refreshed so will contain garbage.
|
||||
fillZ80Memory(MZ_MROM_STACK_ADDR, MZ_MROM_STACK_SIZE, 0x00, 1);
|
||||
|
||||
// Set to refresh mode just in case the I/O processor performs any future action in silent mode!
|
||||
z80Control.disableRefresh = 0;
|
||||
|
||||
// Now reset the machine so everything starts as power on.
|
||||
resetZ80();
|
||||
|
||||
// Disable the interrupts so no further service processing.
|
||||
disableIRQ();
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("WARNING: Unrecognised command:%02x\n", svcControl.cmd);
|
||||
break;
|
||||
@@ -4362,6 +4480,45 @@ uint8_t testTZFSAutoBoot(void)
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Method to identify the type of host the tranZPUter SW is running on. Originally it was only the MZ80A but the scope has expanded
|
||||
// to the MZ-700 and MZ-80B and potentially a plethora of other machines in the future.
|
||||
//
|
||||
void setHost(void)
|
||||
{
|
||||
// Locals.
|
||||
uint8_t buf[4];
|
||||
|
||||
// Copy the ID value from the host monitor so that we can identify the host type.
|
||||
//
|
||||
copyFromZ80(buf, HOST_MON_TEST_VECTOR, 1, 1);
|
||||
|
||||
// Setup the control variable to indicate type of host. This will affect processing of interrupts, BIOS loads etc.
|
||||
//
|
||||
switch(buf[0])
|
||||
{
|
||||
case MZ700_MONITOR_ID:
|
||||
z80Control.hostType = MZ700;
|
||||
z80Control.machineMode = MZ700;
|
||||
printf("Host Type: MZ-700\n");
|
||||
break;
|
||||
|
||||
case MZ80B_MONITOR_ID:
|
||||
z80Control.hostType = MZ80B;
|
||||
z80Control.machineMode = MZ80B;
|
||||
printf("Host Type: MZ-80B\n");
|
||||
break;
|
||||
|
||||
case MZ80A_MONITOR_ID:
|
||||
default:
|
||||
z80Control.hostType = MZ80A;
|
||||
z80Control.machineMode = MZ80A;
|
||||
printf("Host Type: MZ-80A\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Method to configure the hardware and events to operate the tranZPUter SW upgrade.
|
||||
//
|
||||
void setupTranZPUter(void)
|
||||
@@ -4369,6 +4526,12 @@ void setupTranZPUter(void)
|
||||
// Setup the pins to default mode and configure IRQ's.
|
||||
setupZ80Pins(0, &systick_millis_count);
|
||||
|
||||
// Check to see which monitor is installed to determine the host type.
|
||||
setHost();
|
||||
|
||||
// Reset the interrupts so they take into account the current host rather than the default.
|
||||
setupIRQ();
|
||||
|
||||
// Check to see if autoboot is needed.
|
||||
osControl.tzAutoBoot = testTZFSAutoBoot();
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
// Configurable constants.
|
||||
//
|
||||
//#define DECODE_Z80_IO 3 // Flag to enable code, via interrupt, to capture Z80 actions on I/O ports an Memory mapped I/O.
|
||||
//#define DECODE_Z80_IO 3 // Flag to enable code, via interrupt, to capture Z80 actions on I/O ports an Memory mapped I/O.
|
||||
// 0 = No code other than direct service request interrupts.
|
||||
// 1 = Decode Z80 I/O address operations.
|
||||
// 2 = Decode Z80 I/O operations with data.
|
||||
@@ -44,6 +44,7 @@
|
||||
#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 TZBOARD 210 // tranZPUter SW Hardware versions - v1.0 = 110, v1.1 = 110, v2.0 = 200 and v2.1 = 210
|
||||
#define HOST_MON_TEST_VECTOR 0x4 // Address in the host monitor to test to identify host type.
|
||||
|
||||
// tranZPUter Memory Modes - select one of the 32 possible memory models using these constants.
|
||||
//
|
||||
@@ -156,6 +157,7 @@
|
||||
#define TZSVC_CMD_CPU_BASEFREQ 0x40 // Service command to switch to the mainboard frequency.
|
||||
#define TZSVC_CMD_CPU_ALTFREQ 0x41 // Service command to switch to the alternate frequency provided by the K64F.
|
||||
#define TZSVC_CMD_CPU_CHGFREQ 0x42 // Service command to set the alternate frequency in hertz.
|
||||
#define TZSVC_CMD_EXIT 0x7F // Service command to terminate TZFS and restart the machine in original mode.
|
||||
#define TZSVC_DEFAULT_MZF_DIR "MZF" // Default directory where MZF files are stored.
|
||||
#define TZSVC_DEFAULT_CAS_DIR "CAS" // Default directory where BASIC CASsette files are stored.
|
||||
#define TZSVC_DEFAULT_BAS_DIR "BAS" // Default directory where BASIC text files are stored.
|
||||
@@ -411,9 +413,17 @@ enum VIDEO_FRAMES {
|
||||
WORKING = 1
|
||||
};
|
||||
|
||||
// Possible machines the tranZPUter can emulate.
|
||||
// Values in the host monitor ROM to identify a machine type.
|
||||
//
|
||||
enum MACHINE_MODE {
|
||||
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
|
||||
@@ -519,8 +529,8 @@ typedef struct {
|
||||
|
||||
enum CTRL_MODE ctrlMode; // Mode of control, ie normal Z80 Running, controlling mainboard, controlling tranZPUter.
|
||||
enum BUS_DIRECTION busDir; // Direction the bus has been configured for.
|
||||
|
||||
enum MACHINE_MODE machineMode; // Machine compatibility, 0 = Sharp MZ-80A, 1 = MZ-700, 2 = MZ-80B
|
||||
enum MACHINE_TYPES hostType; // The underlying host machine, 0 = Sharp MZ-80A, 1 = MZ-700, 2 = MZ-80B
|
||||
enum MACHINE_TYPES machineMode; // Machine compatibility, 0 = Sharp MZ-80A, 1 = MZ-700, 2 = MZ-80B
|
||||
t_mz700 mz700; // MZ700 emulation control to detect IO commands and adjust the memory map accordingly.
|
||||
t_mz80b mz80b; // MZ-80B emulation control to detect IO commands and adjust the memory map and I/O forwarding accordingly.
|
||||
|
||||
@@ -675,9 +685,11 @@ uint8_t svcReadCPMDrive(void);
|
||||
uint8_t svcWriteCPMDrive(void);
|
||||
uint32_t getServiceAddr(void);
|
||||
void processServiceRequest(void);
|
||||
uint8_t loadBIOS(const char *biosFileName, uint8_t machineMode, uint32_t loadAddr);
|
||||
void loadTranZPUterDefaultROMS(void);
|
||||
void tranZPUterControl(void);
|
||||
uint8_t testTZFSAutoBoot(void);
|
||||
void setHost(void);
|
||||
void setupTranZPUter(void);
|
||||
|
||||
#if defined __APP__
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user