September 17th, 2021

QuatCore

Тестируем atan1 на QuatCore

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

В программу внёс тестовый кусочек, где берётся 30 единичных векторов, распиханных по окружности с шагом 12° (от 0° и до 348°), и от каждого из них последовательно берётся atan1. Вектора просто засунул в неиспользуемую область памяти
[Spoiler (click to open)]
ORG	0x1A0

;тестовые данные для atan1
;набор из 30 векторов, через каждые 12 градусов, проверить работу на всей окружности
TestVec0x	Int16	32767
TestVec0y	Int16	0
TestVec1x	Int16	32052
TestVec1y	Int16	6813
TestVec2x	Int16	29935
TestVec2y	Int16 13328
TestVec3x	Int16	26510
TestVec3y	Int16	19261
TestVec4x	Int16	21926
TestVec4y	Int16	24351
TestVec5x	Int16	16384
TestVec5y	Int16	28378
TestVec6x	Int16	10126
TestVec6y	Int16	31164
TestVec7x	Int16	3425
TestVec7y	Int16	32588
TestVec8x	Int16	-3425
TestVec8y	Int16	32588
TestVec9x	Int16	-10126
TestVec9y	Int16	31164
TestVec10x	Int16	-16384
TestVec10y	Int16	28378
TestVec11x	Int16	-21926
TestVec11y	Int16	24351
TestVec12x	Int16	-26510
TestVec12y	Int16 19261
TestVec13x	Int16 -29935
TestVec13y	Int16 13328
TestVec14x	Int16	-32052
TestVec14y	Int16 6813
TestVec15x	Int16 -32768
TestVec15y	Int16 0
TestVec16x	Int16 -32052
TestVec16y	Int16 -6813
TestVec17x	Int16 -29935
TestVec17y	Int16 -13328
TestVec18x	Int16 -26510
TestVec18y	Int16 -19261
TestVec19x	Int16 -21926
TestVec19y	Int16 -24351
TestVec20x	Int16 -16384
TestVec20y	Int16 -28378
TestVec21x	Int16 -10126
TestVec21y	Int16 -31164
TestVec22x	Int16 -3425
TestVec22y	Int16 -32588
TestVec23x	Int16 3425
TestVec23y	Int16 -32588
TestVec24x	Int16 10126
TestVec24y	Int16 -31164
TestVec25x	Int16 16384
TestVec25y	Int16 -28378
TestVec26x	Int16 21926
TestVec26y	Int16 -24351
TestVec27x	Int16 26510
TestVec27y	Int16 -19261
TestVec28x	Int16 29935
TestVec28y	Int16 -13328
TestVec29x	Int16 32052
TestVec29y	Int16 -6813



и сразу после инициализации стека добавил вот этот код:
;здесь хотим проверить работу atan1
		Y		Matrix	;пока не используем, сойдёт
		k		29		;чтобы замучать 30 векторов
		X		TestVec29x
		Z		RT_PRF_NO	;отсюда начнут углы лежать (заголовок пожалеем)
@@k_loop:	CALL		atan1
		[Z+k]		[Y+1]	;перенесли угол куда хотели
		Acc		X
		SUB		2
		X		Acc
		kLOOP		@@k_loop


Я не питал иллюзий, что оно с первого же раза заработает правильно, поэтому не стал пока прошивать в ПЛИС, а запустил на симуляции. Очень удачно на осциллограмме мне как раз показали участок, где мы возвратились из процедуры atan1. И там я увидел, что регистр X указывает куда-то не туда.

Семён Семёныч: я забыл в atan1 всё-таки раскомментировать код, отвечающий за сохранение регистров в стек и восстановление их значений в конце процедуры, вот регистр X и "затирался".

Collapse )


Да, значения те же самые, что и в дампе, только надо не забывать менять местами старший и младший байт каждого слова.

РАБОТАЕТ!

Краткие итоги: 29 слов кода (58 байт) и 15 слов данных (30 байт). Точность: не хуже 2 единиц младшего разряда, преимущественно 0..1 единица. Время выполнения: около 21,6 мкс (540 тактов). Дополнительная функция: нахождение длины вектора с точностью не хуже 0,36%.

Да вообще-то, меня такое устраивает во всех отношениях :) Хотя есть некий спортивный интерес в получении полной точности, возможной в 16-битном представлении. В теории, алгоритм "atan на ЧЕТЫРЁХ умножениях" на это способен, ещё и уложится тактов в 100, но я не проверял ещё.

PS. Я неправильно ошибку считал: брал относительно исходных 12°, 24° и так далее, но ведь и представить их входными векторами точно я не мог. Сейчас это суммарная точность после двух операций. Возможно, если сравнивать с честно посчитанном atan(y/x) для двух целочисленных значений y,x, результат немного изменится в лучшую сторону. Ну и выборка пока маленькая.

PPS. Погоды сильно не делает. Там, где ошибка свыше 1,5 ЦМР, попробовал честно посчитать. Получил вместо 22 угл секунд ошибку в 21 угл секунду, ну да.