Масштабирование 16-разрядных данных АЦП в 16-разрядный результат. http://caxapa.ru/135412.html
;*************************************************************************
; Умножение знаковых и беззнаковых 16-битных данных (d) на знаковый или
; беззнаковый 16-битный коэффициент k с получением 16-битного результата
; (например, для масштабирования значений АЦП).
;
; Диапазон беззнаковых значений: 0x0000..0xFFFF в прямом коде
; Диапазон знаковых значений: 0x8000..0x7FFF в дополнительном коде
; Интерпретация этих значений как действительных чисел зависит от под-
; разумеваемого положения десятичных точек в каждом конкретном случае.
;
; Точность результатов без округления: [0,0..1,0) младшего разряда
; Точность результатов с округлением: [-0,5..0,5) младшего разряда
;
; Обсуждение в конфе AVR от 11.10.2008 - http://caxapa.ru/134681.html
;*************************************************************************
;-------------------------------------------------------------------------
; Scaling test code
;-------------------------------------------------------------------------
.equ d = 0x40C0
.equ k = 0x40C0
.include <m128def.inc>
ldi r16, high(RAMEND)
out SPH, r16
ldi r16, low(RAMEND)
out SPL, r16
scalings:
; unsigned*unsigned scaling test
; 1. Беззнаковые данные, беззнаковый коэффициент и беззнаковый результат.
ldi r20,low(d) ; unsigned
ldi r21,high(d)
ldi r22,low(k) ; unsigned
ldi r23,high(k)
rcall scale16uu ; unsigned r19r18
; signed*unsigned scaling test
; 2. Знаковые данные, беззнаковый коэффициент и знаковый результат.
ldi r20,low(d) ; signed
ldi r21,high(d)
ldi r22,low(k) ; unsigned
ldi r23,high(k)
rcall scale16su ; signed r19r18
; unsigned*signed scaling test
; 3. Беззнаковые данные, знаковый коэффициент и знаковый результат.
ldi r20,low(k) ; signed
ldi r21,high(k)
ldi r22,low(d) ; unsigned
ldi r23,high(d)
rcall scale16su ; signed r19r18
; signed*signed scaling test
; 4. Знаковые данные, знаковый коэффициент и знаковый результат.
ldi r20,low(d) ; signed
ldi r21,high(d)
ldi r22,low(k) ; signed
ldi r23,high(k)
rcall scale16ss ; signed r19r18
rjmp scalings
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
; Scaling routines
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
; Scales unsigned r21:r20 by unsigned r23:r22 value
;
; Any registers can be used as operands
;
; Result stored in r19:r18
; 17 program words, 20 clocks + ret
;
; 1. Беззнаковые данные, беззнаковый коэффициент и беззнаковый результат.
; r21:r20 данные АЦП в диапазоне 0x0000..0xFFFF | 0.16-> 0,0..1,0 | 0.16-> 0,0..1,0
; r23:r22 коэффициент в диапазоне 0x0000..0xFFFF | 0.16-> 0,0..1,0 | 16.0-> 0..65535
; r19:r18 результат в диапазоне 0x0000..0xFFFF | 0.16-> 0,0..1,0 | 16.0-> 0..65535
; r19:r18:r17 = r23:r22 * r21:r20
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) ; truncation
sbci r18, high(-128)
sbci r19, byte3(-128)
ret
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
; Scales signed r21:r20 by unsigned r23:r22 value
;
; Only r16..r23 registers can be used as operands
; due to the xMULSx command limitations
;
; Result stored in r19:r18
; 18 program words, 21 clocks + ret
;
; 2. Знаковые данные, беззнаковый коэффициент и знаковый результат.
; r21:r20 данные АЦП в диапазоне 0x8000..0x7FFF | 0.16-> -0,5..0,5 | 0.16-> -0,5..0,5
; r23:r22 коэффициент в диапазоне 0x0000..0xFFFF | 0.16-> 0,0..1,0 | 16.0-> 0..65535
; r19:r18 результат в диапазоне 0x8000..0x7FFF | 0.16-> -0,5..0,5 | 16.0-> -32767..32767
; 3. Беззнаковые данные, знаковый коэффициент и знаковый результат.
; r21:r20 коэффициент в диапазоне 0x8000..0x7FFF | 0.16-> -0,5..0,5 | 16.0-> -32767..32767
; r23:r22 данные АЦП в диапазоне 0x0000..0xFFFF | 0.16-> 0,0..1,0 | 0.16-> 0,0..1,0
; r19:r18 результат в диапазоне 0x8000..0x7FFF | 0.16-> -0,5..0,5 | 16.0-> -32767..32767
; r19:r18:r17 = r23:r22 * r21:r20
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) ; truncation
sbci r18, high(-128)
sbci r19, byte3(-128)
ret
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
; Scales signed r21:r20 by signed r23:r22 value
;
; Only r16..r23 registers can be used as operands
; due to the xMULSx command limitations
;
; Result stored in r19:r18
; 20 program words, 23 clocks + ret
;
; 4. Знаковые данные, знаковый коэффициент и знаковый результат.
; r21:r20 данные АЦП в диапазоне 0x8000..0x7FFF | 0.16-> -0,5..0,5 | 1.15-> -1,0..1,0
; r23:r22 коэффициент в диапазоне 0x8000..0x7FFF | 1.15-> -1,0..1,0 | 0.16-> -0,5..0,5
; r19:r18 результат в диапазоне 0x8000..0x7FFF | 0.16-> -0,5..0,5 | 0.16-> -0,5..0,5
;
; r21:r20 данные АЦП в диапазоне 0x8000..0x7FFF | 1.15-> -1,0..1,0 | 0.16-> -0,5..0,5
; r23:r22 коэффициент в диапазоне 0x8000..0x7FFF | 16.0-> -32767..32767 | 17.0-> -65535..65535
; r19:r18 результат в диапазоне 0x8000..0x7FFF | 16.0-> -32767..32767 | 16.0-> -32767..32767
; Для формата 17.0 в R21:R20 записывать только 16 старших разрядов коэффициента
; r19:r18:r17 = ( r23:r22 * r21:r20 ) << 1
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) ; truncation
sbci r18, high(-128)
sbci r19, byte3(-128)
ret
;-------------------------------------------------------------------------