?? decoder.asm
字號:
; decoder.asm
; Decoding a DTMF tone with Goertzel Algorithm
; specify module and ROM routine definition files
$include (maxq20ms10xf.inc)
$include (utilityrom.inc)
; MCNT control bits
MSIG equ 000h ; signed operation
MUNS equ 001h ; unsigned operation
MACC equ 002h ; accumulate
MNEG equ 004h ; negate result
M1OP equ 008h ; one operand mode
MSQU equ 010h ; sqr mode
MCLD equ 020h ; clear data
MMCW equ 040h ; dont update MC
; coefficient for the Goertzel algorithm
a1 equ 001A5h ; 1.65 * 2^8; a1 value for f=770Hz, Fs=8000Hz
D1 equ 00h ; address of D1
D2 equ D1+1 ; address of D2
result equ 00Fh ; pointer to accumulated power result
loop_cnt equ 205
org 000h
Main:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; System Initialization
; 1. initialize A[0] as the active accumulator
; 2. set all data pointer to word mode
; 3. set up DP[1] to point to input samples
; (input samples are pre-downloaded onto program memory.
; If samples are available elsewhere, e.g. from other
; peripherals, modify to point to relevant input source)
; 4. set up result pointer and loop counter
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
move APC, #00h ; set A[0] as the active accumulator
move DPC, #1Ch ; set all data pointer to word mode
move ACC, #x ; map code space to data space
add #8000h
move DP[1], ACC ; DP[1] -> input samples
move A[1], #result ; A[1] -> power results
move LC[0], #loop_cnt ; LC[0] -> number of samples
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Goertzel Algorithm Decoder Routine
; D0=X = ai*D1-D2
; D2=D1, D1=D0
;
; Input:
; DP[1] -> sample input
; LC[0] -> loop_cnt
; Output:
; DP[1] updated to point to next sample input
;
; Implementation:
; 1. initialize the MAC unit
; 2. get input sample
; 3. carry out the Goertzel Algorithm
; 4. calculate power information
; This step does not need to be perform on every sample
; It is done here for demonstration purpose
;
; Note: the input samples are keep to 8 bits value so that
; all MAC operation can be kept to 16x16 operation.
; both a1 and D2 are scaled accordingly to facilitate
; MAC operation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DECODER_LOOP:
move MCNT, #(MSIG+MACC+MCLD); initialized MAC unit
move MA, #100h ; MA = 2^8
move DP[1], DP[1] ; activate DP[1]
lcall UROM_moveDP1inc ; get input samples, DP[0]->next input
move MB, GR ; MB = x, MC=x
move DP[0], #D1 ; DP[0]-> D1
move MA, #a1 ; MA = a1
move MB, @DP[0]++ ; MB = D1, MC=x+a1*D1, DP[0]->D2
move MA, #0FF00h ; MA = -2^8
move MB, @DP[0]-- ; MB = D2, MC=x+a1*D1-D2, DP[0]->D1
move ACC, @DP[0]++ ; ACC = D1, DP[0]->D2
move @DP[0], ACC ; D2 = ACC = D1
move GR, MC0 ; retrieve D0 from MC
move GRL, MC1
move @--DP[0], GRS ; D1=D0, DP[0]->D1
call CALC_P ; Optional, can call this routine after
; the loop
djnz LC[0], DECODER_LOOP
nop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Calculate power of intender frequency in the sample
; D1^2+D2^2-a1*D1*D2
;
; Input:
; DP[0] -> D1
; A[1] -> address of last power value
; Output:
; A[1] updated to point to next sample input
;
; Implementation:
; 1. initialize the MAC unit
; 2. power calculation
; 3. store the resulting power value as a 4 byte value
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CALC_P: ; calculate power
move MCNT, #(MSIG+MCLD) ; initialized MAC unit
move MA, #a1 ; MA = a1
move MB, @DP[0]++ ; MB = D1, MC=a1*D1, DP[0]->D2
nop ; wait for MAC result
move GR, MC0 ; retrieve a1*D1 from MC
move GRL, MC1
move MCNT, #(MSIG+MNEG) ; negate MAC result
move MA, GRS ; MA = a1*D1
move MB, @DP[0]-- ; MB = D2, MC=-a1*D1*D2, DP[0]->D1
move MCNT, #(MSIG+MACC+MSQU); change to square and accumulate mode
move MA, @DP[0]++ ; MA = D1, MC = D1^2-a1*D1*D2, DP[0]->D2
move MA, @DP[0] ; MA = D2, MC = D1^2+D2^2-a1*D1*D2
move DP[0], A[1] ; DP[0] -> result
move GR, MC1 ; store power as 4 bytes value in big-endian format
move @++DP[0], GRS
move GR, MC0
move @++DP[0], GRS
move A[1], DP[0] ; update A[1] to last result pointer
ret
org 100h
; input sample - 770 Hz sine wave
x:
dw 000000h, 000039h, 00005eh, 000061h, 000042h, 00000ch, 00ffd1h, 00ffa7h, 00ff9dh, 00ffb6h,
dw 00ffe9h, 000024h, 000053h, 000064h, 000052h, 000023h, 00ffe7h, 00ffb4h, 00ff9dh, 00ffa8h,
dw 00ffd3h, 00000dh, 000043h, 000061h, 00005dh, 000038h, 00fffeh, 00ffc6h, 00ffa2h, 00ff9fh,
dw 00ffbfh, 00fff6h, 000030h, 000059h, 000063h, 000049h, 000016h, 00ffdah, 00ffach, 00ff9ch,
dw 00ffafh, 00ffdfh, 00001ah, 00004dh, 000064h, 000057h, 00002ch, 00fff1h, 00ffbch, 00ff9eh,
dw 00ffa4h, 00ffcah, 000003h, 00003bh, 00005fh, 000060h, 000040h, 000009h, 00ffceh, 00ffa6h,
dw 00ff9dh, 00ffb8h, 00ffech, 000027h, 000054h, 000064h, 000050h, 000020h, 00ffe4h, 00ffb2h,
dw 00ff9ch, 00ffaah, 00ffd5h, 000010h, 000046h, 000062h, 00005ch, 000035h, 00fffbh, 00ffc3h,
dw 00ffa1h, 00ffa0h, 00ffc1h, 00fff9h, 000033h, 00005bh, 000063h, 000047h, 000013h, 00ffd8h,
dw 00ffabh, 00ff9ch, 00ffb1h, 00ffe2h, 00001dh, 00004fh, 000064h, 000056h, 000029h, 00ffeeh,
dw 00ffb9h, 00ff9eh, 00ffa5h, 00ffcch, 000006h, 00003eh, 000060h, 00005fh, 00003dh, 000005h,
dw 00ffcch, 00ffa5h, 00ff9eh, 00ffbah, 00ffefh, 00002ah, 000056h, 000064h, 00004eh, 00001dh,
dw 00ffe1h, 00ffb1h, 00ff9ch, 00ffabh, 00ffd8h, 000014h, 000048h, 000063h, 00005ah, 000032h,
dw 00fff8h, 00ffc1h, 00ffa0h, 00ffa1h, 00ffc4h, 00fffch, 000036h, 00005ch, 000062h, 000045h,
dw 000010h, 00ffd5h, 00ffa9h, 00ff9ch, 00ffb3h, 00ffe5h, 000020h, 000050h, 000064h, 000054h,
dw 000026h, 00ffebh, 00ffb7h, 00ff9dh, 00ffa6h, 00ffcfh, 000009h, 000040h, 000060h, 00005eh,
dw 00003bh, 000002h, 00ffc9h, 00ffa3h, 00ff9eh, 00ffbch, 00fff2h, 00002dh, 000058h, 000063h,
dw 00004ch, 00001ah, 00ffdeh, 00ffafh, 00ff9ch, 00ffadh, 00ffdbh, 000017h, 00004ah, 000063h,
dw 000059h, 00002fh, 00fff5h, 00ffbeh, 00ff9fh, 00ffa2h, 00ffc6h, 00ffffh, 000038h, 00005dh,
dw 000061h, 000043h, 00000dh, 00ffd2h, 00ffa8h, 00ff9dh, 00ffb5h, 00ffe8h, 000023h, 000052h,
dw 000064h, 000052h, 000023h, 00ffe8h, 00ffb5h,
End
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -