Close
0%
0%

z80ctrl

AVR-based bootloader and IO card for RC2014 retrocomputer

Similar projects worth following
z80ctrl is an AVR-based bootloader, debugger, and I/O device for a Z80 retrocomputer with the following features:

- Plug-in modules for RC2014 extended bus. A complete Z80 computer on two boards.
- Runs CP/M-based software including WordStar, Zork, Ladder, Turbo Pascal and more!
- Allows CP/M programs to seamlessly run and access files from a FAT32-formatted SD Card
- Provides Altair-compatible serial ports and disk controller
- Full compatibility with unmodified Altair disk images from the SIMH emulator project
- Monitor with memory inspector and built-in Z80 disassembler
- Single-step debugging, breakpoints, and watchpoints to trace Z80 bus activity in real-time
- Allows bridging other SPI peripherals to the Z80 using the optional I/O expander card
- Flexible MIT-licensed firmware can be the basis of your own SBC or breadboard computer

Visit the GitHub Repo for all project artifacts and the GitHub Wiki for documentation. 

Kits are available on Tindie.

hex - 175.04 kB - 02/09/2021 at 03:59

Download

Zip Archive - 133.80 kB - 10/05/2020 at 02:11

Download

Zip Archive - 158.35 kB - 10/05/2020 at 02:11

Download

x-zip-compressed - 165.47 kB - 01/12/2019 at 19:39

