Un año después del último artículo (como me cuesta sentarme a escribir), en base a una propuesta de un lector del blog (único comentario hasta el día de la fecha) y continuando el artículo Arduino - Generación de señales de VGA con hardware estádar decidí modificar la librería para un Arduino mas potente: Arduino DUE con la finalidad de obtener mejor resolución / rendimiento y poder darle uso práctico.
Las características del Arduino Due lo hacen por demás interesante para esta aplicación.
Cuenta con controlador Atmel AT91SAM3X8E que corre a 84mhz, 96k de ram y 512kb de flash entre otras.
Los 84mhz de clock a unas 3 instrucciones por pixel permitirían teóricamente alcanzar las frecuencias requeridas para el estándar 640 x 480 (25.175mhz) aunque la memoria ram disponible no lo permite a 8bits por color (256 colores): 640 x 480 x 8bits = 307200bytes.
Cuenta con controlador Atmel AT91SAM3X8E que corre a 84mhz, 96k de ram y 512kb de flash entre otras.
Los 84mhz de clock a unas 3 instrucciones por pixel permitirían teóricamente alcanzar las frecuencias requeridas para el estándar 640 x 480 (25.175mhz) aunque la memoria ram disponible no lo permite a 8bits por color (256 colores): 640 x 480 x 8bits = 307200bytes.
Optaremos por una resolución de 320*240*256 colores (76800bytes de RAM), resolución mas que suficiente para las aplicaciones que tengo en mente del sistema.
Implementación
Hardware
Implementación
Hardware
En esta oportunidad no fabriqué un impreso para el DAC conformado por resistencias. En su lugar armé el pack "en el aire", encinté y empaqueté con PVC.
El DAC de resistencias en escalera difiere al anterior producto de que el Arduino Due utiliza 3v3 para alimentación en lugar de los 5v del Arduino estándar.
Las señales de sincronismo, según especificación (bastante variada por cierto) deberían ser 0 - 5v. Prácticamente hablando no tuve problemas hasta ahora en los monitores que probé con señales 0 - 3v3.
Diagrama de conexionado
Utilizaremos al igual que en el proyecto anterior el DAC ladder con 3bits para rojo y verde y 2bits para el azul (RGB 3-2-2).
El microcontrolador cuenta con hasta 6 puertos de 32bits (hasta 32 pines) que están disponibles total o parcialmente dependiendo del modelo de controlador (encapsulado / cantidad de pines).
Utilizaremos en este caso el único de los puertos (PIOD) que tiene "conexionado" al exterior desde el pin 0 del puerto (8bits menos significativos en el registro de acceso al puerto).
El conexionado es algo "rebuscado" (los muchachos que diseñan los Arduino no suelen pensar en aquellas aplicaciones de tiempo crítico) pero no hay alternativas si se pretende tener el rendimiento buscado.
VGA Monocromático
Software
La librería es la de Arduino VGA con algunas modificaciones / agregados.
En este caso ArduinoDueVGAEngine.cpp, producto de las características del microcontrolador está íntegramente escrita en C a diferencia de la anterior que está escrita mayormente en ensamblador (generación de video) por cuestiones de rendimiento.
Librería
Al igual que el proyecto original, la librería está compuesta por una clase pública para el usuario (ArduinoDueVGA.cpp) y una librería de bajo nivel (ArduinoDueVGAEngine.cpp) con las rutinas de generación de señal.
La misma es de código abierto (licencia a definir) y puede ser descargada desde la web de SourceForge desde aquí.
Para detalles sobre la utilización referirse a apartado Instalación / Utilización del artículo Arduino - Generación de señales de VGA con hardware estádar.
https://code.google.com/archive/p/rl-dac/
https://raronoff.wordpress.com/2012/10/17/rl-dac/
El DAC de resistencias en escalera difiere al anterior producto de que el Arduino Due utiliza 3v3 para alimentación en lugar de los 5v del Arduino estándar.
Las señales de sincronismo, según especificación (bastante variada por cierto) deberían ser 0 - 5v. Prácticamente hablando no tuve problemas hasta ahora en los monitores que probé con señales 0 - 3v3.
ladder de resistencias empaquetado en pvc
Utilizaremos al igual que en el proyecto anterior el DAC ladder con 3bits para rojo y verde y 2bits para el azul (RGB 3-2-2).
El microcontrolador cuenta con hasta 6 puertos de 32bits (hasta 32 pines) que están disponibles total o parcialmente dependiendo del modelo de controlador (encapsulado / cantidad de pines).
Utilizaremos en este caso el único de los puertos (PIOD) que tiene "conexionado" al exterior desde el pin 0 del puerto (8bits menos significativos en el registro de acceso al puerto).
El conexionado es algo "rebuscado" (los muchachos que diseñan los Arduino no suelen pensar en aquellas aplicaciones de tiempo crítico) pero no hay alternativas si se pretende tener el rendimiento buscado.
diagrama de conexionado
Sin implementar de momento. Veré de utilizar en lo próximo algunos de los periféricos de comunicaciones del controlador. Los primeros vistazos al USART no son muy alentadores. El baudrate máximo es FOSC / 16 (84mhz / 16 para nuestro caso = 5.25mhz), bastante por debajo de lo requerido para la resolución buscada.
Software
La librería es la de Arduino VGA con algunas modificaciones / agregados.
En este caso ArduinoDueVGAEngine.cpp, producto de las características del microcontrolador está íntegramente escrita en C a diferencia de la anterior que está escrita mayormente en ensamblador (generación de video) por cuestiones de rendimiento.
Para la generación de las señales de sincronismo utilicé uno de los 9 timers de 32bits disponibles.
Las señales de sincronismo no tienen latencia (o es despreciable), producto de que se utiliza la funcionalidad "generación de señales" del timer. La señal de video se realiza dentro de la rutina de interrupción. Como en cualquier controlador existe una pequeña latencia variable entre el tiempo configurado y la ejecución de la rutina (código). Para compensar esto, en el artículo anterior realicé una rutina de demora variable. Luego de las primeras pruebas, al no poder "dar pié con bola" me interioricé con el funcionamiento del controlador y descubrí que cuenta con un Pipeline de 3 etapas; Hablando en criollo es capaz de ejecutar mas de una instrucción por ciclo de ejecución motivo por el cual es extremadamente dificultoso realizar rutinas de demora con la exactitud requerida. Esto deriva en un defecto de Jitter de video.
Las señales de sincronismo no tienen latencia (o es despreciable), producto de que se utiliza la funcionalidad "generación de señales" del timer. La señal de video se realiza dentro de la rutina de interrupción. Como en cualquier controlador existe una pequeña latencia variable entre el tiempo configurado y la ejecución de la rutina (código). Para compensar esto, en el artículo anterior realicé una rutina de demora variable. Luego de las primeras pruebas, al no poder "dar pié con bola" me interioricé con el funcionamiento del controlador y descubrí que cuenta con un Pipeline de 3 etapas; Hablando en criollo es capaz de ejecutar mas de una instrucción por ciclo de ejecución motivo por el cual es extremadamente dificultoso realizar rutinas de demora con la exactitud requerida. Esto deriva en un defecto de Jitter de video.
Como memoria de video se utiliza un vector de 76800bytes (320 x 240 x 8bits) como buffer intermedio de las rutinas de la clase pública y las rutinas de bajo nivel de generación de señal de video. Quedan disponibles para la aplicación ~21500 bytes de RAM.
Al igual que el proyecto original, la librería está compuesta por una clase pública para el usuario (ArduinoDueVGA.cpp) y una librería de bajo nivel (ArduinoDueVGAEngine.cpp) con las rutinas de generación de señal.
La misma es de código abierto (licencia a definir) y puede ser descargada desde la web de SourceForge desde aquí.
Para detalles sobre la utilización referirse a apartado Instalación / Utilización del artículo Arduino - Generación de señales de VGA con hardware estádar.
Resultados
- Aceptables en relación a simplicidad del circuito / software.
- La resolución de 320 x 240 pixeles es una de las clásicas (junto con la 320 x 200) de demoscene y juegos de los 80's / 90's es suficiente para lograr representaciones aceptables.
- Independientemente del aumento de la potencia de cálculo, la generación de señal de video continúa siendo una tarea crítica:
- La utilización de rutinas de interrupción "pesadas" puede generar Jitter de video.
- El tiempo de procesador disponible ronda el 8%,
- No le encontré la vuelta para poder generar la señal de video sin Jitter, producto de las latencias en la ejecución de rutinas de interrupción y del tiempo de ejecución variable por instrucción (Pipelines). Se observa en la imagen siguiente el defecto.
Ejemplos
Van un par de videos de ejemplos de utilización:
El primero un ejemplo que va junto con la librería de varios efectos de demoscene, algunos fractales y fuentes.
El segundo un clon de Pacman en desarrollo (a medio terminar) que no forma parte de la librería. En cuanto lo termine lo publicaré y formará parte del contenido del blog.
En lo próximo
Tal como lo había propuesto en el artículo anterior, tengo diseñado desde hace ya algunos meses un Shield (económico) para Arduino con un controlador mas potente (ATxmega) exclusivo para la generación de señales de video, memoria RAM onboard y algún que otro chiche.
En cuanto tenga un rato voy a "cocinar" el impreso y empezaré a escribir algo de código.
Estará disponible en cuanto lo tenga listo para publicar (al ritmo que vengo lamentablemente dentro de un año :P).
Doy por terminado este artículo, espero el contenido haya sido de utilidad.
Cualquier duda no duden en consultar, nos vemos en la siguiente entrada.
Saludos, Luis.-
Arduino - Generación de señales de VGA con hardware estádar
http://luispichio.blogspot.com.ar/2015/05/arduino-generacion-de-senales-de-vga.html
Arduino Due
https://www.arduino.cc/en/Main/ArduinoBoardDue
https://www.arduino.cc/en/uploads/Main/arduino-Due-schematic.pdf
En cuanto tenga un rato voy a "cocinar" el impreso y empezaré a escribir algo de código.
Estará disponible en cuanto lo tenga listo para publicar (al ritmo que vengo lamentablemente dentro de un año :P).
Doy por terminado este artículo, espero el contenido haya sido de utilidad.
Cualquier duda no duden en consultar, nos vemos en la siguiente entrada.
Saludos, Luis.-
Referencias
http://luispichio.blogspot.com.ar/2015/05/arduino-generacion-de-senales-de-vga.html
Arduino Due
https://www.arduino.cc/en/Main/ArduinoBoardDue
https://www.arduino.cc/en/uploads/Main/arduino-Due-schematic.pdf
Calculador ladder: RL-DAC
https://raronoff.wordpress.com/2012/10/17/rl-dac/
Muy interesante tu post. Podrías explicar como influye la velocidad del procesador o el tamaño de la ram más detalladamente. Quiero controlar una pantalla flatron de 1366x768 pixeles de resolucion usando un microcontrolador TIVA TM4C123GH6PM DE 80 MHz, 256KB DE FLASH Y 32KB DE RAM. Ayuda ,por favor.
ResponderBorrarBuenas! Muchas gracias por comentar / participar.
BorrarHay un artículo previo en el que explico con un poco mas de detalle de video utilizando DAC en escalera: Arduino - Generación de señales de VGA con hardware estádar (https://goo.gl/C2zkDs).
Trato de resumir en algunas líneas:
El controlador debe generar varios niveles de tensión (de 1 a 3) * cada píxel de la pantalla * la tasa de refresco.
Partiendo de la resolución propuesta 1366x768x60hz (la tasa de refresco la define el estándar):
Generación de señales:
1366 x 768 -> 1049088 píxeles (una pantalla / frame)
1049088 píxeles x 60hz -> 62945280 de "cambios de nivel" por segundo (60 frames / segundo).
Estaría muy justo en relación a la frecuencia de reloj del controlador propuesto (80MHz) (en rigor no da porque estoy obviando "señales adicionales" de sincronismo y "tiempo de blanqueo" que también deben ser generadas).
RAM
En los ejemplos propuestos se utiliza un buffer en memoria RAM "intermedio" en donde "dibujan" las rutinas del usuario. El contenido del buffer, paralelamente se utiliza para generar las señales de video.
1366 x 768 = 1049088 píxeles, a 256 colores por pixel (por poner algo) -> 1049088 bytes de RAM (solo hay 32KB).
Estamos muy lejos en relación a la RAM disponible (incluso en monocromático serían 131136bytes de RAM los requeridos).
Conclusión: esconozco detalles de la aplicación, pero probablemente sea mejor sacrificar resolución o utilizar alguna alternativa (FPGA) para la generación de video.
Saludos.-
Este comentario ha sido eliminado por el autor.
ResponderBorrarHola Luis,
ResponderBorrarMuy buen post. Tengo una pregunta, yo en mi caso no puedo utilizar el Puerto Serie 3 ya que lo tengo ocupado. ¿Es posible cambiar algo en la librería para utilizar el Puerto Serie 2? He mirado por encima pero no encuentro donde se puede hacer.
Saludos
Buenas José, perdón por la tardanza (tampoco te respondí el comentario en el blog).
BorrarRespecto a tu consulta: La librería utiliza los primeros pines del denominado PIOD (uno de los puertos disponibles que tiene el controlador del Arduino DUE).
Se podría cambiar el puerto (reemplazando PIOD en ArduinoDueVGAEngine.cpp de la librería por PIOA por ejemplo, aunque los pines para conectar las resistencias quedarían dispersos en los conectores).
Yo debería trabajar un poco en la librería para poder hacer configurable la selección de puerto y algunas mejoras respecto a la generación de video, tenía pensado hacerlo pero por diferentes motivos hace casi dos años que no toco el proyecto.
Tiempo después de escribir los artículos y trabajar en las librerías encontré el proyecto https://stimmer.github.io/DueVGA/ que es anterior al mío y está bastante mejor resuelto.
Genera las señales de VGA por DMA con lo cual deja mucho mas tiempo disponible para procesamiento.
Te recomiendo le des un vistazo (inclusive utiliza otros pines para la generación de video).
Saludos!