Category: компьютеры

Category was added automatically. Read all entries about "компьютеры".

QuatCore

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

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

Сейчас вот такое приближение "придумал". Напомню: у меня на входе два числа, x и y, причём x2+y2=1.
Допустим, что мы перешли к квадрантам I и IV, т.е x≥0, а потом ещё обеспечили условие x≥|y| (поменяв местами аргументы, если необходимо), т.е угол будет в диапазоне от -45 до +45 градусов. Тогда:



Максимальная ошибка составляет 0,041°, или 2,5 угловые минуты, и, возможно, ещё можно коэффициенты чуть оптимизировать.

Многовато вообще для моей задачи: мне ж этот угол ещё на 2 умножать (т.к в кватернионах угол был половинный), это будет 0,082°, при допустимой ошибке в 0,1°. Но может, кому пригодится такое приближение.

Под катом упоротые выкладки, которые привели к этому выражению... Ну как упоротые - вспоминали школьную математику, ну максимум 1-й курс института.

Collapse )

Наверное, эта тема меня так увлекла, потому что всегда интересно было узнать, а как же компьютер вообще считает сложные математические функции? Как в целом работает, складывает и умножает - уже разобрался, когда АЛУ ковырял, а вот эту математику обходили стороной как могли. В math.h не заглянешь, там одни заголовки, а функции уже откомпилированы под конкретную архитектуру. И в процессор не заглянешь (мой-исключение :), как там FPU вкалывает, а там же явно микрокода выше крыши! Кнут дальше арифметики не пошёл, во многих учебниках по программированию не мудрствуя лукаво говорят: ряд Тэйлора. А тут вроде как и "по делу" пришлось :)
QuatCore

Испытываем новую команду "S"

В прошлый раз мы ввели новую команду, "выдать флаг знака на шину данных", сокращённо "S". Подправили компилятор, запустили старую программу - по крайней мере ничего не поломали.

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

Если co>0, то


в противном случае



и затем кватернион нормируется. Длина ненормированного кватерниона будет от 0,707 (один на корень из двух) до 1, так что итераций для нормировки нужно не шибко много, хватит 4..5, чтобы выйти на полную точность, доступную в 16 битах.

Значение co у нас лежало в [Z], si в [Z+1], компоненты кватерниона мы хотим запихать в [X] и [X+1], для чего применяли такой вот упоротый код:

	;i=j=k=Inv=0				
	ABS	[Z+k]			
	DIV2	Acc
	ADD	16384
	;флаг S (sign) сейчас показывает знак co, что для нас очень полезно
	JGE	@@skip
	i	1	;выходит i=S
@@skip:	X	DA_Quat0
	[X+i]	Acc
	j	1
	DIV2	[Z+1]
	[X+i^j]	Acc	;по сути, Y+(~S)


Нужно его немножко упростить!

Collapse )



Уже лучше. Первый раз кватернион 32767 + 0i, т.е кватернион нулевого поворота. Второй раз -1+32767i, это практически поворот на 180 градусов, как и было в этом "сценарии".

Ещё показания дальности изменились после добавления одной итерации в NormSiCo, теперь "мантисса" 0x953A = 38202, а дальность 38202/32768 * 29-1 = 298,45 метров. Логично: у нас до этого нормировка до конца не доходила, поэтому масштаб выходил меньше и соответствовал большей дальности. Бывает и так: я координаты точек когда-то "сочинял", пытаясь учесть все проблемы, которые могут возникнуть с фотоприёмной матрицей: неравномерность чувствительности, "мёртвые зоны" и пр., может при правильных вычислениях и должно было получиться так...

В следующий раз громко думаем над знаками для FMPM, после чего тестируем арктангенс.
QuatCore

Аффинный алгоритм+информационный обмен, начало отладки

Каждый раз волнительно возвращаться к "железу" после долгого перерыва. У меня оно ещё и от "повербанки" работало, которая мне прям очень понадобилась на прошлой неделе, поэтому её оттуда вытаскивал, а сегодня припаивал на место. Ну ничего, признаки жизни подало - экранчик засветился, выдал там "ЛОИ ВИПС" ещё по старой прошивке, нормально.

Потом традиционно квартус "потерял" USB Blaster, а когда я его выткнул и заново воткнул - намертво завис. Ну это нормальная история, квартус штука глючная, к сожалению.

