nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

Детектор синхроимпульсов на ПЛИС

Потеряв ещё сколько-то времени, мы наконец-то поменяли тактовую частоту, поступающую на ПЛИС 5576ХС4Т с 4 МГц на 25 МГц, которые нам нужны для обработки видео высокой чёткости. дополнение к прошлому посту: как-то я совсем позабыл, что получаю 5 вольт с компьютера по USB, а в задний USB-порт того же компьютера воткнут USB-осциллограф, и его же "земля" соединена через минус щупа с "землёй" макетки. Образуется старая добрая земляная петля и ловит всё, что только может поймать в трёх хитрючих цифровых устройствах :) Сейчас решил отключать ПЛИС от компьютера на время измерений, запитывать её от лабораторного блока питания - вроде стало получше. Но высокие частоты, скажем 25 МГц, уже тяжело он воспринимает, лучше до этого не доводить...

Как производить оцифровку аналогового видеосигнала высокой чёткости, мы почти что рассказали. Это, опять же, вариант "для бедных": данную 8-битную АЦП я купил "в розницу" чуть больше чем за сотню рублей, при том, что не сильно старался найти наименьшую цену. 10-битные или 12-битные АЦП на частоту хотя бы 25 МГц - уже совсем другие расценки... Но посмотрим для начала, на что способны 8 бит, особенно учитывая гамма-функцию. Так уж повелось с зари телевидения, что аналоговые видеосигналы отображают яркость НЕЛИНЕЙНО. Они рассчитаны на то, чтобы после усиления напрямую подаваться между катодом и модулятором электронно-лучевой трубки телевизора, которая имеет нелинейную характеристику - вблизи запирания крутизна очень мала, а по мере роста тока крутизна характеристики растёт. В итоге, снижение напряжения в два раза (если за ноль считать чёрный) не приводит к уменьшению яркости в 2 раза. Считается, что яркость уменьшается примерно вчетверо, т.е как квадрат отношения.

Вызвано это было тем, что один раз провести нелинейное преобразование в телецентре получалось дешевле, чем в каждом телевизоре, ведь на лампах это выходило достаточно серьёзным усложнением! Но даже при появлении компьютерных мониторов решили сохранить данный "формат", поскольку заметили - тогда нам вполне хватает 8 бит для неплохого динамического диапазона, тогда как в противном случае было бы необходимо ставить 12, а то и 16 бит, а в те времена это было серьёзной проблемой.

Так что и мы пока решим, что 8 бит нам хватит.

Пора наконец-то выделить синхроимпульсы, для начала - все "скопом"...




В аналоговой части мы поставили диод, который вроде как должен восстанавливать "уровень синхроимпульса" - что бы ни происходило, а он будет находиться на -0,6 вольтах. Казалось бы - теперь мы просто ставим "цифровой компаратор", настроенный где-то посередине между уровнем синхроимпульса и уровнем чёрного - и проблема решена.

Увы, всё не так просто. Вот как выглядит осциллограмма на входе в АЦП во время кадрового синхроимпульса:


Пока у нас шёл сигнал большого размаха (светлые строки), синхроимпульсы действительно "фиксировались" на постоянном уровне. Но затем наступили уравнивающие импульсы - они пока ещё держались. А вот кадровые импульсы "поползли вверх" - когда на левую обкладку конденсатора подаёшь длительные отрицательные импульсы, они же передаются на правую обкладку, и конденсатор начинает довольно быстро разряжаться через входное сопротивление АЦП.

Но по этой осциллограмме кажется, что мы всё-таки можем подобрать подходящий порог, по которому синхроимпульсы будут надёжно выделяться. Собственно, как и говорилось раньше - где-то посерёдке между уровнем чёрного и уровнем синхроимпульса.

Увы, мы ещё не учли наличие "вспышки" цветовой поднесущей. Если мы выберем порог так, как хотели, то и данные вспышки будут классифицироваться как синхроимпульсы, что может сильно нам навредить:


Можно эти лишние импульсы убрать уже цифровыми методами - сделать необходимый интервал между синхроимпульсами, где-нибудь в половину строки, но мне кажется, что это не лучшее решение.

Я бы предпочёл восстановить уровни ПОВТОРНО, теперь более точно и с нужной нам постоянной времени. Всё-таки, наше решение с диодом - довольно грубое. Как мы обсуждали, в очень тёмных кадрах фиксации происходить вообще не будет (не дойдёт до -0,6 вольта), а на кадровом синхроимпульсе оно поползёт ещё выше. А ещё, все эти уровни будут плавать в зависимости от экземпляра диода и от температуры.

А именно, предлагаю сделать "цифровой аналог" следующей цепи:


"Идеальный диод" будет открываться при нулевом падении напряжения. Величина ёмкости как таковая не имеет роли - главное, что при открытии диода она моментально перезарядится до входного напряжения, а когда диод закроется - будет удерживать это напряжение, но оно будет линейно уменьшаться за счёт источника тока, включённого параллельно.

Надо выбрать такое значение, чтобы этот "конденсатор" разряжался чуточку быстрее, чем его аналоговый тёзка на осциллограмме выше (с кадровым синхроимпульсом) и таким образом, каждый следующий импульс, чуть приподнятый относительно предыдущего, снова фиксировался на нуле.

Приведём код такой "схемы" на верилоге:

module SoftcoreSyncDetector (input clk, input [7:0] D, output reg CompositeSync = 1'b0);

//bigger number: lower leak (1 LSB in 1 / (1 << LeakLevel) pulses)
parameter LeakLevel = 7;

wire drip; //little charge drips into capacitor
//should be consistent with RC circuit on ADC input
//so rise of level by it is comparable to
//rise of level here
lpm_counter Leaker (	.clock (clk),
			.cnt_en (1'b1),
			.cout (drip));
defparam
	Leaker.lpm_direction = "UP",
	Leaker.lpm_port_updown = "PORT_UNUSED",
	Leaker.lpm_type = "LPM_COUNTER",
	Leaker.lpm_width = LeakLevel;

wire [7:0] CapacitorVoltage; //we have 'input capacitor'
wire DiodeClosed;

lpm_counter Capacitor (	.clock (clk),
			.cnt_en (drip),
			.sload (~DiodeClosed), //when diode opens, capacitor voltage becomes equal to input signal
			.data (D),
			.Q (CapacitorVoltage));
defparam
	Capacitor.lpm_direction = "UP",
	Capacitor.lpm_port_updown = "PORT_UNUSED",
	Capacitor.lpm_type = "LPM_COUNTER",
	Capacitor.lpm_width = 8;

//but now we find voltage after this capacitor
wire [7:0] Dnew;

//when subtracting unsigned and have carry=1, it's all right (the only way to make number less is to 'go around')
//when carry = 0, it means 'overflow', that is result is negative
lpm_add_sub CapSubtract (.dataa (D),
			 .datab (CapacitorVoltage),
			 .result (Dnew),
			 .cout (DiodeClosed));
	defparam
		CapSubtract.lpm_direction = "SUB",
		CapSubtract.lpm_hint = "ONE_INPUT_IS_CONSTANT=NO,CIN_USED=NO",
		CapSubtract.lpm_representation = "UNSIGNED",
		CapSubtract.lpm_type = "LPM_ADD_SUB",
		CapSubtract.lpm_width = 8;						 
						 
//second stage: now we just need to compare output signal with some threshold. 70 mV (typ for LM1881) is 18 LSB, 
//let's make it 16 LSB. Maybe we'll change it to 32 LSB later
//yup, since our signal has STRONG sync pulses (0,5 Vpp) and even if  image is fully white and got clamped because of ADC,
//we still have 250 mV pp, while because of ADC noise we're much more susceptible to all sorts of noise!

//also, little filtering could be beneficial.

//so, negative voltage (DiodeClosed = 0) or small positive voltage (0 .. 15) is sync pulse!
always @(posedge clk)
	CompositeSync <= (~DiodeClosed) | (DiodeClosed & (~Dnew[7]) & (~Dnew[6]) & (~Dnew[5]) & (~Dnew[4]));
	
endmodule


Входом является 8-битный отсчёт от АЦП и тактовая частота. Выходом - "комбинированный синхроимпульс".

Как это ни странно, здесь "конденсатор" реализован как счётчик с входом разрешения счёта и с входом параллельной загрузки. Счёт соответствует постепенному разряду конденсатора, что необходимо, чтобы данная схема находила "локальные" минимумы, а не глобальные. Но поскольку полному размаху сигнала соответствует число 255, а самое маленькое значение: 0, то счёт на каждом такте был бы слишком быстрым.

Напомним: длительность строки составляет 64 мкс для стандартного телевизионного сигнала (для 50 Гц) и 53,3 мкс для сигналов высокой чёткости, в чём мы недавно убедились.

На осциллограмме выше (где кадровый синхроимпульс) мы видим, как за 2,5 строки стандартного сигнала (5 вдвое укороченных импульсов) конденсатор успевает разрядиться примерно на 100 мВ, что соответствует скорости 0,625 мВ/мкс. Один отсчёт АЦП у нас равен 4 милливольтам (АЦП принимает напряжения от -0,512 до +0,512 вольт, выход 8 бит), одна микросекунда - это 25 тактов на частоте 25 МГц.

Таким образом, нам нужно вычитать единичку приблизительно каждые 160 тактов.

Для этого мы поставили ещё один счётчик и обозвали его Leaker. Задали параметр, LeakLevel = 7 - это значит, что он будет считать до 27 и досчитав до конца, давать импульс на вход счёта "конденсатора". То есть, мы вычитаем единичку каждые 128 тактов, чтобы иметь некоторый запас. Данный счётчик прост до безобразия - он считает ВСЕГДА. Его "выход переноса" выведен на провод drip ("Кап!").

Ещё один компонент, который описывает и конденсатор (частично), и идеальный диод - это 8-битный сумматор, настроенный на вычитание. Он вычитает из входного сигнала "напряжение на конденсаторе", и это значение поступает далее на компаратор. Выход переноса используем, чтобы понять, что меньшее было вычтено из большего, а значит, пора ОТКРЫВАТЬСЯ ДИОДУ! Иными словами, сейчас выход фиксируется в нуле, и конденсатору ничего не остаётся, как зарядиться до входного значения. Именно это мы и видим в описании "конденсатора" - входом sload (синхронная загрузка) управляет сигнал ~DiodeClosed.

И остаётся только реализовать компаратор. Здесь мы тоже упростили себе задачу: решили в качестве порога выставить 64 мВ, поскольку это соответствует числу 16 (в отсчётах АЦП), а проверить, что число меньше 16 - очень просто. Достаточно, чтобы 4 старших разряда были нулевыми. Дополнительно мы проверяем - не проскочило ли отрицательное число, оно тоже сойдёт :)

Вот, собственно, и весь модуль. Он занимает 27 логических элементов (ЛЭ, LE) - совсем немного даже на фоне 2880 ЛЭ, доступных в 5576ХС6Т. А для 5576ХС4Т с её 9984 ЛЭ - вообще капля в море.

Выведем выход данного модуля на какую-нибудь свободную ножку ПЛИС и посмотрим, что в итоге получается в различных видеоформатах.

осциллограмма для CVI приведена в начале поста. Всё чётко, повторных импульсов на вспышке цветовой поднесущей не возникает.

Теперь переключимся в TVI:


Отлично! И я их, похоже, начал различать "на вид" наконец-то. CVI-в котором самый короткий обратный ход, практически сигнал и синхроимпульс. TVI - у которого очень длинное "гашение" на каждой строке.

Глянем AHD:


Всё хорошо. И наконец, обычный сигнал CVBS:


Всё это время камера была направлена вдоль стола и выдавала некое изображение. Она автоматически подстраивала экспозицию, чтобы были и светлые, и тёмные места. В таком режиме всё работает замечательно.

Но для полной проверки нужно глянуть ещё два граничных случая: тёмный кадр и очень светлый кадр. Чтобы получить тёмный, достаточно заслонить камеру рукой. Она увеличит экспозицию, но свыше 1/25 секунды сделать принципиально нельзя, так что ничего не останется, как показывать чёрный экран. А чтобы потом получить очень светлый кадр - надо убрать руку, и первые пару секунд камера будет "слепнуть" от чрезмерного света, пока не снизит экспозицию до нормального уровня.

Тёмный кадр - нормально:


Светлый кадр - тоже без проблем:


Именно за стандартный сигнал я переживал больше всего, поскольку в нём вспышка цветовой поднесущей самая мощная. Но и здесь она никаких проблем не вызвала.

Конечно, мы ещё не смотрели, что творится на кадровом синхроимпульсе, но сейчас "поймать" его осциллографом довольно сложно.


Теперь осталось сделать селектор синхроимпульсов, который выделит отдельно кадровый синхроимпульс...
Tags: ПЛИС, программки, странные девайсы
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments