First Trial of a C - Interface to the VGA 64 Driver from OBEX

Hi,
Try to built a C interface to the VGA64 driver from OBEX
( the origin author will forgive me ;-)
Basicly works and my first goal was a closer understand of the mailbox interface to pasm code.
Reinhard
Try to built a C interface to the VGA64 driver from OBEX
( the origin author will forgive me ;-)
Basicly works and my first goal was a closer understand of the mailbox interface to pasm code.
/**
Trial of a C - Interface to the VGA 64 Driver from OBEX
VGA64 6 Bits Per Pixel Engine
ORIGIN:
Author: Kwabena W. Agyeman
Updated: 11/17/2010
Designed For: P8X32A
Version: 1.0
Copyright (c) 2010 Kwabena W. Agyeman
--------------------------------------------------
Code from PUB PIXEngineStart(pinGroup)
is go to main
very experimental, basicly works
*/
#include <stdlib.h>
#include <propeller.h>
////////////////////////////////////////////////////////////////////////
// Mailbox
////////////////////////////////////////////////////////////////////////
static unsigned int directionState;
static unsigned int videoState;
static unsigned int frequencyState;
static unsigned int * displayPtr;
static unsigned int *syncIndicatorAdress;
static unsigned int *displayIndicatorAdress;
////////////////////////////////////////////////////////////////////////
unsigned int DISPLAY_BUFFER[(160 * 120) / 4];
unsigned int sync_indi;
unsigned int display_indi;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
unsigned int _rotl( unsigned int value, int shift)
{
if ((shift &= sizeof(value)*8 - 1) == 0)
return value;
return (value << shift) | (value >> (sizeof(value)*8 - shift));
}
////////////////////////////////////////////////////////////////////////
int start(unsigned int *ptr)
{
extern unsigned int binary_vga64_pix_dat_start[];
return cognew(&binary_vga64_pix_dat_start, ptr);
}
////////////////////////////////////////////////////////////////////////
void usleep(int t)
{
if(t < 10) // very small t values will cause a hang
return; // don't bother function delay is likely enough
waitcnt((CLKFREQ/1000000)*t+CNT);
}
////////////////////////////////////////////////////////////////////////
void main (void)
{
int tmp,i,x,y;
// Preset the mailbox parameters
directionState = 0xFF << 16;
videoState = (0x300000FF | (2 << 9));
tmp = (25175000 + 1600) / 4;
frequencyState = 1 ;
for(i = 0; i < 32; i++)
{
tmp = tmp << 1;
frequencyState = _rotl(frequencyState,1);
if(tmp >= _clkfreq)
{
tmp = tmp - _clkfreq;
frequencyState += 1;
}
}
displayPtr = DISPLAY_BUFFER;
syncIndicatorAdress = &sync_indi;
displayIndicatorAdress = &display_indi;
// start the Driver
start(&directionState);
while(1)
{
for (y = 0; y < 120;y++)
{
for (x = 0; x < 160;x++)
{
while((0x80 >> 5) & sync_indi);
//DISPLAY_BUFFER[x + 160 * y] = 0xFF; // set a white pixel at (x,y)
*(unsigned char *)(DISPLAY_BUFFER + x + 160 * y) = 0x30; // Lightgreen
}
}
}
}
////////////////////////////////////////////////////////////////////////
Reinhard
Comments
there is a bug in my program near the DISPLAY_BUFFER size
seems a problem with int/byte access.
work on it, sorry
Reinhard
if ((shift &= sizeof(value)*8 - 1) == 0)
be:if ((shift &= sizeof(value)*4 - 1) == 0)
As value is an int which is 32 bits which is 4 bytes.If I come to the rotl operator I searched for builtins, but do not found.
So I get the rotl function with a short web search and take it as it is, without censorious check.
Heater, what you write make sense, I changed it.
On the screen I see the green stripes, with black spaces between.
My expectation is a full green screen.
I guess the problem is my write into the DISPLAY_BUFFER is different to the spin code:
displayBuffer.byte[.....] I think only 1/4 from Buffer is used by my C program ?!
Try tomorrow a solution.
Reinhard
found " Nyamekye " also in the origin VGA - sourcecode
hi Kye, nice to meet you
feel a little bit like this ...
http://german.about.com/library/blgzauberl.htm
Reinhard
if I replace the line:
DISPLAY_BUFFER[x + 160 * y] = 0x30; with DISPLAY_BUFFER[x + 160 * y] = 0x30303030;
the screen is filled full green,
because the pasm read a long ( I mean this is a int32 in C )
and if I write only 8 Bit into Buffer, the remaining 24 Bits are unused.
So with a little workaround in the interface, the proper setting can done.
Reinhard
Oddly enough there isn't; but the compiler is smart enough to compile
a = (a << b) | (a >> (32-b))
into a single rotl instruction.Eric
Was a long way, but now I have what I want.
A simple Graphic Interface , like at the good old TurboC Times.
/** VGA Graphic Demo with Parallax VGA_512x384_Bitmap Interface for DemoBoard Wiring reimay / January 2012 */ #include <propeller.h> //////////////////////////////////////////////////////////////////////// // Mailbox //////////////////////////////////////////////////////////////////////// static unsigned int sync; static unsigned int reg_dira; static unsigned int reg_vcfg; static unsigned int * pixel_ptr; static unsigned short * color_ptr; //////////////////////////////////////////////////////////////////////// unsigned int PIXEL_BUFFER[6144]; unsigned short COLOR_BUFFER[192]; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// void plot( unsigned int x, unsigned int y) { int tmp = x % 32; if(x >= 0 && x < 512 && y >= 0 && y < 384) { PIXEL_BUFFER[(x/32) + (y*16)] |= 1<<tmp; } } //////////////////////////////////////////////////////////////////////// int start(unsigned int *ptr) { extern unsigned int binary_vga_dat_start[]; return cognew(&binary_vga_dat_start, ptr); } //////////////////////////////////////////////////////////////////////// void main (void) { unsigned int z,i,x,y; // Preset the mailbox parameters sync = 0; reg_dira = 0x00FF0000; reg_vcfg = 0x200000FF + (16 << 6); // Fill Color Buffer for(i = 0; i < 192; i++) { COLOR_BUFFER[i] = 0x2804 ; } pixel_ptr = PIXEL_BUFFER; color_ptr = COLOR_BUFFER; // start the Driver start(&sync); /* Graphic Demo : plot the sierpinsky triangel with binary adresses */ for( y = 0; y <= 255; y++) for(x = 0;x <= y;x++) { z = x & ( y -x) ; if(z==0) plot(x+ (256-y/2),y+30); } } ////////////////////////////////////////////////////////////////////////
Reinhard
have now combined the sigma_delta driver with the vga driver, similar to the microphoneToVGA Demo in the spin example package from parallax.
Basicly works, but I have no idea how to clear the screen.
thanks for any suggestions
Reinhard
Hi Reinhard! Happy New Year.
Some drivers use double buffering. That is, divide a big buffer in half to make 2 screens, draw to each screen, and just change the pointer to display a new screen. The graphics demo does that.
Cheers.
--Steve
Oh, man. I did the exact same thing when I was learning 32-bit x86 assembly code when I was a teenager. I loaded a 32-bit register with a byte value and expected 32-bit memcpy()-style code to "just work" and got vertical stripes down the screen.
I get to study the graphic demos with double buffering !
@plainsteve: Hi, was also a learning process for me.
Interesting to see on neptun are the same pitfalls . . .
Reinhard