VideoJuegoPIC - Funcionamiento
 

El diseño del hardware es absolutamente simple. La fuente de alimentación es justamente un regulador estándar 7805 para conseguir el voltaje a 5v, y tiene un diodo y un casquillo en la entrada así que puede ser alimentada con CA y C.C. (el voltaje de entrada debe ser 8.15v ).
Dos joysticks de C64/Amiga/Atari se utilizan como entrada para los juegos. Cada mando tiene cuatro interruptores de dirección (encima, abajo, de izquierdo, de derecho) y un interruptor de fuego.
El vídeo es generado por dos bits DA, usando solamente dos resistencias y la impedancia de entrada de la TV. Para poder conseguir una resolución más alta, el software utiliza PORTB como registro.
El audio tiene un solo bit  de tal modo que se limita a una señal de audio cuadrado. El potenciometro de 1k y la resistencia de 2k7 forman un divisor del voltaje que hace un límite ajustable del voltaje de cero a 5*1/(1+2.7) =1,35v que asume que la resistencia de  carga es mucho más grande que 1k. El audio puede solamente conducir una línea de entrada en una TV, un amplificador o algun similar, pero no auriculares o dispositivos similares con impedancia baja. Como la salida de audio es solamente una onda cuadrada los sonidos del audio son terribles pero al menos el sistema tiene sonido aunque que suena malo.

Palancas de mando.

Img_01
Una palanca de mando clásica Tac2
Los joysticks usados para este juego son viejas palancas de mando de C64/Amiga/Atari.
Img_02
Diagrama esquemático para la palanca de mando compatible 64 de la CA
.

Conectar el sistema con una TV.

Conectamos el sistema con una TV usando un cable scart.
Img_03
Diagrama esquemático para el sistema que conecta a una SCART-entrada.

 

 

Cómo generar las señales de video en software usando el PIC

 

Señales video
Para entender un poco  sobre la generación de las señales video en tiempo real, se debe saber como trabajan las vídeo-señales detalladamente.


Cómo funciona una TV estandar.
Un TV estándar se construye con un tubo de vacío, que tiene una pantalla de fósforo en la cual un cañón bombardea con electrones. Cuando los electrones del cañón golpean la pantalla, el fósforo emite luz mientras el cañón tire a electrones en él, y también tiene una posluminiscencia corta. El haz electrónico del electrón se puede doblar usando los imanes así que tira en diversas partes de la pantalla. Si se controla esto así,  dibuja líneas horizontales por todas partes en la pantalla en varias pasadas, mientras que la intensidad de la línea es controlada, una imagen se puede dibujar en la pantalla. La pantalla es redibujada 25 veces por segundo en un sistema PAL, pero al reducir oscilación la imagen se entrelaza, mostrando primero  todas las líneas impares uniformes, así que la imagen es parcialmente actualizada 50 veces por segundo. Hay que agradecer a la “persistencia del efecto de la visión” del cerebro humano que la imagen  parece ser constante en vez de oscilar a 50Hz. Para conseguir a color cada punto de la pantalla se divide en tres colores: rojo, verde y azul, no obstante aquí discutiremos solamente la televisión en blanco y negro, porque eso es solamente lo que es posible generar tiempo real en software usando un PIC.


1

1

El haz electrónico que dibuja la pantalla

Las imágenes bipartitas se convierten en una imagen entera.

