Goto page 1, 2, 3  Next
		
			Atlantis
Guest
			Sat Sep 24, 2022 3:58 pm   
			Chciałem ostatnio popchnąć trochę do przodu jeden ze swoich poprzednich 
projektów - sprzętowe radio internetowe o którym pisałem już wcześniej, 
tylko tym razem w wersji ze zaktualizowaną częścią hardware'ową. 
Poprzednia wersja była tworzona na PIC32, teraz powoli chciałem 
przenieść go na STM32.
Większość softu właściwie już przeniosłem, teraz zostało najważniejsze - 
przeportowanie samej aplikacji odpowiedzialnej za odtwarzanie streamu z 
Internetu. W przypadku biblioteki MLA na PIC32 było to relatywnie 
proste. Socket sieciowy dysponuje buforem FIFO o zdefiniowanej 
pojemności - do niego trafiają dane przychodzące z serwera. Dane te 
pobieram i ładuję do bufora audio. Robię to jednak dopiero wtedy, gdy 
sterownik układu VS1003 stwierdzi, że dane są potrzebne.
W przypadku PIC32 było to relatywnie proste. Miałem kilka funkcji:
- TCPIsGetReady() - zwracała liczbę bajtów w buforze
- TCPGetArray() - funkcja zapisywała pod podany adres w pamięci 
określoną maksymalną liczbę bajtów z bufora. Zwracała liczbę bajtów, 
które w rzeczywistości udało się pobrać.
Sprawa była prosta - wystarczyło albo pobrać wszystkie dostępne dane, 
ale (jeśli było ich za dużo) tylko tyle, żeby wypełnić dostępne miejsce. 
W tym drugim przypadku nadwyżka pozostawała w buforze gniazda sieciowego 
i była sukcesywnie uzupełniania o kolejne przychodzące dane, które 
mogłem pobrać wtedy, gdy znów były potrzebne.
Widzę, że w przypadku lwIP (RAW API) sprawa nie jest już tak prosta. 
Zamiast tego muszę zarejestrować callback, który jest wołany za każdym 
razem, gdy przyjdą nowe dane. Callback otrzymuje w jednym z parametrów 
wskaźnik do struct ptr, w której mam m.in.
- void* paylod
- int len
- int tot_len
- struct pbuf* next
Istnieje więc możliwość, że wszystko co będę musiał zrobić to pobranie 
skopiowanie len bajtów spod adresu na który wskazuje payload. Istnieje 
jednak szansa, że danych jest więcej - wtedy tot_len > len i kolejnej 
porcji danych trzeba szukać w kolejnej strukturze, na którą wskazuje 
wskaźnik next.
Jeśli już zakończymy odczytywać dane, trzeba zawołać tcp_recved 
informując stos, że czekamy na kolejną paczkę. Tu jeszcze jest wszystko 
jasne.
Co jednak w sytuacji, gdy powiedzmy do zakończenia wypełniania bufora 
pozostało mi 100 bajtów, a w otrzymanej struct pbuf mam ich 500? Na 
PIC32 po prostu pobierałem 100, a reszta czekała na swoją kolej. W jaki 
sposób uzyskuje się podobny efekt na lwIP?
		
 
		
		
		
			Grzegorz Niemirowski
Guest
			Sat Sep 24, 2022 4:06 pm   
			Atlantis <marekw1986NOSPAM@wp.pl> napisał(a):
Quote:
W jaki sposób uzyskuje się podobny efekt na lwIP?
Użyć socketów zamiast męczyć się z RAW API?
-- 
Grzegorz Niemirowski
https://www.grzegorz.net/
		 
		
		
		
			Atlantis
Guest
			Sat Sep 24, 2022 5:28 pm   
			On 24.09.2022 18:06, Grzegorz Niemirowski wrote:
Quote:
Użyć socketów zamiast męczyć się z RAW API?
Sockety w lwIP chyba wymagają RTOS-a. Tak to jest zrealizowane na 
ESP8266/ESP32 i tam faktycznie nie ma problemu z odbieraniem danych. 
Tutaj jednak chciałem to zrobić bezpośrednio na krzemie, więc jestem 
skazany na RAW API.
		
 
		
		
		
			JDX
Guest
			Sun Sep 25, 2022 11:34 am   
			
		 
		
		
		
			Atlantis
Guest
			Sun Sep 25, 2022 6:08 pm   
			
		 
		
		
		
			Grzegorz Niemirowski
Guest
			Sun Sep 25, 2022 6:11 pm   
			Atlantis <marekw1986NOSPAM@wp.pl> napisał(a):
Quote:
Chcąc przenosić to na RTOS musiałbym część pracy zaczynać od nowa. Tak -
samo włączenie FreeRTOS-a to kwestia kilku kliknięć w STM32CubeMX, ale
potem jeszcze trzeba by dostosować inne części projektu do pracy pod tym
systemem.
Nie znam Twojego projektu, ale tego nie powinno być dużo. I tak mniej niż 
użerać się z RAW API.
Quote:
No i jednak o ile sam system nie zajmuje dużo miejsca we flashu, to już
jednak powoduje zwiększenie zapotrzebowania na RAM.
FreeRTOS także RAM-u nie potrzebuje dużo.
-- 
Grzegorz Niemirowski
https://www.grzegorz.net/
		 
		
		
		
			Guest
			Mon Sep 26, 2022 5:11 am   
			Atlantis <marekw1986NOSPAM@wp.pl> wrote:
Quote:
Chcia?em ostatnio popchn?? troch? do przodu jeden ze swoich poprzednich
projekt?w - sprz?towe radio internetowe o kt?rym pisa?em ju? wcze?niej,
tylko tym razem w wersji ze zaktualizowan? cz??ci? hardware'ow?.
Poprzednia wersja by?a tworzona na PIC32, teraz powoli chcia?em
przenie?? go na STM32.
Wi?kszo?? softu w?a?ciwie ju? przenios?em, teraz zosta?o najwa?niejsze -
przeportowanie samej aplikacji odpowiedzialnej za odtwarzanie streamu z
Internetu. W przypadku biblioteki MLA na PIC32 by?o to relatywnie
proste. Socket sieciowy dysponuje buforem FIFO o zdefiniowanej
pojemno?ci - do niego trafiaj? dane przychodz?ce z serwera. Dane te
pobieram i ?aduj? do bufora audio. Robi? to jednak dopiero wtedy, gdy
sterownik uk?adu VS1003 stwierdzi, ?e dane s? potrzebne.
W przypadku PIC32 by?o to relatywnie proste. Mia?em kilka funkcji:
- TCPIsGetReady() - zwraca?a liczb? bajt?w w buforze
- TCPGetArray() - funkcja zapisywa?a pod podany adres w pami?ci
okre?lon? maksymaln? liczb? bajt?w z bufora. Zwraca?a liczb? bajt?w,
kt?re w rzeczywisto?ci uda?o si? pobra?.
Sprawa by?a prosta - wystarczy?o albo pobra? wszystkie dost?pne dane,
ale (je?li by?o ich za du?o) tylko tyle, ?eby wype?ni? dost?pne miejsce.
W tym drugim przypadku nadwy?ka pozostawa?a w buforze gniazda sieciowego
i by?a sukcesywnie uzupe?niania o kolejne przychodz?ce dane, kt?re
mog?em pobra? wtedy, gdy zn?w by?y potrzebne.
Widz?, ?e w przypadku lwIP (RAW API) sprawa nie jest ju? tak prosta.
Zamiast tego musz? zarejestrowa? callback, kt?ry jest wo?any za ka?dym
razem, gdy przyjd? nowe dane. Callback otrzymuje w jednym z parametr?w
wska?nik do struct ptr, w kt?rej mam m.in.
- void* paylod
- int len
- int tot_len
- struct pbuf* next
Istnieje wi?c mo?liwo??, ?e wszystko co b?d? musia? zrobi? to pobranie
skopiowanie len bajt?w spod adresu na kt?ry wskazuje payload. Istnieje
jednak szansa, ?e danych jest wi?cej - wtedy tot_len > len i kolejnej
porcji danych trzeba szuka? w kolejnej strukturze, na kt?r? wskazuje
wska?nik next.
Je?li ju? zako?czymy odczytywa? dane, trzeba zawo?a? tcp_recved
informuj?c stos, ?e czekamy na kolejn? paczk?. Tu jeszcze jest wszystko
jasne.
Co jednak w sytuacji, gdy powiedzmy do zako?czenia wype?niania bufora
pozosta?o mi 100 bajt?w, a w otrzymanej struct pbuf mam ich 500? Na
PIC32 po prostu pobiera?em 100, a reszta czeka?a na swoj? kolej. W jaki
spos?b uzyskuje si? podobny efekt na lwIP?
Nie uzywalem lwIP ale zerknelem do dokumentacji.
Z dokumantacji lwIP wychodzi ze to ma byc "zero copy".  Czyli trzymasz
buforki tak dlugo jak sa potrzebne, a potem zwalniasz.  Jak cos
zostalo to sobie zapamietujesz polozenie bufora i uzywasz przy kolejnym
callbacku.  tcp_recved _nie_ zwalnia buforow, wyglada ze musisz to
robic oddzielnie przez pbuf_free.
-- 
                              Waldek Hebisch
		
 
		
		
		
			Atlantis
Guest
			Mon Sep 26, 2022 7:09 am   
			On 26.09.2022 05:11, antispam@math.uni.wroc.pl wrote:
Quote:
Nie uzywalem lwIP ale zerknelem do dokumentacji.
Z dokumantacji lwIP wychodzi ze to ma byc "zero copy".  Czyli trzymasz
buforki tak dlugo jak sa potrzebne, a potem zwalniasz.  Jak cos
zostalo to sobie zapamietujesz polozenie bufora i uzywasz przy kolejnym
callbacku.  tcp_recved _nie_ zwalnia buforow, wyglada ze musisz to
robic oddzielnie przez pbuf_free.
Ok, czyli chyba faktycznie najprościej będzie posłużyć się dodatkowym 
buforem pomocniczym, w którym trzymałbym nadwyżkę. Na dobrą sprawę można 
by nawet alokować te dane dynamicznie, na stercie. Wtedy po prostu przed 
zapisaniem kolejnej paczki sprawdzałoby się czy wskaźnik do bufora 
pomocniczego ma wartość inną niż NULL, zapisywało te dane do głównego 
bufora, zwalniało pomocniczy i przypisywało NULL do wskaźnika. Dopiero 
wtedy go głównego bufora szłaby paczka nowych danych, a jeśli coś by 
zostało, to nadwyżka trafiałaby do zaalokowanego na nowo bufora 
dynamicznego.
To chyba jednak bardziej eleganckie rozwiązanie niż opóźnianie 
zwalniania całej struktury pbuf do kolejnego callbacka.
Po prostu miałem nadzieję, że można to zrobić bez takich kombinacji, 
jedynie pobierając potrzebny w danej chwili kawałek bufora, jak w 
przypadku MLA na PIC32.
		
 
		
		
		
			Atlantis
Guest
			Mon Sep 26, 2022 3:33 pm   
			W sumie mam jeszcze inny pomysł. W układzie mam układ pamięci RAM na 
SPI. W późniejszej wersji softu planowałem go wykorzystać w roli nieco 
większego bufora audio, jednak chyba wykorzystam go jako bufor 
cykliczny, pośredniczący w komunikacji pomiędzy siecią a dekoderem MP3.
W callbackach lwIP będę po prostu ładował kolejne przychodzące dane do 
kolejnych adresów w tym układzie, a maszyna stanów obsługująca 
odtwarzanie będzie je sobie pobierała, uzupełniając swój własny, 
mniejszy bufor w pamięci mikrokontrolera. To powinno mi pozwolić na 
rozwiązanie kwestii przekazywania danych w sposób asynchroniczny.
		
 
		
		
		
			J.F
Guest
			Tue Sep 27, 2022 1:35 pm   
			On Sat, 24 Sep 2022 17:58:49 +0200, Atlantis wrote:
