nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

QuatCore: первый свет! (гора родила мышь)

Что-то тяжело у меня сейчас пошло - надеялся уже в пятницу получить картинку, но сколько-нибудь нормальную получил только сегодня, и ту ещё предстоит "облагородить".



Я написал такую программку, ImageTransfer.asm:

;Попробуем передать изображение на компьютер

%include "QuatCoreConsts.inc"
%include "Win1251.inc"

.rodata

	VSync		EQU	0x8000
	HSync		EQU	0x4106	;формат CVI, 9,5 мкс от синхроимпульса до начала строки, и ещё 1 мкс прибавляем, т.к хотим 1024 вместо 1280 (а вообще при 25 МГц полезная строка занимает 1075 пикселей)
	TopRows		EQU	28	;столько синхроимпульсов нужно пропустить, прежде чем начнутся "полезные" строки (минус 1, поскольку считаем до нуля)
	UsefulRows	EQU	719	;количество полезных строк (минус 1, поскольку считаем до нуля)
	WholeRow	EQU	1023	;количество пикселей на строке
	
	; VSync		EQU	0x8000
	; HSync		EQU	0x40EE
	; TopRows	EQU	9
	; UsefulRows	EQU	31
	; WholeRow	EQU	31

.code
	main proc
		%include "SetClock.asm"
		
				SP	Stack
				SIO	UART
				X	InitStr
				CALL	print
		;далее мы хотим "бесконечный цикл", где мы записываем изображение в статическую память, выдаём самую простенькую информацию,
		;и ждём нажатия на кнопку, чтобы передать всё изображение (это дохрена)
	@@FrameLoop:
				ERL	0
				ERH	0
				ACQ	VSync	;дождаться кадрового синхроимпульса
				
				; X	VSyncStr
				; CALL	print
			
				;пропустить верхние "пустые" строки
				Acc	TopRows
	@@TopRowLoop:		ACQ	HSync
				SUB	1
				JGE	@@TopRowLoop

				; X	TopRowStr
				; CALL	print
				
				;начинаются полезные строки
				Acc	UsefulRows
	@@UsefulLoop:		ACQ	HSync
				ACQ	WholeRow
				SUB	1
				JGE	@@UsefulLoop
				
				;ну вот и всё
				;блин, а ведь мы не можем ER вывести, он только на запись!
				;ну и хрен с ним...
				;а давайте прямо выведем - и всё
				
				ERL	0
				ERH	0	;сбрасываем статическую память в нолик
				
				;самое смешное: у нас в 16-битный регистр не влезет то число, до которого делать итерации!
				;либо применить FMA, либо тупо 2 вложенных цикла
				j	29
	@@OuterLoop:		Acc	24575		;24576 * 30 = 1024 * 720 
	@@InnerLoop:		OUT	[ER++]
				SUB	1
				JGE	@@InnerLoop
				jLOOP	@@OuterLoop
				
				;вот как-то так
				;и теперь дождёмся ввода от юзера
				NOP	IN
				JMP	@@FrameLoop
	main	endp
	
	%include "Print.asm"
	
.rodata
	InitStr		db	'Начинаем работу',13,10,0
	VSyncStr	db	'Передали задание VSync',13,10,0
	TopRowStr	db	'Обработали верхние строки',13,10,0
	
.data
	Stack dw ?,?
	


И прямо сразу прошил в ПЛИС. И в общем-то, "признаки жизни" оно подало: частота установилась в 25 МГц, и по UART пришло ровно 1024х720 байт, после чего "всё останавливается", пока не передашь туда произвольное сообщение - тогда эти 1024х720 байт отправляются повторно. Одно плохо: все эти байты 0xFF, то бишь "все единицы"...


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

Уже в самом начале работы, когда даже АЦП не была активирована, "контроллер SRAM" (модуль QuatCoreFastSRAM) почему-то начал инкремент регистра ER, по единичке за такт.

Когда в пятницу на велосипеде ехал домой - сообразил, в чём было дело, "осенило". Если помните, у нас появилось два сигнала, которыми видеопроцессор управляет модулем памяти, это ReadEnable (разрешает осуществлять чтение из памяти, которое идёт по той же шине данных, что и поступает картинка с АЦП) и WriteFromADC (просит записать в память текущий сигнал, идущий с АЦП, т.е со стороны ПЛИС шину надо "освободить", сформировать сигнал WE, а после этого сделать инкремент ER).

Так вот, WriteFromADC мог устанавливаться в 1 даже когда АЦП ещё был неактивен. Критерием для его установки считалось лишь то, что мы "не дожидаемся синхроимпульсов", и не находимся в участке Back Porch сразу после синхроимпульса. При включении так оно и есть - вот и началась запись с инкрементом по чём зря...

Это я в понедельник исправил, снова пробую запустить на ПЛИС - а становится ещё чудесатее - ОНО ЗАВИСАЕТ! Выведя на светодиоды несколько сигналов, я понимаю: застревает на команде ACQ HSync, видимо из-за заполненного буфера, но буфер не освобождается.

Расчехлил осциллограф и стал смотреть, а оно вообще работает? Увидел, что аналоговый сигнал идёт. Тактовая частота на АЦП идёт. А вот на вход отключения АЦП поступает лог. "1", хотя в этот момент должен идти нолик.

Так что снова вернулся к симуляции и стал наблюдать. Сразу обнаружил очень странное поведение UFLO и OFLO - они почему-то на всём протяжении стояли на лог "1", чего быть в принципе не должно! Ведь процессор набивает заданий "под завязку" (ему гораздо быстрее отправить задание из цикла, чем видеопроцессору его обработать), так что UFLO (опустошение буфера команд) "зажигаться" ну никак не должен! Да и учитывая, что каждая вторая команда - это ACQ HSync, которая опустошает выходной буфер, очень странно видеть OFLO=1 (переполнение выходного буфера, т.е процессор не успевает обработать всё то, что ему выкатил видеопроцессор, и теперь новые данные класть тупо некуда).

