beaver with chainsaw

Наконец-то доехал до Гремячего!

7-го января мы расчищали завалы перед Ярославским шоссе, 8-го поехал с бензопилой в сторону Гремячего, но застрял на втором переходе через Вондигу. Сегодня опробовал другой маршрут, "поверху".

И всё-таки доехал.



(синий - обычный маршрут от Дерюзинского поля, зелёный - сегодняшний, красный "отросток" - это я не туда вырулил, красный крест - отсутствующий мостик)

На обратном пути был свидетелем, как народ переходит реку по верёвке.

Collapse )

Следующий этап - "ввести в эксплуатацию" дачу - отопление и водоснабжение "по зимнему варианту".
QuatCore

QuatCore: символьный UART

Пора обзаводиться вводом-выводом, а то мы прошьём свой процессор в ПЛИС, и даже не сообразим, что он работает, поскольку он за 1 мс всё посчитает и уйдёт в бесконечный цикл, ни коим образом не обозначая своего состояния!

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

Но у меня бредовое желание начать всё же с передачи понятного человеку текста - слов и десятичных значений. Сначала по UART, а потом подключить символьный ЖК-экранчик 4х40, и выдавать все параметры на нём. Хочу сделать "демонстрационный макет", который будет работать от одной банки 18650, и выдавать параметры на экранчик - это больше убедит всех причастных, что все вычисления действительно ведутся внутри. Обычно приходится сдавать коробку, подключать к ней 27 вольт и огромный промышленный компьютер рабочего места, запускать на нём программу рабочего места, долго там чего-то запускать по инструкции из ТУ, и затем показывать ряд циферок в окошке, и долго и упорно доказывать, что это те самые циферки, которые нам и нужны, и даёт их, разумеется, та самая коробочка, а не сам промПК.

Пора сделать UART-передатчик, который правильно "встраивается" в QuatCore. Да и вообще, сделать его наконец-то по-нормальному!



Collapse )

Как ни странно, этот модуль синтезируется в такое же количество ЛЭ, в 24 ЛЭ при делителе частоты в 4 раза. Работает ли он в связке с QuatCore - скоро узнаем...
QuatCore

QuatCore: финал аффинного алг - дополнение

Проверим случай, когда берётся обратная величина от 16384, что должно дать 65536, но они не умещаются в 16 бит (это уже НОЛЬ, что не есть хорошо), а также подведём небольшие итоги.

Collapse )

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

Для той программы я подсчитал, что она исполнится за 4000 тактов. Теперь могу посмотреть на симуляторе, сколько реально требуется при текущей реализации - 1,15 мс на частоте 4 МГц, то есть 4600 тактов - не так уж плохо.

Timing Analysis показывает максимально допустимую тактовую частоту 6 МГц ровно, так что мы даже работаем с 1,5-кратным запасом. Все вычисления мы обязаны завершить за 200 мс, а завершили за 1,15 мс - это не обещанный ранее запас в 375 раз, но в 174 раза - тоже неплохо.

Таблица вызова процедур пока содержит всего 4 записи из доступных 16, это процедуры
AffineAlgorithm
NormSiCo
ShiftOrigin
SwapPoints


Всего в программе используется 30 непосредственных (Imm) значений из 128 возможных, самое частое - единица (22 раза), затем тройка (10 раз), на третьем месте нолик (9 раз).

Также используется 29 других адресов источников (SrcAddr), из 128 теоретически возможных, и 47 из 256 возможных адресов получателей (DestAddr).

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

Наконец, процессор QuatCore при данных настройках (шина адреса как в ROM, так и в RAM по 8 бит, доступны адреса i++/j++/k++, но недоступны ijk, ширина аккумулятора 32 бита) синтезируется в 448 ЛЭ, из доступных в моей нынешней ПЛИС 9984 ЛЭ, а в "целевой" - 2880 ЛЭ. Это без оптимизации таблицы адресов и отключения неиспользуемых в данной программе команд.

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

Poll #2098550 Чем дальше заняться

Чем заняться в первую очередь?

