Yet another project trying to generate VGA signals using small avr mcu.
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
I've already investigated changing line frequency, and line count per frame independently, now it's time to see, how the display takes simultaneous changes. As previously, I am starting with standard VGA 640*480 @ 60 Hz.
Now, the line count and line frequency are changed together in such a way as to keep frame rate close to constant of 60 frames per second. This way, when line count per frame is decreased, the line duration is increased accordingly (thus lowering line frequency), and vice versa.
I am starting with decreasing line duration / increasing line number.
The recognized standard VGA 640*480 persists up to 530 lines / 31.796kHz.
At higher line frequency and line number fallback to 800*480 occurs.
A switch occurs when line number reaches 559 and line frequency becomes 33.536 kHz -- now, the image is recognized as 1920*540px. This is exactly half of full HD (1920*1080), and I think it is actually the interlaced version 1080i.
Next switch is at 568 lines / 34.076 kHz -- fall back to 800*480.
At 621 lines occurs switch to LCD native resolution of 1024*600.
At 625 starts to recognize as SVGA (800*600 @60Hz).
At 634 lock is lost, screen is black.
At 740 lines a new lock occurs, the signal is recognized as 1280*720px.
At 779 lock switches to 640*400.
When reaching 819 lines, image size becomes 1280*800.
In the vicinity of 890 lines, switch to 1152*864 -- somewhat strange resolution, I would say.
At 935 lines starts the zone of 1440*900.
Between 975 and 985 lines lies black zone, and then starts 1280*960.
Between 1035 and 1045 is another gap, and then starts 1280*1024.
At 1088 lines starts 1680*1050 @60Hz mode.
At 1115 lines the HD resolution 1920*1080 is recognized. This goes up to 1165 lines, after that switch occurs to (possibly default) 720*400px mode.
At 1195 lines switch back to 1920*1080 occurs.
Maximum number of lines per frame is 1200, when over this value, "Not support" message is shown. This concludes the upwards sweep.
Going down in line number, starting from 525 of the standard VGA, through 522 lines, the image is recognized as 640*480, and starting from 521, it is now 800*480 @60Hz.
At 491 lines the lock is lost, and black screen is presented. Then, starting from 488 lines, lock is regained with resolution of 720*400.
Seems like the lowest line number per frame is 421, as lower values trigger "Not support" message.
Now, I tried to find out what would be a smallest frame supported, at lowest frequency -- it turns out 720 by 400 pixels, at 49 Hz, with line duration of 48.625 microseconds (frequency of 20.565 kHz). By measuring width of image blocks on screen ("pixels" generated by Arduino board) with ruler, and taking into account that to draw one it takes 11 clock cycles, I came to value of 35.44 microseconds, out of the total 48.625, as the active draw length; and having 720 pixels on it, the square pixel duration would be 49.2 nanoseconds, which means pixel clock should be 20.316 MHz. If using 20MHz crystal, these timings will yield image of 708 by 400 very slightly elongated pixels, which can be corrected in width adjustment menu on OSD of this display monitor.
----------------------------
RESULTS:
The cheap noname chinese monitor with LCD panel of 1024 by 600 pixels, and driven by RTD2660H chip can accept a variety of timings through its VGA port, leading to different display resolutions recognized. The line frequency and the number of lines per frame can be varied smoothly in a wide range, only condition is that resulting frame rate should lie in range between 49 and 75 frames per second. There is caveat in that sometimes, close to boundaries between recognized modes, colors can be incorrect, and some narrow ranges can not be locked on. All the most popular modes (640*480, 800*600, 1280*1024, 1280*720 (HD 720p), 1440*900, 1920*1080 (HD 1080i and 1080p)) are recognized, as well as several others, aligned to display's aspect ratio.
Here I post my findings about tolerance to frame height in lines, while line frequency is held constant, equal to one in standard VGA signal (640*480 @60fps -- 31.496kHz line frequency, or 31.75 microseconds per line).
As the full frame at standard resolution contains 525 lines, I am changing it to lower and higher values, until the display cannot lock on it. With line frequency being constant, changing line number inversely affects frame rate -- the higher number of lines per frame, the longer it takes to draw it, and hence the number of frames drawn per second decreases.
At first, I am increasing number of lines - until the total number is no bigger than 530, the display accepts it as valid VGA 640*480, at 59fps. When I increase line count further, the recognized resolution falls back to 800*480. The most lines per frame before display couldn't lock to the signal is 620 lines, at this frequency. This translates to 50Hz frame rate.
Going to the other direction: the lowest line count when 640*480 is recognized is 522, lesser amount triggers fallback to 800*480. This goes down to 492 lines, and with less lines the lock is lost. Surprisingly, at 488 lines lock is regained, and now it recognized as 720*400px image, at 64 Hz. This lock is available at minimum line number of 421 per frame, at 75Hz. Any lower, and OSD is shown with message "Not Support".
----
From this and previous log I can conclude that the main constraint for this display is framerate, which falls in range between 48 and 75 Hz. Anything above and below triggers "Not Support" message on screen, or it just doesn't lock at all, and screen remains black. Seems like, when the frame rate falls in between these extremes, the line frequency and number of lines per frame can be changed freely.
Also, when timings are close to VGA standard, the width to height ratio is chosen to be 4:3, as in the standard, and away from these values the monitor falls back to its native ratio close to 1.7 (1024 by 600 pixels of its LCD).
According to standard timings, line frequency for 640*480@60 Hz VGA signal should be 31.469 kHz, given the full frame, that aside from active area also contains blanking and sync, is 525 lines total. Line duration is thus 31.778 microseconds.
Here are results of my experiments with varying this line duration -- with total lines per frame fixed (525) this will effectively control the frame rate, with shorter line durations leading to faster refresh, and vice versa.
Using Arduino, closest approximation to this line duration can be done in steps of 0.0625 (1/16) of microsecond, as its clock rate is 16MHz. This way, the standard line duration would be 31.75 microseconds (508 clock cycles), and it gives us framerate of 55.993 fps, very close to 60.
With these parameters, the OSD shows the standard VGA:
In previous log I described my findings regarding monitor handling of Vsinc pulse of different widths. It turned out that locking on frame rate is seemingly done on the pulse start, and the pulse polarity is irrelevant. The pulse itself is whatever phase of PWM signal is shorter.
Now, I will do similar investigation on Hsync pulse, for the standard VGA 640*480@60Hz.
The line duration is 31.75 microseconds (us) for this mode, and the Hsync pulse is LOW with duration of 3.8125 us. These are approximations from the standard using base clock of 16MHz - the frequency at which the atmega168 microcontroller chip of my Arduino Nano knock-off board operates.
I started to make this pulse narrower, and the monitor consumed it ok. The smallest pulse duration was just 2 clock cycles, or 125 nanoseconds - looks like in this vicinity the RTD2660H chip locks to start of the line. Only pulse length of 1 clock cycle, i.e. 62.5 ns, is not recognized. Looks like the minimum length is some 100 nanoseconds.
On the other side, there is also a tolerance to bigger horisontal synchronization pulse widths. There is one side-effect visible - during blanking interval which is triggered by sync pulse end, there is dark calibration on part of the line performed. And when pulse width becomes so long that it ends during active image area, the line is sampled at non-zero values, which throws colors off. Otherwise the image itself is stable.
The vertical grey line in the middle of image is probably that dark level sampling area.
When further increasing Hsync pulse length, the lock flips the same way as it was with Vsync -- when LOW pulse becomes longer than HIGH, then the latter starts being used as the synchronization signal, and image now tears apart.
Even further increase of LOW hsync signal duration makes image move left, and when the HIGH part becomes similar in length as standard LOW pulse, the image becomes centered again. This way, the signal polarity is completely flipped, without any consequences on locking onto line.
One fun thing that might be done, is make Hsync and Vsync pulses slightly bigger that half of line / frame respectively -- this way image tears both horisontally and vertically:
------------------------------------
Concluding sync pulse investigations, I can say now that this monitor is very tolerant to synchronization pulse widths and polarities, as long as timings are stable (at start I had jitter and that was preventing lock). One is not required to make these pulses strictly adhere to standard, but only to provide correct periods (line lengths and line numbers per frame) for stable image to be able to be displayed on this screen.
In one of the previous logs I pledged to find out what are tolerances of RTD2660H chip inside the monitor regarding VGA signals it can recognize as valid.
I started with the most VGA signal there is -- 640*480 pixels at 60 frames per second. Though the image is 480 lines in height, the whole frame, taking into account blanking and Vsync has 525 lines in it. As for the number of pixels per line -- the value is almost arbitrary -- the video signal itself is analog, and there is no intrinsic discretisation of the line into separate pixels. The standard of 640 pixels per line is chosen such that pixels are "square" on monitors (on CRTs they are more round than square though). What actually matters is correct timing of horizontal synchronization pulse, and of blanking intervals.
The first experiment is checking the limits on vertical sync pulse width. The standard one is 2 lines. But I found that this monitor is just fine with Vsync pulse of single line. On the bigger side there seemingly no hard limit on vSync width. For the value of 256 lines the image gitches funnily, although for higher and lower values, there is no such glitching.
Starting with 263 lines (i.e. the LOW vsync pulse becomes just longer than half of the frame), the synchronization circuit flips, and image is split in two, with lower half on top and top half in the bottom.
With further increase of the length of low pulse, the image is shifted upwards, and when polarity of Vsync is completely reversed, meaning that instead of active LOW pulse duration of 2 lines there is an active HIGH one of the same length, the image is displayed correctly.
IN CONCLUSION, it seems that RTD2660H chip handling decoding of VGA signal does not enforce strict polarity rules on vertical synchronization pulse, and instead treats the start of the shorter phase as trigger for starting a new frame.
I slightly updated the circuit, adding 3 simple 2-bit resistor ladder DACs, so that now I can output images in 64 colors (RGB 222).
The images are measly 36(or less) by 25 pixels, so are quite blocky. They are taking 900 bytes, thus I can hold only one in 1kB memory of atmega168 chip.
Blockiness is also comes from the fact, that each pixel takes some time to output; in my implementation the for loop is used to retrieve each pixel value from array, and each loop takes 11 cpu cycles, so at 16 MHz, I can output a pixel every 688 nanoseconds, thus effective pixel clock is at 1.4545 MHz, far less than 25.175MHz for standard VGA 640*480@60Hz.
Next is a couple of examples of images produced:
An airport radar tower
NNot 
A picture of a Minion:
Some 3 years ago I've bought a small 10-inch monitor on AliExpress for using in projects involving generating VGA signals. At the time I checked that it works, but haven't done the experiments I intended it for, until just recently; it was lying around in my electronic junk box.
Now, I've retrieved it, and took a look inside, hoping to find out what chip is driving it, and through searching in its datasheet to find which resolutions and framerates it can recognize from VGA input. The chip was found to be RTD2660H, its datasheet proved quite dense, and I couldn't figure out where in it the info I needed could be found. So, now I am resorting to find out experimentally, what it can take for recognizable input, starting with standard timings that it sure should recognize. I'll write what I found in the future log entry.
Now, here will be just photos of this monitor:
Front
Back
Inside
LCD panel number up close:
Controller board:
---------------------------
It looks like this one is similar to small monitors for Raspberry Pi sold by Adafruit; at least the controller board has the same chip, and looks very similar. Example with seemingly the same LCD panel.
It took a couple of days to write a program for avr processor capable of outputting sync signals good enough for the monitor to recognize them as valid.
As I chose to not use pre-made libraries, it takes some time to make things work properly.
As the starting point, I wanted to generate the standard VGA signal, 640*480px @60Hz. After this is achieved, the goal is to test other modes, the standard ones, as well as not so standard -- by playing around with timings and sync signal polarities.
Here is the first image that I generated:
Here is the reason, why the edges looked like this: the Hsync signal is generated by the timer/counter on atmega168 that is operating independently of anything going on on the cpu itself -- essentially I am generating PWM signal, that is very stable, and this way the display monitor is able to lock on it. But the generation of visible pixels is done via software running on this cpu. When the counter reaches pre-set value (508, this at 16MHz the processor is working on is almost exactly the line length for standard VGA signal), it triggers interrupt, and in its service routine the flag is set. This flag is then read/ polled in main loop, and there all the necessary computations are done. While setting the flag by interrupt service routine is consistent, the reading of it via polling loop is not, and this means that the drawing of each line stars with different offset to the Hsync signal, making vertical edges ragged.
After I moved all the line drawing logic into interrupt service routine, the ruggedness was almost gone, although the interrupts are served for almost all the width of drawn line, and vertical edges still showed short comb pattern:
This proved fairly hard to remedy, as the cause is that drawing logic has conditionals in it, and depending on condition, there is different number of cycles the cpu has to do to process them. Finally, with some fiddling with the code, I was able to produce the image with smooth edges - it took inserting another condition, and several 1-cycle instructions such so this combing was canceled out:
Create an account to leave a comment. Already have an account? Log In.
Become a member to follow this project and never miss any updates
zpekic
Pavel
Nathan Kiesman
Nick Bild