Download

  • Hello, Reinvented Retro Judges!

    J.B. Langston06/17/2021 at 20:28 0 comments

    This project has been a multi-year labor of love. I haven't had much time to work on it since last year but it suits this challenge to a tee.  I'm combining a retro Z80 with peripherals emulated on a modern AVR microcontroller to run CP/M, MSX software, ColecoVision games, and more. Check out the linked YouTube video for an overview and peruse the project log for the history of the project and a lot of ideas for what it can do.

  • z80ctrl Rev 6 and CPU/RAM/RTC Board

    J.B. Langston10/03/2020 at 18:47 0 comments

    I've just put the final touches on a new revision of z80ctrl, plus a new companion module that combines a Z80 CPU, 512KB bankable RAM, and and RTC on a single board.  

    I expect kits for the new CPU board will be sold on Tindie and z80ctrl kits will be updated to Rev 6 once the current inventory of Rev 4 boards is sold out.  The timing will be up to Michael Kamprath who is selling the kits.  The current Rev 3 and Rev 4 boards will continue to be supported by the firmware, and the revision to build for will be configurable via a Makefile option.

    The z80ctrl plus the CPU board comprise a fully functional RC2014-compatible Z80 system in only two modules.  The z80ctrl, CPU/RAM/RTC board, TMS9918 video, SN76489 sound, and ColecoVision controller boards, plus Ed Brindley's YM2149 sound board all fit in Steven Cousin's 6 slot SC112 backplane, making for quite a compact package which has everything needed to run CP/M, ColecoVision, and MSX software.

    CPU/RAM/RTC Board Features

    Z80 CPU

    This board is intended to use the Zilog Z84C0010PEG 10MHz Z80 CPU. Other pin-compatible Z80 chips may work, but the z80ctrl can generate a clock signal up to 10MHz, so the CPU should be fast enough to handle this. The CPU is connected to the RAM and RC2014 bus. There are pullup resistors for the NMI, WAIT, BUSRQ, and INT lines to prevent false triggering. The RESET line is expected to be pulled up on the backplane.

    512KB Banked RAM

    The 512KB RAM is divided into 16 32KB banks, any of which can be mapped into the upper and lower halves of the Z80's 64KB address space. The two 4-bit bank addresses are stored in an 8-bit register accessible at I/O addresses 70-7FH. All 16 addresses are mirrors of the same register. The bank register is write-only so software must independently keep track of the current bank addresses. The lower nybble specifies the bank for the lower 32K and the upper nybble specifies the bank for the upper 32K. Therefore a value of 10H maps the first 64K of physical RAM to the Z80's 64K address space. The bank register is not initialized on power up so random banks will be selected until the z80ctrl initializes it.

    DS1302+ Three-Wire RTC

    The DS1302+ RTC chip is connected to the SPI signals that the z80ctrl exposes on the user lines of the RC2014 bus. The SCK, MISO, and AUXCS1 lines from the z80ctrl board are used. The MISO line handles both inbound and outbound traffic since the RTC uses a three-wire protocol instead of true SPI. When the z80ctrl wants to access the RTC, it disables SPI, asserts the AUXCS1 line, and bit-bangs the three-wire protocol using the SCK and MISO lines.  The CPU is not directly connected to the RTC chip, so the z80ctrl board is required to access it.  The z80ctrl exposes the RTC to the Z80 on I/O ports 00-02H. A value of 0 should be written to port 0 to select the RTC (other values may be used to select different SPI peripherals on other boards). Port 1 should be set to the address of the desired RTC register from the datasheet. The selected value can then be read or written on port 2.

    z80ctrl Rev 6 Features

    Wait State Fix

    All revisions of z80ctrl have a jumper that controls which I/O addresses wait states are generated for: none, all, or a configurable block of 32 addresses (00-1FH, 20-3FH, 40-7FH, 80-FFH). Unfortunately in REV3 and REV4, setting the jumper to any setting other than all addresses did not work because the wait signal was not connected to the AVR so it could not tell whether the Z80 was waiting for it to respond to an I/O request. Because of this, the AVR might try to respond to the IORQ signal when the Z80 had already moved on, resulting in I/O timing issues.  Rev 6 fixes this by connecting the wait signal to the AVR.

    Rearranged Control Signals

    IORQ was moved to the IO expander to make room for the WAIT signal and MREQ was moved to make room for the IO expander's interrupt signal on the...

    Read more »

  • New Features

    J.B. Langston12/22/2019 at 21:09 0 comments

    It's been a long time since my last update.  I took a break from the project for the first half of the year, and for the last few months I've been quietly working on some new features that I think are ready to announce.  First, check out the video overview, then read on below to find out more.

    Seamless CP/M Integration

    The headline feature is a BDOS emulation layer that allows unmodified CP/M programs to seamlessly integrate with z80ctrl and access files on the SD card's FAT filesystem directly without using disk images.  In addition, the z80ctrl monitor can now run .COM files directly.  This means you can copy CP/M .COM programs and their associated files directly to your SD card and run them from the z80ctrl> prompt without booting into CP/M first.  

    In order for CP/M programs to work, z80ctrl needs to load some Z80 runtime support into memory that allows the programs to access the FAT filesystem via BDOS calls.  This runtime is automatically loaded from a file called BDOS.BIN in either your root directory or the current directory.  The BDOS.BIN file should be assembled using sjasm from the bdos.asm file in the examples directory.   

    The CP/M program will be able to transparently access any files located in the current directory when the program was launched.  I plan to also add support for mounting additional directories on drives so it will be possible to access files in multiple directories at the same time, but that's not done yet.

    The current status of the BDOS emulation is pretty complete. I have been able to successfully run many programs including Turbo Pascal 3.0, Microsoft BASIC-80 (MBASIC.COM), Microsoft M80 assembler, BBC BASIC, Hi-Tech C, SuperZAP file manager, WordMaster, WordStar, Zork, Catchum, Ladder and more.  Currently the ZDE editor is the only program I am aware of that does not work. I still need to investigate why.

    For the curious, the code for the BDOS emulation is in bdosemu.c. Credit is due to the RunCPM project for showing me that it is possible to emulate BDOS calls on a  FAT filesystem and for serving as a sanity check to understand BDOS behavior when I was having trouble understanding the BDOS assembly code.  However, none of my code has been copied from RunCPM.

    The general concept of the emulation is that the BDOS runtime code establishes a DMA mailbox where the FCB address, DMA address, return code and other pertinent information can be exchanged between the Z80 and the z80ctrl.  The Z80 initiates a BDOS command by writing to port 0xC. The z80ctrl will then pick up the command, perform the necessary FAT filesystem operations, and read or write the file or directory data at the specified DMA address in the format that CP/M expects.  z80ctrl then returns control to the Z80 and the CP/M program is none the wiser that the data it requested came from a FAT filesystem.

    FatFS DMA Interface

    For programs written especially for the z80ctrl, I have also provided a way to make FatFS API calls directly from Z80  code.  The DMA interface code is in filedma.c, and an assembly library to access the DMA interface from the Z80 is available in filedma.asm.  An example filecopy.asm program that copies a file on the FAT filesystem is also provided.

    Using the FatFS API is more performant and full featured than using the BDOS emulation. Almost all FatFS API functions can be called directly from the Z80 and FAT-native features like subdirectories are therefore available.  In addition, DMA transfers are not limited to 128 bytes at a time like they are when using BDOS emulation.

    z80ctrl now automatically loads and executes files with a .PRG extension as a bare-metal program.  I borrowed the idea of .PRG files from the C64, where the first two bytes of the file encode the load address.  z80ctrl automatically loads...

    Read more »

  • z80ctrl Kits Available

    J.B. Langston01/08/2019 at 23:58 0 comments

    z80ctrl Kits are now available on Tindie.  Get 'em while they're hot!

    These kits are sold by Michael Kamprath with my permission. I do not offer any warranty or guarantee of support.

  • One Year of z80ctrl

    J.B. Langston01/04/2019 at 05:39 0 comments

    Around this time last year, I started bread boarding what would become the z80ctrl. In honor of its first birthday, I've decided to take a little trip down memory lane. 

    I made my first commit to GitHub on January 6.  It didn't do a lot back then.  It had a hard-coded program that added two numbers together and then went into an infinite loop, while the AVR printed out a trace of the signals on the Z80 bus.  But it was enough to prove that my design worked. A day later, I had the AVR doing serial I/O and the Z80 printing "hello, world".

    The first real program it ran was the Altair Turn Key Monitor a few days later.  That was followed in quick succession by a more advanced monitor, which allowed me to paste in Intel Hex programs for the Z80 to run.  By January 12, I had the SD card working and could load hex files directly from it. For the next few days, the z80ctrl monitor started to take shape. The dump and fill commands made their debut and the debugging features started to take shape. The monitor from back then is still recognizable now (although with a much longer list of commands).

    On January 15, I got Altair disk emulation working and achieved what felt like the Holy Grail: running CP/M.  On January 21, I posted my first two videos to YouTube. One detailed the Hardware:

    And the other detailed the software:

    Around this time, I started getting the idea that I wanted to design my own PCB.  I started work on a SBC that would include the Z80, memory, and AVR all on one board, but then I came across the RC2014.  I really liked the modularity of the RC2014 backplane and the community surrounding the RC2014.  So on January 20, I ordered a RC2014 Pro kit, and the next day I introduced myself to the RC2014 community.  I started working on an RC2014 module in KiCad and had a first draft by January 23. 

    My RC2014 arrived on February 1, and to prove to myself it would work, I hooked up my breadboarded circuit to the RC2014 backplane. It worked, an after a few weeks of polishing, I finally mustered the courage to place my order from OSH Park on February 16.  After 10 long days, the boards arrived, and... they didn't work.  I couldn't even get the SD card to work, and I was completely stumped.  

    I felt so defeated by the failure of my first PCB design that I took a break from the project for two months, until two members of the RC2014 mailing list, Rodney and Jay,  encouraged me keep working on it.  By April 23, both had their boards working but mine was still a no go.  Rodney offered to send me one of his boards to test, and when I got it, I found that it didn't work either.  Finally, on May 4, I figured out that it wasn't a problem with my board at all, but two lines shorted together on the RC2014 backplane. After figuring this out, my enthusiasm returned and I made a video going over the board's design and discussing some of the problems I ran into:

    I spent the next few weeks helping people on the mailing list to solve problems with their boards and making a new revision to fix the issues I had identified with the first board.  Also during this time, I got serious about documenting the project and squashed a few bugs. 

    On May 20, I started this Hackaday page. The next few weeks were my most productive period since starting the project in January. I added many... new... sofware... features.  I also designed REV3 of the board that had some major optimizations and new features.

    Also during this time, I started working on my other project, TMS9918A video card, which was the first of my game boards for RC2014. I ordered both the video card and z80ctrl rev3 at the same time.  When I got the rev3 boards built, they worked the first time. By mid-July, I was pretty happy with the point I had gotten the z80ctrl to, and I turned my attention to learning to code...

    Read more »

  • MSX-BASIC on RC2014

    J.B. Langston01/02/2019 at 00:21 0 comments

    I've gotten MSX-BASIC to run on the RC2014 with my TMS9918A video card and my z80ctrl card emulating the MSX keyboard.

    I have checked the keyboard emulation code into GitHub.  It takes ASCII characters from the z80ctrl UART and converts them into MSX keyboard scan codes using a table.  Currently it doesn't support some of the control keys on the MSX keyboard such as stop and the arrow keys.  I will keep working on this, but it's usable as is.

    The MSX-BASIC ROM can be obtained from the blueMSX emulator.  Copy MSX.rom from the Machines\Shared Roms directory of your blueMSX installation to your z80ctrl SD card. Once you've copied it, load and run it from z80ctrl:

    z80ctrl>clkdiv 5
    z80ctrl>loadbin 0 msx.rom
    z80ctrl>run 0

    One of the nice things about MSX-BASIC is that it has built-in graphics primitives for the TMS9918A video card, unlike, say, MBASIC on CP/M.  I have used these primitives to draw an analog clock using the time pulled from the RTC chip on my z80ctrl IO expander, which is shown in the video. The BASIC source code is available on GitHub.

    Currently, there is no support for MSX tape or disk drives, so you can't save your program once you have typed it in. The way I worked around this was to edit the program on my PC and then paste it into TeraTerm.  I had to set a 50 ms per-character delay in order to get the program to reliably type in when pasted.  A faster brute force method of saving your program once you have typed it in is to press the halt button on the z80ctrl and run 

    z80ctrl>savebin 8000 ffff image.bin 
    

    This will save the complete state of your BASIC interpreter so that you can load it back up the next time using and pick up where you left off.  Next time, to pick up where you left off, run

    z80ctrl>loadbin 0 msx.rom
    z80ctrl>run 0
    *press the halt button*
    z80ctrl>loadbin 8000 image.bin
    z80ctrl>run

    Your program should now be in exactly the same state as it was before. You can list it to verify it is there, then run it.

    Here are some good references I have found for MSX-BASIC.

  • Interfacing a Character LCD

    J.B. Langston12/31/2018 at 16:27 0 comments

    I've added a few examples for interfacing a character LCD with the z80ctrl IO expander board.  The specific LCD I am using was purchased from Amazon.  However, almost every character LCD you can find will use a standard interface based on the HD44780 chip, and my examples should work with any of them.

    Since the LCD has a parallel interface to begin with, one could argue that it's a bit convoluted having the Z80 talk to the AVR over the parallel bus, which converts it to a serial signal to send to the IO expander, which converts it back into a parallel signal to send to the LCD.  To that, I say: Shut up, one! It's my project and I'll do what I want!

    The pinout for a character LCD is also fairly standardized.  This is from the LCD I bought:

    Hooking up the LCD to the IO expander board is straightforward:

    • Connect pins GPA0-GPA3 from the GPIO A connector to DB4-DB7 on the LCD
    • Connect pins GPA4, GPA5, and GPA6 from the GPIO A connector to RS, R/W, and E on the LCD, respectively
    • Hook up 5V power to VDD and A on the LCD
    • Hook up ground to VSS and K on the LCD
    • Connect a 10K pot to V0 to adjust the contrast

    Once it's hooked up, I wrote a simple MBASIC program that prints "hello, world" on the LCD:

    10 GOSUB 1000
    50 C=&H33:GOSUB 3000: REM RESET SEQUENCE, PART 1
    60 C=&H32:GOSUB 3000: REM RESET SEQUENCE, PART 2
    70 C=&H28:GOSUB 3000: REM 4-BIT MODE, 2 LINES, 5x8 CHARS
    80 C=&HD:GOSUB 3000: REM DISPLAY ON, BLINKING BLOCK CURSOR
    90 C=&H1:GOSUB 3000: REM CLEAR DISPLAY
    100 INPUT "STRING TO PRINT"; S$
    110 GOSUB 5000
    120 END
    
    1000 REM INITIALIZE GPIO PORT
    1010 OUT 0, 1: REM GPIO CHIP 1
    1020 OUT 1, 0: REM DATA DIRECTION REGISTER A
    1030 OUT 2, 0: REM ALL OUTPUT
    1040 OUT 1, &H12: REM GPIO REGISTER A
    1050 RETURN
    
    2000 REM SEND BYTE IN C TO LCD
    2010 OUT 2, &H40 OR M OR (C\16) : REM TOP NYBBLE WITH ENABLE HIGH
    2020 OUT 2, M OR (C\16) : REM TOP NYBBLE WITH ENABLE LOW
    2030 OUT 2, &H40 OR M OR (C AND &HF): REM BOTTOM NYBBLE WITH ENABLE HIGH
    2040 OUT 2, M OR (C AND &HF): REM BOTTOM NYBBLE WITH ENABLE LOW
    2050 RETURN
    
    3000 REM SEND COMMAND IN C TO LCD
    3010 M=0
    3020 GOSUB 2000
    3030 RETURN
    
    4000 REM SEND CHAR IN C TO LCD
    4010 M=&H10
    4020 GOSUB 2000
    4030 RETURN
    
    5000 REM SEND STRING IN S$ TO LCD
    5010 FOR I = 1 TO LEN(S$)
    5020 C=ASC(MID$(S$,I,1))
    5030 GOSUB 4000
    5040 NEXT
    5050 RETURN

    The BASIC program has several subroutines that illustrate how to interface the LCD:

    • 1000 initializes the GPIO port on the IO expander to talk to the LCD. It sets the IODIRA register (address 0) to 0 to make all the pins outputs. Then it selects the GPIOA register (address &H12) which will be used by the rest of the program to control the output.
    • 2000 sends the byte in C to the LCD with the register select bit set in M.  To reduce the number of pins required, the LCD is used in 4-bit mode.  Therefore the program has to sends the byte 4 bits at a time, clocking the enable line each time.
    • 3000 is a wrapper that sends a command to the LCD by setting M=0 and calling 2000
    • 4000 is a wrapper that sends a character to the LCD by setting M=1 and calling 2000
    • 5000 sends a complete string in S$ to the LCD.  It iterates over each character in the string and converts it to ASCII, then calls 4000 to send each character individually
    • The main program starting at 10 sends a series of commands to initialize the LCD by setting the value of C and calling 3000 for each one.  Then it sets the value of S$ to "hello, world" and calls 5000 to send the string.
    • Note: MBASIC is slow enough that I didn't have to check the LCD's busy flag between writes, which would have made the code considerably more complicated. Check out the assembly program below to see how that's done.

    I have also written an assembly program to retrieve the date and time from the RTC and display it on the LCD. Since it's quite long, I won't reproduce...

    Read more »

  • IO Expander from MBASIC

    J.B. Langston12/15/2018 at 21:17 2 comments

    I've recently pushed an update to the z80ctrl repo which makes my new IO expander board accessible to the Z80. 

    To access these features, you'll need to pull the latest code from the Github repo, and then uncomment the IOX_BASE variables in the Makefile. After doing so, run 'make clean' and then 'make install' to rebuild and flash the new code.  You can change the IOX_BASE if desired, but you must modify any code that will access the ports accordingly.  

    The board is exposed to the Z80 on 3 consecutive ports starting from IOX_BASE:

    • Writing to port 0 selects device you want to control.  The RTC is always device 0.  The device number of the GPIO chips correspond to the address configured on the jumpers next to the chip. If you select a non-existent device, writing to the other registers will have no effect.
    • Writing to port 1 selects the active register on the selected device. 
      • The registers for the RTC are fully documented in the DS1306+ datasheet. You can also find a concise list in rtc.h.
      • The registers for the GPIO ports are fully documented in the MCP23S17 datasheet.  You can also look in the iox.h file for a concise list of addresses. You will want to use the register addresses for bank 0 unless you change the bank configuration (read about this in the datasheet).
    • Reading or writing port 2 returns or sets the value of the selected register on the selected chip. Refer to the appropriate datasheet for the meaning of the values written to the registers.

    Here is a simple MBASIC program to flash an LED on the first GPIO port 10 times:

    10 OUT 0, 1: REM select chip address 1
    20 OUT 1, 0: REM select register IODIRA0 (0x00)
    30 OUT 2, 0: REM set register value to 0 (all pins outputs)
    40 OUT 1, &H12: REM select register GPIOA0 (0x12)
    50 FOR I = 1 TO 10
    60 OUT 2, 0: REM turn all pins on GPIOA off
    70 FOR J = 1 TO 1000:NEXT
    80 OUT 2, &HFF: REM turn all pins on GPIOA on
    90 FOR J = 1 TO 1000:NEXT
    100 NEXT

    First, we select the IO direction register on the IO expander configured at address 1, and set all pins to outputs. Then we select the GPIO register.  Within a loop, we toggle all of the pins on and then off, pausing between each transition.

    Here is an MBASIC program demonstrating how to read the time from the RTC:

    10 REM CONVERT VALUES FROM BCD
    20 DEF FNBCD(V)=(V AND &HF0)/16*10+(V AND &HF)
    30 OUT 0,0: REM SELECT RTC CHIP
    40 REM READ DATE/TIME FROM RTC REGISTERS
    50 OUT 1,6: YR=FNBCD(INP(2))+2000
    60 OUT 1,5: MO=FNBCD(INP(2))
    70 OUT 1,4: DY=FNBCD(INP(2))
    80 OUT 1,2: HR=INP(2)
    90 OUT 1,1: MI=FNBCD(INP(2))
    100 OUT 1,0: S=FNBCD(INP(2))
    110 REM HANDLE AM/PM
    120 AMPM$=""
    130 IF (HR AND &H40)=0 THEN 160: REM SKIP IF 24-HR FORMAT
    140 IF HR AND &H20 THEN AMPM$="PM" ELSE AMPM$="AM"
    150 HR=HR AND &H1F: REM GET RID OF AM/PM AND 12-HR BITS
    160 HR=FNBCD(HR)
    170 PRINT USING "The time is ##:##:##& on ##/##/####"; HR, MI, S, AMPM$, MO, DY, YR

    First, we select the RTC device, then read the year, month, day, hour, minute, and second from the corresponding register on the chip.  Next, we check to see if the 12 hour bit is set. If so, we check whether the time is currently AM or PM and then mask off those bits.  Now, we convert all the values from BCD (as they are returned by the RTC) into binary so that BASIC can print them properly.  Finally, we output the date and time in a standardized format. 

  • REV4 Complete

    J.B. Langston12/05/2018 at 03:17 0 comments

    I have completed REV4 of the z80ctrl board. This revision makes the following changes:

    Adds a diode on the /WAIT line to convert it to an open drain output. This is necessary to prevent contention when other boards (such as my SN76489 sound card) need to use the /WAIT line also.  If you plan to use a REV3 board with the SN76489 board, you must cut the wait trace and solder a diode in its place to prevent contention.

    Updates the wait state generator to allow debugging with an external clock. Previously, z80ctrl only generated wait states for IORQ and when debugging, it single stepped the Z80's clock in software.  Now it can optionally also generate wait states for MREQ so that execution of the Z80 can be paused for each memory fetch to allow debugging when the clock cannot be manually controlled.  A jumper (J9) is provided to select between CLK and WAIT modes.  In CLK mode, pin 20 of the AVR is connected to the CLK line on the RC2014 bus, and the z80ctrl provides the Z80's clock like it has in all previous revisions.  In WAIT mode, an external clock must be used and pin 20 is instead used to enable and disable wait states for MREQs. I have not yet written the software to support this mode of operation but the REV4 board will work the same way as REV3 and earlier when the CLK jumper is shorted. Important Note: U3 is now a 74HCT02 quad NOR gate instead of a 74HCT74 dual flip-flop used on previous revisions.

    Adds a jumper to optionally connect the AVR reset pin to the D15 line on the RC2014 bus, which is normally unused. This line can also optionally be connected to the I/O expander's reset pins on the new I/O expander board, allowing the I/O expanders to be reset to a known state whenever the z80ctrl is reset.

  • IO Expander Board

    J.B. Langston11/25/2018 at 22:08 0 comments

    I've recently designed an I/O expander companion board for the z80ctrl that adds an RTC, up to 4 8-bit GPIO ports, and 4 SPI ports.  

    The board makes use of the same MCP23S17 I/O Expander used on the z80ctrl. All of the I/O expanders share the same chip select line and are addressed by a configurable 3-bit address, allowing a total of 8 I/O expanders to share a chip select line.  Jumpers are provided to set the address, so up to 3 I/O expander boards can be added to the RC2014 if desired, giving a maximum of 24 8-bit GPIO ports. The I/O expander on the z80ctrl board which interfaces with the RC2014 bus is hard-coded to address 0, so only address 1 and higher should be configured for the I/O expanders on this board.

    The board also contains a DS1306+ SPI RTC with a battery backup and 32 kHz crystal. This allows the AVR to keep track of the time in order to correctly timestamp files on the SD Card. It can also share the RTC over the Z80's parallel bus so that the RTC is accessible to CP/M, FUZIX, or other operating systems running on the Z80.

    The board allows for up to 4 additional SPI chip selects to connect other SPI peripherals to the board. This is done by ORing the upper 4 bits of the GPIO_B port with the AUX2_CS line from the AVR.  The additional chip select will only become active when both corresponding the GPIO_B line and the AUX2_CS line are set low.  This way, the AVR can communciate with the I/O expander to enable the additional chip selects, but they will only become active once communication with the I/O expander is complete.

    An inverter was also required because the RTC uses an active high chip select whereas most SPI peripherals use active low.  Since I had 5 additional inverters in the package, I also inverted the outputs of the OR gate and exported both the active high and active low chip selects on each of the 4 SPI ports.

    The KiCad design files for the board are available in the GitHub Repo and further details are provided on the GitHub Wiki.

    I have updated the z80ctrl firmware to use the RTC to set the timestamp when creating new files on the SD card. The date can also be viewed and set using the new date monitor command.

    I have also added ioxwrite and ioxread monitor commands that directly write or read I/O expander registers.  This allows low-level configuration of each I/O expander.  The commands take the address of the I/O expander configured via the jumper, and the hex address of the register that you want to interact with.  Refer to the MCP23S17 datasheet for information about the specific registers.  Additional high-level commands can be added to the firmware if a specific function for the I/O expanders is desired.

    Many thanks to JLCPCB for sponsoring the prototypes of this board. Whether  you want to manufacture my boards for your RC2014, or you need to prototype your own electronic project, JLCPCB is an excellent choice. They produce top quality PCBs for an incredibly low price and their service is fast.  I routinely get 5 day or quicker turnaround on my projects, order placed to board in hand.

View all 19 project logs

View all instructions

Enjoy this project?

Share

Discussions

Yoshitaka Kuwata wrote a day ago point

Hi, I modified your project to work with w65c02, which I named '6502ctrl'. I placed the project code at https://github.com/kuwatay/6502ctrl. I designed PCB to use Arduino Mega. I could run OSI-(MS) BASIC and woz monitor with it.

Thank you for your code.

  Are you sure? yes | no

J.B. Langston wrote a day ago point

Neat! I will try it out if I get a chance.

  Are you sure? yes | no

Yoshitaka Kuwata wrote 19 hours ago point

I have extra PCB. I'm happy to send you a PCB. Please contact me if you are interested in it.

  Are you sure? yes | no

caiannello wrote 06/17/2021 at 21:33 point

Hi, I hope to adapt this project to work with a hitachi 63c09ep.  Would it be hard to have a 2-phase CPU clock that ran at 3.58MHz?  

  Are you sure? yes | no

Axel.ahlborn wrote 06/03/2021 at 11:01 point

Hi, am I able to use the RC2014 Raspberry PI Terminal in conjunction with the z80ctrl ?

Greetings Axel Ahlborn

  Are you sure? yes | no

J.B. Langston wrote 06/12/2021 at 20:17 point

z80ctrl puts its serial signals on the bus on the same pins as the SIO module, so in theory it should work with the RPi Terminal. I have never tested it though. Note: you need to remove the SIO module if you install z80ctrl because otherwise you will have two devices trying to control the same serial bus.

  Are you sure? yes | no

