nabbla (nabbla1) wrote,
nabbla
nabbla1

Category:

Возвращаемся к макету

Очень давно макетом видеоизмерителя параметров сближения не занимался: сначала "громко думал" по поводу измерения его положения на аппарате, а потом заболел.

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

Опять полез внутрь с осциллографом, ещё и коротнул что-то случайно, предохранитель сгорел. После замены предохранителя продолжил копаться и обнаружил - тактовая частота на АЦП не поступает. После долгого прозвона понял: она и с ножки ПЛИС не идёт. Причём защитный диод "вниз" звонится, а "вверх" - нет. У других ножек нормально, а у этой конкретной - "нет соединения". Видимо, она всё-таки сгорела. Почему - не знаю, то ли случайно, то ли из-за перегрузки. Всё-таки, с неё непрерывно шло 25 МГц. Единственной нагрузкой был вход АЦП, он КМОПовский, т.е активной нагрузки нет в принципе, ёмкостная - несколько пикофарад. Но учитывая, что это этажерка из 3 макеток, причём на 3-й ещё и четвёртая платка стоит, "адаптер из SSOP в DIP", монтажная ёмкость может быть куда больше...

В итоге припаялся к другой ножке ПЛИС, а "старую" ножку настроил на вход, посмотреть, работает ли входная цепь. Она должна была управлять светодиодиком, но увы - он не зажёгся. Похоже, выгорела напрочь. А на новой ножке померял напряжение: 1,55 вольт, очень похоже на правду (симметричный меандр от 0 до 3,3 вольта).

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


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


Выделенное фиолетовым - это "мантисса" координаты X вектора параллельного переноса, 0x953A = 38202, или 1,16583 в формате UQ1.15 (беззнаковое, 1 разряд перед запятой, диапазон 0..2-2-15). Вместе с экспонентой 9 (предыдущее слово данных) и заданным смещением "-1", получается 298,45 метра дальность.

А ведь раньше у нас получалось 0x9591 = 38289, что приводило к дальности 299,13, что ближе к модельным 300 метрам.

При всём при том, цифры казались очень знакомыми. Перешерстив свой уютный бложек, я нашёл, наконец, в чём дело, в посте "Испытываем новую команду S"

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

Обнаружил это дело, когда испытаывал новую команду, исправил - и ПОЛУЧИЛ РЕЗУЛЬТАТ МЕНЕЕ ТОЧНЫЙ! Это нормально: исходные данные были "модельные" - там у каждого пикселя матрицы была своя чувствительность, сгенерённая в соответствии с Photo Response Non Uniformity, да ещё и свет "проваливался между пикселями" (моделировалось наличие "мёртвых зон" на пикселе, которые нечувствительны к свету, это характерно для матриц "прямой засветки", когда поверх чувствительной области проходят всевозможные дорожки - столбцы и строки), да ещё и оцифровано на 12 бит, в общем все 33 несчастья. И поэтому ошибка в 2 метра была вполне ожидаема. Нам повезло ошибиться "в правильную сторону" и снизить эту ошибку до метра, но именно что ПОВЕЗЛО.

Так что всё в порядке.

Теперь нужно подумать, как снова получить изображение с камеры... У меня и сейчас есть возможность его записать в статическую память 1 МБ. Раньше у меня просто был здоровенный цикл, и я байт за байтом отправлял по UART на компьютер. Время от времени компьютер "сбивался" от такой прорвы, где-то что-то пропадало (надо понимать, преобразователь из USB в RS485 самый простецкий), но в целом получить картинку, убедиться, что пашет, было можно. Причём у меня UART был "8-битный", в смысле что он брал младшие 8 бит из 16-битной шины данных и отправлял только их. Это хорошо сочеталось с 8-битной статической памятью и 8-битным АЦП.

Теперь появилось дополнительное "звено", контроллер МКО - данные автоматически отправляются из определённых областей памяти (внутренней памяти ПЛИС, пока что хватало блока в 1024 байта), но у этой памяти адресация 16-битная, т.е по "словам данных".

По протоколу, чтобы получить изображение, контроллер шины начинает долго и настойчиво заказывать по 32 слова данных с подадреса 9. В ответ приходит заголовок массива 0x55AA, затем "номер посылки", затем 29 слов по 2 пикселя в каждом, и, наконец, CRC данной посылки.

Пока что контроллер МКО возьмёт заголовок, номер посылки и пиксели из внутренней памяти, CRC построит самостоятельно, передаст содержимое - И ВСЁ. Никакой возможности процессору "узнать", что посылка была передана и пора бы заготовить следующую - НЕТ.

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

Вспомним, как этот контроллер был устроен. Так он выглядит в виде отдельного модуля в схеме "верхнего уровня" (внизу слева):


Очень много отладочных выводов - они не подключены. Далее, есть подключение к приёмопередатчику RS485 (в дальнейшем он будет заменён на приёмопередатчик МКО, под это задел есть, "один вытащить - другой вставить") и куча выводов для подключения к внутренней памяти. С контроллера идёт шина адреса, запрос на чтение, запрос на запись, выход данных (чтобы записать их в память), вход данных (из памяти), подтверждение подлинности этих данных (задержка между запросом данных и их получением может немного меняться, т.к к той же памяти обращается и процессор, и у него приоритет, см. DMA для QuatCore).

И остаётся ещё 2 вывода:
- Mark - зафиксировать момент прихода данных. По-хорошему, это должна быть середина экспозиции кадра, но пока, "для отладки" - момент, когда алгоритм закончил вычисления,
- sync - сообщение процессору, что пришло командое слово "Синхронизация" (с СД). Если он в качестве входного устройства выбрал RTC и начал выполнять команду IN, он её не выполнит, пока эта командное слово не придёт. Это также "костыль" - в идеале мне хотелось бы, чтобы синхронизация шла на манер кадровой развёртки" - даже если нас "оставили в покое" - мы продолжаем измерения "в своём темпе". А затем, если нам начали слать эти слова - мы потихоньку подстраиваемся так, чтобы к запросу целевой информации она как раз "вот-вот" была готова. Если сильно заранее - значит мы сообщаем устаревшую информацию. Если не успеем - значит, не сообщим никакой (или сообщим ещё более устаревшую, т.е кадром ранее).

И "уровнем ниже":


Тут мы нарушили требования ГОСТ Р 52070-2003 и поставили адресную заглушку "программно" (по-хорошему надо было вывести 6 выводов на отдельный разъём, чтобы туда перемычки впаивать, задающие адрес от 0 до 30, и ещё один вход для проверки чётности), на первое время пущай.

Далее, тут сидят "часы реального времени" - они отсчитывают в тех единицах, которые были приняты в протоколе информационного обмена (цена младшего разряда 100/512 миллисекунд), а заодно выдают импульсы раз в 2,44 мкс, чтобы соблюсти паузы между запросом и ответом.

Стоит ЕЩЁ ОДИН КОСТЫЛЬ RXisDataForUART. В нормальном МКО мы можем отличить слова данных от командного/ответного слова просто из полярности синхроимпульса. Но я пока перебиваюсь RS485, где такого не предусмотрено, поэтому сделал попроще: первое слово после долгого перерыва - командное, а следующие за ним - слова данных.

Далее, у нас "приёмопередатчик", пока что RS485, потом и МКО будет (Mil-Std 1553), причём прямо в него встроен CRC, т.к проще всего его проверять в "сериализованном" виде, когда отправляется бит за битом!

И, разумеется, устройство контроля за всем этим, MilStdRemoteTerminalController. Он уже на Verilog. Как видно, на него уже приходит 2 16-битные шины: одна из памяти, вторая из "часов реального времени", и внутри стоит мультиплексор с защёлкой, чтобы выбрать что-то одно.

В принципе, не так уж сложно представить, что добавится третья шина, 8-битная, от статической памяти, и дополнительный провод управления ею, "прибавить единичку к адресу". Здесь же надо будет ввести счётчик количества переданных сообщений (и мультиплексировать и его в том числе на выход). Чего-то толсто... Хотя, с другой стороны, основной мультиплексор QuatCore с себя сбросит ношу, то на то и получится.

Если попробовать "ничего не менять" и разобраться чисто программно - сразу упрёмся в проблему 8/16 бит. Из статической памяти приходит 8-битное значение, и нужно их два подряд объединить в 16-битное и посадить уже в память. Сейчас это очень тяжёлая операция, как это ни прискорбно... Аппаратного сдвигателя у нас нет (на этой ПЛИС только "логика общего назначения", на ней Barrel Shifter это толсто, как по ЛЭ, так и по быстродействию - либо куча тактов задержки, либо частоту начнёт ограничивать), что-то похожее на него - это операция умножения, но при умножении выходит сдвиг вправо, а не влево! Сложение есть. "ADD Acc" в цикле 8 раз - вот и получится перенос из младшего байта в старший. Потом прибавить старший. Ну, в принципе, АЛУ может выйти на режим по 3 такта на сложение и работу совместно с модулем QuatCorePC, который в это время будет с циклом управляться, так что можно расчитывать на 24 такта для сдвига, и ещё 3 для добавления нового значения. Для ровного счёта 30 тактов, это 1,2 мкс - за это время как раз 1 бит будет передан, что по МКО, что по RS485 :) А мы успеем 1 слово (16 бит) заготовить :) Так что можно было бы и так... Ввести ещё одно прерывание - "запрос обновления картинки" - приходит оно, когда одно сообщение "изображение ВИПС" уже было отправлено. Тогда в аппаратном плане мы обойдёмся одним лишним компаратором (сравнить подадрес командного слова и в нужный момент выдать прерывание) и одним лишним проводом.

Или вообще не пытаться прямо сейчас выполнить требования протокола - а чисто "для себя" вывести эту картинку отдельным проводом. Сейчас я RS485 использую, а ведь на отладочной плате и USB есть, к которому подключена микросхемка cp2102 ("виртуальный COM-порт"), а с неё на ПЛИС идёт rxd и txd, работают прям в дуплексном режиме (с точки зрения ПЛИС). Отрядить это дело исключительно под картинку - и дело с концом. Одиночный символ на вход - и он начинает отправлять данные, вообще в обход ВСЕГО.

Даже и не знаю, что выбрать.


Poll #2114550 Получение изображения на компьютер

Как отправить изображение из внешней статической памяти на компьютер?

В обход процессора, на "аппаратной" логике контроллера МКО
0(0.0%)
"Программно", т.е процессор будет готовить очередное сообщение из 32 слов во внутренней памяти
1(33.3%)
Вообще через другой порт, на отладочной плате есть cp2102 USB-UART
2(66.7%)
Tags: ПЛИС, математика, программки, работа, странные девайсы
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 1 comment