AVR-es VGA video adapter.

Processing/Wiring (illetve C) nyelvű programozási fogások, tippek. (AVR-Duino, Arduino, EthDuino, Diecimila, Severino, Nano, LilyPad)
Válasz küldése
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

AVR-es VGA video adapter.

Hozzászólás Szerző: kapu48 »

Most kellene kis segítség az alábbi C programban! Amit „WinAVR (GCC)” re írtak!
Az eredeti forrás itt található: VGA video adapter
http://www.serasidis.gr/circuits/AVR_VGA/avr_vga.htm
Maga a HW. roppat 1*ű! Csak a programot nem tudom lefordítani!
Van benne 1 Szerintem a Videó memória tömbje, amit nem talál meg a fordító!
Mi lehet ez a 562. sorban : SPDR = PRG_RDB(_ptr1 + (* _ptr++)*vga_symbol_height/2);
Hibajelzés: Nincsen definiálva „PRG_RDB”????

Kód: Egész kijelölése

//Simplest universal VGA(20x20)/PAL(38x20) terminal
//For sync used Timer0 Timer1
//To avoid flickering while receive UART data,
//recommend to send UART data after VSYNC during
//10-20 VGA lines timing (around 300-600 mks)..

#include <avr/io.h>
#include <avr/signal.h>
#include <avr/sleep.h>
#include <avr/pgmspace.h>
#include <string.h>
#include "symbol_tbl.h"

#define true 1
#define false 0
#define NOP asm("nop")

//Global definitions for VGA render
#define vga_field_line_count 525 //standart VGA quantity lines
#define vga_symbols_per_row 20   //symbols quantity per horizontal
#define vga_row_count 20         //symbols quantity per vertical
#define vga_symbol_height 24	 //rendered symbol height

//Global defenitions for render PAL
#define pal_field_line_count 312 //standart PAL/SECAM quantity lines (interlaced 625~312*2)
#define pal_symbol_height 12	 //rendered symbol height
#define pal_symbols_per_row 38   //symbols quantity per horizontal
#define pal_row_count 20         //symbols quantity per vertical

#define sbi(port, bit) (port) |= (1 << (bit))
#define cbi(port, bit) (port) &= ~(1 << (bit))
#define PRG_RDB pgm_read_byte

//Makro for video handle
//Video
#define video_off  DDRB=0x90
#define video_on  DDRB=0xB0
//HSYNC
#define hsync_off  sbi(PORTD,3)
#define hsync_on  cbi(PORTD,3)
//VSYNC
#define vsync_off  PORTD=0x04
#define vsync_on   PORTD=0x00

#define check_PAL_jumper bit_is_clear(PINC,1)

//Global variables
volatile unsigned char str_array[pal_symbols_per_row*pal_row_count+1]; //Chars array for display buffer
volatile unsigned int current_symbol; //Current symbol number at terminal

volatile unsigned char video_enable_flg;//flag for enable render
volatile unsigned char raw_render;//Current row at display buffer for render
volatile unsigned int linecount;// current line for render
volatile unsigned char y_line_render;	//Current Y-line at symbol for render 

//Store strings data at Program Space, to avoid RAM leakage
const char str1[] PROGMEM =   "Simple PAL terminal v1.2 UART-19200bps";
const char str2[] PROGMEM =   "Simple VGA terminal";
const char str3[] PROGMEM =   "v1.2 UART-19200 bps";

static void avr_init(void);

//All VGA sincronize made here..
SIGNAL(SIG_OVERFLOW0)
{
 TCNT0 = 0xC3; //reload counter value
		//******Syncronization Handler********

			//Count number of lines
			if (++linecount == vga_field_line_count)
			{
			linecount = 0;
			
			//clear pointers for render display buffer
			raw_render = 0; 
			y_line_render = 0;
			}

			//Make Vsync length 2 VGA lines 
			if ((linecount == 10 )||(linecount == 11 ))
			{
				//Make here vertical syncronization & HSYNC syncro level on
				vsync_on;
			}
			else
			{
				//.. & HSYNC syncro level on
				vsync_off;
			}
		
		
			video_enable_flg = true;


			if (linecount < 45)
			{
				video_enable_flg = false;
					//Add to avoid flickering at top display
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					
			}
			else
			{
				 //Forming current string for rendering
				 if (++y_line_render == vga_symbol_height)
				 {
				  raw_render++;
				  y_line_render = 0;
				 }
				 else
				 {
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
				 }
		
			}
		
			hsync_off; //HSYNC syncro level off
		
		//******Syncronization Handler********

}

