Back to the lab
80 column PIC video terminal
You can get this 80 character by 25 line video display out of a PIC18F25K20 microcontroller using only 2 resistors and a crystal*
Click here for a complete PIC based video terminal with RS-232 port and PS/2 keyboard interface.
80 x 25 character display on $99 Coby 12" LCD television using composite video input.
The complete hookup:
R2 and R3 form a primitive 2-bit DAC. The television is an important part of the DAC because it provides 75 ohm termination. If you are measuring the voltage output without a TV attached be sure to add a 75 ohm resistor between video output and ground. The resistor values were chosen to get as close to the standard video levels as possible: 0.0 volts (sync), 0.3 volts (black), and 1.0 volts (white). If you substitute a 5.0 volt PIC you will need to change the resistor values.
Pin C2 is the sync pin.When it's high the video signal is ~0.3 volts (black). When it's low the video signal is ~0 volts (sync). Pin C7 is output from the video shift register. When the sync pin is high a high on C7 produces ~1.0 volt which is our white level. When it's low the output is ~0.3 volts which is our black level. It is possible to get gray scale pixels by raising C7 and lowering C2 but we do not use this combination.
Timer2 is programmed to trigger an interrupt at the beginning of each scan line. With a 14.31818 mHz crystal it fires every 908 instruction clocks (it would be perfect if it fired every 909.09 clocks).
The PIC's EUSART is used in master synchronous transmit mode as a high speed video shift register. The baud rate generator is set to zero which give us one pixel per instruction cycle (14.31818 megapixels/second). A tight loop written in assembly language loads the character code from RAM, converts it to a bitmap via a second lookup from the character generator (in ROM), and writes the byte into the transmit register. Each pass through the loop takes 16 instruction cycles and outputs two characters.
Because the user program only runs when the interrupt handler is not busy we try to spend as little time inside the interrupt as possible. Upon entering the ISR we start our 4 microsecond sync pulse before we save the CPU registers. Once the registers are saved we turn the sync off. Right now we are not doing any useful work during the backporch (8 microseconds per line) so this would be a good time to do something like service a PS/2 keyboard port.
I originally tried to implement 40 column mode by using a lower baud rate. I found that the EUSART would leave a one pixel gap between characters when I did that. As a workaround I created a lookup table which translates 8-bit wide font data into double pixel 16-bit wide output. This consumes 256 bytes of precious RAM. Another solution is to #define CRYSTAL28 and use a 28.636mHz crystal in HS mode (no PLL). This gives a pixel clock of 6.75 mHz (or 7.159). This would save the 256 bytes wasted on lookup table RAM but cuts the available CPU cycles in half.
I did try to use the MSSP (SPI & I²C module) instead of the EUSART but it is not capable of continuous transmission and it left a gap between characters. If you don't "mind the gap" you could use the MSSP and free up the EUSART for communications.
This project was inspired in part by Rickard Gunée's PIC video PONG and Tetris and partly by Don Lancaster's 1978 classic The Cheap Video Cookbook.
The next step is to finish support for a PS/2 keyboard interface. Once that's done and the PIC18F26K22 becomes available (later this quarter) we can use the second EUSART as standard serial port, creating a full fledged ANSI video terminal using only a single chip. Stay tuned!
If you have questions or comments send me some email:
Single layer board was build using PCB-GCODE for Eagle and a Tormach PCNC1100 milling machine.
|PIC Source code||80columnvideo.c|
|80 column HEX file||80columnvideo.hex|
|Eagle PCB Schematic||80column.sch|
|Eagle PCB Board||80column.brd|
September 5, 2010