Sunday 16 April 2023

Mini VIC Development Part 2 - Picking a Microcontroller (including USB Keyboard composite video mod)

This is the second of the Mini VIC development logs, previously Patreon exclusive posts. This one is again from January 2022, peak microcontroller shortage.

In the last post, I identified many of the things I need to do to progress from the proof of principle test. The first one is to pick a suitable microcontroller.

It needs to support the USART in SPI mode used to generate the video, and needs at least one 16 bit timer to trigger the various stages of the video waveform. It also need to be fast (16Mhz minimum, ideally a lot more), and must have lots of pins. Accessing the video RAM is going to need 20+ pins, so the humble ATmega328P is not going to cut it.

I've been trying out various boards, including these AVR128DA28 Curiosity Nanos. Quite a neat idea, there is a built in programmer / debugger at one end and all the pins are taken to pads on the end.

I picked up a few different versions of these with different microcontroller options. There are also PIC versions and the ARM cored SAM range.

The problem with this is the same as the SAMC range I looked at last year. Such a bloated framework with endless updates to get the simplest project loaded. Framework updates, package updates, studio updates, updates to the firmware in the programmer. And finally the "blink" project loads. It has created 121 files and folders, all to blink an LED.

It took me ages to go through all of those to find out what was actually being used. Full of unnecessary things like initialising each IO pin individually to the default values they would already be initialised to at reset, rather than just DDRA=0 etc.

Microcontroller datasheets used to be full of example code in C and assembler. This PIC databook got so much use back in the days of 16C54's and 16C84's etc. I don't think it left my desk for years, and even then was still close at hand on the nearest bookshelf.

The new ones don't seem to have any code examples in. I found one that didn't even have a pinout.

It took a lot of reverse engineering the output of the compiled C code to see how to set the clock - you have to write a secret value (which doesn't appear to be mentioned in the datasheet) to one register to unlock access to certain other registers.

Then just a simple delay loop to blink the LED.

I was hoping to use these new chips, either the AVR128DA48 or AVR128DB48, but I find this just too much hassle to wade through all the layers of frameworks to get down to what is actually required. I started looking at what was going to be required for the serial port and the timers and I gave up. The information wasn't there to do what I needed.

There was a way of generating C code that would do it, but with massively bloated interrupt handlers that were taking dozens of cycles saving all the registers each time. It gets messy to try to mix C and assembler as you can't always control which registers it is using, so when you need tight timing, as I do here, you end up writing it all in assembler.

The framework didn't appear to support the USART in SPI mode, it should be possible, but it looks like it might be more complicated with a second register containing a 9th bit which may also need to be set each time?

It's not a very good photo, but it took so long to get to assembly code flashing that one LED we are all going to look at it and appreciate it.

(2023 update: I did in the end spend an awful lot of time extracting the appropriate bits I needed to write the Minstrel SD code for one of these AVR chips for the Minstrel 4D project, and even used one of these development boards on the prototype.)

I think I'll go back to the older chips. They are slower (16Mhz vs 24Mhz), but some of the seemingly simple tasks I am trying to do take less cycles on the slower chips so actually work out not only easier to write, but faster. The newer chips do have single cycle port bit changes, which would help in the critical sections, so it's not entirely a win for the older chips.

One feature in particular I think will be needed here is the external RAM interface. This was only available on a few microcontrollers (usually the ones with a lot of pins), and allowed external static RAM to be addressed as part of the normal address space.

Even though there were loads of pins, all the chips I have found use a mechanism where the lower address bus and data bus are muxed, requiring an external latch chip and one extra cycle. 

The ideal would have been separate address and data busses, but I don't think any of the range are configured like that. It would also seem to have been a better option to mux the upper address bus instead, since that would likely be changed less frequently.

The alternative is to manually set the two bytes of the address, enable the address lines, toggle the read pin, read the data then toggle read off and then turn the address lines off., All of that will take many cycles more, and it is really tight with 16 cycles to read a character, work out the address in the font ROM, read the bit pattern from the font ROM and output that to the shift register. One of the reasons I kept with separate video ROM, character ROM and shift register in the Mini PET was that allowed me to do all that in just 8 cycles.

It's a tricky time at the moment to develop anything new, as so many parts are out of stock or limited availability, so I have been rummaging around to see what I have on hand that can do the job.

It's a bit old, but the ATmega2560 as used on the Arduino Mega is a possibility. This has several UARTS, loads of pins, and supports the external memory interface.

Looking around at other options, one that might not be an obvious choice is the AT90USB646, a chip I used in the larger USB keyboards.

The speciality of the chip is the USB interface, I don't actually need that here, and don't think I can use it, I would have to stop drawing the screen when the USB was accessed. What is this, a Commodore 64?

It is 16Mhz, has one USART which supports SPI, various timers, lots of pins, and it supports the external memory interface.

I do I have a few test boards from the early days of those, this one looks a good option. I have taken all the pins out to two pads, one of each of which I have soldered pins to.

The chips are still in production, but obviously are out of stock everywhere until next year, but the same is true of most microcontrollers, so I'm not really bothered. (2023 update, just checked and found some of these in stock! ordered.)

I am just going to plough on regardless and see what availability is like when this project is further down the line. I might move to another chip if needs be, but this seems a good starting point.

Surprisingly that lashup worked. The VIC20 test screen code running from the AT90USB646 board, with the resistors and diode on the breadboard that I was using to test the AVR128DB48 with, and the buffer transistor and composite output on the breadboard from the original Arduino ATmega328P tests.

That looks like it's worth taking further, so time for a composite video mod on a USB keyboard controller to make something for a vintage computer kit. (if that's not peak Tynemouth Software Blog, I don't know what is)

The phono jack fits quite nicely where the USB jack was, and I was able to reuse various pads to mount the transistor and wire up the signals to port B.

I have tidied up the code a bit in the move over, and will continue to tweak things. I notice the timer on this chip has three compare outputs rather than the two I was using on the ATmegas, so I should be able to set that up to do the front porch on the video signal.

When I was trying things out, I don't think I had noticed before how much nicer the PET / VIC20 font was.

This is the same screen, but using the font from the C64 and TED machines

I added that font when I was trying to see if I could get 40 columns. The current code is accessing hard coded video RAM and font ROM, so the number of cycles is going to changes when I switch to external RAM, but I just wanted to see if it would fit.

The characters are inverted here as the invert is actually a separate step, and I missed that out to try and get it to fit. The white lines you can see are where the next character was not available in time. The larger the gaps, the more instruction cycles over the limit it is. Here it was only a couple of cycles, but I had to unroll the code loop to get it to fit (i.e. cut and paste the code within the loop 40 times rather than having in check if a counter is less that 40 and looping back if it was, as that added three cycles per character).

The line timing is a bit out (the wobbly edges on the left), but I was more concerned to be able to get the characters out in time. Mini TED anyone?

The next step will be wiring up the external memory access. Lots of wires to solder to the test board. Part of that is going to need a 74HC573, and I don't seem to have any of those left. Plenty of HC574's (which aren't suitable due to the point the data is latched), and plenty of HC373's (which is essentially the right thing, but with an annoying alternating pinout).

In the past it was just a case of going to RS or Digi Key and clicking buy. This is 2022, so obviously, the standard Texas Instruments parts are out of stock everywhere.

I have managed to find an obscure Toshiba version of the same thing, with a whopping 80 of them in stock!

Once those have arrived, on to video RAM access.

More on that in the next post.

(2023 update - actually the next one is going to look at clocks and signal timing)


Minstrel 4D

No Mini VIC or Mini TED kits any time soon, but the Minstrel 4D kits are shipping now, you can order one from The Future Was 8 bit - SPECIAL OFFER - £15 off the Minstrel 4D and free shipping to the USA

More info in a previous post:


You can support me via Patreon, and get access to advance previews of posts like this and behind the scenes updates. These are often in more detail than I can fit in here, and some of these posts contain bits from several Patreon posts. This also includes access to my Patreon only Discord server for even more regular updates.