//All PAL sincronize made here..
SIGNAL(SIG_OUTPUT_COMPARE1A)
{
			
	//Count number of lines
	
	if (++linecount == pal_field_line_count)
	{
		linecount = 0;
		//clear pointers for render display buffer
		raw_render = 0; 
		y_line_render = 0;
	}
	
	//Invert HSYNC for VSYNC
	
	if (linecount > 305 && linecount < 309)
	{
		//Make here vertical syncronization
		
		sbi(PORTC,0); //inverted syncro level on
		char i = 15;
		while (--i)
		{ NOP;}
		//And "black" = 8 mksk;
		cbi(PORTC,0); //inverted syncro level off
	    }
	else
	{
		//Make HSYHC = 4 mksk;
		cbi(PORTC,0); //syncro level on
		char i = 30;
		while (--i)
		{ NOP;}

		//And "black" = 8 mksk;
		sbi(PORTC,0); //syncro level off
	}
			video_enable_flg = true;
			if ((linecount < 40) || (linecount > 278))
			{
				video_enable_flg = false;
					
					//Add to avoid flickering at top display
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
			}
			else
			{
				 //Forming current string for rendering
				 if (++y_line_render == pal_symbol_height)
				 {
				  raw_render++;
				  y_line_render = 0;
				 }
				 else
				 {
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
					NOP;
				 }
		
			}

}

void spi_init (void)
{
    //Set SPI PORT DDR bits
	sbi(DDRB, 7); //SCK
	cbi(DDRB, 6); //MISO
	sbi(DDRB, 5); //MOSI
	sbi(DDRB, 4); //SS
	SPSR = 1 << SPI2X;
	SPCR = (1 << SPE) | (1 << MSTR); //SPI enable as master ,FREQ = fclk/2
	//That's a great pity, that we can't work with SPI with FREQ = fclk,
	//because may be possible build terminal up 40 symbol per row!!!
}

static void uart_init(void)
{
	 UCSRB = 0x00; //disable while setting baud rate
	 UCSRA = 0x00;
	 UCSRC = 0x86;	//8 bits data & 2 stop bits
	//UART SPEED 19200 bs
	UBRRL = 0x33; //set baud rate lo
	UBRRH = 0x00; //set baud rate hi
	//UART SPEED 38400 bs
	//UBRRL = 0x19; //set baud rate lo
	//UBRRH = 0x00; //set baud rate hi
	//UART SPEED 76800 bs
	//UBRRL = 0x0C; //set baud rate lo
	//UBRRH = 0x00; //set baud rate hi
	//UART SPEED 115200 bs
	//UBRRL = 0x08; //set baud rate lo
	//UBRRH = 0x00; //set baud rate hi
	//UART RX Enable
	UCSRB = (1 << RXEN);
}


static void pal_terminal_handle(void)
{
	// Parser received symbols from UART
	while(UCSRA & (1<<RXC))
	{
		unsigned char current_line, received_symbol;
		received_symbol = UDR;
		//Check for overflow display buffer
		if(current_symbol == (pal_row_count*pal_symbols_per_row))
		{
			
			//Clear display buffer

			unsigned char i = pal_row_count;
			char * ptr;
			//Set pointers for clear string array
			ptr = &str_array[0];
			while(i--)
			{
				//Don't use here loop, to fastest clear display buffer
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
			};
			current_symbol = 0x0;
		}
					switch ( received_symbol )
					{
					  //BackSpace
					  case  0x08: 
					  if(current_symbol)
					    {
							str_array[current_symbol] = 0x0;
							str_array[--current_symbol] = 0x0;
						}
					  break;
					  
					  //TAB
					  case  0x09: 
					  if((current_symbol + 5) < (pal_row_count*pal_symbols_per_row))
					    {
							//Add 5 Space
							str_array[current_symbol] = 0x0;
							current_symbol += 5;
						}
					  break;

					  //RETURN
					  case  0x0D: 
					  current_line = current_symbol / pal_symbols_per_row;
					  if((current_line) < 19)
					    {
							str_array[current_symbol] = 0x0;
							current_symbol = current_line*pal_symbols_per_row + pal_symbols_per_row;
						}
					  break;
					  default: str_array[current_symbol++] = received_symbol;
					}
	}
}

void pal_render(void)
{
	unsigned char i;
	char * _ptr;
	const char * _ptr1;
	//Initialize display buffer with StartUp strings
	strcpy_P(&str_array[pal_symbols_per_row*(pal_row_count-1)],&str1[0]); 	
	
	//Enable global interrupt
	asm ("sei");

	for(;;)
    {

		//Wait compare interrupt signal from Timer1
		sleep_mode();
		
		//Check symbol on UART
		if (UCSRA & (1<<RXC))
		{
			//Parse received symbol
			pal_terminal_handle();
			//Can easealy add here RX polling buffer
			//to avoid display flickering
			continue;
		}
		//To make horizontal shift rendered image
		i=14;
		while(i--) NOP;
		//Check visible field
		if(video_enable_flg)
		{
		//OK, visible
		//Main render routine
				//Set pointer for render line (display bufffer)
				_ptr = &str_array[raw_render * pal_symbols_per_row];

				//Set pointer for render line (character generator)
				_ptr1 = &symbol[0][y_line_render];
	
				//Cycle for render line (Ciklus render vonal)
				i = pal_symbols_per_row;
				video_on;
				while(i--)
				{
					SPDR = PRG_RDB(_ptr1 + (* _ptr++)*vga_symbol_height);
					//That's a great pity can't shift data faster (8Mhz at FOSC=16Mhz)!!
					//Ez egy nagy kár nem shift adatok gyorsabban (8MHz a FOSC = 16MHz)!
					NOP;
					NOP;
					NOP;
				}
				//Delay for draw last symbol
				i=6;
				while(i--) NOP;
				
				video_off;

		}
		else
		{
		//Not visible
		//Can do something else..	
					//******Cursor handle
					//Count frame
					static unsigned int framecount;
					framecount++;
					//Here draw cursor
						if (framecount&0x800)
						{
							str_array[current_symbol] = ' ';
						}
						else
						{
							str_array[current_symbol] = 0x7F;
						}
					//******Cursor handle
		//You can add here your own handlers..			
		}
		
    }//for(;;)

}

static void vga_terminal_handle(void)
{
	// Parser received symbols from UART
	while(UCSRA & (1<<RXC))
	{
		unsigned char current_line, received_symbol;
		received_symbol = UDR;
		//Check for overflow display buffer
		if(current_symbol == (vga_row_count*vga_symbols_per_row))
		{
			
			//Clear display buffer

			unsigned char i = vga_row_count;
			char * ptr;
			//Set pointers for clear string array
			ptr = &str_array[0];
			while(i--)
			{
				//Don't use here loop, to fastest clear display buffer
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
				*ptr++ = 0x0;
			};
			current_symbol = 0x0;
		}
					switch ( received_symbol )
					{
					  //BackSpace
					  case  0x08: 
					  if(current_symbol)
					    {
							str_array[current_symbol] = 0x0;
							str_array[--current_symbol] = 0x0;
						}
					  break;
					  
					  //TAB
					  case  0x09: 
					  if((current_symbol + 5) < (vga_row_count*vga_symbols_per_row))
					    {
							//Add 5 Space
							str_array[current_symbol] = 0x0;
							current_symbol += 5;
						}
					  break;

					  //RETURN
					  case  0x0D: 
					  current_line = current_symbol / vga_symbols_per_row;
					  if((current_line) < 19)
					    {
							str_array[current_symbol] = 0x0;
							current_symbol = current_line*vga_symbols_per_row + vga_symbols_per_row;
						}
					  break;
					  default: str_array[current_symbol++] = received_symbol;
					}
	}
}