Quote:
Chciałem ostatnio popchnąć trochę do przodu jeden ze swoich poprzednich
projektów - sprzętowe radio internetowe o którym pisałem już wcześniej,
tylko tym razem w wersji ze zaktualizowaną częścią hardware'ową.
Poprzednia wersja była tworzona na PIC32, teraz powoli chciałem
przenieść go na STM32.
A tak swoja drogą - te radia działają na TCP ?
Bo chyba powinny na UDP ...
Kolejna sprawa - jak te radia działają?
Dawniej podawali jakies parametry do bezposredniej transmisji,
dzis wszystko pochowane. Wyswietl nasza strone 
www.
A radia (te niby "sprzetowe") jakos działają ... maja jakies serwery 
z listami parametrów ?
Quote:
Widzę, że w przypadku lwIP (RAW API) sprawa nie jest już tak prosta.
Zamiast tego muszę zarejestrować callback, który jest wołany za każdym
razem, gdy przyjdą nowe dane. Callback otrzymuje w jednym z parametrów
wskaźnik do struct ptr, w której mam m.in.
- void* paylod
- int len
- int tot_len
- struct pbuf* next
Istnieje więc możliwość, że wszystko co będę musiał zrobić to pobranie
skopiowanie len bajtów spod adresu na który wskazuje payload. Istnieje
jednak szansa, że danych jest więcej - wtedy tot_len > len i kolejnej
porcji danych trzeba szukać w kolejnej strukturze, na którą wskazuje
wskaźnik next.
Jeśli już zakończymy odczytywać dane, trzeba zawołać tcp_recved
informując stos, że czekamy na kolejną paczkę. Tu jeszcze jest wszystko
jasne.
Co jednak w sytuacji, gdy powiedzmy do zakończenia wypełniania bufora
pozostało mi 100 bajtów, a w otrzymanej struct pbuf mam ich 500? Na
PIC32 po prostu pobierałem 100, a reszta czekała na swoją kolej. W jaki
sposób uzyskuje się podobny efekt na lwIP?
Na moj gust, gdzies musisz sobie założyc bufor odpowiedniej dlugosci,
wpychac tam dane które przyszly, i potwierdzac otrzymanie, lub
poczekac jak sie bufor konczy ... aby zatrzymac transmisje.
J.
		
 
		
		
		
			Mateusz Viste
Guest
			Tue Sep 27, 2022 3:12 pm   
			2022-09-27 o 15:35 +0200, J.F napisał:
Quote:
A tak swoja drogą - te radia działają na TCP ?
Bo chyba powinny na UDP ...
Z reguły jednak TCP. Co gorsze - nierzadko z dodatkową warstwą TLS.
Przykłady streamów:
https://31.192.216.10/RMF2
https://radiovassiviere.ice.infomaniak.ch/radiovassiviere-128.aac
http://stream3.nadaje.com:9000/;stream/1
Quote:
Dawniej podawali jakies parametry do bezposredniej transmisji,
dzis wszystko pochowane. Wyswietl nasza strone 
www.
Da się znaleźć, np. tu:
https://online-radio.eu/
W domu mały NAS Linuksowy z VLC robi za radio, podaję mu URLe
skopiowane właśnie z powyższej strony.
Mateusz
		
 
		
		
		
			Cezar
Guest
			Tue Sep 27, 2022 3:22 pm   
			On 27/09/2022 14:35, J.F wrote:
Quote:
On Sat, 24 Sep 2022 17:58:49 +0200, Atlantis wrote:
Chciałem ostatnio popchnąć trochę do przodu jeden ze swoich poprzednich
projektów - sprzętowe radio internetowe o którym pisałem już wcześniej,
tylko tym razem w wersji ze zaktualizowaną częścią hardware'ową.
Poprzednia wersja była tworzona na PIC32, teraz powoli chciałem
przenieść go na STM32.
A tak swoja drogą - te radia działają na TCP ?
Bo chyba powinny na UDP ...
Wszysto idzie po TCP. UDP jest cięzkie do implementacji po stronie 
klienta bo trzeba ogarnąć:
- jitter
- packet loss
- out of order packets
Oczywiście da się to ogarnąc bo tak działa cały VoIP...
Myślę że łatwość implementacji klienta tutaj wygrała - większość 
streamów to TCP (HTTP)
Quote:
Kolejna sprawa - jak te radia działają?
Dawniej podawali jakies parametry do bezposredniej transmisji,
dzis wszystko pochowane. Wyswietl nasza strone 
www.
A radia (te niby "sprzetowe") jakos działają ... maja jakies serwery
z listami parametrów ?
 
		
		
		
			Atlantis
