April 2019

AVR Integration

After several frustrating days and a lot of captures from my logic analyzer I am happy to report that I finally have the AVR integrated with the system, along with the basics of PS/2 keyboard support!

I did have to make one small sacrifice, which is to move my as-yet-unimplemented game pad support from the AVR to the VIA. This was done to free up enough pins on the AVR to let me go back to an external 16 MHz resonator, as running on the internal 8 MHz clock was proving to be a bit too slow to keep up. Game pads don’t support interrupts anyway so this is not going to be an issue at all.

How it works

To begin let me explain the actual hardware connection between the VIA and the AVR (an ATmega 328p):

The connection is a bidirectional parallel bus between port A of VIA #1 and port D of the AVR. Data transfer handshaking is handled by the VIA’s built-in handshaking support., which uses the CA1 and CA2 lines to act as Data Ready and Data Acknowledge signals. When sending, the VIA generates Data Ready pulses on CA2; the AVR acknowledges the bytes by sending Data Acknowledge pulses on CA1. Receive mode works the same way except the meaning of the CA1 and CA2 lines is flipped; note that this means CA1 is always the input and CA2 the output.

Since the VIA and AVR are sharing a bidirectional data bus it is important to make sure only one device is trying to drive the bus at any given moment. This is controlled by the VIA using the DDIR line; it is high when the VIA is driving the bus and low otherwise.

Data Transactions

Every transaction starts with a data packet from the VIA, followed by a response packet from the AVR. The packet format is very simple and consists of a packet type, payload length, and the payload:

+0Packet Type
+1Payload size, low byte first
+3 – +514
Payload (optional)

The payload, when present, can be up to 512 bytes in length; this number was chosen to allow a single SD card block to fit in a packet. The payload length can even be zero, in which case the entire packet is just three bytes.

A transaction starts when the VIA drives DDIR high; this signals that it’s about to start transmitting a packet. The VIA then transmits the packet in its entirety before pulling DDIR low again and going into receive mode. It then waits for the AVR to transmit the reply packet, after which both sides fall back to their idle state.

The AVR never sends data unless it is replying to a request from the VIA. It can, however, generate an interrupt by driving the CB1 input to the VIA low. A GET_STATUS request can then be sent to the AVR to determine the source of the interrupt.

The AVR Implementation

On the AVR side all of this is implemented as a state machine, driven almost entirely by pin change interrupts:

The only part that is not interrupt-driven is the transition from the RECEIVED state to the SENDING state. The actual packet processing is done in the AVR’s main loop, and the act of queuing the reply is what triggers that state transition.

There is one small difference between the diagram above and the actual implementation, and that is the handling of DDIR going high. In the code as implemented a DDIR low-high transition will ALWAYS transition to the RECEIVING state, regardless of the current state. I did this so that it is possible to recover easily from a botched transaction without needing to reset the AVR.

PS/2 Keyboard Support

With the VIA and AVR finally talking reliably I moved on to implementing the PS/2 keyboard driver. This was much easier and took me maybe half a day.

Like the MPU interface, the PS/2 driver is interrupt-driven, this time by the PS/2 clock signal, which is always generated by the device. I won’t take the time to diagram it here since there are quite a few examples on the net of how to do this, and my implementation is nothing special.

As it stands now I am able to send and receive bytes with a PS/2 keyboard; this means I can receive key up/down events as well as control the LEDs, configure the typematic key repeat, and other fun things. I need to implement two more pieces to make this a complete solution however:

  1. Implement interrupts when the AVR has buffered data from the keyboard
  2. Decoding of key scan codes into actual ASCII that the rest of the computer expects. I am leaning towards doing this on the ‘816 side.

These two tasks are my focus for at least the beginning of the week. I’ll post another status as soon as I’m able to type to the computer without using the serial port!

I’ve Rebranded

As you probably noticed my blog has a new name – Area 73.

When I originally started this blog it was just a replacement for my aging personal homepage, and I wasn’t sure how long I would really stick with it. So, I brought the blog online in a subfolder of my personal family domain name. My intent was just to blog about random life things, and in fact my first post was about cooking.

Fast forward two and a half years, and now my blog has morphed into a place for me to showcase my hobby projects. With that in mind I decided it was time to give the blog a better name than just “Josh’s Blog”. I wanted a name that invoked images of a skunk works or secret lab, and also something easy to remember. So, I opened up my favorite DNS reseller and started looking at what was available.

After some thought I decided to parody the infamous Area 51, and so I settled on Area 73. Not only is it my birth year, it also happens to be the best number. It’s also unique enough that it won’t be confused with anything else (unlike my first choice, Area 313, which is also the name of a local DJ/musicians collective).

Along with the new name I’m going to be remodeling a bit (changing the WordPress theme). It may get a bit messy for a bit, so please watch your step. 😉

COLE-2 Status Update

Progress for the past few days has been slower than I’d like, but hey, progress is progress right?

Hardware Updates

I’ve finally ironed out the remaining bugs in the hardware interface with the propeller. Previously I had thought things were stable, but when I attempted to read back the frame buffer in my scroll code I would get corrupted data, frequent crashes, and hard lockups. I spent two long nights trying to figure out what was wrong with my code; turns out it was a couple of hardware issue…

Bus Buffer Timing

The first problem was with the propeller’s data bus buffer, a 74LVC245 used for converting the 5V signals from the rest of the system down to 3.3V. When the propeller isn’t being accessed this buffer was being held in a high-Z state by a signal called /PROPBE generated by one of my GALs. I suspect that this signal, which was generated from the output of a second GAL, introduced enough extra lag that the buffer was not shutting off fast enough. Putting that signal back under direct propeller control solved the random crashes and data corruption, but not the lockups.

Clock instability

The second problem was with the /STP signal used for clock stretching. This signal had been giving me problems since day one due to voltage level differences. The obvious solution of using an ACT series part for the flip-flop did NOT work; despite the data sheet claiming the 74ACT74 is TTL-level compatible it would not recognize 3.3V on the /PRE input. So, I had the signal hooked up with a pull-up to 5V and was relying on the propeller to pull it low. As it turns out, this only sort of worked, and it was enough to cause the CPU clock to randomly start and stop at weird times, violating the timing specs and causing random lockups. I finally gave up and just tossed a 74HCT04 inverter in front of that signal, since I had a few on-hand, and voila! No more lockups.

The system is now rock-solid as far as I’ve been able to tell. I’ve had it running for more than 48 hours with zero issues. I may even swap out the crystal and see if I can push it up to 4 MHz; previously this made the system horrendously unstable, but with the /STP issue fixed it may finally work.

Video

With the hardware issues sorted out I was finally able to get a basic console driver working, including scrolling. To celebrate I prettied up the boot screen:

The console code is still in that “hacky but at least it works” state. Some of this is due to the fact that I have been dragging my feet on implementing a real driver architecture in my BIOS. Fixing that is high on my priority list for ROM enhancements.

Another thing the console driver is sorely lacking is a robust set of control codes. I briefly considered implementing VT-100 for compatibility with the old serial console, but VT-100 is pretty complex and way overkill for my needs (and it would require a decimal parser in the console driver…yuck). Instead I’ve decided to go more Apple II-style using control characters. Right now the only thing implemented is Ctrl-A + byte to change the text attribute byte.

Sound

Not much to report here. I would like to code up a boot sound soon, but I have zero experience with the SID. I am hoping to find some code I can borrow for that.

Keyboard

Absolutely no progress here. I did briefly work on hooking up the PS/2 connection directly through the VIA, but abandoned it; I just didn’t want the VIA doing that much polling during interrupts. So, I’m back to my original plan of using an ATmega to handle the user input devices.

SPI

After much internal debate I think I’m going to offload SPI onto the ATmega instead of the propeller. The driving force here is that my current propeller interface just doesn’t really provide for a clean way to implement SPI. The shortage of I/O pins contributed as well.

The new plan is to designate the ATmega as the I/O coprocessor; it will handle SPI in addition to the keyboard, mouse, and game controllers. I have not yet decided HOW to do this, as this means the ATmega<->VIA interface will need to be bidirectional. I do have some ideas though.

Next Steps

This week’s number one priority is to get the ATmega interface up and running. Once that’s done I will implement the keyboard code and then finally be free of the serial console for now.

Time permitting I’d also like to finally start tackling the mess that is the BIOS. In fact I may make another post this week just talking about the BIOS design, as I’m finding that these posts help me think through my issues.

As always thanks for reading! 😉