Cześć wszystkim!
Projektuję właśnie prostą konsolę do gier wykorzystującą monitor VGA i opartą na ATmedze644PA. Tak tak, wiem że generowanie sygnału VGA to zadanie dla układów typu FPGA, ale odrobina szaleństwa jeszcze nikomu nie zaszkodziła
Tak więc, ATmega644 służy do generowania sygnału VGA. Klatki są przechowywane w pamięci RAM (układ AS6C1008). Jest ona sekwencyjnie odczytywana w pojawiającym się regularnie przerwaniu na Timerze. Aby wycisnąć tak wiele pikseli jak mogę mikrokontroler taktowany jest zegarem 25.175MHz (standard dla VGA). Wszystko działa świetnie, zdecydowałem się więc dodać trochę bajerów, m.in. odtwarzanie dźwięku. I tu pojawił się problem.
Do odtwarzania dźwięku wykorzystuję PWM z Timer'a 2, który dostrajam do odpowiedniej, słyszalnej częstotliwości. Wyjście z PWM ustawione jest na OC2B, warto dodać że pin ten nie jest wykorzystywany do żadnej innej funkcji a jego wartości PORTD, PIND i DDRD nie są w żadnym miejscu zmieniane. Ze względu na złożoność przerwania wideo, jego rozmiar jest bardzo duży (w assemblerze ok. 1200 instrukcji). Wszystko powinno być jednak dobrze dobrane i żadna instrukcja nie jest bez sensu.
Przechodząc do samego problemu:
- jeśli wyświetlam tylko wideo, wszystko zachowuje się poprawnie
- jeśli odtwarzam tylko dźwięk przy wyłączonym przerwaniu wideo (np/ zakomentuję SEI; jest inicjowany poza przerwaniem, w przerwaniu jest tylko ewentualnie zmieniany) brzmi on czysto
- jeśli natomiast odblokuję przerwanie (np. odkomentuję SEI), to słychać wyraźny szum
Żeby zilustrować problem przygotowałem krótkie nagranie, można wyraźnie rozpoznać który dźwięk jest pożądanym C, a który zniekształcony. Przygotowałem też schematy w Eagle (nic skomplikowanego) i fragmenty kodu.
Potrzebuję waszej pomocy w stwierdzeniu co jest przyczyną problemu. Nie wydaje mi się żeby był to problem hardware'owy, jeśli po zablokowaniu przerwania (zmiana software'u) dźwięk przestaje być zakłócony. Czy może być to:
- rzeczywiście problem hardware'u (wszystko jest robione na płytce stykowej)
- problem zbyt długiego przerwania (jak gdzieś ktoś mi zasugerował)
- problem z tym, że okoliczne piny są w tym przerwaniu często zmieniane (służą np. do generowania adresu pamięci SRAM, więc jeden z portów jest inkrementowany co drugą instrukcję w assemblerze) i to powoduje wygenerowanie zakłóceń na pinie buzzera.
Kod źródłowy gdzie nastawiam Timer:
Tak jak wspomniałem, różnica występuje po zakomentowaniu/odkomentowaniu instrukcji SEI.
Przykład dźwiękowy (pierwszy sygnał zaszumiony, drugi poprawny):
Schemat:
Będę wdzięczny za pomoc! Oczywiście jeśli potrzeba czegoś więcej (treści przerwania, które pominąłem ze względu na długość) to wszystko dodam. Ratujcie
Projektuję właśnie prostą konsolę do gier wykorzystującą monitor VGA i opartą na ATmedze644PA. Tak tak, wiem że generowanie sygnału VGA to zadanie dla układów typu FPGA, ale odrobina szaleństwa jeszcze nikomu nie zaszkodziła
Tak więc, ATmega644 służy do generowania sygnału VGA. Klatki są przechowywane w pamięci RAM (układ AS6C1008). Jest ona sekwencyjnie odczytywana w pojawiającym się regularnie przerwaniu na Timerze. Aby wycisnąć tak wiele pikseli jak mogę mikrokontroler taktowany jest zegarem 25.175MHz (standard dla VGA). Wszystko działa świetnie, zdecydowałem się więc dodać trochę bajerów, m.in. odtwarzanie dźwięku. I tu pojawił się problem.
Do odtwarzania dźwięku wykorzystuję PWM z Timer'a 2, który dostrajam do odpowiedniej, słyszalnej częstotliwości. Wyjście z PWM ustawione jest na OC2B, warto dodać że pin ten nie jest wykorzystywany do żadnej innej funkcji a jego wartości PORTD, PIND i DDRD nie są w żadnym miejscu zmieniane. Ze względu na złożoność przerwania wideo, jego rozmiar jest bardzo duży (w assemblerze ok. 1200 instrukcji). Wszystko powinno być jednak dobrze dobrane i żadna instrukcja nie jest bez sensu.
Przechodząc do samego problemu:
- jeśli wyświetlam tylko wideo, wszystko zachowuje się poprawnie
- jeśli odtwarzam tylko dźwięk przy wyłączonym przerwaniu wideo (np/ zakomentuję SEI; jest inicjowany poza przerwaniem, w przerwaniu jest tylko ewentualnie zmieniany) brzmi on czysto
- jeśli natomiast odblokuję przerwanie (np. odkomentuję SEI), to słychać wyraźny szum
Żeby zilustrować problem przygotowałem krótkie nagranie, można wyraźnie rozpoznać który dźwięk jest pożądanym C, a który zniekształcony. Przygotowałem też schematy w Eagle (nic skomplikowanego) i fragmenty kodu.
Potrzebuję waszej pomocy w stwierdzeniu co jest przyczyną problemu. Nie wydaje mi się żeby był to problem hardware'owy, jeśli po zablokowaniu przerwania (zmiana software'u) dźwięk przestaje być zakłócony. Czy może być to:
- rzeczywiście problem hardware'u (wszystko jest robione na płytce stykowej)
- problem zbyt długiego przerwania (jak gdzieś ktoś mi zasugerował)
- problem z tym, że okoliczne piny są w tym przerwaniu często zmieniane (służą np. do generowania adresu pamięci SRAM, więc jeden z portów jest inkrementowany co drugą instrukcję w assemblerze) i to powoduje wygenerowanie zakłóceń na pinie buzzera.
Kod źródłowy gdzie nastawiam Timer:
Kod: C / C++
Tak jak wspomniałem, różnica występuje po zakomentowaniu/odkomentowaniu instrukcji SEI.
Przykład dźwiękowy (pierwszy sygnał zaszumiony, drugi poprawny):
Schemat:
Będę wdzięczny za pomoc! Oczywiście jeśli potrzeba czegoś więcej (treści przerwania, które pominąłem ze względu na długość) to wszystko dodam. Ratujcie
