ATENÇÃO: A VERSÃO MAIS ATUAL DESSE PROJETO VOCÊ ENCONTRA NESSE LINK:

http://labdegaragem.com/profiles/blogs/gerando-sinal-vga-colorido-c...

OS PROBLEMAS RELATADOS ABAIXO JÁ FORAM RESOLVIDOS. :))

************************************************************************************************************

Fala galera,

Continuando meus estudos sobre sinal VGA, consegui gerar o sinal de sincronia e os sinais RGB. Agora já dá para gerar barras e retângulos coloridos.

Ainda estou enfrentando alguns problemas, como o preenchimento total da tela (ainda está rolando uma área preta do lado direito da tela), mas acho que isso pode ser resolvido com uma análise melhor dos tempos das instruções durante a execução, estou perdendo parte da linha ainda.

Além disso, nem todos os monitores LCD reconhecem o sinal, os CRT entendem tranquilamente. Acredito que seja um ajuste mais fino de tempo e/ou casamento de impedância.

Seguem os detalhes abaixo:

Esse foi o primeiro passo: gerar um retângulo sólido e estável na tela. Ele é branco porque joguei sinal HIGH nos 3 bits de cor (RGB), o importante aqui é que os sinais de sincronia funcionaram perfeitamente.

Aqui uma foto tosca do monitor (a câmera e minhas habilidades fotográficas não ajudaram), mas o importante é que alternando os bits R, G e B, foi possível gerar as 8 cores. Na verdade, seria possível gerar muito mais cores utilizando outras estratégias ou simplesmente controlando os níveis de tensão de cada bit de cor (0 a 0,7V), mas para isso teria que usar portas analógicas, que não são rápidas o suficiente. Bom, aqui ainda há muito o que estudar e testar.

Segue o código que usei, que está cheio de bugs e coisas a melhorar, mas pode ser útil para alguém:

#define NOP asm("nop")
#define PRETO PORTB = B00000000;
#define AZUL PORTB = B00000001;
#define VERDE PORTB = B00000010;
#define CIANO PORTB = B00000011;
#define VERMELHO PORTB = B00000100;
#define MAGENTA PORTB = B00000101;
#define AMARELO PORTB = B00000110;
#define BRANCO PORTB = B00000111;

unsigned int contalinhas = 1;

void setup()
{
//Seta pinos 5, 6 e 7 como saidas
// 7 - HSYNC
// 6 - VSYNC
// 10 - R
// 9 - G
// 8 - B

DDRD |= B11100000;

DDRB |= B11100111;
PORTD |= B11000000;

//set timer
TCCR2A = 0x02; // WGM22=0 + WGM21=1 + WGM20=0 = Mode2 (CTC)
TCCR2B |= (1 CS20); //
TCCR2B |= (1 CS21); // Seta prescaler
TCCR2B &= ~(1 CS22); //

TCNT2 = 0; // limpa contador
OCR2A = 0x0f; // seta contador para comaracao

TIMSK2 |= (1OCIE2A); // seta interrupcao por comparacao
}

void loop()
{
do{
}while(1);

}

ISR(TIMER2_COMPA_vect){


PORTD &= ~(1 7);
if (++contalinhas == 525){ //525 linhas
contalinhas = 1;
}
PORTD |= (1 7);

NOP;NOP;NOP;NOP;NOP;NOP;


if (contalinhas == 492){
PORTD &= ~(1 6);
} else {
PORTD |= (1 6);


if ((contalinhas >= 2) && (contalinhas <= 480)){

//Pinta um arco-iris na tela
for (int j=0; j<6; j++){
PRETO;NOP;
AZUL;
PRETO;NOP;
VERDE;
PRETO;NOP;
CIANO;
PRETO;NOP;
VERMELHO;
PRETO;NOP;
MAGENTA;
PRETO;NOP;
AMARELO;
PRETO;NOP;
BRANCO;
PRETO;NOP;
}
}

}

NOP; //pequeno ajuste de tempo, pode ser necessario ou nao dependendo da placa

}

Bom, é isso! Essa primeira etapa foi para acertar a sincronia. Falta ainda compreender os formatos e ajustar melhor o frame no monitor. Em paralelo, casar as impedâncias entre o circuito e o monitor (que pode ser a causa de alguns LCDs não entenderem o sinal).

Quero ainda melhorar a precisão do sinal de sincronia.

Posteriormente, criar janelas de tempo para aquisição de dados.

Com isso tudo, pretendo chegar a uma biblioteca para a galera usar com qualquer Arduino e qualquer monitor VGA, inclusive TFTs. :) 

Vamos ver no que vai dar!

Vou postando e compartilhando com a galera do Lab de Garagem cada passo dado.

Abraços!!

Exibições: 1761

Comentar

Você precisa ser um membro de Laboratorio de Garagem (arduino, eletrônica, robotica, hacking) para adicionar comentários!

Entrar em Laboratorio de Garagem (arduino, eletrônica, robotica, hacking)

Comentário de Joe Nova em 23 março 2012 às 10:25

 

Olá !

 

Realmente pode ser um problema de gerenciamento dos tempos, algo não tão simples de ser feito qdo vc esta usando uma liguagem de alto nivel, não é mesmo ? Em assembler é fácil.

Mas programar em assembler..haja paciencia né...

Boa sorte !

 

 

Comentário de Marcelo Rodrigues em 23 março 2012 às 10:10

Valeu Joe,

No meu caso, pelo que estudei ontem, é que o tempo de entrada e retorno da interrupção estão grandes demais, comendo parte do frame. O que pretendo fazer hoje (se der tempo) é não chamar a função da interrupção, mas ficar monitorando o flag de interrução e desenhar a linha dentro de um if.

Se der certo, acho que eu preencho o resto o frame.

Veremos!!! :)

Abraço!!

Comentário de Joe Nova em 23 março 2012 às 9:53

 

Olá Marcelo

 

Interessante este projeto, já andei gerando barras, com Cis digitais, discretos...no formato NTSC e PAL-M, tive problemas com o sincronismo tb. O meu problema era na linha de alimentação os divisores digitais geram ruídos de comutação os quais são lidos durante os intervalos de apagamento pelo monitor, ai então resultam em deslocamentos de quadro conforme vc observou.

 

A solução para o meu problema foi colocar pequenos indutores 100 uH a 1000uH nos pinos de entrada de VCC dos circuitos digitais.

 

abços

 

 

Comentário de Nelson Ion de Oliveira em 21 março 2012 às 20:19

Fantástico e parabéns.

já tenho aplicações em mente com esse seu trabalho.

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço