-
1. Data: 2020-06-11 11:44:58
Temat: Działająca biblioteka C do VS1003?
Od: Atlantis <m...@w...pl>
Próbuję właśnie uruchomić urządzenie posiadające sprzętowy dekoder MP3
VS1003. Urządzenie wykonałem w dwóch wariantach: z układem
PIC32MX795F512L oraz szesnastobitowym układem PIC24 (zacząłem od tego
drugiego, ale w międzyczasie postanowiłem przenieść projekt na układ 32
bitowy). Ma to znaczenie o tyle, że w obydwu wersjach kod zachowuje się
tak samo, czyli raczej można wykluczyć problem wynikający ze specyfiki
sprzętowej, np. pin zajęty przez jakieś układ peryferyjny.
Płytki zostały zaprojektowane w oparciu schematy z PDF-ów producenta. W
obydwu wersjach schemat jest identyczny, a ukłąd ścieżek prawie
identyczny. Przyglądałem się wielokrotnie i błędów w połączeniach nie
dostrzegam.
Od strony programowej próbowałem posłużyć się tym kodem z STM32
znalezionym na GitHubie, portując go na PIC24/PIC32.
https://github.com/digao6975/stm32-player/tree/maste
r/src
Dekoder częściowo działa. W pętli głównej czytam do bufora po kawałku
plik MP3, a potem wysyłam te dane do układu. Przed wysłaniem każdego
kolejnego bajtu czekam w pętli na ustawienie linii DREQ (tymczasowa
prowizorka, lepiej byłoby to zrobić na przerwaniach). Po dotarciu do
końca pliku zaczynam go czytać od nowa.
Dźwięk jest odtwarzany, ale najlepsze co uzyskałem to "ćwierkający"
efekt. Co ciekawe najlepsze efekty uzyskałem przy małym buforze na
fragmenty danych z pliku (zaledwie 16 bitów). Gdy ustawię więcej,
"ćwierkanie" staje się szybsze przechodzi w szum albo wręcz nastaje
cisza. Efekty nie są też w 100% powtarzalne, nie zawsze odtwarzanie chce
się rozpocząć.
Co najdziwniejsze, przy większych rozmiarach bufora program szybciej
dociera do końca pliku, jakby linia DREQ nic nie dawała - jej
konfigurację po stronie MPU sprawdzałem wiele razy i wszystko wydaje się
być ok.
W tej chwili skończyły mi się pomysły i jeśli nic innego nie przyjdzie
mi do głowy, przeportuję popularną bibliotekę z Arduino, napisaną w C++.
Nie chciałbym jednak wyważać otwartych drzwi, jeśli istnieje jakaś dobra
biblioteka w C, którą można łatwo przenosić między rodzinami
mikrokontrolerów, albo która ma wersję dla PIC32.
-
2. Data: 2020-06-11 15:49:14
Temat: Re: Działająca biblioteka C do VS1003?
Od: Marek <f...@f...com>
On Thu, 11 Jun 2020 11:44:58 +0200, Atlantis <m...@w...pl>
wrote:
> plik MP3, a potem wysyłam te dane do układu. Przed wysłaniem każdego
> kolejnego bajtu czekam w pętli na ustawienie linii DREQ
Dlaczego? Stan wysoki na DREQ zezwala przesłanie bez sprawdzania
stanu linii DREQ min. 32 bajtów kolejnych danych ze strumienia.
Jeśli po wysłaniu każdego bajtu sprawdzasz stan linii DREQ może to
być za wolne i powodujesz buffer underrun dekodera.
Oczywiście może być jeszcze problem, że przesyłane dane są
porozrywane, gdzieś przy czytaniu z pliku gubisz bajty lub nie
przesyłasz całego odczytanego z pliku bufora do vs'a tylko jakiś
jego fragment.
--
Marek
-
3. Data: 2020-06-11 15:53:42
Temat: Re: Działająca biblioteka C do VS1003?
Od: Marek <f...@f...com>
On Thu, 11 Jun 2020 11:44:58 +0200, Atlantis <m...@w...pl>
wrote:
> Co najdziwniejsze, przy większych rozmiarach bufora program szybciej
> dociera do końca pliku, jakby linia DREQ nic nie dawała - jej
Taki efekt występuje gdy do vs'a przesyłasz popsuty strumień i vs
szybko "przewija" do przodu szukając początek prawidłowej ramki,
wtedy DREQ rzadko robi się low bo nie ma pełnego dekodowania
strumienia.
--
Marek
-
4. Data: 2020-06-11 17:59:51
Temat: Re: Działająca biblioteka C do VS1003?
Od: Atlantis <m...@w...pl>
On 11.06.2020 15:53, Marek wrote:
> Taki efekt występuje gdy do vs'a przesyłasz popsuty strumień i vs szybko
> "przewija" do przodu szukając początek prawidłowej ramki, wtedy DREQ
> rzadko robi się low bo nie ma pełnego dekodowania strumienia.
Dokładnie tak to właśnie brzmi - jakby strumień dźwiękowy co chwilę
przeskakiwał o chwilę do przodu, z charakterystycznym "ćwierknięciem".
Poświęciłem jeszcze chwilę czasu na przeportowanie teb biblioteki z Arduino:
https://github.com/andykarpov/VS1003
Efekt jest dokładnie taki sam, więc to ja muszę robić coś źle.
Kod odpowiedzialny za odczyt i przesyłanie ich do ukłądu wygląda
następująco:
res = f_read(&fsrc, buffer, sizeof(buffer), &br);
if(res == FR_OK) {
VS1003_playChunk(buffer, br);
}
//End of file
if(br == 0) {
res = f_lseek(&fsrc, 0);
if (res != FR_OK) printf("f_lseek ERROR\r\n");
else printf("f_lseek OK\r\n");
}
Kod funkcji VS1003_playChubk() można znaleźć tutaj, ja po prostu
przeniosłem go z C na C++.
https://github.com/andykarpov/VS1003/blob/master/VS1
003.cpp
Eksperymentuję też z rozmiarami bufora i odstępami czasowymi pomiędzy
kolejnymi odczytami z pliku i zapisami do VS1003. Udaje mi się uzyskać
lepsze i gorsze efekty, ale za każdym razem są one dalekie od ideału.
Może robię coś nie tak i plik należy czytać w specyficzny sposób? Albo
nie wszystkie formaty MP3 są kompatybilne z tym układem? Albo trzeba
odczytać metadane i w oparciu o nie skonfigurować układ?
-
5. Data: 2020-06-11 19:54:34
Temat: Re: Działająca biblioteka C do VS1003?
Od: Atlantis <m...@w...pl>
Chyba, że ten układ potrzebuje bardziej zaawansowanego buforowania po
stronie MCU? Coś na zasadzie dwóch buforów: jeden aktywny i drugi
zapasowy. Z pierwszego pobierane są dane paczkami po 32 bajty w momencie
ustawienia pinu DREQ, a drugi czeka na swoją kolej. Gdy pierwszy się
opróżni, drugi jest oznaczany jako aktywny, a pierwszy wypełnia się
kolejną porcją danych z pliku.
-
6. Data: 2020-06-11 20:03:37
Temat: Re: Działająca biblioteka C do VS1003?
Od: Marek <f...@f...com>
On Thu, 11 Jun 2020 17:59:51 +0200, Atlantis <m...@w...pl>
wrote:
> Może robię coś nie tak i plik należy czytać w specyficzny sposób?
Rozumiem, że ten cytowany kod jest w pętli?
Jedyne co mi przychodzi do głowy to, że pin DREQ nie jest prawidłowo
skonfigurowany w mcu (odczyt stanu nie jest prawidlowy: w
rzeczywistości vs ma pełny bufor a funkcja i tak mu wysyła dane).
> Alno nie wszystkie formaty MP3 są kompatybilne z tym układem?
Kompatybilność masz w datasheet vs'a, ale raczej musiałby to być dość
skrajny przypadek pliku MP3.
>Albo trzeba
> odczytać metadane i w oparciu o nie skonfigurować układ?
Nie, vs robi to automatycznie czytając format z każdej ramki MPEG
podczas feedu, stąd możesz plik zacząć nawet odtwarzać ze środka.
Natomiast w przypadku formatów pcm np. wav musisz przesłać plik od
początku by vs z headera pliku odczytał sobie wpierw metadane
(częstotliwość próbkowania, liczna kanałów, liczbę bitów/próbkę itp.)
i o ile pamiętam jeśli chce się przerwać odtwarzanie wav przed jego
końcem i zacząć odtwarzać inny plik/format to trzeba ten koniec
odpowiednio zasygnalizować zapisem w specjalnym rejestrze. W nagłówku
wav jest liczba sampli stąd vs wie kiedy plik się "kończy" i należy
od nowa analizować prZycjodzavy strumień by go zidentyfikować
(wav/MP3 itp).
--
Marek
-
7. Data: 2020-06-11 20:10:46
Temat: Re: Działająca biblioteka C do VS1003?
Od: Marek <f...@f...com>
On Thu, 11 Jun 2020 19:54:34 +0200, Atlantis <m...@w...pl>
wrote:
> Chyba, że ten układ potrzebuje bardziej zaawansowanego buforowania
> po
> stronie MCU? Coś na zasadzie dwóch buforów: jeden aktywny i drugi
> zapasowy. Z pierwszego pobierane są dane paczkami po 32 bajty w
> momencie
Bufor vs'a to ok 8kB, gdy DREQ jest high oznacza to, że minimum 32
bajty można przesłać ale może to być więcej. Sprawdź czy ma pewno
wyrabia się mcu (nie ma sytuacji, że dreq jest cały czas high) oraz
czy nie występuje stacja przeciwna - mcu przelewa vs'a danymi bo
widzi dreq cały czas high (zle skonfigurowany pin, brak połączenia
elektrycznego z vs).
--
Marek
-
8. Data: 2020-06-11 23:30:48
Temat: Re: Działająca biblioteka C do VS1003?
Od: Atlantis <m...@w...pl>
On 11.06.2020 20:03, Marek wrote:
> Rozumiem, że ten cytowany kod jest w pętli?
Tak, kod jest uruchamiany w pętli głównej.
> Jedyne co mi przychodzi do głowy to, że pin DREQ nie jest prawidłowo
> skonfigurowany w mcu (odczyt stanu nie jest prawidlowy: w rzeczywistości
> vs ma pełny bufor a funkcja i tak mu wysyła dane).
To była pierwsza rzecz, jaka przyszła mi do głowy. Tyle tylko, że:
1) Sprawdziłem kilka razy. Na najnowszej wersji płytki (tej z PIC32)
DREQ to RC1. Konfiguracja tego pinu wygląda u mnie następująco:
#define VS_DREQ_TRIS TRISCbits.TRISC1
#define VS_DREQ_PIN PORTCbits.RC1
VS_DREQ_TRIS = 1;
2) Pin RC1 ma tylko jedną alternatywną funkcją jest T2CK. Nigdzie w tym
projekcie nie wykorzystuję Timera2, a już na pewno nie z zewnętrznym
taktowaniem.
3) Bliźniaczy problem występuje także na płytce z PIC24, a tam piny są
inne. Musiałem to uwzględnić przenosząc kod i byłoby mało prawdopodobne,
gdybym robiąc to popełnił identyczny błąd. Kod z drugiej płytki też
sprawdziłem parokrotnie.
4) Z linii DREQ korzysta także funkcja inicjująca VS1003, a ona
przechodzi prawidłowo.
Spróbowałem jeszcze następującego kodu w pętli głównej:
while (VS_DREQ_PIN) {
br = 0;
res = f_read(&fsrc, buffer, 32, &br);
if (res == FR_OK && br) {
data_mode_on();
for (i=0; i<br; i++) VS1003_SPI_transfer(buffer[i]);
data_mode_off();
}
if (br == 0) {
VS1003_stopSong();
VS1003_startSong();
f_lseek(&fsrc, 0);
}
}
Efektem jest świergot w słuchawkach, jakby dźwięk byl bardzo szybko
przewijany na podglądzie. Potem pojawia się terkot, po którym następuje
cisza.
-
9. Data: 2020-06-12 10:32:55
Temat: Re: Działająca biblioteka C do VS1003?
Od: Atlantis <m...@w...pl>
Ok, przyczyna się znalazła i okazała się być całkowicie sprzętową - pin
TEST był niepodłączony do VCC. Takie rzeczy mogłyby mieć swoją drogą
wewnętrzne pull-upy...
-
10. Data: 2020-06-12 10:53:08
Temat: Re: Działająca biblioteka C do VS1003?
Od: Marek <f...@f...com>
On Thu, 11 Jun 2020 23:30:48 +0200, Atlantis <m...@w...pl>
wrote:
> while (VS_DREQ_PIN) {
> br = 0;
> res = f_read(&fsrc, buffer, 32, &br);
> if (res == FR_OK && br) {
> data_mode_on();
> for (i=0; i<br; i++) VS1003_SPI_transfer(buffer[i]);
> data_mode_off();
> }
> if (br == 0) {
> VS1003_stopSong();
> VS1003_startSong();
> f_lseek(&fsrc, 0);
> }
Ten kod nie jest optymalny dla vs'a.
Jak dreq jest wysoki to dopiero robisz fread, a to już za późno. Na
DREQ high musisz już mieć gotowy odczytany z sd bufor w ram a nie
dopiero go czytać z sd. Sekwencja powinna wyglądać tak: najpierw
czytasz pierwszy bufor, wysyłasz go do vs'a tak długo aż
zasygnalizuje DREQ low, dopiero wtedy uzupelniasz/czytasz następny
bufor z sd i sprawdzasz przed jego wysłaniem czy dreq jest high.
Bufor w ram na dane (typu FIFO) musisz mieć min 10kB (musi być
większy niż bufor vs'a) bo inaczej pierwsze wypełnienie bufora vs'a
będzie zbyt płytkie, co nie da czasu na odczyt kolejnej porcji danych
(fread możesz robić tylko wtedy gdy w buforze vs'a jest wystarczająco
dużo danych).
Inaczej zawsze będziesz miał zawsze nieczyste odtwarzanie z różnymi
dziwnymi efektami.
W pętli czytania zrób też tymczasowy printf gdy DREQ jest low, by się
upewnić czy faktycznie mcu widzi ten stan.
Jeszcze jest kwestia SPI, czy driver SPI vs'a na pewno czeka na
przesłanie całego bufora SPI (bufora słowa SPI) przed wysłaniem
następnego słowa?
{
--
Marek