0%
0%

# 32 Shades of Grey

Portable NTSC test pattern generator

Similar projects worth following
2.7k views
This project implements a low cost portable NTSC video pattern generator for testing monochrome video systems regarding gain and resolution.
The circuit provides a video output with voltage and impedance according with the RS-170 standard.
A CR2025 coin cell powers the circuit that it is automatically activated when the output plug is connected.

The heart of the project is the ATMegaxx8 ATTiny85 running with internal PLL thus providing 6 pins for generating the video signal, being 5 used for luminance and 1 for synchronism.

The 5 bits of luminance drive a resistor network that altogether with the pin used for sync are calculated to provide the output voltages expected by RS-170 standard having an output impedance of 75 ohms.  To accomplish that some math is required, basically an extension of this article

Using 5 bits it is possible to have 32 steps of amplitude from full black to full white,  which one will result in one equation. The Sync tip adds another equation, thus giving 33 equations. Such number should be count twice as we need to solve the equations both with and without the 75 ohm load.  Then the number of equations is 33 x 2 = 66 equations.

We have 7 terms in each equation, each one corresponds to one of the currents of the circuit above.

At the end we have a matrix of 66x7 wich might sound frightening but the assembly of such matix can be performed using a spreadsheet program and solely fullfilling some voltage values:

VOH, VOL: Those are the voltage levels for the output signals for a given voltage and both can be found on the datasheet of the microcontroller. For ATTiny85 operating at 3,0Volts such voltages are 2.5V and 0.5V respectively.

VSyncL = DC Voltage level of the sync tip under 75 Ohm load. Should not be zero or negative as the microcontroller is powered by positive voltage only. A value of 0.1V is a good start.

From the values above we can derivate:

VBlackL = The black level under 75 Ohm load should be 0.3 Volts above the voltage of the Sync Tip wich equals 0.4V for a Sync tip level of 0.1V

VWhiteL = The white level  under 75 Ohm load should be 0.7 Volts above the black level or 1.1V for the present project.

VSyncO = Sync tip level with Open circuit (no load). Shall be twice the value of the equivalent voltage under load. For this project 0.2V

VBlackO = Black level without load. Same principle, twice the value of the voltage under load or 0.8V for this project.

VWhiteO = Same as above, which means 2.2Volts. Some care must be taken when the source is powered at low voltages as this value can not be higher than the VOH.

After the calculation (which is explained below) the values obtained were:

ResistorCalculatedClose comercial value
R1208220
R2412390
R3800820
R415111K5
R527122K7
R6477470
R7763750

As the pin PB5/Reset of the ATTiny85 can't source many current as the other it can be used to drive resistor R5 which will never exceed 925uA (2.5V/2700Ohms)

(Spoiler Alert! Long explanation ahead)

The matrix equation follows Ohm's law:

[ V ] x [ R^-1]  = [ I ]

We know the values of [ V ] and [ I ] and we calculate the values of [ R ] by

[ R^-1]  = [ V ] ^-1 x [ I ]

and finally [ R ] = 1 / [ R^-1 ]

for simplicity we use the conductance [ R^-1 ] instead of resistance.

The voltage matrix is assembled by spreading the voltage levels from black to white along all the possible bit combinations.

As an example let's see how it is done for 2 bits:

V1V2Vout
VOLVOLVBlackL
VOLVOHVBlackL+ (1/3) (VWhiteL-VBlackL)
VOHVOLVBlackL+ (2/3) (VWhiteL-VBlackL)
VOHVOHVWhiteL

We also have to include the voltage Vsync, which should be kept at high level except at the moment of sync tip. Let's also call the intermediary voltages by a short name to declutter the table.

V1V2VSyncVout should be
VOLVOLVOLVsyncL
VOLVOLVOHV0% L
VOLVOHVOHV33% L
VOHVOLVOHV66% L
VOHVOHVOHV100% L

We use the voltage table above to calculate the Voltage drop over each of the resistors, including the pull down resistor, which has negative value since current sinks throug it (while is sourced by the other)

Drop R1Drop R2Drop RSyncDrop R pulldown (-Vout)
VOL-voutVOL-voutVOL-vout-VsyncL
VOL-voutVOL-voutVOH-vout-V0% L
VOL-voutVOH-voutVOH-vout-V33% L
VOH-voutVOL-voutVOH-vout-V66% L
VOH-voutVOH-voutVOH-vout-V100% L

The current...

Read more »

• ### Yet Tweaking

danjovic05/22/2018 at 01:18 0 comments

Replaced the "DAC" resistors with an association to get more precision. The association values have been calculated using an online tool (link)

Desired Value (Ohms)Association (Ohms)
31313k3 // 56K
15631K + 560
780390 + 390
390390
195390 // 390
211220 // 5k6
187220 // 1k2

Nevertheless, the shades yet were not gradual at the center. After some tweaking adding resistors in parallel I've managed to figure out which resistor in the network was disturbing the "linearity" of the output. It happened that to be the 195 Ohms resistor association. Few experiments later I have added a 120 Ohm resistor in parallel thus resulting in 75 ohms (sic) but I've managed to get a good image.

It didn't occurred to me at the moment but maybe there is one bit flipped either in software or in the circuit.

• ### Prototype: Assembly finished and first tests

danjovic05/09/2018 at 03:56 0 comments

Finished assembling the prototype, but first fixed another issue that was a missing pull up resistor on RESET pin. Completely forgot about it because the first prototype, based on ATTiny85 had the RESET pin configured as IO thus such resistor was not required.

Noticed a couple of issues that might be, however, connected. First is the signal voltage that is 1.2Volts peak to peak with open circuit and 0.8 when terminated with 75 ohms resistor. The second issue is that the bars at the middle of the screen are somewhat scrambled again.

It will be necessary to perform a more acurate measurement of Voh and Vol on the circuit and this will probably influence the value of the resistors.

The resolution pattern was very clear on this TV set, as the thinnest line pairs could be distinguished. It demonstrates that this TV set analog circuits can deal with video content compatible with its native resolution (1360 pixels wide). Worth to remember that the test pattern is equivalent to a resolution of 850 pixels.

• ### Browned Out!

danjovic05/09/2018 at 02:05 0 comments

After changing the platform for this project to ATMegaxx8 and used an Arduino board to finally debug my code I have started to assemble the prototype version in perfboard. I have decided to go with prudence and wired only the power and crystal lanes so I could check that such "infrastructure" of my board was ok.

Looking at the datasheet the maximum operatinf frequency should be around 15.6MHz for a supply votage of down to 3,0Volts which is close enough to the frequency that the microprocessor should operate.

The first tests running with the CR2025 battery showed that despite there the clock is being generated on the crystal leads, the completely dead.

Tested again with 5.0Volts and the circuit was OK.. This was a bad signal! What have I missed?

After struggling some time with the idea of changing to a larger Tic Tac box or either using a lower frequency crystal I have remembered to check if the Brown Out Detection was active, and which would be its treshold.

The reading of the fuse bits showed that the brown out was set to 2.7Volts, which should not pose a problem as the battery voltage was about 3.0Volts when tested. Nevertheless I have reprogrammed the fuses to disable the brown out detection and this time the circuit started to generate the signals just as expected.

• ### Anything Redeeming

danjovic05/05/2018 at 03:09 0 comments

After some work on the code I have finally managed to make it work as expected!

The last bug to fall was the color of the bar right after the resolution pattern. It was a register that should be updated but I was out of spare cycles.

Then I have abandoned the use of a table and a pointer to pick up the color of the current stripe; instead I have used a macro with a parameter which happens to be the color and repeated such macro 31 times along the line.

Then, at the lines which contain the resolution pattern it gets easy to replace some stripes for the pattern simply by commenting  the macro. As long as the cycle count matches the multiples of the width of a stripe everything gets fine!

• ### Board for ATMegaxx8 version

danjovic05/04/2018 at 22:18 0 comments

New schematic and board for ATMegaxx8 (48/88/168/328), still in a mint case with provision for a button to allow change the pattern on screen.

• ### Getting things right

danjovic05/04/2018 at 04:33 0 comments

After failing with using the internal oscillator I have switched to Arduino Board as a prototyping platform.

First thing noticed is that the image is perfectly stable using the crystal.

The correction of the grayscale shades after the resolution test pattern were another story. I needed a spare clock cycle to add 3 to the color pointer, then it was necessary to move one instruction some memory positions before and thus save a cycle. some tweak is still necessary, though to get the correct stripe colour after the resolution line pairs.

I have produced a spreadsheet that can calculate all the resistors based on values of VOH, VOL and the sync voltage level when the 75ohm load is attached (e.g. 0,15V). I have a good link on how to solve a matrix equation with rectangular matrices using standard functions of a modern spreadsheet program. No Scilab necessary!

The spreadsheet resulted some values and I have used the most close value available in my parts bin. HOWEVER, I have noticed that the value for the resistors on most significant bits are somewhat critical.

for instance the calculated and used values were:

 Resistor Calculated (Ohms) Used (Ohms) R Sync 211 220 R Bit 4 195 220 R Bit 3 390 390 R Bit 2 781 750 (1k5//1k5) R Bit 1 1563 1K5 R Bit 0 3131 3170 (2k7+470) R Pulldown 187 150

I have lost some time trying to figure out why I couldn't have a good linear (progressive) gradiend after the middle of the screen, and finally discovered that I should have used a value closer to 190 Ohm than the 220 Ohm I have used. At the end I have put another resistor in parallel so the equivalent resistance dropped to 180 Ohms (1k//220) and finally get a good gradient!

The image with correct resistor value can be seen below

Some work has yet to be done to correct the color stripe right after the last vertical line. But I am happy for now.

• ### Failing miserably

danjovic05/03/2018 at 23:55 2 comments

The ATTiny85 internal RC oscillator drifts so badly that it was not possible to have a good image.

It was tested on two TV sets with similar result.

The circuit have been powered by both an arduino actig as a power supply and a battery (to eliminate any chance of power lane induced instability).

The code needs to be corrected (by advancing a pointer) to compensate for 3 missing shades of grey during resolution test pattern.

It looks like some of the resistors are corrected to the wrong pins as the grayscale is not progressive but rather it looks to have 4 distinct progressive patterns on the screen following the order 1 3 2 4 instead of 1 2 3 4.

• ### Checking waveforms

danjovic05/03/2018 at 01:22 0 comments

First captured waveforms showed good results. It seems that everything is OK with the code.

The vertical retrace interval seems to be OK, with the Horizontal Equalization lines as well as the vertical serration.

• ### Operation at 3.3V, Oscillator accuracy

danjovic05/03/2018 at 01:03 0 comments

The initial tests so far have been good. I needed to check:

• That the ATTiny85 could run at 16MHz on 3,3V - OK
• The accuracy of the internal oscillator - OK

The accuracy was no so good as the measured frequency was 16.1MHz, but it is always possible to trim this later using a given EEPROM address that is loaded on the OSCCAL register on the beginning of the code.

It is necessary to program the fuses accordingly and to attach the scope at pin 3 to check the frequency.

Of course it is possible to use other methods that do not involve reprogramming of fuse bits.

• ### Rendering

danjovic05/02/2018 at 14:25 0 comments

Just created a Python script to render the image as it should appear on TV screen.

```# Project: 32 SOG
from PIL import Image

pixelclocks = 837

img = Image.new( 'RGB', (pixelclocks,pixelclocks*3/4), "black") # create a new black image
pixels = img.load() # create the pixel map

for y in range(img.size[1]/2):    # for every line
x=0
g=8
for stripe in range(31):    # For every stripe
for xx in range (27):
pixels[x+xx,y]=(g,g,g)
g=g+8
x=x+27

for y in range(1+img.size[1]/2):    # for every line
x=0
g=256
for stripe in range(31):    # For every stripe
for xx in range (27):
pixels[x+xx,y+img.size[1]/2]=(g,g,g)
g=g-8
x=x+27

img.show()```

Which resulted in the following image

Noticed the height of the image was proportionally enlarged to fit in 3:4 format as it takes 400 lines on the screen.

Share

## Discussions

Morning.Star wrote 05/04/2018 at 03:53 point

Lol thats a punishing specification. You have to do an Open Source one.

'Freed' XD

Are you sure? yes | no

bobricius wrote 04/26/2018 at 05:45 point

GREYat project name ;)

Are you sure? yes | no

danjovic wrote 04/26/2018 at 23:49 point

I don't mean to be proud but I thoroughly aGREY!

Are you sure? yes | no

# Does this project spark your interest?

Become a member to follow this project and never miss any updates