Наконец, "залил" новую прошивку, не во Flash-конфигуратор, просто в саму ПЛИС, т.е до отключения питания. Попробовал отправить что-то осмысленное:



И да, что-то осмысленное получил в ответ!

Collapse )

Очень неплохо! Как будто бы информационный обмен работает правильно, память они делят между собой как надо. Дальность находит правильно, метку времени вставляет, правда, в синхронизации мог ещё накосячить немного. Кватернион до конца не отнормировался, и смещения криво посчитались. Пока что думаю, что с программой накосячил, когда память переразмечал, но первое впечатление бывает ошибочным.

Завтра (в смысле, сегодня, после сна) продолжим...
QuatCore

Синхронизация QuatCore с компьютером

Вообще, рано или поздно я хочу получить нечто, напоминающее работу синхронизации в старых добрых телевизорах: пока нет внешнего сигнала, оно уже "живёт своей жизнью", на чуть отличающейся частоте, поскольку совсем не работать нельзя. Но когда начнут идти запросы на получение целевой информации, то постараемся выйти на такой режим, чтобы новый кадр был экспонирован и обработан аккурат перед следующим запросом, чтобы свести задержку к минимуму, ведь "борт" интересует самая свежая информация, где мы находимся СЕЙЧАС, а не 100 мс назад!

Как именно это сделать - ещё предстоит подумать, там фотоприёмная матрица 1205ХВ014 "подложила свинью" - в ней не предусмотрена "внешняя синхронизация", считается "мы её включили" - и она начала фигачить кадр за кадром без перерывов. Как наиболее грамотно её всё-таки "прижать к ногтю" - надо будет и с разработчиками обсудить, и самим опробовать. Можно, к примеру, переставать на неё подавать тактовую частоту, дескать "один кадр она отдала" - теперь пущай время для неё замрёт, потом в нужный момент возобновим подачу, этот кадр выйдет "запоротым", зато следующий будет нормальным, и как раз в нужный момент :) А можно "нажать Reset", быстренько перенастроить - и пущай снова работает. Это, наверное, более мягко, и чуть проще, и надёжнее в каком-то плане.

А пока, чтобы упростить отладку, сделаем более грязно - без внешних сигналов мы просто будем останавливаться, и запускать работу только по приходу команды "Синхронизация (с СД)". Программа написана, теперь нужно переделать ввод-вывод, выкинуть из него уже ненужный UART, а вместо него "подсоединиться" к протокольному контроллеру и часам реального времени...

Вот старая "схема":


Collapse )

Этот обновлённый проект синтезируется в 1730 ЛЭ (1702 ЛЭ перед Place&Route, а в ПЛИС, куда я бы хотел влезть, 2800 ЛЭ), тогда как перед ковыряниями синтезировался в 1733. Похоже на правду: лишний UART мы выкинули, но RTC в кои-то веки подключили, раньше-то при "заземлённом" входе Mark квартус удалял почти всё содержимое модуля, т.к результат его работы никуда не шёл. Вот примерно и вышло столько же.

Предельная частота: 26,95 МГц, тогда как мне достаточно 25 МГц, устраивает.

Что ж, всё готово для проверки работы процессора в связке с информационным обменом! Можно начать делать ставки, как скоро оно заработает. Думаю, как только заработает - напишу заявление на отпуск. Будем считать, что для отладки этого безобразия ещё и в комплекте с обработкой изображения нужно ещё 2 недели. Успею до отпуска запустить - будет шикарно. Не успею - виной тому недостаток отдыха, чего-то производительность труда снизилась, я последний раз был в отпуске в августе 2019 года. А значит, всё равно надо отдохнуть!
QuatCore

Аффинный алгоритм + информационный обмен, код

Память для этого монстрика мы разметили. Теперь ещё код подправить. Ранее у нас вообще никакого ввода-вывода для этого алгоритма не предусматривалось: программа стартует с нулевого адреса, обрабатывает заранее лежащие в памяти данные - и уходит в бесконечный цикл. Да и выбор, какой из алгоритмов использовать, для ближней дистанции или для дальней, мы делали сами, "комментируя" один прыжок. А надо худо-бедно заставить его работать самостоятельно.

