Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Cyfrowy filtr audio z prockami ATMEGA/ATTINY do gier.

kazkowicz 16 May 2010 20:11 3707 5
NDN
  • Witam,

    Znajdziecie tu program na ATMEGA8 (docelowo też na... TINY13?!), który jest przeróbką oryginału z niemieckiej strony http://www.mikrocontroller.net/articles/Digitalfilter_mit_ATmega robionego na podstawie noty AVR223. Jego twórca najwyraźniej jest krótkofalowcem i oryginał ma służyć m.in. do filtrowania sygnału SSTV.

    No ale nie samą SSTV człowiek żyje, ja od dłuższego czasu szukałem czegoś do dodania realizmu gierkom strzelanym w necie. Mój pierwowzór wykonany na wzmacniaczach operacyjnych (FGP 4. rzędu 600Hz + FDP 2. rzędu 6kHz) często wywołuje pozytywne zainteresowanie na tzw. respie. Chciałem jednak spróbować zrobić to na procku, zarówno dla sprawdzenia czy to prawda że AVR 8bit da radę pociągnąć filtrowanie audio w czasie rzeczywistym (nie licząc wielu projektów analizatorów widma m.cz.), jak i w nadziei że uda się uzyskać większą elastyczność i... gorszą jakość audio:). Ideał - głos po przetworzeniu brzmi jak z krótkofalówki na amerykańskich filmach;). No ale do tego jeszcze daleko. Tymczasem zamieszczam pierwszą działającą wersję, jest to nadal ów filtr SSTV, ale jakiś efekt już jest. Źródło programu przerobiłem tak, żeby bez problemu kompilowało go AVRStudio. Nie usuwałem oryginalnych linii, a jedynie remowałem/poprawiałem co było trzeba, więc każdy może zobaczyć różnice. Każdy może eksperymentować z częstotliwością kwarcu (lub generatora wewn.) czy częstotliwością taktowania ADC i natychmiast słyszeć różnicę. Jako że u mnie obrabiany jest sygnał mikrofonowy, został on wzmocniony ok 11x i podany przez kondensator na AIN0 (oczywiście można przełączyć wedle uznania modyfikując ADMUX - ale np. AIN4 i AIN5 mają większe zakłócenia). Wejście przetwornika wstępnie polaryzuję połową Aref - u mnie wewnętrzne źródło 2,56V (oryginał używa Avcc). Odpowiedni dzielnik dla Vcc 5V to np. 68k górny i 22k dolny rezystor (wiem, zaraz ktoś zacznie że w sumie powinno być <10kiloomów, a jest ok. 17k - ale do tego jest jeszcze wyjście przedwzmacniacza no i można dać 1 - 10nF do masy. No i łapie wszystkie śmieci z zasilania). Na wyjściu OC1B dałem "FDP" 4k7 + 22nF, resztę załatwiają filtry karty muzycznej. OC1A odłączyłem (w oryginale niby było podłączone, ale... nic na nie nie trafiało - w założeniu miał chyba tam iść sygnał prosto z ADC?). Co ciekawe, obecność OC1A chyba można wykorzystać do zrobienia mostkowego wyjścia na słuchawki, wystarczy odwrócić fazę PWM A bitami COM1A1:COM1A0 (11) i ładować OCR1AL tą samą wartością co OCR1BL - ale należy zabezpieczyć oba wyjścia szeregowymi rezystorami po minimum 100 omów i połączyć obie słuchawki szeregowo (czyli Ro minimum 250 - 260 omów). Dodałem też SLEEP (w oryginale brak), poprawia się trochę sygnał/szum. Niestety tylko w trybie IDLE, tryb ADC NOISE REDUCTION powoduje wzbudzanie się filtrów (wyłączałem free run etc., na razie bez efektu). Pomysłów jest więcej, m.in dodanie generatora szumu pseudolosowego (tło a'la radio), przełączanie efektów (w ATMEGA8 trochę się ich zmieści), dodanie kolejnych ogniw filtrujących, zrobienie wersji na ATTINY13 (wygląda na to, że jeden efekt (trzy filtry 2. rzędu) spokojnie się mieści i sprzętowo też ogarnia - to dopiero wygar! Taki maluch!), no ale najważniejsze to rozgryzienie współczynników filtrów aby zacząć eksperymenty z własnymi. FilterFree jest potencjalnym kandydatem, ale jego obliczenia trzeba jeszcze przerobić. Obecnie w procu siedzą trzy moduły filtrów 2. rzędu, z których wyraźnie dwa są FDP, a jeden FGP. Pierwszym krokiem powinna być zmiana na jeden FDP i dwa FGP, a potem dobranie reszty parametrów. Zachęcam do eksperymentów i ewentualnego dzielenia się uzyskanymi efektami, podając współczynniki, nastawy ADC i f zegara. Wspólnie może uda się znaleźć ciekawe rozwiązania do wykorzystania w necie. Załączam pliki asm i hex (zmienione rozszerzenia), fusy poniżej, zegar 11,0592MHz - będzie chodzić i z mniejszymi, i z większymi. Z prymitywnym filtrem DP 1. rzędu na wejściu aliasing dla mowy praktycznie nie występuje, dla innych sygnałów być może trzeba dać coś więcej.

    Pisane na szybko, więc w razie czego dajcie znać jeżeli coś zakręciłem - "sie poprawi". Komentarze w kodzie źródłowym powinny też nieco wyjaśnić. Wszystkie ewentualne pytania zadawajcie na forum, żeby każdy mógł skorzystać. Na PW nie odpowiadam.

    Fusebity:
    Cyfrowy filtr audio z prockami ATMEGA/ATTINY do gier.

    Cool? Ranking DIY
    About Author
    kazkowicz
    Level 14  
    Offline 
    Has specialization in: chechłacze
    kazkowicz wrote 105 posts with rating 4, helped 5 times. Live in city W-wa. Been with us since 2008 year.
  • NDN
  • #2
    chaka
    VIP Meritorious for electroda.pl
    Jak wpłynie na wydajność dołożenie zewnętrznych przetworników AD i DA?
  • NDN
  • #3
    kazkowicz
    Level 14  
    Witam,

    Wcale lub na minus. Wszystko zależy od wybranego przetwornika i rozdzielczości. Gdy np. ośmiobitowy przetwornik będzie umiał zgłosić koniec konwersji pracując w trybie auto, to po prostu obliczenia zamiast w przerwaniu ADC trzeba będzie umieścić w przerwaniu np. INT0 lub INT1. Ilość obliczeń, czyli obciążenie CPU się nie zmieni. Wewnętrzny ADC działa autonomicznie od CPU, wobec niego jest praktycznie zewnętrzny, za to dobrze sprzęgnięty sprzętowo. Bardziej warto podciągnąć zegary - procka i ADC. Co do zegarów, taki np. ATmega8515 potrafił mi chodzić przy 25MHz/5V, tylko już np. interfejs RAM zaczynał się krzaczyć.

    Przy zewnętrznym ADC zmieni się za to choćby poziom szumów i zakłóceń od zasilania, bo trudno tak do końca odkłócić wewnętrzny ADC. Z zewnętrznym powinno być łatwiej. Jednak i tak dolny limit szumów wyznaczają: rozdzielczość przetwornika, współczynniki filtru i precyzja obliczeń, ta ostatnia tu zdefiniowana na stałe. Podobne rozważania dotyczą DAC, choć tu poprawa jakości sygnału może być znaczna - nadal jednak bez wpływu na wydajność CPU.

    Wracając do oryginalnego tematu (choć oczywiście ten filtr jest uniwersalny) załączam asm i hex mojego aktualnego filtru, obliczony przy pomocy FilterFree (darmowy, gdyby nie było jasne). Każde ogniwo IIR drugiego rzędu (SOS, Second Order Section lub biquad) liczone osobno. W wolnej chwili podam sposób implementacji. Filtr daje efekt podobny do swojego analogowego odpowiednika, z tym że wyposażyłem go w generator szumu "radiowego" (opisany w listingu, można wyłączyć całą sekcję), co już stanowi przewagę nad analogiem. Bez generatora poziom szumu jest gorszy niż w filtrze SSTV, przeczuwam że warto pokombinować z wartościami współczynników (przemnożyć wszystkie przez tą samą liczbę, mniejszą lub większą od 1).

    Jestem ciekaw waszych wrażeń z ewentualnego użytkowania, jednocześnie sam lecę trochę postrzelać. Go go go! :)
  • #5
    kazkowicz
    Level 14  
    Spoko, dzięki, wygodny programik - wybierając współczynniki jako 16 bitów ze znakiem dostajemy gotowe wartości do podstawienia w programie. Poniżej porównanie wyników dla filtru 2. rzędu GP (HP) 600Hz:

    FilterFree:

    NUM = [.8144, -1.629, .8144] HP 600Hz
    DEN = [1, -1.594, .6636]

    13343 ; b01 *16384
    -26690 ; b11 *16384
    13343 ; b21 *16384

    16384 ; a01 *16384
    25625 ; -a11 *16384
    -10872 ; -a21 *16384

    WinFilter:

    ACoef
    13339,
    -26679,
    13339

    BCoef
    16384,
    -26118,
    10872

    Muszę to jeszcze sprawdzić, bo na oko widać że współczynniki A z FilterFree wydają się być współczynnikami B z WinFilter i odwrotnie. W programie filtru a01 jest zawsze równy 1, a tu widać że w WinFilter to b01 jest równy 1 (16384). Reszta współczynników ma wyraźnie zbliżone wartości, tylko trzeba pamiętać żeby wyliczone współczynniki a01 i a02 przed podstawieniem do programu filtru przemnożyć przez -1.
  • #6
    TReneR666
    Level 13  
    Matlab + signal processing toolbox