Updates for v2.1 of the tranZPUter board

This commit is contained in:
Philip Smart
2020-07-29 14:02:28 +01:00
parent 2f8b80ccb5
commit 29116f8b3f
12 changed files with 119 additions and 16 deletions

2
.gitignore vendored
View File

@@ -72,3 +72,5 @@ zOS/*.s
zputa/*.i
zputa/*.ii
zputa/*.s
zOS/main.save

View File

@@ -8,7 +8,10 @@
// Credits:
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
//
// History: May 2020 - Initial write of the TranZPUter software.
// History: May 2020 - Initial write of the TranZPUter software.
// July 2020 - Another test, a bug with the VHDL on the v2.1 tranZPUter board, so
// needed to output a constant memory mode. The bug turned out to be
// a delayed tri-stating of the bus.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -101,6 +104,25 @@ void testBus(void)
}
}
void testSixtyBug(void)
{
printf("Repeating a write to 0x0060\n");
while(true)
{
if(reqTranZPUterBus(100) == 0)
{
setupSignalsForZ80Access(WRITE);
uint8_t data = 0x07;
writeZ80Memory(0x0060, data);
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.
@@ -125,6 +147,8 @@ uint32_t app(uint32_t param1, uint32_t param2)
//}
// _init_Teensyduino_internal_();
// setupZ80Pins(1, G->millis);
//
testSixtyBug();
printf("Loading Monitor ROM\n");
loadZ80Memory("SA1510.rom", 0, 0x00000000, 0, 0, 0, 1);

View File

@@ -34,6 +34,9 @@
// for Z80 A11:A0 and Port A 15:12 for Z80 A15:12. This was done due to the
// extra overhead required to piece together address and data lines in v1.0
// where the PCB was routed for linear reading and routing.
// v1.2 July 2020 - Updates for the v2.1 tranZPUter board. I've used macro processing
// to seperate v1+ and v2+ but I may well create two seperate directories
// as both projects are updated. Alternatively I use git flow or similar, TBD!
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -164,6 +167,7 @@ static void __attribute((naked, noinline)) irqPortC_dummy(void)
}
#endif
#if TZBOARD == 100 || TZBOARD == 110 || TZBOARD == 200 || TZBOARD == 210
// This method is called everytime an active irq triggers on Port E. For this design, this means the two IO CS
// lines, TZ_SVCREQ and TZ_SYSREQ. The SVCREQ is used when the Z80 requires a service, the SYSREQ is yet to
// be utilised.
@@ -202,7 +206,9 @@ static void __attribute((naked, noinline)) irqPortE(void)
return;
}
#endif
#if TZBOARD == 110 || TZBOARD == 200 || TZBOARD == 210
// This method is called everytime an active irq triggers on Port D. For this design, this means the IORQ and RESET lines.
//
// There are 3 versions of the same routine, originally using #if macro preprocessor statements but it became
@@ -227,10 +233,10 @@ static void __attribute((naked, noinline)) irqPortD_Mode0(void)
" str r0, [r1, #0] \n"
// Is Z80_RESET active, set flag and exit.
" movs r0, #1 \n"
" tst r5, #0x010 \n"
" movs r1, #1 \n"
" tst r0, #0x0010 \n"
" beq irqPortD_Exit \n"
" strb r0, %[val0] \n"
" strb r1, %[val0] \n"
" irqPortD_Exit: \n"
@@ -243,10 +249,11 @@ static void __attribute((naked, noinline)) irqPortD_Mode0(void)
return;
}
#endif
//
// Mode 1 & 2 - Capture and store an IORQ or MREQ Memory Mapped event for the main thread to process.
//
#if 1
#if TZBOARD == 110
static void __attribute((naked, noinline)) irqPortD_Mode12(void)
{
// Save minimum number of registers, cycles matter as we need to capture the address and halt the Z80 whilst we decode it.
@@ -462,6 +469,7 @@ static void __attribute((naked, noinline)) irqPortD_Mode12(void)
return;
}
#endif
#if TZBOARD == 110
//
// Mode 3 - MZ700 processing.
//
@@ -840,6 +848,7 @@ static void __attribute((naked, noinline)) irqPortD_Mode3(void)
return;
}
#endif
// Method to install the interrupt vector and enable it to capture Z80 memory/IO operations.
//
@@ -853,10 +862,18 @@ static void setupIRQ(void)
// For the MZ700 we need to enable IORQ to process the OUT statements the Z80 generates for memory mode selection.
case MZ700:
// Install the dummy method to be called when PortE triggers.
#if TZBOARD == 110
_VectorsRam[IRQ_PORTE + 16] = irqPortE_dummy;
#elif TZBOARD == 200 || TZBOARD == 210
_VectorsRam[IRQ_PORTE + 16] = irqPortE;
#endif
// Install the method to be called when PortD triggers.
#if TZBOARD == 110
_VectorsRam[IRQ_PORTD + 16] = irqPortD_Mode3;
#elif TZBOARD == 200 || TZBOARD == 210
_VectorsRam[IRQ_PORTD + 16] = irqPortD_Mode0;
#endif
// Setup the IRQ for Z80_IORQ.
installIRQ(Z80_IORQ, IRQ_MASK_FALLING);
@@ -864,6 +881,7 @@ static void setupIRQ(void)
// Setup the IRQ for Z80_RESET.
installIRQ(Z80_RESET, IRQ_MASK_FALLING);
#if TZBOARD == 110
// Setup the IRQ for Z80_MREQ.
//installIRQ(Z80_MREQ, IRQ_MASK_RISING);
@@ -871,6 +889,14 @@ static void setupIRQ(void)
removeIRQ(TZ_SVCREQ);
removeIRQ(TZ_SYSREQ);
#elif TZBOARD == 200 || TZBOARD == 210
// Setup the IRQ for TZ_SYSREQ.
installIRQ(TZ_SYSREQ, IRQ_MASK_FALLING);
// Setup the IRQ for Z80_RESET.
installIRQ(Z80_RESET, IRQ_MASK_FALLING);
#endif
// Set relevant priorities to meet latency.
NVIC_SET_PRIORITY(IRQ_PORTD, 0);
NVIC_SET_PRIORITY(IRQ_PORTE, 16);
@@ -882,7 +908,11 @@ static void setupIRQ(void)
_VectorsRam[IRQ_PORTE + 16] = irqPortE_dummy;
// Install the method to be called when PortD triggers.
#if TZBOARD == 110
_VectorsRam[IRQ_PORTD + 16] = irqPortD_Mode3;
#elif TZBOARD == 200 || TZBOARD == 210
_VectorsRam[IRQ_PORTD + 16] = irqPortD_Mode0;
#endif
// Setup the IRQ for Z80_IORQ.
installIRQ(Z80_IORQ, IRQ_MASK_FALLING);
@@ -890,8 +920,10 @@ static void setupIRQ(void)
// Setup the IRQ for Z80_RESET.
installIRQ(Z80_RESET, IRQ_MASK_FALLING);
#if TZBOARD == 110
// Setup the IRQ for Z80_MREQ.
//installIRQ(Z80_MREQ, IRQ_MASK_RISING);
#endif
// Remove previous interrupts not needed in this mode.
removeIRQ(TZ_SVCREQ);
@@ -947,8 +979,10 @@ static void restoreIRQ(void)
// Setup the IRQ for Z80_IORQ.
installIRQ(Z80_IORQ, IRQ_MASK_FALLING);
#if TZBOARD == 110
// Setup the IRQ for Z80_MREQ.
//installIRQ(Z80_MREQ, IRQ_MASK_FALLING);
#endif
// Setup the IRQ for Z80_RESET.
installIRQ(Z80_RESET, IRQ_MASK_FALLING);
@@ -959,8 +993,10 @@ static void restoreIRQ(void)
// Setup the IRQ for Z80_IORQ.
installIRQ(Z80_IORQ, IRQ_MASK_FALLING);
#if TZBOARD == 110
// Setup the IRQ for Z80_MREQ.
//installIRQ(Z80_MREQ, IRQ_MASK_FALLING);
#endif
// Setup the IRQ for Z80_RESET.
installIRQ(Z80_RESET, IRQ_MASK_FALLING);
@@ -1361,7 +1397,6 @@ uint8_t writeZ80Memory(uint16_t addr, uint8_t data)
{
// Locals.
uint32_t startTime = *ms;
volatile uint32_t pulseWidth;
// Set the data and address on the bus.
//
@@ -1369,8 +1404,9 @@ uint8_t writeZ80Memory(uint16_t addr, uint8_t data)
setZ80Data(data);
// Setup time before applying control signals.
for(pulseWidth = 0; pulseWidth < 5; pulseWidth++);
for(volatile uint32_t pulseWidth = 0; pulseWidth < 3; pulseWidth++);
pinLow(Z80_MREQ);
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.
@@ -1385,7 +1421,11 @@ uint8_t writeZ80Memory(uint16_t addr, uint8_t data)
pinLow(Z80_WR);
// On a Teensy3.5 K64F running at 120MHz this delay gives a pulsewidth of 760nS.
for(volatile uint32_t pulseWidth=0; pulseWidth < 2; pulseWidth++);
#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++);
#endif
// Another wait loop check as the Z80 can assert wait at the time of Write or anytime before it is deasserted.
while((*ms - startTime) < 200 && pinGet(Z80_WAIT) == 0);
@@ -1393,10 +1433,15 @@ uint8_t writeZ80Memory(uint16_t addr, uint8_t data)
{
// Start the write cycle, MREQ and WR go low.
pinLow(Z80_WR);
}
// Hold time for the WR signal before clearing it.
for(pulseWidth = 0; pulseWidth < 5; pulseWidth++);
// On a Teensy3.5 K64F running at 120MHz this delay gives a pulsewidth of 760nS.
#if TZBOARD == 100 || TZBOARD == 110
for(volatile uint32_t pulseWidth = 0; pulseWidth < 2; pulseWidth++);
// With the tranZPUter SW v2 boards, need to increase the write pulse width, alternatively wait until a positive edge on the CPU clock.
#elif TZBOARD == 200 || TZBOARD == 210
for(volatile uint32_t pulseWidth=0; pulseWidth < 3; pulseWidth++);
#endif
}
// Complete the write cycle.
//
@@ -1430,11 +1475,21 @@ uint8_t readZ80Memory(uint16_t addr)
// 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
for(volatile uint32_t pulseWidth=0; pulseWidth < 1; pulseWidth++);
// With the tranZPUter SW v2 boards, need to increase the write pulse width, alternatively wait until a positive edge on the CPU clock.
#elif TZBOARD == 200 || TZBOARD == 210
for(volatile uint32_t pulseWidth=0; pulseWidth < 4; pulseWidth++);
#endif
} 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.
#if TZBOARD == 100 || TZBOARD == 110
for(volatile uint32_t pulseWidth=0; pulseWidth < 1; pulseWidth++);
// With the tranZPUter SW v2 boards, need to increase the write pulse width to accommodate the different memories used.
#elif TZBOARD == 200 || TZBOARD == 210
for(volatile uint32_t pulseWidth=0; pulseWidth < 4; pulseWidth++);
#endif
}
// Fetch the data before deasserting the signals.
@@ -1481,14 +1536,23 @@ uint8_t writeZ80IO(uint16_t addr, uint8_t data)
pinLow(Z80_WR);
// On a Teensy3.5 K64F running at 120MHz this delay gives a pulsewidth of 760nS.
#if TZBOARD == 100 || TZBOARD == 110
//for(volatile uint32_t pulseWidth=0; pulseWidth < 2; pulseWidth++);
#elif TZBOARD == 200 || TZBOARD == 210
for(volatile uint32_t pulseWidth=0; pulseWidth < 2; pulseWidth++);
#endif
// Another wait loop check as the Z80 can assert wait at the time of Write or anytime before it is deasserted.
while((*ms - startTime) < 200 && pinGet(Z80_WAIT) == 0);
} else
{
// Start the write cycle, MREQ and WR go low.
// Start the write cycle, WR go low.
pinLow(Z80_WR);
// With the tranZPUter SW v2 boards, need to increase the write pulse width as the latch is synchronous, alternatively wait until a positive edge on the CPU clock.
#if TZBOARD == 200 || TZBOARD == 210
for(volatile uint32_t pulseWidth=0; pulseWidth < 8; pulseWidth++);
#endif
}
// Complete the write cycle.
@@ -4013,7 +4077,7 @@ uint32_t getServiceAddr(void)
{
// Locals.
uint32_t addr = TZSVC_CMD_STRUCT_ADDR_TZFS;
uint8_t memoryMode = readCtrlLatch();
uint8_t memoryMode = readCtrlLatch() & 0x1F;
// If in CPM mode then set the service address accordingly.
if(memoryMode == TZMM_CPM || memoryMode == TZMM_CPM2)
@@ -4160,7 +4224,11 @@ void processServiceRequest(void)
// Load the 40 column MZ700 1Z-013A bios into memory.
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)
#elif TZBOARD == 200 || TZBOARD == 210
if((status=loadZ80Memory((const char *)MZ_ROM_1Z_013A_40C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK)
#endif
{
printf("Error: Failed to load %s into tranZPUter memory.\n", MZ_ROM_1Z_013A_40C);
}
@@ -4177,7 +4245,11 @@ void processServiceRequest(void)
// Load the 80 column MZ700 1Z-013A bios into memory.
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)
#elif TZBOARD == 200 || TZBOARD == 210
if((status=loadZ80Memory((const char *)MZ_ROM_1Z_013A_80C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK)
#endif
{
printf("Error: Failed to load %s into tranZPUter memory.\n", MZ_ROM_1Z_013A_80C);
}

View File

@@ -9,6 +9,7 @@
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
//
// History: May 2020 - Initial write of the TranZPUter software.
// July 2020- Updates to accommodate v2.1 of the tranZPUter board.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -42,6 +43,7 @@
// 3 = NZ700 memory mode decode - This doesnt work per original, the memory change occurs one instruction after the OUT instruction due to the way the Z80 functions in respect to BUSRQ.
#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
// tranZPUter Memory Modes - select one of the 32 possible memory models using these constants.
//
@@ -106,6 +108,8 @@
#define MZ_ROM_SA1510_80C "0:\\TZFS\\SA1510-8.ROM" // Original Monitor ROM patched for 80 character screen mode.
#define MZ_ROM_1Z_013A_40C "0:\\TZFS\\1Z-013A.ROM" // Original 40 character Monitor ROM for the Sharp MZ700.
#define MZ_ROM_1Z_013A_80C "0:\\TZFS\\1Z-013A-8.ROM" // Original Monitor ROM patched for the Sharp MZ700 patched for 80 column mode.
#define MZ_ROM_1Z_013A_KM_40C "0:\\TZFS\\1Z-013A-KM.ROM" // Original 40 character Monitor ROM for the Sharp MZ700 with keyboard remapped for the MZ80A.
#define MZ_ROM_1Z_013A_KM_80C "0:\\TZFS\\1Z-013A-KM-8.ROM" // Original Monitor ROM patched for the Sharp MZ700 with keyboard remapped for the MZ80A and patched for 80 column mode.
#define MZ_ROM_MZ80B_IPL "0:\\TZFS\\MZ80B_IPL.ROM" // Original IPL ROM for the Sharp MZ-80B.
#define MZ_ROM_TZFS "0:\\TZFS\\TZFS.ROM" // tranZPUter Filing System ROM.

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

@@ -48,8 +48,8 @@ TARGET = main
TEENSY = 35
# Set to 24000000, 48000000, or 96000000 to set CPU core speed
TEENSY_CORE_SPEED = 168000000
#TEENSY_CORE_SPEED = 120000000
#TEENSY_CORE_SPEED = 168000000
TEENSY_CORE_SPEED = 120000000
# Some libraries will require this to be defined
# If you define this, you will break the default main.cpp

View File

@@ -19,6 +19,7 @@
// enhanced to work with both the ZPU and K64F for the original purpose
// of testing but also now for end application programming using the
// features of zOS where applicable.
// July 2020 - Tweaks to accomodate v2.1 of the tranZPUter board.
//
// Notes: See Makefile to enable/disable conditional components
// USELOADB - The Byte write command is implemented in hw/sw so use it.