logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Atmega32A - Konfiguracja PWM do odtwarzania dźwięku

szpada89 07 Sty 2013 19:50 5172 26
REKLAMA
  • #1 11756440
    szpada89
    Poziom 9  
    Witam forumowiczów :D! Tworze projekt na zaliczenie - prostą perkusje elektroniczną, która posiada 12 przycisków, czytnik kart SD i wyjście PWM podpięte przez wzmacniacze do gniazda jack. Wszystko do momentu odtwarzania dźwięku działa poprawnie - wartości z pliku czyta prawidłowo (przetestowane na diodzie). Problem pojawia się gdy zaczynam odtwarzać dźwięki. Wydaje mi się, że o czymś zapomniałem konfigurując PWM. Próbowałem już wielu ustawień, starałem się uzyskać 22050Hz ustawiając odpowiedni prescaler, wartość TOP (ICR1) ale efekt jest mizerny - słychać brzęczenie i trzaski.

    Format Wave

    Atmega32A - Konfiguracja PWM do odtwarzania dźwięku

    Schemat układu
    Atmega32A - Konfiguracja PWM do odtwarzania dźwięku

    Inspiracja do tak stworzonego audio
    http://www.gaw.ru/pdf/Atmel/app/at45_to_avr.pdf (strona 5)

    Program
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Działanie programu
    Tablica danych z pliku wave jest wyciągana zewnętrznym programem i zapisywana do pliku txt w formacie :
    001 dla 1 058 dla 58 i tak dalej.
    Po naciśnięciu odpowiedniego przycisku otwierany jest plik .txt z karty SD i ładowane są wartości do chara, potem przesuwane o 48 i mnożone w zależności od pozycji przez 100, 10 albo 1. Tak uzyskana próbka ląduje na OCR1B.

    Ustawienia SPI
    SPCR = 0x50;
    SPSR = 0x01;
    PORTB = 0xb0;
    DDRB = 0xbf;


    Fuse bity
    Atmega32A - Konfiguracja PWM do odtwarzania dźwięku

    Atmega została przyśpieszona do 8Mhz aby odczyt z karty SD nie trwał tak długo (ponad sekunde przy standardowym ustawieniu 1Mhz).

    ....................
    Ok PWM wydaje się być ustawione poprawnie. Teraz pozostaje kwestia odtwarzania. Stworzyłem 2 bufory do których ładowane są wartości z karty SD. Chce aby program działał w ten sposób :
    czytam dane do 2 buforów i następnie odtwarzam dane z jednego bufora, kiedy się skończą zaczynam czytać z drugiego a pierwszy zapełniam i tak w kółko aż do wyczerpania danych. Niezbędne będzie wykorzystanie przerwania podczas odtwarzania ale nie mam pojęcia jak to ustawić aby działało poprawnie.
  • REKLAMA
  • #2 11763227
    WOBI
    Poziom 19  
    tu masz trochę opisane w tym temacie, wprawdzie bascom ale zasada i ustawienie PWM są tam gotowe do podglądnięcia, przy okazji troche teorii, warto poczytać.

    Należy pamiętać że częstotliwość kwarcu jest ściśle powiązana z częstotliwościa PWM a to dalej powiązane jest w częstotliwościa wystawiania próbek czyli z próbkowaniem.
    Próbkowanie to nie to samo co częstotliwość PWM, próbkowanie to zmiana wartości wypełnienia PWM co określony czas np 22,05kHz wartościa pobraną z pliku.

    16MHz można uzyskać próbki 32khz / 16khz / 8 khz / 4khz
    11,0952MHz uzyskujemy 22,05kHz / 11,025KHz / 5,5125kHz

    a wynika to z matematyki = częstotliwosc liczymy dla 8 bit pwm fosc/510 dla prescale =1
    czyli dla 16MHz / 510 = 31,37kHz / dzielnik (2) = 15,68kHz blisko 16kHz

    Wzór dla prawidłowego wyliczenia częstotliwości kwarcu to (uwaga na jednostki!!!)
    dla dzielnika przez R=2 programowego Fosc(MHz= Fprób(kHz) * (0,51 * R)

    dla próbki 16kHz * (0,51 * 2) = 16,32MHz taki powinien być prawidłowy kwarc, ale przyjmujemy przybliżenie i zastosowano popularny kwarc 16MHz.

    Dla kwarcu 24MHz uzyskamy częstotliwość PWM 24 / 510 = 47,0588kHz czyli używając prograwowego dzielnika 2, 3 lub 4 uzyskamy odpowiednio
    23,52 kHz, 15,58 kHz i 11,76 kHz
    i ważne jeszcze BUFor im szybsze próbkowanie tym bufor powiniem byc wiekszy, robiłem próby i dla 16khz wystarcza 256bajtów dla 32khz powiniem byc 512bajtów.
  • #3 11765444
    szpada89
    Poziom 9  
    PWM skonfigurowałem w oparciu datasheet Atmegi32 oraz o kalkulator (http://www.et06.dk/atmega_timers/), który mi wyliczył takie wartości :
    Atmega32A - Konfiguracja PWM do odtwarzania dźwięku

    PWM zostało więc ustawione następująco :

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jeśli chodzi o program to stworzyłem sobie 2 bufory, do których zapisuje porcje danych z karty SD a następnie odczytuje na zmianę. Co przerwanie (Timmer OverFlow) wystawiam na OCR1B wartość z aktualnie aktywnego rejestru. Następnie inkrementuje pozycje w buforze, jeśli doszedł do końca to wracam na początek (position = 0) i zamieniam bufory. Oto kod programu:

    Deklaracja buforów
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Przerwanie
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Funckja do zmiany flag buforow
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Czytanie danych
    Liczba próbek wprowadzona na stałe do zmiennej length (220500 próbek zapisanych do pliku jako 3 znaki co daje 661500 znaków).

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Niestety gdzieś popełniam błąd bo na wyjściu dostaje tylko trzask potem chwile pisku i cisza. Zastanawiam się czy może być tak że odczyt danych trwa zbyt długo i dlatego to się sypie :(
    Z góry dziękuje za wszelką pomoc.
  • #4 11765737
    ZbeeGin
    Poziom 39  
    szpada89 napisał:
    Wydaje mi się, że o czymś zapomniałem konfigurując PWM.

    Mnie się wydaje, że ze schematu jasno wynika, że chcesz słuchać transmisji przychodzącej dla układu UART (filtr podpięty pod RXD/PD0), a nie sygnału PWM z licznika (OC1B/PD4 który wisi w powietrzu).
  • #5 11765812
    szpada89
    Poziom 9  
    Nie nie, jest podpięty pod odpowiedni port (słychać przy odgrywaniu dźwięków jakieś piszczenie, pikanie itd na wyjściu jack, do którego wychodzi właśnie OC1B). Teraz widzę, że wysłałem jakiś dziwny schemat, sorry. Nie mam dostępu w tej chwili do aktualnego ale hardware jest dobrze zrobiony.
  • #6 11765921
    ZbeeGin
    Poziom 39  
    Jeszcze jedno. Próbki w pliku WAV są signed czy unsigned? Jeśli signed to czy przeliczasz je na unsigned przed wysłaniem do OCR? Widzę w programie jakieś dziwne przeliczenia, ale nie widzę by była taka konwersja.
  • #7 11765972
    szpada89
    Poziom 9  
    Próbki tak naprawdę nie są dostarczane na karcie w formacie WAVE a txt, w którym zapisane są w postaci jednego wielkiego ciągu (bez znaków nowej lini itd). W programie pobierane są bloki o ustalonej wielkości (wielokrotności 3) do bufora, a przy odczycie (trójkami) są sklejane i wystawiane na OCR1B
  • #8 11766037
    ZbeeGin
    Poziom 39  
    Jak finalnie jest to przedstawiane w pliku TXT to nie jest tak istotne. Istotne jest to, czy próbki oryginalnie był signed czy unsigned.
  • REKLAMA
  • #9 11766097
    szpada89
    Poziom 9  
    Próbki są unsigned.
  • #10 11768317
    szelus
    Poziom 34  
    Największy błąd jaki robisz, to wykorzystanie timera. Do odtwarzania 8 bitowych próbek przez PWM potrzebujesz 8 bitowego zakresu, więc nie możesz go obcinać ustawiając wartość TOP. Poza tym, bez sensu korzystasz do tego z 16 bitowego timera.
    Jeżeli będziesz korzystał z pełnego zakresu 8 bitowego timera, to z kolei nie możesz wybrać dowolnej częstotliwości próbkowania, tak jak napisał kolega WOBI - musisz dobrać kwarc do częstotliwości próbkowania, albo zewnętrznym programem "zresamplować" plik WAV do częstotliwości próbkowania wynikającej z zastosowanego kwarcu.
    Poza tym, wydaje mi się, że dane w likach WAV są zawsze signed i trzeba je przeliczyć na unsigned do takiego wykorzystania, jak Twoje, ale tu głowy nie dam.
    Natomiast trzymanie przetworzonych danych w pliku txt jest raczej bez sensu - musisz odczytywać z karty 3 razy więcej danych, niepotrzebnie spowalniając działanie programu.
  • #11 11768423
    szpada89
    Poziom 9  
    Ok, to mógłbyś mi podpowiedzieć jak skonfigurować PWM tak aby otrzymać 22050Hz (lub 44100Hz)?. Poza tym skoro mam nie używać timera to kiedy wystawiać próbki (obecnie wystawiane są w przerwaniu kiedy przepełni się timer)?. Docelowo zmienię te pliki bo rzeczywiście to jest bezsensu :)
  • #12 11768536
    szelus
    Poziom 34  
    Ale przecież napisał już WOBI, że się nie da, chyba, że użyjesz kwarcu 11,0952 MHz. Wtedy, jeżeli upierasz się używać timer 1 to zostawiasz tak, jak masz, tylko ustawiasz ICP1 = 255 i masz ok. 22khz. (dokładnie 21670Hz) Dla 44 musiałbyś dać kwarc 22Mhz.
    Dla dokładnie 22050 powinieneś użyć kwarcu o czestotliwości 22050*512 = 11,2896MHz, ale nie wiem, czy da się taki kupić.
  • REKLAMA
  • #13 11769420
    szpada89
    Poziom 9  
    W tej chwili jestem tylko w posiadaniu kwarcu 10MHz, więc go sobie przylutuje ustawie fuse bity i zobaczę jak to śmiga.
  • REKLAMA
  • #14 11770383
    WOBI
    Poziom 19  
    Możesz użyć kwarcu 10MHz wychodzi 19,6 kHz wystawianie próbek, jak z takim kwarcem wystawisz plik o próbkowaniu 22,05 KHz to będzie tylko trochę wolniejszy dźwięk, to taki efekt jak byś nagraną kasetę magnetofonową odtwarzał z trochę wolniejszą prędkością. Większość programów do obróbki dźwięku ma w efektach specjalnych taką możliwość, przyśpieszyć lub zwolnić. I tu uzyskasz efekt zwolnienia po użyciu 10MHz.
    A tak apropo unsigned i signed, plik wav 8bit może być taki lub taki zależy jak go nagramy, ja w CollEdit mam przy zapisie możliwość wyboru. Ale o czymś innym chciałem, timer jest 8bit i ładujemy do niego próbki też 8 bitów odwzorowują one napięcie które uzyskujemy na wyjściu już po filtrze, czyli dźwięk. Jak narysujesz sobie sinusoidę i odniesiesz do niej próbki od 0 do 255 gdzie przejście sinusoidy przez zero będzie miało poziom = 127 to będzie przykład pliku unsigned i drugi rysunek -127 do +127 a przejście przez zero ma wtedy poziom 0 przykład pliku signed to zobaczysz że tak naprawdę w czym jest różnica.
    Więc ładuj plik unsigned na kartę a z niej do bufora i bufora do PWM.
    Trzeba poczytać o obróbce cyfrowej dźwięku, samplowaniu, przetwornikach AC i DA, zjawiskach które zachodzą przy przetwarzaniu cyfrowym sygnału audio(np. aliasing). Bez zrozumienia tego i podstawowych pojęć nie zrozumiesz tego.

    Więc zrób próbę na tym 10MHz a w między czasie doczytaj trochę teorii a będziesz mógł swobodnie pisać programy. tu linki artykuł
    a tu mały rysunek jak to wygłada AC i DC przetwarzanie, tych krateczek (papieru milimetrowego tak dla zobrazowania) dla 8 bitów jest 255 na rysunku dla uproszczenia jest mniej, strzałka jest obustronnna czyli dźwięk na "cyfre" i odwrotnie.
    Atmega32A - Konfiguracja PWM do odtwarzania dźwięku
  • #15 11770753
    ZbeeGin
    Poziom 39  
    WOBI napisał:
    A tak apropo unsigned i signed, plik wav 8bit może być taki lub taki zależy jak go nagramy, ja w CollEdit mam przy zapisie możliwość wyboru. Ale o czymś innym chciałem i tak timer jest 8bit i ładujemy do niego próbki też 8 bitów i nie robimy już żadnych operacji matematycznych na nich więc nie ma tak naprawdę znaczenia jakie one są unsigned signed bo i tak odwzorowują one napięcie które uzyskujemy na wyjściu już po filtrze, czyli dźwięk. Jak narysujesz sobie sinusoidę i odniesiesz do niej próbki od 0 do 255 gdzie przejście sinusoidy przez zero będzie miało poziom = 127 i drugi rysunek -127 do +127 a przejście przez zero ma wtedy poziom 0 to zobaczysz że tak naprawdę to tylko punkt odniesienia. Dźwięk będzie i tak odtwarzany dobrze, trzeba poczytać o obróbce cyfrowej dźwięku, samplowaniu, przetwornikach AC i DA,

    Niestety, dźwięk nie będzie odtwarzany dobrze jeśli zastosujesz ten sam algorytm dla próbek signed i unsigned. Próbki signed zapisane w kodzie U2 trzeba przed wysłaniem do PWM (pracującym jako unsigned) nieco poprawić matematycznie. W całym Twoim wywodzie brakuje jednej ważnej rzeczy. Nie uwzględniasz jak bitowo zapisują procesory liczby ujemne. Prześledź sobie jak wygląda rozkład bitów w kodzie U2 dla liczb ujemnych to zobaczysz różnicę. Podpowiem tylko tyle: -1 to 0xFF, a -127 to 0x81.
    Zresztą jako posiadacz CoolEdit-a możesz zrobić próbę: Zapisz dźwięk jako RAW PCM signed, a potem podczas odczytu wybierz unsigned. Zobaczysz jak wyglądać będzie wtedy próbka.
    Podstawowe pojęcia swoje, a mikroprocesory swoje, zatem trzeba do masy teorii dodać szczyptę praktyki...
  • #16 11771119
    WOBI
    Poziom 19  
    Dziękuję za poprawienie mnie, coś niewyspany dzis jestem. Chciałem napisać tylko o punkcie odniesienia przy próbkowaniu w odniesieniu do signed i unsigned a pomieszałem totalnie zapis U2 signed, masz rację. Trzeba używać plików 8bit unsigned lub poddawać konwersji signed.
  • #17 11773182
    szpada89
    Poziom 9  
    Podłączyłem kwarc ale nie mam pojęcia jak poustawiać te wszystkie rejestry żeby to działało prawidłowo. Ustawiałem wszytskie kombinacje :
    Atmega32A - Konfiguracja PWM do odtwarzania dźwięku

    Na wyjściu dostaje piski i nic więcej. Pomocy :/
  • #18 11774307
    ZbeeGin
    Poziom 39  
    szpada89 napisał:
    Na wyjściu dostaje piski i nic więcej. Pomocy :/

    Proponuję podejść do tego nieco inaczej. Na początek usuń całą komunikację z kartą SD. W pamięci Flash (tablica z kaluzulą PROGMEM) umieść próbkę sinusa 1kHz - jeden okres by danych nie było zbyt dużo. Napisz fragment programu który miałby ten sinus odtwarzać cyklicznie przez PWM. Tutaj masz prawie gotowca.

    Jeśli próbka będzie odtwarzana poprawnie, to dalej dorabiaj do tego resztę.
  • #19 11778165
    WOBI
    Poziom 19  
    Źle bufor masz zorganizowany, źle wystawiasz dane z tego bufora do PWM.
    Nie napiszę tego w C bo nie będę dawał gotowca,ale mogę napisać jak logicznie to powinno być, resztę sam musisz zrobić.
    W przerwaniu timera masz tylko ładować do PWMa bajt z bufora wskazywany przez wskaźnik, nic więcej nie robisz w przerwaniu, a juz na pewno nie przeładowanie bufora lub jakieś inne czasowożerne procedury, tam tylko flagi. Ma to być jak najbardziej proste i krótkie czasowo, reszta w programie głównym.

    konfigurujesz timer1 PWM 8bit rozdzielczość, preskaler 1
    deklarujesz bufor np. 128bajtów

    otwierasz plik (plik musi być z próbkami 8 bit, unsigned)
    ładujesz wstępnie bufor od 0 do 128 danymi z pliku, dla bufora tu w przykładzie 128bajtów
    ustawiasz flagi bufora na 1 flaga_gora i flaga_dol
    wskaźnik bufora ustawiasz na 0
    dopiero teraz odblokowujesz przerwanie od timera1 (od tego momentu zaczyna się ładowanie w przerwaniu próbek do OCR1A)

    teraz pętla!!! główna odtwarzania do końca pliku lub do przerwania jej przez użytkownika (np. przycisk lub jakiś inny warunek, zmiana pliku itp)
    w pętli sprawdzasz czy nie wystąpił koniec pliku lub dodatkowo swój warunek
    i warunki dla flag

    if flaga_dol = 0 ' jeżeli opróżniła się dolna połowa buforu to ją ładujemy
    od 0 do 64 z pliku ładujemy bajty do bufora
    ustawiamy flaga_dol na 1 po napełnieniu ' ważne!!!
    i sprawdzamy czy nie nastąpił koniec pliku Eof, jeśli tak koniec odtwarzania wychodzimy z pętli

    if flaga_gora = 1 ' jeżeli opróżniła się górna połowa buforu to ją ładujemy
    od 65 do 128 z pliku ładujemy bajty do bufora
    ustawiamy flaga_gora na 1 po napełnieniu ' ważne!!!
    i sprawdzamy czy nie nastąpił koniec pliku Eof, jeśli tak koniec odtwarzania wychodzimy z pętli

    i tak pętla główna do końca pliku.
    po wyjściu z pętli głównej blokujesz przerwanie i stopujesz timer1 !!!
    ......
    ..... tu dalszy Twój program
    '====================== przerwanie=========
    Tu obsługa przerwania, tutaj ładujesz co przerwanie timera1 próbki z bufora do timera1 i ustawiasz flagi bufora
    W przerwaniu od timera1

    ładujesz do OCR1A bajt z bufora (wskaźnikiem) bufora

    zwiększamy wskaźnik o 1

    teraz sprawdzasz wskaźnik bufora

    if wskaźnik = 64 kasujemy flaga_dol =0 ' informacja dla pętli że opróżniliśmy już dolna połowę bufora

    if wskaźnik = 128 kasujemy flaga_dol =0 ' informacja dla pętli że opróżniliśmy już górną połowę bufora i
    zerujesz wskaźnik = 0

    return z przerwania.

    W przerwaniu nic więcej nie robisz, żadnego ładowania z karty SD !!! po to masz bufor, jak sama nazwa wskazuje, buforuje, by próbki były wystawiane do PWMa co obliczony czas timera(synchronicznie), to musi być niezależne od programu głównego. Nadchodzi przerwanie i trzeba kolejną próbkę załadować i tak cyklicznie. Nic nie może tego procesu zakłócać, np. niedopuszczalna jest w tym przerwaniu wywoływać inne procedury, a już na pewno nie obsługę karty SD. Pomyśl co się stanie jak czas procedury np karty SD przekroczy czas kolejnego przerwania od timera, a Ty dalej siedzisz w tym przerwaniu bo jeszcze go nie opuściłeś od kolejnego przerwania, bo coś jeszcze robisz. Jak myślisz co sie wtedy dzieje?

    Inne uwagi.
    Bufor nie może być zbyt mały bo nie nadążysz go ładować i dużego też nie ma co dawać bo procedura ładowania będzie niepotrzebnie trwała długo. Najczęściej karty SD zorganizowane są w sektory po 512 bajtów, wtedy w programie można dać 128, 256 lub 512 bufor. Program i jego organizacja czasowa będzie wtedy najlepiej zorganizowana, dopasowana czasowo, zoptymalizowane wskaźniki buforów zarówno karty jak i buforu danych do PWM
  • #20 11779002
    szpada89
    Poziom 9  
    Moje rozwiązanie jest bardzo podobne do tego, o którym Ty mówisz z tą różnicą, że ja mam 2 bufory zamiast jednego.

    Cytat:
    W przerwaniu timera masz tylko ładować do PWMa bajt z bufora wskazywany przez wskaźnik, nic więcej nie robisz w przerwaniu, a juz na pewno nie przeładowanie bufora lub jakieś inne czasowożerne procedury, tam tylko flagi. Ma to być jak najbardziej najproste i krótkie czasowo, reszta w programie głównym.


    Tak jak mówisz - w przerwaniu mam tylko wczytanie danych z bufora do OCR1B, inkrementacja pozycji w buforze i ewentualnie przełączenie flag, nic więcej.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Cytat:
    if flaga_dol = 0 ' jeżeli opróżniła się dolna połowa buforu to ją ładujemy
    od 0 do 64 z pliku ładujemy bajty do bufora
    ustawiamy flaga_dol na 1 po napełnieniu ' ważne!!!
    i sprawdzamy czy nie nastąpił koniec pliku Eof, jeśli tak koniec odtwarzania wychodzimy z pętli

    if flaga_gora = 1 ' jeżeli opróżniła się górna połowa buforu to ją ładujemy
    od 65 do 128 z pliku ładujemy bajty do bufora
    ustawiamy flaga_gora na 1 po napełnieniu ' ważne!!!
    i sprawdzamy czy nie nastąpił koniec pliku Eof, jeśli tak koniec odtwarzania wychodzimy z pętli


    Znowu tak jak mówisz tylko z podziałem na 2 bufory.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Cytat:
    po wyjściu z pętli głównej blokujesz przerwanie i stopujesz timer1 !!!


    O tym zapomniałem ale nawet jeśli coś by to naknociło to dopiero po pierwszym wav'ie.

    Tak więc wydaje mi się, że zaprogramowane jest to poprawnie, nie jestem pewny co do ustawienia wielkości buforów bo nie udało mi się nigdzie znaleźć czasu odczytu pliku w PetitFat.
  • #21 11779057
    WOBI
    Poziom 19  
    Ok to dobrze. Zmień rozmiar buforów, daj dwa po 256 bajtów, pamiętaj że ATmega32 ma tylko 2Kb sramu, nie pamiętam ile ramu potrzebuje Petifat, może przy obsłudze dwóch buforów i przepisywaniu do nich bajtów z karty Petifat coś miesza. Uprość tą obsługę bufora do jednego.
    Tu masz linka do playera zbudowanego na petifat są źródła i schematy Simple SD Audio Player with an 8-pin IC
    A na karcie SD masz poprawny plik wav 8bit ?

    Widzę że dalej ładujesz składaka 3 bajtów do PWM??? Masz ładować jeden bajt bo PWM!!! i tylko jeden z pliku wav unsigned 8bit!!!

    co to za cudo??
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    ma być tylko ładowanie jednego bajtu
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    jeśli masz bufor typu char to ładujesz to do OCR1B i nic więcej, żadnych konwersji typów.
  • #22 11779491
    ZbeeGin
    Poziom 39  
    WOBI napisał:
    co to za cudo??

    Kolega po prostu czyta tekst i trzy znaki ASCII przekształca na liczbę 000-255. Oczywiście mógłby to robić korzystając z funkcji atio(), ale może ma powód by to robić "na piechotę". Taki zapis jest także jawnym marnotrawstwem pamięci karty i raczej niczego nie upraszcza, ale weź przekonaj...

    Co do takiego zapisu, nic jednak nie wiemy czy dane są ciągłe, czyli:
    001003004010025 itd.
    czy jednak:
    001
    003
    004
    010
    025
    itd. ze znakami końca linii.
    Jeśli tekst jest ze znakami końca linii to nie byłoby dziwne, że z takich danych wychodzi "audio sieczka".
  • #23 11779991
    WOBI
    Poziom 19  
    W przerwaniu nie miało być nic. A co to za funkcja operująca na buforze??
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Ciekawe jaka logika myślenia skłania do takiego pisania programów, użyję porównania: to jak drapanie się po lewym uchu prawą nogą ;).
    I jak napisałeś wychodzi "audio sieczka" bo tak naprawdę nie wiemy jak wygląda naprawdę plik i czym jest stworzony, co tam w nim jest, na pewno sieczka ;)

    Ale poważnie, ile czasu zajmuje funkcja ładowania/składania do OCR1B tych 3 bajtów, plus dodawanie, plus mnożenie?
    Na dodatek rejestr OCR1B jest 8 bitowy, a użyta funkcja jest typu integer 2 bajtowa i co tak naprawdę jest umieszczane (jaki wynik) ląduje w OCR1B. Jak int jest umieszczane w 8bitach
    Dla mnie jest to karkołomne ;) i już pachnie kłopotami.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Masz rację weź i przekonaj... do prostoty, poprawnego napisania programu, użycia pliku wav 8bit unsigned i prostego ładowania 8bitów z malego buforu prosto do OCR1B.
  • #24 11780706
    szpada89
    Poziom 9  
    Cytat:
    Co do takiego zapisu, nic jednak nie wiemy czy dane są ciągłe, czyli:
    001003004010025 itd.
    czy jednak:
    001
    003
    004
    010
    025
    itd. ze znakami końca linii.
    Jeśli tekst jest ze znakami końca linii to nie byłoby dziwne, że z takich danych wychodzi "audio sieczka".


    Znaki są zapisane jako ciągłe, stąd cięcie co 3.

    Cytat:
    W przerwaniu nie miało być nic. A co to za funkcja operująca na buforze??


    To funkcja ustawiająca odpowiednie flagi, przeniosę ją do przerwania bo rozumiem, że proces samego wywoływania funkcji w przerwaniu jest niezbyt przemyślany.

    Cytat:
    Ale poważnie, ile czasu zajmuje funkcja ładowania/składania do OCR1B tych 3 bajtów, plus dodawanie, plus mnożenie?
    Na dodatek rejestr OCR1B jest 8 bitowy, a użyta funkcja jest typu integer 2 bajtowa i co tak naprawdę jest umieszczane (jaki wynik) ląduje w OCR1B. Jak int jest umieszczane w 8bitach
    Dla mnie jest to karkołomne Wink i już pachnie kłopotami.


    Docelowo zrobię to na plikach wave, na szybko łatwiej było mi napisać pobieranie znaków niż czytanie odpowiednio nagłówków a potem tablicy znaków. Zmienię również typ z int na BYTE żeby nie było problemów z konwersją.
  • #25 11781198
    WOBI
    Poziom 19  
    szpada89 napisał:
    Docelowo zrobię to na plikach wave, na szybko łatwiej było mi napisać pobieranie znaków niż czytanie odpowiednio nagłówków a potem tablicy znaków. Zmienię również typ z int na BYTE żeby nie było problemów z konwersją.

    Zrób to zaraz i nie baw się w to składanie, szkoda Twojego i naszego czasu.
    Zauważ że to co robisz, czyli mnożenie *100 później *10, dodawanie, składanie bajtu z trzech jest czasowo niestabilne. Czas w jakim wykonują się te działania jest za każdym razem inny, zależnym od wartości obliczanych (zapominasz o tym).
    Psujesz podstawowe założenie przerwania by próbki były synchronicznie wystawiane do PWM.
    W Twoim przypadku nie pojawiają się co ten sam okres czasu, bo mnożysz, dodajesz.

    Dlatego w przerwaniu ładujesz tylko do OCR1B = bufor[wskaznikiem] bo to wykonuje się za każdym przerwaniem tak samo, to podstawowe o bardzo ważne założenie by działało prawidłowo.

    Nagłówka na razie nie musisz analizować, poprostu go omijaj pierwsze 45bajtów pliku i już.
    masz tu gotowy plik wav 8 bit unsigned czysty raw bez nagłówka. Rób próby na tym. Już więcej nie możemy Ci pomóc co do składania 3 bajtowego ;)
  • #26 12245759
    Badmaneq
    Poziom 23  
    Cytat:
    a wynika to z matematyki = częstotliwosc liczymy dla 8 bit pwm fosc/510 dla prescale =1


    Dlaczego przez 510 ?
  • #27 12258330
    WOBI
    Poziom 19  
    Wynika to z zasady działania PWM i jest opisane w dokumentacji Atmega8. Timer używany do PWM jest w tym przypadku 8 bitowy, czyli 8 bitów to FFhex czyli 255 dziesiętnie. 255 dodać 255 daje 510. Nie wnikając w szczegóły poprostu tak zbudowany jest PWM i jak poczytasz PDF atmela lub książkę o budowie i działaniu timerów to tam jest wszystko wyjaśnione szczegółowo.
REKLAMA