И конечно, на таких более простых вещах QuatCore начинает жутко "тупить", в смысле что требовать кучу кода на простейшие операции. У нас же до сих пор нет флага нуля, обходились без него как-то! И соответственно, прыжков JE/JNE тоже нет, только JL и JGE, работающие по одному лишь знаку...

Collapse )

В итоге, программа занимает 284 слова кода (658 байт), т.е подрос на 30 слов. Нормально.

Пока что получаем ширину адресных шин по 9 бит, что ОЗУ, что ПЗУ. Соответственно, выделяем 1024 байта на ОЗУ и ещё 1024 байта на ПЗУ. Если я надеюсь уместиться в 5576ХС6Т, то 40% памяти уже занял, остаётся не так уж много.

Квартусовский проект вполне себе синтезируется, давая 1733 ЛЭ (в 5576ХС6Т имеется 2800 ЛЭ) и предельную частоту 27 МГц, нормально.

Но надо ещё I/O доковырять, после чего можно будет опробовать всё это безобразие в работе. Это уже в понедельник.
QuatCore

Аффинный алгоритм + информационный обмен

Возвращаемся к нашим баранам, к макету видеоизмерителя параметров сближения.

В нём готов и сколько-нибудь отлажен модуль информационного обмена, работающий автономно, без помощи процессора. И также готов модуль DMA (Direct Memory Access), позволяющий и процессору, и модулю информационного обмена обращаться к одной и той же оперативной памяти, но пока не отлажен.

Хочется попробовать всё это запустить "с нахрапу", но для этого надо программу подправить. Возьму пока "аффинный алгоритм", который у меня влез в "загрузочный сектор" (512 байт), но надо всю память перераспределить, в соответствии с этой табличкой:



Collapse )

На удивление долго память размечал. Вроде бы должен был "на автомате" практически сделать, но всё сомнения одолевали. Маленький милый поросёнок как-то внезапно превратился в ОГРОМНОГО КАБАНА! Мне по душе задачки поменьше, где можно как-то хитро извернуться и красиво решить, где всё очерчено хорошо. Но что делать, когда всё это соединяешь вместе, хочешь-не хочешь, получится толсто.

Теперь ещё есть желание переделать вход IN с UART, чтобы это не UART был как таковой, а "отмашка" от протокольного контроллера, сигнал к началу работы. OUT вообще "выкинуть" - и попробовать всё это запустить на железе, вдруг прям возьмёт и заработает? Это будет очень подозрительно...
QuatCore

DMA для QuatCore

Вот фрагмент схемы нашего "процессорного ядра" QuatCore:


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

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

Сейчас адрес используется ровно один. Кроме него, на оперативную память поступают 16 бит для записи, напрямую из шины данных, сигнал WREN (WRite ENable), а выход отправляется в модуль QuatCoreMem, где стоит мультиплексор, срабатывающий на "квадратные скобки" в мнемонике команды. Если они стоят - значит нам нужно значение из памяти, коммутируем его. Если нет - значение одного из регистров (X,Y,Z,SP), выдадим его.

Теперь бы как-нибудь к этой же памяти подключить "провода" D,Q, MemWrReq, MemRdReq и MemReady из протокольного контроллера МКО, желательно малой кровью... Обеспечить ему пресловутый Прямой Доступ к Памяти, или Direct Memory Access (DMA)...

Collapse )

Схема "верхнего уровня":


Барабанная дробь... Синтезируется в 1704 ЛЭ (перед фиттером), 1732 ЛЭ (после фиттера). Timing Analyzer: все требования выполнены, предельная частота 26,04 МГц!

Как-то слишком просто... Я ожидал, что будет эдак 20 МГц, и ещё неделю-другую надо будет "конвейер перебирать", чтобы вернуться к родным 25 МГц. Какая-то жуткая подлянка затаилась и ждёт своего часу.

Ну ладно, с завтрашнего дня начинаю отладку. Разрозненные части, наконец-то, собираются в целое.
QuatCore

"МКО через UART" в железе - 2

Продолжим проверять этот модулёк.


Collapse )