Реализовать алгоритм сопровождения
1(33.3%)
Написать модуль обработки видео
2(66.7%)
Кардинально поменять род деятельности
0(0.0%)
QuatCore

QuatCore: финал аффинного алгоритма!

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

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



Collapse )

За нами должок - посмотреть "особый случай", для которого мы знаем 3 слова...

И залить это безобразие на ПЛИС, не забыв сделать какой-никакой I/O...
QuatCore

Хорошая штука байпас!

Сейчас смотрю, как работает нахождение обратной величины по методу Ньютона в своём QuatCore, по формуле


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

Тогда я сказал, немного не подумавши, что 4 итераций хватит, чтобы получить 16 точных бит, если входное число в диапазоне от 16384 до 32768.

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

NoBypassIsBad.png

Проблема именно в накоплении ошибок промежуточных вычислений.

А вот если результат вычисления скобки поступает в следующую операцию целиком - ошибка сразу же уходит, 4 итераций действительно хватает, чтобы получить 16 точных бит!

Collapse )

UPD. И ещё внезапно дошло, что как таковая "двойка" нам и не нужна здесь, можно поставить НОЛЬ - и ничего в работе не изменится! Точнее, изменится флаг переполнения на противоположный, а больше ничего, т.к "разряд двоек" у нас в конечный результат всё равно не попадает!
QuatCore

О преобразовании к научному формату ("к плавающей точке")

Пусть у нас есть целое число, к примеру, в 6 десятичных разрядов, и мы хотим превратить его в научную запись с 2 значащими разрядами.

Скажем, число 35 превратится в 3,5×101, а число 123 - в 1,2×102.

Мы пытаемся формализовать такое преобразование. Записываем все 6 разрядов числа, даже если там нули:

000035

Изначально мы присваиваем порядок ("экспоненту") e=5. А далее, сдвигаем число влево по одному разряду, и попутно вычитаем по единичке из e, пока в старшем разряде не появится ненулевая цифра:

000350, e=4,
003500, e=3,
035000, e=2,
350000, e=1. Вот оно!

И остаётся округлить число до двух значащих разрядов, взять два старших разряда - и операция завершена.

Но есть здесь одна небольшая подлянка...

Collapse )
QuatCore

Проблемы с UFMS

По счастью, не с управлением федеральной миграционной службы, а с Unsigned Fused Multiply-Subtract. Сейчас наконец-то начал отлаживать часть программы, которая использует данную команду для нахождения обратной величины методом Ньютона - и напоролся - выдаёт полнейший бред.



Мы должны были посчитать выражение
2 - (37555/32768)(27979/32768)
и получить ответ: 33470/32768. Вместо этого у нас получилось 43044/32768 - ну вообще ни к селу ни к городу!

Чуть ранее мы считали выражение
2 - (32767/32768)(27979/32768)
и получили почти что правильный ответ: 37556, тогда как должны были получить 37557...

Collapse )
QuatCore

QuatCore: измерение масштаба

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

Осталось немного. Сейчас необходимо найти масштаб.

В этот раз задачу разобьём чуть по-другому - не только найдём масштаб, но и его самого отмасштабируем, чтобы был в диапазоне от 16384 до 32767 (от 0,5 до 1), попутно получив "экспоненту". Так мы хоть увидим, чему же равен результат, т.к в противном случае он "застревает" в аккумуляторе, причём часть его - в младших разрядах, которые мы вообще не видим с шины данных.

Так что сейчас мы наконец-то убедимся, что "байпас" (раз, два) работает, а ещё проверим работу флага переполнения и команд условного перехода, на него реагирующих. Ну и глянем, нет ли подводных камней в замене UDIV2 (беззнак. деления на 2, по сути лог. сдвига вправо на 1) на DIV2 (знак. деления на 2) и вычитание 32767.

Collapse )

Осталось совсем немного - найти обратную величину методом Ньютона и посчитать вектор параллельного переноса. Ну и алгоритм сопровождения целиком, разумеется. И модуль видеообработки на 1,2 ГБит/с.

В Радонеж с бензопилой

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


Первый опыт - скамеечка из спиленного бревна

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


Collapse )

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