Projektuję własne przenośne urządzenie do gier oparte na mikrokontrolerze AVR i małym wyświetlaczu OLED.
Zacząłem od monochromatycznego wyświetlacza 128 x 64 pikseli i mogę wygodnie rysować z prędkością ponad 60 klatek na sekundę.
Niedawno przerobiłem go, aby używał RGB OLED, 128 x 128 pikseli, nie myśląc zbyt wiele, by znaleźć tylko 4 FPS. Po kilku przemyśleniach i starannej refaktoryzacji mogę uzyskać do ~ 12 kl./s, jeśli nie przejmuję się zbytnio robieniem czegoś innego!
Moje pytanie brzmi - w jaki sposób urządzenie takie jak GBA (Game Boy Advance) osiągnęło częstotliwość klatek wynoszącą prawie 60 klatek na sekundę? Pomyślałem o oddzielnym „procesorze graficznym”, ale zdałem sobie sprawę, że nadal będę miał wąskie gardło w przenoszeniu do tego danych wyświetlanych.
Zastanawiałem się również nad użyciem oryginalnego 8-bitowego interfejsu równoległego, który ma większość tych ekranów, co może przynieść mi 8-krotne przyspieszenie, z tym wyjątkiem, że współczesne MCU nie mają zwykle sprzętowych interfejsów równoległych, jak w przypadku szeregowego i bitowego walenie prawdopodobnie pochłonie dużą część prędkości.
Jakie są inne opcje?
Obecnie używam ATmega1284P podłączonego do kontrolera OLD SSD1306 przez USART-SPI. To jest wersja monochromatyczna.
Kolorowy ekran to SSD1351, pierwotnie niepołączony ze sprzętowym interfejsem SPI. Nie byłem przekonany, że to zrobi wystarczającą różnicę, ogólnie jest to po prostu zbyt powolne
Wiem, że mogę uzyskać szybsze MCU, ale chcę wiedzieć, jakie inne opcje mogę zbadać - procesor GBA jest znacznie wolniejszy niż mój 1284!
źródło
Odpowiedzi:
Inne odpowiedzi dość dobrze pokrywają twoje pytanie na poziomie abstrakcyjnym (sprzętowym), ale mając faktyczne doświadczenie z GBA, pomyślałem, że bardziej szczegółowe wyjaśnienie może być warte zachodu.
GBA miał wiele trybów rysowania i ustawień, które można wykorzystać do kontrolowania interpretacji pamięci RAM przez procesor graficzny, ale jedno jest nieuniknione: szybkość klatek. Procesor graficzny rysował na ekranie w prawie (więcej na ten temat poniżej) stałej pętli. (Jest to prawdopodobnie najbardziej odpowiedni bit dla twojego pytania).
Rysowałby jedną linię na raz, robiąc bardzo krótką przerwę między nimi. Po narysowaniu ostatniej linii dla ramki zajęłoby to przerwę w przybliżeniu równą czasowi, który zajmuje narysowanie 30 linii. Następnie zacznij od nowa. Czas każdej linii i czas każdej ramy zostały z góry określone i osadzone w kamieniu. Pod wieloma względami procesor graficzny był tak naprawdę mistrzem tego systemu i trzeba było pisać gry wokół jego zachowania, ponieważ kontynuowałoby to, co robił, niezależnie od tego, czy byłeś gotowy.
Około 75-80% czasu aktywnie naciskało na ekran. Jakie liczby klatek można osiągnąć, jeśli robisz to samo?
To 80% czasu było również tym, co CPU musiał przetwarzać przez użytkownika, obliczać stan gry i ładować duszki / kafelki do obszarów VRAM, które były obecnie poza ekranem (lub przynajmniej nie były uwzględnione w rysowanej linii).
20% między klatkami to tyle, ile procesor musiał dostosować ustawienia wideo lub pamięci RAM, które wpłynęłyby na całą następną klatkę.
Na końcu każdej linii procesor graficzny wyśle do procesora przerwanie synchronizacji linii. Przerwania tego można użyć do dostosowania ustawień kilku duszków lub kilku warstw tła (w ten sposób można uzyskać efekt przypominający stożkowe światło punktowe, zmieniając rozmiar i położenie jednej z prostokątnych masek między każdą narysowaną linią. jeśli chodzi o sprzęt, wszystkie te regiony są prostokątne). Trzeba uważać, aby te aktualizacje były małe i zakończyć, zanim procesor graficzny zacznie rysować kolejną linię, aby uzyskać brzydkie wyniki. Każdy czas spędzony na przetwarzaniu tych przerwań skraca również 80% czasu przetwarzania procesora ...
W przypadku gier, które w pełni wykorzystały ten system, ani procesor, ani procesor graficzny nigdy nie zrobiły prawdziwej przerwy; obaj gonili się nawzajem po pętli, aktualizując to, czego nie oglądał obecnie drugi.
źródło
Kluczową cechą wszystkich konsol do gier, które odróżniały je od wczesnych komputerów PC i praktycznie wszystkich komputerów domowych (1), były sprity sprzętowe .
Połączony przewodnik programowania GBA pokazuje, jak działają z punktu widzenia głównego procesora. Mapy bitowe reprezentujące gracza, tło, wrogów itp. Są ładowane do jednego obszaru pamięci. Inny obszar pamięci określa lokalizację duszków. Zamiast więc ponownie zapisywać całą pamięć RAM wideo w każdej klatce, co wymaga wielu instrukcji, procesor musi po prostu zaktualizować lokalizację duszków.
Procesor wideo może następnie pracować piksel po pikselu, aby określić, który duszek ma rysować w tym punkcie.
Wymaga to jednak podwójnej pamięci RAM współdzielonej między nimi i myślę, że w GBA procesor wideo jest na tym samym układzie co główny procesor ARM i dodatkowy procesor Z80.
(1) Godny uwagi wyjątek: Amiga
źródło
„Moje pytanie brzmi - w jaki sposób urządzenie takie jak GBA osiągnęło częstotliwość klatek prawie 60 kl./s?”
Aby odpowiedzieć tylko na pytanie, zrobili to za pomocą procesora graficznego. Jestem pewien, że Game Boy używał grafiki sprite. Na najwyższym poziomie oznacza to, że procesor graficzny wczytuje rzeczy takie jak obraz tła, obraz Mario, obraz Princess Peach itp. Następnie główny procesor wydaje polecenia takie jak „pokaż przesunięcie tła przez to dużo na xiy, nakładka obrazu Mario nr 3 na tę pozycję x, y ”itd. Tak więc główny procesor absolutnie nie zajmuje się rysowaniem każdego piksela, a procesor graficzny absolutnie pozytywnie nie zajmuje się obliczaniem stanu gra. Każda jest zoptymalizowana pod kątem tego, co musi zrobić, a wynikiem jest całkiem dobra gra wideo bez użycia dużej mocy obliczeniowej.
źródło
GBA miał dość wolny procesor. ARM7 jest bardzo fajny; po prostu uruchomili go powoli i nie dali prawie żadnych zasobów.
Jest powód, dla którego wiele gier Nintendo w tym momencie i wcześniej było side-scrollerami. SPRZĘT KOMPUTEROWY. Wszystko odbywa się sprzętowo. Miałeś wiele warstw kafelków i co najmniej jedną duszkę, a sprzęt wykonał całą pracę, aby wyodrębnić piksele z tych tabel i sterować wyświetlaniem.
Zbudujesz zestaw kafelków z przodu, a następnie będziesz miał niewielką pamięć, która była mapą kafelków. Chcesz, aby dolna lewa płytka była płytką 7? Umieszczasz 7 w tym miejscu pamięci. Chcesz, aby następnym kafelkiem był kafelek 19? W zestawie kafelków umieścisz tam 19 itd. Dla każdej włączonej warstwy. W przypadku duszka po prostu ustaw adres x / y. Możesz także skalować i obracać, ustawiając niektóre rejestry, a sprzęt zajmie się resztą.
Tryb 7, jeśli dobrze pamiętam, był trybem pikselowym, ale to było jak tradycyjna karta wideo, w której umieszcza się bajty w tej pokrywie koloru piksela, a sprzęt zajmuje się odświeżaniem wideo. Myślę, że możesz pingować ponga, a przynajmniej kiedy masz nową ramkę, możesz je przerzucić, ale nie pamiętam dobrze. Ponownie procesor był dość podkręcony w tym dniu i wieku i nie miał zbyt wielu szybkich zasobów. Podczas gdy niektóre gry były w trybie 7, wiele z nich to side-scrollery oparte na kafelkach ...
Jeśli chcesz mieć rozwiązanie o wysokiej liczbie klatek na sekundę, musisz je zaprojektować. Nie możesz po prostu wziąć żadnego starego wyświetlanego ekranu i porozmawiać z nim przez SPI lub I²C lub coś w tym rodzaju. Umieść przed sobą co najmniej jeden bufor ramki, najlepiej dwa, i kontroluj wiersze i kolumny, jeśli to możliwe, na tym ekranie.
Pewna liczba wyświetlaczy, które, jak podejrzewam, kupujesz, ma kontroler, z którym rozmawiasz. Jeśli chcesz wydajności typu GBA / konsoli, tworzysz / implementujesz kontroler. Lub kupujesz / budujesz z GPU / układem wideo / blokiem logicznym i używasz HDMI lub innego wspólnego interfejsu do standardowego monitora.
To, że rower ma opony, łańcuch i biegi, nie oznacza, że może jechać tak szybko, jak motocykl. Musisz zaprojektować system tak, aby spełniał Twoje wymagania dotyczące wydajności od początku do końca. Możesz umieścić to koło rowerowe na tym motocyklu, ale nie będzie ono działać zgodnie z oczekiwaniami; wszystkie elementy muszą być częścią ogólnego projektu.
Asteroidy też działały w ten sposób; potrzebował tylko jednego 6502. Grafika wektorowa została wykonana z osobną logiką; 6502 wysłał niewielki ciąg danych do kontrolera grafiki wektorowej, który użył pamięci ROM i tych danych do sporządzenia wykresu xy wiązki i z, włączanie / wyłączanie ... Niektóre stacje miały oddzielne procesory do obsługi audio i wideo oddzielnie od procesor obliczający grę. Oczywiście dzisiaj wideo jest obsługiwane przez setki, jeśli nie tysiące procesorów, które są oddzielone od głównego procesora ...
źródło
Sprzęt komputerowy.
Ma pamięć graficzną, która może, ale nie musi, dzielić tę samą magistralę co pamięć programu / danych ... ale ważne jest to, że ma procesor graficzny, który odczytuje pamięć 60 razy na sekundę i wysyła dane do LCD za pomocą zoptymalizowany interfejs, który został zaprojektowany tak, aby efektywnie to robić.
Możesz zrobić to samo z dowolnym nowoczesnym mikrokontrolerem wyposażonym w urządzenie peryferyjne z „interfejsem LCD”, na przykład LPC4330, chociaż może to być przesada. Oczywiście potrzebujesz kompatybilnego panelu LCD.
Dzięki nowoczesnym szybkim mikrokontrolerom (tj. ARM nie AVR) i tak małemu ekranowi prawdopodobnie nie będziesz potrzebował sprite'ów ani blittera, aby przyspieszyć operacje graficzne. W przypadku 8-bitowego AVR może to być powolne.
Ale bez względu na procesor, bit walenie interfejsu do wyświetlacza będzie do bani.
Wydaje mi się, że Atari 2600 wykorzystywał procesor bittingu do wysyłania obrazu do telewizora. To jest trochę przestarzałe.
źródło