bert.hoogenboom wrote 02/24/2021 at 18:19 point

Check your fuse settings of the Atmel chip. The  fuse for the JTAG interface must by off.  The JTAG interface messes up some pin's of the ATMEGA  

  Are you sure? yes | no

hackaday wrote 02/24/2021 at 21:35 point

I'm pretty sure the makefile uses 'avrdude -P usb -c avrispmkii -p atmega1284p -U lfuse:w:0xf7:m hfuse:w:0xd6 efuse:w:0xfd' but I went and flashed that again just to be sure and it did not help. http://eleccelerator.com/fusecalc/fusecalc.php?chip=atmega1284p shows 0xd6 high fuse does not include JTAGEN

  Are you sure? yes | no

J.B. Langston wrote 02/25/2021 at 19:45 point

He wouldn't have gotten this far if the fuses were wrong.

  Are you sure? yes | no

hackaday wrote 01/28/2021 at 22:02 point

I just built the Kamprath-sold rev4 board and can't get it to actually work with the companion z80ram CPU RAM RTC Board. At the monitor z80ctrl:/> prompt CLK sits steady at 5V, and when 'run' is executed it drops down to a noisy zero volts. I can run a simple pin toggling program for pin 20 and it shows up on CLK nicely on my scope, but that's it. I've re-installed the mighty 1284p bootloader with the settings given in the assembly instructions and 'make install' is able to upload the monitor. No idea if there's other issues, but I figure without CLK it's not going anywhere.

  Are you sure? yes | no

J.B. Langston wrote 01/29/2021 at 20:43 point

Do you have the CLK/WAIT jumper in the CLK position?

  Are you sure? yes | no

hackaday wrote 02/01/2021 at 19:52 point

Yes. I have also tried it on 'WAIT' and in that position I get 'bus request timed out'

  Are you sure? yes | no

J.B. Langston wrote 02/01/2021 at 22:02 point

That jumper should always be set to CLK. Software support for the WAIT mode is not done.  If you've got it set to CLK, then I'm not sure what's wrong. The clock is generated by a PWM output and should be 10MHz by default.  Is your oscilloscope able to sample signals that fast?  Reason I ask is some cheap scopes like the DSO nano can't go that high. You could try using the clkdiv command to set it to a much slower clock and see if works. "clkdiv 200" should output a 100 kHz clock.  Are you connecting the scope directly to the clock output on the z80ctrl? Is there anything else on the bus that could be pulling it down?

  Are you sure? yes | no

hackaday wrote 02/01/2021 at 22:25 point

(not sure why I can't reply below this one)
Even with the board removed from the backplane and powered via the USB serial adapter, there's no clock signal on the RC2014 pins or physical pin 20 of the 1284p. On both my z80ctrl and z80 RAM/ROM/RTC all pins have continuity to the CPU/RAM/MCU as they should, so I'm confident there's no solder issues.

Only way I've been able to get anything to show up on hardware pin 20 is to run a simple program which software toggles the pin.

Is it possible there's something broken with MIghty 1284p in it's current form? I'll try flashing the supplied bootloader hex file and see if that works.

  Are you sure? yes | no

hackaday wrote 02/01/2021 at 22:42 point

Flashed the bootloader with "avrdude -P usb -c avrispmkii -p atmega1284p -U optiboot_flash_atmega1284p_UART0_115200_20000000L_B0_BIGBOOT.hex" and then ran a 'make install' to load the firmware. Same result though, no CLK.


I have a 60 MHz scope, so no issues with looking at a 10 MHz signal.

  Are you sure? yes | no

J.B. Langston wrote 02/03/2021 at 23:03 point

Do you have your fuse bits set appropriately?  See the last bullet here: https://github.com/jblang/z80ctrl/wiki/Board-Assembly-Instructions#installing-a-bootloader

If that doesn't work, I don't know.  I can't think of any reason why manually toggling the pin would work when outputting the PWM signal on it wouldn't.  This is the code that generates the signal: https://github.com/jblang/z80ctrl/blob/master/firmware/bus.c#L54-L61

You could try that in a standalone program and see if it works. You'll also need to set the pin to an output:

DDRD |= (1 << 6);

  Are you sure? yes | no

hackaday wrote 02/04/2021 at 02:28 point

I tried the suggested code. With

    OCR2A = (4);
    OCR2B = (4) >> 1;

I get 31.25 KHz on CLK per the scope. I have also set the fuse bits manually as suggested, but this didn't make the z80ctrl code work with regards to CLK.

Here's some info about the git commit I have:

$ git log
commit b825d1a6b06b3fab9ced50fe321f78a82c897402 (HEAD -> master, origin/master, origin/HEAD)
Author: J.B. Langston <jb.langston@gmail.com>
Date:   Thu Nov 26 20:32:17 2020 -0600

    Fix delay between files

commit 2394ac0e62ad55c0b558e3b5ae3f561170369bb6
Author: J.B. Langston <jb.langston@gmail.com>
Date:   Thu Nov 26 20:28:11 2020 -0600

    Add Xmodem prompt back

commit 466d6baf21e84658cd577b9ff4ae17ce1cf89e82
Author: J.B. Langston <jb.langston@gmail.com>
Date:   Thu Nov 26 19:42:29 2020 -0600

    Update graphical clock example to work with both DS1306 and DS1302

commit 45d1bc6fdd7e1e4119afcd7a0af1088aaf52f2e9
Author: J.B. Langston <jb.langston@gmail.com>
Date:   Thu Nov 26 19:31:17 2020 -0600

    Update RTC example to work with both DS1306 and DS1302

commit 6caf0c18aa9d184e5a779a9800fe62edf5965fb8
Author: J.B. Langston <jb.langston@gmail.com>
Date:   Thu Nov 26 18:33:45 2020 -0600

    Add CPU/RAM/RTC board schematic

commit cfd0b77ddb5cb2ef8eb5d371c0673b9228468312
Author: J.B. Langston <jb.langston@gmail.com>
Date:   Tue Nov 24 19:01:33 2020 -0600





  Are you sure? yes | no

J.B. Langston wrote 02/04/2021 at 21:24 point

You have the latest commit.  Do you have the right BOARD_REV set to 4 in your Makefile?  Needs to match the hardware you have.

  Are you sure? yes | no

hackaday wrote 02/05/2021 at 18:59 point

Yes.. Here's what I have set:

# Hardware revision (Important: must be set to correct value)
BOARD_REV?=4

# Bank address for z80ctrl-style banked RAM; comment out to disable support
BANK_PORT=0x78

# Base address for RomWBW-style banked RAM; comment out to disable support
# BANK_BASE=0x78

# Uncomment to enable support for SST39F0x0 flash chips on RomWBW boards
# SST_FLASH=1

# Uncomment to enable DS1306 RTC support (used on IOX board)
# DS1306_RTC=1

# Uncomment to enable DS1302 RTC support (used on CPU/RAM/RTC board)
DS1302_RTC=1

# Base address TMS9918A chip; comment out to disable support
TMS_BASE=0xBE

# Port assigned to SN76489 sound chip
SN76489_PORT=0xFF

# Base port on which to expose I/O expander card to Z80
# IOX_BASE=0x00

# Base port for MSX keyboard
#MSX_KEY_BASE=0xA9

# Current git hash
GITVERSION:= $(shell git log -1 --pretty='%h')

# MCU type and frequency
MCU?=atmega1284p
F_CPU?=20000000L

# Programmer options
PROGRAMMER?=arduino
PORT?=/dev/ttyUSB0
BAUD?=115200

AVRCC?=avr-gcc
OBJCOPY?=avr-objcopy
AVRDUDE?=avrdude


  Are you sure? yes | no

J.B. Langston wrote 02/06/2021 at 22:03 point

That all looks fine.  Sorry, I am stumped as to what the problem could be...

  Are you sure? yes | no

hackaday wrote 02/07/2021 at 16:35 point

When the z80ctrl is running at the serial input prompt, is CLK being generated or is this only when the 'run' command is issued? If only when 'run', is is checking for some status from the z80? I don't have a good way to test the z80 board by itself as I don't have a separate serial I/O board. My other setups are all Z180 or Z280, so they have serial on the CPU card.

  Are you sure? yes | no

J.B. Langston wrote 02/08/2021 at 15:05 point

It only generates the clock while run is issued. Another thing you could try is to use debug instead. That manually generates the clock by toggling the pin using normal GPIO instead of using the PWM signal.  It's too slow to run complex software but it would work for testing with hello world.

  Are you sure? yes | no

J.B. Langston wrote 02/08/2021 at 15:13 point

You can see exactly what the run command does here: https://github.com/jblang/z80ctrl/blob/master/firmware/z80.c#L83-L134

It does a bus_release, which checks for the BUSACK signal from the Z80 to go high after it releases the BUSREQ signal: https://github.com/jblang/z80ctrl/blob/master/firmware/bus.c#L103-L123.  

However, if that doesn't happen after 256 clock cycles it will time out and print a message that it did so.There are some #ifdefs there for the different board revisions because REV4 doesn't a way to quickly check the halt and reset signals so some of the logic I use there is different.  I am usually developing with REV6 so it's possible I have made a mistake here, but I'm 99% sure I tested this code on REV4 before I checked it in.  I will try it again once I get a chance to be sure.  However, even if there is a mistake in that logic, I would still expect the clock to be started because that happens outside of any ifdefs.

  Are you sure? yes | no

hackaday wrote 02/09/2021 at 01:12 point

On 'run 100' I see BUSACK and BUSREQ  high.

I thought I might see if you had a release specific to rev4 of the hardware and found this: https://github.com/jblang/z80ctrl/releases/tag/REV4 but it won't compile with BOARD_REV=4.

  Are you sure? yes | no

J.B. Langston wrote 02/09/2021 at 04:01 point

The REV4 tag is for the hardware, not the firmware. The latest firmware maintains compatibility with REV3 later.

I've just tried the latest commit, b825d1a, on my REV4 board and it works fine. I'm truly baffled what could be wrong with your board. As a sanity check, I have added z80ctrl-REV4-b825d1a.hex to the downloads here on my project page. This is the exact same image I flashed to my REV4 board.  Try flashing that and see if it makes any difference, though I don't see how it would.

Also, please do try the debug test I suggested.  In case you missed that reply what I said was:

 Another thing you could try is to use the debug command instead. That manually generates the clock by toggling the pin using normal GPIO instead of using the PWM signal.  It's too slow to run complex software but it would work for testing with hello world.

  Are you sure? yes | no

hackaday wrote 02/09/2021 at 16:56 point

Running via 'debug 100' hangs as well, as with the new firmware file. Here are some photos of my boards: https://www.matrixwide.com/wp/2021/02/troubeshooting-z80ctrl-board/

I am sure this is something very simple but I'm unable to see it. Thanks for hanging in there with me.

  Are you sure? yes | no

hackaday wrote 02/09/2021 at 16:58 point

Here's what I get running the ctrl board without the CPU board - there's no error message:

z80ctrl:/>loadhex hello.hex
loading from hello.hex
loaded 45 bytes total from 0100-012c
z80ctrl:/>run 100
z80ctrl:/>

  Are you sure? yes | no

hackaday wrote 02/09/2021 at 17:04 point

OK interesting. With the CPU board out, running via 'debug 100' gives 1.249 MHz on CLK. No CLK if I just use 'run 100' and with the CPU board in, no CLK either way.

  Are you sure? yes | no

J.B. Langston wrote 02/10/2021 at 02:07 point

I don't see anything obviously wrong with your board, but if you're seeing a clock with the CPU board out that makes me think either the CPU is bad or there is a short between the CLK line and something else somewhere on the CPU board.  I would check for continuity between CLK and any other pins near it both on the CPU and the bus header. 

With the CPU board out, I'm not surprised that run doesn't work, but if debug is able to produce a clock signal without the CPU that definitely seems like a fault on the CPU board.

  Are you sure? yes | no

J.B. Langston wrote 02/10/2021 at 02:18 point

Zooming in on the photos I see a few things on both the CPU and z80ctrl boards that could be errant solder blobs, or they could just be reflections in the flux--it's hard to tell. Getting the flux off would make it easier to tell if there are any actual solder bridges, and flux itself can be mildly conductive.

I would take a toothbrush with some isopropyl and remove the flux. It will make a sticky mess when you do, so it may take a few passes, rinsing the toothbrush in clean isopropyl between them.  Once you got it mostly clean, take an old tshirt, place it over the back of the board, dampen your toothbrush in alcohol, and run it over the shirt while it's pressed against the board. The idea is to get the shirt in between the pins so it can wick up any flux/isopropyl mixture that is going to be sticky when it dries. It may take a few tries, but I've been able to get my boards pretty clean with this method.

  Are you sure? yes | no

hackaday wrote 02/10/2021 at 14:31 point

I've cleaned the boards and don't see any solder bridges under a 10x loupe. Continuity is good on the pins near CLK. So far, I have swapped everything on the board except the 74HCT574 as I don't have a DIP version of that on hand. I'll either order one or craft an adapter for an SOIC size one I do have.

  Are you sure? yes | no

J.B. Langston wrote 02/10/2021 at 15:03 point

Never say never, but I see no way that the 74HCT574, or any of the logic chips for that matter, could affect the clock signal. They are not connected to it, and they are only used to set the memory bank address.

By everything, I guess that means you tested a different Z80 too?

  Are you sure? yes | no

hackaday wrote 02/10/2021 at 18:51 point

Yes, I have a Zilog Z0840006PSC Z80.

I also swapped my backplanes. No luck with that either.

  Are you sure? yes | no

hackaday wrote 02/10/2021 at 19:01 point

Also I tried the fill command below to test the RAM and at least starting at 0x0100 it looks good:

z80ctrl:/>dump 0100
ADDR   +0 +1 +2 +3  +4 +5 +6 +7  +8 +9 +A +B  +C +D +E +F   0123456789ABCDEF
00100  00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F   ................
00110  10 11 12 13  14 15 16 17  18 19 1A 1B  1C 1D 1E 1F   ................
00120  20 21 22 23  24 25 26 27  28 29 2A 2B  2C 2D 2E 2F    !"#$%&'()*+,-./
00130  30 31 32 33  34 35 36 37  38 39 3A 3B  3C 3D 3E 3F   0123456789:;<=>?
00140  40 41 42 43  44 45 46 47  48 49 4A 4B  4C 4D 4E 4F   @ABCDEFGHIJKLMNO
00150  50 51 52 53  54 55 56 57  58 59 5A 5B  5C 5D 5E 5F   PQRSTUVWXYZ[\]^_
00160  60 61 62 63  64 65 66 67  68 69 6A 6B  6C 6D 6E 6F   `abcdefghijklmno
00170  70 71 72 73  74 75 76 77  78 79 7A 7B  7C 7D 7E 7F   pqrstuvwxyz{|}~.

  Are you sure? yes | no

hackaday wrote 02/11/2021 at 14:18 point

The CPU card has continuity for every pin on the CPU to either a logic chip or the RC2014 bus pins.

  Are you sure? yes | no

hackaday wrote 02/11/2021 at 14:45 point

I swapped the mcp23s17-e/sp port expander. I now at least get returned to a prompt, though no expected 'hello world' output:

type help to list available commands
z80ctrl:/>bus  
        0009 87                      busrq busack                        
z80ctrl:/>loadhex hello.hex
loading from hello.hex
loaded 45 bytes total from 0100-012c
z80ctrl:/>run 100
z80ctrl:/>bus
        0000 02                      busrq busack      halt

  Are you sure? yes | no

J.B. Langston wrote 02/12/2021 at 01:50 point

What happens if you run `watch opfetch` followed by `debug 100`?

  Are you sure? yes | no

hackaday wrote 02/12/2021 at 02:11 point

z80ctrl:/>loadhex hello.hex                                            
loading from hello.hex                                                 
loaded 45 bytes total from 0100-012c                                   
z80ctrl:/>watch opfetch                                                
z80ctrl:/>debug 100                                                    
00100 31 ff ff    1..  ld sp, 0ffffh
00102 ff          .    rst 38h
00106 cd 0a 01    ...  call 010ah
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
0010c c8          .    ret z
00112 f7          .    rst 30h
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011a f1          .    pop af
0011c 11 c9 68    ..h  ld de, 68c9h
00110 23          #    inc hl
00110 23          #    inc hl
0010a 7e          ~    ld a, (hl)
0010a 7e          ~    ld a, (hl)
0010c c8          .    ret z
00108 01 76 7e    .v~  ld bc, 7e76h

  Are you sure? yes | no

J.B. Langston wrote 02/12/2021 at 02:26 point

It does look like it is at least running the program, but something is weird.  Every instruction is listed twice and there are some extra instructions there that shouldn't be.  This is what the output is supposed to look like (done on my REV6 board).  I'll double check on REV4 and make sure that I get the same output there.

z80ctrl:/>debug 100

00100 31 ff ff    1..  ld sp, 0ffffh
00103 21 1e 01    !..  ld hl, 011eh
00106 cd 0a 01    ...  call 010ah
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
h0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
e0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
l0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
l0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
o0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
,0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
 0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
w0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
o0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
r0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
l0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
d0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a
0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
0010d cd 13 01    ...  call 0113h
00113 f5          .    push af
00114 db 10       ..   in a, (10h)
00116 cb 4f       .O   bit 1, a
00118 28 fa       (.   jr z, -6
0011a f1          .    pop af
0011b d3 11       ..   out (11h), a

0011d c9          .    ret
00110 23          #    inc hl
00111 18 f7       ..   jr -9
0010a 7e          ~    ld a, (hl)
0010b a7          .    and a
0010c c8          .    ret z
00109 76          v    halt

  Are you sure? yes | no

J.B. Langston wrote 02/12/2021 at 02:30 point

I confirmed that it works correctly on REV4 as well.  It's like something with the clock is still off, or the Z80 isn't moving on to the next instruction every cycle like it should be.

  Are you sure? yes | no

J.B. Langston wrote 02/12/2021 at 02:36 point

You said you checked continuity on each bus line from one board to the other, but did you check for shorts between pins? At this point I'm less inclined to think there's something that's not connected, but rather that something is connected that shouldn't be.  That's why I asked you to test the adjacent pins and make sure there were no shorts between them.  Also check your backplane for solder bridges.  When I first designed these boards I had a weird issue that took me forever to figure out where the SD card would not work when i had it plugged into the bus, but it worked fine when I took it out.  It turned out I had a short between one of the SPI lines and an adjacent line on my bus.  I couldn't see any solder bridges anywhere, but the continuity tester showed a short. Eventually I cut those traces around the socket where the short was occurring. I never did find the source of it-- I just don't use that socket anymore. Maybe there is a solder bridge underneath the socket where I can't see it... who knows?  Anyway the moral of that story is that very unexpected things can happen and even if you believe there's no way something could happen, it always pays to test every connection very methodically.

  Are you sure? yes | no

hackaday wrote 02/12/2021 at 14:20 point

Yeah some sort of solder bridge under a socket seems likely. I'll pull all the chips and test between pins.

  Are you sure? yes | no

hackaday wrote 02/13/2021 at 02:13 point

I pulled the chips on both cards and found no shorts between bus pins or chip pins (except in the few places where they're supposed to be).

  Are you sure? yes | no

J.B. Langston wrote 02/13/2021 at 20:46 point

I'm running out of ideas. Maybe something is putting a capacitive load on the clock line. That could explain you can see a signal at lower frequencies and not higher ones, and possibly could explain the doubled instructions if it makes the clock transition too slowly. 

  Are you sure? yes | no

hackaday wrote 02/14/2021 at 02:27 point

CLK looks fine at higher speeds.

I'm picking up an HP 1630D logic analyzer tomorrow. This should help figure out what's really going on.


EDIT: Unfortunately without CLK the analyzer isn't able to capture anything other than a simple state condition. CLK is still sitting there as HIGH.

  Are you sure? yes | no

hackaday wrote 02/20/2021 at 18:06 point

OK one final thing. I pulled the MCP23S17, stuck it on a breadboard, and ran some simple code to sequence through all 16 outputs to light LEDs. That works fine on all three of my MCP23S17. So... that was the final thing to swap and I'm out of ideas. I'll see if the tindie seller is willing to do a board swap.

  Are you sure? yes | no

hackaday wrote 02/22/2021 at 15:49 point

looks like the culprit was the AS6C4008 SRAM.

  Are you sure? yes | no

J.B. Langston wrote 02/22/2021 at 18:36 point

Huh... I did not suspect that because of the original issue you reported was with the CLK signal, and the RAM isn't connected to the clock. Just goes to show you should never rule anything out because it seems impossible ;).  I'm glad you figured it out. Everything working as it should now?

  Are you sure? yes | no

hackaday wrote 02/22/2021 at 20:17 point

I can get hello.hex to return 'hello, world' but only if run via 'debug 100'.

For CLK, isn't there a check from the CPU before the clock is started? I tested the SRAM in my TL866 II, it failed on A0, so that could prevent the z80ctrl from talking to the CPU.

  Are you sure? yes | no

J.B. Langston wrote 02/23/2021 at 04:14 point

Before it starts a program, z80ctrl sets BUSREQ high and waits for BUSACK to go high.  If it doesn't within 255 clock cycles it will print "bus release timed out".  This happens regardless of whether you use debug or run.  So I'm not sure why it's still not working when you use run. Maybe there is a problem with the clock at full speed. You could try setting "clkdiv 200" before you type run. That would cause the clock to run at 100 kHz instead of 10MHz, which should be slow enough to work if the problem is related to the clock speed.

  Are you sure? yes | no

hackaday wrote 02/24/2021 at 21:08 point

'clkdiv 7' is as fast as I can go and still have it return 'hello, world'.

  Are you sure? yes | no

J.B. Langston wrote 02/25/2021 at 19:48 point

Given that you can run it at lower speeds, it makes me think there is some parasitic capacitive load on the clock line.  Not sure what would cause that, but basically, there is something acting like a low pass filter on your clock line so that lower frequencies can get through and higher frequencies are either so attenuated or so distorted that the Z80 doesn't recognize it as a valid clock signal.

  Are you sure? yes | no

hackaday wrote 02/26/2021 at 14:10 point

Looking on the scope, there's no evidence of roll-off happening, even with clkdiv set to '2'. I see some ringing and overshoot, but I'm measuring at the end of the bus and using protoboard jumpers to connect the scope probe. It's nothing that I feel would cause TTL or CMOS triggering issues.

What's interesting is that despite what clkdiv is set to, there's always a 'preamble' of 5 MHz CLK before it switches to the actual clkdiv setting.

  Are you sure? yes | no

J.B. Langston wrote 02/26/2021 at 20:43 point

I don't know then... have you tried with a different Z80 since fixing the memory issues?

The 5MHz signal you see is probably during the bus release phase where the code manually toggles the clock line. The clkdiv doesn't have any effect there.

  Are you sure? yes | no

hackaday wrote 02/26/2021 at 22:21 point

I've got an old one which is probably 4 MHz I can try. I've tried that one before I swapped the SRAM so it's worth another shot. Would the RC2014 bus benefit from some termination resistance?

  Are you sure? yes | no

hackaday wrote 02/27/2021 at 02:24 point

My pull Z80 is actually a 6 MHz part. So far, I can't make it fail, even multiple times with clkdiv = 2. I guess the kit cpu is faulty.

  Are you sure? yes | no

J.B. Langston wrote 02/27/2021 at 00:12 point

I'm sure that termination resistance couldn't hurt but I have never had any problems without it.  My RC2014 has been super stable for the most part both with the SC112 and RC2014 pro backplanes, with the stock RC2014 boards, and with Z80ctrl running the Z80 up to 10MHz.

  Are you sure? yes | no

J.B. Langston wrote 02/27/2021 at 04:28 point

Huh, it's really strange that both chips had issues... maybe they got zapped with static?

  Are you sure? yes | no

wynn.rostek56 wrote 01/22/2019 at 18:58 point

Found it. RAM was flaky due to a bit of crud on the contacts. Replaced the bad jumper, and everything works. Great board. I'm glad I ordered two of them, I have a second backplane that I will bring up as soon as I get the CPU and RAM boards built for it. Thanks for the support and the wonderful board. I think you may have a second board, some kind of I/O am I right or confused?

  Are you sure? yes | no

J.B. Langston wrote 01/22/2019 at 20:33 point

I'm glad you got everything working and that you are enjoying the board. Yes, I have a SPI I/O expander board that adds a RTC and up to 4 8-bit GPIOs.  If you look at some of the project blog entries, you can see a few examples of what it can do.  I also have the game boards (video, sound, controller), but those aren't directly tied in with z80ctrl.

  Are you sure? yes | no

wynn.rostek56 wrote 01/22/2019 at 09:22 point

Error is that I see physical sector size must be 128 and the software kicks back to the monitor.

  Are you sure? yes | no

J.B. Langston wrote 01/22/2019 at 16:00 point

I am pretty sure the problem is not with the sector size unless you are using some other disk format.  Are you trying to use the cpm2.dsk image from SIMH?  If so, it should work. The disk emulation code has not changed in a very long time and I have not had any problems with it.

  Are you sure? yes | no

wynn.rostek56 wrote 01/22/2019 at 09:12 point

J.B. J4 is to the far right and J9 is to the left (CLK) but am still unable to get cpm to boot.

  Are you sure? yes | no

J.B. Langston wrote 01/22/2019 at 15:57 point

The behavior sounds to me like the wait state generator isn't working properly.

For U3, are you using a 74HCT02? This part changed in REV4; previously it was a 74HCT74.  

  Are you sure? yes | no

[deleted]

[this comment has been deleted]

J.B. Langston wrote 01/20/2019 at 23:12 point

Which position do you have jumpered for J4? Try putting it on the far right.

  Are you sure? yes | no

[deleted]

[this comment has been deleted]

J.B. Langston wrote 01/20/2019 at 23:10 point

I'm glad you figured that out. And you're right about the typo in ihex.c. I have pushed a fix to Github. Thanks for letting me know!

  Are you sure? yes | no

[deleted]

[this comment has been deleted]

J.B. Langston wrote 01/20/2019 at 16:43 point

Do you get an error when you run loadhex, or it just doesn't have any effect?

Can you also try "fill 0 ffff asc"? It should fill the memory with values 0-FF ascending, over and over.  This is a little more complex pattern that would be a better test than filling with 0, but still rule of some of the complexity of loadhex.

  Are you sure? yes | no

villaromba wrote 10/08/2018 at 18:19 point

Fully understand - likewise!!!

At some point it would be good to have (as outlined in your possible expansion)

to add other SPI peripherals and implement I/O port interfaces to them for the Z80. Examples: real-time clock, GPIO, 7-segment display, LCD display, etc.

  Are you sure? yes | no

villaromba wrote 10/08/2018 at 16:08 point

Hi JB

Are you going to be adding any further work to this project?

Colin

  Are you sure? yes | no

J.B. Langston wrote 10/08/2018 at 18:04 point

Probably at some point, but I have been focused on other stuff lately. Is there something specific you are hoping I would work on?

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates