Small embedded microcontrollers do not usually come with a video output. The aim of this project is design a low cost stamp sized module that can be used to provide a VGA text display rendered at full 640x400 or 640x480 and interface with a PS/2 keyboard. The module acts as an embeddable VT100 terminal to the host via serial port. It takes care of the video generation, critical timing issues and simplifies the driver for the embedded host. The host only need to deal with sending/receiving characters and control code via serial port.
This is an DIY project with readily available parts. It can boot up instantaneously to catch console messages and consumes ~25mA at 3.3V for monochrome video (without the PS/2 keyboard). The module is small enough (0.7"x1.0") and cheap enough to be embedded in a design.
640 x 400/480 VGA text mode uses a 25.175MHz pixel clock. Most of the video monitors can accommodate 25MHz which is commonly used for Ethernet and the crystal/oscillators are easily available at a much lower price.
There is a bit of overclocking involved in this project, so YMMV.
I have tested the STM32F030 SPI at 25MHz for three chips with different date code. It works fine for the SCK and MOSI signals in 8-bit master mode.
I am trying to deduce where the SPI 18MHz limitation on the datasheet comes from. The APB peripherals STM32F0 value line are qualified to work at 48MHz. The I/O (clock to data out) timing on the datasheet actually very tight and have plenty of margins meant for a much higher frequency.
The SPI clock frequency are at 18MHz for some reasons.
Here is what I think happens: Someone copy the numbers from a different product line.
The following is from their 72MHz STM32F10X line. 72MHz is probably a bit too fast for the SPI block, so they divide the frequency down to 36MHz. There is a further divide by 2 inside the SPI module for the SCK clock. Hence the maximum data rate is: PCLK/2 = 36MHz/2 = 18MHz.
Most of the other VGA projects uses a mid range ARM Cortex M with a lot more RAM and/or renders the output in a lower resolution. It is easier to ignore cost and throw resources at a problem. I am trying to use the "value" line STM32F0 for cost reason and as a technical challenge. The part is available here at $0.44 at QTY 10.
My challenge is to implement a working subset of a VT100 terminal while emulating the missing hardware using a high level language and working within similar memory constraints of the original VT100. For VT100 compatibility verification, I am using a standard open source test suite called VTTest.
Initially I planned to use external SPI RAM as the frame buffer for a full graphic + colour display, but I scale back and try to work with only on chip resources. The amount of RAM in this part is only 4KB which is not sufficient to store the entire frame buffer. The alternative is to generate all the scan lines at full resolution (640x400 or 640x480) on the fly for each frame.
The block diagram is actually very similar to the "6845 CRTC" inside old terminals. It is all implemented inside the STM32F030F4 microcontroller.
Above is a modified version of typical usage example from the MC6845 datasheet.
- The ARM M0 core is the "Processor"
- The internal RAM is used as "Refresh RAM" that holds a Character buffer as well as a scan line buffer. Thebuffer is used to decouple the (faster than real time) rendering process from the video generation.
- Hardware timer is used to generate the HS (Horizontal sync) and an IRQ is used to keep track of the current scan line "Refresh Memory Address" for rendering, VS (Vertical sync.) generation and Ping-pong buffer management.
- DMA transfer rendered scan line from the buffer to the SPI acting as the "Shift Register"
- A firmware rendering routine described below is used to implement the "ROM Character Generator" function.
The rendering process
- A text buffer is used to store the characters to be displayed.
- For each scanline, for each of the character in the...