Например TDA7294

Форум РадиоКот • Просмотр темы - проблема с алгоритмом БПФ.
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Пн июл 28, 2025 13:11:14

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Эта тема закрыта, Вы не можете редактировать и оставлять сообщения в ней.  [ Сообщений: 4 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: проблема с алгоритмом БПФ.
СообщениеДобавлено: Чт янв 26, 2012 22:06:52 
Родился

Зарегистрирован: Сб сен 05, 2009 14:45:39
Сообщений: 13
Откуда: Рыбинск, Ярославская область
Рейтинг сообщения: 0
Изучаю БПФ, набросал код вычисления.

Камень - 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

отсюда у функции появляется дребезг.

Вопрос - КАК?.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: проблема с алгоритмом БПФ.
СообщениеДобавлено: Чт янв 26, 2012 22:30:22 
Родился

Зарегистрирован: Сб сен 05, 2009 14:45:39
Сообщений: 13
Откуда: Рыбинск, Ярославская область
Рейтинг сообщения: 0
ошибку нашел, тему можно закрывать.

кому интересно - флаг менялся в теле прерывания. устранил запоминанием регистра SREG в стек при обработке прерывания


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: проблема с алгоритмом БПФ.
СообщениеДобавлено: Пт янв 27, 2012 16:25:17 
Друг Кота
Аватар пользователя

Карма: 32
Рейтинг сообщений: 235
Зарегистрирован: Пт янв 29, 2010 10:27:40
Сообщений: 3863
Откуда: Москва
Рейтинг сообщения: 0
Кстати, есть маленькая хитрость для ускорения обработчика прерывания, ведь как известно обработчик прерывания нужно делать как можно быстрее. Если есть свободный регистр, то его можно использовать вместо стека. Потому как IN и OUT выполняются за 1 такт, а PUSH и POP за 2.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: проблема с алгоритмом БПФ.
СообщениеДобавлено: Вс янв 29, 2012 13:29:29 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 1247
Зарегистрирован: Вс мар 29, 2009 22:09:05
Сообщений: 7517
Рейтинг сообщения: 0
Цитата:
furie_func_300Hz:


FOURIER.

Furie переводится с итальянского как "ярость". :))) А вот fourier transform - это то, что Вы и делали. :wink:

_________________
Разница между теорией и практикой на практике гораздо больше, чем в теории.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Эта тема закрыта, Вы не можете редактировать и оставлять сообщения в ней.  [ Сообщений: 4 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 27


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y