void vga_render()
{
	unsigned char i;
	char * _ptr;
	const char * _ptr1;

	//Initialize display buffer with StartUp strings
	//Inicializálása kijelző puffer StartUp húrok
	strcpy_P(&str_array[vga_symbols_per_row*(vga_row_count-2)],&str2[0]); 	
	strcpy_P(&str_array[vga_symbols_per_row*(vga_row_count-1)],&str3[0]); 	

	//Enable global interrupt
	asm ("sei");

	for(;;)
    {

		//Wait compare interrupt signal from Timer1
		sleep_mode();
		
		//Check symbol on UART
		if (UCSRA & (1<<RXC))
		{
			//Parse received symbol
			vga_terminal_handle();
			continue;
		}
		
		//Check visible field  Ellenőrizze a látható mező
		if(video_enable_flg)
		{
		//OK, visible
		//Main render routine
				//Set pointer for render line (display bufffer)
				//Állítsa be a mutatót teszik vonal (kijelző bufffer)
				_ptr = &str_array[raw_render * vga_symbols_per_row];

				//Set pointer for render line (character generator)
				_ptr1 = &symbol[0][y_line_render >> 1];
	
				//Cycle for render line 
				i = vga_symbols_per_row;
				while(i--)
				{
				    SPDR = PRG_RDB(_ptr1 + (* _ptr++)*vga_symbol_height/2);
				    video_on;
					//That's a great pity can't shift data faster (8Mhz at FOSC=16Mhz)!!
					//Ez egy nagy kár nem shift adatok gyorsabban (8MHz a FOSC = 16MHz)!
					NOP;
					NOP;
				}
				//Delay for draw last symbol
				NOP;
				NOP;
				NOP;
				NOP;
				NOP;
				NOP;
				video_off;

		}
		else
		{
		//Not visible
		//Can do something else..	
					//******Cursor handle
					//Count frame
					static unsigned int framecount;
					framecount++;
					//Here draw cursor
						if (framecount&0x800)
						{
							str_array[current_symbol] = ' ';
						}
						else
						{
							str_array[current_symbol] = 0x7F;
						}
					//******Cursor handle
		//You can add here your own handlers..			
		}
		
    }//for(;;)
}

int main(void)
{
    avr_init();
	  //Check pin VGA/PAL
	if(check_PAL_jumper)
	pal_render();
	else
	vga_render();
	
    return(0);
}



static void avr_init(void)
{

  //Set pin jumper VGA/PAL
  cbi(DDRC,1);
  sbi(PORTC,1);
  
  //Enable SPI
  spi_init();

  //init uart
  uart_init();

  //Set power mode
  set_sleep_mode(SLEEP_MODE_IDLE); 	

  //Check pin mode VGA/PAL
  if(check_PAL_jumper)
  {
	  //init PAL SYNC port
	  sbi(DDRC,0);
	  //C.0 is sync:1000 ohm + diode to 75 ohm resistor
	  //MOSI is video:330 ohm + diode to 75 ohm resistor
	  
	  // Initialize Sync for PAL
	  OCR1A = 1024; 			 //One PAL line 64us
	  TCCR1B = (1<<WGM12)|(1<<CS10);//full speed; clear-on-match
	  TCCR1A = 0x00;			//turn off pwm and oc lines
	  TIMSK = 1<<OCIE1A;		//enable interrupt from Timer1 CompareA
  }	
  else
  {
	  //init VGA SYNC ports
	  //HSYNC
	  sbi(PORTD,3);
	  sbi(DDRD,3);
	  //VSYNC
	  sbi(PORTD,2);
	  sbi(DDRD,2);
	
	  // Initialize Sync for VGA
	 TCCR0 = 0x00; //stop
	 TCNT0 = 0xC3; //set count, One VGA line 31.77us
	 TCCR0 = 1<<CS01; //start timer with prescaler select 1/8
	 TIMSK = 1<<TOV0; //enable interrupt from Timer0 overflow
  }

  return;
}
 
Kicsit hosszú a program, de csak így 1ben érthető!
Ui.: A hiba kijavítva! Most már fordítható.
Következik a tesztelés!
A hozzászólást 1 alkalommal szerkesztették, utoljára kapu48 2011. november 23. szerda, 8:51-kor.
Avatar
Gerifield
DrótVégénSzéndarab
Hozzászólások: 27
Csatlakozott: 2011. szeptember 19. hétfő, 6:00

Hozzászólás Szerző: Gerifield »

A probléma az, ahogy írja is, hogy nem találja a PRG_RDB függvény definícióját.

Ha minden igaz már nincs benne az az újabb avr-gcc-kben, de elvileg könnyen megoldható a dolog.
http://www.avrfreaks.net/index.php?name ... 62&start=0

Tömören: Dobd bele a file elejébe a defekhez ezt is:

Kód: Egész kijelölése

#define PRG_RDB pgm_read_byte
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Hozzászólás Szerző: kapu48 »

Köszi a segítséget! Így már összejött a fordítás!
Most már érdemes lesz, megépítem a HW részt is. Kísérletezéshez, hogy mire is lenne használható?
Valami bontót laptop kijelzővel olcsón helyettesíteni lehetne a drága grafikus LCD-t.

Javítottam is a bemásolt programot!
:D
Válasz küldése