Tuesday, March 12, 2019

NOP

The architecture of my Atari cartridge port interface adapter to an ESP8266 is to use an Arduino Nano (ATmega328P MCU) as an intermediary. Another way is to use an FPGA, but that's more costly and I don't have enough experience to try that yet. Using an MCU on the cartridge port, which is really just the 6502 bus, calls for the use of 3-state latches to capture and to hold data in place while the two microprocessors go about their business. While there is a flashcart out there that uses a 32-bit STMicro MCU to respond with 6502-bus timing, I'm not confident I can do that with a 16-MHz 8-bit MCU.

I've run into several challenges. First, what DIO pins should I use? I ended up splitting the 8-bit bus into two 4-bit nybbles spread between ATmega328P Ports D and B. The Arduino doesn't have an entire 8-bit port free. Reading the port requires some fun bitmath. Second, the output enable is sent out over a pin on Port C right before the 8-bit data is read. The 16-MHz is so fast, I had to throw in a NOP instruction to properly read the data. The enable time of the SN74HCT573 (/OE->Q) is at least 40 ns. Assuming the ATmega changes its output pin state at the end of it's clock cycle and begins its read at the start of the next, there's not enough time for the latch to output its data. A single NOP on the ATmega is 62.5 ns, more than the enable time on the latch. Or, maybe the ATmega328P digital input has some setup time that's otherwise violated. Either way, some brief testing indicates no missing bits.

The third challenge is related to the second - the disable time on the latch is also at least 40 ns. I want to read the address latch and the data latch sequentially. To avoid bus contention, the second latch cannot be enabled until after the first latch is fully disabled. This problem was solved by moving some instructions around inside the interrupt routine to put some delay between the two read operations.

Here's a logic analyzer plot showing the timing:
The disable time (OED rising edge to Q0 rising edge) is much longer than expected. But the Arduino C++ interrupt code arrangement makes the timing work out:

The interrupt routines reads two bytes and increments a counter, all in less than 5 microseconds. I put the counter increment in between the two reads to give the first latch time to disable before the second latch is enabled, which avoids bus contention. Cool.

3 comments:

  1. Some ideas about parallel to serial:
    https://systemembedded.eu/viewtopic.php?f=28&t=33

    https://www.youtube.com/watch?v=9B7ZSIGpW1Q&feature=autoshare
    and
    https://docs.google.com/presentation/d/1S0WdhuGAStP1GVe-UWvJGx7SMww4fuWeBTP9UniAyYs/pub?slide=id.gfe0ea98b7_0_53
    and
    http://i.imgur.com/NATdeh8.png

    https://atariwiki.org/wiki/Wiki.jsp?page=ARGS%20RS232%20Cartridge

    ReplyDelete
  2. Another idea - it seems very similar to your project:
    https://hackaday.com/2019/02/11/a-network-card-for-the-trash-80/
    http://pski.net/2019/02/03/trsnic/

    ReplyDelete