Выглядит неплохо! Есть, что улучшить:
- пусть и на индивидуальную команду "Синхронизация (с СД)" отвечает правильно, подтверждая, что команда пришла,
- если "пообещать" длинное сообщение (например, 32 слова), но не передать его целиком - контроллер будет до посинения ждать, пока нужное число слов данных будет передано, здесь никакого таймаута пока не предусмотрено. Когда "ручками" с ним общаешься - неприятно, что-то немного не то вбил - и вдруг ни ответа ни привета, и поди разберись, что с ним. На деле, не так уж это и страшно, пошлёшь запрос повторно, он "доберёт" сколько надо слов, уйдёт в sIdle по несовпадению CRC, и дело с концом. Но вообще с таймаутом правильнее, ГОСТ предписывает проверять временнЫе параметры и при отступлении от норм тихо ругаться.
- у меня были предусмотрены команды "дамп памяти" и "передать изображение", там маленькими кусочками передаётся содержимое памяти, "внутренней" и "внешней" соответственно. Можно было бы это дело на контроллер "взвалить", чтоб делал без участия процессора. Но пока было лень...

А сейчас, пожалуй, надо взяться за DMA.
QuatCore

"МКО через UART" в железе

Долго мучали эту штуковину на симуляции, пора уже в макет это прошить и посмотреть, как оно себя поведёт.

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

Окинем прощальным взором львиную долю "схемы" TopLevel:


Collapse )



Что-то есть. Первое сообщение "начинаем работу" - это от старой прошивки. При подаче питания срабатывает она, потом я по JTAG "запихиваю" в ПЛИС текущий проект. Это показывает, что по крайней мере "железо" рабочее.

Далее даю командное слово: адрес 6, подадрес 110002, передача ОУ-КШ, передать одно слово данных. Байты переставлены местами, потому как у меня приёмник и передатчик передают по 16 бит за раз, от младшего бита к старшему, а на компьютере передаётся по байту, от младшего бита к старшему, из-за чего "endian" меняется.

В ответ получаю ответное слово 0x3000 (адрес 6, все флажки сброшены, "всё в порядке") и одно слово данных: 0000. Да: по нашей логике последнее слово это всегда CRC, даже если оно по совместительству первое :) Вот это оно и есть, CRC от пустого сообщения!

Потом посылаю командные слова на "чужой" адрес 0, и никакого ответа не получаю. Всё верно.

В следующий раз заказал по тому же адресу и подадресу ("телеметрия") 2 слова данных - и получил заголовок массива телеметрии, 0xFF00, а затем CRC от него. Тот же CRC можно получить на crccalc.com, если ввести 00FF, и в строке CRC16/KERMIT в результате 0x0F78 переставить местами байты.

Потом ещё попробовал 3 слова данных, 4, 5, 6, 7. Результат: ответное слово, за ним заголовок массива, за ним сплошные нули (ну да, здесь я в память никаких "интересных" значений не клал), и CRC. Во всех случаях корректный.

И ещё "заказал" 0 слов данных, только этот ноль в МКО (ГОСТ Р 52070-2003, Mil-Std 1553) интерпретируется как 32 слова, что нужно было также прописать в коде. Что ж, эта часть также работает, выдаётся ответное слово и ещё 32 слова данных, последнее из которых: CRC.

Продолжение следует...
QuatCore

"Ошибка на единицу" при передаче CRC

В прошлый раз обнаружили нехорошую вещь: при передаче данных от нашего устройства, CRC начинает работать одним словом раньше, чем надо, и результат своей работы отсылает одним словом раньше.

Пора уже это исправить, чего-то задолбался я немного.

Collapse )
Действительно обошлись "малой кровью", не добавив ни одного ЛЭ.

Вот, кажется, и всё, протокол информационного обмена исполнен в полном объёме, на "жёсткой логике", без обращения к процессору.

Осталось всё это "в железе" посмотреть, заодно написав "программу рабочего места". Потом, если всё нормально, написать примитивный DMA. Дальше ожидаю раунд борьбы с фиттером, который может завалить трассировку всего проекта целиком, и второй раунд, когда в кои-то веки придётся все части программы свести в единое целое, так что и ROM и RAM подрастут, и ширина адресных шин вместе с ними.

Тяжело идёт, и уже как-то "через силу". Кажется, что всё творческое уже позади, а сейчас надо просто стиснуть зубы и довести хреновину до кондиции...