Efekt do gitary elektrycznej o nazwie Fuzz Graficzny jest prawie zawsze używany przy muzyce rockowej, jego brzmienie jest łagodniejsze od klasycznego efektu "distortion" i zazwyczaj stosowany jest do gitary prowadzącej, może być jednak używany przez gitary solowe. Realizacja efektu polega na tym, że sygnał rozdzielony jest na wiele pasm częstotliwości, a w każdym z nich znajduje się zwykły "fuzz" klasyczny. Sposób działania tego efektu pokazano na rysunku 1.
Działanie urządzenia
Pierwszy etap polega na przetworzeniu sygnału analogowego na cyfrowy za pomocą przetwornika znajdującego się w układzie kodeka. Następnie sygnał jest przetwarzany przez zespół filtrów cyfrowych, i w każdym kanale wytwarzane są zniekształcenia. Tworzenie zniekształceń polega na obcięciu chwilowej amplitudy sygnału. Następnie kanały są sumowane i sygnał cyfrowy wysyłany jest do przetwornika analogowo-cyfrowego zawartego w układzie kodeka.
Opis programu komputerowego
Cały program składa się z dwóch części: procedur przetwarzania sygnału, w skład których wchodzi również komunikacja z układem kodeka oraz z interfejsu użytkownika, który jest odpowiedzialny za ustawianie parametrów urządzenia i obsługuje przyciski sprzętowe, enkoder oraz steruje wyświetlaczem graficznym.
Część DSP - sterowanie kodekiem
Sterowanie układem WM8904 odbywa się z użyciem dwóch interfejsów: I²C oraz I²S. Magistrala I²C służy do konfiguracji urządzenia poprzez programowanie wewnętrznych rejestrów procesora dźwięku. Można w ten sposób zaprogramować: wzmocnienie wewnętrznego wzmacniacza PGA, źródła sygnału wejściowego i wyjściowego, częstotliwość próbkowania itp. Interfejs I²S służy do przesyłania próbek dźwiękowych.
W naszym programie używamy gotowej biblioteki służącej do konfiguracji kodeka. Obsługa transmisji danych odbywa się poprzez dwa interfejsy I²S. Zastosowany mikrokontroler dostarcza system dziewięciu uniwersalnych bloków komunikacji szeregowej, nazwanych FLEXCOM, każdy z nich można skonfigurować jako jeden z interfejsów do transmisji danych (UART, USART, SPI, I²C, I²S). W naszym układzie korzystamy z FLEXCOM6 i FLEXCOM7, gdyż są one elektrycznie podłączone do układu WM8904. Interfejs I²S zaimplementowany na module FLEXCOM6 jest używany jako wejście sygnału akustycznego, natomiast transmisja odbywająca się poprzez FLEXCOM7 wysyła dane do przetwornika DAC, czyli pełni funkcję wyjścia. Ponieważ sygnały sterujące transmisją (BCK i WS) są takie same dla obydwu interfejsów, należy dokonać ich połączenia. Służy do tego moduł SYSCTL.
Program ma funkcję regulacji sygnału wyjściowego oraz ustawienia typu wejścia - wejście mikrofonowe lub wejście liniowe. Rodzaj wejścia wybiera się poprzez zmianę wzmocnienia wewnętrznego wzmacniacza PGA (Programable Gain Amplifier). Obydwa te parametry można zmieniać poprzez ustawianie wartości w rejestrach układu kodeka.
Do działania kodeka konieczne jest dostarczenie sygnału taktującego na wejście MCLK. Sygnał ten wytwarzany jest przez mikrokontroler i wyprowadzony na odpowiednio skonfigurowane wyjście MCLK. Częstotliwość sygnału wynosi 24 576 000 Hz. Jest to zalecana wartość częstotliwości, która umożliwia wytworzenie wymaganych przebiegów sterujących dla standardowych prędkości próbkowania.
Na rysunku 2 pokazano strukturę wewnętrzną układu kodeka WM8904, natomiast rysunek 3 obrazuje transmisję pomiędzy kodekiem a mikrokontrolerem.
Opis algorytmu DSP
Sygnał, który przeszedł próbkowanie, jest poddawany cyfrowej filtracji. Jako filtry zastosowałem cyfrowe imitacje szeregowych obwodów rezonansowych. Do ich zaprojektowania użyłem następujące zależności:
gdzie:
- UR - napięcie na rezystorze,
- UC - napięcie na kondensatorze,
- UL - napięcie na cewce.
Wartości L i C można wyliczyć na podstawie częstotliwości rezonansowej oraz wymaganej dobroci filtru. Natomiast wartość rezystancji najwygodniej przyjąć równą jeden. Struktura tego filtru zamieszczona jest na rysunku 4.
Na listingu 1 zamieszczam fragment kodu odpowiedzialny za przetwarzanie sygnału akustycznego. Schemat algorytmu wprowadzającego zniekształcenia pokazany jest na rysunku 5.
Jednym z elementów tego algorytmu jest układ pomiaru amplitudy. Algorytm jego działania jest pokazany na rysunku 6.
Zasada jego działania jest bardzo prosta. Polega na wyliczeniu wartości bezwzględnej sygnału, a następnie poddaniu go działaniu filtru dolnoprzepustowego. Natomiast zasada działania układu kompresora (służy on do utrzymywania stałej wartości sygnału na wyjściu) jest pokazana na rysunku 7.
Aby wykorzystać maksymalną częstotliwość procesora, procedura DSP została umieszczona w pamięci operacyjnej, a wszystkie powtarzające się procedury zostały napisane w postaci makr (listing 1).
#include “app.h”
#include “dsp.hpp”
#define T_PA ((float)100/FP)
#define PomiarAmplitudy(n,x)\
static float n##BA = 0;\
static float n##C1 = 0;\
n##C1 += (((x<0) ? -x :x)-n##C1)*T_PA;\
n##BA += (n##C1-n##BA)*T_PA;
#define Filtr(f,q,x)\
static float uc##f = 0;\
static float IL##f = 0;\
uc##f += IL##f * (float)((float)2 * STALA_PI / FP * (float)q * (float)f);\
IL##f += (x - uc##f - IL##f) * (float)((float)2 * STALA_PI / FP * (float)f / (float)q);\
SParFuzz ParFuzz = {0.5,0.5,0.05,0.5,0.5,0.5,0.5,0.5,0.5,0,0,0,0,true};
void __attribute__((section(“RamFunction”))) PrzetwarzanieGlowne()
{
volatile register float wl,wp;
wl = (float)WartoscWE_L/(float)0x7FFF;
wp = (float)WartoscWE_P/(float)0x7FFF;
volatile register float ww = 0, wsp, ba, we = wl+wp, fk = 1/ParFuzz.Odc;
Filtr(21,1,we);
PomiarAmplitudy(P20_,IL21);
ba = P20_BA;
wsp = IL21*fk;
ww += ((ba<wsp) ? ba : ((-ba>wsp) ? -ba : wsp))*ParFuzz.A20;
Filtr(46,1,we);
PomiarAmplitudy(P50_,IL46);
ba = P50_BA;
wsp = IL46*fk;
ww += ((ba<wsp) ? ba : ((-ba>wsp) ? -ba : wsp))*ParFuzz.A50;
Filtr(100,1,we);
PomiarAmplitudy(P100_,IL100);
ba = P100_BA;
wsp = IL100*fk;
ww += ((ba<wsp) ? ba : ((-ba>wsp) ? -ba : wsp))*ParFuzz.A100;
Filtr(215,1,we);
PomiarAmplitudy(P200_,IL215);
ba = P200_BA;
wsp = IL215*fk;
ww += ((ba<wsp) ? ba : ((-ba>wsp) ? -ba : wsp))*ParFuzz.A200;
Filtr(464,1,we);
PomiarAmplitudy(P500_,IL464);
ba = P500_BA;
wsp = IL464*fk;
ww += ((ba<wsp) ? ba : ((-ba>wsp) ? -ba : wsp))*ParFuzz.A500;
Filtr(1000,1,we);
PomiarAmplitudy(P1K_,IL1000);
ba = P1K_BA;
wsp = IL1000*fk;
ww += ((ba<wsp) ? ba : ((-ba>wsp) ? -ba : wsp))*ParFuzz.A1K;
Filtr(2150,1,we);
PomiarAmplitudy(P2K_,IL2150);
ba = P2K_BA;
wsp = IL2150*fk;
ww += ((ba<wsp) ? ba : ((-ba>wsp) ? -ba : wsp))*ParFuzz.A2K;
Filtr(4640,1,we);
PomiarAmplitudy(P5K_,IL4640);
ba = P5K_BA;
wsp = IL4640*fk;
ww += ((ba<wsp) ? ba : ((-ba>wsp) ? -ba : wsp))*ParFuzz.A5K;
Filtr(10000,1.5,we);
PomiarAmplitudy(P10K_,IL10000);
ba = P10K_BA;
wsp = IL1000*fk;
ww += ((ba<wsp) ? ba : ((-ba>wsp) ? -ba : wsp))*ParFuzz.A10K;
ww*=2;
if(ww>1)
ww = 1;
if(ww<-1)
ww=-1;
WartoscWY_P = WartoscWY_L = (int16_t)(ww*(float)0x7FFF);
}
Interfej GUI
Do opracowania interfejsu użytkownika zastosowano zaprojektowaną przez autora bibliotekę, która współpracuje z wyświetlaczem graficznym LCD o rozdzielczości 128×64 pikseli. Umożliwia ona utworzenie na ekranie siedmiu kontrolek:
- "Check box" - obiekt służy do wyboru dwóch stanów;
- "Radio Button" - ta kontrolka umożliwia wybór jednej z wielu opcji;
- "Text" - wyświetla tekst w ramce na ekranie i może być traktowana jako przycisk;
- "Label" - tylko wyświetla tekst;
- "Bar" - wyświetla słupek o zmieniającej się wysokości. Kontrolka ta jest używana do ustawiania wartości;
- "Edit" - ten obiekt umożliwia edycję napisu;
- "Arrow" - wyświetla strzałkę na ekranie.
Główną klasą do obsługi interfejsu użytkownika jest EGUI. Umożliwia ona wyświetlanie treści na ekranie oraz odczyt wartości z przycisków i enkodera. Również za pomocą jej funkcji składowych można do interfejsu dodawać okna kontrolne wywodzące się z klasy EKontrolkaBaza. Na rysunku 8 pokazano hierarchię klas, natomiast na rysunku 9 pokazano strukturę interfejsu GUI naszego programu.
Interfejs GUI korzysta z biblioteki graficznej, również opracowanej przez autora, służącej do wyświetlania różnych kształtów na ekranie wyświetlacza. Koncepcję tej biblioteki obrazuje rysunek 10.
Opis układu elektrycznego
Chociaż układ zbudowany jest na bazie gotowego modułu z mikrokontrolerem firmy NXP do jego działania potrzebnych jest kilka elementów dodatkowych. Są to: wyświetlacz graficzny 128×64 piksele oraz układ do jego sterowania. Można również do modułu dołączyć dwa przyciski, chociaż nie jest to konieczne, ponieważ do sterowania urządzeniem można używać przycisków znajdujących się na płytce ewaluacyjnej.
Zastosowany w naszym układzie wyświetlacz graficzny może pracować w dwóch trybach. Może być sterowany za pomocą transmisji równoległej lub szeregowej w protokole SPI. W naszym układzie stosujemy tryb transmisji szeregowej. Ponieważ wyświetlacz fabrycznie jest skonfigurowany do pracy przy transmisji równoległej, należy przełączyć zworę, która znajduje się na jego tylnej części (rysunek 11).
Dodatkowo, ponieważ układ logiczny wyświetlacza jest sterowany napięciami niezgodnymi z logiką standardu 3,3 V, czyli wartościami wyjściowymi mikrokontrolera (wysoki stan wejść wymaga napięcia wyższego niż 3,5 V), zastosowano bufor 74HCT541. Schemat części elektrycznej pokazany jest na rysunku 12.
Elementy zastosowane w układzie
Wyświetlacz monochromatyczny, graficzny LCD typu LCD-EG-128064H-FHW K/W-E6 daje dobre wrażenie. Charakteryzuje się niską ceną i jest dostępny w wielu sklepach internetowych m.in. ARTRONIC czy KAMAMI. Jako bufor służy układ 74HCT541. Potencjometr do regulacji kontrastu może być dowolnym potencjometrem montażowym o rezystancji około 25 kΩ. Jako enkoder można zastosować dowolny 3-wyjściowy enkoder inkrementalny.
Tomasz Krogulski
krogul70@gmail.com