Modułowy odtwarzacz MP3 (2)
Praktyczne testy
Ponieważ napięcia zasilające i interfejs sterujący jest taki sam jak w module YX5300, zastosowałem taki sam układ testowy z modułem Microstick II, wyświetlaczem OLED i enkoderem. Dokładnie w taki sam sposób został skonfigurowany układ UART oraz obsługa wyświetlacza i enkodera.
Odtwarzanie
Funkcje komend zapisują bufor BufCmd kolejnymi bajtami przesyłanymi przez UART do modułu. Na listingu 7 jest pokazana funkcja PlayMp3() wysyłająca komendę PLAY o kodzie 01h.
void PlayMp3(void) { BufCmd[0]=0x7e; //bajt startu BufCmd[1]=0x02; //bajt liczby danych BufCmd[2]=0x01; //bajt komendy PLAY BufCmd[3]=0xef; //bajt stopu DispTxt(0,0,"PLAY TRACK ", 16,1); RefreshRAM(); WriteCmdMp3(BufCmd,4); }
Listing 7. Komenda PLAY
Najpierw do bufora BufCmd[] są zapisywane bajty: startu, ilości danych, kodu komendy i stopu. Potem na ekranie wyświetlacza jest wyświetlana informacja o uruchomieniu odtwarzania „PLAY TRACK” i wywoływana jest funkcja WriteCmdMp3() z argumentami: wskaźnikiem na bufor z bajtami do wysłania i ilością danych do wysłania.
uint8_t WriteCmdMp3(uint8_t *buf,uint8_t len){ uint8_t i,status; uint8_t bufor[10]; for(i=0;i<len;i++) //wysłanie zadanej liczby bajtów UART1_Write(buf[i]); Delay_ms(50); //odczekanie na odpowiedź status=UART1_TransferStatusGet(); if((status&2)==2) //czy odebrano jakieś znaki { UART1_ReadBuffer(bufor,8);//zapisanie bufora odebranymi znakami if(bufor[0]=='O'&&bufor[1]=='K')//czy komenda prawidłowa {DispTxt(0,20,"ok!", 16,1); RefreshRAM(); return(0);} if(bufor[0]=='E')//czy komenda nie rozpoznana { DispTxt(0,20,"err", 16,1); RefreshRAM(); return(1);} else { DispTxt(0,20,"NACK", 16,1);//odebrano inne znaki (nie potwierdzenie) RefreshRAM(); return(2);} } DispTxt(0,20,"NOE", 16,1);//nie odebrano żadnych znaków RefreshRAM(); return(3); }
Listing 8. Funkcja wysłania bajtów komendy
Po wysłaniu bajtów komendy program odczekuje 50 ms na odebranie potwierdzenia. To dużo więcej niż potrzeba. Każdy bajt to 10 bitów przesyłanych z prędkością 9600 bitów na sekundę. Czyli przesłanie jednego bajtu trwa 1/9600*10=1,04 ms . Trzy bajty potwierdzenia to ok 3 ms, 4 bajty odpowiedzi po komendach o status modułu to ok 4ms . Jednak przy obserwowaniu transmisji na oscyloskopie widać było, że moduł nie odsyła odpowiedzi natychmiast.
Program sprawdza czy bajty zostały odebrane testując status transmisji funkcją UART1_TransferStatusGet();. W innych implementacjach użytkownik musi sobie zapewnić możliwość odbierania bajtów i sygnalizację odebrania.
Po odebraniu odpowiedzi następuje analiza odebranych znaków. Wykrycie znaków „OK” oznacza prawidłowo odebrana komendę, wykrycie znaku „E” oznacza niezidentyfikowane polecenie, wykrycie innych znaków jest sygnalizowane brakiem potwierdzenia NACK. Komendy PAUZA i STOP zostały pokazane na listingu 9.
uint8_t PauseMp3(void) { BufCmd[0]=0x7e; BufCmd[1]=0x02; BufCmd[2]=0x02; BufCmd[3]=0xef; DispTxt(0,0,"PAUSE ", 16,1); RefreshRAM(); return(WriteCmdMp3(BufCmd,4)); } uint8_t StopMp3(void) { BufCmd[0]=0x7e; BufCmd[1]=0x02; BufCmd[2]=0x0e; BufCmd[3]=0xef; return(WriteCmdMp3(BufCmd,4)); }
Listing 9. Komedy PAUZA i STOP
Głośność
Z zestawu komend konfigurujących najczęściej używana będzie komenda ustawiania głośności – listing 10.
uint8_t VolMp3(uint8_t vol){ BufCmd[0]=0x7e; BufCmd[1]=0x03;//liczba bajtów BufCmd[2]=0x31;//kod komendy BufCmd[3]=vol; //ustawiana wartość BufCmd[4]=0xef;//bajt stopu return(WriteCmdMp3(BufCmd,5)); }
Listing 10. Ustawianie głośności
W tym przypadku po kodzie komendy jest wysyłany jeden bajt argumentu mogący mieć wartość z zakresu 0…30.
Wybór utworu
Do przedstawionych wyżej komend trzeba dołączyć komendę wyboru pliku na podstawie numeru katalogu i numeru pliku (listing 11) i można zbudować prosty ale funkcjonalny odtwarzacz mp3.
uint8_t PlayTrackMP3(uint8_t fld,uint8_t plk ){ BufCmd[0]=0x7e; BufCmd[1]=0x04; BufCmd[2]=0x42;//funkcja wybierz folder i plik BufCmd[3]=fld;//numer folderu BufCmd[4]=plk;//numer pliku BufCmd[5]=0xef;//bajt stopu DispTxt(0,0,"Play ", 16,1); DispHex(fld,40,0,16);//wyświetl numer folderu DispHex(plk,60,0,16);//wyświetl numer pliku RefreshRAM(); return(WriteCmdMp3(BufCmd,6)); }
Listing 11. Funkcja wyboru pliku do odtwarzania
Podsumowanie
Pokazane w artykule moduły odtwarzacz MP3 są głównie przeznaczone do zastosowań przemysłowych. Zbudowanie „konsumenckiego” odtwarzacza plików muzycznych mp3 jest również możliwe, ale kłopotliwe. Przeszkodą mogą być narzucone nazwy plików oraz brak możliwości odczytania rzeczywistej nazwy pliku będącej jednocześnie nazwą utworu. Żeby skutecznie wybierać utwory do odtwarzania trzeba za każdym razem zmieniać ich nazwę, tak by zaczynała się od trzycyfrowej liczby.
Ta niedogodność jest jednocześnie zaletą kiedy chcemy wybierać komunikaty głosowe nie na podstawie dowolnej nazwy składającej się ze znaków ASCII, ale na podstawie wartości cyfrowej. Takie rozwiązanie bardzo ułatwia odtwarzanie komunikatów zależnie od jakiejś wartości, na przykład napięcia, mocy, temperatury, itp.
Podczas testów okazało się, że oba moduły radzą sobie z podanymi częstotliwościami próbkowania, ale gorzej jest z przepływnością. Na początku przez zupełny przypadek umieściłem na nośniku pliki z przepływnością 320kb/s. Moduł YX5300 jakoś sobie poradził. Odtwarzacz MP3 z interfejsem USB odtwarzał materiał dźwiękowy ze sporym poziomem szumów i chwilowymi zniekształceniami. Widać było ,że wbudowany mikrokontroler nie bardzo radził sobie z takim plikiem. Materiał nagrany w 64 kB/s i 128 kb/s był odtwarzany z dobrą jakością. Zważywszy na przeznaczenie modułów, trudno to zakwalifikować jako wadę, gdyż przepływność 128 kb/s daje już bardzo dobrą jakość.
Na pewno ze względu na bardzo korzystny stosunek cena/możliwości warto się zainteresować zastosowaniem tego rozwiązania we własnych konstrukcjach. Trzeba jednak pamiętać, że problemem może być stabilność dostaw.
Tomasz Jabłoński