Guest
			Wed Sep 28, 2022 7:30 am   
			On 27.09.2022 15:35, J.F wrote:
Quote:
A tak swoja drogą - te radia działają na TCP ?
Działają na TCP, a konkretnie na zwyczajnym protokole HTTP. Otwierasz 
połączenie z serwerem i wysyłasz GET-a, prosząc o udostępnienie 
konkretnego streamu. W odpowiedzi dostajesz odpowiedź i nagłówki. Jeśli 
jest to 200 OK, możesz zacząć odbierać i dekodować przychodzące dane 
audio. Oczywiście trzeba też obsłużyć inne sytuacje, jak np. 
przekierowanie pod inny adres.
Quote:
Bo chyba powinny na UDP ...
Po co? Strumień audio nie potrzebuje niskiej latencji - wszystko i tak 
jest buforowane po stronie serwera. Można się o tym dość łatwo przekonać 
włączając jednocześnie dowolne radio FM i jego sieciowy odpowiednik, 
albo jeszcze lepiej - Jedynkę na falach długich i tę samą stację 
nadawaną on-line.
Quote:
Kolejna sprawa - jak te radia działają?
Dawniej podawali jakies parametry do bezposredniej transmisji,
dzis wszystko pochowane. Wyswietl nasza strone 
www.
Niektóre stacje nadal podają bezpośrednie URL-e do swoich streamów. Jest 
też trochę różnych zestawień w Internecie. W przypadku stacji 
narzucających własną aplikację na stronie i tak bardzo często pod spodem 
mamy zwyczajne połączenie HTTP - wtedy wystarczy wyłuskać adres 
analizując ruch, np. za pomocą narzędzi deweloperskich Chrome'a.
Quote:
A radia (te niby "sprzetowe") jakos działają ... maja jakies serwery
z listami parametrów ?
Tak. I to jest właśnie głównym powodem dla którego zabrałem się za ten 
projekt. Wkurzał mnie fakt, że większość dostępnych komercyjnie 
rozwiązań będzie działała tak długo, jak długo producent raczy 
utrzymywać infrastrukturę. Tutaj sam wpisuję URL-e stacji, które chcę 
słuchać.
Quote:
Na moj gust, gdzies musisz sobie założyc bufor odpowiedniej dlugosci,
wpychac tam dane które przyszly, i potwierdzac otrzymanie, lub
poczekac jak sie bufor konczy ... aby zatrzymac transmisje.
No właśnie tutaj jak na razie rozbijam się o szczegóły. W przypadku 
stosu MLA z PIC32 po prostu pobierałem sobie z bufora odbiorczego tyle 
danych, ile w danym momencie potrzebowałem. Stos robił pod spodem całą 
resztę - jeśli w buforze było miejsce, prosił serwer o więcej danych. 
Efekt był taki, że dekoder MP3 z automatu narzucał prędkość transmisji i 
nawet przy stosunkowo niewielkich buforach wszystko działało płynnie.
Tutaj sprawa jest trochę bardziej skomplikowana. Dane nie są buforowane 
w taki sposób i nie mogę po prostu pobrać dowolnej ilości w dowolnym 
momencie. Jeśli zostanie wywołany callback odbiorczy, mam obowiązek 
odebrać całą paczkę, zwolnić pamięć i wywołać tcp_recved. Jednak z tego 
co rozumiem ta ostatnia funkcja jedynie zwiększa rozmiar okna 
odbiorczego, więc nawet pomimo braku jej wywołania nie mam gwarancji, że 
jeszcze przez chwilę nie przyjdą kolejne callbacki - być może uda mi się 
uzyskać taki efekt odpowiednio manipulując ustawieniami stosu.
Przerobiłem wczoraj nieco swoją aplikację, implementując bufor cykliczny 
do którego trafiają dane ze strumienia. Serwer jednak wysyła je nieco 
szybciej niż wynikałoby to z bitrate'u strumienia audio - ma to sens, bo 
nadmiarowe dane w normalnych warunkach mogą zostać użyte do uzupełniania 
bufora. Tak więc jeśli po prostu odbieram dane, wrzucam je do bufora i 
potwierdzam otrzymanie, to dość szybko dochodzi do przepełnienia bufora 
- dźwięk jest, ale postrzępiony. Próbowałem wywoływać tcp_recved() w 
innym miejscu dopiero wtedy, gdy w buforze była dostatecznie dużo 
wolnego miejsca, jednak jak na razie nie udało mi się uzyskać poprawnego 
działania. Będę jeszcze eksperymentował.
Eksperymenty z zewnętrzną pamięcią SPI RAM 128 kB jak na razie też nie 
przyniosły idealnych rezultatów. Nawet przy maksymalnej
dostępnej prędkości (18 MHz) wydaje się ona zwyczajnie zbyt wolna. 
Trochę mnie to zaskoczyło, bo karta SD przy dwa razy wolniejszej 
transmisji spokojnie wyrabiała z dostarczaniem danych z pliku MP3. Z 
drugiej strony jednak tutaj mam operacje odczytu i zapisu, występujące 
naprzemiennie w krótkich odstępach czasu.
Zaczynam zastanawiać się czy faktycznie dobrym pomysłem nie będzie 
zastosowanie FreeRTOS-a i socketów. Nie wiem tylko czy problemem nie 
będzie niewielka ilość RAM-u mikrokontrolerze (64kB).
		
 
		
		
		
			Atlantis