Diversos estándares de la TV
Hay tres TV-estándares importantes: NTSC, SECAM y PAL. El NTSC es el TV-estándar americano, tiene solamente 525 líneas, pero tiene una frecuencia de  actualización de 30Hz. SECAM  es el TV-estándar francés, ha mejorado la resolución de la estabilidad de color y de intensidad más alta pero con menos resolución del color. El estándar europeo es PAL (líneas que se alternan de fase, tiene 625 líneas por marco, 25 marcos por segundo. Se basa en NTSC, pero la codificación de color ha sido mejorada usando un desplazamiento de fase en cada línea para quitar los errores del color que se daban con NTSC.

La información en la señal video
La imagen considerada en la pantalla tiene diversas intensidades. Como los barridos del haz electrónico sobre la pantalla, la intensidad que debe estar en la posición de la línea, se envía como nivel voltaico en la señal video. No hay información en esta señal de intensidad sobre la que está el haz electrónico en la pantalla. Para solucionar esto, un pulso de sincronización se envía  al principio de cada línea para decir que la línea actual de TV está acabada y para bajar el haz electrónico a la línea siguiente. (Como la llave del <Enter> en el teclado, al escribir un texto con una computadora) La TV debe también saber cuándo está viniendo una nueva imagen, esto se realiza haciendo un patrón especial de la sincronización. (Como la función del “nuevo documento” al escribir un texto con una computadora) una imagen que es 25 veces actualizadas por segundo estaría oscilando absolutamente,  por consiguiente todas las líneas uniformes se dibuja primero y entonces todos los impares, muestreando de este modo 50  imágenes por  segundo, haciendo que el cuadro oscile menos. Las líneas o impares de la información se envían en el patrón de la sincronización vertical, como diversos patrones para las imágenes impares y uniformes. La señal de video tiene una gama de voltaje de 0 a 1V, donde 0.3V representa negro, y 1.0V es blanco (las intensidades grises tienen voltajes entre estos valores). Los niveles cerca de cero representan pulsos de sincronización.


1

Cuadro del “osciloscopio” - de una explorar-línea

Las líneas
La imagen se divide en líneas, él es la parte más importante de la imagen puesto que contiene los datos de la imagen. Las líneas son de 64us de largo. Primero un pulso largo de sincronización de 4us es enviado, fijando la señal llana a 0V, para decir la TV que está viniendo un giro nuevo. Las viejas TV eran más lentas, así que necesitaban 8us después del pulso para conseguir el haz electrónico en la posición. Durante este tiempo la señal se guarda en el nivel negro. El retraso de 8us es seguido por los datos de la imagen para 52us, dibujados en la pantalla de izquierda a derecha con las intensidades obtenidas de la señal video. El negro es representado por 0.3V y como el voltaje aumenta la intensidad, con la intensidad máxima se tiene 1.0v (blanco).

Juntando las líneas como una imagen
Una imagen se construye de 625 líneas, pero una TV no muestra 625 líneas. Algunas de las líneas se utilizan para los pulsos de sincronización, y algunas líneas son invisibles porque las viejas TV necesitaron un cierto tiempo para mover el haz electrónico desde el fondo de la pantalla. (Esas líneas invisibles se utilizan hoy en día para otros propósitos, Texto-TV por ejemplo).


1

Cuadro del “osciloscopio” - de varias íneas en una señal video.

Los pulsos de sincronización vertical.
Para decirle a la TV que esté viniendo una nueva imagen, un patrón especial de pulsos de sincronización es enviado. Puesto que el cuadro se construye a partir de dos medios cuadros, el patrón es diferente para las imágenes impares y uniformes. La sincronización vertical es la siguiente:


1

Este cuadro muestra los diversos pulsos de la sincronización vertical para las dos medias imágenes. Los niveles son 0v y 0.3v.

Cómo  hacerlo en software
Esta es la parte sobre cómo crear la señal de video en el software, no será posible entenderlo si no se entiende la materia de la señal video descrita arriba.
Cuando se sabe como debe ser la señal de video que se quiere, es absolutamente fácil generarla en software, si tienes energía de proceso ilimitada. El problema es que requiere mucha energía del procesador, pero si no tienes un procesador de gran potencia que pueda  hacerlo, de todos modos, se puede hacer pensando antes el código a escribir.
En mis ejemplos del código en esta parte utilizaré las dos macros siguientes:
DNOP - nop dual, una macro para esperar dos ciclos de reloj, en vez de dos nops
DELAY – Un retraso de la macro que retrasa 3 veces el número de pulsos en el registro W.


El hardware
Para poder generar una señal video, es necesario un mínimo hardware para poder generar niveles de señal entre 0 y 1V. Para conseguir un cuadro necesitaremos por lo menos 3 niveles. La TV necesita una sincronización y el nivel negro poder generar la señal video. Si deseas más que una imagen negra necesitarás un cierto nivel gris o blanco. Una cierta clase de convertidor digital a analógico es necesaria, por lo menos de 2 bits para conseguir diferentes niveles. La impedancia de entrada en una TV estándar es de 75 ohmios, y usando dos resistores y un CDA de 2 bit se puede crear (como en las imágenes abajo) gracias a la división del voltaje.


1

Conectando ambos D0 y D1 con la tierra, el voltaje en la entrada de la TV será 0v (nivel de la sinc.) porque no se conecta nada con VDD.

1

D1 que conecta a la tierra y D0 a 5v, pondrá el resistor 450ohm paralelamente a la impedancia de la entrada 75ohm de la TV, y con el resistor 900ohm conectado en serie, y lo agradece a la división del voltaje que éste genera 0.33v en la entrada de la TV, y ése es absolutamente negro. (el nivel negro verdadero es 0.3v)

1

D1 que conecta a la tierra y D0 a 5v, pondrá el resistor 900ohm paralelamente a la impedancia de la entrada 75ohm de la TV, y con el resistor 450ohm conectado en serie, y lo agradece a la división del voltaje que éste genera 0.67v en la entrada de la TV, y ése es gris.

1

Conectar ambos D1 y D0 con 5v, pondrá el resistor 450ohm paralelamente al resistor de 900 ohmios, con la impedancia de la entrada 75ohm de la TV conectada en serie, y lo agradece a la división del voltaje que éste genera 1.0 en la entrada de la TV, y ése es nivel blanco.

Con este circuito, cuatro niveles pueden ser creados. La imagen arriba muestra los circuitos equivalentes para los cuatro diversos niveles y cómo se crean los voltajes. Los valores del resistor no son críticos, se podrían utilizar los valores más estándares 470 y 1k en vez de 450 y de 900.


Software contra señales video generado por componentes físicos.
En un sistema video estándar como el de la tarjeta de un PC, la información gráfica sobre lo que se va a dibujar en la pantalla se toma de una memoria. Esto se hace automáticamente en hardware. Los pulsos de sincronización también se crean automáticamente en hardware. En un PIC16F84 hay una memoria de 68 byte, y esa memoria se debe también utilizar para otros propósitos . No es posible almacenar la imagen entera en memoria como en tarjetas gráficas, la imagen tiene que hacerse generado barridos de la señal video a través de la pantalla. La generación de las señales video en software en un procesador tan simple es difícil, sólo las imágenes muy simples pueden ser creadas. La ventaja es que es absolutamente barata.

Una línea, haciendo una barra vertical.
Creando línea con la información del color gris-negro-blanco-negro-gris, y repitiendo la  línea indefinidamente, una imagen se podía ver en una TV. La señal contiene un pulso horizontal, seguido por el retraso y de la información del color, así que la TV podría trabar  la señal horizontalmente.

1

1

La señal de video generada por el código abajo aparecería esto en un osciloscopio. Los niveles bajos son las barras negras, y el nivel grande en el centro es la barra blanca.

La señal video generada por el código abajo parecería esto si estuvo entrada en una TV. Dos barras negras y una barra blanca. (La frontera marrón se supone para ser la TV)

El problema con la resolución pobre
En un PIC16F84 @ 12Mhz, se realizan 3 millones de instrucciones por segundo, durante exploración de línea de 64us, se realizan 192 instrucciones, y durante la parte visible de los 52us solamente 156 instrucciones pueden ser realizadas. Si el valor del DA se fija para cada instrucción durante los 52us, conseguiríamos una resolución de 156 píxeles en el eje x, que es realmente malo. Lo que es incluso peor es que los 156 píxeles no se pueden utilizar exactamente como deseas, apenas se pueden calcular el valor de un píxel en un ciclo de reloj a menos que sean siempre iguales así que puede ser generado por una instrucción de un bit del sistema.


Obteniendo una resolución más alta cambiando los datos.

Si deseamos mostrar 8 píxeles en blanco y negro, almacenado en un bit de memoria se haría algo así:


movlw 8

; el número de píxeles es 8 (1)

contador del movwf

; fijar opuestamente al número de los píxeles (1)

shiftloop:

 

movlw COLOR_BLACK

; color determinado del defecto al negro (1)

thedata del rrf, f

; rotar los datos a la derecha, pone el pedacito adentro llevan (1)

skpnc

; comprobar si llevar, si no el píxel sigue siendo negro (1 o 2)

movlw COLOR_WITE

; llevar fue fijado, fijan color al blanco (1)

movwf VIDEO_PORT

; fijar el color a DA (1)

contador del decfsz

; disminuir al revés, comprobar para saber si hay cero (1 o 2)

shiftloop goto

; si más píxeles, guardan el colocar (2)


thedata del movfw

; instalar el octeto que se cambiará de puesto hacia fuera (1)

movwf PORTB, f

; el primer pedacito llega a ser visible ahora (1)

rrf PORTB, f

; el segundo pedacito se cambia de puesto hacia fuera (1)

rrf PORTB, f

; el tercer pedacito se cambia de puesto hacia fuera (1)

rrf PORTB, f

; el cuarto pedacito se cambia de puesto hacia fuera (1)

rrf PORTB, f

; el quinto pedacito se cambia de puesto hacia fuera (1)

rrf PORTB, f

; el sexto pedacito se cambia de puesto hacia fuera (1)

rrf PORTB, f

; el séptimo pedacito se cambia de puesto hacia fuera (1)

rrf PORTB, f

; el octavo pedacito se cambia de puesto hacia fuera (1)

Este código hace salir los bit de un byte al puerto de video, como el ejemplo anterior, pero éste es mucho más rápido, aunque requiere cambiar los pins.


1

Los caracteres se dibujan solamente en cada segunda línea como se describe anteriormente.

El ejemplo de arriba usa un pulso de reloj por bit, dando una resolución de 156 píxeles. En el juego del pong que el tiempo de setup se puede ver cuando el texto se exhibe en la pantalla, se hace usando este método, Las secuencias son 8 caracteres  pero sería posible conseguir 10 caracteres en la pantalla. En pong, los bits que se cambiarán de puesto se toman de una posición de memoria que contiene  8*8 bits = 8 byte. Para cada línea estos 8 bytes tienen que ser calculados leyendo los caracteres de la secuencia de los datos de la eeprom, donde se almacena, y después conseguir el mapa de bits correcto , y almacenar los datos de imagen en la memoria. Hacer esto para 8 caracteres toma mucho tiempo, así que se hace durante un scanline entero. La razón por la que el texto solamente exhibe una línea cada segundo es que el procesador está calculando la línea siguiente para mostrar durante las líneas negras entre líneas exploradas de los gráficos.
Así pues, este método permite mostrar gráficos con una resolución mucho más alta, pero ocupa el PORTB entero durante la operación. Puede ser que parezca al principio imposible utilizar el PORTB para hacer otra cosa más, pero es posible. Puede ser utilizado fácilmente como salida si un pin, el PORTA, se utiliza para inhabilitar el hardware unido a PORTB cuando se utiliza como registro de cambio. Es también posible utilizarlo como entrada cuando no está siendo utilizado para cambiar un registro. En los juegos se necesitan muchos pins para conectar el joystick, pero conectar el joystick  directamente es peligroso, porque cuando se usa el joystick utilizado como salida podría quemarse el buffer del puerto. Esto se soluciona usando resistencias pull-up de 100k, y las resistencias de protección de 1k. Esto da un voltaje cerca de cero, cuando se pulsa el interruptor del joystick , cuando el joystick es leído por el puerto, pero para proteger el puerto contra cortocircuitos a tierra cuando es utilizado como salida cuando el puerto se utiliza como registro de cambio.


La sincronización vertical.

Para conseguir que la TV saque la señal video, deben ser generados los pulsos verticales. Se puede hacer mediante el código siguiente:


Shortsync:

; etiqueta “Shortsync”, entrada para el generador corto de la sinc.

movwf counter1

; fijar counter1 al número de shortsyncs

shortsync_l0:

; etiquetar “Shortsync_l0”, entrada corta del lazo de la cuenta de la sinc.

porta del bcf, 0

fijar llano al synclevel (mordido 1)

portb del bcf, 0

; fijar llano al synclevel (mordido 0)

dnop

;

movlw 0x1d

;

movwf counter2

; fijar counter2 a “30us”

nop

;

bsf PORTA, 0

; fijar llano al negro

shortsync_l1

; etiquetar “Shortsync_l1”, sinc. corta retrasa el lazo

decfsz counter2

; retrasar el contar

shortsync_l1 goto

; el lazo si no acabó con retrasa

decfsz counter1

; número de la cuenta de shortsyncs

shortsync_l0 goto

; si más shortsyncs, guardan el colocar

retlw 5

; volver y fijar W al número de los longsyncs (5 longsyncs)

vertsync:

;

movlw 5

;

videostuff de los btfss, 0

;

movlw 6

;

shortsync de la llamada

;

videostuff del incf

;

longsync:

;

movwf counter1

; fijar el synccounter al número de los longsyncs (1)

longsync:

; etiqueta “longsync”

movlw 0x1d

; (1)

movwf counter2

; fijar opuestamente a 30us (1)

porta del bcf, 0

; fijar llano al pedacito 1 (1) de la sinc.

portb del bcf, 0

; fijar llano al pedacito 0 (1) de la sinc.

longsync_l1

; etiquetan “longsync_l1”, sinc. larga retrasan el lazo

decfsz counter2

; retrasar el contar (1)

longsync_l1 goto

; el lazo si no acabó con retrasa (3)

nop

;(1)

porta del bsf, 0

; fijar llano al negro (1)

nop

;(1)

decfsz counter1

; número de la cuenta de shortsyncs (1 o 2)

longsync_l0 goto

; si más shortsyncs, guardan el colocar (3)

movlw 5

; fijar el número de shortsyncs a 5 (1)

videostuff de los btfss, 0

; comprobar si segundo campo (1 o 2)

movlw 4

; sí, hacer 4 shortsyncs en lugar de otro (1)

shortsync goto

; hacer esos syncs cortos

 

 

Este código genera la sincronización de pulsos necesarios., según lo descrito anteriormente.

 

Los juegos

1



Pong.


La lógica del juego es sobre todo guardar la bola dentro de la pantalla. Las primeras líneas son apenas blancas, y es en las líneas superiores donde la lógica del juego está realizada. Para todas las líneas en el campo de juego verdadero hay dos clases de líneas, las que está con una bola y las que están sin ella. Primero muestra al que no tiene la bola, y si es necesario al jugador izquierdo, entonces la línea es negra hasta que el jugador adecuado debe ser mostrado (o no). Las líneas con una bola encendida son similares, con la diferencia de que la bola se debe demostrar en el área negra. Haciendo dos retardos en el PIC antes y después hace que se muestre la bola, donde los retardos dependen de la posición x de la bola. Desde que el reloj cuenta tres pulsos de reloj, la bola se mueve en pasos  grandes en el eje de las x.
En la parte inferior de la pantalla, se muestra el marcador. Se saca con el método descrito anteriormente. En la mayoría de las líneas la rutina  comprueba si el sonido está activo.
Todos los menús de texto tienen su texto almacenado en la eeprom en strings de tipo long char de 8bits.El texto se muestra solamente cada segunda línea porque en la primera línea el texto se extrae de la eeprom y los datos de memoria de imagen se almacenan en un área del buffer. En la segunda línea se muestra el resultado.


1



Tetris.


La lógica del juego Tetris primero se hizo con Borland C en el DOS en un PC, apenas para conseguir la lógica correcta antes de que fuera hecha para el ensamblador de PIC. Los bloques se almacenan en memoria en un formato comprimido, y después se descomprimen según el ángulo actual de un área de buffer donde se almacena como coordenadas relativas. Tres diferentes rutinas pueden utilizar el bloque en el área del buffer para operar en la pantalla. Estas rutinas son las que hacen posible que un bloque sea desplazado de un lado a otro y que pueda ser depositado cualquier bloque en la parte de abajo. La rutina de la salida es absolutamente similar a la que saca los caracteres a la pantalla, a excepción de que esta no tiene que estar rápidamente poniendo los píxeles negros entre los bloques, así que los cambios que hace para mostrar el campo de juego en la pantalla, es bastante fácil.
En la mayoría de las líneas se llama una rutina de música cambiando el canal de audio por intervalos con diversas frecuencias, está hecho en todas las líneas excepto las primeras. Debido a esto la música se distorsiona bastante. La música está en un formato comprimido en la eeprom, con un tono y una longitud almacenados en un byte. Todas las frecuencias tienen que ser un múltiplo de la frecuencia de líneas exploradas, así que las frecuencias no son exactamente correctas, y ésta hace que el sonido de la música sea incluso peor. Aunque el sonido es muy malo, al menos tiene sonido.
La puntuación se muestra con el método shift-out, sacar a la pantalla,  No hay menús en Tetris porque no había mas sitio en memoria.

 

Programación PIC

Que necesitamos:
-Programador T-20
-ICprog (Puedes descargarlo en la seccion descargas o aqui)
-Parche XP ICprog (Puedes descargarlo en la seccion descargas o aqui)
-Ficheros de los juego Tetris y Pong

Primerdo descargamos el ICprog y el parche y metemos los dos archivos en el mismo directorio, seguidamente ejecutamos el archivo icprog.exe. En la parte derecha superior seleccionamos el pic que vamos a utilizar (en este caso el pic 16f84A).


ahora conectamos el programador al ordenador mediante un cable rs-232 estandarizado y instalamos el pic como aparece en la imagen siguiente.

Seguidamente presionamos sobre -archivo>abrir datos>y seleccionamos el juego a cargar. Despues vamos a la pestaña comando y seleccionamos borrar todo (para asegurarnos de tener el pic en blanco). Una vez esto nos queda seleccionar comando y programar todo.

ya tenemos listo el pic para jugar.


 
 
Inicio | Funcionamiento | Materiales | Descargas | Fotos y Videos | Fotolitos | Links | Acerca de
  ©VideoJuegoPIC Freelance web designer