Форум РадиоКот https://radiokot.ru/forum/ |
|
проблема с алгоритмом БПФ. https://radiokot.ru/forum/viewtopic.php?f=22&t=63331 |
Страница 1 из 1 |
Автор: | Golosov_SA [ Чт янв 26, 2012 22:06:52 ] |
Заголовок сообщения: | проблема с алгоритмом БПФ. |
Изучаю БПФ, набросал код вычисления. Камень - ATMega16 частота - 16МГц Код: ; 3. для частоты 300 Гц кол-во выборок: 38400 / 300 = 128 ; используемые регистры ;.def mulres_lo = R0 ;.def mulres_hi = R1 ;.def Lm2 = R15 ;.def Lm1 = R16 ;.def Lm0 = R17 ;.def Re2 = R18 ;.def Re1 = R19 ;.def Re0 = R20 ;.def adcv = R21 ;.def sin = R22 ;.def cos = R23 ;.def i_lo = R24 ;.def i_hi = R25 ;.def sqr_lo = R16 ;.def sqr_hi = R17 ; возвращаемый результат ; .def retval = R20 furie_func_300Hz: clr Re2 ; Re = 0 (1 т) clr Re1 ; (1 т) clr Re0 ; (1 т) clr Lm2 ; Lm = 0 (1 т) clr Lm1 ; (1 т) clr Lm0 ; (1 т) ldi i_lo, 3 ; (1 т) ldi R26, LOW(adc_buf) ; x = adc_buf; (1 т) ldi R27, HIGH(adc_buf) ; (1 т) furie_func_300Hz_loop_i_lo: ; brpl - переход по положит. зн. (N == 0) ldi R30, LOW(sin_cos_128) ; z = cos128 (1 т) ldi R31, HIGH(sin_cos_128) ; (1 т) ldi i_hi, 127 ; (1 т) furie_func_300Hz_loop_i_hi: ld adcv, X+ ; adcv = *x++; (2 т) lpm sin, Z+ ; sin = *z++; (3 т) lpm cos, Z+ ; cos = *z++; (3 т) muls adcv, sin ; mulres = adcv * sin (2 т) ; здесь надо приобразовать 2х байтный результат умножения в 3х байтный с учетом знака ; знак в старшем байте (если он есть), проверяем clr mulres_3 ; в R2 - 3й байт результата умножения (1 т) tst mulres_hi ; если число положительное, то пропускаем (1 т) brpl furie_func_300Hz_loop_negative_test_1_skip ; (2 т) ; иначе нам надо изменить 3й байт результата умножения, ; записав в него 0xFF ser mulres_3 ; (1 т) furie_func_300Hz_loop_negative_test_1_skip: ; теперь просто складываем 2 24х битных числа add Lm0, mulres_lo ; Lm += mulres (1 т) adc Lm1, mulres_hi ; (1 т) adc Lm2, mulres_3 ; (1 т) muls adcv, cos ; mulres = adcv * cos (2 т) ; здесь надо приобразовать 2х байтный результат умножения в 3х байтный с учетом знака ; знак в старшем байте (если он есть), проверяем clr mulres_3 ; в R2 - 3й байт результата умножения (1 т) tst mulres_hi ; если число положительное, то пропускаем (1 т) brpl furie_func_300Hz_loop_negative_test_2_skip ; (2 т) ; иначе нам надо изменить 3й байт результата умножения, ; записав в него 0xFF ser mulres_3 ; (1 т) furie_func_300Hz_loop_negative_test_2_skip: ; теперь просто складываем 2 24х битных числа add Re0, mulres_lo ; Lm += mulres (1 т) adc Re1, mulres_hi ; (1 т) adc Re2, mulres_3 ; (1 т) dec i_hi ; (1 т) brpl furie_func_300Hz_loop_i_hi ; (2 т) ; предъидущий цикл 128*31=3968 тактов dec i_lo ; (1 т) brpl furie_func_300Hz_loop_i_lo ; (2 т) ; предъидущий цикл 4*(3968+3+3)=15896 тактов ;здесь надо Lm и Re cделать положительными clr i_lo ; (1 т) ldi i_hi, 1 ; (1 т) tst Lm2 ; (1 т) brpl furie_func_300Hz_negative_test_1_skip ; (2 т) com Lm0 ; (1 т) com Lm1 ; (1 т) com Lm2 ; (1 т) add Lm0, i_hi ; (1 т) adc Lm1, i_lo ; (1 т) adc Lm2, i_lo ; (1 т) furie_func_300Hz_negative_test_1_skip: tst Re2 ; (1 т) brpl furie_func_300Hz_negative_test_2_skip ; (2 т) com Re0 ; (1 т) com Re1 ; (1 т) com Re2 ; (1 т) add Re0, i_hi ; (1 т) adc Re1, i_lo ; (1 т) adc Re2, i_lo ; (1 т) furie_func_300Hz_negative_test_2_skip: ; Lm >>= 16; Re >>= 16; ldi i_lo, 16 ; i = 16 (1 т) furie_func_300Hz_loop2: ; lsr Lm2 ; Lm >>= 1 (1 т) ror Lm1 ; (1 т) ror Lm0 ; (1 т) lsr Re2 ; Re >>= 1 (1 т) ror Re1 ; (1 т) ror Re0 ; (1 т) dec i_lo ; i-- (1 т) brne furie_func_300Hz_loop2 ; while (i) (2 т) ; предъидущий цикл 1+16*9=145 тактов ; sqr = Lm * Lm + Re * Re muls Lm0, Lm0 ; mulres = Lm * Lm (2 т) movw sqr_lo, mulres_lo ; sqr = mulres (1 т) muls Re0, Re0 ; mulres = Re * Re (2 т) add sqr_lo, mulres_lo ; sqr += mulres (1 т) adc sqr_hi, mulres_hi ; (1 т) ; ret = qsqr(sqr); rcall qsqrt ; 3+344 такта ; результат в R20 ret ; 4 такта ; максимальное количество тактов функции 9+15896+20+145+7+3+344+4=16428 тактов ; время выполнения ~1027 мкс на входе 512 выборок 8ми битных значений с АЦП. частота дискретизации сигнала ~ 38400 Hz При работе обнаружен "дребезг" полученных значений при оцифровке нулевого сигнала. Причем дребезг очень большой. Для отладки я заполнил входные данные (буфер adc_buf) нулевыми значениями, дребезг стал меньше, но, тем не менее, остался при отладке обнаружил, что здесь Код: muls adcv, sin ; mulres = adcv * sin (2 т) ; здесь надо приобразовать 2х байтный результат умножения в 3х байтный с учетом знака ; знак в старшем байте (если он есть), проверяем clr mulres_3 ; в R2 - 3й байт результата умножения (1 т) tst mulres_hi ; если число положительное, то пропускаем (1 т) brpl furie_func_300Hz_loop_negative_test_1_skip ; (2 т) ; иначе нам надо изменить 3й байт результата умножения, ; записав в него 0xFF ser mulres_3 ; (1 т) ; <---------- ЗДЕСЬ------------------- furie_func_300Hz_loop_negative_test_1_skip: ; теперь просто складываем 2 24х битных числа add Lm0, mulres_lo ; Lm += mulres (1 т) adc Lm1, mulres_hi ; (1 т) adc Lm2, mulres_3 ; (1 т) на определенном шаге (тоесть не всегда) инструкция проходит, хотя adcv в отладчике == 0, mulres (R1:R0) тоже равен нулю, а флаг N == 1 после строчки tst mulres_hi ; tst R1 отсюда у функции появляется дребезг. Вопрос - КАК?. |
Автор: | Golosov_SA [ Чт янв 26, 2012 22:30:22 ] |
Заголовок сообщения: | Re: проблема с алгоритмом БПФ. |
ошибку нашел, тему можно закрывать. кому интересно - флаг менялся в теле прерывания. устранил запоминанием регистра SREG в стек при обработке прерывания |
Автор: | Engineer_Keen [ Пт янв 27, 2012 16:25:17 ] |
Заголовок сообщения: | Re: проблема с алгоритмом БПФ. |
Кстати, есть маленькая хитрость для ускорения обработчика прерывания, ведь как известно обработчик прерывания нужно делать как можно быстрее. Если есть свободный регистр, то его можно использовать вместо стека. Потому как IN и OUT выполняются за 1 такт, а PUSH и POP за 2. |
Автор: | YS [ Вс янв 29, 2012 13:29:29 ] |
Заголовок сообщения: | Re: проблема с алгоритмом БПФ. |
Цитата: furie_func_300Hz: FOURIER. Furie переводится с итальянского как "ярость". ![]() ![]() |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |