Оформил, перевел свои каменты на русский, убрал лишние советы, чтобы не сбивать людей с толку. Проверь перед тем, как я отправлю это в "Исходники"
;*******************************************************************************
; Умножение знаковых (sdat) и беззнаковых (dat) 16-битных данных на
; знаковый (scoef) или беззнаковый (coef) 16-битный коэффициент с получением
; 16-битного результата (например, для масштабирования значений АЦП).
;
; Диапазон беззнаковых целых значений dat: 0..65535 в прямом коде.
; Диапазон знаковых целых значений sdat: -32768..+32767 в дополнительном коде.
;
; Диапазон беззнаковых целых значений coef: 0..65535 в прямом коде, что
; соответствует диапазону 0..0.99998 в представлении fractional 0.16 (q16)
; Диапазон знаковых целых значений scoef: -32768..+32767 в дополнительном коде,
; что соответствует диапазону -1..+0.99998 в представлении fractional 1.15 (q15)
;
; Точность результатов без округления: [0,0..1,0) младшего разряда
; Точность результатов с округлением: [-0,5..0,5) младшего разряда
;
; Обсуждение в конфе AVR в октябре 2008г. - http://caxapa.ru/134681.html,
; http://caxapa.ru/135412.html, http://caxapa.ru/135949.html
;
; (c) leon_, MBedder
;*******************************************************************************
;-------------------------------------------------------------------------------
; Код для проверки подпрограмм масштабирования:
;
.equ dat = 65432 ; Беззнаковое тестовое число
.equ sdat = dat/2 ; Знаковое тестовое число
.equ coef = int(0.87654*65536) ; Беззнаковый тестовый коэффициент
.equ scoef = coef/2 ; Знаковый тестовый коэффициент
.cseg
scalings:
; Тест 1. Беззнаковые данные, беззнаковый коэффициент и беззнаковый результат:
ldi r20,low(dat ) ; Беззнаковые данные в r21r20,
ldi r21,high(dat)
ldi r22,low(coef) ; Беззнаковый коэффициент в r23r22,
ldi r23,high(coef)
rcall scale16uu ; Беззнаковый результат будет в r19r18.
; Тест 2. Знаковые данные, беззнаковый коэффициент и знаковый результат:
ldi r20,low(-sdat) ; Знаковые данные в r21r20,
ldi r21,high(-sdat)
ldi r22,low(coef) ; Беззнаковый коэффициент в r23r22,
ldi r23,high(coef)
rcall scale16su ; Знаковый результат будет в r19r18.
; Тест 3. Беззнаковые данные, знаковый коэффициент и знаковый результат:
ldi r20,low(-scoef) ; Знаковый коэффициент в r23r22,
ldi r21,high(-scoef)
ldi r22,low(dat) ; Безнаковые данные в r21r20,
ldi r23,high(dat)
rcall scale16su ; Знаковый результат будет в r19r18.
; Тест 4. Знаковые данные, знаковый коэффициент и знаковый результат:
ldi r20,low(-sdat) ; Знаковые данные в r21r20,
ldi r21,high(-sdat)
ldi r22,low(-scoef) ; Знаковый коэффициент в r23r22,
ldi r23,high(-scoef)
rcall scale16ss ; Знаковый результат будет в r19r18.
rjmp scalings
;
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; Собственно подпрограммы масштабирования:
;
;-------------------------------------------------------------------------------
; 1. Беззнаковые данные, беззнаковый коэффициент и беззнаковый результат.
;
; r21:r20 - данные в диапазоне 0..65535
; r23:r22 - коэффициент в диапазоне (0.0..0.99999)*65536
; r19:r18 - результат в диапазоне 0..65535
;
; Фактически выполнена операция r19:r18:r17 = r23:r22 * r21:r20, т.е.
; r17 может быть использован для получения более точного результата
;
; 17 слов кода, 20 тактов + ret
;
scale16uu:
clr r2
mul r23,r21
movw r18,r0
mul r22,r20
mov r17,r1
mul r23,r20
add r17,r0
adc r18,r1
adc r19,r2
mul r21,r22
add r17,r0
adc r18,r1
adc r19,r2
subi r17,low(-128) ; Округление
sbci r18,high(-128) ;
sbci r19,byte3(-128) ;
ret
;
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
; 2. Знаковые данные, беззнаковый коэффициент и знаковый результат:
;
; r21:r20 - данные в диапазоне -32768..+32767
; r23:r22 - коэффициент в диапазоне (0.00000..0.99999)*65536
;
; 3. Беззнаковые данные, знаковый коэффициент и знаковый результат:
;
; r21:r20 - коэффициент в диапазоне (-1.0000..+0.99999)*32768
; r23:r22 - данные в диапазоне 0..65535
; r19:r18 - результат в диапазоне -32768..+32767
;
; Фактически выполнена операция r19:r18:r17 = r23:r22 * r21:r20, т.е.
; r17 может быть использован для получения более точного результата
;
; 18 слов кода, 21 такт + ret
;
scale16su:
clr r2
mulsu r21,r23
movw r18,r0
mul r22,r20
mov r17,r1
mul r23,r20
add r17,r0
adc r18,r1
adc r19,r2
mulsu r21,r22
sbc r19,r2
add r17,r0
adc r18,r1
adc r19,r2
subi r17,low(-128) ; Округление
sbci r18,high(-128) ;
sbci r19,byte3(-128) ;
ret
;
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
; 4. Знаковые данные, знаковый коэффициент и знаковый результат.
;
; r21:r20 - данные в диапазоне -32768..+32767
; r23:r22 - коэффициент в диапазоне (-1.0000..+0.99999)*32768
; r19:r18 - результат в диапазоне -32768..+32767
;
; Фактически выполнена операция r19:r18:r17 = r23:r22 * r21:r20, т.е.
; r17 может быть использован для получения более точного результата
;
; 20 слов кода, 23 такта + ret
;
scale16ss:
clr r2
fmuls r23,r21
movw r18,r0
fmul r22,r20
adc r18,r2
mov r17,r0
fmulsu r23,r20
sbc r19,r2
add r17,r0
adc r18,r1
adc r19,r2
fmulsu r21,r22
sbc r19,r2
add r17,r0
adc r18,r1
adc r19,r2
subi r17,low(-128) ; Округление
sbci r18,high(-128) ;
sbci r19,byte3(-128) ;
ret
;
;-------------------------------------------------------------------------
-
- Спасибо. Все правильно. Избыточность действительно может сбить с толку. Надо только в начале указать, что такие варианты (диапазоны) представления данных и коэффициента являются наиболее практичными (применимыми, удобными) из множества допустимых. И еще, leon_(193 знак., 03.11.2008 11:52)
- Нет, представление К в виде +-0.5 * 2е16 сконфузит многих своей якобы ограниченностью - в большинстве случаев масштабирование используется как +-1*Data. Вводную лекцию по вариантам представления К и D тоже считаю излишней. Обновил --> - MBedder(03.11.2008 12:31, ссылка)
- коэффициент в диапазоне -1.0000..+0.99999 умножить на данные в диапазоне 0..65535 получаем результат в диапазоне -32768..+32767. Неужели по Вашему это нормальнее чем -0.5000..+0.49999 умножить на 0..65535 результат -32768..+32767? - leon_(03.11.2008 16:06)
- Да, поправил каменты - MBedder(03.11.2008 17:37)
- коэффициент в диапазоне -1.0000..+0.99999 умножить на данные в диапазоне 0..65535 получаем результат в диапазоне -32768..+32767. Неужели по Вашему это нормальнее чем -0.5000..+0.49999 умножить на 0..65535 результат -32768..+32767? - leon_(03.11.2008 16:06)
- Нет, представление К в виде +-0.5 * 2е16 сконфузит многих своей якобы ограниченностью - в большинстве случаев масштабирование используется как +-1*Data. Вводную лекцию по вариантам представления К и D тоже считаю излишней. Обновил --> - MBedder(03.11.2008 12:31, ссылка)
- Спасибо. Все правильно. Избыточность действительно может сбить с толку. Надо только в начале указать, что такие варианты (диапазоны) представления данных и коэффициента являются наиболее практичными (применимыми, удобными) из множества допустимых. И еще, leon_(193 знак., 03.11.2008 11:52)