Не знаю, сколько часов потратил, разбираясь в этом. То "пристально вглядывался" в модули, пытаясь понять - КАК ТАКОЕ ВООБЩЕ ВОЗМОЖНО? То добавлял уйму "отладочных выводов", чтобы увидеть, откуда же оно смогло сформироваться?

В итоге оказалось: ВЫВОДЫ UFLO и OFLO БЫЛИ ТУПО ПРИСОЕДИНЕНЫ НЕ ТУДА! Пока я переделывал всю эту конструкцию, схемотехнический символ QuatCore+GPU чуть поменялся - выводы стали в другом порядке, и эти UFLO и OFLO оказались присоединены к SPI, по-моему вообще один из них к ADC_nCS (для "медленной" АЦП, которую мы вообще не использовали сейчас), а другой к ETH_nCS (а вот это мы использовали в самом начале чтобы установить тактовую частоту). АААА, НУ КАК ТАК-ТО???

Но оставалось тайной, почему же у нас отключён АЦП, если по симуляции он совершенно железно включался? Сегодня я "вывел на светодиоды" управляющие сигналы для АЦП и SRAM. Смотрю - опять зависло, но светодиод, отвечающий за ADC_Disable ("отключение АЦП") ПОГАШЕН! То ЛОГИКА ВНУТРИ ПЛИС СРАБАТЫВАЕТ ВЕРНО! Достал тестер - и стал прозванивать провод, ведущий от ПЛИС к АЦП. На отладочной плате ПЛИС НОЛЬ. На плату SRAM также пришёл НОЛЬ (там оно транзитом проходит, через цанговые разъёмы). На плату с АЦП тоже НОЛЬ. Таак, а на ножке АЦП? И ЗДЕСЬ НОЛЬ!

Да что за нахрен??? Раз здесь ноль - должно работать. Хм, А оно работает! В общем, какой-то ГейзенБаг.


Видимо, где-то контакта не было тупо... Действительно, я на выходные всю эту конструкцию домой забирал, думал - вдруг захочется поработать. Не захотелось почему-то. По-моему, там непропай на платке АЦП. Я какие-то древние штырьки PLS нашёл у себя в загашниках, потемневшие, видать недоочистил.

Но оказалось, что на компьютер опять пришли сплошные 0xFF, т.е "белый экран". Пришли к тому же, с чего начали в пятницу...

После очередного "пристального взгляда" наконец увидел, в чём проблема: у меня стоял параметр EnableSRAM=0. Так что все беды от жадности! Переправил его на 1 - и наконец-то получил что-то более многообещающее:



Но очень уж быстро приходили к одному и тому же 0x38 0x3A - и так на всём протяжении файла, с небольшими вкраплениями 0x39.

Частичное объяснение этому тоже было найдено: я забыл переправить константы назад к "штатным", к картинке 1024х720 вместо "модельной" 32х32. Поэтому ясно: АЦП отстрелялся слишком быстро, а дальше неинициализированная память. Почему она настолько однородно не инициализирована - уж не знаю.

Наконец, когда я переправил константы назад, то получил нечто "информативное" от начала до конца. Но когда составил из этого картинку, вышло такое:


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

Здесь уже угадывалась проблема: камера была настроена в режим CVBS (видеосигнал стандартной четкости, который можно через желтый тюльпан подключить к любому телевизору), а мы-то ожидали сигнала высокой чёткости!. В итоге, вместо 25 Гц прогрессивной развёртки, выходило 50 Гц чересстрочной, и с другой длительностью строки.

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

Картинка не ахти пока что.
Во-первых, она "циклически сдвинута по горизонтали". Причину этому я уже знаю: процессор обнуляет ER и начинает передачу картинки, НЕ ДОЖИДАЯСЬ ОКОНЧАНИЯ РАБОТЫ ВИДЕОПРОЦЕССОРА! Тому ещё остаётся обработать 4 строки, и он записывает их уже после обнуления ER, тем самым сдвигая его. Сейчас на обратном пути подумаю, как это красивее всего исправить. Но оно очевидно исправляется, пусть даже тупо длинным циклом, за время которого обработка заведомо завершится :)

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

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

Ладно, надо же с чего-то начинать!
Tags: ПЛИС, программки, работа, странные девайсы
Subscribe

Recent Posts from This Journal

  • Формулы приведения, что б их... (и atan на ТРЁХ умножениях)

    Формулу арктангенса на 4 умножениях ещё немножко оптимизировал с помощью алгоритма Ремеза: Ошибка уменьшилась с 4,9 до 4,65 угловой секунды, и…

  • Алгоритм Ремеза в экселе

    Вот и до него руки дошли, причина станет ясна в следующем посте. Изучать чужие библиотеки было лениво (в том же BOOSTе сам чёрт ногу сломит), писать…

  • atan на ЧЕТЫРЁХ умножениях

    Мишка такой человек — ему обязательно надо, чтоб от всего была польза. Когда у него бывают лишние деньги, он идёт в магазин и покупает какую-нибудь…

  • Ай да Пафнутий Львович!

    Решил ещё немного поковыряться со своим арктангенсом. Хотел применить алгоритм Ремеза, но начал с узлов Чебышёва. И для начала со своего "линейного…

  • atan(y/x) на двух умножениях!

    Чего-то никак меня не отпустит эта тема, всё кажется, что есть очень простой и эффективный метод, надо только его найти! Сейчас вот такое…

  • Таблица коэффициентов для atan1

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

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 2 comments