Dijital filtreler analog filtrelere göre daha kararlı çalışırlar. Filtrenin karakteristliği sadece katsayılar değiştirilerek kolayca değiştirilebilir. Dijital filtreler işlemcilerde büyük işlem yükü getirirler. Bunun için dijital filtrelerin DSP üzerinden yapılması ya da hard bir şekilde FPGA ile yapılması performansı arttırabilir. Bu yazımda filtre işlemlerini yaparken Cortex-M4 işlemcisinin Fixed-Point DSP'sinden yararlanacağım. Dijital filtrelerin 2 farklı türü vardır, bunlardan biri FIR yani Finite Impulse Response diğeri IIR yani Infinite Impulse Response'dir. Her iki filtrenin de çalışma mantığı benzerdir. Belli aralıklarla alınan veriler önceden hesaplanmış katsayılar ile çarpılıp toplanarak çıkışa gönderilir. FIR filtrenin tasarımı aşağıdaki gibidir:
Katsayıları MATLAB programının "Filter Design & Analysis Tool" uygulasından hesaplayabiliriz.
Aşağıda Cortex-M4 işlemcisinin DSP komutları gösterilmiştir. Bu komutların hepsi 1 cycle'da gerçekleşir.
Bu komutları kullaranak aşağıdaki gibi bir kod yazılabilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
;Programda kullanılan adresler LDR R7, =ADC1 LDR R8, =DAC LDR R0, =Degerler LDR R1, =Katsayi Loop ;Örnekleme frekansını tutturmak için gerekirse bekle ;MOV R9, #5 Bekle ;SUBS R9, #1 ;BNE Bekle ;************************************************************* ;* * ;* ADC'den Alınan Verileri Katsayılar ile Çarpma Rutini * ;* * ;************************************************************* ;ADC değerlerinin tutulduğu pointer'dan 2 tane ;32 bit uzunluğundaki veriyi R2 ve R3'e yükle ;Daha sonra pointerîn değerini 8 arttır LDRD R2, R3, [R0], #8 ;Aynı şekilde Katsayilarin tutulduğu pointer'dan ;2 tane 32 bitlik veriyi R4 ve R5'e yükle ;Daha sonra pointerîn değerini 8 arttır LDRD R4, R5, [R1], #8 ;R2 nin üst 16 biti ile R4'ün üst 16 bitini çarp, bununla ;R2 nin alt 16 biti ile R4'ün alt 16 bitinin çarpımını topla ve ;bulunan değeri R6'ya yükle SMUAD R6, R2, R4 ;R3 nin üst 16 biti ile R5'ün üst 16 bitini çarp, bununla ;R3 nin alt 16 biti ile R5'ün alt 16 bitinin çarpımını topla ve ;bulunan değeri R6 ile tekrar toplayıp R6'ya yükle SMLAD R6, R3, R5, R6 ;Aynı işlemi 6 defa daha yap LDRD R2, R3, [R0], #8 LDRD R4, R5, [R1], #8 SMLAD R6, R2, R4, R6 SMLAD R6, R3, R5, R6 LDRD R2, R3, [R0], #8 LDRD R4, R5, [R1], #8 SMLAD R6, R2, R4, R6 SMLAD R6, R3, R5, R6 LDRD R2, R3, [R0], #8 LDRD R4, R5, [R1], #8 SMLAD R6, R2, R4, R6 SMLAD R6, R3, R5, R6 LDRD R2, R3, [R0], #8 LDRD R4, R5, [R1], #8 SMLAD R6, R2, R4, R6 SMLAD R6, R3, R5, R6 LDRD R2, R3, [R0], #8 LDRD R4, R5, [R1], #8 SMLAD R6, R2, R4, R6 SMLAD R6, R3, R5, R6 ;En son işlemde pointer'dan 48 değerinin çıkararak ;pointer'ı ilk haline döndür LDRD R2, R3, [R0], #-48 LDRD R4, R5, [R1], #-48 SMLAD R6, R2, R4, R6 SMLAD R6, R3, R5, R6 ;Filtreden çıkan değeri 16 bit sağa kaydır LSR R6, #16 ;DAC modülüne gönder STRH R6, [R8, #0x14] ;******************************************************* ;* * ;* ADC den Alınan Verilerin Kaydırılma Rutini * ;* * ;******************************************************* ;ADC değerlerinin tutulduğu pointer'dan 2 tane ;32 bit uzunluğundaki veriyi R2 ve R3'e yükle ;Daha sonra pointerîn değerini 8 arttır LDRD R2, R3, [R0] ;R6 registerinin alt 16 bitini R4 registerinin alt 16 bitine, ;R2 registerinin alt 16 bitini R4 registerinin üst 16 bitine yaz PKHBT R4, R6, R2, LSL #16 ;R3 registerinin alt 16 bitini R5 registerinin alt 16 bitine, ;R2 registerinin üst 16 bitini R5 registerinin üst 16 bitine yaz PKHBT R5, R3, R2 ;R5 registerinin alt 16 biti ile üst 16 bitinin yerlerini değiştir ROR R5, #16 ;R6 registerine, R3 registerinin alt 16 ve üst 16 bitlernin ;yerlerinin değiştirerek yaz MOV R6, R3, ROR #16 ;R4 ve R5 registerlerini ADC verilerinin bulunduğu pointer'a sakla ;Daha sonra pointer'ın değerini 8 arttır STRD R4, R5, [R0], #8 ;Aynı işlemleri 6 defa daha yap LDRD R2, R3, [R0] PKHBT R4, R6, R2, LSL #16 PKHBT R5, R3, R2 ROR R5, #16 MOV R6, R3, ROR #16 STRD R4, R5, [R0], #8 LDRD R2, R3, [R0] PKHBT R4, R6, R2, LSL #16 PKHBT R5, R3, R2 ROR R5, #16 MOV R6, R3, ROR #16 STRD R4, R5, [R0], #8 LDRD R2, R3, [R0] PKHBT R4, R6, R2, LSL #16 PKHBT R5, R3, R2 ROR R5, #16 MOV R6, R3, ROR #16 STRD R4, R5, [R0], #8 LDRD R2, R3, [R0] PKHBT R4, R6, R2, LSL #16 PKHBT R5, R3, R2 ROR R5, #16 MOV R6, R3, ROR #16 STRD R4, R5, [R0], #8 LDRD R2, R3, [R0] PKHBT R4, R6, R2, LSL #16 PKHBT R5, R3, R2 ROR R5, #16 MOV R6, R3, ROR #16 STRD R4, R5, [R0], #8 LDRD R2, R3, [R0] PKHBT R4, R6, R2, LSL #16 PKHBT R5, R3, R2 ROR R5, #16 MOV R6, R3, ROR #16 STRD R4, R5, [R0], #-48 ;ADC den yeni veri oku LDRH R2, [R7, #0x4C] ;Okunan değerden 2047 çıkar ;İşaretsiz sayı işaretli sayıya çevrildi SUB R2, #2047 STRH R2, [R0] ;Başa dön B Loop B . ENDP ALIGN ;ADC verileri AREA ADCDATA, DATA, READWRITE Degerler SPACE 256 ;Katsayılar AREA COEF, DATA, READONLY Katsayi DCW -995, 2550, 1175, 737, 588, 513, 442, 350, 230, \ 80, -96, -298, -518, -753, -998, -1242, -1482, -1704, \ -1908, -2087, -2229, -2336, -2401, 30345, -2401, -2336, -2229, \ -2087, -1908, -1704, -1482, -1242, -998, -753, -518, -298, \ -96, 80, 230, 350, 442, 513, 588, 737, 1175, \ 2550, -995 END |
Program bu hali ile 48 tap için 140 cycle'da bir döngüyü tamamlamaktadır. Programdaki bütün döngüler loop unrolling ile açılarak daha hızlı gerçekleşmesi sağlanmıştır. Loop unrolling ile ilgili daha önce yazdığım yazıya buradan ulaşabilirsiniz.
FIR filtrelerin tipine göre katsatılar arasında ilişkiler vardır:
- Tip-1 : Katsayı sayısı tek, katsayılar aralarında simetrik
- Tip-2 : Katsayı sayısı çift, katsayılar aralarında simetrik
- Tip-3 : Katsayı sayısı tek, katsayılar aralarında ters simetrik
- Tip-4 : Katsayı sayısı çift, katsayılar aralarında ters simetrik
Bu ilişkilere göre programda optimizasyonlar yapılabilir. Örneğin Tip-2 filtre için ilk ADC verisi ile son ADC verisi toplanıp katsayı ile tek seferde çarpılabilir.
Yüksek hızlarda katsayıların tutulduğu flash memory, ram'den daha yavaş kalacağından katsayılar programın başında flash'dan ram'e aktarılması programın daha hızlı çalışmasını sağlayacaktır.