nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

Алг. ближней дистанции, умножение матриц

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

И у нас уже была мааленькая процедура для умножения матрицы 3х4 на матрицу 4х2:

	;состояние регистров к этому моменту
	;Y = Points2D
	;X = Fx3
	;Z = Fx2
	;i=j=k=0
	;Inv неизвестен
	;C, Acc - неважно
	Compute4PointAffine	proc
				X		AffineMat
	;по сути, Z = X * Y, где все операнды - матрицы.
				k		1	;номер строки результата (и строки AffineMat)
		@@k_loop:	j		2	;номер столбца результата (и столбца Points2D)
		@@j_loop:	i		3	;номер столбца AffineMat и строки Points2D
				ZAcc		RoundZero	;обнулить до 1/2 мл. разр
		@@i_loop:	C		[X+4j+i]
				FMA		[Y+2i+k]
				iLOOP		@@i_loop
				Z		Matrix ;вообще AfTransf, но это промежуточная матрица, её занесём сюда (пока не наступило сопровождение, эти ячейки напрочь не нужны!)				
	;очередной результат готов...
				[Z+2j+k]	Acc
				jLOOP		@@j_loop
				kLOOP		@@k_loop
	;вот, какбе и всё...	
	Compute4PointAffine	endp


С массивом точек проблем не будет. Мы обращаемся к нему через [Y+2i+k], здесь i - номер точки, k - "номер координаты" (X:0, Y:1). Точек может быть сколько угодно, надо только перед началом цикла задать либо i=3 (как сейчас в коде) для мишени дальней дистанции, либо i=5 для ближней.

Вся проблема в обращении к матрице слева, которая будет либо 3х4, либо 3х6. Мы в своё время подумали, что сделать множитель "4" аппаратно проще, чем "3", поэтому сохранили матрицу "строка за строкой". И теперь с этим надо что-то делать...


Вообще, как это ни странно, адресация "4j" использовалась ровно в одной строке, в этой самой процедуре! Мы упоминали возможное её использование в алгоритме обнаружения точек, где вместо "однородных данных" (вроде векторов или матриц) у нас хранятся координаты, радиус пятна, его яркость и указатель на следующее пятно. Там нам нужна была простейшая адресация "[X], [X+1], [X+2], [X+3], [X+4]", и она реализовывалась, если постановить j=1, k=0, см. раз, два, три, четыре, пять.

Пока что нам не нужно было [X+4], поскольку мы сейчас вообще перестали яркость сохранять, но рано или поздно она всё-таки понадобится, для управления экспозицией! Нужно будет фиксировать яркость ПОЛЕЗНЫХ пятен и держать её чуть-чуть перед насыщением, чтобы и сигнал мощный, и информация не терялась. При этом паразитные блики вполне могут оказываться в насыщении, а значит, нельзя просто настроить экспозицию "по максимальной яркости" - в таком случае полезный сигнал может стать слишком тусклым и шумным.

Хотел было оставить систему команд в покое, "работает не лезь".

А вместо этого применить в очередной раз SP (Stack Pointer), у которого есть возможность инкремента и декремента. Сохраним матрицу в памяти в следующем виде (нумерация указывает смещение относительно базового адреса), и будем вычислять сначала второй столбец, снизу вверх:


(прошу прощения, нарисовал лишние 2 строки в правой матрице, эти две точки есть, но использовать их мы здесь не хотели)

Т.е по левой матрице идёт декремент, по правой матрице (собственно, наши 8 точек) прокручиваем один и тот же столбец 3 раза подряд.

Затем опять инициализируем SP - и делаем то же самое для первого столбца.

Но нам катастрофически не хватает регистров для такой работы! Если использовать декременты, то исходное положение SP будет определяться количеством точек: для мишени дальней дистанции мы должны будем присвоить SP = Fx4 (чтобы при первом же [--SP] мы взяли значение Fy3), а для ближней дистанции: SP = Fx6. Но делать-то мы это должны внутри цикла, значит где-то должны хранить этот адрес. Подошли бы [SP] или [SP+1], но поскольку мы только что перетащили указатель SP совсем на другое, то это страшно неудобно!

