My DTV mod: C64 DTV in the original C64 case

When I first heard about the C64DTV, I knew this is what I have been waiting for. I always wanted a clone which is compatible with the original Commodore 64, but more powerful and has extra resources like other resolutions, more memory, etc. Fortunately the C64DTV (I own a European PAL version V2) can be hacked many ways, and you can find a lot of information about it on the Internet. See my references below!

I checked many hacking pages, so I knew that it is possible to attach an original disk drive via the IEC bus, and it is possible to attach PS2 keyboard to the unit. But as far as I know, no one tried to put the DTV back into an original C64 box (I can be wrong though). Then I found Lars Pontoppidan's MMC2IEC project which uses MMC/SD card for the storage and it acts like a 1541 drive (sure a little bit better).

As I am experienced with microcontrollers as well as C/C++ and the assembly language, I knew that there is a way to handle the original C64 keyboard matrix with a microcontroller. Unfortunately the DTV does not have the keyboard rows/cols pinouts, so there is no perfect solution, but the PS2 implementation might be good enough for my purposes. I thought, the same microcontroller - in this case it's the Atmel ATMEGA32 with 32 I/O pins - could scan the keyboard matrix and send the necessary press and release codes on the PS2 bus to the DTV. The PS2 port on the DTV is unidirectional, it means the host never sends data to the keyboard. Great. Thanks to the other researches that cool guys have done before, I had enough knowledge about everything. I knew how to generate PS2 codes, I knew how to scan the keyboard matrix, and thanks to Lars Pontoppidan, I had a solution for the IEC interface. All I had to do is just modify the original MMC2IEC design a little bit, and implement the keyboard scanner function.

I have spent about 3 weekends with this. Unfortunately the PS2 interface for the DTV has some odds. It also has some remappings, therefore my implementation had to do some workaround for special keys. For example on the C64 keyboard the key 2 has the " sign when it's shifted, the PC keyboard has the sign @. There are some other mismatches, which make my life difficult. Anyway, what you see here is the first version. I know it's not perfect, but it works.

I do not want to write about the other obvious hacks for the DTV, you can find out yourselves these ones (like joy port, video fix, updating the flash, etc), just google them. I am not really concerned about the IEC and MMC stuff either, Lars did a great job. I am only writing about the keyboard matrix here.

Theory: the IEC bus has higher priority than the keyboard matrix. Whenever the IEC works - which means you load or save something - there is no keyboard scanning at all. When there is no disk handling, the microcontroller has an idle time, in this case I scan the keyboard matrix as fast as I can. Every time I compare the last scanned values with the new ones, so in case of one key there is four different states (0-pressed, 1-released) if we have the bit #1 as the old bit, and the bit #0 is the new bit:

  • 00: was pressed before and still pressed
  • 01: was pressed, now it's released
  • 10: was released, now it's pressed
  • 11: was released, still released
In case of 00 and 11 there is nothing to do, because the state of given key has not changed. If we get the 01 value, we have to generate a release code, whereas if we get the 10 value, we have to generate the press code. Because of the different keys (like 2/@ - 2/" or 6/^ - 6/&) sometimes it's more complicated, so we need to change the code or virtually press or release the shifts. This is all done by the UpdateKeyMatrix() function.

Let me highlight some points about the schematic.

  • First of all, it's pretty simple. I used a 40PIN version of the microcontroller, where we have the PORTA and PORTC on the "right side" of the chip. This makes the soldering very easy.
  • I use the PORTA and PORTC for the keyboard matrix (COLS and ROWS), but in this version I do not handle the Restore button. (maybe in the next version)
  • I do not use LEDs, but they are on the PORTD bit #0 and bit #1. They were in the original MMC2IEC project but I just don't need them.
  • Between the DTV and the AtMEGA microcontroller there are five data lines: PS2Data, PS2Clock, IECData, IECClock, IECAtn. These are on the PORTD.
  • The PORTB is used to handle the SPI bus, this is what communicates with the SD/MMC card.
  • I use the internal 8MHz clock source, but it's just around 7.6MHz because of the 3.3V Vcc voltage.

Some points about the software:

The main loop in the mmc2iec.c is pretty simple. It scans the keyboard if there is nothing else to do, otherwise the IEC handler works. Obviously I initialized the keyboard handler with the InitKeyMatrix() function before I use the UpdateKeyMatrix().

  While (TRUE) {
    // scan the keyboard normally (IDLE time)
    // IEC-MMC handler (LOAD/SAVE)
Ps2.c: this is the one that sends a byte on the PS2 bus to the DTV. Simple as hell, as the PS2 port is only output for the microcontroller. I am not even sure that the parity bit generation is correct. If not, that means the DTV does not care about the parity bit. Good.

C64keymtx.c: the keyboard handler module. There is an array called "r" (unsigned char r[64] PROGMEM) which contains the PS2 codes. The only one exception is the colon ":" key, which is handled differently and I used 0xff for this key. Obviously, the table contains the keys based on the schematic - as you can see, the rows and cols are mixed, but it was the easiest way to solder and I did not mind to change the bits in the software. It does not matter anyway.

How it works? Read the source. It tells everything.

One more thing to mention. You will find out that I used the goto statement inside the UpdateKeyMatrix() to break up the loops some cases. I know that every book says you should never use gotos. Bullshit. I use what I want to use. And besides, this is a microcontroller application where speed and space are factors. I tried some different ways. Anything else generates more code. BTW the WINAVR is just perfect, the best compiler I've ever seen. Still, some bytes matter to me. So for those who are against the goto: try to write an assembly code without braches and jumps. Good luck for that. Gotos don't mix up your code. If they do for you, you should find another job to do. Selling postcards for example. :-)


Links and references

Things to do for the next release (just some ideas in my mind)

  • Accurate RESTORE key handling. Well, there is no RESTORE handler at all now.
  • LED's. Just to make it perfect.
  • Modify the DTV's flash so I won't need to press the CTRL key always. Absoultely required.
  • Video fix and dedicated video and audio ports on the box. Won't be too hard.
  • Soldering the joy ports as well. I will do.
  • Hack the original IEC routines to speed up the load and save. There must be a way as we can modify the FLASH. Thanks, Mr. Kahlin.

- Here you can see the fusebits settings for the microcontroller: Fusebits
- You can download the compiled version in intel-hex format: mmc2iec.hex (right-click, then Save target as)

Addendum: (2007.12.10)
As I experienced, sometimes it's not a pretty good idea to connect the RESET line of the DVT with the RESET line of the ATMega chip.

Therefore, if the design does not work, try to remove the RESET line from the ATMega, the microcontroller should be able to start without a connected RESET line. In this case the microcontroller will be initalized and the keyboard lines will be already at high level, when the DTV first checks them.

19th of Oct, 2007


The schematics

Before I started (I had a dead C64)

The microcontroller with the keyboard

Have a seat, please.

The first trial. They work!

Power connector. I use the original switch.

Another shot of the power connector.

I realized that the gray floppy wires are too thick. Changed them to thin ones.

Everything's there. What an empty box is that...

It DOES work!