Ogólny opis układu
Chociaż do działania samego rejestratora wystarczyłby sam moduł ewaluacyjny, to w ramach projektu został on rozbudowany o kartę SD (zewnętrzna pamięć znacznie powiększa pojemność rejestratora – czyli długość zapisywanych dźwięków) oraz kolorowy wyświetlacz. To drugie rozwiązanie uprościło obsługę urządzenia, co więcej: aby konstrukcja prezentowała się atrakcyjniej, projekt wzbogacono o wizualizację widma sygnału oraz korektor graficzny. W roli ekranu zastosowano wyświetlacz kolorowy 4” ze sterownikiem ILI9488, dostępny na rynku od niedawna. Jest on wyposażony w szeregowy interfejs SPI (co bardzo ułatwia konstrukcję), a do jego zalet należy również bardzo niska cena i łatwa dostępność na popularnych portalach handlowych. Do sterowania programem zastosowano enkoder 24-pozycyjny oraz dwa przełączniki monostabilne. Elementy te wpięto do złączy, na które wyprowadzone zostały sygnały procesora. Sposób podłączenia elementów zewnętrznych do płytki rozwojowej pokazany został na rysunkach 1 i 2.
Algorytm programu
Ogólny algorytm działania programu pokazuje rysunek 3. Jak widać, składa się on z części przetwarzania sygnału akustycznego (która odpowiada za odczyt dźwięku z kodeka, korekcję częstotliwościową dźwięku za pomocą equalizera, zapis na karcie SD oraz wyznaczanie amplitud używanych przez procedurę wizualizacji widma sygnału) oraz bloku obsługującego interfejs graficzny, tworzący na wyświetlaczu obiekty przeznaczone do regulacji parametrów programu, a także wyświetlania użytecznych danych. Interfejs jest sterowany za pomocą enkodera z przyciskiem oraz dwóch mikroprzełączników.
Schemat blokowy korektora graficznego i układu analizatora widma pokazany został na rysunku 4.
Rejestracja sygnału polega na zapisywaniu danych na kartę SD, co odbywa się za pomocą interfejsu sprzętowego realizującego transmisję. Jak widać na schemacie, z filtrów cyfrowych korzystają zarówno algorytm korektora graficznego, jak i procedura pomiaru wartości sygnału w poszczególnych pasmach częstotliwości. W celu poprawy działania filtru, jego kod wykonywany jest 4 razy w czasie jednego cyklu taktowania. Tak więc rzeczywista częstotliwość pracy filtrów wynosi: 4×fP. Cała procedura przetwarzania sygnału została umieszczona w pamięci RAM, a z myślą o dalszym zwiększeniu prędkości jej wykonywania wyeliminowano stosowanie wywołań funkcji, zamiast których wprowadzone zostały makra. Na listingu 1 zaprezentowano fragmenty programu zawierające kod filtru pasmowego oraz detektora amplitudy.
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)4) * (float)q * (float)f;\
IL##f += (x – uc##f – IL##f) * (float)((float)2 * STALA_PI / FP/(float)4) * (float)f / (float)q;\
uc##f += IL##f * (float)((float)2 * STALA_PI / FP/(float)4) * (float)q * (float)f;\
IL##f += (x – uc##f – IL##f) * (float)((float)2 * STALA_PI / FP/(float)4) * (float)f / (float)q;\
uc##f += IL##f * (float)((float)2 * STALA_PI / FP/(float)4) * (float)q * (float)f;\
IL##f += (x – uc##f – IL##f) * (float)((float)2 * STALA_PI / FP/(float)4) * (float)f / (float)q;\
uc##f += IL##f * (float)((float)2 * STALA_PI / FP/(float)4) * (float)q * (float)f;\
IL##f += (x – uc##f – IL##f) * (float)((float)2 * STALA_PI / FP/(float)4) * (float)f / (float)q;\
Listing 1. Makra odpowiedzialne za pomiar amplitudy oraz filtrację danych
Zasada działania bloku pomiaru amplitudy pokazana jest na rysunku 5. Jeśli Czytelnik chciałby zmodyfikować program, należy zwrócić szczególną uwagę na to, aby do przechowywania wartości sygnału i wykonywania na nim operacji matematycznych stosować zmienne typu float (pojedynczej precyzji), a stałe zamieniać (metodą konwersji jawnej) także na typ float, gdyż tylko on jest obsługiwany sprzętowo. Operacje na zmiennych typu double są o wiele bardziej czasochłonne i mogą spowodować nieprawidłowe działanie programu.
Rejestrowane dane zapisywane są na karcie SD podzielonej na 22 fragmenty. Na każdym z nich można zapisać około pół godziny dźwięku. Reprezentacja danych jednej ścieżki dźwiękowej pokazana została na rysunku 6.
Do wykonania części interfejsu graficznego użytkownika zastosowano bibliotekę napisaną przez autora. Składa się ona z 5 obiektów oraz 5 procedur graficznych, które są stosowane przez interfejs, ale można także korzystać z nich niezależnie od tego ostatniego.
Do budowy interfejsu graficznego służą następujące obiekty:
- Słupek – umożliwia ustawianie wartości,
- Wybór – wywołuje procedurę zdarzenia po wciśnięciu przycisku enkodera,
- Opcja – pozwala ustawić wartość pojedynczej flagi,
- Lista – umożliwia wybranie jednej pozycji z listy napisów,
- Statyczna – wyświetla tekst lub bitmapę.
Do zmiany obiektu na ekranie służą dwa przyciski.
Aby umieścić obiekt interaktywny na wyświetlaczu, należy odpowiednio wypełnić jego strukturę oraz wywołać funkcję: „GUI_Add” i jako parametr podać wspomnianą strukturę konfiguracyjną. Wszystkie deklaracje obiektów używanych przez interfejs użytkownika znajdują się w pliku nagłówkowym GUI. Strukturę interfejsu graficznego pokazuje rysunek 7.
Oto wszystkie zaimplementowane funkcje GUI:
- void InicjujPG(),
- void GUI_Init() – inicjalizuje Framework,
- void GUI_Add(E_Kontrol*) – wstawia kontrolkę i wyświetla ją na ekranie,
- void GUI_New() – usuwa wszystkie obiekty,
- void GUI_Hide() – zaciemnia ekran,
- void GUI_Show() – usuwa zaciemnienie ekranu,
- void GUI_Zatwierdz(E_Kontrol*) – rysuje ponownie obiekt,
- void GUI_UstawKontrol(int id) – ustawia aktywny obiekt,
- E_Kontrol* GUI_Podaj(int id) – zwraca strukturę obiektu na podstawie jego numeru identyfikacyjnego.
Do obsługi zdarzeń służy funkcja, którą należy przypisać odpowiedniemu polu obiektu graficznego:
gdzie T_Z: typ wyliczeniowy pokazany na listingu 2.
{
Z_INICJUJ, //inicjacja objektu
Z_EN_L, //ruch enkodera w lewo
Z_EN_P, //ruch enkodera w prawo
Z_EN_SW, //naciśnięcie przycisku enkodera
Z_SW1, //naciśnięty przycisk 1
Z_SW2, //naciśnięty przycisk 1
Z_TIMER, //skończenie odliczania przez TIMER
//(wywoływana jest funkcja wskazywana przez *TH)
Z_TICK // wewnętrzny
};
Listing 2. Definicja typu wyliczeniowego T_Z
Obsługa urządzenia
Ustawianie parametrów urządzenia odbywa się poprzez zastosowanie zwykłych kontrolek biblioteki, natomiast wyświetlanie pasków wizualizacji widma realizowane jest za pomocą procedury rysowania kształtu prostokątnego. Z powodu dość wolnej transmisji nie robi się tego jednak w sposób bezpośredni – wielkość słupka wskazującego wartość sygnału jest powiększana lub zmniejszana w zależności od zmiany amplitudy.
Interfejs składa się z trzech ekranów. Pierwszy z nich służy do wyboru numeru pozycji, pod którą zostanie zapisany lub odczytany dźwięk – fotografia 1.
Drugi (fotografia 2) zawiera elementy do regulacji parametrów equalizera.
Na ostatnim wyświetlane jest widmo sygnału (wartości napięcia dla różnych pasm częstotliwości) – fotografia 3.
Do przełączania ekranów służy obiekt typu „Wybór”, leżący w prawym górnym rogu ekranu.
Do użycia dostępne są 22 pozycje pamięci. Obszar karty SD podzielony jest właśnie na tyle równych fragmentów, z których każdy umożliwia zapisanie około 30 min dźwięku. Całkowita wielkość zastosowanej karty wynosi 8 GB. Schemat przesyłania danych pomiędzy kartą a mikrokontrolerem pokazano na rysunku 8.
Zapisanie i modyfikacja programu
Moduł ewaluacyjny LP55S28EV wyposażony jest we wbudowany programator MCU-Link. Aby jednak uruchomić program na mikrokontrolerze, należy go najpierw wpisać do pamięci Flash. Potrzebne do tego jest oprogramowanie działające na komputerze PC – MCUXpresso IDE. Dzięki wspomnianemu środowisku możemy zaprogramować nasz moduł oraz dowolny procesor firmy NXP, jak również przeglądać i modyfikować kod naszego programu. Aby skompilować program, musimy zainstalować pakiet SDK odpowiedni dla płytki ewaluacyjnej z procesorem LPC55S28. Najwygodniejszym sposobem instalacji pakietów jest wejście na stronę startową środowiska IDE i wybranie odpowiedniej opcji. Najprościej ekran powitalny uruchomić za pomocą sekwencji menu: HELP/WELCOME, a następnie na ekranie, który się wyświetli, wybrać polecenie „Install SDK” – rysunek 9.
Aby przenieść nasz projekt do procesora płytki rozwojowej, trzeba wykonać kilka kroków.
- Dodać projekt do przestrzeni roboczej (rysunek 10).
- Z głównego menu wybrać ‘File’/’Open Project from File System’.
- Teraz możemy już zaprogramować płytkę lub uruchomić Debugger, wybierając odpowiednie pozycje z paska narzędzi. Jeśli chcemy dokonać zmian w kodzie, należy go powtórnie skompilować – patrz rysunek 11.
Tomasz Krogulski