Efekt do gitary na bazie LPC5528

Efekt do gitary na bazie LPC5528

W artykule zaprezentuję kolejne zastosowanie płytki ewaluacyjnej firmy NXP demonstrujące działanie mikrokontrolera serii LPC55xx. Jest to najbardziej popularny efekt do gitary elektrycznej o nazwie Fuzz Graficzny. Płytka ewaluacyjna wyjątkowo dobrze nadaje się do tego zastosowania, ponieważ jest wyposażona w 16-bitowy kodek WM8904 oraz procesor LPC5528 zawierający odpowiednie interfejsy do komunikacji z nim, a dołączenie graficznego wyświetlacza powoduje, że używanie urządzenia jest bardzo wygodne.

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.

Rysunek 1. Schemat przedstawiający działanie efektu Fuzz Graficzny

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.

Rysunek 2. Schemat blokowy kodeka

Na rysunku 2 pokazano strukturę wewnętrzną układu kodeka WM8904, natomiast rysunek 3 obrazuje transmisję pomiędzy kodekiem a mikrokontrolerem.

Rysunek 3. Realizacja transmisji pomiędzy MPU, a kodekiem

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.

Rysunek 4. Schemat blokowy filtru pasmowego

Na listingu 1 zamieszczam fragment kodu odpowiedzialny za przetwarzanie sygnału akustycznego. Schemat algorytmu wprowadzającego zniekształcenia pokazany jest na rysunku 5.

Rysunek 5. Działanie algorytmu wprowadzania zniekształceń

Jednym z elementów tego algorytmu jest układ pomiaru amplitudy. Algorytm jego działania jest pokazany na rysunku 6.

Rysunek 6. Algorytm układu pomiaru amplitudy

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.

Rysunek 7. Zasada działania kompresora

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).

Listing 1. Fragment kodu odpowiedzialny za przetwarzanie sygnału akustycznego

#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.
Rysunek 8. Hierarchia klas interfejsu GUI

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.

Rysunek 9. Schemat poglądowy struktury naszego interfejsu

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.

Rysunek 10. Koncepcja działania interfejsu graficznego obsługującego wyświetlacz LCD

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).

Rysunek 11. Schemat podłączenia wyświetlacza

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.

Rysunek 12. Schemat części elektrycznej

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

Artykuł ukazał się w
Elektronika Praktyczna
styczeń 2024

Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik czerwiec 2024

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio maj - czerwiec 2024

Świat Radio

Magazyn krótkofalowców i amatorów CB

Automatyka, Podzespoły, Aplikacje maj 2024

Automatyka, Podzespoły, Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna czerwiec 2024

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Elektronika dla Wszystkich czerwiec 2024

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów