He estado diseñando mi propio dispositivo de juegos portátil basado en un microcontrolador AVR y una pequeña pantalla OLED.
Comencé con una pantalla monocromática de 128x64 píxeles y puedo dibujar cómodamente a más de 60 cuadros por segundo.
Recientemente lo modifiqué para usar un OLED RGB, 128x128 píxeles sin pensar realmente demasiado solo para descubrir que solo podía lograr unos 4 FPS. ¡Después de pensarlo un poco y refactorizarlo cuidadosamente, puedo obtener eso hasta ~ 12 fps si no me importa demasiado hacer otra cosa!
Mi pregunta es: ¿cómo logró un dispositivo como el GBA (Game Boy Advance) una velocidad de cuadro de casi 60 fps? Pensé en tener un 'procesador de gráficos' separado, pero me di cuenta de que aún estaría bloqueado al transferir los datos de la pantalla a eso.
También me pregunté sobre el uso de la interfaz paralela vestigial de 8 bits que la mayoría de estas pantallas tienden a tener, lo que podría generar una velocidad 8 veces mayor, excepto que las MCU modernas no tienden a tener interfaces paralelas de hardware como lo hacen para serial y bit- golpear probablemente consumirá gran parte de la ganancia de velocidad.
¿Qué otras opciones existen?
Actualmente estoy usando un ATmega1284P conectado a un controlador OLED SSD1306 a través de USART-SPI. Esa es la versión monocroma.
La pantalla a color era un SSD1351, no conectado originalmente al hardware SPI. No estaba convencido de que haría suficiente diferencia, en general es demasiado lento
Sé que puedo obtener MCU más rápidas, pero quiero saber qué otras opciones podría explorar: ¡el procesador GBA es mucho más lento que mi 1284!
fuente
Respuestas:
Otras respuestas cubren su pregunta bastante bien en un nivel abstracto (hardware), pero teniendo experiencia real con el GBA en particular, pensé que una explicación más detallada podría valer la pena.
El GBA tenía muchos modos y configuraciones de dibujo que podían usarse para controlar cómo el procesador de gráficos interpretaba la RAM de video, pero una cosa era inevitable: la velocidad de fotogramas. El procesador gráfico estaba dibujando en la pantalla en un bucle constante (más sobre esto a continuación). (Este es probablemente el bit más relevante para su pregunta).
Dibujaría una línea a la vez tomando un breve descanso entre cada una. Después de dibujar la última línea para el marco, se tomaría un descanso aproximadamente igual al tiempo que lleva dibujar 30 líneas. Entonces comienza de nuevo. El tiempo de cada línea y el tiempo de cada cuadro fueron predeterminados y establecidos en piedra. En muchos sentidos, el procesador de gráficos era realmente el maestro de ese sistema y necesitabas escribir tus juegos en torno a su comportamiento, porque continuaría haciendo lo que hacía si estabas listo o no.
Aproximadamente el 75-80% del tiempo estaba empujando activamente a la pantalla. ¿Qué velocidad de cuadro podría lograr si estuviera haciendo lo mismo?
Ese 80% del tiempo también fue lo que la CPU tuvo que procesar la entrada del usuario, calcular el estado del juego y cargar sprites / mosaicos en áreas de VRAM que estaban actualmente fuera de la pantalla (o al menos no incluidas en la línea actual que se dibuja).
El 20% entre fotogramas fue todo lo que la CPU tuvo que ajustar la configuración de video o RAM que afectaría todo el siguiente fotograma.
Al final de cada línea, el procesador de gráficos enviaría una interrupción de sincronización de línea a la CPU. Esta interrupción podría usarse para ajustar la configuración de algunos sprites o algunas capas de fondo (así es como puede obtener un efecto como un foco cónico, cambiando el tamaño y la ubicación de una de las máscaras rectangulares entre cada línea dibujada. en lo que respecta al hardware, todas esas regiones son rectangulares). Debe tener cuidado de mantener estas actualizaciones pequeñas y finalizar antes de que el procesador gráfico comience a dibujar la siguiente línea o puede obtener resultados feos. Cualquier tiempo dedicado a procesar estas interrupciones también reduce ese 80% del tiempo de procesamiento de la CPU ...
Para los juegos que sacaron el máximo provecho de este sistema, ni la CPU ni el procesador gráfico tomaron un descanso real; cada uno perseguía al otro alrededor del ciclo actualizando lo que el otro no estaba mirando actualmente.
fuente
La característica clave de todas las consolas de juegos que las distinguían de las primeras PC y prácticamente todas las computadoras domésticas (1) eran los sprites de hardware .
La guía de programación GBA vinculada muestra cómo funcionan desde el punto de vista del procesador principal. Los mapas de bits que representan jugadores, antecedentes, enemigos, etc. se cargan en un área de la memoria. Otra área de memoria especifica la ubicación de los sprites. Entonces, en lugar de tener que volver a escribir toda la RAM de video en cada cuadro, lo que requiere muchas instrucciones, el procesador solo tiene que actualizar la ubicación de los sprites.
El procesador de video puede trabajar píxel por píxel para determinar qué sprite dibujar en ese punto.
Sin embargo, esto requiere RAM de doble puerto compartida entre los dos, y creo que en el GBA el procesador de video está en el mismo chip que el procesador ARM principal y el procesador Z80 secundario.
(1) Excepción notable: Amiga
fuente
"Mi pregunta es: ¿cómo logró un dispositivo como el GBA una velocidad de cuadro de casi 60 fps?"
Para responder solo la pregunta, lo hicieron con un procesador de gráficos. Estoy bastante seguro de que Game Boy usó gráficos de sprites. En un nivel superior, eso significa que el procesador de gráficos carga cosas como una imagen de fondo y una imagen de Mario y una imagen de Princess Peach, etc. Luego, el procesador principal emite comandos como "mostrar el desplazamiento del fondo por esto tanto en x como en y, superponga la imagen de Mario # 3 en esta posición x, y ", etc. Por lo tanto, el procesador principal no está absolutamente seguro de dibujar cada píxel, y el procesador gráfico no está absolutamente seguro de calcular el estado del juego. Cada uno está optimizado para lo que necesita hacer, y el resultado es un videojuego bastante bueno sin usar mucha potencia de cálculo.
fuente
El GBA tenía un procesador bastante lento. El ARM7 es muy bueno; simplemente lo corrieron lentamente y lo dieron casi sin recursos.
Hay una razón por la cual muchos juegos de Nintendo en ese momento y antes eran de desplazamiento lateral. HARDWARE. Todo se hace en hardware. Tenía varias capas de mosaicos más uno o más sprites y el hardware hizo todo el trabajo para extraer píxeles de esas tablas y controlar la pantalla.
Construiste el mosaico configurado al frente y luego tenías una memoria pequeña que era un mapa de mosaico. ¿Quieres que la ficha inferior izquierda sea la ficha 7? Pones un 7 en esa ubicación de memoria. ¿Quieres que la siguiente ficha sea la ficha 19? En el conjunto de mosaicos, coloca un 19 allí, y así sucesivamente para cada capa que ha habilitado. Para el sprite, simplemente configura la dirección x / y. También puede escalar y rotar configurando algunos registros y el hardware se encarga del resto.
El modo 7, si no recuerdo mal, era un modo de píxeles, pero eso era como una tarjeta de video tradicional donde pones bytes que cubren el color de un píxel y el hardware se encarga de la actualización del video. Creo que podrías hacer ping pong o, al menos, cuando tenías un nuevo marco, podrías voltearlos, pero no recuerdo bien. Una vez más, el procesador estaba bastante desacelerado para ese día y edad y no tenía demasiados recursos rápidos. Entonces, mientras que algunos juegos eran modo 7, muchos eran desplazadores laterales basados en mosaicos ...
Si desea una solución que tenga una alta velocidad de cuadros, necesita diseñar esa solución. No puede simplemente tomar cualquier pantalla antigua que encuentre y hablar con ella a través de SPI o I²C o algo así. Coloque al menos un framebuffer delante, idealmente dos, y tenga control de fila y columna si es posible sobre esa pantalla.
Algunas de las pantallas que sospecho que está comprando tienen un controlador con el que realmente está hablando. Si desea un rendimiento de tipo GBA / consola, cree / implemente el controlador. O compra / construye con una GPU / chip de video / blob lógico, y usa HDMI u otra interfaz común en un monitor estándar.
El hecho de que una bicicleta tenga neumáticos y una cadena y engranajes no significa que pueda ir tan rápido como una motocicleta. Debe diseñar el sistema para satisfacer sus necesidades de rendimiento, de principio a fin. Puedes poner esa rueda de bicicleta en esa motocicleta, pero no funcionará como desees; Todos los componentes tienen que ser parte del diseño general.
Los asteroides también funcionaron de esta manera; solo necesitaba un 6502. Los gráficos vectoriales se realizaron con lógica separada; El 6502 envió una pequeña cadena de datos al controlador de gráficos vectoriales, que usó una ROM y esos datos para hacer el trazado xy del haz y z, activar / desactivar ... Algunas pantallas tenían procesadores separados para manejar el audio y el video por separado. El procesador que computa el juego. Por supuesto, hoy el video es manejado por cientos, si no miles, de procesadores que están separados del procesador principal ...
fuente
Hardware.
Tiene memoria gráfica, que puede o no compartir el mismo bus que la memoria de programa / datos ... pero lo importante es que tiene un procesador gráfico que lee la memoria 60 veces por segundo y envía los datos a la pantalla LCD usando un Interfaz optimizada que está diseñada para hacer esto de manera eficiente.
Puede hacer lo mismo con cualquier microcontrolador moderno equipado con un periférico de "interfaz LCD", por ejemplo, el LPC4330, aunque esto podría ser excesivo. Por supuesto, necesitará un panel LCD compatible.
Con los modernos microcontroladores rápidos (es decir, ARM no AVR) y una pantalla tan pequeña, probablemente no necesitará sprites o un blitter para acelerar las operaciones gráficas. Con un AVR de 8 bits, puede ser lento.
Pero no importa la CPU, un poco golpear la interfaz de la pantalla va a apestar.
Creo que el Atari 2600 usó golpes de bits de CPU para enviar la imagen al televisor. Eso es un poco obsoleto.
fuente