Тема: Розробка фільтру із кінцевою імпульсною характеристикою блокового типу
КІХ– фільтри (фільтри з кінцевою імпульсною характеристикою) широко використовуються в різноманітних областях цифрової обробки сигналів, таких як аудіо- та відео- обробка, бездротовий зв’язок, медичні прилади та інше. Для багатьох практичних застосувань, таких як бездротовий зв’язок (БДКР – багатостанційний доступ з кодовим розділенням каналів / БДЧР – багатостанційний доступ з розділенням каналів у часі), потокове відео (MPEG/JPEG) та передача голосу по IP мережам (протокол Інтернету) (VoIP), цифрові вибірки вхідного сигналу, зазвичай, згруповані у кадри з часовою тривалістю від декількох мілісекунд до декількох сотень мілісекунд. Можливі два варіанти обчислення алгоритму цифрової фільтрації – блокова (обробляється одночасно декілька відліків вхідного сигналу) та послідовна (обробляється лише один наступний відлік вхідного сигналу) фільтрація. Зрозуміло, що більш ефективною є блокова обробка. Наведений нижче приклад являє собою програму на мові С обчислення КІХ– фільтру (fir.c), спроектованого для послідовної обробки сигналу. Вона легко може бути змінена на програму блокової обробки, тобто реалізацію блокового фільтру.
Приклад 1: Програма на мові С, яка реалізує КІХ-фільтр що послідовно обробляє М вхідних відліків сигналу.
Як правило, при розробці та відпрацюванні програмного забезпечення для ЦОС, використовуються різноманітні методи симуляції та емуляції. Вони також є дуже корисними при вивченні та аналізі алгоритмів ЦОС. Використовуючи програму генератора сигналу, можна створювати необхідні сигнали для застосування в процесі налагодження та аналізу алгоритму. Нижче наведено приклад програми генератора синусного сигналу (signal_gen.c), яка може бути використана для генерації вхідних експериментальних даних (файлу input5.dat) для перевірки роботи фільтру.
Приклад 2: програма генератора синусного сигналу для перевірки.
Завдання А.
Реалізація блокового КІХ-фільтру
Наведений вираз:
відображає алгоритм роботи КІХ-фільтра. Він включає до себе два різних процеси: (1) Перший виконує додавання результатів множення відліків вхідного сигналу на коефіцієнти фільтру; (2) Другий поновлює масив зберігання вхідного сигналу для включення до нього нової вибірки. Щоб виконати операцію фільтрації КІХ-фільтром з L коефіцієнтами (фільтр L-порядку), необхідно виконати L операцій множення та (L-1) операцій додавання. Крім того, потрібні додаткові операції для переміщення даних у пам’яті. Поновлення масиву вхідного сигналу вприкладі 1 потребує виконання операції зсуву у пам’яті. Операція зсуву (L-1) вибірок в масиві вхідного сигналу потребує додаткових командних циклів. Зазначені операції роблять задачу реалізації КІХ-фільтра для мікропроцесорів загального призначення достатньо складною, яка потребує великого об’єму обчислення.
Процесор TMS320C55x має наступні важливі особливості, які суттєво спрощують алгоритм реалізації КІХ-фільтру. Його система команд включає операції множення з накопиченням які виконуються за один цикл. Це означає, що процесор С55х може завершити обчислення для одного каскаду фільтру в кожному машинному циклі. В прикладі 1, поновлення масиву вхідного сигналу шляхом зміщення даних у пам’яті, потребує виконання декількох операцій по переміщенню даних. На практиці, можна використовувати оператори циклу. Фрагмент програми на мові асемблер, який використовує операції циклу для реалізації КІХ-фільтра, наведений вприкл.3. Щоб вилучити програмний контроль за виконанням циклу, в процесорі TMS320C55х використовується спеціальне апаратне забезпечення, що дозволяє реалізувати лічильники циклу. Воно дозволяє підтримувати до трьох рівней вкладеності циклів за допомогою регістрів BRC0, BRC1 та CSR.
Прикл.3 Фрагмент програми на мові асемблер, який використовує операції циклу для реалізації КІХ-фільтра.
В даному прикладі використовуються чотири допоміжні регістри-вказівники, AR0-AR3. AR0 вказує адресу розміщення масиву вхідного сигналу in[]. Масив сигналу x[], на адресу якого вказує регістр AR3, містить черговий відлік даних x(n) та (L-1) попередніх відліків. На адресу коефіцієнтів фільтру (масив h[]) вказує регістр AR1. На кожному кроці зовнішнього циклу нова вибірка розміщується в масиві сигналу, а внутрішній цикл повторює команди множення з накопиченням. Наприкінці, вихідні дані фільтру y(n) округлюються та зберігаються в масиві вихідних даних out[], на адресу якого вказує регістр AR2. Регістри AR1 та AR3 використовуються у режимі циклічної адресації. Значення в регістрі-вказівникі AR1 змінюється циклічно, таким чином, в кінці обчислення регістр знову буде вказувати на перший коефіцієнт фільтру.
В програмі на мові асемблер до лічильника повторень CSR завантажується значення L-3 (буде виконано L-2 ітерацій). Така кількість ітерацій визначена тому, що одна команда множення використовується до початку циклу, а ще одна команда множення з накопиченням та округленням результату – після закінчення циклу. Програма на мові асемблер (fir.asm), яка реалізує алгоритм роботи КІХ-фільтру, наведена нижче.
;
; fir.asm – Generic FIR filter
;
; prototype: unsigned int fir(int *, unsigned int, int *,
; unsigned int, int *, int *, unsigned int);
;
; Entry: arg0: AR0 – filter input buffer pointer
; arg1: T0 – number of samples in input buffer
; arg2: AR1 – FIR coefficients array pointer
; arg3: T1 – FIR filter order
; arg4: AR2 – output buffer pointer
; arg5: AR3 – signal buffer pointer
; arg6: AR4 – signal buffer index
;
; Return: T0 = signal buffer index
;
.def _fir
.sect “fir_code”
_fir
pshm ST1_55 ; Save ST1, ST2, and ST3
pshm ST2_55
pshm ST3_55
or #0x340,mmap(ST1_55); Set FRCT,SXMD,SATD
bset SMUL ; Set SMUL
mov mmap(AR1),BSA01 ; AR1=base address for coeff
mov mmap(T1),BK03 ; Set coefficient array size
mov mmap(AR3),BSA23 ; AR3=base address for signal buffer
or #0xA,mmap(ST2_55) ; AR1 & AR3 as circular pointers
mov #0,AR1 ; Start from zero offset
mov AR4,AR3 ; Start with offset=index
sub #1,T0 ; T0=M-1
mov T0,BRC0 ; Init outer loop for M times
sub #3,T1,T0 ; T0=L-3
mov T0,CSR ; Init inner loop L-2 times
|| rptblocal sample_loop-1 ; Start the outer loop
mov *AR0+,*AR3 ; Put the new sample to signal buffer
mpym *AR3+,*AR1+,AC0 ; Do the 1st operation
|| rpt CSR ; Start the inner loop
macm *AR3+,*AR1+,AC0
macmr *AR3,*AR1+,AC0 ; Do the last operation
mov hi(AC0),*AR2+ ; Save Q15 filtered value
sample_loop
popm ST3_55 ; Restore ST1, ST2, and ST3
popm ST2_55
popm ST1_55
mov AR3,T0 ; Return signal buffer index
|| ret
.end
Головна програма на мові С (exp5A.c) зчитує вхідні дані з файлу input5.dat, та викликає підпрограму fir() для виконання алгоритму низькочастотної фільтрації. Глобальна змінна indexзберігає індекс масиву вхідного сигналу для відстеження початкової позиції при кожному зчитуванні чергового блоку вибірки сигналу.
Компілятор процесора С55х підтримує декілька спеціальних директив. Найбільш часто використовуються з них дві – CODE_SECTION та DATA_SECTION, що призначені для розміщення даних та програм в спеціальних областях пам’яті процесора. Повний перелік підтриманих директив мови С наведено у настанові користувача по оптимізації роботи компілятора мови С для процесора TMS320C55x.
Нижче наведена головна програма (exp5A.c) на мові С.
/*
exp5a.c – Block FIR filter function experiment
using input data file
*/
#define M 128 /* Input sample size */
#define L 48 /* Number of FIR filter coefficients */
#define SN L /* Signal buffer size */
extern unsigned int fir(int *, unsigned int, int *, unsigned int, int *, int *, unsigned int);
/* Define DSP system memory map */
#pragma DATA_SECTION(LP_h, “fir_coef”);
#pragma DATA_SECTION(x, “fir_data”);
#pragma DATA_SECTION(index, “fir_data”);
#pragma DATA_SECTION(out, “output”);
#pragma DATA_SECTION(in, “input”);
#pragma DATA_SECTION(input, “input”);
#pragma CODE_SECTION(main, “fir_code”);
/* Input data */
#include “input5.dat”
/* Low-pass FIR filter coefficients */
int LP_h[L]={
-6,28,46,27,-35,-100,-93,26,191,240,52,-291,-497,-278,
337,888,773,-210,-1486,-1895,-442,2870,6793,9445,
9445,6793,2870,-442,-1895,-1486,-210,773,888,337,
-278,-497,-291,52,240,191,26,-93,-100,-35,27,46,28,-6};
int x[SN]; /* Signal buffer */
unsigned int index; /* Signal buffer index */
int out[M]; /* Output buffer */
int in[M]; /* Input buffer */
void main(void)
{
unsigned int i,j;
/* Initialize filter signal buffer */
for (i=0; i<SN;i++)
x[i]=0;
index = 0;
/* Processing samples using a block FIR filter */
j=0;
for (;;)
{
for (i=0; i<M; i++)
{
in[i]=input[j++]; /* Get a buffer of samples */
if (j == 160)
j=0;
}
index=fir(in,M,LP_h,L,out,x,index); /* FIR filter */
}
}
CODE_SECTION – це директива, що розміщує об’єктні коди програми до вказаного сегменту пам’яті програм. Синтаксис даної директиви задається так:
#pragma CODE_SECTION(func_name, “section_name”);
де func_name – це назва функції (підпрограми) на мові С, яка буде розміщена в сегменті пам’яті програм, який визначений ім’ям section_name. Командний файл компоновника використовує цю директиву для визначення та виділення спеціальних сегментів пам’яті програм, і розміщення там вказаної функції.
DATA_SECTION – це директива, що розміщує дані у відповідні, зазначені сегменти пам’яті даних. Синтаксис даної директиви задається так:
#pragma DATA_SECTION(var_name, “section_name”);
де var_name це ім’я змінної, яка знаходиться у програмі, і яка буде розміщена в сегменті пам’яті даних, який визначений ім’ям section_name. Командний файл компоновника використовує цю директиву для виділення сегменту пам’яті даних і розміщення там вказаної змінної.
Виконайте наступні кроки:
1. Створіть новий проект у середовищі CCS; назвіть його expА та збережіть його у відповідній директорії. Напишіть програму exp5А.с на основі наведеного вище коду. Скопіюйте командний файл лінкера exp5.cmd з директорії вхідних даних до завдання. Додайте до проекту файли exp5А.с, exp5.cmd, fir.asm. Підключить бібліотеку засобів динамічної підтримки rst55.lib (розташована у директорії C:\ti\c5500\cgtools\lib). Запустіть програму на компіляцію. Використайте згенерований файл input5.dat(розміщений в директорії вхідних даних до завдання), як вхідний сигнал для обробки.
2. Завантажте програму до процесора. Відкрийте чотири графічних вікна для перегляду вхідного сигналу, його спектру, вихідного сигналу та його спектру. Параметри налагодження графічних вікон наведені на рис.1.
Рис.1 Приклад настройки графічних вікон для виведення вхідного та вихідного сигналів.
3. Встановіть точку переривання в передостанньому рядку головної програми exp5А.с. Запустіть програму на виконання в режимі анімації. Проаналізуйте отриманий результат.