[posted] Teensy 3.6 based 8086 PC emulator with CGA graphics, PS2 keyboard

Mike Chambers

Well-known member
Hi all! This is something I did last year, but thought I'd finally share. I wrote a PC-based PC emulator some years ago, and later wanted to see how it worked on a microcontroller. So, I ripped the CPU core and a few other bits out, and got to work. I originally tried this with an Arduino Mega2560. It worked. Very, very slowly. Turns out AVRs don't make the best CPU emulators! :D Thanks to Paul for putting out these great little boards!

Like the title says, it's an 8086 (actually 80186) PC emulator based around a Teensy 3.6. It uses as much fast native RAM as it can, but then digs into SPI RAM to complete the 640 KB range you'd find in an old PC. It supports CGA graphics on an LCD screen and lets you plug in a PS2 keyboard. It uses raw access to an SD card as a hard disk.

It's no speed demon, but it runs well enough for MOST old programs you'd have come across in the 80's when overclocked to 240 MHz. Some other software is pretty painful, like Ultima 6. That was really aimed at 286+ anyway though. The main thing slowing it down is waiting for SPI communications with the RAM and LCD.

If anybody is interested in the code to create your own or hack it up a bit, I'll be sharing it probably tomorrow. I'll come back and edit the post. It's been a while since I wrote this, and want to make sure I remember all the different libraries used so I can link to them. I need to glance over the code again.

Here's a pic and some video. My soldering is terrible, and sorry for the shaky video.


Nice work. Did you try the edit in boards.txt to allow 256MHz?

remove '#' to uncomment:
#teensy36.menu.speed.256=256 MHz (overclock)
That will bump bus speed if that might break anything - though it might help depending.

Bus speed can also be doubled if desired finding these lines in ...\hardware\teensy\avr\cores\teensy3\kinetis.h
 #define F_BUS 64000000
 //#define F_BUS 128000000  // all the usual overclocking caveats apply...
 #define F_MEM 32000000
#elif (F_CPU == 240000000)
 #define F_PLL 240000000
 #ifndef F_BUS
 #define F_BUS 60000000
 //#define F_BUS 80000000   // uncomment these to try peripheral overclocking
 //#define F_BUS 120000000  // all the usual overclocking caveats apply...

Not sure if RAM could run faster with that?
Thanks for the info, I wasn't aware of those options. I'll give them a try tonight and see how it goes. The emulator actually runs a bit faster than it shows in these videos, as tonight I realized I had it compiled with the "ADVANCED_CLIENT" define, which causes it to send all video memory updates through the UART.

The "advanced client" is a PC program I wrote that could be used as a display and keyboard instead of using an LCD and PS2 keyboard. It also allows the Teensy emulator to have a makeshift emulated Ethernet adapter, which I wrote a DOS packet driver for. The PC program uses pcap and forwards packet data between the Teensy and your real network. I was using it to run a web browser and an IRC client on this. If there's any interest in that, I can release it too.

It also looks like I can't edit the original post, so I'll put the code here.

The only libraries I used are the optimized ILI9341 lib by Paul, and the SPIRAM24 library by FemtoCow.

I used the LCD screen available from pjrc.com.

I've attached a ZIP with the code. It's pretty messy after lots of experimenting. I haven't taken the time to clean it up, but if I don't release it now, I probably never will get around to it. If you're wondering why it's called "zero86" it's because I was starting to develop it for the Arduino Zero and never changed the name.

You can actually use this without SPI RAM if you don't have any, but you'll be limited to 231,424 bytes of RAM in the emulator.

SPI RAM pins:
- 256 KB SPI RAM chips CS lines should be on pins 25, 26.
- MOSI = 21
- MISO = 5
- SCK = 20

LCD/TFT screen pins:
- DC = 9
- CS = 10
- MOSI = 11
- MISO = 12
- SCK = 13

PS/2 keyboard pins:
- Data = 18
- Clock = 19

I believe that covers all the pins.

Here's a sample hard drive image with DOS 6.22, Windows 3.0, and a few 80's games. Just write it directly to an SD card with something like HDD Raw Copy.


You can make your own image if you want using another emulator. It expects disk geometry of 16 heads, 63 sectors. It can be up to 500 MB.

I hope somebody gets some use out of this! It was a fun project to work on.


  • zero86.zip
    86.6 KB · Views: 579
Last edited:
Oh my.. that SPIRAM24 lib looks very unoptimized and slow..
For Teensy, it really should use the FIFOs and the max allowed SPI speed. Then, it supports single Bytes transfers only? Pretty high overhead..
I wondered how Teensy efficient that SPIRAM24 might be! Those PSRAM chips can run as fast at 84 MHz when crossing page boundaries - so T_3.6 could clock at 60/64 with faster OC F_BUS?

Hi FrankB - was wondering if you saw this thread. I ordered 8 of the 8MB PSRAM chips, nice you got yours so fast!
Yes, they were surprisingly fast with shipping.
If anyone wants to use these RAMs: They use the usual commands (0x02/0x03), but they need a reset command to initialize, like a flash. And they don't like CS too long active without data transfer, best is to deassert it immediately.
But I don't want to be off-topic here.
That 8 MB RAM chip looks great! I'll need to see if I can get one of those.

I also didn't know about the FIFO capability, I'm going to have to see what kind of improvements can be had with that. It should be pretty substantial! :)

When running entirely on the 3.6's native RAM, the emulator is quite fast.

I haven't dug into the details too much with the Teensy hardware yet, I'm coming from an AVR background. (And a little bit of PIC)

I'm glad you like the project, Frank!
Am I correct in assuming that the FIFO can only be used on SPI0? I'll need to rewire the board slightly if that's the case. The RAM is on SPI1 right now, I'll need to share the LCD's bus with it.