Documentos de Académico
Documentos de Profesional
Documentos de Cultura
2
5 Diseño de módulos VHDL ..................................................................... 34
5.1 Conversión de entrada ......................................................................... 34
5.2 Conversión de salida............................................................................ 37
5.3 Análisis de regiones ............................................................................. 38
5.4 Contadores de posición ....................................................................... 41
5.5 Captura de imagen................................................................................ 45
5.6 Generador OSD..................................................................................... 49
5.7 Comunicación. Esclavo de I2C............................................................ 51
6 Uso y verificación del sistema completo ............................................. 55
6.1 Montaje provisional del sistema.......................................................... 55
6.2 Montaje y configuración del sistema completo ................................. 57
6.3 Control del sistema LVDS Capturer vía Telnet................................... 59
7 Arquitectura del software ...................................................................... 67
7.1 Desarrollo de librerías .......................................................................... 67
7.1.1 DLL para la comunicación con la ESIIC ............................................... 68
7.1.2 DLL para la obtención de un fichero bitmap.......................................... 71
7.2 Secuencia de test.................................................................................. 73
7.2.1 Análisis de regiones................................................................................ 74
7.2.2 Captura de regiones ................................................................................ 76
8 Implementación en la línea de producción .......................................... 80
8.1 Montaje final y proceso de la máquina de test................................... 80
8.2 Subsecuencia de video adaptada........................................................ 82
8.3 Incidencias ............................................................................................ 84
9 Conclusiones.......................................................................................... 85
10 Bibliografía.............................................................................................. 86
11 Anexos .................................................................................................... 87
3
1 Introducción
El problema que plantea el sistema actual, y que se pretende solucionar con este
proyecto, consiste en que estas máquinas de test no son capaces de comprobar
exhaustivamente la señal de video enviada al panel. En la actualidad el método que se
lleva a cabo para comprobar la señal de video varía según el tipo de señal entrante al
televisor, permitiendo comprobar que se transmite algún tipo de señal hacía el panel, no
que dicha señal llegue al conector de salida de la placa de TV y mucho menos que la
señal enviada sea la correcta.
Esta comprobación del video de salida, incompleta y poco rigurosa, produce que placas
defectuosas pasen satisfactoriamente por el proceso de verificación y continúen su
camino por la línea de producción detectándose el problema al final, cuando el LCD ya
se encuentra totalmente montado, produciendo un gasto innecesario, tanto material
como humano.
Para solucionar el problema, se propone un sistema que sea capaz de analizar la imagen
de salida antes de que el televisor LCD se empiece a montar. Este sistema debe permitir,
por tanto, analizar la imagen de salida de la placa del televisor en ausencia de cualquier
interfaz visual, ya que en esta etapa de verificación no se dispone de un panel con el que
poder analizar fácilmente la imagen mediante cámaras.
Por último, se desarrolla un software que aprovecha todas las capacidades del hardware
diseñado, permitiendo controlar el sistema a través de un ordenador con conexión
ethernet, y recibiendo por esta misma conexión, tanto los resultados de las regiones
analizadas como la propia región.
4
2 Conceptos básicos
Este capítulo tiene como finalidad presentar los conceptos básicos que pueden aparecer
al hablar de televisores LCD, introduciendo brevemente al lector en la terminología
técnica que rodea a este proyecto. Se aprovecha también para realizar una primera
aproximación al sistema de verificación de las placas de televisores LCD que se utiliza
hoy en día en Sony(Viladecavalls). Finalmente se explica de forma más exhaustiva la
finalidad del proyecto que se presenta en este documento.
Entre los principales objetivos que persigue la alta definición se encuentran los
siguientes:
Que una resolución sea de 1920 x 1080 píxeles no implica que la imagen sea Full HD,
ya que este concepto no depende solo de la resolución que es capaz de alcanzar el
televisor, sino también del modo en que lo hace. Actualmente existen dos modos con
los que se puede alcanzar esta resolución, el modo entrelazado y el modo progresivo,
que respectivamente forman las resoluciones 1080i y 1080p, con i de "interlaced" y con
p de "progressive".
5
Para el caso entrelazado(1080i) se divide la imagen en 2 partes del mismo tamaño y en
cada refresco solo se actualiza una de estas partes, más concretamente en un refresco se
actualizan las columnas impares y en el siguiente las pares. Este comportamiento
fraccionado no es totalmente percibido por el usuario ya que al realizarse a altas
velocidades ambas imágenes se acaban fusionando. En el peor de los casos se puede
llegar a detectar una ligera sensación de parpadeo.
Por otra parte, el escaneado progresivo genera en cada refresco todas las columnas de la
imagen en orden, por tanto si en ambos casos 1080i y 1080p tenemos la misma
velocidad de refresco, esto se traduce en que la FHD(1080p) tiene el doble de
definición.
Un concepto muy extendido hoy en día es el conocido como "HD Ready". Este
término, que literalmente se traduce como "preparado para la alta definición", no es un
formato sino un distintivo europeo que garantiza que un dispositivo está preparado para
funcionar con alta definición. Un televisor con este distintivo se caracteriza porque
como mínimo es capaz de ofrecer una resolución de 720p, y por tanto, acepta entradas
de alta definición.
Aunque hoy en día los formatos para televisores más frecuentes del mercado suelen ser
del tipo FHD o HD Ready, no hay que olvidar que existe una gran variedad de
estándares clasificados básicamente según su resolución y relación de aspecto.
6
2.2 Señal LVDS
Las siglas LVDS se utilizan para definir un tipo de señalización diferencial de bajo
voltaje ( Low Voltage Differential Signaling). Este tipo de señalización permite la
transmisión a altas velocidades sobre medios de transmisión económicos.
En este sistema la señal se transmite por duplicado, por una de las líneas se envía la
señal con signo positivo y por la otra línea la misma señal pero con signo negativo. El
protocolo LVDS utiliza esta diferencia de tensión entre las dos líneas para codificar la
información.
Una de las ventajas del LVDS consiste en que al usar amplitudes de tensión bajas y
mantener un bajo acoplamiento tanto eléctrico como magnético entre ambas líneas se
reduce drásticamente la cantidad de ruido electromagnético generado. Además al tener
una tensión en modo común muy baja (alrededor de 1,25V) el LVDS puede ser usado
con un amplio rango de circuitos integrados con tensiones de alimentación de 2,5V o
menores. Por otra parte, la baja tensión diferencial (alrededor de 350 mV) provoca que
la comunicación LVDS consuma muy poca potencia comparándola con otros sistemas.
7
Hay que remarcar que el protocolo LVDS no especifica un esquema de codificación
concreto, LVDS es simplemente un mecanismo físico para transportar bits a través de
dos líneas y por tanto no incluye bits de start, stop, etc. Por tanto cualquier codificación
especificada por un usuario puede ser enviada y recibida a través de un enlace LVDS.
Por último, añadir que la mayoría de los transmisores LVDS están diseñados para
enlaces de transmisión punto a punto, aunque sistemas de bus multipunto se pueden
llevar a cabo usando transmisores LVDS modificados con salidas capaces de
proporcionar una corriente lo bastante elevada como para atacar múltiples resistencias
de terminación.
2.3.1 Funcionamiento
Cada píxel del panel LCD a su vez se divide en tres partes, conocidas como subpíxels,
de color rojo, verde y azul.
Cada subpíxel está formado por una capa de moléculas de cristal liquido alineadas y
situadas entre dos electrodos transparentes y dos filtros de polarización, normalmente
perpendiculares entre si.
8
de alineación de los electrodos son perpendiculares entre sí y las moléculas de cristal
líquido se organizan de forma helicoidal. Debido a esta organización, la luz que
atraviesa el primer filtro, aproximadamente la mitad de la incidente, gira por culpa del
cristal líquido atravesando con la polarización correcta el siguiente filtro y generando
imagen.
Por contra, cuando se aplica un voltaje a los electrodos, las moléculas de cristal líquido
se orientan paralelas al campo eléctrico y dejan de seguir una estructura totalmente
helicoidal. A mayor voltaje aplicado más perpendicular se va volviendo la luz incidente
al segundo filtro de polarización y por tanto en mayor medida será bloqueada.
Las pantallas LCD actuales no emiten luz propia, por tanto, necesitan luces de alta
potencia en la parte trasera del panel con las que proporcionar el brillo necesario a la
imagen. A esta luz trasera se le conoce como backlight o retroiluminación y existen
diversos tipos:
LEDs: Consiste en usar diodos LED. Éstos emiten luz blanca muy brillante,
consumiendo menos energía y desprendiendo menos calor que los CCFL. Además, el
tiempo de vida de un LED es muy superior al de los tubos fluorescentes. También
proporcionan una mayor gama cromática y una iluminación más uniforme en todo el
panel. Su mayor precio respecto a los CCFL ha provocado que su cuota de mercado
por el momento sea reducida, extendiéndose su uso en los LCDs de alta gama.
OLEDs: Utiliza diodos orgánicos emisores de luz, que se basan en una capa
electroluminiscente formada por una película de componentes orgánicos que
reaccionan a una determinada estimulación eléctrica, generando y emitiendo luz por sí
mismos. Esta nueva generación, que actualmente se encuentra en fase de desarrollo,
supera las limitaciones de los LCD-TFT actuales permitiendo que sean más delgados
y flexibles, ofreciendo mayor brillo y contraste. Además ofrecen mayor ángulo de
visión y menor consumo. Al encontrarse en fase de desarrollo y debido a que el
formato LED aún no es el predominante en el mercado, los fabricantes de televisores
LCDs han decidido retrasar su lanzamiento, haciendo imposible encontrar cualquier
dispositivo en el mercado que trabaje con esta tecnología.
9
2.3.3 Interfaz de entrada
Normalmente, un panel LCD tiene dos conectores de entrada, aunque hay casos en que
ambos conectores se integran en uno solo. Por uno de ellos se reciben las señales de
control y los bits de RGB, transmitidos en forma de señales diferenciales, que formarán
la imagen. El otro conector suele recibir la salida de un circuito conocido con el nombre
de inverter, encargado de coger una tensión de entrada DC e invertirla a una tensión AC
de alto voltaje, esta tensión posteriormente se aplica a los fluorescentes que generan el
backlight del panel.
En este apartado nos centraremos en las señales transmitidas por el conector de datos, el
encargado de transferir al panel la sincronización y los bits que conformarán la imagen.
En el caso de un panel FHD, el conector se divide en dos subpartes, una referente a los
píxels impares, y otra a los píxels pares. Cada subparte está formada por 4 pares de
líneas diferenciales, encargadas de transmitir los valores R,G y B de cada píxel, y una
línea de reloj de 74.25 MHz, también diferencial, para sincronizar dichos píxels.
Input Terminal
Píxeles impares Píxeles pares
RO0- RE0-
RO0+ RE0+
RO1- RE1-
RO1+ RE1+
RO2- RE2-
RO2+ RE2+
RO3- RE3-
RO3+ RE3+
ROCLKIN- RECLKIN-
ROCLKIN+ RECLKIN+
Figura 4. Líneas diferenciales entrantes a un LCD
10
Figura 5. Ordenación de trama en formato NS
11
En las dos figuras anteriores cada hexágono representa un bit concreto. Por ejemplo, RX
representa el bit X del byte de color rojo, de igual manera ocurre con GX y BX.
También podemos apreciar que aparte de los bits correspondientes a los 24 bits de color,
aparecen dos señales más, DE y NA. DE es la señal de control que indica el inicio de un
nueva imagen o de una nueva línea. Su funcionalidad es claramente de sincronización y
permite junto con la señal de reloj, la representación correcta en el panel de cada píxel
enviado. En la figura 7 se puede observar como la señal DE indica el inicio de un nuevo
frame generando un pulso acompañado de un tiempo de silencio Tblk(v). Después de
este periodo de silencio aparecen pulsos de forma continuada, donde cada uno de ellos
indica el inicio de una nueva línea de la imagen, así hasta el siguiente tiempo de silencio
Tblk(v) que indicará el inicio del siguiente frame.
12
Por otra parte, los campos marcados con NA en las figuras 5 y 6, corresponden en teoría
a posiciones vacías, no obstante 2 de los 3 campos marcados con NA, los
correspondientes a la línea diferencial RIN2, transportan dos señales de gran utilidad
VSYNC y HSYNC. Estas señales realizan prácticamente la misma funcionalidad que la
señal DE, indican del inicio de un nuevo frame y de una nueva línea respectivamente.
Por tanto, en la práctica existen dos formas de sincronización: una utilizando la señal
DE, y otra forma más popular, utilizando las líneas de sincronización vertical y
horizontal. No obstante, existe una gran diferencia entre ambos métodos. En la señal
VSYNC aparece un pulso cada vez que se inicia un frame, y en la señal HSYNC
aparece un pulso cada vez que se inicia una línea, pero que se inicie una línea no
implica que nos encontremos en la zona visible de la pantalla. Tras un pulso de
HSYNC pasan múltiples ciclos de reloj antes de que nos encontremos en la parte útil de
la pantalla y hasta que no llega este momento, no se están enviando píxels. Esto no
ocurre en el caso de sincronización mediante DE, ya que justo en el momento en que la
señal DE se activa, ya se encuentra en el bus el valor del primer píxel. Esto hace que la
sincronización mediante DE sea más cómoda de usar que la basada en H/VSYNC.
2.4 El entorno
Para detectar errores similares a estos antes de que el monitor esté totalmente montado,
Sony dispone de máquinas de test, conocidas como Vitams o CBAs. Estas máquinas se
situan después de la etapa de montaje de las placas de televisión, punto en que no se
dispone ni de panel, ni de cableado. La figura 9 se muestra una placa de un televisor
LCD, justo después de su montaje y lista para introducirse en la máquina de test.
13
Figura 9. Placa de TV del modelo EX2N.
En amarillo, el conector de salida LVDS hacía el panel
Los Vitams o CBAs por un lado incorporan unas secuencias de test que controlan las
electroválvulas que permiten introducir conectores, señales y alimentación a las placas.
Una vez las placas tienen todo lo que necesitan para funcionar, la máquina comprueba
que la placa, TV PCB (Print Circuit Board) en adelante, funciona correctamente, tanto a
nivel eléctrico como mecánico.
14
Aunque en este proceso se comprueba gran parte del funcionamiento de la TV PCB,
esta comprobación no es exhaustiva. Una de las comprobaciones no realizadas es el
caso que nos incumbe, la salida de imagen hacia el panel. En la actualidad, los
VITAMS, en cuanto a lo que imagen se refiere solo comprueban que la TV PCB
produce algún tipo de señal, pero no que dicha señal llegue al conector de salida, y
mucho menos que la señal de salida sea correcta.
Así, el proyecto que se presenta, nace con la finalidad de ampliar las verificaciones que
realiza dicha maquina de test. Como objetivo se plantea el desarrollo de un sistema
completo, hardware y software, que permita la captura y el análisis de la imagen de
salida de los televisores LCD Sony.
En la figura 10 se puede observar que estas máquinas de test están formadas por una
gran cantidad de dispositivos: ordenador, electroválvulas, fuente de alimentación,
generadores de señal, etc. Debido a que detallar el funcionamiento de esta máquina no
es el objetivo de este documento, solo comentaremos la parte que tiene relación directa
con el proyecto, es decir, la parte hardware/software que controla gran parte de este
sistema, la ESIIC.
15
La ESIIC(Ethernet Specific Interface I2C) es un sistema compuesto por un kit fabricado
por Altera y una plataforma diseñada por Sony. El sistema que se desarrollará en este
proyecto deberá mantener una comunicación con la ESIIC, ya que a través de ésta se
llevará a cabo tanto el control como el envio de información hacia el ordenador.
La plataforma diseñada por Sony es una placa conectada al kit anterior. Esta plataforma
actúa como dispositivo periférico y su finalidad es controlar gran parte del proceso de
verificación que realiza el VITAM. Entre sus principales características se puede decir
que tiene gran número de pines de entrada y salida, ya que consta de 2 FPGAs Cyclone,
es capaz de generar y recibir audio en múltiples formatos, dispone de switchs de HDMI
y genera VGA. No obstante, nosotros la usaremos, más que por estos periféricos,
porque nos facilitará el proceso de comunicación al disponer de las siguientes
características:
16
Figura 13. Plataforma de la ESIIC. A la izquierda cara top, a la derecha cara bottom
Debido a que la entrada de la placa LVDS Capturer será la imagen que sale por el
conector LVDS de la TV, se decide usar como conexionado el mismo tipo de cable que
se usa para conectar la placa de TV al panel.
Al pasar la imagen por nuestro hardware, éste debe ser capaz de seleccionar y analizar,
en tiempo real, zonas de la imagen o incluso la imagen FHD completa. En caso que se
desee, aunque no es la finalidad de este hardware, también debe permitir la captura y
almacenamiento de la imagen.
17
3 Descripción detallada del sistema
En el capítulo anterior se ha introducido al lector en el entorno que rodea nuestro
sistema. También, de forma algo genérica, se ha mostrado la finalidad y las
funcionalidades que deseamos que tenga el sistema desarrollado, así como la relación
que existirá entre la plataforma ESIIC y la placa LVDS Capturer.
Una vez dadas las nociones básicas, procederemos a describir con detalle las partes que
forman el sistema, y propondremos soluciones a los problemas que se irán presentando.
Para evitar la fabricación y el montaje de cables LVDS, formados por gran cantidad de
líneas que a la vez requieren gran precisión en su montaje, se decide utilizar el mismo
cable que utiliza la placa de TV EX2N para conectar con su correspondiente panel. De
esta forma se reducen por un lado posibles problemas relacionados con un montaje
incorrecto, por otra parte en caso de avería es fácilmente sustituible y por último, el
sistema diseñado para testear la imagen de salida será aún más parecido al caso real de
un televisor LCD.
El cable de líneas diferenciales LVDS que conecta por un extremo con este conector y
por el otro con el panel será el mismo que usaremos para interconectar la placa de TV
con la placa LVDS Capturer. Por este cable viajan multitud de señales, la mayoría
diferenciales, que contienen entre otras informaciones, los bits de la imagen que se está
enviando hacía el panel, o en nuestro caso, hacia el capturador de señales LVDS.
18
Línea cable LVDS Señal Tipo de Línea
1-5 VCC Alimentación para el inverter del panel
6-9, 16, 19, 24,31,34,39 GND Masa
10,11 RO[0] Línea diferencial impar 1( O=odd)
12,13 RO[1] Línea diferencial impar 2( O=odd)
14,15 RO[2] Línea diferencial impar 3( O=odd)
20,21 RO[3] Línea diferencial impar 4( O=odd)
17,18 ROCLK Línea diferencial de reloj. Píxels impares
25,26 RE[0] Línea diferencial par 1( E=even)
27,28 RE[1] Línea diferencial par 2( E=even)
29,30 RE[2] Línea diferencial par 3( E=event)
35,36 RE[3] Línea diferencial par 4( E=even)
32,33 RECLK Línea diferencial de reloj. Píxels pares
45 LVDS OPTION Orden de codificación de la trama enviada( NS o JETDA)
Figura 15. Contenido de las líneas que forman el cable de LVDS (visto desde el panel)
19
Figura 16. Diagrama de bloques de la conversión realizada por el THC63LVD104
A la hora de decidir el dispositivo a usar para este análisis se han barajado distintas
posibilidades, eligiendo finalmente una FPGA por los siguientes motivos:
En base a los anteriores motivos decidimos usar como núcleo de procesado la FPGA
Cyclone II EP2C8T144C7N de Altera, que dispone de 85 pines de entrada/salida
para usuario.
20
Teniendo en cuenta que uno de los requisitos que marcamos en el proyecto es que la
señal tenía que poder pasar a través de la placa LVDS Capturer de forma
transparente, necesitamos que las 29 líneas que salen del conversor LVDS a TTL
entren a la FPGA por 29 pins de entrada y salgan por otros 29 pins de salida. En
resumen, 58 pins de los 85 disponibles ya son ocupados solo con el paso de la señal
hacía el panel. Si además reservamos algunos pines para la etapa de comunicación
posterior y la colocación de algunos indicadores visuales del estado de la FPGA, se
puede ver que solo los bits correspondientes a los píxels pares ocupan una FPGA
entera, por tanto necesitamos otra para los píxels impares, siguiendo de esta forma
con la simetría par/impar que también hemos fijado en los conversores de entrada.
Como se ha dicho en apartados anteriores, la señal que llega del televisor y pasa por las
FPGAs, debe poder enviarse en el caso que sea deseado hacía un panel LCD, de esta
forma se podrían visualizar las modificaciones que realicemos en la imagen, o
simplemente verificar que la señal pasa por el sistema sin degradarse. Para poder
insertar esta imagen en el panel antes debemos devolverla a su estado inicial, es decir, al
formato LVDS que teníamos antes de pasar por los conversores de entrada.
21
Los siete bits correspondientes a TE0-6 no los usamos, la línea diferencial TE+/-
tampoco, y por tanto volvemos a tener las cuatro líneas diferenciales más una de reloj,
que era exactamente la mitad de la información que nos llegó a la placa LVDS Capturer
desde la televisión. Para seguir con la dualidad necesitamos dos conversores de TTL a
LVDS, uno para píxels pares y otro para impares.
Por los mismos motivos que se detallaron en el apartado 3.1.1 se decide utilizar para la
conexión entre la placa LVDS Capturer y el panel, el mismo cable que utiliza el
televisor en su estado final para unir la placa de TV con el panel.
Así el conector que debemos introducir en nuestro diseño es el que corresponde al otro
extremo del cable LVDS, es decir, el que inicialmente conectaba con la placa de
televisión, y por tanto la numeración de las líneas es distinta.
22
modificar la imagen de salida, capturar imagen y guardar los resultados para que
posteriormente sean leídos desde otro dispositivo.
Figura 19. Diagrama de bloques completo del sistema LVDS Capturer propuesto
23
4 Diseño y verificación del circuito
4.1.2 Reset
Con la finalidad de disponer de una señal de reset para las FPGAs se propone el uso del
integrado TLC77331D. Este integrado genera una señal de reset a partir de la actuación
sobre un pulsador externo o mediante una señal de control, además la duración de la
señal de reset es fácilmente configurable a través de un condensador externo. En nuestro
caso incorporamos las dos opciones, la manual y una señal controlable desde la ESIIC
por si deseamos realizar un reset vía software de las FPGAs.
24
Figura 20. Esquemático del módulo de reset
Por último remarcar, que las dos señales de clock, de 40MHz y de 74.25 MHz, no se
pueden introducir en cualquier pin de entrada de la FPGA. Si no tenemos en cuenta este
detalle podría darse el caso de que varios módulos implementados dentro de la misma
FPGA, que funcionan con la misma señal de reloj, no trabajen de forma coordinada, y
por tanto el resultado podría no ser el esperado. Este suceso ocurre porque la señal que
llega a un pin de entrada corriente no se reparte de forma equitativa por todas las partes
del dispositivo, esto provoca retardos entre distintos bloques hardware, es lo que se
conoce como skew. Para solucionar este problema las FPGAs suelen tener pines de
entrada dedicados para señales de reloj. Estos pins especiales se reparten de forma
equitativa por todas las partes del hardware interno, de esta forma se garantiza la calidad
y la sincronización de la señal en todo el dispositivo.
25
4.1.4 Conversores de nivel
• Un único master de I2C controla los esclavos de I2C de las dos FPGAs.
• Se utilizan dos masters de I2C. Cada uno controla el esclavo de una FPGA.
El active serial permite la grabación de un fichero .pof en una memoria externa, que
debe incluirse en el diseño. Este sistema tiene la ventaja de que el contenido que se
desea implementar en la FPGA se almacena en una memoria, y cada vez que se reinicia
el sistema, la FPGA lee la información que contiene esta memoria para configurarse de
forma automática.
La otra posibilidad de grabación, hace uso del sistema de test JTAG, para grabar un
fichero .sof de configuración en la memoria volátil de la FPGA. Este sistema permite
depurar fácilmente el sistema implementado dentro del dispositivo, no obstante su
duración es temporal. Al resetear, la información de configuración ha desaparecido y es
necesario repetir el proceso.
26
4.2 Restricciones de diseño
Una vez comentadas las principales del hardware del proyecto queda remarcar un
aspecto importante que forma parte de todo diseño electrónico, las restricciones.
Una restricción o condición importante que se debe tener en cuenta a la hora de realizar
un circuito impreso que trabaja a altas velocidades, como es el caso de las señales
LVDS, consiste en fijar unas normas para el enrutado de este circuito. La comunicación
vía señales LVDS, como se ha comentado en capítulos anteriores, se basa en pares de
líneas diferenciales D- y D+, y la relación diferencial entre estas dos líneas en el
receptor permite identificar el valor lógico de los bits recibidos. En base a lo anterior, si
ambas señales de alta velocidad sufren la misma distorsión o son afectadas por el
mismo ruido, el receptor no tendrá problema para detectar correctamente el valor
recibido, ya que al receptor lo que le interesa es únicamente la diferencia entre ambas
señales, y no el valor absoluto de estas.Por tanto, se puede decir que una señalización
diferencial presenta una gran robustez frente a ruidos o interferencias externas, lo que le
permite trabajar a velocidades muy elevadas y con niveles de tensión reducidos.
No obstante, para que estas ventajas puedan conseguirse hay que cuidar el diseño del
circuito impreso. El motivo es simple, si estas pistas diferenciales, que forman el
protocolo de comunicación LVDS, se enrutasen de forma independiente, cada una
siguiendo un recorrido distinto, cada pista se vería afectada por interferencias distintas y
esto se traduciría en problemas a la hora de descodificar. Además, si la longitud de las
pistas o incluso los ángulos no son prácticamente iguales, una de las líneas se retardaría
más y por tanto, la decodificación en el receptor se dificultaría.
Para asegurar que la señal LVDS llega a su destino en condiciones óptimas, se deben
asegurar las siguientes normas de diseño:
2. Se debe evitar en el mayor grado las interferencias provocadas por otras zonas del
propio diseño, como podrían ser zonas de alimentación o vías que unen las dos
partes del circuito impreso, que solo afecten a una de las líneas.
Figura 21. Líneas diferenciales enrutadas de forma paralela y simétrica. Ambas líneas son de igual
longitud y se encuentran afectadas de igual forma por la vía.
27
3. Los pares de líneas diferenciales deben ser lo más cortos posible para reducir así
su resistencia parásita.
4. Los pares de líneas diferenciales entre sí deben estar lo más separados posible. Al
ser señales rápidas y de baja tensión tienen gran facilidad para afectar y ser
afectadas por otros pares diferenciales. No es recomendable cruzar pares de líneas
diferenciales aunque estos se encuentren en caras distintas del circuito impreso.
28
4.3 Verificación del sistema
4.3.1 Power Up
En base a la anterior problemática, dentro de este power up solo podemos verificar los
siguientes puntos:
• Obtención de la tensión esperada a la salida de los reguladores
• Funcionamiento correcto de los conversores LVDS-TTL y viceversa.
• Grabación de las FPGAs mediante los dos métodos disponibles.
• Aceptación de la imagen de salida por el panel LCD.
29
Procedemos inicialmente con la grabación active serial, que hace uso de la memoria
externa, y por tanto, la grabación es permanente. Tras realizar la grabación de la
memoria sin incidentes, realizamos un reset en la placa LVDS Capturer, ya que es en el
momento de arranque cuando la FPGA procede a la lectura de esta memoria. Al
reiniciarse la FPGA, los LEDs se encuentran el estado deseado, garantizando el correcto
funcionamiento del modo de grabación active serial y de la FPGA.
Con la segunda FPGA el resultado es idéntico, el modo JTAG sigue sin funcionar,
incrementando la probabilidad de que la hipótesis sobre el origen del error sea cierta.
Con esta comprobación deseamos garantizar que por un lado los conversores funcionan
correctamente, y por otro lado que la señal de salida de la placa de LVDS Capturer
mantiene una calidad lo suficientemente buena como para que el panel la acepte sin
problemas, es decir, que la placa LVDS Capturer sea de cara a la señal, transparente.
Hay que decir que lo más correcto sería comprobar uno a uno los conversores, antes de
realizar una comprobación global del sistema como bypass. No obstante, la alta
velocidad y la codificación diferencial del protocolo LVDS hace muy complicado el
proceso de verificación con un simple osciloscopio, por tanto verificando previamente
que los conversores de entrada generan algún tipo de salida en niveles TTL, se pasa al
proceso de verificación global.
Para realizar esta verificación, se debe realizar con Quartus II una conexión de las
señales de entrada de la FPGA que proceden de los conversores LVDS-TTL con las
salidas de la FPGA que conectan con las entradas de los conversores TTL-LVDS.
En total debemos interconectar 28 líneas de datos (7 bits por par LVDS x 4 pares LVDS
de datos), más una línea adicional procedente del par LVDS del clock en cada una de
las FPGAs. Recordamos que la primera FPGA transporta solo los píxels impares y la
segunda los pares, por tanto, si solo realizamos esta conexión en una de las FPGAs el
panel debería mostrar únicamente la mitad de los pixels que forman la imagen.
A continuación debemos fijar en las FPGAs el estado deseado para las 6 líneas de
control que cada FPGA controla, 3 por cada uno de los conversores. Las fijamos de tal
modo que los conversores estén habilitados y que la conversión se realice por flanco de
subida de la señal de reloj.
30
grises, comprobamos en las figuras 22 y 23 la imagen que se visualiza en el panel sin y
con placa LVDS Capturer entre ambos dispositivos.
Figura 22.Televisor LCD Sony en estado normal. A la izquierda vista frontal, a la derecha
vista trasera.
Figura 23. Televisore LCD Sony con placa LVDS Capturer entre panel y TV Board. A la
izquierda vista frontal, a la derecha vista trasera.En la imagen frontal se puede llegar a apreciar
unos caracteres de color blanco en la esquina superior derecha, estos son provocados de forma
voluntaria por la placa LVDS Capturer y se detalla su funcionalidad en futuros apartados.
Como se ha podido comprobar, tras pasar por un cable de LVDS, convertirse a niveles
TTL, atravesar las FPGAs y volver a convertirse a nivel LVDS para volver a pasar
finalmente por otro cable LVDS hasta llegar al panel, la señal sigue llegando en un
estado óptimo, sin observarse ningún tipo de degradación en este proceso.
Habiendo superado con éxito esta prueba, podemos garantizar que el sistema podrá ser
totalmente funcional una vez se haya implementado en las FPGAs los módulos de
procesado y comunicación.
31
4.3.2 Análisis de incidencias
Una vez comprobado que el sistema realiza las funciones básicas, es el momento de
solucionar los incidentes que han aparecido.
Las memorias que almacenan los ficheros .pof de configuración para las FPGAs deben
alimentarse a 3.3V, no obstante están siendo alimentadas a 5V. Aunque el datasheet
indica que su sistema de protección interno permite su funcionamiento con tensiones
más elevadas, se decide por seguridad modificar su tensión de alimentación a los 3.3V
recomendados. Como disponemos de una memoria para cada FPGA, se deben realizar
dos modificaciones sobre el hardware.
Los dos puntos anteriores, describen los dos reworks fundamentales. De todos modos,
se ha realizado alguna modificación adicional relacionada con el bus de comunicación
I2C, que se detallará en los próximos capítulos, con la finalidad de aumentar la
velocidad de este bus.
• En marrón los conectores para los cables LVDS. Abajo el conector de entrada
para la señal procedente de la placa de TV, arriba el conector de salida para la
señal que va hacía el panel.
• En lila los conversores de entrada de LVDS a TTL.
• En azul los conversores de salida de TTL a LVDS.
• En rojo las FPGAs Cyclone II.
• En amarillo el conector para la grabación de las FPGAs en modo active serial y
las memorias necesarias para esta grabación.
• En naranja los conectores para la grabación mediante protocolo JTAG.
• En azul celeste el conector para la comunicación I2C. Incluyendo dos
resistencias pull-up para las dos líneas que forman el bus I2C.
32
• En negro el conector de entrada para la alimentación. Incluyendo un filtro
externo para los 5V de entrada.
33
5 Diseño de módulos VHDL
Hasta el momento se ha diseñado un hardware, se ha verificado su funcionamiento y se
han solventado incidencias. No obstante, aunque el sistema a nivel de hardware
funciona, solo es capaz de convertir las señales diferenciales de entrada a niveles TTLs,
más manejables. Estas señales atraviesan las FPGAs, pero por el momento no se realiza
ningún procesado sobre ellas.
Si observamos la figura 16, podemos apreciar que los conversores de LVDS a TTL
generan siete bits por cada una de las líneas diferenciales de entrada. Estos bits son
directamente los que transportan internamente cada una de las tramas de señal LVDS,
indistintamente del contenido de la imagen. Para conocer qué información transporta
cada trama, tenemos que analizar el tipo de codificación que genera el emisor, en este
caso la placa de televisión. Los bits que envía cada trama LVDS y la correspondencia de
éstos con la imagen, se puede apreciar en las figuras 4 y 5.
Debido a las dos posibles ordenaciones que pueden tener los bits de estas tramas, este
módulo tiene una señal de control que permite seleccionar una de ellas, esta señal se
llama JETDA_NS. Según el valor de esta señal de control, el módulo reordena los bits
de entrada, creando salidas que corresponden a R, G, B y las señales de sincronismo
DE, HSYNC y VSYNC.
34
Descripción de señales
TTL_I!PUT_RA,RB,RC,RD[6..0]: Entradas. Señales procedentes del conversor
LVDS a TTL Su formato depende del tipo de codificación JETDA o NS.
J_!S: Entrada. Señal de control que específica la codificación con que se está
trabajando. A nivel alto JETDA, a nivel bajo NS.
R,G,B[7..0]: Salidas que forman el píxel que se esta recibiendo, en formato RGB.
Para más información sobre las señales de sincronismo anteriores revisar el apartado
2.3.3 de este documento.
SignalTap
SignalTap es una herramienta incluida en Quartus II que permite capturar en tiempo real
la actividad de las entradas y salidas de la FPGA. Se podría decir que es similar a un
osciloscopio digital con la ventaja de que no necesita la conexión de ningún dispositivo
externo sobre los pins de la FPGA, además de permitir la captura de un gran número de
señales de forma simultánea.
Uno de los problemas que conlleva el uso de SignalTap consiste en que para realizar
esta comprobación hay que crear un fichero con las señales a observar, indicar la señal
que actuará como trigger(señal de disparo), fijar el número de muestras a tomar de la
señal de entrada, volver a compilar todo el proyecto y por último cargarlo en la FPGA.
Esta compilación, que es el proceso que mayor tiempo conlleva, es obligatoria ya que
hay que crear una nueva configuración del hardware interno de la FPGA para que sea
capaz de capturar y almacenar en registros internos la actividad de las señales deseadas.
Para comprobar el correcto funcionamiento del conversor LVDS a TTL, así como la
ordenación de los bits propuesta en este módulo, creamos un fichero con esta aplicación
donde se capturan las señales de video y sincronización que entran a la FPGA. En este
caso conectamos a la TV una señal de video que corresponde a una carta de grises,
ordenamos las señales correctamente y realizamos la captura.
35
Figura 26. Captura con SignalTap ordenando las líneas de entrada a la FPGA. En este caso se esta
introduciendo como señal a la TV una carta de grises
Por otro lado, en esta figura se muestra también que tras agrupar las líneas en tres buses
de 8 bits (Red, Green y Blue) el resultado corresponde a tres rampas, comportamiento
que coincide con una carta de grises. En una carta de grises el primer píxel horizontal es
totalmente oscuro( R=0,G=0,B=0), y el último píxel es muy cercano al blanco (R=255,
G=255,B=255).
36
5.2 Conversión de salida
Este módulo no sería necesario si solo quisiésemos dejar pasar la señal procedente de la
placa de televisión, ya que bastaría con interconectar las líneas de la señal de entrada
con sus respectivas salidas. Sin embargo, como deseamos analizar regiones concretas de
la imagen nos interesará poder modificarla remarcando por ejemplo la zona que estamos
analizando.
Las señales que participan en este módulo son idénticas al módulo de entrada, por este
motivo no se detallarán de nuevo.
37
5.3 Análisis de regiones
El módulo secuencial síncrono Mesure_ROI de la figura 28 analiza una región
específica de la imagen en tiempo real, devolviendo la siguiente información sobre
dicha región de interés (ROI):
Se debe tener en cuenta que las señales de video de entrada a la televisión en la máquina
de test CBA son siempre cartas de barras de colores. Las cartas de barras de colores,
como su nombre indica, son imágenes de video fijas formadas por un conjunto de barras
de distintos colores.
Para comprobar si la imagen es correcta, se selecciona una región de una de estas barras
y se comparan los valores obtenidos con los esperados. Para realizar este proceso se
fijan unas especificaciones de valores R, G, B y luminancia para las regiones que se van
a analizar y si los valores obtenidos no coinciden con los especificados, la placa de TV
se descarta de la cadena de montaje y se envía a reparación.
38
Descripción de señales
clk: Entrada. Señal de reloj procedente de los conversores LVDS-TTL, por tanto,
es la frecuencia de los píxeles pares/impares.
enable: Entrada. Señal de habilitación del módulo. Una vez indicada la región de
interés a analizar, se debe provocar un pulso de un ciclo de reloj en esta señal para
iniciar el análisis.
R,G,B[7..0]: Entradas. Valores RGB del píxel actual. Estos valores corresponden
a un nuevo píxel cuando nos encontramos dentro de la zona visible del panel y
además se produce un flanco de bajada de la señal de reloj clk.
39
Funcionamiento
Tras un reset el módulo pasa al estado de espera Waiting, donde se mantiene a la espera
de un pulso de la señal Enable. Al generar este pulso las señales que limitan la región de
interés, off_v, off_h, width y length deben haber sido previamente fijadas. En este
momento, el sistema pasa al estado Wait2, en el que permanece a la espera de que el
píxel actual sea el primer píxel de la ROI, es decir que contador_vert=off_v y
contador_hori=off_h. Cuando esta condición se cumple pasamos al estado Run que se
encarga de incrementar los valores totales de RGB por cada píxel valido de la ROI, así
como de contar el número de píxels que forman esta región. A la vez actualiza, si es el
caso, el valor RGB máximo o mínimo encontrado hasta el momento. En este estado con
cada ciclo de reloj se garantiza que estemos dentro de los márgenes de la ROI, por tanto,
cada vez que salgamos de la zona hasta que volvamos a entrar en ella, el estado
permanece inactivo sin incrementar las variables que se desean medir. Cuando nos
encontramos en el último píxel de la ROI, es decir, contador_vert = off_v + length -1 y
cont_hori = off_h + width, el sistema pasa al estado Math donde realiza los cálculos de
los valores RGB medios, los pone en las líneas de salida e indica mediante la señal
read_strobe que los datos están listos para ser leídos.
Figura 29. Diagrama de estados del módulo Mesure_ROI. Las líneas azules indican las condiciones para
la transición entre estados, las rojas las acciones que se realizan en ese estado
40
5.4 Contadores de posición
Con la finalidad de simplificar el proceso de análisis y modificación de la imagen se
decide crear un módulo que indica la posición (en píxels) dentro de la parte visible de la
pantalla donde nos encontramos. En este apartado se describen las principales
características de este módulo.
Para obtener estos indicadores de posición se hace uso de las señales de sincronización
Hsync, Vsync y DE procedentes de los conversores LVDS a TTL. Tal y como se
describió en el apartado 2.3 dedicado a paneles LCD existen dos opciones de
sincronización: Hsync conjuntamente con Vsync o DE.
Inicialmente se planteó usar la opción de Hsync más Vsync por ser la más conocida, no
obstante esta opción plantea serias limitaciones. Una de estas limitaciones como se
muestra en la figura 30 consiste en que en estas señales, para indicar el inicio de un
nuevo frame en el caso de Vsync o una nueva línea en el caso de Hsync, pasan a nivel
bajo, manteniéndose en este estado durante cierto tiempo para después volver al estado
de reposo, a nivel alto. El problema es que tras este flanco de bajada existe un tiempo
variable(Thb/Tvb-Time Horizontal/Vertical Blanking) hasta la llegada del primer píxel
que pertenece a la parte visible o activa del panel y de igual forma existe otro tiempo
variable(Thf/Tvf. Time Horizontal/Vertical offset) desde que finaliza la zona activa del
panel hasta que se genera un nuevo flanco de bajada en las señales de sincronismo.
El uso de este tipo de sincronización implica tener que contar los píxels de la zona
pasiva para conocer cuando nos encontramos dentro de la zona útil del panel.
No obstante, la limitación más importante, es que el fabricante del panel garantiza una
cantidad de píxels fija para las zonas activas del panel, en el caso de un panel FHD,
estos valores suelen ser de 1080 píxels verticales y 960 horizontales. Volvemos a
recordar que estos 960 horizontales es debido a que la imagen se encuentra dividida en
píxels pares e impares que se tratan de forma independiente. En cambio, las zonas del
panel de píxels pasivos no son de tamaño fijo y el fabricante simplemente proporciona
41
un valor mínimo y máximo para estas zonas. Además estas cotas son variables según
diversos parámetros de configuración del panel, como por ejemplo la frecuencia de
refresco.
Como alternativa se planteaba el uso de la señal DE( Display Enable), que como se
puede ver en la figura 30 solo se encuentra a nivel alto cuando nos encontramos dentro
de la zona activa del panel, permitiendo que el sistema sea escalable a otros paneles y
resoluciones fácilmente, reduciendo a la vez el número de necesarios. No obstante, el
comportamiento de la señal DE (ver figura 7 y 8) muestra la necesidad de utilizar un
contador adicional para calcular el tiempo que la señal DE permanece a nivel bajo, ya
que un tiempo prolongado a nivel bajo antes de un flanco de subida indica que estamos
en el píxel número uno de un nuevo frame, un tiempo corto a nivel bajo indica que
estábamos en la zona de blanking existente entre líneas horizontales.
42
Descripción de señales
clk: Entrada. Señal de reloj procedente de los conversores LVDS-TTL, por tanto,
es la frecuencia de los píxeles pares/impares.
Funcionamiento
El sistema repite el bucle anterior, hasta que se produce un flanco de subida de la señal
Vsync, indicando que se inicia un nuevo frame, fijando de nuevo Waiting_First_DE='1'
y reiniciando ambos contadores.
43
Sincro_H
B
Reset(Cont_vert)
Vsync_rise_edge=’1' Reset(Cont_hori)
Waiting_First_DE=’1'
Sincro_H
DE=’0' &Waiting_First_DE=’1'
B
Sincro_H
DE=’0' &Waiting_First_DE=’0'
B
nrst=’0'
Sincro_H
Sincro_V Vsync_rise_edge=’1'
Reset(Cont_hori)
Sincro_H
DE=’1'
B
Waiting_First_DE=’1'
Waiting_First_DE=’0'
INCREMENT(Cont_hori)
DE_fall_edge=’1'
Sincro_H
B
INCREMENT(Cont_vert)
44
5.5 Captura de imagen
Hasta el momento se han descrito módulos cuya finalidad es reorganizar la información,
generar indicadores de posición y permitir el análisis de forma rápida y directa en las
FPGAs de una región específica. No obstante, es posible que se desee obtener algo más
que los valores RGB medios, mínimos y máximos de una región de la imagen, por
ejemplo, que se desee adquirir una imagen completa para procesarla en un ordenador.
Para realizar una captura de imagen rápida haría falta un enlace de comunicaciones más
rápido que la frecuencia de píxel, que es de 75 MHz. Como éste no es el caso, nos
vemos con la necesidad de almacenar temporalmente los píxels hasta que sean leídos
por el ordenador. Por ello incluimos un bloque FIFO de palabras de 24 bits, que es el
número de bits que forman un píxel.
Este bloque de memoria FIFO presenta un serio problema ya que en las FPGAs se
puede almacenar un máximo de 4096 palabras de 24 bits o lo que es lo mismo 4096
píxels. Esto implica que como máximo podemos guardar en estas FIFOs regiones de un
tamaño similar a 64x64 píxels que comparando con los 960x1080 píxels que maneja
cada FPGA es una zona muy reducida.
45
Figura 35. FIFO para el almacenamiento de píxels
Para solventar este problema y poder capturar regiones de hasta 960x1080 píxels se
implementa la siguiente estrategia:
Descripción de señales
clk: Entrada. Señal de reloj procedente de los conversores LVDS-TTL, por tanto,
es la frecuencia de los píxeles pares/impares.
enable: Entrada. Señal de habilitación del módulo. Una vez indicada la región de
interés a capturar, se debe provocar un pulso de un ciclo de reloj en esta señal para
iniciar la captura.
46
FHD(1920 x 1080p). Off_h debe estar comprendido entre 0 y 960, debido a que la
imagen FHD se divide en dos partes, píxels pares e impares.
R,G,B[7..0]: Entradas. Valores RGB del píxel actual. Estos valores corresponden
a un nuevo píxel cuando nos encontramos dentro de la zona visible del panel y
además se produce un flanco de bajada de la señal de reloj clk.
Fifo_full: Entrada. Línea de salida de la FIFO que indica cuando está completa.
o_R, o_G, o_B[7..0]: Salidas. Valores RGB del píxel actual modificado. Estas
señales corresponden en general a las señales de entrada R,G,B[7..0], con un
recuadro de un color verde alrededor de la zona de interés prefijada, que indica
visualmente la zona que se esta analizando/ capturando.
Funcionamiento
Tras un reset el módulo va al estado waiting, en el que permanece a la espera de un
pulso de enable. En el momento que se genera el pulso todos los parámetros que
configuran la ROI ya han sido prefijados, la FIFO se ha resetado y el contador de
posición se ha activado.
Cuando se recibe la señal de enable el sistema pasa al estado full. Tras la generación de
un pulso de enable la FIFO se vacía por tanto en este caso la señal fifo_full ='0'.
Además el sistema almacena el punto desde donde la captura de imagen debe continuar.
Como partimos de una condición de reset, se almacena el primer punto de la ROI, es
decir, point_hori= off_H y point_vert=off_V
47
Al haber sitio en la FIFO, el sistema espera a leer el primer píxel de la ROI( point_hori
y point_vert). Al llegar a la situación de este píxel cont_hori=point_hori y
cont_vert=point_vert y al haber sitio en la FIFO el sistema pasa al estado run.
Al llegar a este nuevo estado con un ciclo de reloj de retardo el sistema almacena en la
FIFO el píxel anterior que se va almacenando de forma continua con cada ciclo de reloj.
Mientras la captura de la ROI no haya finalizado, sigamos dentro de la ROI y siga
habiendo sitio en la FIFO el sistema continua almacenando píxels. Si se sale de la zona
de la ROI, habiendo sitio en la FIFO el sistema permanece inactivo en este estado
esperando a que se vuelva a entrar en la zona de interés. Por contra, si la FIFO se llena,
el sistema actualiza la situación del último píxel grabado en la FIFO actualizando la
posición donde se encuentra y que se debería guardar en un futuro en la FIFO, es decir,
hace que point_hori= cont_hori y point_vert= cont_vert y pasa al estado full.
El sistema permanece en este estado hasta que vuelve a haber sitio en la FIFO. Cuando
esto sucede vuelve al estado run y espera a encontrarse en el píxel donde se había
quedado para proseguir con la captura. El salto entre el estado run y full se repite hasta
que se completa la captura de la ROI, se genera una señal de reset o se genera otro pulso
de enable para capturar una región distinta.
Por último indicar que tras haber seleccionado una zona de interés y haber generado un
pulso de enable, cada vez que el píxel actual corresponde a la periferia de esta zona, el
color de estos píxels se modifica a un color verde intenso. Esta acción en el modo de
prototipado permite conocer con exactitud la zona del panel que se esta capturando, ya
que en este modo de pruebas si que se conecta en el otro extremo de la placa LVDS
Capturer un panel LCD.
48
5.6 Generador OSD
En nuestro caso el OSD solo tiene utilidad si en el otro extremo de la placa LVDS
Capturer se conecta un panel. Esta situación solo se dará en el caso de prototipado, en el
caso de reparación de un VITAM o en el departamento de reparación de placas. En
estos dos últimos casos, disponer de un panel facilita la detección del problema. En
estas tres situaciones se podría usar este OSD para dar una información adicional a
través del panel del estado actual del proceso que se está llevando a cabo.
Funcionamiento
El generador de OSD se basa en un módulo llamado TopSchemROM3. Este módulo a
su vez está formado por dos módulos: comparPos4Rom3 y Char_ROM.
Char_ROM: Es una memoria ROM que contiene caracteres de tamaño 8x8 píxels,
character_address[5..0] indica la dirección de memoria del carácter que se desea dibujar
49
y font_row y font_col indican un píxel específico de los 64 que forman el carácter. El
valor del píxel seleccionado con cada ciclo de reloj ( 1 o 0) se envia por romout.
Las dos salidas del módulo TopSchemROM3 por tanto son print, para indicar si
estamos en la región 8x8 de un caracter, y romout que indica si el valor a imprimir por
pantalla corresponde a 0(negro) o 1 (blanco). Los valores de la salida romout se
muestran en binario en la figura 38.
Para superponer sobre la imagen de entrada únicamente los valores lógicos '1', que
corresponden a la escritura de un carácter, se realiza el montaje de la figura 39.
50
5.7 Comunicación. Esclavo de I2C
Uno de los módulos importantes del sistema es el que gestiona la comunicación con la
placa ESIIC. A través de esta comunicación se puede controlar el funcionamiento de la
placa LVDS Capturer, así como transferir información hacia la ESIIC para
posteriormente enviarla al ordenador. Como se ha dicho, esta comunicación se establece
a través de un bus I2C, donde la ESIIC hará las funciones de master y nuestro hardware
el de esclavo.
51
Register Name Utility Register Name Utility
Mem(0) Offset vertical - MSB Mem(13) Red mean value
Mem(1) Offset vertical - LSB Mem(14) Green mean value
Mem(2) Offset Horizontal - MSB Mem(15) Blue mean value
Mem(3) Offset Horizontal - LSB Mem(16) Luminance
Mem(4) Length(ROI)- MSB Mem(17) Locked
Mem(5) Length(ROI)- LSB Mem(18) Rmin
Mem(6) Width(ROI)- MSB Mem(19) Rmax
Mem(7) Width(ROI)- LSB Mem(20) Gmin
Mem(8) Control/Configuration: Mem(21) Gmax
Bit0= Reset
Bit1= Enable
Bit2 = Jetda/NS
Mem(9) Empty Mem(22) Bmin
Mem(10) Red pixel Mem(23) Bmax
Mem(11) Green pixel Mem(24) Bit0= '1' Available read data
Mem(12) Blue pixel
Figura 41. Registros internos del módulo de comunicación. En amarillo los de
escritura, en gris los de lectura
Descripción de señales
clk: Entrada. Señal de reloj procedente de los conversores LVDS-TTL, por tanto,
es la frecuencia de los píxeles pares/impares.
rst_o: Salida. Señal de reset para los diversos módulos del sistema.
52
off_v, off_h[10..0]: Salida. Offset vertical y horizontal de la región a analizar.
Funcionamiento
53
cada byte recibido. Tras leer estos 8 bits, el proceso se repite incrementando la
dirección de lectura y volviendo a enviar los 8 bits siguientes. El proceso de envio y
reconocimiento se repite hasta que el master genera una condición de stop que envía al
sistema al estado idle.
Para facilitar y agilizar el proceso de captura de una región desde el ordenador, el propio
esclavo de I2C se encarga de coger los tres bytes que forman un píxel de la FIFO( si hay
muestras disponibles) y los guarda en los registros internos de lectura Mem(10),
Mem(11), y Mem(12). En caso de que se realice un proceso de lectura de N píxels
(N*3 bytes), con dirección inicial la correspondiente al registro Mem(10), el esclavo
funciona de un modo continuo. Es decir, a medida que se leen los 3 registros que
corresponden a un píxel, el propio I2C comprueba si la FIFO tiene otro píxel disponible,
en caso afirmativo vuelve a cargar estos registros Mem(10..12) con la información del
siguiente píxel. Además cuando la dirección de lectura inicial corresponde a la del
registro Mem(10), el esclavo internamente genera un bucle con los tres registros que
contienen el píxel, Mem(10), Mem(11) y Mem(12).Es decir, cuando llega a Mem(12) y
se desean leer más píxels , el esclavo directamente vuelve a colocar la dirección de
lectura a Mem(10) para que éste sea este el siguiente registro a leer.
54
6 Uso y verificación del sistema completo
En el capítulo anterior se han descrito los módulos VHDL que dotan de funcionalidad a
la placa LVDS Capturer. En el transcurso del capítulo se ha descrito de forma detallada
el funcionamiento, así como las señales y el diagrama, para la mayoría de los bloques
que se van a incorporar. Además se ha mostrado su funcionamiento mediante
simulaciones o capturas con SignalTap.
Figura 43. Elementos necesarios para el montaje provisional. A la izquierda un LCD Sony EX2N, a la
derecha la placa desarrollada, LVDS Capturer.
Tras comprobar que el panel funciona correctamente, sin la placa LVDS Capturer,
realizamos los siguientes pasos para llevar a cabo el montaje básico:
55
Figura 44. Montaje básico del sistema. Se puede apreciar la conexión entre las placas, los cables de
alimentación para la placa LVDS Capturer (a la izquierda) y un cable HDMI procedente de un DVD
conectado a la TV Board, encargado de proporcionar la imagen.
En este momento estamos listos para proceder a verificar el funcionamiento básico del
sistema. Por el momento no existe ninguna conexión con la placa externa ESIIC y por
tanto aún no existe comunicación con el ordenador que permita su control.
Figura 45.LCD EX2N con el módulo generador de OSD funcionando en su estado por defecto. A la
izquierda imagen completa del panel LCD, a la derecha zoom de la esquina superior derecha.
56
devolver alguna información visual a través del panel, útil por ejemplo para los
departamentos de reparación o simplemente para mostrar el logotipo de la empresa.
Con esta prueba realizada se verifica que la señal es capaz de pasar por el hardware de
forma óptima, y además se ha mostrado que el generador de OSD (preconfigurado con
el texto "JAUME") funciona correctamente.
Para llevar a cabo este montaje lo único que necesitamos es un cable que conecte alguno
de los masters de I2C que posee la ESIIC con nuestro conector I2C, que comunica con
los esclavos de I2C implementados en cada FPGA. Para poder utilizar un mismo bus
I2C para controlar ambas placas, se ha configurado en cada FPGA una dirección
distinta, la primera ( píxels impares) se ha configurado con la dirección 0xA4 y la
segunda (píxels pares) con la dirección 0xA6.
Por otro lado necesitamos alimentar la ESIIC y conectarla a través de un cable Ethernet
a la tarjeta de red del ordenador.
57
El siguiente paso es configurar el ordenador para establecer comunicación con la ESIIC,
para ello se requiere que la tarjeta de red se configure con una dirección específica. El
procesador Nios II que implementa la comunicación vía TCP/IP tiene por defecto la IP
10.0.0.51 y como puerto de acceso, el 30. Debido a esta IP y a la máscara IP usada, se
debe configurar la tarjeta de red con una IP del rango 10.0.0.XX.
Figura 47. Configuración de la tarjeta de red. Se opta por seleccionar la dirección IP 10.0.0.56
Una vez configurada la tarjeta de red, debemos establecer una comunicación entre el
ordenador y la ESIIC. El modo más sencillo de llevar a cabo esta comunicación es
creando un enlace entre ambos dispositivos a través de un terminal telnet.
Inmediatamente después de que la ESIIC acepte la conexión, el menú devuelto indica
que la comunicación se encuentra establecida y que la ESIIC se encuentra a la espera de
recibir una nueva orden.
58
6.3 Control del sistema LVDS Capturer vía Telnet
Una vez realizado el montaje completo, y habiendo introducido los principios básicos
para utilizar la ESIIC, sólo necesitamos enviar los comandos adecuados a través del
terminal Telnet para que el master de I2C genere las tramas con la información deseada.
I2CMaster: Master de I2C que debe establecer la comunicación. Ex: i2c1, i2c2,..
write_data: Acción de escritura.
rate: Velocidad de la comunicación, en bps.
i2caddr: Dirección del esclavo de I2C con el que se desea interactuar, en
hexadecimal.
subaddrini: Dirección del registro interno al que se desea acceder, en decimal
num_bytes: número de bytes a escribir, en decimal
data: Información en hexadecimal a enviar.
I2CMaster: Master de I2C que debe establecer la comunicación. Ex: i2c1, i2c2,..
read_Rx: Acción de lectura.
rate: Velocidad de la comunicación, en bps.
i2caddr: Dirección del esclavo de I2C con el que se desea interactuar, en
hexadecimal.
subaddrini: Dirección del registro interno al que se desea acceder, en decimal
num_bytes: número de bytes a leer, en decimal
59
de esta región el proceso de comprobación de los resultados será más sencillo que con
cualquier otro tipo de imagen.
Figura 49. LCD Sony con una carta de barras de colores como señal de entrada
60
Al introducir en el terminal de telnet el comando anterior, el resultado devuelto por la
ESIIC se puede apreciar en la figura 50.
Figura 50. Respuesta devuelta por la ESIIC ante un comando de escritura por I2C
Y observando la pantalla del LCD en la figura 51a, a primera vista vemos que se ha
remarcado en un color verde intenso los píxels que rodean la zona de interés
seleccionada, aunque en realidad solo se han remarcado de color verde los píxels
impares que rodean esta zona. Para seleccionar la zona completa, incluyendo también
los píxels pares, se hace necesario enviar el mismo comando de I2C anterior, pero esta
vez destinado al otro esclavo de I2C, el configurado con la dirección 0x06.
El resultado devuelto por terminal es idéntico al caso anterior y en el panel LCD vemos
que ahora si se encuentran en verde los píxels pares que rodean la ROI( figura 51b). De
hecho si ampliásemos la zona remarcada, veríamos que debido a esta dualidad de píxels
pares e impares, la zona remarcada en verde no es únicamente de un píxel de anchura si
no que el marco superior e inferior si que es de un píxel, en cambio los marcos laterales
son de dos píxels de anchura.
(a) (b)
Figura 51. a) Panel LCD con los píxels impares que rodean la ROI remarcados en verde.
b) Panel LCD con todos los píxels que rodean la ROI remarcados en verde.
61
Una vez prefijada la zona de interés es el momento de analizar esta región, para ello
activamos el bit de enable del registro Mem(8) en los dos esclavos de I2C. Los
comandos son los siguientes:
Nota: Al realizar una escritura sobre el bit de enable en uno de los esclavos, éstos generan un único pulso
de un ciclo de reloj del esclavo de I2C hacia los demás módulos y automáticamente vuelven a colocar el
bit de enable de este registro a cero.
Figura 52. Valores RGB medios devueltos por cada uno de los esclavos de I2C.
62
Colocando la información obtenida en un formato más visual obtenemos la siguiente
tabla:
Como se puede observar los valores parecen tener coherencia con la región analizada,
de todos modos una forma fácil de comprobarlo es utilizar cualquier herramienta de
dibujo, como por ejemplo paint, y generar un color con estos valores RGB. Debido a
que estos valores decimales son muy próximos a 255 es evidente que el resultado
obtenido es un color prácticamente blanco.
Con la finalidad de obtener un valor que sea más fácil de comparar, capturamos esta vez
una región de la barra de color lila.
Si ahora vamos a paint y creamos un color con los valores RGB medios calculados,
obtenemos el siguiente resultado:
63
Figura 56. Color creado en paint con las características anteriores.
Si comparamos ahora el color obtenido mediante paint de la figura 56 con la zona que
se encuentra remarcada en la figura 54 se aprecia que ambos colores coinciden,
quedando validado en la práctica que el sistema de análisis de regiones desarrollado,
principal objetivo de este proyecto, funciona satisfactoriamente.
Captura de ROIs
Habiendo comprobado que las medidas realizadas sobre las ROIs son correctas, queda
por comprobar que el sistema desarrollado con FIFOs para la captura y envio de
regiones enteras hacía el PC también funciona.
2. Una región relativamente pequeña como la que hemos tratado en el caso anterior
ronda unas dimensiones de 40x40 píxels, lo que implica 1600 píxels, o lo que es
lo mismo realizar manualmente 50 lecturas de 96 bytes por cada esclavo de I2C.
3. Cada FPGA contiene una FIFO capaz de almacenar 4096 palabras de 3 bytes, o
lo que es lo mismo 4096 píxels. Esto implica que para comprobar el correcto
funcionamiento del sistema de captura de imagen de forma manual al completo
deberíamos exceder este límite. De esta forma se comprobaría que cuando la
FIFO se llena, ésta se mantiene a la espera de que empiece a ser vaciada para
proseguir con la captura de los píxels pendientes.
4. Al leer una zona de un único color todos los valores devueltos deben ser iguales
lo que implica que si los registros que contienen el siguiente píxel a leer no se
actualizan a cada ciclo de reloj no notaremos la diferencia.
Los anteriores motivos en conjunto hacen inviable en esta fase del proyecto comprobar
totalmente la captura de regiones. Lo que si que se puede hacer es delimitar como ROI
una región de tamaño pequeño, de unos 10x10 píxels y comprobar que los valores
64
devueltos coinciden con la ROI seleccionada. Comprobar una región de 100 píxels
implica realizar una lectura de 300 bytes, o lo que es lo mismo tres capturas de 96 bytes
y una más de 12 bytes. En caso de que intentásemos leer más bytes de los que incluye la
ROI, al encontrarse la FIFO vacía deberíamos leer valores nulos. Para comprobar que la
FIFO se vacía totalmente cuando leamos los 300 bytes lo que hacemos es conectar la
salida FIFO_empty, que indica cuando la FIFO no tiene más muestras, a uno de los
LEDs que la placa LVDS Capturer incluye. De esta forma cuando capturemos una zona
el LED se apagará y no se debería encender hasta que hayamos leído los 300 bytes que
contiene FIFO.
Para definir una zona de tamaño 10x10 píxels debemos realizar las siguientes escrituras:
i2c2 -write_data -rate 100000 -i2caddr A4 -subaddrini 00 -num_bytes 9 -data
00010001000A000A00
i2c2 -write_data -rate 100000 -i2caddr A6 -subaddrini 00 -num_bytes 9 -data
00010001000A000A00
Figura 57. Pantalla LCD con una ROI reducida de 10x10 píxels
El resultado de las lecturas devuelto por Telnet se muestra en la figura 58, y se aprecia
que a partir del byte 300 en ambos esclavos el valor devuelto no es válido, expresado
como FF.
65
Figura 58. Información devuelta por Telnet al leer cuatro bloques de 96 píxels
Por otro lado, se aprecia que los valores RGB devueltos para cada píxel son idénticos a
los valores RGB medios que en el caso de análisis de regiones se habían obtenido.
Además como se había pronosticado el LED que se ha configurado para que indique si
la FIFO se encuentra vacía, al leer los 300 bytes almacenados se ha activado.
66
7 Arquitectura del software
En capítulos anteriores se ha establecido un orden cronológico en el que se detallaban
las motivaciones que llevaron al desarrollo de este proyecto, los objetivos que se
querían conseguir, la funcionalidad y estructura del sistema propuesto, el diseño
hardware desarrollado, y por último, los módulos VHDL que dotaron de funcionalidad
al hardware. Luego, hasta el momento, el documento solo se ha centrado en una parte
del sistema, la parte hardware.
Por último añadiremos que para mantener una estructura común en todas las funciones
de librería se ha decidido que en general todas estas sean del tipo boolean, es decir, que
la función solo pueda devolver dos resultados. True o '1' será devuelto en caso de que la
función haya finalizado con éxito y False o '0' en caso de que haya ocurrido algún
problema. Esto implica que tanto las entradas como las salidas de las funciones, en caso
de que sean necesarias, serán en forma de parámetros. Además únicamente en el caso de
que la función devuelva False, es decir para el caso de error, las funciones incluyen un
parámetro denominado Err_Msg o message, que como su nombre indica devuelve
información detallada del error que ha ocurrido.
67
7.1.1 DLL para la comunicación con la ESIIC
Esta librería a desarrollar, debido a que la comunicación es vía TCP/IP, debe ser capaz
de gestionar una comunicación vía sockets con el servidor, que en este caso es la ESIIC.
Para ello entre las funciones básicas que esta librería debe incorporar se encuentran las
siguientes: Conexión con la ESIIC, envio de comandos, lectura de resultados y
finalización de la conexión.
Esta función crea un cliente socket que establece la comunicación con la ESIIC.
Haciendo uso de las funciones para sockets que incorpora la API de Windows. Entre los
parámetros más importantes que recibe esta función se encuentran los dos básicos de
una comunicación TCP/IP, una dirección IP(char *ipString) y un puerto específico al
que conectar(int ipPort). El parámetro unsigned int *esiicFileDes es el
objeto resultante de esta función y permite posteriormente realizar escrituras y lecturas
directamente sobre este objeto sin tener que volver a establecer comunicación.
El proceso interno que realiza esta función es por tanto inicializar un cliente socket,
asociarlo con cualquier puerto o interfaz de la máquina local, conectar con el servicio
Telnet en la dirección y puerto que se indico como parámetro de la función y
finalmente, se asegura de recibir y eliminar la información que devuelve la ESIIC al
conectarse por primera vez con ella, es decir el menu que se aprecia en la figura 50. En
68
caso de que el timeout (int timeout) se agote y no se haya conseguido establecer una
comunicación con la ESIIC o en caso de que se produzca cualquier otro tipo de error, la
función devuelve un 0(false) y un mensaje de error(char message[512]).
Esta función genera un comando como el utilizado en el terminal para que un master
I2C de la ESIIC genere una escritura sobre un esclavo específico, es decir la trama
generada es la siguiente:
Entre los parámetros de entrada incluye el nombre del I2CMaster que deseamos que
realice la escritura(char i2c_selected[256]), la velocidad de escritura (int rate),
sobre qué esclavo(char i2c_address), sobre qué registro(int subaddr_ini) y el
número de bytes a enviar(int bytes_data), así como los bytes a enviar.
El proceso interno que realiza esta función consiste en generar a partir de los parámetros
de entrada una trama idéntica a la que enviábamos por el terminal de Telnet. Además
para evitar escribir en hexadecimal los nueve bytes a enviar que delimitan la ROI, se
incorpora en esta cabecera 4 parámetros: offsetx, offsety, length y width.
Estos parámetros se introducen en formato decimal e internamente la función los
convierte a formato hexadecimal, para formar finalmente una línea de comando como la
siguiente:
En caso de que se reciba respuesta antes de que el timeout expire la función analiza la
respuesta recibida. Si la trama comienza con un OK significa que el envio ha sido
correcto y la función finaliza, en caso de recibir KO el envio ha sido incorrecto y la
función finaliza devolviendo un error.
69
int __declspec(dllexport)__stdcall ReadI2cIndividualBytesLVDSESIIC
(char message[512], unsigned int esiicFileDes, char i2c_selected[256],
int rate, unsigned char i2c_address, int subaddr_ini, int
bytes_subaddr, int bytes_to_read, int*recv_data);
Entre los parámetros de entrada se incluye el nombre del I2CMaster que deseamos que
realice la lectura(char i2c_selected[256]), la velocidad de lectura (int rate),
sobre qué esclavo(char i2c_address), sobre qué registro(int subaddr_ini) y el
número de bytes a leer(int bytes_to_read).Los bytes leidos (int*recv_data) se
guardan en un buffer que se devuelve como parámetro de salida de la función.
El funcionamiento interno de esta función es análogo al caso anterior, genera una línea
de comandos con los parámetros de entrada, la envia a través del enlace de
comunicaciones y espera una respuesta. En este caso la respuesta si que es de interés ya
que corresponde con la información de los registros leidos que almacenan los resultados
de la ROI, por tanto, estos bytes leidos se guardan en el buffer recv_data.
Para facilitar la lectura de los resultados de una ROI y devolverlos de forma separada
como valores RGB y Luminancia media se crea esta función. Esta función encapsula
internamente dos llamadas a la función ReadI2cIndividualBytesLVDSESIIC para que
genere una línea de comandos que lea directamente los bytes que interesan de los dos
esclavos de I2C, es decir, los registros de los esclavos de I2C que contienen los valores
medios de la región analizada. En resumen envia las dos tramas siguientes:
Con cada envio de las líneas de comandos anterior, captura los resultados devueltos por
la placa LVDS Capturer, lo que serían los valores RGB medios calculados, los separa
en R, G y B, y los convierte de formato hexadecimal a decimal. Finalmente pondera los
resultados obtenidos por los dos esclavos de I2C y los devuelve como los parámetros de
salida Rmean, Gmean,Bmean y Luminancia.
Función análoga a la anterior, pero esta vez realizando lecturas sobre los registros que
contienen información de los valores mínimos y máximos de las regiones analizadas.
70
int__declspec(dllexport)__stdcall Create_Data_Storage_LVDS (char
message[512] , int *bits,int width, int heigth);
int__declspec(dllexport)__stdcall Close_Data_Storage_LVDS(char
message[512],int *bits);
Libera la zona de memoria reservada a la que hace referencia el parámetro int *bits.
Utiliza las funciones de la API de Windows para finalizar la conexión establecida que
tenia como enlace el objeto creado con la función Connect, es decir, unsigned int
esiicFileDes.
Uno de los objetivos deseables de este proyecto consistía en la captura y el envio de una
ROI hacia el PC. En capítulos anteriores se ha descrito el proceso que se realiza para
capturar una de estas regiones, así como los registros que hay que leer para obtener cada
uno de los píxels que forman esta ROI y las limitaciones que estas lecturas tienen.
También se ha mostrado que la información obtenida corresponde a un conjunto de
bytes en formato hexadecimal que difícilmente permite conocer si los píxels leídos
corresponden realmente a la imagen que se deseaba capturar.
Para solventar este problema y obtener una imagen bitmap a través del conjunto de
bytes leídos que permita conocer directamente si los píxels leídos desde el ordenador
coinciden con los de la ROI se crea esta librería.
En este apartado, por tanto, se pretende presentar de una forma muy esquemática el
funcionamiento de las principales funciones que aparecen en esta librería. El código
íntegro y comentado de esta DLL se anexa en el fichero Bitmaps.c.
71
int__declspec(dllexport)__stdcall Create_Data_Storage(char
message[512], int *bits, int width, int height);
Para generar una imagen, una de las funciones que se incluye en esta librería necesita
disponer de los píxels RGB almacenados en forma de vector o array de una única
dimensión. La función por tanto reserva una zona de memoria, apuntada por int *bits
donde se almacenarán todos los bytes de la ROI leidos en forma de vector, es decir,
reserva una zona de memoria de tamaño 3 x width x height bytes, siendo width y heigth
el tamaño de la ROI en píxels.
Internamente lo que hace esta función es coger tres bytes(un píxel) del bloque de píxels
impares datablock1 y lo guarda en tres posiciones consecutivas del array bits¸ a
continuación coge otro tres bytes del bloque de píxels pares datablock2 y lo guarda en
las tres posiciones siguientes. Este proceso alternado se realiza hasta que todos los
píxels capturados han sido correctamente ordenados, formando en conjunto un array bits
que alterna los dos tipos de píxels existentes.
Esta función genera un fichero imagen bitmap de tamaño width x heigth con las
muestras almacenadas en la dirección de memoria referenciada por el puntero bits
guardando la imagen en la ruta especificada por el parámetro char filepath[512].
Además aprovecha que disponemos en un único vector con todos los píxels que forman
la imagen para calcular los valores RGB medios.
72
7.2 Secuencia de test
Una vez disponemos de unas librerías que permiten controlar y obtener información de
las placas LVDS Capturer, es el momento de implementar estas funciones dentro de una
secuencia de test. Esta secuencia de test nos permite obtener dos resultados importantes.
Por un lado comprobaremos si el proceso completo para la captura de regiones
funciona, por otro lado será más fácil someter al sistema a pruebas continuas que
garanticen su fiabilidad
Hay que tener en cuenta que la finalidad de este proyecto es mejorar la comprobación
actual de la salida de video hacía el LCD de la TV Board en de una cadena de
producción, a la vez que se intenta reducir el tiempo de este proceso. No hace falta decir
que un sistema poco seguro podría provocar un comportamiento anómalo de la máquina
de test CBA con los problemas que esto conllevaría, pudiendo provocar la parada
temporal de las líneas de producción.
Para realizar esta secuencia de test se ha uso de TestStand, una utilidad de National
Instruments que hace la función de secuenciador, permitiendo la llamada a funciones de
librerías desarrolladas en entornos de programación muy distintos como LabView,
LabWindows, C, C++, C# desde un mismo entorno gráfico. También tiene funciones
básicas como pueden ser condicionales como while, if, else y funciones de
sincronización. El uso de este programa implica que todos los parámetros de
entrada/salida que se deben pasar a las funciones se crean como variables locales o
parámetros propios de TestStand, de esta forma se puede debugar la secuencia llamada a
llamada, observando el valor actual de dichos parámetros.
Process
Setup
Main
Sequence
Proces
Cleanup
Finished Sequence
73
La secuencia global de Test está formada por 3 partes, el Process setup, Main sequence
y Process Cleanup.
Pocess Setup: Este código se ejecuta una única vez cuando se lanza la secuencia.
Su finalidad es realizar configuraciones y verificaciones previas del sistema,
antes de comenzar a verificar cualquier placa de televisión.
Process Cleanup: Código que se ejecuta una única vez tras finalizar la secuencia
de TestStand. Su finalidad es liberar objetos creados en las anteriores etapas.
Figura 61. Secuencia de TestStand para el análisis de tres barras de colores distintas
Una vez establecida la comunicación y decidido el tamaño de las ROI tenemos que
hacer dos llamadas a la función SendI2CCommandLVDSESIIC, una para cada esclavo de
I2C. Estas funciones tienen prefijados unos offsetx y un offsety, que juntamente con el
tamaño de la ROI definido permiten especificar exactamente una zona de captura, en
este caso en el centro de una de las barras de colores. Tras ejecutar estas dos funciones,
la región seleccionada se remarca en el panel y se realiza su análisis.
74
Finalmente una llamada a la función GetInfoImageLVDS, devuelve el valor promedio
RGB de esta ROI.
Figura 62. Resultados obtenidos en TestStand para las tres regiones analizadas
Regiones
Zona 1 Zona 2 Zona 3
Rmean 198 72 196
Gmean 194 192 0
Bmean 3 2 187
Figura 63. Resumen del análisis de las tres regiones
Y si generamos un color para cada una de las zonas analizadas obtenemos tres de los
colores que aparecen en la carta, que lógicamente eran los colores que se habían
seleccionado para su análisis.
Figura 64. Colores obtenidos mediante Paint a través de los resultados mostrados en TestStand
75
7.2.2 Captura de regiones
Uno de los puntos que no se pudo comprobar en el capítulo 6 era el proceso de captura
y envio hacia el ordenador de una región específica de la imagen. Con el desarrollo de
las librerías descritas en este capítulo ya podemos realizar capturas de tamaño
considerable y además generar un bitmap que permita ver los resultados obtenidos.
La primera fase para llevar a cabo estas capturas, consiste en seleccionar la zona de
interés mediante dos escrituras por I2C, uno para cada esclavo, haciendo uso de la
función SendI2cCommandLVDSESIIC.
El siguiente paso consiste en crear dos buffers de memoria para los píxels leidos por
cada una de las FPGAs, así como otro buffer global que se utilizará posteriormente para
unir los dos buffers anteriores y generar la imagen bitmap. Para ello usamos la función
Create_Data_Storage_LVDS para los buffers independientes y Create_Data_Storage
para el buffer global del bitmap.
76
Figura 67. Cálculo del número de lecturas y bucles de lectura
Ahora pasamos los bloques de memoria que contienen los píxels pares e impares a la
función Store_RGB_Block que se encargará de rellenar el buffer global intercalando en
él píxels pares e impares. Por último generamos la imagen con la información contenida
en este buffer mediante la función Save_Bitmap y liberamos el espacio de memoria que
habíamos reservado.
Figura 69. A la izquierda una foto del LCD donde se aprecia la región
seleccionada, a la derecha imagen capturada con la secuencia de TestStand.
Uno de los problemas que presenta la captura anterior y que nos impide verificar por
completo el sistema consiste en que al tratarse de una región pequeña hemos obtenido
una imagen formada por un color único, en este caso azul. Para asegurar que el sistema
es capaz de capturar cualquier tipo de imagen es conveniente probar a capturar una
imagen con formas y tonalidades variadas ya que en la captura de la figura 69 cualquier
movimiento o posicionamiento incorrecto de los píxels daría un resultado equivalente,
sin ser este correcto.
Para realizar una comprobación mas exhaustiva introducimos esta vez una señal de
entrada más compleja y variada con múltiples polígonos y formas donde se podría
77
apreciar claramente cualquier desvió en el proceso de captura. La señal introducida en el
panel y la captura obtenida se muestran en la figura 70.
Figura 70. A la izquierda LCD con la señal de entrada, a la derecha la captura realizada mediante la
secuencia de TestStand. Las diferencias entre ambas tonalidades se deben a que en la imagen de la
izquierda, la del panel, al hacer una fotografía los colores se han visto ligeramente alterados. El mismo
fenómeno ocurre en todas las fotografías realizadas directamente a un televisor LCD.
En este caso como se puede apreciar la captura ha sido de mayor tamaño, 1800x1000
píxels, casí la resolución máxima de un televisor FullHD( 1920x1080píxels). Como se
puede observar la captura y la imagen del panel son idénticas (ignorando el cambio de
tonalidad provocado por la cámara), las barras de colores que incluye esta señal de
entrada coinciden y los polígonos entrelazados también.
El único problema que plantea este sistema, y que lo hace inviable para realizar capturas
en la línea de producción, consiste en la reducida velocidad del bus I2C(100 Kbps). Para
dar unos tiempos aproximados, la captura de la imagen de la figura 70 ha tardado
aproximadamente 30 minutos. Si tenemos en cuenta que en las máquinas de test, donde
se desea implementar el sistema LVDS Capturer, se deben analizar alrededor de siete
señales de video recibidas en diferentes formatos, la comprobación del video por cada
una de las TV Board rondaría los 210 minutos, tiempo excesivamente elevado para una
cadena de producción. Una posible solución consistiría en incrementar la velocidad del
bus I2C, no obstante a velocidades ligeramente superiores a 100Kbps con el hardware
actual se empiezan a producir lecturas erróneas de píxels, que degradan
considerablemente la imagen.
Para analizar los límites de velocidad de la nueva configuración del bus I2C decidimos
introducir otra señal de entrada, esta vez una barra de colores verticales básica. Se
realizan múltiples capturas de una imagen de 1800x1000 píxels como la anterior. En las
pruebas realizadas el sistema funciona a velocidades de 800Kbps sin mostrar ningún
tipo de degradación de la imagen capturada. De hecho, en las pruebas realizadas el
78
sistema fue capaz de funcionar a velocidades superiores a 1Mbps, pero los resultados en
algunas de estas capturas mostraban la pérdida de algunos píxels.
Figura 71. A la izquierda LCD con carta de barras de colores, a la derecha la captura realizada mediante
la secuencia de TestStand. De nuevo las diferencias entre ambas tonalidades se deben a que en la imagen
de la izquierda, la del panel, al hacer una fotografía los colores se han visto ligeramente alterados. El
mismo fenómeno ocurre en todas las fotografías realizadas directamente a un televisor LCD.
79
8 Implementación en la línea de producción
Una vez verificado que el sistema es totalmente funcional tanto en su función básica de
análisis de regiones como en su versión extendida como capturador de imagen se
procede a implementar el sistema en la máquina de test CBA.
Figura 72. Máquina de test CBA remarcando la posición de los instrumentos que intervienen en el
sistema.
80
Una vez posicionado cada dispositivo en la máquina de test CBA, se procede a la
sustitución de la parte de la secuencia dedicada al "análisis" de las señales de video por
los fragmentos de secuencia desarrollados en el capítulo anterior. Además en esta
secuencia se deben añadir comprobaciones adicionales basadas en la lectura de los
registros delos esclavos de I2C, de esta forma se consiguen sustituir los tiempos de
espera estáticos introducidos en la secuencia de prueba por esperas dinámicas basadas
en el estado de los registros.
81
8.2 Subsecuencia de video adaptada
Lo siguiente es comprobar que existe una señal de reloj procedente de la TV Board que
llega a la placa LVDS Capturer y que es capaz de sincronizarse con el PLL de
74.25MHz que se ha implementado en las FPGAs. Este registro recibe el nombre de
Mem(17)-Locked.
Figura 74. Lectura de los registros de sincronización del PLL de la placa LVDS Capturer
82
Si la sincronización de la placa LVDS Capturer con el reloj procedente de la TV Board
no se produce, la lectura de este registro devolverá un '0', que indica que no hay señal de
reloj o que la frecuencia es errónea.
Figura 75. Envió de comandos para la selección de la ROI y bucle de lectura del registro Mem(24) que
indica la existencia de nuevos resultados
Figura 76. Lectura de los resultados con la posibilidad elegir entre comprobar los valores RGB Medios o
sólo la luminancia. Al final las llamadas Check comparan los resultados con las especificaciones.
Si los resultados de las tres regiones de video son correctos la secuencia continúa su
proceso realizando la comprobación de las demás entradas de video, en caso contrario,
la secuencia finaliza indicando un fallo debido a una TV Board dañada.
83
8.3 Incidencias
Tras realizar el montaje del sistema en la máquina de test, proceder a la modificación de
la secuencia WRK_Check_Video e introducir unas especificaciones para los resultados
de cada una de las zonas analizadas se lanza la secuencia, insertando previamente una
placa de televisión en la máquina de test. Para comprobar si la secuencia y el sistema
completo funcionan correctamente se ha colocado un panel LCD conectado a la salida
de la placa LVDS Capturer pudiendo apreciar así que con cada señal de video de
entrada el panel muestra la carta de colores correctamente, además se aprecia como se
remarcan las tres regiones especificadas para cada una de las señales de video de
entrada. La secuencia finaliza con éxito, estando todos los valores medios obtenidos
dentro de las especificaciones marcadas.
84
9 Conclusiones
Se han conseguido todos los objetivos que se habían fijado al plantear el proyecto, y el
diseño desarrollado tanto a nivel hardware como a nivel software funciona
correctamente.
Se debe añadir también que debido al éxito que ha tenido este proyecto, se encuentra
actualmente en fase de desarrollo otra versión más completa de la placa LVDS
Capturer, compatible con todos los modelos de televisión que se fabrican en la fábrica
de Sony en Viladecavalls. Esta nueva versión, entre otras opciones, permite el envío vía
ethernet hacia el ordenador de la señal de video en tiempo real que se esta enviando al
panel, permitiendo la captura rápida de imágenes FHD, así como la captura de video, y
no únicamente imágenes fijas como permitía este proyecto. Además, se trabaja
directamente sobre las señales diferenciales, eliminando los conversores de niveles
LVDS a TLL.
85
10 Bibliografía
WEBS DE I!TERÉS
• http://www.altera.com/
• http://www.altera.com/products/devices/cyclone2/cy2-index.jsp
• http://www.altium.com/products/en/products_home.cfm
• http://www.thine.co.jp/index_e.php
• http://www.thine.co.jp/products_e/LVDS/
DOCUME!TOS DE I!TERÉS
86
11 Anexos
87
ANEXO 1
Descripción del bus I2C
2-WIRE CMOS SERIAL E2PROM
S-24CS01A/02A/04A/08A Rev.2.0_10
Operation
1. Start Condition
Start is identified by a high to low transition of the SDA line while the SCL line is stable at high.
Every operation begins from a start condition.
2. Stop Condition
Stop is identified by a low to high transition of the SDA line while the SCL line is stable at high.
When a device receives a stop condition during a read sequence, the read operation is interrupted, and the
device enters standby mode.
When a device receives a stop condition during a write sequence, the reception of the write data is halted,
2
and the E PROM initiates a write cycle.
SCL
SDA
3. Data Transmission
Changing the SDA line while the SCL line is low, data is transmitted.
Changing the SDA line while the SCL line is high, a start or stop condition is recognized.
tSU.DAT tHD.DAT
SCL
SDA
4. Acknowledge
The unit of data transmission is 8 bits. During the 9th clock cycle period the receiver on the bus pulls down
the SDA line to acknowledge the receipt of the 8-bit data.
When a internal write cycle is in progress, the device does not generate an acknowledge.
SCL
(E2PROM Input) 1 8 9
SDA
(Master Output)
Acknowledge
SDA Output
2
(E PROM Output) Start Condition
tAA tDH
5. Device Addressing
To start communication, the master device on the system generates a start condition to the bus line. Next,
the master device sends 7-bit device address and a 1-bit read / write instruction code on to the SDA bus.
The 4 most significant bits of the device address are called the "Device Code", and are fixed to "1010".
In S-24CS01A/02A, successive 3 bits are called the "Slave Address". These 3 bits are used to identify a
device on the system bus and are compared with the predetermined value which is defined by the address
input pins (A0, A1 and A2). When the comparison result matches, the slave device responds with an
acknowledge during the 9th clock cycle.
In S-24CS04A, successive 2 bits are called the "Slave Address." These 2 bits are used to identify a device
on the system bus and are compared with the predetermined value which is defined by the address input
pins (A1 and A2). When the comparison result matches, the slave device responds with an acknowledge
during the 9th clock cycle.
The successive 1 bit (P0) is used to define a page address and choose the two 256-byte memory blocks
(Address 000h to 0FFh and 100h to 1FFh).
In S-24CS08A, successive 1 bit is called the “Slave Addrdess”. This 1 bit is used to identify a device on the
system bus and is compared with the predetermined value which is defined by the address input pin (A2).
When the comparison result matches, the slave device responds with an acknowledge during the 9th
clocks cycle.
The successive 2 bits (P1 and P0) are used to define a page address and choose the four 256-byte
memory blocks (Address 000h to 0FFh, 100h to 1FFh, 200h to 2FFh and 300h to 3FFh).
S-24CS01A/02A 1 0 1 0 A2 A1 A0 R/W
MSB LSB
Slave / Page
Device Code Address
S-24CS04A 1 0 1 0 A2 A1 P0 R/W
S-24CS08A 1 0 1 0 A2 P1 P0 R/W
MSB LSB
6. Write
When the master sends a 7-bit device address and a 1-bit read / write instruction code set to "0", following
2 2
a start condition, the E PROM acknowledges it. The E PROM then receives an 8-bit word address and
2
responds with an acknowledge. After the E PROM receives 8-bit write data and responds with an
acknowledge, it receives a stop condition and that initiates the write cycle at the addressed memory.
During the write cycle all operations are forbidden and no acknowledge is generated.
S W
T R S
A I T
R DEVICE T O
T ADDRESS E WORD ADDRESS DATA P
SDA LINE 1 0 1 0 A2 A1 A0 0 W7 W6 W5 W4 W3 W2 W1 W0 D7 D6 D5 D4 D3 D2 D1 D0
M L R A A A
S S / C C C
B B WK K K
The page write mode allows up to 8 bytes to be written in a single wire operation in the S-24CS01A/02A
and 16 bytes to be written in a single write operation in the S-24CS04A/08A.
Basic data transmission procedure is the same as that in the "Byte Write". But instead of generating a stop
condition, the master transmitts 8-bit write data up to 8 bytes before the page write.
2
When the E PROM receives a 7-bit device address and a 1-bit read / write instruction code set to "0",
2
following a start condition, it generates an acknowledge. Then the E PROM receives an 8-bit word
2
address, and responds with an acknowledge. After the E PROM receives 8-bit write data and responds
with an acknowledge, it receives 8-bit write data corresponding to the next word address, and generates
2
an acknowledge. The E PROM repeats reception of 8-bit write data and generation of acknowledge in
2
succession. The E PROM can receive as many write data as the maximum page size.
Receiving a stop condition initiates a write cycle of the area starting from the designated memory address
and having the page size equal to the received write data.
S W
T R S
A I T
R DEVICE T
ADDRESS E O
T WORD ADDRESS (n) DATA (n) DATA (n+1) DATA (n+x) P
SDA
1 0 1 0 A2 A1 A0 0 W7 W6 W5 W4 W3 W2 W1 W0 D7 D6 D5 D4 D3 D2 D1 D0 D7 D0 D7 D0
LINE
M L R A A A A A
S S / C C C C C
B B WK K K K K
Remark1. A1 is P1 in the S-24CS08A.
2. A0 is P0 in the S-24CS04A/08A. ADR INC ADR INC ADR INC
3. W7 is optional in the S-24CS01A.
Figure 13 Page Write
In S-24CS01A/02A, the lower 3 bits of the word address are automatically incremented every time when
2
the E PROM receives 8-bit write data. If the size of the write data exceeds 8 bytes, the upper 5 bits of the
word address remain unchanged, and the lower 3 bits are rolled over and previously received data will be
overwritten.
In S-24CS04A, the lower 4 bits of the word address are automatically incremented every time when the
2
E PROM receives 8-bit write data. If the size of the write data exceeds 16 bytes, the upper 4 bits of the
word address and page address (P0) remain unchanged, and the lower 4 bits are rolled over and
previously received data will be overwritten.
In S-24CS08A, the lower 4 bits of the word address are automatically incremented every time when the
2
E PROM receives 8-bit write data. If the size of the write data exceeds 16 bytes, the upper 4 bits of the
word address and page address (P1 and P0) remain unchanged, and the lower 4 bits are rolled over and
previously received data will be overwritten.
2
Acknowledge polling is used to know the completion of the write cycle in the E PROM.
2
After the E PROM receives a stop condition and once starts the write cycle, all operations are forbidden
and no response is made to the signal transmitted by the master device.
2
Accordingly the master device can recognize the completion of the write cycle in the E PROM by detecting
a response from the slave device after transmitting the start condition, the device address and the
2
read/write instruction code to the E PROM, namely to the slave devices.
2
That is, if the E PROM does not generate an acknowledge, the write cycle is in progress and if the
2
E PROM generates an acknowledge, the write cycle has been completed.
It is recommended to use the read instruction "1" as the read/write instruction code transmitted by the
master device.
Write protection is available in the S-24CS01A/02A/04A/08A. When the WP pin is connected to the VCC,
write operation to memory area is forbidden at all.
When the WP pin is connected to the GND, the write protection is invalid, and write operation in all memory
area is available. There is no need for using write protection, the WP pin should be connected to the GND.
The write protection is valid in the operating voltage range.
7. Read
2
Either in writing or in reading the E PROM holds the last accessed memory address, internally
incremented by one. The memory address is maintained as long as the power voltage is higher than the
current address hold voltage VAH.
The master device can read the data at the memory address of the current address pointer without
assigning the word address as a result, when it recognizes the position of the address pointer in the
2
E PROM. This is called "Current Address Read".
2
In the following the address counter in the E PROM is assumed to be “n”.
2
When the E PROM receives a 7-bit device address and a 1-bit read / write instruction code set to “1”
following a start condition, it responds with an acknowledge. However, the page address (P0) in S-
24CS04A and the page address (P1 and P0) in S-24CS08A become invalid and the memory address of
the current address pointer becoms valid.
2
Next an 8-bit data at the address "n" is sent from the E PROM synchronous to the SCL clock. The address
counter is incremented at the falling edge of the SCL clock for the 8th bit data, and the content of the
address counter becomes n+1.
The master device has to not acknowledge the 8-bit data and terminates the reading with a stop condition.
S NO ACK from
T R Master Device S
A E T
R DEVICE A O
T ADDRESS D P
SDA LINE 1 0 1 0 A2 A1 A0 1 D7 D6 D5 D4 D3 D2 D1 D0
M L R A DATA
S S / C
B B W K
ADR INC
Remark1. A1 is P1 in S-24CS08A.
2. A0 is P0 in S-24CS04A/08A.
2
Attention should be paid to the following point on the recognition of the address pointer in the E PROM.
2
In the read operation the memory address counter in the E PROM is automatically incremented at every
falling edge of the SCL clock for the 8th bit of the output data. In the write operation, on the other hand, the
*1
upper bits of the memory address (the upper bits of the word address and page address) are left
unchanged and are not incremented at the falling edge of the SCL clock for the 8th bit of the received
data.
S W S
T R T R NO ACK from S
A I A E Master Device T
R DEVICE T WORD R DEVICE A O
T ADDRESS E ADDRESS (n) T ADDRESS D DATA P
SDA
LINE 1 0 1 0 A2 A1 A0 0 W7W6W5W4W3W2W1W0 1 0 1 0 A2 A1 A0 1 D7 D6 D5 D4 D3 D2 D1 D0
M L R A A M L R A
S S / C C S S / C
B B WK K B B W K
ADR INC
DUMMY WRITE
2
When the E PROM receives a 7-bit device address and a 1-bit read / write instruction code set to "1"
following a start condition both in current and random read operations, it responds with an acknowledge.
2
An 8-bit data is then sent from the E PROM synchronous to the SCL clock and the address counter is
automatically incremented at the falling edge of the SCL clock for the 8th bit data.
When the master device responds with an acknowledge, the data at the next memory address is
transmitted. Response with an acknowledge by the master device has the memory address counter in the
2
E PROM incremented and makes it possible to read data in succession. This is called "Sequential Read".
The master device has not acknowledge and terminates the reading with a stop condition.
Data can be read in succession in the sequential read mode. When the memory address counter reaches
the last word address, it rolls over to the first memory address.
NO ACK from
R Master Device S
DEVICE E A A A T
ADDRESS A C C C O
D K K K P
SDA D7 D0 D7 D0 D7 D0 D7 D0
LINE 1
The timing for the automatic address increment is the falling edge of the SCL clock for the 8th bit of the
read data in read operation and the the falling edge of the SCL clock for the 8th bit of the received data in
write operation.
SCL
8 9 1 8 9
Address Increment
SCL
8 9 1 8 9
Address Increment
Figure 18 Address Increment Timing in Writing
The S-24CS01A/02A/04A/08A have a detection circuit for low power voltage. The detection circuit cancels a
write instruction when the power voltage is low or the power switch is on. The detection voltage is 1.75 V
typically and the release voltage is 2.05 V typically, the hysteresis of approximate 0.3 V thus exists. (See
Figure 19.)
When a low power voltage is detected, a write instruction is canceled at the reception of a stop condition.
When the power voltage lowers during a data transmission or a write operation, the date at the address of
the operation is not assured.
Hysteresis width
0.3 V approximately
Power supply voltage
Release voltage (+VDET)
Detection voltage (-VDET) 2.05 V typ.
1.75 V typ.
Write Instruction
cancel
BANK 4
BANK 1
BANK 2 BANK 3
BANK 4
BANK 1
CN1
1 2 1 2 1 2 1 2 1 2
4 3 4 3 4 3 4 3 4 3
1 2 1 2 1 2 1 2 1 2
4 3 4 3 4 3 4 3 4 3
ANEXO 3
Código VHDL
Date: May 30, 2010 COUNTER_V2.vhd Project: lvds1
1 Library IEEE;
2 Use ieee.std_logic_1164.all;
3 Use ieee.std_logic_arith.all;
4
5
6
7 entity COUNTER_V2 is
8 Port(
9 clk,nrst : in std_logic;
10 v_sync: in std_logic;
11 DE: in std_logic;
12 hori_pos: out integer range 0 to 1919;
13 vert_pos : out integer range 0 to 1079
14 );
15 end entity;
16
17
18 architecture comportament of COUNTER_V2 is
19
20 signal contador_hori: integer range 0 to 1919;
21 signal contador_vert: integer range 0 to 1079;
22 signal s_DE, sv_sync,waiting_first_de: std_logic;
23
24 type states is (sincro_v,sincro_h);
25 signal state : states;
26
27 begin
28
29 contador: process(clk,nrst)
30 begin
31 if( nrst = '0') then
32 contador_hori<=0;
33 contador_vert<=0;
34 waiting_first_de <='1';
35 state <=sincro_v;
36
37 elsif ((clk'event and clk = '1')) then
38 sv_sync <=v_sync;
39 s_DE<= DE;
40 case state is
41 when sincro_v =>
42 --A nivell vertical tot comença amb el vsync
43 if (v_sync ='1' and sv_sync ='0') then
44 state <= sincro_h;
45 waiting_first_de<='1';
46 end if;
47 --Al trobar un vsync despress hi ha blanking
48
49 when sincro_h =>
50 --Pixels parells
51 --Mentre DE estigui a baix el contador_horizontal
ha de ser 0
52 --SI DE esta a 0 ,el contrador vertical ha de
passar a 0 nomes si es el primer cop despres d'un vsync
53 if (DE='0') then
54 if (waiting_first_de='1') then
55 contador_hori <=0;
56 contador_vert <=0;
57 else
413
414
415 --Aqui carreguem el valor del nou
pixel al registre mem:
416 --La adreça quan tornem a entrar
a data_out i veniem de data_out ha de ser x"09"
417 if ( bit_cnt = 7 ) then
418 if ( read_address_counter = x"09"
) then
419 if(fifo_empty='1' and
flag_ultima_lectura ='0') then
420 mem(CONV_INTEGER(
read_address_counter+1))<="11111111";
421 mem(CONV_INTEGER(
read_address_counter+2))<="11111111";
WSACleanup( );
return 0;
}
if (*esiicFileDes == INVALID_SOCKET){
C:\Users\Jaume\Documents\Visual Studio 2005\Projects\esiic.c.cpp 2
SocketErrorHandler(errMessage, WSAGetLastError());
strcpy(message, "Windows Sockets error: ");
strcat(message, errMessage);
WSACleanup( );
return 0;
}
cli_addr.sin_family=AF_INET;
cli_addr.sin_addr.s_addr=INADDR_ANY;
cli_addr.sin_port=0; // no specific port req'd
if (bind(*esiicFileDes,(LPSOCKADDR)&cli_addr,sizeof(cli_addr)) == SOCKET_ERROR){
SocketErrorHandler(errMessage, WSAGetLastError());
strcpy(message, "Windows Sockets error: ");
strcat(message, errMessage);
// UnloadWinsockAPI(*esiicFileDes);
return 0;
}
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.s_addr = inet_addr(ipString);
srv_addr.sin_port = htons(ipPort);
tmout.tv_sec = timeout;
tmout.tv_usec = 0;
}
else{
SocketErrorHandler(errMessage, WSAGetLastError());
strcpy(message, "Windows Sockets error: ");
strcat(message, errMessage);
// UnloadWinsockAPI(*esiicFileDes);
return 0;
}
}
}
rx_buffer[total_bytes_received]=0;
return 1;
else{
//flush menu
total_bytes_received=0;
timeout = 0;
while(total_bytes_received<377 && timeout < 20){
bytes_received = recv(*esiicFileDes, &rx_buffer[total_bytes_received],
RX_BUFF_SIZE-1-total_bytes_received, 0);
if(bytes_received > 0){
total_bytes_received = total_bytes_received + bytes_received;
// Zero terminate so we can use string functions
}
else{
//Error Checking de problemes amb el socket
err = WSAGetLastError();
if(err == WSAEWOULDBLOCK || err == 0){
timeout++;
Delay(0.1);
}
else{
SocketErrorHandler(errMessage, WSAGetLastError());
strcpy(message, "Windows Sockets error: ");
strcat(message, errMessage);
// UnloadWinsockAPI(*esiicFileDes);
C:\Users\Jaume\Documents\Visual Studio 2005\Projects\esiic.c.cpp 4
return 0;
}
}
}
if (timeout >= 20){
strcpy(message, "Windows Sockets error: ");
strcat(message, "Timeout Error (likely disconnected device)");
// UnloadWinsockAPI(*esiicFileDes);
return 0;
}
rx_buffer[total_bytes_received]=0;
return 1;
//Menu correctly flushed from receive queue
}
}
int __declspec(dllexport) __stdcall CloseConnectionWithESIIC(char message[512], unsigned
int esiicFileDes){
int err;
char errMessage[512];
//First we will need to close the default resource manager.
err = shutdown(esiicFileDes, 1 );
SocketErrorHandler(errMessage, WSAGetLastError());
if( err == SOCKET_ERROR ){
strcpy(message, "Windows Sockets error: ");
strcat(message, errMessage);
UnloadWinsockAPI(esiicFileDes);
return 0;
}
closesocket(esiicFileDes);
WSACleanup();
return 1;
}
char command[256];
char data[256];
char errMessage [256];
char message_single [256];
char fileName2C35[256];
char *token;
int sizeFile=0;
unsigned char dada_llegida[256];
DWORD prewritetime;
DWORD postwritetime;
double write_time;
int result;
BYTE i2c_subaddr_array[4];
C:\Users\Jaume\Documents\Visual Studio 2005\Projects\esiic.c.cpp 5
RemoveSurroundingWhiteSpace (i2c_selected);
RemoveSurroundingWhiteSpace (cs_selected);
//CS Modes Allowed
//"no_cs","se1boot"."vga"."vga_pin10"
//i2chdmi1 -write_data -rate 400000 -i2caddr D0 -subaddrini 00 -num_bytes 3 -data
2A0000 -cs se1boot
// for(i=0; i<bytes_data; i++){
// Fmt(&data[2*i], "%x[b1up0w2]", tx[i]);
// }
Fmt(&data[0],"%x[b2up0w4]",offsety);
Fmt(&data[4],"%x[b2up0w4]", offsetx);
Fmt(&data[8],"%x[b2up0w4]",length);
Fmt(&data[12],"%x[b2up0w4]",width);
/* if(ReadI2cIndividualBytesESIIC(message,esiicFileDes,i2c_selected,rate, i2c_address,
17, 1, 1,dada_llegida) == 0){
return 0;
//Control d'errors en cas de que la funció ReadI2c... falli. Retornarem l'error d
'aquesta funció.
}
if(dada_llegida[0]==0){
//En cas que no detectem clock, ERROR
strcpy(message, "ESIIC generic error:LVDS clock not detected");
return 0;}
*/
if(subaddr_ini == -1){
Fmt(command, "%s -write_data -rate %d -i2caddr %x[b1up0w2] -data %s -num_bytes %d\
r\n ", i2c_selected, rate, i2c_address, data, bytes_data);
}
else{
prewritetime = timeGetTime();
//Enviar la comanda al socket. Ara s'ha d'implementar amb timeouts
bytes_to_send = strlen(command);
data_sent = 0;
while(data_sent<bytes_to_send){
bytes_sent = send(esiicFileDes, command, bytes_to_send, 0);
//Socket non-blocking. Don't hang if can't send bytes, it returns SOCKET_ERROR
err = WSAGetLastError();
if (bytes_sent > 0) {
data_sent = data_sent + bytes_sent;
}
//if (bytes_sent == SOCKET_ERROR) {
else{
//Error Checking de problemes amb el socket
if(err == WSAETIMEDOUT ){
strcpy(message, "Windows Sockets error: ");
strcat(message, "Timeout Error (likely disconnected device)");
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
else{
SocketErrorHandler(errMessage, WSAGetLastError());
strcpy(message, "Windows Sockets error: ");
strcat(message, errMessage);
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
}
}
ret = getsockopt(esiicFileDes, SOL_SOCKET, SO_RCVTIMEO, (char*)&old_tmout, &len);
if(ret == SOCKET_ERROR){
SocketErrorHandler(errMessage, WSAGetLastError());
strcpy(message, "getsockopt(SO_RCVTIMEO) failed: ");
strcat(message, errMessage);
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
new_tmout.tv_sec = rcv_timeout;
new_tmout.tv_usec = 0;
//Capturar ara el que retorna el socket. Ara s'ha d'implementar amb timeouts
lf_addr = NULL;
total_bytes_received=0;
while(lf_addr == NULL){
bytes_received = recv(esiicFileDes, &rx_buffer[total_bytes_received], RX_BUFF_SIZE
-total_bytes_received, 0);
err = WSAGetLastError();
if(bytes_received > 0){
total_bytes_received = total_bytes_received + bytes_received;
}
//if (bytes_sent == SOCKET_ERROR) {
else{
//Error Checking de problemes amb el socket
if(err == WSAETIMEDOUT ){
strcpy(message, "Windows Sockets error: ");
strcat(message, "Timeout Error (likely disconnected device)");
// UnloadWinsockAPI(esiicFileDes);
return 0;
C:\Users\Jaume\Documents\Visual Studio 2005\Projects\esiic.c.cpp 7
}
else{
SocketErrorHandler(errMessage, WSAGetLastError());
strcpy(message, "Windows Sockets error: ");
strcat(message, errMessage);
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
}
lf_addr = strchr(rx_buffer, '\n');
}
*(lf_addr+1) = 0;
//Ara hem de interpretar el que ens ha retornat rx_buffer. Trencar en tokens
token = strtok(rx_buffer,"|");
if(!strcmp(token,"OK")){
postwritetime = timeGetTime();
write_time = (double)(postwritetime - prewritetime)/1000;
Fmt(message, "I2C transaction total time: %f[p4] segons", write_time);
strcpy(message, "Command execution succesful");
}
}
char temp[50];
char errMessage[512];
char command[512];
char temp_subaddr_string[32];
char subaddr_ini_string[32];
strcpy(subaddr_ini_string,"");
strcpy(temp_subaddr_string,"");
//i2chdmi1 -read_rx -rate 100000 -i2caddr A0 -subaddrini 00 -num_bytes 16
if(subaddr_ini == -1){
Fmt(command, "%s -read_rx -rate %d -i2caddr %x[b1up0w2] -num_bytes %d \r\n",
i2c_selected, rate, i2c_address, bytes_to_read);
}
else{
//Depenen dels bytes de subadreça, definir el que enviem
i2c_subaddr_array[0] = subaddr_ini & 0xFF;
i2c_subaddr_array[1] = (subaddr_ini & 0xFF00) >> 8;
i2c_subaddr_array[2] = (subaddr_ini & 0xFF0000) >> 16;
i2c_subaddr_array[3] = (subaddr_ini & 0xFF000000) >> 24;
firstloop=1;
for(i=bytes_subaddr-1; i>=0; i--){
Fmt(temp_subaddr_string, "%x[b1up0w2]", i2c_subaddr_array[i]);
if(firstloop==1){
strcpy(subaddr_ini_string, temp_subaddr_string);
firstloop=0;
}
else{
strcat(subaddr_ini_string, temp_subaddr_string);
}
}
Fmt(command, "%s -read_rx -rate %d -i2caddr %x[b1up0w2] -subaddrini %s -num_bytes
%d \r\n", i2c_selected, rate, i2c_address, subaddr_ini_string, bytes_to_read);
}
//Capturar ara el que retorna el socket. Ara s'ha d'implementar amb timeouts
lf_addr = NULL;
total_bytes_received=0;
while(lf_addr == NULL){
bytes_received = recv(esiicFileDes, &rx_buffer[total_bytes_received], RX_BUFF_SIZE
-total_bytes_received, 0);
err = WSAGetLastError();
if(bytes_received > 0){
total_bytes_received = total_bytes_received + bytes_received;
}
//if (bytes_sent == SOCKET_ERROR) {
else{
//Error Checking de problemes amb el socket
if(err == WSAETIMEDOUT ){
strcpy(message, "Windows Sockets error: ");
strcat(message, "Timeout Error (likely disconnected device)");
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
else{
SocketErrorHandler(errMessage, WSAGetLastError());
strcpy(message, "Windows Sockets error: ");
strcat(message, errMessage);
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
}
lf_addr = strchr(rx_buffer, '\n');
}
*(lf_addr+1) = 0;
//Ara hem de interpretar el que ens ha retornat rx_buffer. Trencar en tokens
token = strtok(rx_buffer,"|");
if(!strcmp(token,"RT")){
//Return bytes Format |RT|12|00|0004|03B36A91
token = strtok(NULL,"|");
//Tasca que ha donat l'error
token = strtok(NULL,"|");
//SubFunció dintre la tasca que ha donat l'error
token = strtok(NULL,"|");
//Número de bytes que retorna
ret_bytes_read = atoi(token);
if(ret_bytes_read != bytes_to_read){
strcpy(message, "ESIIC I2C read error: bytes read by i2c different from
expected ones");
//Discutible si cal tancar
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
token = strtok(NULL,"|");
//Bytes llegits. En el cas de checksum, passar a enter el valor
//Hem de convertir de hexa_string a unsigned char
for(cntChar=0;cntChar<ret_bytes_read;cntChar++){
Fmt (&rx_data[cntChar],"%i[r16]<%s[w2]",&token[cntChar*2]);
recv_data[cntChar] = rx_data[cntChar] & 0xFF;
}
int rate;
unsigned int rx_data[100];
unsigned char i2c_address1;
unsigned char i2c_address2;
int subaddr_ini;
int bytes_subaddr;
int bytes_to_read;
unsigned char dada_llegida[5];
*Rmean= (int)(dada_llegida[0]/2);
*Gmean= (int)(dada_llegida[1]/2);
*Bmean= (int)(dada_llegida[2]/2);
Delay(0.1);
if(ReadI2cIndividualBytesESIIC(message,esiicFileDes,i2c_selected, rate, i2c_address2,
subaddr_ini, bytes_subaddr, bytes_to_read,dada_llegida) == 0){
return 0;
//Control d'errors en cas de que la funció ReadI2c... falli. Retornarem l'error d
C:\Users\Jaume\Documents\Visual Studio 2005\Projects\esiic.c.cpp 11
'aquesta funció.
}
*Rmean+= (int)(dada_llegida[0]/2);
*Gmean+= (int)(dada_llegida[1]/2);
*Bmean+= (int)(dada_llegida[2]/2);
*Luminancia= (int)(0.299**Rmean + 0.587**Gmean + 0.114**Bmean);
return 1;
*Rmin= (int)(dada_llegida[0]/2);
*Gmin= (int)(dada_llegida[1]/2);
*Bmin= (int)(dada_llegida[2]/2);
*Rmax= (int)(dada_llegida[3]/2);
*Gmax= (int)(dada_llegida[4]/2);
*Bmax= (int)(dada_llegida[5]/2);
return 1;
char temp[50];
char errMessage[512];
char command[512];
char temp_subaddr_string[32];
char subaddr_ini_string[32];
strcpy(subaddr_ini_string,"");
strcpy(temp_subaddr_string,"");
//i2chdmi1 -read_rx -rate 100000 -i2caddr A0 -subaddrini 00 -num_bytes 16
if(subaddr_ini == -1){
Fmt(command, "%s -read_rx -rate %d -i2caddr %x[b1up0w2] -num_bytes %d \r\n",
i2c_selected, rate, i2c_address, bytes_to_read);
}
else{
//Depenen dels bytes de subadreça, definir el que enviem
i2c_subaddr_array[0] = subaddr_ini & 0xFF;
i2c_subaddr_array[1] = (subaddr_ini & 0xFF00) >> 8;
i2c_subaddr_array[2] = (subaddr_ini & 0xFF0000) >> 16;
i2c_subaddr_array[3] = (subaddr_ini & 0xFF000000) >> 24;
firstloop=1;
for(i=bytes_subaddr-1; i>=0; i--){
Fmt(temp_subaddr_string, "%x[b1up0w2]", i2c_subaddr_array[i]);
if(firstloop==1){
strcpy(subaddr_ini_string, temp_subaddr_string);
firstloop=0;
}
else{
strcat(subaddr_ini_string, temp_subaddr_string);
}
C:\Users\Jaume\Documents\Visual Studio 2005\Projects\esiic.c.cpp 13
}
Fmt(command, "%s -read_rx -rate %d -i2caddr %x[b1up0w2] -subaddrini %s -num_bytes
%d \r\n", i2c_selected, rate, i2c_address, subaddr_ini_string, bytes_to_read);
}
return 0;
}
else{
SocketErrorHandler(errMessage, WSAGetLastError());
strcpy(message, "Windows Sockets error: ");
strcat(message, errMessage);
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
}
}
//Capturar ara el que retorna el socket. Ara s'ha d'implementar amb timeouts
lf_addr = NULL;
total_bytes_received=0;
while(lf_addr == NULL){
bytes_received = recv(esiicFileDes, &rx_buffer[total_bytes_received], RX_BUFF_SIZE
-total_bytes_received, 0);
err = WSAGetLastError();
if(bytes_received > 0){
total_bytes_received = total_bytes_received + bytes_received;
}
//if (bytes_sent == SOCKET_ERROR) {
else{
//Error Checking de problemes amb el socket
if(err == WSAETIMEDOUT ){
strcpy(message, "Windows Sockets error: ");
strcat(message, "Timeout Error (likely disconnected device)");
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
else{
SocketErrorHandler(errMessage, WSAGetLastError());
strcpy(message, "Windows Sockets error: ");
strcat(message, errMessage);
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
}
lf_addr = strchr(rx_buffer, '\n');
}
*(lf_addr+1) = 0;
//Ara hem de interpretar el que ens ha retornat rx_buffer. Trencar en tokens
token = strtok(rx_buffer,"|");
if(!strcmp(token,"RT")){
//Return bytes Format |RT|12|00|0004|03B36A91
token = strtok(NULL,"|");
//Tasca que ha donat l'error
C:\Users\Jaume\Documents\Visual Studio 2005\Projects\esiic.c.cpp 14
token = strtok(NULL,"|");
//SubFunció dintre la tasca que ha donat l'error
token = strtok(NULL,"|");
//Número de bytes que retorna
ret_bytes_read = atoi(token);
if(ret_bytes_read != bytes_to_read){
strcpy(message, "ESIIC I2C read error: bytes read by i2c different from
expected ones");
//Discutible si cal tancar
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
token = strtok(NULL,"|");
//Bytes llegits. En el cas de checksum, passar a enter el valor
//Hem de convertir de hexa_string a unsigned char
for(cntChar=0;cntChar<ret_bytes_read;cntChar++){
Fmt (&rx_data[cntChar],"%i[r16]<%s[w2]",&token[cntChar*2]);
// recv_data[cntChar] = rx_data[cntChar] & 0xFF;
bits_alloc[cntChar] = rx_data[cntChar] & 0xFF;
}
return 1;
}
else{
//Error Format: |NG|10|01|0001|Incorrect Format: nothing in cmdline to execute
token = strtok(NULL,"|");
//Tasca que ha donat l'error
token = strtok(NULL,"|");
//SubFunció dintre la tasca que ha donat l'error
token = strtok(NULL,"|");
//Codi d'error definit
token = strtok(NULL,"|");
//Missatge d'error. De moment l'únic que utilitzarem
strcpy(errMessage, token);
strcpy(message, "ESIIC Checksum read error: ");
strcat(message, errMessage);
//Discutible si cal tancar
// UnloadWinsockAPI(esiicFileDes);
return 0;
}
}
C:\Users\Jaume\Desktop\PenDrive\PFC LVDS\Bitmaps\Bitmaps.c 1
#include "windows.h"
#include <winsock.h>
#include <formatio.h>
#include "mmsystem.h"
#include <utility.h>
#include <userint.h>
#include "inifile.h"
#include <stdio.h>
#include <stdlib.h>
//datablock es un vector
for (j=0;j<height;j++){
for (i=0;i<width;i++){
//pixel par
if (i%2==0){
bits_alloc[j*width*3+i*3] = bits_alloc1[pixel*3] & 0xFF;
bits_alloc[j*width*3+i*3+1] =bits_alloc1[pixel*3+1] & 0xFF;
bits_alloc[j*width*3+i*3+2] =bits_alloc1[pixel*3+2] & 0xFF;}
//pixel parell
else{
bits_alloc[j*width*3+i*3] = bits_alloc2[pixel*3] & 0xFF;
bits_alloc[j*width*3+i*3+1] =bits_alloc2[pixel*3+1] & 0xFF;
bits_alloc[j*width*3+i*3+2] =bits_alloc2[pixel*3+2] & 0xFF;
pixel++;
}
}
C:\Users\Jaume\Desktop\PenDrive\PFC LVDS\Bitmaps\Bitmaps.c 2
}
int colorTable[12];
int handle;
int status;
int i;
unsigned char *bits_alloc;
i=0;
bits_alloc = (unsigned char *) *bits;
for(i=0; i<height*width;i++){
*Rmean+=bits_alloc[i*3];
*Gmean+=bits_alloc[i*3+1];
*Bmean+=bits_alloc[i*3+2];
}
*Rmean/=height*width;
*Gmean/=height*width;
*Bmean/=height*width;
int colorSize;
int bitsSize;
int maskSize;
int bytesPerRow;
int pixelDepth;
int width;
int height;
int *colorTable;
unsigned char *mask;
int dades_len;
int y;
int x;
//Reads a bitmap image from a file and creates a bitmap object- int GetBitmapFromFile
(char filename[], int *bitmapID);
status = GetBitmapFromFile (source_filepath, &handle);
//Obtains size information about the image associated with a bitmap. int GetBitmapInfo
(int bitmapID, int *colorSize, int *bitsSize, int *maskSize);
status = GetBitmapInfo (handle, &colorSize, &bitsSize, &maskSize);
//Obtains the bit values that define the image associated with a bitmap. int
GetBitmapData (int bitmapID, int *bytesPerRow, int *pixelDepth, int *width, int *
height, int colorTable[], unsigned char bits[], unsigned char mask[]);
C:\Users\Jaume\Desktop\PenDrive\PFC LVDS\Bitmaps\Bitmaps.c 3
status = GetBitmapData (handle, &bytesPerRow, &pixelDepth, &width, &height, 0,
line_bits_alloc, 0);
dades_len = strlen(line_bits_alloc);
return 1;
}
/*
//Exemples de codi de prova abans de la llibreria definitiva
int i;
int row;
int change=0;
int bitmap_handle;
int status;
unsigned char *bits_alloc;
return 1;
}
int __declspec(dllexport) __stdcall Store_RGB(char message[512], int *bits)
{
unsigned char *bits_alloc;
bits_alloc[0] = 0xFF;
bits_alloc[1] = 0x00;
bits_alloc[2] = 0x00;
*bits = (int) bits_alloc;
return 1;
}
C:\Users\Jaume\Desktop\PenDrive\PFC LVDS\Bitmaps\Bitmaps.c 4
int colorTable[12];
unsigned char bits[12];
int status;
bits[0]=0x00; //RR
bits[1]=0x00; //GG
bits[2]=0x00; //BB
bits[3]=0xFF;
bits[4]=0xFF;
bits[5]=0xFF;
bits[6]=0xFF;
bits[7]=0xFF;
bits[8]=0xFF;
bits[9]=0x00;
bits[10]=0x00;
bits[11]=0x00;
//tauler d'escacs de 2
int colorTable[12];
int handle;
int status;
unsigned char *bits_alloc;
bits_alloc = (unsigned char *) *bits;