Guest
			Wed Sep 28, 2022 7:35 am   
			On 27.09.2022 17:12, Mateusz Viste wrote:
Quote:
W domu mały NAS Linuksowy z VLC robi za radio, podaję mu URLe
skopiowane właśnie z powyższej strony.
Moje pierwsze podejście do tematu autonomicznego radia internetowego 
polegało właśnie na wykorzystaniu Raspberry Pi (Zero) z zewnętrznym 
DAC-iem i standardowym oprogramowaniem do odtwarzania audio (MPD) pod 
spodem. Otwierało to sporo dodatkowych możliwości, jednak trochę 
absurdalny wydawał mi się fakt, że urządzenie musi najpierw załadować i 
uruchomić cały system operacyjny, żeby zacząć odbierać stację. W celach 
edukacyjnych postanowiłem więc złożyć wersję na mikrokontrolerze. 
 
		 
		
		
		
			Mateusz Viste
Guest
			Wed Sep 28, 2022 8:52 am   
			2022-09-28 o 09:35 +0200, Atlantis napisał:
Quote:
On 27.09.2022 17:12, Mateusz Viste wrote:
W domu mały NAS Linuksowy z VLC robi za radio, podaję mu URLe
skopiowane właśnie z powyższej strony.
Moje pierwsze podejście do tematu autonomicznego radia internetowego
polegało właśnie na wykorzystaniu Raspberry Pi (Zero) z zewnętrznym
DAC-iem i standardowym oprogramowaniem do odtwarzania audio (MPD) pod
spodem. Otwierało to sporo dodatkowych możliwości, jednak trochę
absurdalny wydawał mi się fakt, że urządzenie musi najpierw załadować
i uruchomić cały system operacyjny, żeby zacząć odbierać stację. W
celach edukacyjnych postanowiłem więc złożyć wersję na
mikrokontrolerze. 
 
Chwalebnie... i ambitnie - bo trzeba samemu obsłużyć TCP, HTTP,
kilka popularnych kodeków, TLS... sporo warstw do przebicia.
Niemniej doceniam i rozumiem myśl. Też mnie denerwuje, że po włączeniu
"radia" muszę czekać niemal minutę na dźwięk.
Mateusz
		
 
		
		
	Goto page 1, 2, 3  Next