Updates to allow the tranZPUter v2.2 to work with the new pin allocation

This commit is contained in:
Philip Smart
2020-09-06 00:51:00 +01:00
parent 08b71c8b62
commit add502f1c7
10 changed files with 2015 additions and 2563 deletions

View File

@@ -37,6 +37,10 @@
// 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!
// v1.3 Sep 2020 - Updates for the v2.2 tranZPUter board using an MK64FX512LLVQ 100 pin CPU
// instead of the Teensy board. As the v2.2 continues on its own branch, all
// references to previous boards and conditonal compilation have been removed
// to make the code simpler to read.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -165,7 +169,6 @@ 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.
@@ -181,17 +184,11 @@ static void __attribute((naked, noinline)) irqPortE(void)
" ldr r5, [r4, #0] \n"
" str r5, [r4, #0] \n"
// Is TZ_SVCREQ (E10) active (low), set flag and exit if it is.
// Is TZ_SVCREQ (E24) active (low), set flag and exit if it is.
" movs r4, #1 \n"
" tst r5, #0x400 \n"
" beq ebr0 \n"
" strb r4, %[val0] \n"
" ebr0: \n"
// Is TZ_SYSREQ (E11) active (low), set flag and exit if it is.
" tst r5, #0x800 \n"
" tst r5, #0x01000000 \n"
" beq irqPortE_Exit \n"
" strb r4, %[val1] \n"
" strb r4, %[val0] \n"
" irqPortE_Exit: \n"
@@ -204,23 +201,12 @@ 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
// unwieldy. The purpose of the 3 versions are:
// 0 = Basic IRQ just sets the reset flag if the user presses reset on the host.
// 1,2 = Captures I/O and memory events, stores the address/data of the I/O command or processes the memory mapped transaction.
// 3 = MZ700 mode - this mode detects the MZ700 OUT commands and changes memory mode. Unfortunately it doesnt work 100% due to another
// ISR occasionally delaying the activation of this routine which means we cannot apply a WAIT state and consequently the data on the Z80
// address bus has changed. Other than removing realtime clock and threads I cant see a way around it in software, will have to look at
// a hardware solution.
// Basic RESET detection.
//
// Mode 0 - Basic RESET detection.
//
static void __attribute((naked, noinline)) irqPortD_Mode0(void)
static void __attribute((naked, noinline)) irqPortD(void)
{
// This code is critical, if the Z80 is running at higher frequencies then very little time to capture it's requests.
asm volatile(" push {r0-r3,lr} \n");
@@ -247,606 +233,6 @@ 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 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.
asm volatile(" push {r0-r8,lr} \n"
// Get the triggering interrupt.
" ldr r0, =0x4004c0a0 \n"
" ldr r4, [r0, #0] \n"
// Assert BUSRQ so we keep the Z80 from moving to the next instruction in-case we need to update the memory latch.
" ldr r0, =0x43fe1900 \n" // CTL_BUSRQ
" movs r1, #1 \n"
" str r1, [r0,#0] \n"
);
asm volatile( // Is Z80_RESET active, set flag and exit.
// NB: We are testing the interrupt register, a bit is set if the given signal caused the interrupt, so a 1 means the signal went active.
" tst r4, #0x0010 \n"
" beq irqd0 \n"
" movs r6, #1 \n"
" strb r6, %[val1] \n"
" b irqPortD_Exit3 \n"
: [val1] "=m" (z80Control.resetEvent)
:
: "r4","r5","r6","r7","r8","r9","r10","r11","r12");
asm volatile( // If the IORQ line and MREQ lines are high (another interrupt triggered us or false trigger) get out, cant work with incomplete data.
" irqd0: tst r4, #0x0008 \n"
" bne irqd1 \n"
" tst r4, #0x0004 \n"
" bne irqd10 \n"
" b irqPortD_Exit3 \n"
);
////////////////////////////////////////////
// IORQ logic, intercept IO operations.
////////////////////////////////////////////
// Capture GPIO ports - this is necessary in order to make a clean capture and then decode.
asm volatile(" irqd1: ldr r0, =0x400ff010 \n" // GPIOA_PDIR
" ldr r4, [r0, #0] \n"
" add.w r0, #64 \n" // GPIOB_PDIR
" ldr r5, [r0, #0] \n"
" add.w r0, #64 \n" // GPIOC_PDIR
" ldr r6, [r0, #0] \n"
" add.w r0, #64 \n" // GPIOD_PDIR
" ldr r7, [r0, #0] \n"
" add.w r0, #64 \n" // GPIOE_PDIR
" ldr r8, [r0, #0] \n"
:
:
: "r0","r1","r4","r5","r6","r7","r8","r9","r10","r11","r12");
asm volatile( // Is TZ_SVCREQ (E10) active (low), set flag and exit if it is.
" movs r0, #1 \n"
" tst r8, #0x400 \n"
" bne irqd2 \n"
" strb r0, %[val0] \n"
" b irqPortD_Exit3 \n"
// Is TZ_SYSREQ (E11) active (low), set flag and exit if it is.
" irqd2: tst r8, #0x800 \n"
" bne irqd3 \n"
" strb r0, %[val1] \n"
" b irqPortD_Exit3 \n"
: [val0] "+m" (z80Control.svcRequest),
[val1] "+m" (z80Control.sysRequest)
:
: "r0","r4","r5","r7","r8","r9","r10","r11","r12");
asm volatile( // Is Z80_WR active, continue if it is as we consider IO WRITE cycles.
" irqd3: tst r7, #0x200 \n" // Z80_WR = D9 v1.1+
" beq irqd4 \n"
// Is Z80_RD active, continue if it is as we consider IO READ cycles.
" tst r7, #0x800 \n" // Z80_RD = D11 v1.1+
" bne irqPortD_Exit3 \n"
" irqd4: \n"
);
// Convert lower 8 address bits into a byte and store.
//
asm volatile(" and r0, r6, #0xFF \n" // Port C 7:0 = Z80 A7:A0
// Store the address for later processing..
" strb r0, %[val0] \n"
" mov r8, r0 \n" // Addr in R8
: [val0] "=m" (z80Control.ioAddr)
:
: "r0","r1","r4","r5","r6","r7","r8","r9","r10","r11","r12");
#if 0
// Convert data port bits into a byte and store.
asm volatile(" lsrs r1, r5, 16 \n" // Data Port B 23:17 = Z80 D7:D0
" and r1, r1, #0xFF \n" // Clear out top bits.
" strb r1, %[val0] \n"
" mov r7, r0 \n" // Data in R7
: [val0] "=m" (z80Control.ioData)
:
: "r0","r1","r4","r5","r6","r7","r8","r9","r10","r11","r12");
#endif
// Process the IO request by setting the ioEvent flag as it wasnt an MZ700 memory switch request.
asm volatile(" movs r4, #1 \n"
" strb r4, %[val2] \n"
" b irqPortD_Exit12 \n"
: [val2] "=m" (z80Control.ioEvent)
:
: "r4","r5","r6","r7","r8","r9","r10","r11","r12");
////////////////////////////////////////////
// MREQ logic, intercept memory operations.
////////////////////////////////////////////
// Convert 16 address bits into a byte and store.
//
asm volatile(" and r0, r4, #0xF000 \n" // Port A 15:12 = Z80 A15:A12
" and r1, r6, #0xFFF \n" // Port C 11:0 = Z80 A11:A0
" orr r0, r1 \n" // Complete address into R0
// Store the address for later processing..
" strb r0, %[val0] \n"
" mov r8, r0 \n" // Addr in R8
: [val0] "=m" (z80Control.ioAddr)
:
: "r0","r1","r4","r5","r6","r7","r8","r9","r10","r11","r12");
#if 0
// Convert data port bits into a byte and store.
asm volatile(" lsrs r1, r5, 16 \n" // Data Port B 23:17 = Z80 D7:D0
" and r1, r1, #0xFF \n" // Clear out top bits.
" strb r1, %[val0] \n"
" mov r7, r0 \n" // Data in R7
: [val0] "=m" (z80Control.ioData)
:
: "r0","r1","r4","r5","r6","r7","r8","r9","r10","r11","r12");
#endif
asm volatile( // A memory swap event.
" movw r1," XSTR(MZ_MEMORY_SWAP) "\n"
" cmp r0, r1 \n"
" bne br0 \n"
" movs r2, #1 \n"
" b.n br1 \n"
" br0: \n"
// A memory reset event.
" movw r1, " XSTR(MZ_MEMORY_RESET) "\n"
" cmp r0, r1 \n"
" bne br2 \n"
" movs r2, #0 \n"
" br1: \n"
// Store to memorySwap
" strb r2, %[val0] \n"
" b.n irqPortC_Exit \n"
" br2: \n"
// A CRT to normal mode event.
" movw r1, " XSTR(MZ_CRT_NORMAL) "\n"
" cmp r0, r1 \n"
" bne br3 \n"
" movs r2, #0 \n"
" b.n br4 \n"
" br3: \n"
// A CRT to inverse mode event.
" movw r1, " XSTR(MZ_CRT_INVERSE) "\n"
" cmp r0, r1 \n"
" bne br5 \n"
" movs r2, #0 \n"
" br4: \n"
// Store to crtMode.
" strb r2, %[val1] \n"
" b.n irqPortC_Exit \n"
" br5: \n"
// Memory address in SCROLL region?
" sub.w r1, r0, " XSTR(MZ_SCROL_END - MZ_SCROL_BASE) "\n"
" cmp r1, #255 \n"
" bhi.n irqPortC_Exit \n"
" strb r0, %[val2] \n"
: [val0] "+m" (z80Control.memorySwap),
[val1] "+m" (z80Control.crtMode),
[val2] "+m" (z80Control.scroll)
:
: "r2","r3","r4","r5","r7","r8","r9","r10","r11","r12");
asm volatile(" irqPortD_Exit12: \n"
// De-assert BUSRQ nothing more to do.
" ldr r4, =0x43fe1800 \n" // CTL_BUSRQ, Set=43fe1800, Clear=43fe1900
" movs r5, #1 \n"
" str r5, [r4,#0] \n"
// Reset the triggering interrupt, PORTD_ISFR <= PORTD_ISFR
" ldr r0, =0x4004c0a0 \n"
" ldr r4, [r0, #0] \n"
" str r4, [r0, #0] \n"
// Restore registers, all done.
" pop {r0-r8,pc} \n"
:
:
: "r4","r5","r6","r7","r8","r9","r10","r11","r12");
return;
}
#endif
#if TZBOARD == 110
//
// Mode 3 - MZ700 processing.
//
// v1.1 address reference:
// CTL_BUSRQ, Set=43fe1800, Clear=43fe1900
// Z80_WAIT, Set=43fe183c, Clear=43fe193c
// CTL_BUSACK, Set=43fe1818, Clear=43fe1918
// Z80_IORQ, Set=43fe180c, Clear=43fe190c
// Z80_MREQ, Set=43fe1808, Clear=43fe1908
//
//
static void __attribute((naked, noinline)) irqPortD_Mode3(void)
{
// Save minimum number of registers, cycles matter as we need to capture the address and halt the Z80 whilst we decode it.
asm volatile(" push {r0-r8,lr} \n"
// Get the triggering interrupt.
" ldr r0, =0x4004c0a0 \n"
" ldr r4, [r0, #0] \n"
// Assert BUSRQ so we keep the Z80 from moving to the next instruction in-case we need to update the memory latch.
" ldr r0, =0x43fe1900 \n" // CTL_BUSRQ
" movs r1, #1 \n"
" str r1, [r0,#0] \n"
);
asm volatile( // Is Z80_RESET active, set flag and exit.
// NB: We are testing the interrupt register, a bit is set if the given signal caused the interrupt, so a 1 means the signal went active.
" tst r4, #0x0010 \n"
" beq irqd0 \n"
" movs r6, #1 \n"
" strb r6, %[val1] \n"
" b irqPortD_Exit3 \n"
: [val1] "=m" (z80Control.resetEvent)
:
: "r4","r5","r6","r7","r8","r9","r10","r11","r12");
asm volatile( // If the IORQ line is high (another interrupt triggered us or false trigger) get out, cant work with incomplete data.
" irqd0: tst r4, #0x0008 \n"
" beq irqPortD_Exit3 \n"
);
// Capture GPIO ports - this is necessary in order to make a clean capture and then decode.
asm volatile(" ldr r0, =0x400ff010 \n" // GPIOA_PDIR
" ldr r4, [r0, #0] \n"
" add.w r0, #64 \n" // GPIOB_PDIR
" ldr r5, [r0, #0] \n"
" add.w r0, #64 \n" // GPIOC_PDIR
" ldr r6, [r0, #0] \n"
" add.w r0, #64 \n" // GPIOD_PDIR
" ldr r7, [r0, #0] \n"
" add.w r0, #64 \n" // GPIOE_PDIR
" ldr r8, [r0, #0] \n"
:
:
: "r0","r1","r4","r5","r6","r7","r8","r9","r10","r11","r12");
asm volatile( // Is TZ_SVCREQ (E10) active (low), set flag and exit if it is.
" movs r0, #1 \n"
" tst r8, #0x400 \n"
" bne irqd1 \n"
" strb r0, %[val0] \n"
" b irqPortD_Exit3 \n"
// Is TZ_SYSREQ (E11) active (low), set flag and exit if it is.
" irqd1: tst r8, #0x800 \n"
" bne irqd2 \n"
" strb r0, %[val1] \n"
" b irqPortD_Exit3 \n"
: [val0] "+m" (z80Control.svcRequest),
[val1] "+m" (z80Control.sysRequest)
:
: "r0","r4","r5","r7","r8","r9","r10","r11","r12");
asm volatile( // Is Z80_WR active, continue if it is as we consider IO WRITE cycles.
" irqd2: tst r7, #0x200 \n" // Z80_WR = D9 v1.1+
" beq irqd3 \n"
// Is Z80_RD active, continue if it is as we consider IO READ cycles.
" tst r7, #0x800 \n" // Z80_RD = D11 v1.1+
" bne irqPortD_Exit3 \n"
" irqd3: \n"
);
// Convert lower 8 address bits into a byte and store.
//
asm volatile(" and r0, r6, #0xFF \n" // Port C 7:0 = Z80 A7:A0
// Store the address for later processing..
" strb r0, %[val0] \n"
" mov r8, r0 \n" // Addr in R8
: [val0] "=m" (z80Control.ioAddr)
:
: "r0","r1","r4","r5","r6","r7","r8","r9","r10","r11","r12");
// MZ700 memory mode switch?
// 0x0000:0x0FFF 0xD000:0xFFFF
// 0xE0 = DRAM
// 0xE1 = DRAM
// 0xE2 = MONITOR
// 0xE3 = Memory Mapped I/O
// 0xE4 = MONITOR Memory Mapped I/O
// 0xE5 = Inhibit
// 0xE6 = Return to state prior to 0xE5
//
// Must be in range 0xE0-0xE6 to be an MZ700 operation.
//
// ADDR 7 ADDR 6 ADDR 5 ADDR 4 ADDR 3 ADDR 2 ADDR 1 ADDR 0
// PORT C:7 PORT C:6 PORT C:5 PORT C:4 PORT C:3 PORT C:2 PORT C:1 PORT C:0
//
// DATA 7 DATA 6 DATA 5 DATA 4 DATA 3 DATA 2 DATA 1 DATA 0
// PORT B:23 PORT B:22 PORT B:21 PORT B:20 PORT B:19 PORT B:18 PORT B:17 PORT B:16
//
//
// Z80 WAIT SYSCLK CTL BUSACK CTL BUSRQ Z80 IORQ Z80 WR
// PORT D:15 PORT A:5 PORT D:6 PORT D:0 PORT D:3 PORT D:9
//
// CTL_BUSRQ, Set=43fe1800, Clear=43fe1900
// Z80_WAIT, Set=43fe183c, Clear=43fe193c
// CTL_BUSACK, Set=43fe1818, Clear=43fe1918
// Z80_IORQ, Set=43fe180c, Clear=43fe190c
// Z80_MREQ, Set=43fe1808, Clear=43fe1908
// Z80_RD, Set=43fe182c, Clear=43fe192c
// Z80_WR, Set=43fe1824, Clear=43fe1924
//
asm volatile(" cmp.w r8, #224 \n"
" blt irqd20 \n"
" cmp.w r8, #230 \n"
" bgt irqd20 \n"
" \n"
" ldr r6, %[val1] \n" // Retrieve the config value for the MZ700.
" tst r6, #0x40000 \n"
" bne irqd16 \n" // For locked mode, only service E4, E5 & E6.
" and r6, r6, #0xFFFFFF00 \n" // Clear out the memoryMode[current[ as a new value will be stored.
// 0xE0
" irqd12: cmp.w r8, #224 \n" // R8 = address location of OUT command on Z80.
" bne irqd13 \n"
" orr r6, #65536 \n" // mode[16] = 1
" b irqd11x \n"
// 0xE1
" irqd13: cmp.w r8, #225 \n"
" bne irqd14 \n"
" orr r6, #131072 \n" // mode[17] = 1
" b irqd11x \n"
// 0xE2
" irqd14: cmp.w r9, #226 \n"
" bne irqd15 \n"
" bic r6, #65536 \n" // mode[16] = 0
" b irqd11x \n"
// 0xE3
" irqd15: cmp.w r8, #227 \n"
" bne irqd16 \n"
" bic r6, #131072 \n" // mode[17] = 0
// if(z80Control.mz700.mode[17:16] == '00')
" irqd11x: tst r6, #0x30000 \n"
" bne irqd12x \n"
" orr r6," XSTR(TZMM_TZFS + TZMM_ENIOWAIT) "\n" // memoryMode = 2
" b irqd19 \n"
// if(z80Control.mz700.mode[17:16] == '10')
" irqd12x: tst r6, #0x20000 \n"
" beq irqd13x \n"
" tst r6, #0x10000 \n"
" bne irqd14x \n"
" orr r6," XSTR(TZMM_MZ700_1 + TZMM_ENIOWAIT) "\n" // memoryMode = 11
" b irqd19 \n"
// if(z80Control.mz700.mode[17:16] == '01')
" irqd13x: orr r6," XSTR(TZMM_MZ700_0 + TZMM_ENIOWAIT) "\n" // memoryMode = 10
" b irqd19 \n"
// if(z80Control.mz700.mode[17:16] == '11)
" irqd14x: orr r6," XSTR(TZMM_MZ700_2 + TZMM_ENIOWAIT) "\n" // memoryMode = 12
" b irqd19 \n"
// 0xE4 - Reset to default.
" irqd16: cmp.w r8, #228 \n"
" bne irqd17 \n"
" mov r6," XSTR(TZMM_TZFS + TZMM_ENIOWAIT) "\n" // mode[17:16] = '00', mode[inhibit] = '0', memoryMode[current] = 2, memoryMode[old] = 2
" b irqd19 \n"
// 0xE5 - Lock the region D000-FFFF by setting memory mode to 13.
" irqd17: cmp.w r8, #229 \n"
" bne irqd18 \n"
" orr r6, #0x40000 \n" // mode[inhibit] = 1
" and r5, r6, #0x0000FF00 \n" // Look at previous memory mode and use to decide the mode we lock into.
" cmp r5, #0xB00 \n"
" bne irqd17x \n"
" orr r6," XSTR(TZMM_MZ700_3 + TZMM_ENIOWAIT) "\n" // memoryMode[current] = 13 - Monitor ROM at 0000:0FFF
" b irqd19 \n"
" irqd17x: orr r6," XSTR(TZMM_MZ700_4 + TZMM_ENIOWAIT) "\n" // memoryMode[current] = 14 - System RAM at 0000:0FFF
" b irqd19 \n"
// 0xE6 - Unlock the region D000-FFF by returning the memory mode to original.
" irqd18: cmp.w r8, #230 \n"
" bne irqd2 \n"
" and r6, #0xFFFBFFFF \n" // mode[inhibit] = 0
" and r5, r6, #0x0000FF00 \n"
" lsrs r5, r5, #8 \n"
" orr r6, r5 \n" // memoryMode[current] = memoryMode[old]
// Store the changed value back to the control structure.
" irqd19: lsls r8, r8, #24 \n"
" and r6, r6, #0x00FFFFFF \n"
" orr r6, r8 \n"
" and r5, r6, #0x000000FF \n"
" lsls r5, r5, #8 \n"
" and r6, r6, #0xFFFF00FF \n"
" orr r6, r5 \n" // memoryMode[old] = memoryMode[current]
" str r6, %[val1] \n"
// Output to variables.
: [val1] "=m" (z80Control.mz700.config)
// Input from variables.
:
: "r5","r6","r7","r8","r9","r10","r11","r12");
// Write memory mode to the latch.
// This requires all signals A7-A0, D7-D0, WR, IORQ be set to output and de-asserted, data and address set
// control signals asserted, de-asserted then all signals returned to being inputs. Finally reset the IRQ!!
//
asm volatile(" mov r2, r6 \n"
// Read current PDOR values ready to be changed.
//
" ldr r0, =0x400FF040 \n" // PDOR B
" ldr r5, [r0, #0] \n"
" lsls r2, r2, 16 \n" // Data into position.
" and r2, #0b00000000111111110000000000000000 \n" // Mask the shifted data.
" and r5, #0b11111111000000001111111111111111 \n" // Clear out the data bits in the output register.
" orr r5, r2 \n" // Add data onto register bits.
" str r5, [r0, #0] \n" // And put back to output register.
" add r0, #0x40 \n" // PDOR C
" ldr r6, [r0, #0] \n"
" and r6, #0b11111111111111111111111100000000 \n" // Port C
" orr r6, #0b00000000000000000000000001100000 \n" // Set address to 60H
" str r6, [r0, #0] \n"
" add r0, #0x40 \n" // PDOR D
" ldr r7, [r0, #0] \n"
" orr r7, #0b00000000000000000000000000001000 \n" // Set all control signals to inactive.
" orr r1, #0b00000000000000000000001000000000 \n"
" str r7, [r0, #0] \n"
// Setup the Data Direction Register PDDR[x].
//
" ldr r0, =0x400FF054 \n" // Port B
" ldr r1, [r0, #0] \n"
" orr r1, #0b00000000111111110000000000000000 \n"
" str r1, [r0, #0] \n"
" add r0, #0x40 \n" // Port C
" ldr r1, [r0, #0] \n"
" orr r1, #0b00000000000000000000000011111111 \n"
" str r1, [r0, #0] \n"
" add r0, #0x40 \n" // Port D
" ldr r1, [r0, #0] \n"
" orr r1, #0b00000000000000000000000000001000 \n"
" orr r1, #0b00000000000000000000001000000000 \n"
" str r1, [r0, #0] \n"
);
// Setup the required pins for output mode (CTL_BUSRQ, Z80_WR).
//
asm volatile(" ldr r0, =0x4004A084 \n" // Port B high
" ldr r1, =0x00FF0143 \n" // Bits 23:16
" str r1, [r0,#0] \n"
" add r0, #0xFFC \n" // Port C low
" ldr r1, =0x00FF0143 \n" // Bits 7:0
" str r1, [r0,#0] \n"
" add r0, #0x1000 \n" // Port D low
" ldr r1, =0x02080143 \n" // Bits 9, 3
" str r1, [r0,#0] \n"
// Update the PDOR registers with the determined values.
//
" ldr r0, =0x400FF040 \n" // PDOR B
" str r5, [r0, #0] \n"
" add r0, #0x40 \n" // PDOR C
" str r6, [r0, #0] \n"
" add r0, #0x40 \n" // PDOR D
" str r7, [r0, #0] \n"
);
// Start the write cycle, IORQ and WR go low.
asm volatile(" mov r1, #1 \n"
" ldr r0, =0x43fe190c \n" // Set IORQ Set=43fe180c, Clear=43fe190c
" str r1, [r0,#0] \n"
" add r0, #0x18 \n" // Set WR Set=43fe1824, Clear=43fe1924
" str r1, [r0,#0] \n"
// A small delay to ensure the pulse width is sufficient to cater for 55ns of the flash decoder + 40ns for the HCT138 + latch timing.
// The main criteria is data settle time prior to rising edge on the latch.
" movs r1, #8 \n"
" sd8: subs r1, #1 \n"
" bne sd8 \n"
// Complete the write cycle by raising the WR and IORQ signals.
" mov r1, #1 \n"
" ldr r0, =0x43fe180c \n" // Set IORQ Set=43fe180c, Clear=43fe190c
" str r1, [r0,#0] \n"
" add r0, #0x18 \n" // Set WR Set=43fe1824, Clear=43fe1924
" str r1, [r0,#0] \n"
);
// Revert the Data Direction Register PDDR[x].
//
asm volatile(" ldr r0, =0x400FF0D4 \n" // Port D
" ldr r1, [r0, #0] \n"
" and r1, #0b11111111111111111111110111110111 \n"
" str r1, [r0, #0] \n"
" sub r0, #0x40 \n" // Port C
" ldr r1, [r0, #0] \n"
" and r1, #0b11111111111111111111111100000000 \n"
" str r1, [r0, #0] \n"
" sub r0, #0x40 \n" // Port B
" ldr r1, [r0, #0] \n"
" and r1, #0b11111111000000001111111111111111 \n"
" str r1, [r0, #0] \n"
);
// Global Pin Control Register
// Setup all changed signals to now be inputs.
asm volatile(" ldr r0, =0x4004A084 \n" // Port B high
" ldr r1, =0x00FF0103 \n" // Bits 23:16
" str r1, [r0,#0] \n"
" add r0, #0xFFC \n" // Port C low
" ldr r1, =0x00FF0103 \n" // Bits 7:0
" str r1, [r0,#0] \n"
" add r0, #0x1000 \n" // Port D low
" ldr r1, =0x02080103 \n" // Bits 9, 3
" str r1, [r0,#0] \n"
// After writing out the data, jump to exit, we dont set the ioEvent flag as the event has been processed already.
" b irqPortD_Exit3 \n"
);
asm volatile( // Process the IO request by setting the ioEvent flag as it wasnt an MZ700 memory switch request.
" irqd20: movs r4, #1 \n"
" strb r4, %[val2] \n"
: [val2] "+m" (z80Control.ioEvent)
:
: "r4","r5","r6","r7","r8","r9","r10","r11","r12");
asm volatile(" irqPortD_Exit3: \n"
// De-assert BUSRQ nothing more to do.
" ldr r4, =0x43fe1800 \n" // CTL_BUSRQ, Set=43fe1800, Clear=43fe1900
" movs r5, #1 \n"
" str r5, [r4,#0] \n"
// Reset the triggering interrupt, PORTD_ISFR <= PORTD_ISFR
" ldr r0, =0x4004c0a0 \n"
" ldr r4, [r0, #0] \n"
" str r4, [r0, #0] \n"
// Restore registers, all done.
" pop {r0-r8,pc} \n"
:
:
: "r4","r5","r6","r7","r8","r9","r10","r11","r12");
return;
}
#endif
// Method to install the interrupt vector and enable it to capture Z80 memory/IO operations.
//
@@ -860,18 +246,10 @@ 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
_VectorsRam[IRQ_PORTD + 16] = irqPortD;
// Setup the IRQ for Z80_IORQ.
installIRQ(Z80_IORQ, IRQ_MASK_FALLING);
@@ -879,21 +257,8 @@ 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);
// Remove previous interrupts not needed in this mode.
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);
@@ -906,11 +271,7 @@ 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
_VectorsRam[IRQ_PORTD + 16] = irqPortD;
// Setup the IRQ for Z80_IORQ.
installIRQ(Z80_IORQ, IRQ_MASK_FALLING);
@@ -918,14 +279,8 @@ 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);
removeIRQ(TZ_SYSREQ);
// Set relevant priorities to meet latency.
NVIC_SET_PRIORITY(IRQ_PORTD, 0);
@@ -939,14 +294,11 @@ static void setupIRQ(void)
_VectorsRam[IRQ_PORTE + 16] = irqPortE;
// Install the method to be called when PortD triggers.
_VectorsRam[IRQ_PORTD + 16] = irqPortD_Mode0;
_VectorsRam[IRQ_PORTD + 16] = irqPortD;
// Setup the IRQ for TZ_SVCREQ.
installIRQ(TZ_SVCREQ, IRQ_MASK_FALLING);
// Setup the IRQ for TZ_SYSREQ.
installIRQ(TZ_SYSREQ, IRQ_MASK_FALLING);
// Setup the IRQ for Z80_RESET.
installIRQ(Z80_RESET, IRQ_MASK_FALLING);
@@ -976,7 +328,6 @@ static void disableIRQ(void)
// Remove the interrupts.
removeIRQ(TZ_SVCREQ);
removeIRQ(TZ_SYSREQ);
removeIRQ(Z80_IORQ);
removeIRQ(Z80_RESET);
@@ -999,11 +350,6 @@ 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);
break;
@@ -1013,11 +359,6 @@ 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);
break;
@@ -1028,9 +369,6 @@ static void restoreIRQ(void)
// Setup the IRQ for TZ_SVCREQ.
installIRQ(TZ_SVCREQ, IRQ_MASK_FALLING);
// Setup the IRQ for TZ_SYSREQ.
installIRQ(TZ_SYSREQ, IRQ_MASK_FALLING);
// Setup the IRQ for Z80_RESET.
installIRQ(Z80_RESET, IRQ_MASK_FALLING);
break;
@@ -1098,7 +436,6 @@ void setupZ80Pins(uint8_t initTeensy, volatile uint32_t *millisecondTick)
pinMap[Z80_MEM2] = Z80_MEM2_PIN;
pinMap[Z80_MEM3] = Z80_MEM3_PIN;
pinMap[Z80_MEM4] = Z80_MEM4_PIN;
pinMap[ENIOWAIT] = ENIOWAIT_PIN;
pinMap[Z80_IORQ] = Z80_IORQ_PIN;
pinMap[Z80_MREQ] = Z80_MREQ_PIN;
@@ -1113,7 +450,6 @@ void setupZ80Pins(uint8_t initTeensy, volatile uint32_t *millisecondTick)
pinMap[MB_SYSCLK] = SYSCLK_PIN;
pinMap[TZ_BUSACK] = TZ_BUSACK_PIN;
pinMap[TZ_SVCREQ] = TZ_SVCREQ_PIN;
pinMap[TZ_SYSREQ] = TZ_SYSREQ_PIN;
pinMap[CTL_BUSACK] = CTL_BUSACK_PIN;
pinMap[CTL_BUSRQ] = CTL_BUSRQ_PIN;
@@ -1207,7 +543,7 @@ void resetZ80(void)
//
__disable_irq();
pinOutputSet(Z80_RESET, LOW);
for(volatile uint32_t pulseWidth=0; pulseWidth < 100; pulseWidth++);
for(volatile uint32_t pulseWidth=0; pulseWidth < 200; pulseWidth++);
pinHigh(Z80_RESET);
pinInput(Z80_RESET);
__enable_irq();
@@ -1459,11 +795,7 @@ 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.
#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 < 4; 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);
@@ -1473,12 +805,8 @@ 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.
#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.
@@ -1529,24 +857,14 @@ 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
// 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.
#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.
@@ -1593,11 +911,7 @@ 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);
@@ -1607,9 +921,7 @@ uint8_t writeZ80IO(uint16_t addr, uint8_t data)
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.
@@ -1769,7 +1081,7 @@ void setCtrlLatch(uint8_t latchVal)
{
// Gain control of the bus then set the latch value.
//
if(reqTranZPUterBus(500) == 0)
if(reqTranZPUterBus(DEFAULT_BUSREQ_TIMEOUT) == 0)
{
// Setup the pins to perform a write operation.
//
@@ -1806,7 +1118,7 @@ uint32_t setZ80CPUFrequency(float frequency, uint8_t action)
{
// Gain control of the bus to change the CPU frequency latch.
//
if(reqTranZPUterBus(500) == 0)
if(reqTranZPUterBus(DEFAULT_BUSREQ_TIMEOUT) == 0)
{
// Setup the pins to perform a write operation.
//
@@ -1836,7 +1148,7 @@ uint8_t copyFromZ80(uint8_t *dst, uint32_t src, uint32_t size, uint8_t mainBoard
// Request the correct bus.
//
if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) )
if( (mainBoard == 0 && reqTranZPUterBus(DEFAULT_BUSREQ_TIMEOUT) == 0) || (mainBoard != 0 && reqMainboardBus(DEFAULT_BUSREQ_TIMEOUT) == 0) )
{
// Setup the pins to perform a read operation (after setting the latch to starting value).
//
@@ -1895,7 +1207,7 @@ uint8_t copyToZ80(uint32_t dst, uint8_t *src, uint32_t size, uint8_t mainBoard)
// Request the correct bus.
//
if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) )
if( (mainBoard == 0 && reqTranZPUterBus(DEFAULT_BUSREQ_TIMEOUT) == 0) || (mainBoard != 0 && reqMainboardBus(DEFAULT_BUSREQ_TIMEOUT) == 0) )
{
// Setup the pins to perform a write operation.
//
@@ -1943,7 +1255,7 @@ void fillZ80Memory(uint32_t addr, uint32_t size, uint8_t data, uint8_t mainBoard
// Locals.
uint8_t upperAddrBits = 0;
if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) )
if( (mainBoard == 0 && reqTranZPUterBus(DEFAULT_BUSREQ_TIMEOUT) == 0) || (mainBoard != 0 && reqMainboardBus(DEFAULT_BUSREQ_TIMEOUT) == 0) )
{
// Setup the pins to perform a read operation (after setting the latch to starting value).
//
@@ -1986,7 +1298,7 @@ void captureVideoFrame(enum VIDEO_FRAMES frame, uint8_t noAttributeFrame)
{
// Locals.
if(reqMainboardBus(500) == 0)
if(reqMainboardBus(DEFAULT_BUSREQ_TIMEOUT) == 0)
{
// Setup the pins to perform a read operation (after setting the latch to starting value).
//
@@ -2033,7 +1345,7 @@ void refreshVideoFrame(enum VIDEO_FRAMES frame, uint8_t scrolHome, uint8_t noAtt
{
// Locals.
if(reqMainboardBus(500) == 0)
if(reqMainboardBus(DEFAULT_BUSREQ_TIMEOUT) == 0)
{
// Setup the pins to perform a write operation.
//
@@ -2220,10 +1532,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(500);
reqTranZPUterBus(DEFAULT_BUSREQ_TIMEOUT);
} else
{
reqMainboardBus(500);
reqMainboardBus(DEFAULT_BUSREQ_TIMEOUT);
}
// If successful, setup the control pins for upload mode.
@@ -2407,7 +1719,7 @@ FRESULT saveZ80Memory(const char *dst, uint32_t addr, uint32_t size, t_svcDirEnt
if(!fr0)
{
if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) )
if( (mainBoard == 0 && reqTranZPUterBus(DEFAULT_BUSREQ_TIMEOUT) == 0) || (mainBoard != 0 && reqMainboardBus(DEFAULT_BUSREQ_TIMEOUT) == 0) )
{
// Setup the pins to perform a read operation (after setting the latch to starting value).
//
@@ -2501,7 +1813,7 @@ int memoryDumpZ80(uint32_t memaddr, uint32_t memsize, uint32_t dispaddr, uint8_t
// Request the correct bus.
//
if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) )
if( (mainBoard == 0 && reqTranZPUterBus(DEFAULT_BUSREQ_TIMEOUT) == 0) || (mainBoard != 0 && reqMainboardBus(DEFAULT_BUSREQ_TIMEOUT) == 0) )
{
// Setup the pins to perform a read operation (after setting the latch to starting value).
//
@@ -2789,7 +2101,7 @@ uint8_t setZ80SvcStatus(uint8_t status)
// Request the tranZPUter bus.
//
if(reqTranZPUterBus(500) == 0)
if(reqTranZPUterBus(DEFAULT_BUSREQ_TIMEOUT) == 0)
{
// Setup the pins to perform a write operation.
//
@@ -4321,11 +3633,7 @@ void processServiceRequest(void)
// 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)
#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);
}
@@ -4342,11 +3650,7 @@ void processServiceRequest(void)
// 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)
#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,7 +9,8 @@
// 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.
// Jul 2020 - Updates to accommodate v2.1 of the tranZPUter board.
// Sep 2020 - Updates to accommodate v2.2 of the tranZPUter board.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -36,15 +37,10 @@
// 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.
// 0 = No code other than direct service request interrupts.
// 1 = Decode Z80 I/O address operations.
// 2 = Decode Z80 I/O operations with data.
// 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
#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.
// tranZPUter Memory Modes - select one of the 32 possible memory models using these constants.
//
@@ -199,15 +195,14 @@
// Pin Constants - Pins assigned at the hardware level to specific tasks/signals.
//
#define MAX_TRANZPUTER_PINS 53
#define MAX_TRANZPUTER_PINS 51
#define Z80_MEM0_PIN 16
#define Z80_MEM1_PIN 17
#define Z80_MEM2_PIN 19
#define Z80_MEM3_PIN 18
#define Z80_MEM4_PIN 49
#define ENIOWAIT_PIN 50
#define Z80_WR_PIN 48
#define Z80_RD_PIN 55
#define Z80_MEM4_PIN 71 // 49
#define Z80_WR_PIN 20 // 48
#define Z80_RD_PIN 5 // 55
#define Z80_IORQ_PIN 8
#define Z80_MREQ_PIN 7
#define Z80_A0_PIN 15
@@ -222,13 +217,13 @@
#define Z80_A9_PIN 36
#define Z80_A10_PIN 37
#define Z80_A11_PIN 38
#define Z80_A12_PIN 3
#define Z80_A13_PIN 4
#define Z80_A14_PIN 26
#define Z80_A15_PIN 27
#define Z80_A16_PIN 33
#define Z80_A17_PIN 34
#define Z80_A18_PIN 24
#define Z80_A12_PIN 64 // 3
#define Z80_A13_PIN 65 // 4
#define Z80_A14_PIN 66 // 26
#define Z80_A15_PIN 67 // 27
#define Z80_A16_PIN 68 // 33
#define Z80_A17_PIN 69 // 34
#define Z80_A18_PIN 70 // 24
#define Z80_D0_PIN 0
#define Z80_D1_PIN 1
#define Z80_D2_PIN 29
@@ -237,22 +232,21 @@
#define Z80_D5_PIN 46
#define Z80_D6_PIN 44
#define Z80_D7_PIN 45
#define Z80_WAIT_PIN 54
#define Z80_BUSACK_PIN 5
#define Z80_WAIT_PIN 31 // 54
#define Z80_BUSACK_PIN 24 // 5
#define Z80_NMI_PIN 39
#define Z80_INT_PIN 28
#define Z80_RESET_PIN 6
#define SYSCLK_PIN 25
#define CTL_RFSH_PIN 53
#define CTL_HALT_PIN 51
#define CTL_M1_PIN 20
#define CTL_RFSH_PIN 4 // 53
#define CTL_HALT_PIN 26 // 51
#define CTL_M1_PIN 3 // 20
#define CTL_BUSRQ_PIN 2
#define CTL_BUSACK_PIN 21
#define CTL_CLK_PIN 14
#define CTL_CLKSLCT_PIN 47
#define CTL_CLKSLCT_PIN 32 // 47
#define TZ_BUSACK_PIN 52
#define TZ_SVCREQ_PIN 56
#define TZ_SYSREQ_PIN 57
#define TZ_SVCREQ_PIN 33 // 56
// IRQ mask values for the different types of IRQ trigger.
//
@@ -294,13 +288,13 @@
#define pinIndex(a) getPinIndex(pinMap[a])
#define setZ80Data(a) { GPIOB_PDOR = (GPIOB_PDOR & 0xff00ffff) | ((a << 16) & 0x00ff0000); }
#define setZ80Addr(a) { GPIOA_PDOR = (GPIOA_PDOR & 0xffff0fff) | (a & 0x00000f000); GPIOC_PDOR = (GPIOC_PDOR & 0xfffff000) | (a & 0x00000fff); }
#define setZ80Addr(a) { GPIOC_PDOR = (GPIOC_PDOR & 0xffff0000) | (a & 0x0000ffff); }
#define setZ80AddrLower(a) { GPIOC_PDOR = (GPIOC_PDOR & 0xffffff00) | (a & 0x000000ff); }
#define setZ80RefreshAddr(a) { GPIOC_PDOR = (GPIOC_PDOR & 0xffffff80) | (a & 0x0000007f); }
#define readZ80AddrLower() ( GPIOC_PDIR & 0x000000ff )
#define readZ80Addr() ( (GPIOA_PDIR & 0x00000f000) | (GPIOC_PDIR & 0x00000fff) )
#define readZ80Addr() ( (GPIOC_PDIR & 0x0000ffff) )
#define readZ80DataBus() ( (GPIOB_PDIR >> 16) & 0x000000ff )
#define readCtrlLatch() ( GPIOB_PDIR & 0x0000003f )
#define readCtrlLatch() ( ((GPIOB_PDIR & 0x00000200) >> 5) | (GPIOB_PDIR & 0x0000000f) )
#define writeCtrlLatch(a) { writeZ80IO(IO_TZ_CTRLLATCH, a); }
#define setZ80Direction(a) { for(uint8_t idx=Z80_D0; idx <= Z80_D7; idx++) { if(a == WRITE) { pinOutput(idx); } else { pinInput(idx); } }; z80Control.busDir = a; }
#define reqZ80BusChange(a) { if(a == MAINBOARD_ACCESS && z80Control.ctrlMode == TRANZPUTER_ACCESS) \
@@ -366,30 +360,28 @@ enum pinIdxToPinNumMap {
Z80_MEM2 = 29,
Z80_MEM3 = 30,
Z80_MEM4 = 31,
ENIOWAIT = 32,
Z80_IORQ = 33,
Z80_MREQ = 34,
Z80_RD = 35,
Z80_WR = 36,
Z80_WAIT = 37,
Z80_BUSACK = 38,
Z80_IORQ = 32,
Z80_MREQ = 33,
Z80_RD = 34,
Z80_WR = 35,
Z80_WAIT = 36,
Z80_BUSACK = 37,
Z80_NMI = 39,
Z80_INT = 40,
Z80_RESET = 41,
MB_SYSCLK = 42,
TZ_BUSACK = 43,
TZ_SVCREQ = 44,
TZ_SYSREQ = 45,
Z80_NMI = 38,
Z80_INT = 39,
Z80_RESET = 40,
MB_SYSCLK = 41,
TZ_BUSACK = 42,
TZ_SVCREQ = 43,
CTL_BUSACK = 46,
CTL_BUSRQ = 47,
CTL_RFSH = 48,
CTL_HALT = 49,
CTL_M1 = 50,
CTL_CLK = 51,
CTL_CLKSLCT = 52
CTL_BUSACK = 44,
CTL_BUSRQ = 45,
CTL_RFSH = 46,
CTL_HALT = 47,
CTL_M1 = 48,
CTL_CLK = 49,
CTL_CLKSLCT = 50
};
// Possible control modes that the K64F can be in, do nothing where the Z80 runs normally, control the Z80 and mainboard, or control the Z80 and tranZPUter.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 PJRC.COM, LLC.
* Copyright (c) 2020 P. D. Smart, tranZPUter SW updates.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -105,6 +106,17 @@ const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM
{GPIO_BITBAND_PTR(CORE_PIN62_PORTREG, CORE_PIN62_BIT), &CORE_PIN62_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN63_PORTREG, CORE_PIN63_BIT), &CORE_PIN63_CONFIG},
#endif
// tranZPUter v2.2 additional pins.
#ifdef CORE_PIN64_PORTREG
{GPIO_BITBAND_PTR(CORE_PIN64_PORTREG, CORE_PIN64_BIT), &CORE_PIN64_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN65_PORTREG, CORE_PIN65_BIT), &CORE_PIN65_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN66_PORTREG, CORE_PIN66_BIT), &CORE_PIN66_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN67_PORTREG, CORE_PIN67_BIT), &CORE_PIN67_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN68_PORTREG, CORE_PIN68_BIT), &CORE_PIN68_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN69_PORTREG, CORE_PIN69_BIT), &CORE_PIN69_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN70_PORTREG, CORE_PIN70_BIT), &CORE_PIN70_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN71_PORTREG, CORE_PIN71_BIT), &CORE_PIN71_CONFIG},
#endif
};
#elif defined(KINETISL)