Так что всё-таки заменим 4j на 3j в системе команд! Достучаться до [X+4] в алгоритме обнаружения мы сможем, [X+3j+1], а больше эта четвёрка нигде и не была нужна!

Заглянем в модуль QuatCoreFirstIndexMux:
module QuatCoreFirstIndexMux (input [15:0] ijk, input [1:0] Base, input [1:0] adr, 
								output [7:0] Q);
								
wire [4:0] i = ijk[9:5];
wire [4:0] j = ijk[4:0];
wire [2:0] smj = j[2:0]; //for TreugNum
								
wire [3:0] TreugNum;
assign TreugNum[3] = smj[2];
assign TreugNum[2:0] = 	(smj == 3'd0)? 	3'd0 :
			(smj == 3'd1)? 	3'd1 :
			(smj == 3'd2)? 	3'd3 :
			(smj == 3'd3)? 	3'd6 :
			(smj == 3'd4)? 	3'd2 :
			(smj == 3'd5)? 	3'd7 :
					3'bxxx;
										
assign Q = 	(adr == 2'b00)? 8'b00000000 :		//0
		(adr == 2'b01)? {2'b0, i, 1'b0} : 	//2i
		(adr == 2'b10)? {2'b0, j, 1'b0} : 	//2j
		(~Base[0])?	{1'b0, j, 2'b0}	: 	//4j for X or Z
		Base[1]?	8'b11111111 :		//-1 for SP
				{4'b0, TreugNum};	//TreugNum for Y
endmodule


Реальное умножение на 3 здесь делать не хочется. Нам нужны эти утроенные значения лишь для j от 0 до 5. Выпишем их в бинарном виде:

 j        3j
000  ->  0000
001  ->  0011
010  ->  0110
011  ->  1001
100  ->  1100
101  ->  1111


Сразу же видно, что младший бит остаётся "как есть". Оно и ясно, нечётное число при умножении на 3 остаётся нечётным, чётное остаётся чётным.

Следующий бит получается как j[0]^j[1]: когда два младших разряда регистра j совпадают, там будет ноль, когда они разные - 1.

С предпоследним битом уже хуже: он зависит от всех трёх битов j, как и последний. Впрочем, хоть чуть-чуть упрощённые формулы можно придумать и для них. Получаем вот что:

//заменяем 4j на 3j, при j от 0 до 5, дальше похрен.

module QuatCoreFirstIndexMuxV2 (input [15:0] ijk, input [1:0] Base, input [1:0] adr, 
								output [7:0] Q);
								
wire [4:0] i = ijk[9:5];
wire [4:0] j = ijk[4:0];
wire [2:0] smj = j[2:0]; //for TreugNum
								
wire [3:0] TreugNum;
assign TreugNum[3] = smj[2];
assign TreugNum[2:0] = 	(smj == 3'd0)? 	3'd0 :
			(smj == 3'd1)? 	3'd1 :
			(smj == 3'd2)? 	3'd3 :
			(smj == 3'd3)? 	3'd6 :
			(smj == 3'd4)? 	3'd2 :
			(smj == 3'd5)? 	3'd7 :
					3'bxxx;
										
wire [3:0] j3;	//j*3
assign j3[0] = j[0];
assign j3[1] = j[0]^j[1];
assign j3[2] = j[2]|(j[1]&(~j[0]));
assign j3[3] = j[2]|(j[1]&j[0]);

										
										
assign Q = 	(adr == 2'b00)? 8'b00000000 :		//0
		(adr == 2'b01)? {2'b0, i, 1'b0} : 	//2i
		(adr == 2'b10)? {2'b0, j, 1'b0} : 	//2j
		(~Base[0])?	{4'b0, j3}	: 	//3j for X or Z (j=0..5)
		Base[1]?	8'b11111111 :		//-1 for SP
				{4'b0, TreugNum};	//TreugNum for Y
endmodule
										


Как ни странно, этот модуль как синтезировался в 20 ЛЭ, так и продолжает синтезироваться. Да, чуть усложнились младшие разряды, зато мы выкинули старшие.

Тут ещё есть что упрощать: можно вместо 8-битного выхода сделать 7-битный, или того меньше, если 2i и 2j также не должны иметь честные 6 бит (от 0 до 63). Но не сейчас. Вот будет у нас всё это дело в сборе - тогда и посмотрим, какая реальная разрядность нужна у всех регистров и их комбинаций.

Вообще, был ещё один вариант: оставить 4j, но просто хранить матрицы с "прорехами" в виде несуществующей 4-й строки. Потеряли бы аж 16 байт памяти "впустую". А может даже придумали бы, какие данные туда сунуть...

Конфиги компилятора тоже переделываем, везде заменяя "+4j" в мнемонике команд на "+3j". Тут всё понятно.

Ну и переписываем процедуру:
			Z		ShortRangeAffine	;нужно перед ComputeNPointAffine, чтобы она была универсальна, и для дальней, и для ближней дистанции
			[SP+1]		5			;количество точек (нумерация с нуля)
			
;состояние регистров к этому моменту
;X = Points2D
;Y = a11 = Matrix (временное хранилище), куда сунем матрицу аф преобразования
;Z = ShortRangeAffine либо LongRangeAffine (в зависимости от алгоритма)
;Inv=0, k=0
;i=4,j=6 (если это мишень ближней дистанции)
;но если удобнее, можем сделать i=1, j=5. 
;C, Acc - неважно
;[SP+1] = количество точек (нумерация с нуля)

ComputeNPointAffine	proc
;по сути, Y = Z * X, где все операнды - матрицы.
			k		1		;номер столбца результата (и столбца Points2D)
	@@k_loop:	i		2		;номер строки результата (и строки AffineMat)
	@@i_loop:	j		[SP+1]	;номер столбца AffineMat и строки Points2D (либо 5 для ближней дистанции, либо 3 для дальней)
			ZAcc		RoundZero	;обнулить до 1/2 мл. разр
	@@j_loop:	C		[Z+3j+i]
			FMA		[X+2j+k]
			jLOOP		@@j_loop
			[Y+2i+k]	Acc
			iLOOP		@@i_loop
			kLOOP		@@k_loop
;вот, какбе и всё...	
Compute4PointAffine	endp	


Запускаем компилятор (до сих пор не знаю точной разницы между компилятором и транслятором, проект когда-то назвал Translator, а в уютном бложике раз за разом называю компилятором), он грязно выругался:


Ах да, забыл в конце переправить название процедуры. Попробуем ещё разок:


Ага, RoundZero у нас определено в файле QuatCoreConsts.inc:

;константы для аргументов QuatCore
;можно было бы их в сам компилятор "зашить", но пущай так
.data ;костыль нашего компилятора - он ищет EQU только в сегменте данных

;устройства ввода-вывода. Выбор производится командой SIO
UART		EQU	0
LCD		EQU	1
ETH		EQU	2
SD		EQU	10
ADC		EQU	14

;для передачи изображения в 1-битном Ч/Б вместо 8 бит градаций серого
BIT_UART 	EQU 	16

;константы, которыми можно инициализировать аккумулятор, командой ZAcc
MinusThreeHalf	EQU	0
MinusOne	EQU	1
ThreeHalf	EQU	2
RoundZero	EQU	3


Надо было просто его добавить в файл ShortRangeAffine.asm, с которым мы сейчас возимся. Например, в самое начало файла:
%include "QuatCoreConsts.inc"


Попробуем ещё разок. Наконец-то!

[Отчёт]
Загружаем файл конфигурации транслятора
Файл конфигурации прочитан, готовы к работе
Обрабатываем файл ShortRangeAffine.asm
Включаем файл QuatCoreConsts.inc
Конфликт (Hazard) между командами [SP] и [Z+2j+k], файл ShortRangeAffine.asm, процедура Find2Points, строки:
		[SP]		0		;сравниваем с точкой i. Начинаем считать квадрат расстояния
@@k_loop:	DIV2		[Z+2j+k]	;это Fy[j+1], если k=1, или Fx[j+1], если k=0
Вставляем NOP

Конфликт (Hazard) между командами [SP] и [X+i], файл ShortRangeAffine.asm, процедура CheckUpsideDown, строки:
			[SP]		0
@@i_loop:		Acc		[X+i]		;Fy0 на первой итерации, Fx0 на второй
Вставляем NOP

Конфликт (Hazard) между командами [SP] и [X+2j+k], файл ShortRangeAffine.asm, процедура FindCentralPoint, строки:
			[SP]		0		;сумма квадратов
@@inner_cycle:	Acc		[X+2j+k]	;Fy[i] если k=1,  Fx[i] если k=0
Вставляем NOP

Пытаемся оптимизировать таблицу вызова процедур
FindCentralPoint = 0055 
SwapPoints       = 006C 

Бит 6 адреса
Всегда единица...
Бит 5 адреса
не повторяет предыдущих (сигнатура 1)
Сопоставление его биту SrcAddr[3] прошло успешно
Бит 4 адреса
не повторяет предыдущих (сигнатура 2)
Сопоставление его биту SrcAddr[2] прошло успешно
Бит 3 адреса
в точности повторяет бит 5...
Бит 2 адреса
Всегда единица...
Бит 1 адреса
Всегда ноль...
Бит 0 адреса
в точности повторяет бит 4...
2 входных бит оказались не сопоставленными битам адреса
Таблица непоср. значений

135   00FF SP Stack/i 7/j++ 0/ZACC RoundZero/NOP 0         
2     00FF Z Fx1/i 2                                       
198   FFFF j 6/ijk 0x00C6/ijk 0x00C6                       
0     FFFF [SP+1] 0/[SP] 0/[SP] 0/[SP] 0                   
33    007F k 1/jLOOP SortByProjection::@j_loop/k 1/k 1/k 1 
8     007F kLOOP Find2Points::@k_loop                      
18    007F JL Find2Points::@skip                           
5     FFFF iLOOP Find2Points::@i_loop/j 5/[SP+1] 5         
4     007F jLOOP Find2Points::@j_loop                      
1220  FFFF ijk 0x04C4/JGE CheckUpsideDown::@skip           
88    00FF Y a14                                           
41    007F [SP] SortByProjection::@loopEnd                 
28    00FF kLOOP SortByProjection::@Dif/Z ShortRangeAffine 
108   007F JGE SwapPoints                                  
34    007F iLOOP SortByProjection::@i_loop                 
82    00FF Y a11                                           
3     001F j 3                                             
39    FFFF ijk 0x0027                                      
54    007F iLOOP CheckUpsideDown::@i_loop                  
66    FFFF ijk 0x0042                                      
65    007F iLOOP CheckUpsideDown::@reverse                 
37    FFFF ijk 0x0025                                      
134   FFFF ijk 0x0086                                      
78    007F jLOOP ComputeNPointAffine::@j_loop              
76    007F iLOOP ComputeNPointAffine::@i_loop              
75    007F kLOOP ComputeNPointAffine::@k_loop              
84    007F JMP endless                                     
1221  FFFF ijk 0x04C5                                      
25933 FFFF C 25933                                         
6835  FFFF C 6835                                          
86    007F kLOOP FindCentralPoint::@k_loop                 
32767 FFFF [SP+1] 32767                                    
96    007F kLOOP FindCentralPoint::@inner_cycle            
106   007F JGE FindCentralPoint::@skip                     
93    007F jLOOP FindCentralPoint::@outer_cycle            
110   007F kLOOP SwapPoints::@swap                         

Компиляция завершена успешно

Ширина адреса сегмента кода (и регистра PC):           7   
Ширина адреса сегмента данных (и регистров X,Y,Z,SP):  8   
Ширина сумматора для относительных прыжков:            8   
Количество инициализированных слов данных:             137 
Количество инициализированных слов кода:               115 
Количество адресов процедур:                           2   

Адреса процедур:
FindCentralPoint = 0055(поле Src = B4) 
SwapPoints       = 006C(поле Src = B8) 

Используемые Immediate-значения:
0  (8 раз) 
1  (2 раз) 
2  (3 раз) 
3  (4 раз) 
4  (5 раз) 
5  (1 раз) 
6  (1 раз) 
7  (3 раз) 
8  (1 раз) 
9  (2 раз) 
10 (1 раз) 
11 (1 раз) 
12 (2 раз) 
13 (1 раз) 
14 (1 раз) 
15 (1 раз) 
16 (1 раз) 
17 (1 раз) 
18 (1 раз) 
19 (1 раз) 
20 (1 раз) 
21 (1 раз) 
22 (1 раз) 
23 (1 раз) 
24 (1 раз) 
25 (1 раз) 
26 (1 раз) 
27 (1 раз) 
28 (1 раз) 
29 (1 раз) 
30 (1 раз) 
31 (1 раз) 
32 (1 раз) 
33 (1 раз) 
34 (1 раз) 
35 (1 раз) 
(задействовано 36 из 128)

Используемые адреса Src:
Acc(80)                   9 раз 
C(83)                     1 раз 
j(A1)                     3 раз 
ijk(A4)                   1 раз 
CALL FindCentralPoint(B4) 2 раз 
CALL SwapPoints(B8)       9 раз 
[X+2i+1](C1)              1 раз 
[X+i](C4)                 1 раз 
[X+2j+i](C6)              1 раз 
[X+2i+k](C9)              5 раз 
[X+2j+k](CA)              2 раз 
[Y+1](D0)                 1 раз 
[Y+k](D8)                 2 раз 
[Y+i^j](DC)               1 раз 
Y(DD)                     2 раз 
[Z+2j+1](E2)              1 раз 
[Z+3j+i](E7)              1 раз 
[Z+2i+k](E9)              2 раз 
[Z+2j+k](EA)              3 раз 
[SP+1](F0)                3 раз 
[SP](FC)                  6 раз 
[--SP](FF)                1 раз 
(задействовано 22 из 128)

Используемые адреса Dest:
Acc(80)      2 раз  
ADD(82)      2 раз  
SUB(83)      5 раз  
ZACC(88)     1 раз  
NOP(89)      4 раз  
C(8A)        7 раз  
DIV2(8C)     2 раз  
DIV2S(8F)    2 раз  
MUL(90)      3 раз  
FMA(92)      3 раз  
FMS(93)      2 раз  
SQRD2(9C)    2 раз  
i(A0)        5 раз  
j(A1)        4 раз  
k(A2)        4 раз  
j++(A5)      1 раз  
ijk(A7)      10 раз 
iLOOP(A8)    5 раз  
jLOOP(A9)    4 раз  
kLOOP(AA)    6 раз  
JMP(B0)      3 раз  
JL(B8)       1 раз  
JGE(BC)      3 раз  
[X+2i+k](C9) 1 раз  
[Y+k](D8)    2 раз  
[Y+2i+k](D9) 1 раз  
Y(DD)        3 раз  
[Z+2j+k](EA) 1 раз  
Z(ED)        2 раз  
[SP+1](F0)   5 раз  
[SP++](F3)   2 раз  
[SP](FC)     16 раз 
SP(FD)       1 раз  
(задействовано 33 из 256)

Список используемых меток:
a11 =                            0052 (данные)  
a12 =                            0053 (данные)  
a13 =                            0055 (данные)  
a14 =                            0058 (данные)  
a15 =                            005C (данные)  
a16 =                            0061 (данные)  
a22 =                            0054 (данные)  
a23 =                            0056 (данные)  
a24 =                            0059 (данные)  
a25 =                            005D (данные)  
a26 =                            0062 (данные)  
a33 =                            0057 (данные)  
a34 =                            005A (данные)  
a35 =                            005E (данные)  
a36 =                            0063 (данные)  
a44 =                            005B (данные)  
a45 =                            005F (данные)  
a46 =                            0064 (данные)  
a55 =                            0060 (данные)  
a56 =                            0065 (данные)  
a66 =                            0066 (данные)  
ADC =                            000E (литерал) 
AfMat00 =                        0010 (данные)  
AfMat01 =                        0011 (данные)  
AfMat02 =                        0012 (данные)  
AfMat03 =                        0013 (данные)  
AfMat10 =                        0014 (данные)  
AfMat11 =                        0015 (данные)  
AfMat12 =                        0016 (данные)  
AfMat13 =                        0017 (данные)  
AfMat20 =                        0018 (данные)  
AfMat21 =                        0019 (данные)  
AfMat22 =                        001A (данные)  
AfMat23 =                        001B (данные)  
AfTransf =                       0058 (данные)  
BIT_UART =                       0010 (литерал) 
CheckUpsideDown =                0033 (код)     
CheckUpsideDown::@i_loop =       0036 (код)     
CheckUpsideDown::@reverse =      0041 (код)     
CheckUpsideDown::@skip =         0044 (код)     
ComputeNPointAffine =            004A (код)     
ComputeNPointAffine::@i_loop =   004C (код)     
ComputeNPointAffine::@j_loop =   004E (код)     
ComputeNPointAffine::@k_loop =   004B (код)     
DistA[0] =                       0067 (данные)  
DistA[1] =                       0068 (данные)  
DistA[10] =                      0071 (данные)  
DistA[11] =                      0072 (данные)  
DistA[12] =                      0073 (данные)  
DistA[13] =                      0074 (данные)  
DistA[14] =                      0075 (данные)  
DistA[15] =                      0076 (данные)  
DistA[16] =                      0077 (данные)  
DistA[17] =                      0078 (данные)  
DistA[18] =                      0079 (данные)  
DistA[19] =                      007A (данные)  
DistA[2] =                       0069 (данные)  
DistA[20] =                      007B (данные)  
DistA[21] =                      007C (данные)  
DistA[22] =                      007D (данные)  
DistA[23] =                      007E (данные)  
DistA[24] =                      007F (данные)  
DistA[25] =                      0080 (данные)  
DistA[26] =                      0081 (данные)  
DistA[27] =                      0082 (данные)  
DistA[28] =                      0083 (данные)  
DistA[29] =                      0084 (данные)  
DistA[3] =                       006A (данные)  
DistA[30] =                      0085 (данные)  
DistA[31] =                      0086 (данные)  
DistA[4] =                       006B (данные)  
DistA[5] =                       006C (данные)  
DistA[6] =                       006D (данные)  
DistA[7] =                       006E (данные)  
DistA[8] =                       006F (данные)  
DistA[9] =                       0070 (данные)  
endless =                        0054 (код)     
ETH =                            0002 (литерал) 
Find2Points =                    0001 (код)     
Find2Points::@i_loop =           0005 (код)     
Find2Points::@j_loop =           0004 (код)     
Find2Points::@k_loop =           0008 (код)     
Find2Points::@skip =             0012 (код)     
FindCentralPoint =               0055 (код)     
FindCentralPoint::@inner_cycle = 0060 (код)     
FindCentralPoint::@k_loop =      0056 (код)     
FindCentralPoint::@outer_cycle = 005D (код)     
FindCentralPoint::@skip =        006A (код)     
FindCentralPoints =              002B (код)     
Fx0 =                            0000 (данные)  
Fx1 =                            0002 (данные)  
Fx2 =                            0004 (данные)  
Fx3 =                            0006 (данные)  
Fx4 =                            0008 (данные)  
Fx5 =                            000A (данные)  
Fx6 =                            000C (данные)  
Fx7 =                            000E (данные)  
Fy0 =                            0001 (данные)  
Fy1 =                            0003 (данные)  
Fy2 =                            0005 (данные)  
Fy3 =                            0007 (данные)  
Fy4 =                            0009 (данные)  
Fy5 =                            000B (данные)  
Fy6 =                            000D (данные)  
Fy7 =                            000F (данные)  
LCD =                            0001 (литерал) 
LongRangeAffine =                0010 (данные)  
LongRangeRefPoints =             004E (данные)  
Matrix =                         0052 (данные)  
MBD1x =                          002E (данные)  
MBD1y =                          002F (данные)  
MBD1z =                          0030 (данные)  
MBD2x =                          0031 (данные)  
MBD2y =                          0032 (данные)  
MBD2z =                          0033 (данные)  
MBD3x =                          0034 (данные)  
MBD3y =                          0035 (данные)  
MBD3z =                          0036 (данные)  
MBD4x =                          0037 (данные)  
MBD4y =                          0038 (данные)  
MBD4z =                          0039 (данные)  
MBD5x =                          003A (данные)  
MBD5y =                          003B (данные)  
MBD5z =                          003C (данные)  
MBD6x =                          003D (данные)  
MBD6y =                          003E (данные)  
MBD6z =                          003F (данные)  
MBD7x =                          0040 (данные)  
MBD7y =                          0041 (данные)  
MBD7z =                          0042 (данные)  
MBD8x =                          0043 (данные)  
MBD8y =                          0044 (данные)  
MBD8z =                          0045 (данные)  
MBDx =                           004F (данные)  
MBDy =                           0050 (данные)  
MBDz =                           0051 (данные)  
MDD1x =                          0049 (данные)  
MDD1y =                          004A (данные)  
MDD1z =                          004B (данные)  
MDD2x =                          004C (данные)  
MDD2y =                          004D (данные)  
MDD2z =                          004E (данные)  
MDD3x =                          0046 (данные)  
MDD3y =                          0047 (данные)  
MDD3z =                          0048 (данные)  
MinusOne =                       0001 (литерал) 
MinusThreeHalf =                 0000 (литерал) 
Points2D =                       0000 (данные)  
RoundZero =                      0003 (литерал) 
Rx =                             0056 (данные)  
Ry =                             0057 (данные)  
SaMat00 =                        001C (данные)  
SaMat01 =                        001D (данные)  
SaMat02 =                        001E (данные)  
SaMat10 =                        001F (данные)  
SaMat11 =                        0020 (данные)  
SaMat12 =                        0021 (данные)  
SaMat20 =                        0022 (данные)  
SaMat21 =                        0023 (данные)  
SaMat22 =                        0024 (данные)  
SaMat30 =                        0025 (данные)  
SaMat31 =                        0026 (данные)  
SaMat32 =                        0027 (данные)  
SaMat40 =                        0028 (данные)  
SaMat41 =                        0029 (данные)  
SaMat42 =                        002A (данные)  
SaMat50 =                        002B (данные)  
SaMat51 =                        002C (данные)  
SaMat52 =                        002D (данные)  
SD =                             000A (литерал) 
ShortRangeAffine =               001C (данные)  
ShortRangeRefPoints =            004B (данные)  
SortByProjection =               001A (код)     
SortByProjection::@Dif =         001C (код)     
SortByProjection::@i_loop =      0022 (код)     
SortByProjection::@j_loop =      0021 (код)     
SortByProjection::@loopEnd =     0029 (код)     
Stack =                          0087 (данные)  
SwapPoints =                     006C (код)     
SwapPoints::@swap =              006E (код)     
ThreeHalf =                      0002 (литерал) 
Txx =                            0058 (данные)  
Txx' =                           0052 (данные)  
Txy =                            005A (данные)  
Txy' =                           0054 (данные)  
Tyx =                            0059 (данные)  
Tyx' =                           0053 (данные)  
Tyy =                            005B (данные)  
Tyy' =                           0055 (данные)  
UART =                           0000 (литерал) 




Но прежде чем проверить этот код, надо будет ещё обратить Y-координату у "обнаруженных точек", чтобы система координат была правой, и построить необходимую для работы матрицу 3х6...
Tags: ПЛИС, программки, работа, странные девайсы
Subscribe

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

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

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

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

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

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

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

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

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

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

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

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

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments