Fala galera!
Pela foto acima dá para perceber que o problema com a área vazia foi resolvido, agora toda a
área da tela é preenchida. Então a gente pode desenhar em qualquer canto (640 x 480 @ 60Hz).
O problema era a função de interrução, os tempos de chamada e retorno eram altos demais no
ATmega328 para o monitor, então substituí a função por um "if", checando o o valor no registrador
do timer o tempo todo. Quando o timer chega a um determinado valor (31.3KHz), a condição do
"if" é verdadeira e a linha é impressa. Assim o programa não desperdiça tempo chamando e
retornando da função de interrupção.
área da tela é preenchida. Então a gente pode desenhar em qualquer canto (640 x 480 @ 60Hz).
O problema era a função de interrução, os tempos de chamada e retorno eram altos demais no
ATmega328 para o monitor, então substituí a função por um "if", checando o o valor no registrador
do timer o tempo todo. Quando o timer chega a um determinado valor (31.3KHz), a condição do
"if" é verdadeira e a linha é impressa. Assim o programa não desperdiça tempo chamando e
retornando da função de interrupção.
Outro problema era que apenas monitores CRT entendiam o sinal. Esse problema foi resolvido
ajustando o nível de tensão dos pinos RGB para o padrão de 0,7V, usando um resistor em
série com um diodo, reduzindo de TTL (5V) para 0,7V, conforme imagem acima. Assim,
todos os monitores estão entendendo o sinal (incluindo LCD e LED).
ajustando o nível de tensão dos pinos RGB para o padrão de 0,7V, usando um resistor em
série com um diodo, reduzindo de TTL (5V) para 0,7V, conforme imagem acima. Assim,
todos os monitores estão entendendo o sinal (incluindo LCD e LED).
Com tudo resolvido, nós podemos gerar sinal VGA COLORIDO!!!
Agora vou tentar criar uma biblioteca inteligente o suficiente para desenhar figuras e letras,
e talvez gerar mais cores.
e talvez gerar mais cores.
Tudo usando apenas um Arduino UNO. :))
Aqui está o código que escrevi. Aproveitem! Estamos aqui para compartilhar.
Se você vai tentar usar esse código, é bom saber também:
E isso também:
Clique na imagem para ampliar
"VGA industry standard" 640x480 pixel mode
General characteristics
Clock frequency 25.175 MHz
Line frequency 31469 Hz
Field frequency 59.94 Hz
Line frequency 31469 Hz
Field frequency 59.94 Hz
One line
8 pixels front porch
96 pixels horizontal sync
40 pixels back porch
8 pixels left border
640 pixels video
8 pixels right border
---
800 pixels total per line
96 pixels horizontal sync
40 pixels back porch
8 pixels left border
640 pixels video
8 pixels right border
---
800 pixels total per line
One field
2 lines front porch
2 lines vertical sync
25 lines back porch
8 lines top border
480 lines video
8 lines bottom border
---
525 lines total per field
2 lines vertical sync
25 lines back porch
8 lines top border
480 lines video
8 lines bottom border
---
525 lines total per field
Atente-se em desligar seu sinal RGB sempre que for pulsar um de sincronia.
E fique esperto com o que o compilador faz. Muito tempo é desperdiçado em muitas situações, e os tempos não repetitivos são os mais perigosos.
Se o seu sinal não estiver em perfeita sincronia, o monitor vai rejeitar.
Use o osciloscópio para monitorar tudo!
Boa sorte e conte comigo se precisar de ajuda!
Abraço!!!
Atualização 05 novembro de 2014:
Atendendo a pedido, segue abaixo o código para gerar a imagem acima (precisa revisar,
faz tempo que fiz). A matriz logoldg[25][40] é a representação da imagem pixel a pixel.
Ela é obtida através do script em Python abaixo que lê a imagem BMP e transforma
cada pixel nos valores para carregamento no registrador para gerar os bits RGB. A
imagem tem 40x25 pixels e pode ser feita em qualquer software gráfico.
faz tempo que fiz). A matriz logoldg[25][40] é a representação da imagem pixel a pixel.
Ela é obtida através do script em Python abaixo que lê a imagem BMP e transforma
cada pixel nos valores para carregamento no registrador para gerar os bits RGB. A
imagem tem 40x25 pixels e pode ser feita em qualquer software gráfico.
Imagem original BMP (a ser apresentada na tela):
Ela é pequena porque é o máximo que o ATmega328 consegue armazenar na flash.
#include
#define NOP asm("nop")
#define PRETO PORTB = B00000000; //0
#define AZUL PORTB = B00000001; //1
#define VERDE PORTB = B00000010; //2
#define CIANO PORTB = B00000011; //3
#define VERMELHO PORTB = B00000100; //4
#define MAGENTA PORTB = B00000101; //5
#define AMARELO PORTB = B00000110; //6
#define BRANCO PORTB = B00000111; //7
#define PRETO PORTB = B00000000; //0
#define AZUL PORTB = B00000001; //1
#define VERDE PORTB = B00000010; //2
#define CIANO PORTB = B00000011; //3
#define VERMELHO PORTB = B00000100; //4
#define MAGENTA PORTB = B00000101; //5
#define AMARELO PORTB = B00000110; //6
#define BRANCO PORTB = B00000111; //7
unsigned int contalinhas = 1;
void setup()
{
//Seta pinos 5, 6 e 7 como saidas
// 7 - HSYNC
// 6 - VSYNC
// 5 - RGB
DDRD |= B11100000;
DDRB |= B11100111;
PORTD |= B11000000;
{
//Seta pinos 5, 6 e 7 como saidas
// 7 - HSYNC
// 6 - VSYNC
// 5 - RGB
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 = 0x03; // seta contador para comaracao
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 = 0x03; // seta contador para comaracao
TIMSK2 &= ~(1OCIE2A); // seta interrupcao por comparacao
TIMSK2 |= (1TOIE2); // seta interrupcao por overflow
}
TIMSK2 |= (1TOIE2); // seta interrupcao por overflow
}
void loop()
{
PROGMEM byte logoldg[25][40] = { //A matriz da imagem contendo elementos hexadecimais no formato correto para o LCD
6,6,6,6,6,6,6,6,6,0,0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,0,4,4,4,4,4,0,0,6,6,6,0,0,4,4,4,4,4,0,0,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,0,4,4,4,4,4,4,0,0,0,0,0,4,4,4,4,4,4,4,0,0,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,4,4,4,4,4,4,4,7,4,4,4,4,4,0,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,4,4,4,4,4,4,4,7,4,4,4,4,4,4,0,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,4,4,4,4,4,4,4,7,4,4,4,4,4,4,0,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,7,7,7,7,7,4,4,7,7,7,7,4,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,4,4,4,4,7,7,4,7,4,4,7,7,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,4,7,7,7,7,7,4,7,4,4,7,7,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,7,7,4,4,7,7,4,7,4,4,7,7,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,7,7,4,7,7,4,4,7,7,4,7,7,7,7,7,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,7,7,4,4,7,7,7,7,4,4,7,7,7,7,4,4,4,0,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,0,4,4,4,4,4,0,0,4,4,4,4,4,4,4,0,0,0,0,0,4,4,4,0,6,6,6,6,6,6,6,
1,1,1,1,1,1,1,1,0,4,4,4,4,4,4,0,0,4,4,4,4,4,4,4,0,0,0,0,0,4,4,4,0,1,1,1,1,1,1,1,
1,1,1,1,1,2,2,2,0,4,4,4,0,0,0,0,0,4,4,4,4,4,4,4,0,4,4,4,4,4,4,4,0,2,2,1,1,1,1,1,
1,1,1,1,2,2,2,2,0,4,4,4,0,0,0,0,0,4,0,0,0,0,4,4,0,4,4,4,4,4,4,4,0,2,2,2,2,1,1,1,
1,1,2,2,2,2,2,2,0,4,4,4,0,4,4,0,0,4,0,4,4,0,0,4,0,4,0,0,0,4,4,4,0,2,2,2,2,1,1,1,
1,1,2,2,2,2,2,2,0,4,4,4,0,4,4,0,0,4,0,0,0,0,0,4,0,4,4,4,0,4,4,4,0,2,2,2,2,2,1,1,
1,1,2,2,2,2,2,2,0,4,4,4,0,4,4,0,0,4,0,4,4,4,4,4,0,0,0,0,0,4,4,4,0,2,2,2,2,2,1,1,
1,1,2,2,2,2,2,2,0,4,4,4,0,0,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,4,4,4,0,2,2,2,2,2,1,1,
1,1,1,2,2,2,2,2,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,2,2,2,2,1,1,1,
1,1,1,1,1,2,2,2,2,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,2,2,2,2,1,1,1,1,
1,1,1,1,1,1,1,2,2,2,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,2,2,2,2,1,1,1,1,1,
1,1,1,1,1,1,1,1,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,1,1,1,1,1,1,1,
//1,1,1,1,1,1,1,1,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,1,1,1,1,1,1,1,
{
PROGMEM byte logoldg[25][40] = { //A matriz da imagem contendo elementos hexadecimais no formato correto para o LCD
6,6,6,6,6,6,6,6,6,0,0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,0,4,4,4,4,4,0,0,6,6,6,0,0,4,4,4,4,4,0,0,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,0,4,4,4,4,4,4,0,0,0,0,0,4,4,4,4,4,4,4,0,0,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,4,4,4,4,4,4,4,7,4,4,4,4,4,0,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,4,4,4,4,4,4,4,7,4,4,4,4,4,4,0,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,4,4,4,4,4,4,4,7,4,4,4,4,4,4,0,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,7,7,7,7,7,4,4,7,7,7,7,4,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,4,4,4,4,7,7,4,7,4,4,7,7,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,4,7,7,7,7,7,4,7,4,4,7,7,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,4,4,4,7,7,4,4,7,7,4,7,4,4,7,7,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,7,7,4,7,7,4,4,7,7,4,7,7,7,7,7,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,7,7,7,7,4,4,7,7,7,7,4,4,7,7,7,7,4,4,4,0,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,0,4,4,4,4,4,0,0,4,4,4,4,4,4,4,0,0,0,0,0,4,4,4,0,6,6,6,6,6,6,6,
1,1,1,1,1,1,1,1,0,4,4,4,4,4,4,0,0,4,4,4,4,4,4,4,0,0,0,0,0,4,4,4,0,1,1,1,1,1,1,1,
1,1,1,1,1,2,2,2,0,4,4,4,0,0,0,0,0,4,4,4,4,4,4,4,0,4,4,4,4,4,4,4,0,2,2,1,1,1,1,1,
1,1,1,1,2,2,2,2,0,4,4,4,0,0,0,0,0,4,0,0,0,0,4,4,0,4,4,4,4,4,4,4,0,2,2,2,2,1,1,1,
1,1,2,2,2,2,2,2,0,4,4,4,0,4,4,0,0,4,0,4,4,0,0,4,0,4,0,0,0,4,4,4,0,2,2,2,2,1,1,1,
1,1,2,2,2,2,2,2,0,4,4,4,0,4,4,0,0,4,0,0,0,0,0,4,0,4,4,4,0,4,4,4,0,2,2,2,2,2,1,1,
1,1,2,2,2,2,2,2,0,4,4,4,0,4,4,0,0,4,0,4,4,4,4,4,0,0,0,0,0,4,4,4,0,2,2,2,2,2,1,1,
1,1,2,2,2,2,2,2,0,4,4,4,0,0,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,4,4,4,0,2,2,2,2,2,1,1,
1,1,1,2,2,2,2,2,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,2,2,2,2,1,1,1,
1,1,1,1,1,2,2,2,2,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,2,2,2,2,1,1,1,1,
1,1,1,1,1,1,1,2,2,2,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,2,2,2,2,1,1,1,1,1,
1,1,1,1,1,1,1,1,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,1,1,1,1,1,1,1,
//1,1,1,1,1,1,1,1,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,1,1,1,1,1,1,1,
};
noInterrupts();
do{
PRETO;
if (TCNT2 > 0x0f){
noInterrupts();
do{
PRETO;
if (TCNT2 > 0x0f){
delayMicroseconds(1);
NOP;NOP;NOP;NOP;
TCNT2 = 0x00;
NOP;NOP;NOP;NOP;
TCNT2 = 0x00;
//pequeno ajuste de tempo, pode ser necessario ou nao dependendo da placa
// #### HSYNC ###
PORTD &= ~(1 7);
if (++contalinhas >= 525){ //525 linhas
contalinhas = 1;
}
PORTD |= (1 7);
// ### VSYNC ###
if ((contalinhas == 1)||(contalinhas == 2)){ //492 e 493
PORTD &= ~(1 6);
} else {
PORTD |= (1 6);
if ((contalinhas == 1)||(contalinhas == 2)){ //492 e 493
PORTD &= ~(1 6);
} else {
PORTD |= (1 6);
//NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;
//NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;
//NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;
//NOP;NOP;NOP;NOP;NOP;
int linhamatriz = 0;
linhamatriz = contalinhas / 16 - 1;
int j=0;
if ((contalinhas >= 16) && (contalinhas <= 415)){ // 2 e 482
//NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;
//NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;
//NOP;NOP;NOP;NOP;NOP;
int linhamatriz = 0;
linhamatriz = contalinhas / 16 - 1;
int j=0;
if ((contalinhas >= 16) && (contalinhas <= 415)){ // 2 e 482
PRETO;
//delayMicroseconds(1);NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP; //delay ate 25
//unsigned int i=contalinhas/9;
int j=0;
while(j<40 br="">PORTB = logoldg[linhamatriz][j];
j++;
}
NOP;NOP;
PRETO;
NOP;NOP;NOP;NOP;40>
//delayMicroseconds(1);NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP; //delay ate 25
//unsigned int i=contalinhas/9;
int j=0;
while(j<40 br="">PORTB = logoldg[linhamatriz][j];
j++;
}
NOP;NOP;
PRETO;
NOP;NOP;NOP;NOP;40>
}
}
}
}while(1);
}
Script em Python para gerar a matriz:
print "labdegaragem.com"
import Image
import ImageColor
image='paisagem.bmp' #Coloque aqui o nome do arquivo que deseja converter
texto='paisagem.txt' #Crie um arquivo texto em branco em um diretorio a sua escolha e coloque aqui o nome do arquivo texto para guardar a matriz da imagem em hexadecimal
f=open(texto,'w') #Ira abrir o arquivo texto
imopen=Image.open(image) #Abrira a imagem
x=y=0
h=0
while y<25: 40x25="" a="" altura="" aqui="" br="" da="" imagem.="" imagem="" maxima="" oloque="" pixels="" tem="">#print y
x=0
while x<40: aqui="" br="" coloque="" comprimento="" da="" imagem.="" o="">#print x
z=imopen.getpixel((x,y))
h=0
if z[0] > 200:
h = h+4
if z[1] > 200:
h = h+2
if z[2] > 200:
h = h+1
#print z[0],"-",z[1],"-",z[2],"=",h
f.write(str(h))
f.write(',')
x=x+1
y=y+1
f.write('\n')
f.close()40:>25:>
import Image
import ImageColor
image='paisagem.bmp' #Coloque aqui o nome do arquivo que deseja converter
texto='paisagem.txt' #Crie um arquivo texto em branco em um diretorio a sua escolha e coloque aqui o nome do arquivo texto para guardar a matriz da imagem em hexadecimal
f=open(texto,'w') #Ira abrir o arquivo texto
imopen=Image.open(image) #Abrira a imagem
x=y=0
h=0
while y<25: 40x25="" a="" altura="" aqui="" br="" da="" imagem.="" imagem="" maxima="" oloque="" pixels="" tem="">#print y
x=0
while x<40: aqui="" br="" coloque="" comprimento="" da="" imagem.="" o="">#print x
z=imopen.getpixel((x,y))
h=0
if z[0] > 200:
h = h+4
if z[1] > 200:
h = h+2
if z[2] > 200:
h = h+1
#print z[0],"-",z[1],"-",z[2],"=",h
f.write(str(h))
f.write(',')
x=x+1
y=y+1
f.write('\n')
f.close()40:>25:>
No comments:
Post a Comment