Arduino Forum

Products => Arduino Due => Topic started by: stimmer on Nov 05, 2012, 01:43 am

Title: VGA output
Post by: stimmer on Nov 05, 2012, 01:43 am
After working out how to do a timer interrupt I've had a go at making a VGA framebuffer. It is rather low-res at present(160x240) and fuzzy but I hope to be able to improve that. It has 8-bit colour (RRRGGGBB).

I cannot get Eagle to run right now so will have to describe the schematic in text:
Due pin 2 -> VGA pin 13 (HSync)
Due pin 3 -> VGA pin 14 (VSync)

Due pin 25 -> 820R resistor -> VGA pin 3 (blue)
Due pin 26 -> 390R resistor -> VGA pin 3 (blue)

Due pin 27 -> 2k2 resistor -> VGA pin 2 (green)
Due pin 28 -> 1k resistor -> VGA pin 2 (green)
Due pin 14 -> 470R resistor -> VGA pin 2 (green)

Due pin 15 -> 2k2 resistor -> VGA pin 1 (red)
Due pin 29 -> 1k resistor -> VGA pin 1 (red)
Due pin 11 -> 470R resistor -> VGA pin 1(red)

Due pin GND -> VGA pins 5,6,7,8,10

Code: [Select]
inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
byte fb[240][160];

void TC0_Handler()
{
    long dummy=REG_TC0_SR0;
                           
    if(line < 480){
        int i,j=line>>1;
        for(i=0;i<160;i++) REG_PIOD_ODSR = fb[j][i];
        REG_PIOD_ODSR = 0;
    }     
    if(line==490) digitalWriteDirect(3,1);
    if(line==492) digitalWriteDirect(3,0);
   
    line++; if(line == 525) line=0;
}

void setup(){
  for(int i=0;i<160;i++)for(int j=0;j<240;j++)fb[j][i]=j+i;
 
  pinMode(3,OUTPUT);  pinMode(2,OUTPUT);                      // vsync=3 hsync=2
  pinMode(25,OUTPUT); pinMode(26,OUTPUT);                     // blue  (26=msb,25=lsb)
  pinMode(27,OUTPUT); pinMode(28,OUTPUT); pinMode(14,OUTPUT); // green (14=msb,28,27=lsb)
  pinMode(15,OUTPUT); pinMode(29,OUTPUT); pinMode(11,OUTPUT); // red   (11=msb,29,15=lsb)

  REG_PIOD_OWER= 0xff;
  REG_PMC_PCER0= 1<<27; 
  REG_PIOB_PDR = 1<<25;
  REG_PIOB_ABSR= 1<<25;
  REG_TC0_WPMR = 0x54494D00;
  REG_TC0_CMR0 = 0b00000000000010011100010000000000;
  REG_TC0_RC0  = 1334;
  REG_TC0_RA0  = 1174; 
  REG_TC0_CCR0 = 0b101;   
  REG_TC0_IER0 = 0b00010000;
  REG_TC0_IDR0 = 0b11101111;
  NVIC_EnableIRQ(TC0_IRQn);
}

#include <complex>
using namespace std;

const byte cmap[]={0b00000000,0b11100000,0b11100100,0b11101000,0b11101100,0b11110000,0b11110100,0b11111000,0b11111100,
                   0b11011100,0b10111100,0b10011100,0b01111100,0b01011100,0b00111100,0b00011100,0b00011101,0b00011110,
                   0b00011111,0b00011011,0b00010111,0b00010011,0b00001111,0b00001011,0b00000111,0b00000011,0b00100011,
                   0b01000011,0b01100011,0b10000011,0b10100011,0b11000011,0b11100011,0b11100010,0b11100001,0b11100000,0b00000000};
void loop(){
  for(int i=0;i<160;i++){
    for(int j=0;j<240;j++){     
      complex<float> z(0,0),c(i/320.0,(j+240.0)/640.0);
      int n;
      for(n=1;n<sizeof(cmap);n++){
        z=z*z+c;
        if(norm(z)>4.0)break;
      }
      fb[j][i]=cmap[sizeof(cmap)-n];
    }
  }
  for(;;);
}

Title: Re: VGA output
Post by: stimmer on Nov 05, 2012, 02:59 am
I unrolled a loop and now it is 320x240 8) The resolution could go higher but 320x240x8 is 77Kbytes of RAM already.

Code: [Select]

/* Arduino Due VGA-Out v0.2 by stimmer
http://arduino.cc/forum/index.php/topic,130742.0.html */

inline void digitalWriteDirect(int pin, boolean val){
 if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
 else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
byte fb[240][320];

#define do20(x) x x x x x x x x x x x x x x x x x x x x
#define do80(x)  do20(x) do20(x) do20(x) do20(x)
#define do320(x) do80(x) do80(x) do80(x) do80(x)
#define MNOP(x) asm volatile (" .rept " #x "\n\t nop \n\t .endr \n\t")

void TC0_Handler()
{
   long dummy=REG_TC0_SR0;
                         
   if(line < 480){        
       byte * p=fb[line>>1];
       MNOP(160);
       do320(REG_PIOD_ODSR = *p++;MNOP(2);)
       REG_PIOD_ODSR = 0;
   }      
   if(line==490) digitalWriteDirect(3,1); //or digitalWriteDirect(3,0); to invert vsync
   if(line==492) digitalWriteDirect(3,0); //or digitalWriteDirect(3,1); to invert vsync
   
   line++; if(line == 525) line=0;
}

void setup(){
 for(int i=0;i<320;i++)for(int j=0;j<240;j++)fb[j][i]=j+i;
 
 pinMode(3,OUTPUT);  pinMode(2,OUTPUT);                      // vsync=3 hsync=2
 pinMode(25,OUTPUT); pinMode(26,OUTPUT);                     // blue  (26=msb,25=lsb)
 pinMode(27,OUTPUT); pinMode(28,OUTPUT); pinMode(14,OUTPUT); // green (14=msb,28,27=lsb)
 pinMode(15,OUTPUT); pinMode(29,OUTPUT); pinMode(11,OUTPUT); // red   (11=msb,29,15=lsb)

 REG_PIOD_OWER= 0xff;
 REG_PMC_PCER0= 1<<27;  
 REG_PIOB_PDR = 1<<25;
 REG_PIOB_ABSR= 1<<25;
 REG_TC0_WPMR = 0x54494D00;
 REG_TC0_CMR0 = 0b00000000000010011100010000000000;
//  REG_TC0_CMR0 = 0b00000000000001101100010000000000; // this inverts hsync
 REG_TC0_RC0  = 1334;
 REG_TC0_RA0  = 1174;  
 REG_TC0_CCR0 = 0b101;    
 REG_TC0_IER0 = 0b00010000;
 REG_TC0_IDR0 = 0b11101111;
 NVIC_EnableIRQ(TC0_IRQn);
}

#include <complex>
using namespace std;

const byte cmap[]={0b00000000,0b11100000,0b11100100,0b11101000,0b11101100,0b11110000,0b11110100,0b11111000,0b11111100,
                  0b11011100,0b10111100,0b10011100,0b01111100,0b01011100,0b00111100,0b00011100,0b00011101,0b00011110,
                  0b00011111,0b00011011,0b00010111,0b00010011,0b00001111,0b00001011,0b00000111,0b00000011,0b00100011,
                  0b01000011,0b01100011,0b10000011,0b10100011,0b11000011,0b11100011,0b11100010,0b11100001,0b11100000,0b00000000};
void loop(){
  for(int i=0;i<320;i++){
    for(int j=0;j<240;j++){     
      complex<float> z(0,0),c((i+180.0)/1280.0,(j+640.0)/1280.0);
      int n;
      for(n=1;n<sizeof(cmap);n++){
        z=z*z+c;
        if(norm(z)>4.0)break;
      }
      fb[j][i]=cmap[sizeof(cmap)-n];
    }
  }
  for(;;);
}
Title: Re: VGA output
Post by: cmaglie on Nov 05, 2012, 11:12 am
:smiley-surprise:

stimmer, you've got some serious skills here!
nice work!

C
Title: Re: VGA output
Post by: micnossub on Nov 06, 2012, 02:19 am
it is possible to only display black and white and get a better resolution?
Title: Re: VGA output
Post by: stimmer on Nov 06, 2012, 02:38 am
640x480 black and white only should be possible. It might even be possible with 2 bit greyscale.

There's a chance 800x600 black and white might work. Anything more than that takes too much memory.
Title: Re: VGA output
Post by: micnossub on Nov 06, 2012, 02:52 am
that would be nice 640x480! but just one bit!
Title: Re: VGA output
Post by: canter on Nov 06, 2012, 01:24 pm
This project can work with arduino uno?
Thanks.
Title: Re: VGA output
Post by: MichaelMeissner on Nov 06, 2012, 01:37 pm

This project can work with arduino uno?
Thanks.

No, the UNO only has enough memory for something like a 120x96 black and white image.

If that is fine, there are two shields that use the TVout library that are supposed to make the job easier:


I have the Video Experimenter, but it is on my to-do pile, and I haven't tried it out yet
Title: Re: VGA output
Post by: WilliamK Govinda on Nov 07, 2012, 08:04 pm
Superb!
Title: Re: VGA output
Post by: JLS1 on Nov 12, 2012, 10:45 am
This is very usefull for me - thanks

Is possible post source code for 640x480 or 800x600 black/white ?

Many thanks

Kamil
Title: Re: VGA output
Post by: cjdelphi on Nov 12, 2012, 03:10 pm
How long before we see a GPU or a graphics card from 1995 get modified to work with due/uno and a VGA monitor? :)
Title: Re: VGA output
Post by: neslekkim on Nov 12, 2012, 08:02 pm
why 95?
Someone have done it with stm32 based boards: http://hackaday.com/2012/10/08/stm32-driving-a-pcie-video-card/
and Gameduino produces vga(I think) using an FPGA adapterboard.

and, btw, the Propeller, with its 8 "core's" produces vga for games and such, if one could interface more memory on the Due (wish that could be possible on the next SAM based card) one could have kinda ok graphics.
Title: Re: VGA output
Post by: JLS1 on Nov 13, 2012, 11:19 pm
Simple Game of Life example :-)

Code: [Select]

#define GRID_X 100
#define GRID_Y 92

#define MAX_GENERATIONS 250

uint8_t grid[2][GRID_X][GRID_Y];
uint8_t current_grid = 0;
uint8_t generations = 0;

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
byte fb[240][320];

#define do20(x) x x x x x x x x x x x x x x x x x x x x
#define do80(x)  do20(x) do20(x) do20(x) do20(x)
#define do320(x) do80(x) do80(x) do80(x) do80(x)
#define MNOP(x) asm volatile (" .rept " #x "\n\t nop \n\t .endr \n\t")

void TC0_Handler()
{
    long dummy=REG_TC0_SR0;
                           
    if(line < 480){       
        byte * p=fb[line>>1];
        MNOP(160);
        do320(REG_PIOD_ODSR = *p++;MNOP(2);)
        REG_PIOD_ODSR = 0;
    }     
    if(line==490) digitalWriteDirect(3,1); //or digitalWriteDirect(3,0); to invert vsync
    if(line==492) digitalWriteDirect(3,0); //or digitalWriteDirect(3,1); to invert vsync
   
    line++; if(line == 525) line=0;
}

void setup(){
 
  pinMode(3,OUTPUT);  pinMode(2,OUTPUT);                      // vsync=3 hsync=2
  pinMode(25,OUTPUT); pinMode(26,OUTPUT);                     // blue  (26=msb,25=lsb)
  pinMode(27,OUTPUT); pinMode(28,OUTPUT); pinMode(14,OUTPUT); // green (14=msb,28,27=lsb)
  pinMode(15,OUTPUT); pinMode(29,OUTPUT); pinMode(11,OUTPUT); // red   (11=msb,29,15=lsb)

  REG_PIOD_OWER= 0xff;
  REG_PMC_PCER0= 1<<27; 
  REG_PIOB_PDR = 1<<25;
  REG_PIOB_ABSR= 1<<25;
  REG_TC0_WPMR = 0x54494D00;
  REG_TC0_CMR0 = 0b00000000000010011100010000000000;
//  REG_TC0_CMR0 = 0b00000000000001101100010000000000; // this inverts hsync
  REG_TC0_RC0  = 1334;
  REG_TC0_RA0  = 1174; 
  REG_TC0_CCR0 = 0b101;   
  REG_TC0_IER0 = 0b00010000;
  REG_TC0_IDR0 = 0b11101111;
  NVIC_EnableIRQ(TC0_IRQn);
 
  initGrid();
  drawGrid();
}


void loop(){
 
  runGrid();
drawGrid();
generations++;
if (generations > MAX_GENERATIONS) {
generations = 0;
initGrid();
}

}

void initGrid()
{
int i, j;
int t;

current_grid = 0;
for (i = 0; i < GRID_X; i++) {
for (j = 0; j < GRID_Y; j++) {

if (rand()%2) {
grid[0][i][j] = 2;
} else {
grid[0][i][j] = 0;
}
}
}
}

void runGrid()
{
uint8_t x, y;
int count;
uint8_t value = 0;
uint8_t new_grid;

new_grid = 1 - current_grid;
for (y = 0; y < GRID_Y; y++) {
for (x = 0; x < GRID_X; x++) {
count = count_neighbours(x, y);
if (count < 2 || count > 3) { value = 0; }
else if (count == 3) { value = 3; }
else { value = grid[current_grid][x][y]; }
grid[new_grid][x][y] = value;
}
}
current_grid = new_grid;
}

int count_neighbours(int x, int y)
{
int i, j;
int sx;
int result = 0;

x--;
y--;
for (i = 0; i < 3; i++) {
if (y < 0 || y > (GRID_Y - 1)) { continue; }
for (j = 0; j < 3; j++) {
if (x < 0 || x > (GRID_X - 1)) { continue; }
if (i==1 && j == 1) { x++; continue; }
if (grid[current_grid][x][y]) { result++; }
x++;
}
y++;
x -= 3;
}
return result;
}

void drawGrid()
{
uint8_t  x,  y;
uint8_t cx, cy;
uint8_t grid_next_colour = 0;
cx = 0;
cy = 0;
for (y = 0; y < GRID_Y; y++) {
cx = 0;
for (x = 0; x < GRID_X; x++) {
if (grid[1-current_grid][x][y] != grid[current_grid][x][y]) {
  if(grid[current_grid][x][y]) {
    fb[cy][cx]=rand()%255;
}
    else {
    fb[cy][cx]=0;
}

}
cx += 2;
}
cy += 2;
}
}
Title: Re: VGA output
Post by: stimmer on Nov 14, 2012, 11:45 am

Simple Game of Life example :-)


Nice work  :D (I accidentally left it running all night, it's still going strong!)

Here's a quick status update for the VGA output project. Basically to get any further with this I need to learn ARM inline assembler, which is what I've been doing. With the code above the output is shimmering slightly and if you look closely some of the pixels are bigger than others. I do have code which solves the wide pixels problem and reduces the shimmering, however it is unreliable (sometimes it doesn't compile, sometimes it compiles but doesn't work, sometimes it works perfectly). I guess I have a little more to learn.

I haven't started on 640x480 1bpp yet but I still think it is viable. I don't know about 800x600 (the pixel rate would be 40Mpixels/sec) but there might be a way...

Finally when reading the datasheet I noticed that the SAM3X has some DMA controllers. I am strongly tempted to evaluate whether I can use them rather than the inline assembler. This is even more to learn (I've never used DMA before) but if it does work it would be a much better solution. It would use much less CPU for one thing  :smiley-mr-green:
Title: Re: VGA output
Post by: JLS1 on Nov 14, 2012, 09:33 pm
Simple Wolfram 1D Cellular Automata example :-)

Code: [Select]

/* Wolfram Cellular Automata 1D v1.0 */

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
byte fb[240][320];

#define do20(x) x x x x x x x x x x x x x x x x x x x x
#define do80(x)  do20(x) do20(x) do20(x) do20(x)
#define do320(x) do80(x) do80(x) do80(x) do80(x)
#define MNOP(x) asm volatile (" .rept " #x "\n\t nop \n\t .endr \n\t")

void TC0_Handler()
{
    long dummy=REG_TC0_SR0;
                           
    if(line < 480){       
        byte * p=fb[line>>1];
        MNOP(160);
        do320(REG_PIOD_ODSR = *p++;MNOP(2);)
        REG_PIOD_ODSR = 0;
    }     
    if(line==490) digitalWriteDirect(3,1); //or digitalWriteDirect(3,0); to invert vsync
    if(line==492) digitalWriteDirect(3,0); //or digitalWriteDirect(3,1); to invert vsync
   
    line++; if(line == 525) line=0;
}

void setup(){
 
  pinMode(3,OUTPUT);  pinMode(2,OUTPUT);                      // vsync=3 hsync=2
  pinMode(25,OUTPUT); pinMode(26,OUTPUT);                     // blue  (26=msb,25=lsb)
  pinMode(27,OUTPUT); pinMode(28,OUTPUT); pinMode(14,OUTPUT); // green (14=msb,28,27=lsb)
  pinMode(15,OUTPUT); pinMode(29,OUTPUT); pinMode(11,OUTPUT); // red   (11=msb,29,15=lsb)

  REG_PIOD_OWER= 0xff;
  REG_PMC_PCER0= 1<<27; 
  REG_PIOB_PDR = 1<<25;
  REG_PIOB_ABSR= 1<<25;
  REG_TC0_WPMR = 0x54494D00;
  REG_TC0_CMR0 = 0b00000000000010011100010000000000;
//  REG_TC0_CMR0 = 0b00000000000001101100010000000000; // this inverts hsync
  REG_TC0_RC0  = 1334;
  REG_TC0_RA0  = 1174; 
  REG_TC0_CCR0 = 0b101;   
  REG_TC0_IER0 = 0b00010000;
  REG_TC0_IDR0 = 0b11101111;
  NVIC_EnableIRQ(TC0_IRQn);
 
}

void loop(){
 
  int iteration = 240;
  int lenght = 320;
  int row = 0;
  int state[lenght];
  int newstate[lenght];
  int i,j,k;
  int rules[8] = {
  int (rand()%2),
  int (rand()%2),
  int (rand()%2),
  int (rand()%2),
  int (rand()%2),
  int (rand()%2),
  int (rand()%2),
  int (rand()%2)};

  for (i=0;i<lenght;i++) state[i]= int (rand()%2);

   for (i=0;i<iteration;i++) {

      for (j=0;j<lenght;j++)
         newstate[j] = 0;

      for (j=0;j<lenght;j++) {
         k = 4*state[(j-1+lenght)%lenght] + 2*state[j] + state[(j+1)%lenght];
         newstate[j] = rules[k];
      }

      for (j=0;j<lenght;j++)
        state[j] = newstate[j];
        DisplayState(state,lenght,row);
        row = row + 1;
   }
}

void DisplayState(int s[],int len, int row)
{
   int i;

   for (i=0;i<len;i++) {
      if (s[i] == 1){
       fb[row][i]=255;
       }       
      else{
       fb[row][i]=0;
        }
      }
}
Title: Re: VGA output
Post by: JLS1 on Nov 19, 2012, 09:30 pm
Chua chaotic oscillator example :-)

Code: [Select]

/* Chua Chaotic Oscillator v1.0 */

inline void digitalWriteDirect(int pin, boolean val){
 if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
 else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
byte fb[240][320];

#define do20(x) x x x x x x x x x x x x x x x x x x x x
#define do80(x)  do20(x) do20(x) do20(x) do20(x)
#define do320(x) do80(x) do80(x) do80(x) do80(x)
#define MNOP(x) asm volatile (" .rept " #x "\n\t nop \n\t .endr \n\t")

void TC0_Handler()
{
   long dummy=REG_TC0_SR0;
                         
   if(line < 480){        
       byte * p=fb[line>>1];
       MNOP(160);
       do320(REG_PIOD_ODSR = *p++;MNOP(2);)
       REG_PIOD_ODSR = 0;
   }      
   if(line==490) digitalWriteDirect(3,1); //or digitalWriteDirect(3,0); to invert vsync
   if(line==492) digitalWriteDirect(3,0); //or digitalWriteDirect(3,1); to invert vsync
   
   line++; if(line == 525) line=0;
}

void setup(){
 
 pinMode(3,OUTPUT);  pinMode(2,OUTPUT);                      // vsync=3 hsync=2
 pinMode(25,OUTPUT); pinMode(26,OUTPUT);                     // blue  (26=msb,25=lsb)
 pinMode(27,OUTPUT); pinMode(28,OUTPUT); pinMode(14,OUTPUT); // green (14=msb,28,27=lsb)
 pinMode(15,OUTPUT); pinMode(29,OUTPUT); pinMode(11,OUTPUT); // red   (11=msb,29,15=lsb)

 REG_PIOD_OWER= 0xff;
 REG_PMC_PCER0= 1<<27;  
 REG_PIOB_PDR = 1<<25;
 REG_PIOB_ABSR= 1<<25;
 REG_TC0_WPMR = 0x54494D00;
 REG_TC0_CMR0 = 0b00000000000010011100010000000000;
//  REG_TC0_CMR0 = 0b00000000000001101100010000000000; // this inverts hsync
 REG_TC0_RC0  = 1334;
 REG_TC0_RA0  = 1174;  
 REG_TC0_CCR0 = 0b101;    
 REG_TC0_IER0 = 0b00010000;
 REG_TC0_IDR0 = 0b11101111;
 NVIC_EnableIRQ(TC0_IRQn);
 
}

 float x = 0.5;
 float y = 0.25;
 float z = 0.125;
 float h = 0;
     
 float dt = 0.005;

 float alpha = 15.6;
 float beta = 28.58;
 float a = -1.14286;
 float b = -0.714286;

void loop(){
 
 float oldx = x;
 float oldy = y;
 float oldz = z;

 h = (b * x) + (0.5 * (a - b) * (abs(x+1) - abs(x-1)));
             
 x = oldx + dt * (alpha * (oldy - oldx - h));
 y = oldy + dt * (oldx - oldy + oldz);
 z = oldz + dt * (-beta * oldy);

 fb[120+int(65*4*y)][160+int(65*x)]=255;

}
Title: Re: VGA output
Post by: stimmer on Nov 19, 2012, 10:34 pm
Nice :-) It looks great in colour too, change the last line to this:

Code: [Select]

  static int c=0;
  fb[120+int(65*4*y)][160+int(65*x)]=(c++)>>12;
Title: Re: VGA output
Post by: mbanzi on Nov 19, 2012, 11:45 pm
stimmer do you think your code can be packaged up as a library?
it would make it very simple to make nice graphics apps with the Due

m
Title: Re: VGA output
Post by: stimmer on Nov 20, 2012, 01:25 am
Yes, but please not just yet. I am still evaluating better ways of generating the VGA signal, which may be more steady and use less CPU. This might mean changing the pins the signal is output on. However I am not likely to change the format of the framebuffer (240x320 array) so any nice demo code people make now should still work and would be easy to use as example code in a library if authors wanted.

There's also some design decisions to make - if it turns out 640x480 works, should it be a separate library or the same one? Being the same library could make code larger and slower, but might allow mode changes at runtime. Also a library would need standard graphics functions (lines, text, bitmaps) - this is different in an 8bpp mode to a 1bpp mode. And whether to support composite output - 320x200 or 240 8-bit greyscale would be possible. I think that a single library would be more easily maintainable.
Title: Re: VGA output
Post by: stimmer on Nov 20, 2012, 02:28 am
Attached are some screenshots of JLS1's demo programs. Chua oscillator has my modification for colour. Life is Conway's famous 'game' we all know and love.

Cellular automata are explained in Wolfram's 'A New Kind Of Science' chapter 6 - he classifies them into four main types (uniform, structured, random, and complex) and others which are rarer and hard to classify. Attached are two examples, cell2 is complex and cell1 is one that doesn't fit the main types.
Title: Re: VGA output
Post by: JLS1 on Nov 20, 2012, 10:07 pm
Mira-Gumowski Fractal nice colour example :-)

Code: [Select]

/* Mira Gumowski Fractal v1.0 */

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
byte fb[240][320];

#define do20(x) x x x x x x x x x x x x x x x x x x x x
#define do80(x)  do20(x) do20(x) do20(x) do20(x)
#define do320(x) do80(x) do80(x) do80(x) do80(x)
#define MNOP(x) asm volatile (" .rept " #x "\n\t nop \n\t .endr \n\t")

void TC0_Handler()
{
    long dummy=REG_TC0_SR0;
                           
    if(line < 480){       
        byte * p=fb[line>>1];
        MNOP(160);
        do320(REG_PIOD_ODSR = *p++;MNOP(2);)
        REG_PIOD_ODSR = 0;
    }     
    if(line==490) digitalWriteDirect(3,1); //or digitalWriteDirect(3,0); to invert vsync
    if(line==492) digitalWriteDirect(3,0); //or digitalWriteDirect(3,1); to invert vsync
   
    line++; if(line == 525) line=0;
}

void setup(){
 
  pinMode(3,OUTPUT);  pinMode(2,OUTPUT);                      // vsync=3 hsync=2
  pinMode(25,OUTPUT); pinMode(26,OUTPUT);                     // blue  (26=msb,25=lsb)
  pinMode(27,OUTPUT); pinMode(28,OUTPUT); pinMode(14,OUTPUT); // green (14=msb,28,27=lsb)
  pinMode(15,OUTPUT); pinMode(29,OUTPUT); pinMode(11,OUTPUT); // red   (11=msb,29,15=lsb)

  REG_PIOD_OWER= 0xff;
  REG_PMC_PCER0= 1<<27; 
  REG_PIOB_PDR = 1<<25;
  REG_PIOB_ABSR= 1<<25;
  REG_TC0_WPMR = 0x54494D00;
  REG_TC0_CMR0 = 0b00000000000010011100010000000000;
//  REG_TC0_CMR0 = 0b00000000000001101100010000000000; // this inverts hsync
  REG_TC0_RC0  = 1334;
  REG_TC0_RA0  = 1174; 
  REG_TC0_CCR0 = 0b101;   
  REG_TC0_IER0 = 0b00010000;
  REG_TC0_IDR0 = 0b11101111;
  NVIC_EnableIRQ(TC0_IRQn);
 
}

   float a = -0.6624;
   float c = 2*(1-a);
   float x = 14.7176;
   float y = -14.6602;
   float f = 0;
   
   int xx,yy;
   
   int cnt = 0;
   int col = 255;

void loop(){
 
    double oldx = x;
    x = f+1*y;
    f = a*x+c*x*x/(1+x*x);
    y = f-oldx;
   
    xx = 160+3*x;
    yy = 120+4*y;
   
    if (cnt == 2000) {
col = rand();
cnt = 0; }

    cnt++;
   
    if ((xx>=0)&(xx<=319)&(yy>=0)&(yy<=239)) {

  fb[yy][xx]=col; }

}
Title: Re: VGA output
Post by: JLS1 on Nov 21, 2012, 09:51 pm
Hopalong Orbit Fractal example :-)

Code: [Select]

/* Hopalong Orbit Fractal v1.0 */

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
byte fb[240][320];

#define do20(x) x x x x x x x x x x x x x x x x x x x x
#define do80(x)  do20(x) do20(x) do20(x) do20(x)
#define do320(x) do80(x) do80(x) do80(x) do80(x)
#define MNOP(x) asm volatile (" .rept " #x "\n\t nop \n\t .endr \n\t")

void TC0_Handler()
{
    long dummy=REG_TC0_SR0;
                           
    if(line < 480){       
        byte * p=fb[line>>1];
        MNOP(160);
        do320(REG_PIOD_ODSR = *p++;MNOP(2);)
        REG_PIOD_ODSR = 0;
    }     
    if(line==490) digitalWriteDirect(3,1); //or digitalWriteDirect(3,0); to invert vsync
    if(line==492) digitalWriteDirect(3,0); //or digitalWriteDirect(3,1); to invert vsync
   
    line++; if(line == 525) line=0;
}

void setup(){
 
  pinMode(3,OUTPUT);  pinMode(2,OUTPUT);                      // vsync=3 hsync=2
  pinMode(25,OUTPUT); pinMode(26,OUTPUT);                     // blue  (26=msb,25=lsb)
  pinMode(27,OUTPUT); pinMode(28,OUTPUT); pinMode(14,OUTPUT); // green (14=msb,28,27=lsb)
  pinMode(15,OUTPUT); pinMode(29,OUTPUT); pinMode(11,OUTPUT); // red   (11=msb,29,15=lsb)

  REG_PIOD_OWER= 0xff;
  REG_PMC_PCER0= 1<<27; 
  REG_PIOB_PDR = 1<<25;
  REG_PIOB_ABSR= 1<<25;
  REG_TC0_WPMR = 0x54494D00;
  REG_TC0_CMR0 = 0b00000000000010011100010000000000;
//  REG_TC0_CMR0 = 0b00000000000001101100010000000000; // this inverts hsync
  REG_TC0_RC0  = 1334;
  REG_TC0_RA0  = 1174; 
  REG_TC0_CCR0 = 0b101;   
  REG_TC0_IER0 = 0b00010000;
  REG_TC0_IDR0 = 0b11101111;
  NVIC_EnableIRQ(TC0_IRQn);
 
}

   float a = 0.5;
   float b = -0.6;
   float c = 0.7;
   float x = 1;
   float y = 0;
   
   int xx,yy;
   
   int cnt = 0;
   int col = 255;

void loop(){
 
    double oldx = x;
    double oldy = y;
   
    x = oldy-(oldx/abs(oldx))*sqrt(abs(b*oldx-c));
    y = a-oldx;
   
    xx = 160+8*x;
    yy = 120+8*y;
   
    if (cnt == 2000) {
col = rand();
cnt = 0; }

    cnt++;
   
    if ((xx>=0)&(xx<=319)&(yy>=0)&(yy<=239)) {

  fb[yy][xx]=col; }

}
Title: Re: VGA output
Post by: stimmer on Nov 23, 2012, 01:56 am
This is the latest version of the code. The output pins have changed completely and are now more convenient. Also I have attempted to reduce/eliminate the shimmering problem.

The connections are now:

Due pin 34 -> 820R resistor -> VGA pin 3 (blue)
Due pin 35 -> 390R resistor -> VGA pin 3 (blue)

Due pin 36 -> 2k2 resistor -> VGA pin 2 (green)
Due pin 37 -> 1k resistor -> VGA pin 2 (green)
Due pin 38 -> 470R resistor -> VGA pin 2 (green)

Due pin 39 -> 2k2 resistor -> VGA pin 1 (red)
Due pin 40 -> 1k resistor -> VGA pin 1 (red)
Due pin 41 -> 470R resistor -> VGA pin 1(red)

Due pin 42 -> VGA pin 14 (VSync)
Due pin 43 -> VGA pin 13 (HSync)

Due pin GND -> VGA pins 5,6,7,8,10

Code: [Select]

/* Arduino Due VGA-Out v0.8 by stimmer
http://arduino.cc/forum/index.php/topic,130742.0.html */

int bins[256];
void  __attribute__((aligned(64))) doLine(byte *p){
       asm volatile (
       "isb \n\t"
       "dsb \n\t"        
       "movw r1,#0x4254 \n\t"
       "movt r1,#0x4009 \n\t"
       "ldr r0,[r1] \n\t"
       "subs r0,#66 \n\t"
       "lsls r0,r0,#1 \n\t"
       "orr r0,#1 \n\t"  
       "add r0,pc \n\t"
       "isb \n\t"
       ".align 5 \n\t"
       "bx r0 \n\t"
       ".rept 160 \n\t"
       "nop \n\t"
       ".endr \n\t"
       
       //this is debugging code, but because the timimg is so sensitive I have to leave it in
       "ldr r0,[r1] \n\t"
       "subs r0,#128 \n\t"
       "ldr r2,[%[bins],r0,lsl #2] \n\t"
       "adds r2,#1 \n\t"
       "str r2,[%[bins],r0,lsl #2] \n\t"
       
       
       "movw r1,#0x1238 \n\t"
       "movt r1,#0x400e \n\t"
       
       ".rept 320 \n\t"        
       "ldrb r0,[%[bytes]],#1 \n\t"
       "lsls r0,r0,#2 \n\t"
       "str r0,[r1] \n\t"
       ".endr \n\t"
       
       "mov r0,#0 \n\t"
       "str r0,[r1] \n\t"
       :[bytes]"+r"(p)
       :[bins]"r"(bins)
       :"r0","r1","r2"
       );  
}

inline void digitalWriteDirect(int pin, boolean val){
 if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
 else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
byte fb[240][320];

void PWM_Handler()
{
   long dummy=REG_PWM_ISR1;
                         
   if(line < 480){        
       byte * p=fb[line>>1];
       doLine(p);
   }      
   if(line==490) digitalWriteDirect(42,1); //or digitalWriteDirect(42,0); to invert vsync
   if(line==492) digitalWriteDirect(42,0); //or digitalWriteDirect(42,1);

   line++; if(line == 525) line=0;
}

void setup(){
   
 pinMode(42,OUTPUT); pinMode(43,OUTPUT);                     // vsync=42 hsync=43
 pinMode(34,OUTPUT); pinMode(35,OUTPUT);                     // blue  (35=msb,34=lsb)
 pinMode(36,OUTPUT); pinMode(37,OUTPUT); pinMode(38,OUTPUT); // green (38=msb,37,36=lsb)
 pinMode(39,OUTPUT); pinMode(40,OUTPUT); pinMode(41,OUTPUT); // red   (41=msb,40,39=lsb)

 REG_PIOC_OWER= 0x3fc;
 REG_PMC_PCER0= 1<<27;
 
 REG_PIOA_PDR |=1<<20;
 REG_PIOA_ABSR|=1<<20;
 REG_PMC_PCER1= 1<<4;
 REG_PWM_WPCR= 0x50574dfc;
 REG_PWM_CLK= 0x00010001;
 REG_PWM_DIS= 1<<2;
 REG_PWM_CMR2=0x0;   //  REG_PWM_CMR2=0x200;  //to invert hsync polarity
 REG_PWM_CPRD2=2668;
 REG_PWM_CDTY2=2348;
 REG_PWM_SCM=0;
 REG_PWM_IER1=1<<2;
 REG_PWM_ENA= 1<<2;  
 NVIC_EnableIRQ(PWM_IRQn);

}

void loop(){
 
 for(int x=0;x<320;x++){
   int my=240;
   for(float Z=-15.02;Z<15.0;Z+=0.01){
     float X=(x-159.98)/16.0;
     float R=sqrt(X*X+Z*Z);
     float Y=150.0*(1.0+sin(R)/R);
     int y=320.0-(Z*4.0)-Y;
     if(y<my && y>=0){
       byte c=Y;
       fb[y][x]=c;
       my=y;
     }
   }
 }
         
}


Title: Re: VGA output
Post by: stimmer on Nov 24, 2012, 08:39 pm
I have had some success with 640x480 1bpp. This version is using SPI and DMA - this has the advantage that now the CPU can carry on working most of the time while the screen is being drawn. Therefore it is much faster than the 320x240x8bpp code. The downside is that the video output is on the SPI connector (MOSI - middle pin of lower row - look at http://arduino.cc/forum/index.php/topic,132130.0.html if you can't find it). Connect MOSI through a 100R resistor to VGA R,G and B. VSync is on pin 42 and HSync is on pin 43.

There is slight shimmering in this version which I hope to be able to correct. Also the timings are quite a way out (pixel clock is 10% too fast) hopefully most LCDs will be able to stretch the picture enough. If anyone does try it and it does/doesn't work please tell me.

If you make any demos with this please use the putPixel/getPixel functions if they are fast enough, as I might yet change the underlying format of the framebuffer.

Code: [Select]

/* Arduino Due VGA-Out 640x480 v0.4 by stimmer
http://arduino.cc/forum/index.php/topic,130742.0.html */

int bins[256];
void  __attribute__((aligned(64))) doLine(byte *p){
       asm volatile (        
       "isb \n\t"
       "dsb \n\t"
       "movw r1,#0x4254 \n\t"
       "movt r1,#0x4009 \n\t"
       "ldr r0,[r1] \n\t"
       "subs r0,#35 \n\t"
       "lsls r0,r0,#1 \n\t"
       "orr r0,#1 \n\t"  
       "add r0,pc \n\t"
       "isb \n\t"
       ".align 5 \n\t"
       "bx r0 \n\t"
       ".rept 200 \n\t"
       "nop \n\t"
       ".endr \n\t"
               
       //this is debugging code, but because the timimg is so sensitive I have to leave it in
       "ldr r0,[r1] \n\t"
       "subs r0,#128 \n\t"
       "ldr r2,[%[bins],r0,lsl #2] \n\t"
       "adds r2,#1 \n\t"
       "str r2,[%[bins],r0,lsl #2] \n\t"
       
       "movw r1,#0x4104 \n\t"
       "movt r1,#0x400C \n\t"
       "str %[bytes],[r1] \n\t"
       "movw r1,#0x4110 \n\t"
       "movt r1,#0x400C \n\t"
       "movw r0,80 \n\t"
       "movt r0,#0x0000 \n\t"
       "str r0,[r1] \n\t"
       "movw r1,#0x4028 \n\t"
       "movt r1,#0x400C \n\t"
       "mov r0,1<<5 \n\t"
       "str r0,[r1] \n\t"
       "movw r1,#0x0e04 \n\t"
       "movt r1,#0x400e \n\t"
       "mov r0,1<<26 \n\t"
       ".rept 26\n\t nop\n\t .endr\n\t"
       "str r0,[r1] \n\t"
             
       :[bytes]"+r"(p)
       :[bins]"r"(bins)
       :"r0","r1","r2"
       );  
         
}

void __attribute__((aligned(64))) DMAC_Handler()
{
   REG_SPI0_TDR=0;
   asm volatile("nop\n\t nop\n\t nop\n\t");
   REG_PIOA_PER  = 1<<26;
   uint32_t dummy=REG_DMAC_EBCISR;
}

inline void digitalWriteDirect(int pin, boolean val){
 if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
 else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
byte fb[480][80] __attribute__((aligned(256)));

void __attribute__((aligned(64))) PWM_Handler()
{
   long dummy=REG_PWM_ISR1;
               
   if(line < 480){        
       byte * p=fb[line];
       doLine(p);
   }      
   if(line==490) digitalWriteDirect(42,1); //or digitalWriteDirect(42,0); to invert vsync
   if(line==492) digitalWriteDirect(42,0); //or digitalWriteDirect(42,1);
   
   line++; if(line == 525){
     line=0;
   }
}

void setup(){
   
 pinMode(42,OUTPUT); pinMode(43,OUTPUT);                     // vsync=42 hsync=43
 // video output is on SPI MOSI pin (bottom middle on SAM3 3x2 SPI connector)                                      
 
 REG_PIOA_PDR  =1<<20;
 REG_PIOA_ABSR|=1<<20;
 REG_PMC_PCER1= 1<<4;
 REG_PWM_WPCR= 0x50574dfc;
 REG_PWM_CLK= 0x00010001;
 REG_PWM_DIS= 1<<2;
 REG_PWM_CMR2=0x0;   //  REG_PWM_CMR2=0x200;  //to invert hsync polarity
 REG_PWM_CPRD2=2668;
 REG_PWM_CDTY2=2348;
 REG_PWM_SCM=0;
 REG_PWM_IER1=1<<2;
 REG_PWM_ENA= 1<<2;  
 NVIC_EnableIRQ(PWM_IRQn);

 REG_PMC_PCER1= 1<<7;  
 REG_DMAC_WPMR=DMAC_WPMR_WPKEY(0x444d4143);
 REG_DMAC_EN=1;
 REG_DMAC_GCFG=0x00;
 REG_DMAC_EBCIER=1<<5;
 REG_DMAC_DADDR5=(uint32_t)&REG_SPI0_TDR;  
 REG_DMAC_DSCR5=0;
 REG_DMAC_CTRLB5=0x20310000;
 REG_DMAC_CFG5=  0x21012210;
   
 NVIC_EnableIRQ(DMAC_IRQn);

 REG_PIOA_PDR  = (1<<25)|(1<<27)|(1<<28);
 REG_PIOA_PER  = 1<<26;
 REG_PIOA_ABSR&=~((1<<25)|(1<<27)|(1<<28));
 REG_PMC_PCER0= 1<<24;
 REG_SPI0_WPMR=0x53504900;
 REG_SPI0_CR=0x1;
 REG_SPI0_MR=0x00000011;
 SPI0->SPI_CSR[0]=0x00000300;
 
}

inline void putPixel(int x,int y,byte c=1){
 if((x<0)||(x>=640)||(y<0)||(y>=480))return;
 byte mask=1<<((~x)&7);
 if(c) fb[y][x>>3]|= mask;
 else  fb[y][x>>3]&=~mask;
}

inline int getPixel(int x,int y){
 if((x<0)||(x>=640)||(y<0)||(y>=480))return -1;
 byte mask=1<<((~x)&7);
 return (fb[y][x>>3] & mask)?1:0;
}

inline void clearBuffer(byte c=0){
 memset(fb,c?255:0,sizeof(fb));  
}

void loop(){

 float c[3][2]={{random(640),random(480)},{random(640),random(480)},{random(640),random(480)}};
 
 static int j=1;
 if(random(10)==0){clearBuffer(j);j=1-j;}

 for(int x=0;x<640;x+=2){putPixel(x,0);putPixel(x,479);}
 for(int y=0;y<480;y+=2){putPixel(0,y);putPixel(639,y);}

 float x=c[0][0],y=c[0][1];

 for(int t=0;t<40000;t++){
   int i=random(0,3);
   x=(x+c[i][0])/2;
   y=(y+c[i][1])/2;
   putPixel(x,y,j);
 }
         
}
Title: Re: VGA output
Post by: stimmer on Nov 25, 2012, 11:51 pm
Great news - SVGA 800x600x1bpp is possible  :smiley-mr-green: Connections are the same as 640x480 above (Video out on SPI MOSI, VSync on pin 42 and HSync on pin 43)

Code: [Select]
/* Arduino Due SVGA-Out 800x600 v0.3 by stimmer
http://arduino.cc/forum/index.php/topic,130742.0.html
Please do not attempt to understand this code :-) */

int bins[256];
void  __attribute__((aligned(64))) doLine(byte *p){
        asm volatile (       
        "isb \n\t"
        "dsb \n\t"
        "movw r1,#0x4254 \n\t"
        "movt r1,#0x4009 \n\t"
        "ldr r0,[r1] \n\t"
        "subs r0,#40 \n\t"
        "lsls r0,r0,#1 \n\t"
        "orr r0,#1 \n\t" 
        "add r0,pc \n\t"
        "isb \n\t"
        ".align 5 \n\t"
        "bx r0 \n\t"
        ".rept 90 \n\t"
        "nop \n\t"
        ".endr \n\t"
               
        //this is debugging code, but because the timimg is so sensitive I have to leave it in
        "ldr r0,[r1] \n\t"
        "subs r0,#128 \n\t"
        "ldr r2,[%[bins],r0,lsl #2] \n\t"
        "adds r2,#1 \n\t"
        "str r2,[%[bins],r0,lsl #2] \n\t"
       
        //"movw r1,#0x40DC \n\t"
        //"movt r1,#0x400C \n\t"
        //"str %[bytes],[r1] \n\t"
        "movw r1,#0x40E8 \n\t"
        "movt r1,#0x400C \n\t"
        "movw r0,26 \n\t"
        "movt r0,#0x1203 \n\t"
        "str r0,[r1] \n\t"
        "movw r1,#0x4028 \n\t"
        "movt r1,#0x400C \n\t"
        "mov r0,1<<4 \n\t"
        "str r0,[r1] \n\t"
        "movw r1,#0x0e04 \n\t"
        "movt r1,#0x400e \n\t"
        "mov r0,1<<26 \n\t"
        ".rept 12\n\t nop\n\t .endr\n\t"
        "str r0,[r1] \n\t"
             
        :[bytes]"+r"(p)
        :[bins]"r"(bins)
        :"r0","r1","r2"
        ); 
         
}

void __attribute__((aligned(64))) DMAC_Handler()
{
    REG_PIOA_PER  = 1<<26;     
    uint32_t dummy=REG_DMAC_EBCISR;
}

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
uint16_t fb[600][52] __attribute__((aligned(256)));

void __attribute__((aligned(64))) PWM_Handler()
{
    long dummy=REG_PWM_ISR1;
                 
    if(line < 600){       
        //byte * p=fb[line];
        doLine(0);
    }     
    if(line==601) digitalWriteDirect(42,1); //or digitalWriteDirect(42,0); to invert vsync
    if(line==605) digitalWriteDirect(42,0); //or digitalWriteDirect(42,1);
   
    line++; if(line == 628){
      REG_DMAC_SADDR4=(uint32_t)fb;
      line=0;
    }
}

void setup(){
   
  pinMode(42,OUTPUT); pinMode(43,OUTPUT);                     // vsync=42 hsync=43
  // video output is on SPI MOSI pin (bottom middle on SAM3 3x2 SPI connector)                                     
 
  REG_PIOA_PDR  =1<<20;
  REG_PIOA_ABSR|=1<<20;
  REG_PMC_PCER1= 1<<4;
  REG_PWM_WPCR= 0x50574dfc;
  REG_PWM_CLK= 0x00010001;
  REG_PWM_DIS= 1<<2;
  REG_PWM_CMR2=0x0;   //  REG_PWM_CMR2=0x200;  //to invert hsync polarity
  REG_PWM_CPRD2=2218;
  REG_PWM_CDTY2=1949;
  REG_PWM_SCM=0;
  REG_PWM_IER1=1<<2;
  REG_PWM_ENA= 1<<2; 
  NVIC_EnableIRQ(PWM_IRQn);

  REG_PMC_PCER1= 1<<7; 
  REG_DMAC_WPMR=DMAC_WPMR_WPKEY(0x444d4143);
  REG_DMAC_EN=1;
  REG_DMAC_GCFG=0x00;
  REG_DMAC_EBCIER=1<<4;
  REG_DMAC_DADDR4=(uint32_t)&REG_SPI0_TDR; 
  REG_DMAC_DSCR4=0;
  REG_DMAC_CTRLB4=0x20310000;
  REG_DMAC_CFG4=  0x01412210;
   
  NVIC_EnableIRQ(DMAC_IRQn);

  REG_PIOA_PDR  = (1<<25)|(1<<27)|(1<<28);
  REG_PIOA_PER  = 1<<26;
  REG_PIOA_ABSR&=~((1<<25)|(1<<27)|(1<<28));
  REG_PMC_PCER0= 1<<24;
  REG_SPI0_WPMR=0x53504900;
  REG_SPI0_CR=0x1;
  REG_SPI0_MR=0x00000011;
  SPI0->SPI_CSR[0]=0x00000280;
 
  Serial.begin(9600);
}

inline void putPixel(int x,int y,byte c=1){
  if((x<0)||(x>=800)||(y<0)||(y>=600))return;
  uint16_t mask=1<<((~x)&15);
  if(c) fb[y][x>>4]|= mask;
  else  fb[y][x>>4]&=~mask;
}

inline int getPixel(int x,int y){
  if((x<0)||(x>=800)||(y<0)||(y>=600))return -1;
  uint16_t mask=1<<((~x)&15);
  return (fb[y][x>>4] & mask)?1:0;
}

#define sgn(x) (((x)>0)?1:((x)<0)?-1:0)
void drawLine(int x0, int y0, int x1, int y1,int c){
   int dx=abs(x1-x0), dy=abs(y1-y0),sx=sgn(x1-x0),sy=sgn(y1-y0);
   int err=dx-dy;
   do{ putPixel(x0,y0,c<2?c:!getPixel(x0,y0));
       int e2=2*err;
       if (e2 > -dy){err-=dy;x0+=sx;}
       if (e2 <  dx){err+=dx;y0+=sy;}
   }   while ((x0!=x1)||(y0!=y1));
}

void loop(){ 
  int j=random(6)-221;
  for(int i=j;i<800-j;i++)drawLine(i,j-100,799-i,699-j,2);
  for(int i=799-j;i>=j;i--)drawLine(j,i-100,799-j,699-i,2);             
}

Title: Re: VGA output
Post by: JLS1 on Nov 26, 2012, 10:55 pm
Hi Stimmer

800x600 is great work many thanks :-)

Kamil

P.S. is possible 640x480 with some colors ?
Title: Re: VGA output
Post by: JLS1 on Nov 26, 2012, 11:05 pm
SVGA Hopalong Orbit Fractal :-)

Code: [Select]

/* Hopalong Orbit Fractal v1.1 by JLS 2012 */

/* Arduino Due SVGA-Out 800x600 v0.3 by stimmer
http://arduino.cc/forum/index.php/topic,130742.0.html
Please do not attempt to understand this code :-) */

int bins[256];
void  __attribute__((aligned(64))) doLine(byte *p){
       asm volatile (        
       "isb \n\t"
       "dsb \n\t"
       "movw r1,#0x4254 \n\t"
       "movt r1,#0x4009 \n\t"
       "ldr r0,[r1] \n\t"
       "subs r0,#40 \n\t"
       "lsls r0,r0,#1 \n\t"
       "orr r0,#1 \n\t"  
       "add r0,pc \n\t"
       "isb \n\t"
       ".align 5 \n\t"
       "bx r0 \n\t"
       ".rept 90 \n\t"
       "nop \n\t"
       ".endr \n\t"
               
       //this is debugging code, but because the timimg is so sensitive I have to leave it in
       "ldr r0,[r1] \n\t"
       "subs r0,#128 \n\t"
       "ldr r2,[%[bins],r0,lsl #2] \n\t"
       "adds r2,#1 \n\t"
       "str r2,[%[bins],r0,lsl #2] \n\t"
       
       //"movw r1,#0x40DC \n\t"
       //"movt r1,#0x400C \n\t"
       //"str %[bytes],[r1] \n\t"
       "movw r1,#0x40E8 \n\t"
       "movt r1,#0x400C \n\t"
       "movw r0,26 \n\t"
       "movt r0,#0x1203 \n\t"
       "str r0,[r1] \n\t"
       "movw r1,#0x4028 \n\t"
       "movt r1,#0x400C \n\t"
       "mov r0,1<<4 \n\t"
       "str r0,[r1] \n\t"
       "movw r1,#0x0e04 \n\t"
       "movt r1,#0x400e \n\t"
       "mov r0,1<<26 \n\t"
       ".rept 12\n\t nop\n\t .endr\n\t"
       "str r0,[r1] \n\t"
             
       :[bytes]"+r"(p)
       :[bins]"r"(bins)
       :"r0","r1","r2"
       );  
         
}

void __attribute__((aligned(64))) DMAC_Handler()
{
   REG_PIOA_PER  = 1<<26;    
   uint32_t dummy=REG_DMAC_EBCISR;
}

inline void digitalWriteDirect(int pin, boolean val){
 if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
 else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
uint16_t fb[600][52] __attribute__((aligned(256)));

void __attribute__((aligned(64))) PWM_Handler()
{
   long dummy=REG_PWM_ISR1;
               
   if(line < 600){        
       //byte * p=fb[line];
       doLine(0);
   }      
   if(line==601) digitalWriteDirect(42,1); //or digitalWriteDirect(42,0); to invert vsync
   if(line==605) digitalWriteDirect(42,0); //or digitalWriteDirect(42,1);
   
   line++; if(line == 628){
     REG_DMAC_SADDR4=(uint32_t)fb;
     line=0;
   }
}

void setup(){
   
 pinMode(42,OUTPUT); pinMode(43,OUTPUT);                     // vsync=42 hsync=43
 // video output is on SPI MOSI pin (bottom middle on SAM3 3x2 SPI connector)                                      
 
 REG_PIOA_PDR  =1<<20;
 REG_PIOA_ABSR|=1<<20;
 REG_PMC_PCER1= 1<<4;
 REG_PWM_WPCR= 0x50574dfc;
 REG_PWM_CLK= 0x00010001;
 REG_PWM_DIS= 1<<2;
 REG_PWM_CMR2=0x0;   //  REG_PWM_CMR2=0x200;  //to invert hsync polarity
 REG_PWM_CPRD2=2218;
 REG_PWM_CDTY2=1949;
 REG_PWM_SCM=0;
 REG_PWM_IER1=1<<2;
 REG_PWM_ENA= 1<<2;  
 NVIC_EnableIRQ(PWM_IRQn);

 REG_PMC_PCER1= 1<<7;  
 REG_DMAC_WPMR=DMAC_WPMR_WPKEY(0x444d4143);
 REG_DMAC_EN=1;
 REG_DMAC_GCFG=0x00;
 REG_DMAC_EBCIER=1<<4;
 REG_DMAC_DADDR4=(uint32_t)&REG_SPI0_TDR;  
 REG_DMAC_DSCR4=0;
 REG_DMAC_CTRLB4=0x20310000;
 REG_DMAC_CFG4=  0x01412210;
   
 NVIC_EnableIRQ(DMAC_IRQn);

 REG_PIOA_PDR  = (1<<25)|(1<<27)|(1<<28);
 REG_PIOA_PER  = 1<<26;
 REG_PIOA_ABSR&=~((1<<25)|(1<<27)|(1<<28));
 REG_PMC_PCER0= 1<<24;
 REG_SPI0_WPMR=0x53504900;
 REG_SPI0_CR=0x1;
 REG_SPI0_MR=0x00000011;
 SPI0->SPI_CSR[0]=0x00000280;
 
 Serial.begin(9600);
}

inline void putPixel(int x,int y,byte c=1){
 if((x<0)||(x>=800)||(y<0)||(y>=600))return;
 uint16_t mask=1<<((~x)&15);
 if(c) fb[y][x>>4]|= mask;
 else  fb[y][x>>4]&=~mask;
}

inline int getPixel(int x,int y){
 if((x<0)||(x>=800)||(y<0)||(y>=600))return -1;
 uint16_t mask=1<<((~x)&15);
 return (fb[y][x>>4] & mask)?1:0;
}

#define sgn(x) (((x)>0)?1:((x)<0)?-1:0)
void drawLine(int x0, int y0, int x1, int y1,int c){
  int dx=abs(x1-x0), dy=abs(y1-y0),sx=sgn(x1-x0),sy=sgn(y1-y0);
  int err=dx-dy;
  do{ putPixel(x0,y0,c<2?c:!getPixel(x0,y0));
      int e2=2*err;
      if (e2 > -dy){err-=dy;x0+=sx;}
      if (e2 <  dx){err+=dx;y0+=sy;}
  }   while ((x0!=x1)||(y0!=y1));
}

  float a = 0.5;
  float b = -0.6;
  float c = 0.7;
  float x = 1;
  float y = 0;
 
  int xx,yy;
 
  int cnt = 0;
  int col = 1;

void loop(){  
       
   double oldx = x;
   double oldy = y;
   
   x = oldy-(oldx/abs(oldx))*sqrt(abs(b*oldx-c));
   y = a-oldx;
   
   xx = 400+10*x;
   yy = 300+10*y;
   
   if (cnt == 1000) {
col = rand()%2;
cnt = 0; }

   cnt++;
   
   if ((xx>=0)&(xx<=799)&(yy>=0)&(yy<=599)) putPixel(xx,yy,col);
}
Title: Re: VGA output
Post by: JLS1 on Nov 26, 2012, 11:15 pm
SVGA Three Ply Orbit Fractal :-)

Code: [Select]

/* Three Ply Orbit Fractal v1.1 by JLS 2012 */

/* Arduino Due SVGA-Out 800x600 v0.3 by stimmer
http://arduino.cc/forum/index.php/topic,130742.0.html
Please do not attempt to understand this code :-) */

int bins[256];
void  __attribute__((aligned(64))) doLine(byte *p){
        asm volatile (       
        "isb \n\t"
        "dsb \n\t"
        "movw r1,#0x4254 \n\t"
        "movt r1,#0x4009 \n\t"
        "ldr r0,[r1] \n\t"
        "subs r0,#40 \n\t"
        "lsls r0,r0,#1 \n\t"
        "orr r0,#1 \n\t" 
        "add r0,pc \n\t"
        "isb \n\t"
        ".align 5 \n\t"
        "bx r0 \n\t"
        ".rept 90 \n\t"
        "nop \n\t"
        ".endr \n\t"
               
        //this is debugging code, but because the timimg is so sensitive I have to leave it in
        "ldr r0,[r1] \n\t"
        "subs r0,#128 \n\t"
        "ldr r2,[%[bins],r0,lsl #2] \n\t"
        "adds r2,#1 \n\t"
        "str r2,[%[bins],r0,lsl #2] \n\t"
       
        //"movw r1,#0x40DC \n\t"
        //"movt r1,#0x400C \n\t"
        //"str %[bytes],[r1] \n\t"
        "movw r1,#0x40E8 \n\t"
        "movt r1,#0x400C \n\t"
        "movw r0,26 \n\t"
        "movt r0,#0x1203 \n\t"
        "str r0,[r1] \n\t"
        "movw r1,#0x4028 \n\t"
        "movt r1,#0x400C \n\t"
        "mov r0,1<<4 \n\t"
        "str r0,[r1] \n\t"
        "movw r1,#0x0e04 \n\t"
        "movt r1,#0x400e \n\t"
        "mov r0,1<<26 \n\t"
        ".rept 12\n\t nop\n\t .endr\n\t"
        "str r0,[r1] \n\t"
             
        :[bytes]"+r"(p)
        :[bins]"r"(bins)
        :"r0","r1","r2"
        ); 
         
}

void __attribute__((aligned(64))) DMAC_Handler()
{
    REG_PIOA_PER  = 1<<26;     
    uint32_t dummy=REG_DMAC_EBCISR;
}

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
uint16_t fb[600][52] __attribute__((aligned(256)));

void __attribute__((aligned(64))) PWM_Handler()
{
    long dummy=REG_PWM_ISR1;
                 
    if(line < 600){       
        //byte * p=fb[line];
        doLine(0);
    }     
    if(line==601) digitalWriteDirect(42,1); //or digitalWriteDirect(42,0); to invert vsync
    if(line==605) digitalWriteDirect(42,0); //or digitalWriteDirect(42,1);
   
    line++; if(line == 628){
      REG_DMAC_SADDR4=(uint32_t)fb;
      line=0;
    }
}

void setup(){
   
  pinMode(42,OUTPUT); pinMode(43,OUTPUT);                     // vsync=42 hsync=43
  // video output is on SPI MOSI pin (bottom middle on SAM3 3x2 SPI connector)                                     
 
  REG_PIOA_PDR  =1<<20;
  REG_PIOA_ABSR|=1<<20;
  REG_PMC_PCER1= 1<<4;
  REG_PWM_WPCR= 0x50574dfc;
  REG_PWM_CLK= 0x00010001;
  REG_PWM_DIS= 1<<2;
  REG_PWM_CMR2=0x0;   //  REG_PWM_CMR2=0x200;  //to invert hsync polarity
  REG_PWM_CPRD2=2218;
  REG_PWM_CDTY2=1949;
  REG_PWM_SCM=0;
  REG_PWM_IER1=1<<2;
  REG_PWM_ENA= 1<<2; 
  NVIC_EnableIRQ(PWM_IRQn);

  REG_PMC_PCER1= 1<<7; 
  REG_DMAC_WPMR=DMAC_WPMR_WPKEY(0x444d4143);
  REG_DMAC_EN=1;
  REG_DMAC_GCFG=0x00;
  REG_DMAC_EBCIER=1<<4;
  REG_DMAC_DADDR4=(uint32_t)&REG_SPI0_TDR; 
  REG_DMAC_DSCR4=0;
  REG_DMAC_CTRLB4=0x20310000;
  REG_DMAC_CFG4=  0x01412210;
   
  NVIC_EnableIRQ(DMAC_IRQn);

  REG_PIOA_PDR  = (1<<25)|(1<<27)|(1<<28);
  REG_PIOA_PER  = 1<<26;
  REG_PIOA_ABSR&=~((1<<25)|(1<<27)|(1<<28));
  REG_PMC_PCER0= 1<<24;
  REG_SPI0_WPMR=0x53504900;
  REG_SPI0_CR=0x1;
  REG_SPI0_MR=0x00000011;
  SPI0->SPI_CSR[0]=0x00000280;
 
  Serial.begin(9600);
}

inline void putPixel(int x,int y,byte c=1){
  if((x<0)||(x>=800)||(y<0)||(y>=600))return;
  uint16_t mask=1<<((~x)&15);
  if(c) fb[y][x>>4]|= mask;
  else  fb[y][x>>4]&=~mask;
}

inline int getPixel(int x,int y){
  if((x<0)||(x>=800)||(y<0)||(y>=600))return -1;
  uint16_t mask=1<<((~x)&15);
  return (fb[y][x>>4] & mask)?1:0;
}

#define sgn(x) (((x)>0)?1:((x)<0)?-1:0)
void drawLine(int x0, int y0, int x1, int y1,int c){
   int dx=abs(x1-x0), dy=abs(y1-y0),sx=sgn(x1-x0),sy=sgn(y1-y0);
   int err=dx-dy;
   do{ putPixel(x0,y0,c<2?c:!getPixel(x0,y0));
       int e2=2*err;
       if (e2 > -dy){err-=dy;x0+=sx;}
       if (e2 <  dx){err+=dx;y0+=sy;}
   }   while ((x0!=x1)||(y0!=y1));
}

   float a = -55;
   float b = -1;
   float c = -41;
   float x = 1;
   float y = 0;
   
   int xx,yy;
   
   int cnt = 0;
   int col = 1;

void loop(){ 
         
    double oldx = x;
    double oldy = y;
   
    x = oldy-(oldx/abs(oldx))*abs(sin(oldx)*cos(b)+c-oldx*sin(a+b+c));
    y = a-oldx;
   
    xx = 400+x/5;
    yy = 300+y/5;
   
    if (cnt == 1000) {
col = rand()%2;
cnt = 0; }

    cnt++;
   
    if ((xx>=0)&(xx<=799)&(yy>=0)&(yy<=599)) putPixel(xx,yy,col);
}
Title: Re: VGA output
Post by: stimmer on Nov 27, 2012, 05:07 pm

Hi Stimmer

800x600 is great work many thanks :-)

Kamil

P.S. is possible 640x480 with some colors ?


I don't think 640x480 with 2 bits per pixel will be possible unfortunately. 640x480x3bpp is definitely impossible as there is not enough memory. With 2bpp there is enough memory but not enough speed. I got 640x480 working by using the SPI hardware but there is only one fast SPI channel on the Due.

What might be possible is a 640x480 overlay on a much lower resolution background. I've attached a screenshot of one of my experiments, this is 640x480 over an 80x60 grid of background colours (although the timing is all wrong at the moment). This isn't so useful for graphics demos, but could be good if I added text and fonts because it would give some control over text background colour. But I don't know if I can get it working well enough yet.

Title: Re: VGA output
Post by: JLS1 on Nov 27, 2012, 10:45 pm
Thanks info

Kamil
Title: Re: VGA output
Post by: JLS1 on Nov 27, 2012, 11:30 pm
SVGA Quadrup Two Orbit Fractal :-)

Code: [Select]

/* Quadrup Two Orbit Fractal v1.1 by JLS 2012 */

/* Arduino Due SVGA-Out 800x600 v0.3 by stimmer
http://arduino.cc/forum/index.php/topic,130742.0.html
Please do not attempt to understand this code :-) */

int bins[256];
void  __attribute__((aligned(64))) doLine(byte *p){
        asm volatile (       
        "isb \n\t"
        "dsb \n\t"
        "movw r1,#0x4254 \n\t"
        "movt r1,#0x4009 \n\t"
        "ldr r0,[r1] \n\t"
        "subs r0,#40 \n\t"
        "lsls r0,r0,#1 \n\t"
        "orr r0,#1 \n\t" 
        "add r0,pc \n\t"
        "isb \n\t"
        ".align 5 \n\t"
        "bx r0 \n\t"
        ".rept 90 \n\t"
        "nop \n\t"
        ".endr \n\t"
               
        //this is debugging code, but because the timimg is so sensitive I have to leave it in
        "ldr r0,[r1] \n\t"
        "subs r0,#128 \n\t"
        "ldr r2,[%[bins],r0,lsl #2] \n\t"
        "adds r2,#1 \n\t"
        "str r2,[%[bins],r0,lsl #2] \n\t"
       
        //"movw r1,#0x40DC \n\t"
        //"movt r1,#0x400C \n\t"
        //"str %[bytes],[r1] \n\t"
        "movw r1,#0x40E8 \n\t"
        "movt r1,#0x400C \n\t"
        "movw r0,26 \n\t"
        "movt r0,#0x1203 \n\t"
        "str r0,[r1] \n\t"
        "movw r1,#0x4028 \n\t"
        "movt r1,#0x400C \n\t"
        "mov r0,1<<4 \n\t"
        "str r0,[r1] \n\t"
        "movw r1,#0x0e04 \n\t"
        "movt r1,#0x400e \n\t"
        "mov r0,1<<26 \n\t"
        ".rept 12\n\t nop\n\t .endr\n\t"
        "str r0,[r1] \n\t"
             
        :[bytes]"+r"(p)
        :[bins]"r"(bins)
        :"r0","r1","r2"
        ); 
         
}

void __attribute__((aligned(64))) DMAC_Handler()
{
    REG_PIOA_PER  = 1<<26;     
    uint32_t dummy=REG_DMAC_EBCISR;
}

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
uint16_t fb[600][52] __attribute__((aligned(256)));

void __attribute__((aligned(64))) PWM_Handler()
{
    long dummy=REG_PWM_ISR1;
                 
    if(line < 600){       
        //byte * p=fb[line];
        doLine(0);
    }     
    if(line==601) digitalWriteDirect(42,1); //or digitalWriteDirect(42,0); to invert vsync
    if(line==605) digitalWriteDirect(42,0); //or digitalWriteDirect(42,1);
   
    line++; if(line == 628){
      REG_DMAC_SADDR4=(uint32_t)fb;
      line=0;
    }
}

void setup(){
   
  pinMode(42,OUTPUT); pinMode(43,OUTPUT);                     // vsync=42 hsync=43
  // video output is on SPI MOSI pin (bottom middle on SAM3 3x2 SPI connector)                                     
 
  REG_PIOA_PDR  =1<<20;
  REG_PIOA_ABSR|=1<<20;
  REG_PMC_PCER1= 1<<4;
  REG_PWM_WPCR= 0x50574dfc;
  REG_PWM_CLK= 0x00010001;
  REG_PWM_DIS= 1<<2;
  REG_PWM_CMR2=0x0;   //  REG_PWM_CMR2=0x200;  //to invert hsync polarity
  REG_PWM_CPRD2=2218;
  REG_PWM_CDTY2=1949;
  REG_PWM_SCM=0;
  REG_PWM_IER1=1<<2;
  REG_PWM_ENA= 1<<2; 
  NVIC_EnableIRQ(PWM_IRQn);

  REG_PMC_PCER1= 1<<7; 
  REG_DMAC_WPMR=DMAC_WPMR_WPKEY(0x444d4143);
  REG_DMAC_EN=1;
  REG_DMAC_GCFG=0x00;
  REG_DMAC_EBCIER=1<<4;
  REG_DMAC_DADDR4=(uint32_t)&REG_SPI0_TDR; 
  REG_DMAC_DSCR4=0;
  REG_DMAC_CTRLB4=0x20310000;
  REG_DMAC_CFG4=  0x01412210;
   
  NVIC_EnableIRQ(DMAC_IRQn);

  REG_PIOA_PDR  = (1<<25)|(1<<27)|(1<<28);
  REG_PIOA_PER  = 1<<26;
  REG_PIOA_ABSR&=~((1<<25)|(1<<27)|(1<<28));
  REG_PMC_PCER0= 1<<24;
  REG_SPI0_WPMR=0x53504900;
  REG_SPI0_CR=0x1;
  REG_SPI0_MR=0x00000011;
  SPI0->SPI_CSR[0]=0x00000280;
 
  Serial.begin(9600);
}

inline void putPixel(int x,int y,byte c=1){
  if((x<0)||(x>=800)||(y<0)||(y>=600))return;
  uint16_t mask=1<<((~x)&15);
  if(c) fb[y][x>>4]|= mask;
  else  fb[y][x>>4]&=~mask;
}

inline int getPixel(int x,int y){
  if((x<0)||(x>=800)||(y<0)||(y>=600))return -1;
  uint16_t mask=1<<((~x)&15);
  return (fb[y][x>>4] & mask)?1:0;
}

#define sgn(x) (((x)>0)?1:((x)<0)?-1:0)
void drawLine(int x0, int y0, int x1, int y1,int c){
   int dx=abs(x1-x0), dy=abs(y1-y0),sx=sgn(x1-x0),sy=sgn(y1-y0);
   int err=dx-dy;
   do{ putPixel(x0,y0,c<2?c:!getPixel(x0,y0));
       int e2=2*err;
       if (e2 > -dy){err-=dy;x0+=sx;}
       if (e2 <  dx){err+=dx;y0+=sy;}
   }   while ((x0!=x1)||(y0!=y1));
}

    float a = 34;
    float b = 0.9;
    float c = 5;
    float x = 1;
    float y = 0;
   
    int xx,yy;
   
    int cnt = 0;
    int col = 1;

void loop(){ 
         
    double oldx = x;
    double oldy = y;
   
    x = oldy-(oldx/abs(oldx))*sin(log(abs(b*oldx-c)))*atan(abs((pow(c*oldx-b,2))));
    y = a-oldx;
   
    xx = 285+7*x;
    yy = 210+5.5*y;
   
    if (cnt == 1000) {
col = rand()%2;
cnt = 0; }

    cnt++;
   
    if ((xx>=0)&(xx<=799)&(yy>=0)&(yy<=599)) putPixel(xx,yy,col);
}
Title: Re: VGA output
Post by: JLS1 on Dec 09, 2012, 04:05 pm
SVGA New Strange Attractor :-)

Update !

Code: [Select]

/* New Strange Attractor v1.1 by JLS 2012 */

/* Arduino Due SVGA-Out 800x600 v0.3 by stimmer
http://arduino.cc/forum/index.php/topic,130742.0.html
Please do not attempt to understand this code :-) */

int bins[256];
void  __attribute__((aligned(64))) doLine(byte *p){
        asm volatile (       
        "isb \n\t"
        "dsb \n\t"
        "movw r1,#0x4254 \n\t"
        "movt r1,#0x4009 \n\t"
        "ldr r0,[r1] \n\t"
        "subs r0,#40 \n\t"
        "lsls r0,r0,#1 \n\t"
        "orr r0,#1 \n\t" 
        "add r0,pc \n\t"
        "isb \n\t"
        ".align 5 \n\t"
        "bx r0 \n\t"
        ".rept 90 \n\t"
        "nop \n\t"
        ".endr \n\t"
               
        //this is debugging code, but because the timimg is so sensitive I have to leave it in
        "ldr r0,[r1] \n\t"
        "subs r0,#128 \n\t"
        "ldr r2,[%[bins],r0,lsl #2] \n\t"
        "adds r2,#1 \n\t"
        "str r2,[%[bins],r0,lsl #2] \n\t"
       
        //"movw r1,#0x40DC \n\t"
        //"movt r1,#0x400C \n\t"
        //"str %[bytes],[r1] \n\t"
        "movw r1,#0x40E8 \n\t"
        "movt r1,#0x400C \n\t"
        "movw r0,26 \n\t"
        "movt r0,#0x1203 \n\t"
        "str r0,[r1] \n\t"
        "movw r1,#0x4028 \n\t"
        "movt r1,#0x400C \n\t"
        "mov r0,1<<4 \n\t"
        "str r0,[r1] \n\t"
        "movw r1,#0x0e04 \n\t"
        "movt r1,#0x400e \n\t"
        "mov r0,1<<26 \n\t"
        ".rept 12\n\t nop\n\t .endr\n\t"
        "str r0,[r1] \n\t"
             
        :[bytes]"+r"(p)
        :[bins]"r"(bins)
        :"r0","r1","r2"
        ); 
         
}

void __attribute__((aligned(64))) DMAC_Handler()
{
    REG_PIOA_PER  = 1<<26;     
    uint32_t dummy=REG_DMAC_EBCISR;
}

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
uint16_t fb[600][52] __attribute__((aligned(256)));

void __attribute__((aligned(64))) PWM_Handler()
{
    long dummy=REG_PWM_ISR1;
                 
    if(line < 600){       
        //byte * p=fb[line];
        doLine(0);
    }     
    if(line==601) digitalWriteDirect(42,1); //or digitalWriteDirect(42,0); to invert vsync
    if(line==605) digitalWriteDirect(42,0); //or digitalWriteDirect(42,1);
   
    line++; if(line == 628){
      REG_DMAC_SADDR4=(uint32_t)fb;
      line=0;
    }
}

   float x = 1;
   float y = 1;
   float a,b,c,d;
   
   int xx,yy;
   
void rndval(){
   randomSeed(analogRead(8));
   a = 2+(random(500)/100);
   randomSeed(analogRead(9));
   b = 2+(random(500)/100);
   randomSeed(analogRead(10));
   c = 2+(random(500)/100);
   randomSeed(analogRead(11));
   d = 2+(random(500)/100);
}

void setup(){
   
  pinMode(42,OUTPUT); pinMode(43,OUTPUT);                     // vsync=42 hsync=43
  // video output is on SPI MOSI pin (bottom middle on SAM3 3x2 SPI connector)                                     
 
  REG_PIOA_PDR  =1<<20;
  REG_PIOA_ABSR|=1<<20;
  REG_PMC_PCER1= 1<<4;
  REG_PWM_WPCR= 0x50574dfc;
  REG_PWM_CLK= 0x00010001;
  REG_PWM_DIS= 1<<2;
  REG_PWM_CMR2=0x0;   //  REG_PWM_CMR2=0x200;  //to invert hsync polarity
  REG_PWM_CPRD2=2218;
  REG_PWM_CDTY2=1949;
  REG_PWM_SCM=0;
  REG_PWM_IER1=1<<2;
  REG_PWM_ENA= 1<<2; 
  NVIC_EnableIRQ(PWM_IRQn);

  REG_PMC_PCER1= 1<<7; 
  REG_DMAC_WPMR=DMAC_WPMR_WPKEY(0x444d4143);
  REG_DMAC_EN=1;
  REG_DMAC_GCFG=0x00;
  REG_DMAC_EBCIER=1<<4;
  REG_DMAC_DADDR4=(uint32_t)&REG_SPI0_TDR; 
  REG_DMAC_DSCR4=0;
  REG_DMAC_CTRLB4=0x20310000;
  REG_DMAC_CFG4=  0x01412210;
   
  NVIC_EnableIRQ(DMAC_IRQn);

  REG_PIOA_PDR  = (1<<25)|(1<<27)|(1<<28);
  REG_PIOA_PER  = 1<<26;
  REG_PIOA_ABSR&=~((1<<25)|(1<<27)|(1<<28));
  REG_PMC_PCER0= 1<<24;
  REG_SPI0_WPMR=0x53504900;
  REG_SPI0_CR=0x1;
  REG_SPI0_MR=0x00000011;
  SPI0->SPI_CSR[0]=0x00000280;
}

inline void putPixel(int x,int y,byte c=1){
  if((x<0)||(x>=800)||(y<0)||(y>=600))return;
  uint16_t mask=1<<((~x)&15);
  if(c) fb[y][x>>4]|= mask;
  else  fb[y][x>>4]&=~mask;
}

void cls(){
  for(int bb=0;bb<599;bb++){
  for(int aa=0;aa<799;aa++)putPixel(aa,bb,0);
  }
}

void loop(){
 
    rndval();
    cls();
 
    for (int i=0; i <= 30000; i++){
         
    double oldx = x;
    double oldy = y;
   
    x = sin(-a*oldy)-cos(b*oldx);
    y = sin(c*oldx)-cos(d*oldy);
   
    xx = 400+140*x;
    yy = 300+140*y;
   
    if ((xx>=0)&(xx<=799)&(yy>=0)&(yy<=599)) putPixel(xx,yy,1);
   
    }
}
Title: Re: VGA output
Post by: JLS1 on Dec 11, 2012, 10:38 pm
SVGA Novel 4D chaotic attractor :-)

Code: [Select]

/* Novel 4D Chaotic Attractor v1.0 by JLS 2012 */

/* Arduino Due SVGA-Out 800x600 v0.3 by stimmer
http://arduino.cc/forum/index.php/topic,130742.0.html
Please do not attempt to understand this code :-) */

int bins[256];
void  __attribute__((aligned(64))) doLine(byte *p){
        asm volatile (       
        "isb \n\t"
        "dsb \n\t"
        "movw r1,#0x4254 \n\t"
        "movt r1,#0x4009 \n\t"
        "ldr r0,[r1] \n\t"
        "subs r0,#40 \n\t"
        "lsls r0,r0,#1 \n\t"
        "orr r0,#1 \n\t" 
        "add r0,pc \n\t"
        "isb \n\t"
        ".align 5 \n\t"
        "bx r0 \n\t"
        ".rept 90 \n\t"
        "nop \n\t"
        ".endr \n\t"
               
        //this is debugging code, but because the timimg is so sensitive I have to leave it in
        "ldr r0,[r1] \n\t"
        "subs r0,#128 \n\t"
        "ldr r2,[%[bins],r0,lsl #2] \n\t"
        "adds r2,#1 \n\t"
        "str r2,[%[bins],r0,lsl #2] \n\t"
       
        //"movw r1,#0x40DC \n\t"
        //"movt r1,#0x400C \n\t"
        //"str %[bytes],[r1] \n\t"
        "movw r1,#0x40E8 \n\t"
        "movt r1,#0x400C \n\t"
        "movw r0,26 \n\t"
        "movt r0,#0x1203 \n\t"
        "str r0,[r1] \n\t"
        "movw r1,#0x4028 \n\t"
        "movt r1,#0x400C \n\t"
        "mov r0,1<<4 \n\t"
        "str r0,[r1] \n\t"
        "movw r1,#0x0e04 \n\t"
        "movt r1,#0x400e \n\t"
        "mov r0,1<<26 \n\t"
        ".rept 12\n\t nop\n\t .endr\n\t"
        "str r0,[r1] \n\t"
             
        :[bytes]"+r"(p)
        :[bins]"r"(bins)
        :"r0","r1","r2"
        ); 
         
}

void __attribute__((aligned(64))) DMAC_Handler()
{
    REG_PIOA_PER  = 1<<26;     
    uint32_t dummy=REG_DMAC_EBCISR;
}

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

volatile short line;
uint16_t fb[600][52] __attribute__((aligned(256)));

void __attribute__((aligned(64))) PWM_Handler()
{
    long dummy=REG_PWM_ISR1;
                 
    if(line < 600){       
        //byte * p=fb[line];
        doLine(0);
    }     
    if(line==601) digitalWriteDirect(42,1); //or digitalWriteDirect(42,0); to invert vsync
    if(line==605) digitalWriteDirect(42,0); //or digitalWriteDirect(42,1);
   
    line++; if(line == 628){
      REG_DMAC_SADDR4=(uint32_t)fb;
      line=0;
    }
}

void setup(){
   
  pinMode(42,OUTPUT); pinMode(43,OUTPUT);                     // vsync=42 hsync=43
  // video output is on SPI MOSI pin (bottom middle on SAM3 3x2 SPI connector)                                     
 
  REG_PIOA_PDR  =1<<20;
  REG_PIOA_ABSR|=1<<20;
  REG_PMC_PCER1= 1<<4;
  REG_PWM_WPCR= 0x50574dfc;
  REG_PWM_CLK= 0x00010001;
  REG_PWM_DIS= 1<<2;
  REG_PWM_CMR2=0x0;   //  REG_PWM_CMR2=0x200;  //to invert hsync polarity
  REG_PWM_CPRD2=2218;
  REG_PWM_CDTY2=1949;
  REG_PWM_SCM=0;
  REG_PWM_IER1=1<<2;
  REG_PWM_ENA= 1<<2; 
  NVIC_EnableIRQ(PWM_IRQn);

  REG_PMC_PCER1= 1<<7; 
  REG_DMAC_WPMR=DMAC_WPMR_WPKEY(0x444d4143);
  REG_DMAC_EN=1;
  REG_DMAC_GCFG=0x00;
  REG_DMAC_EBCIER=1<<4;
  REG_DMAC_DADDR4=(uint32_t)&REG_SPI0_TDR; 
  REG_DMAC_DSCR4=0;
  REG_DMAC_CTRLB4=0x20310000;
  REG_DMAC_CFG4=  0x01412210;
   
  NVIC_EnableIRQ(DMAC_IRQn);

  REG_PIOA_PDR  = (1<<25)|(1<<27)|(1<<28);
  REG_PIOA_PER  = 1<<26;
  REG_PIOA_ABSR&=~((1<<25)|(1<<27)|(1<<28));
  REG_PMC_PCER0= 1<<24;
  REG_SPI0_WPMR=0x53504900;
  REG_SPI0_CR=0x1;
  REG_SPI0_MR=0x00000011;
  SPI0->SPI_CSR[0]=0x00000280;
}

inline void putPixel(int x,int y,byte c=1){
  if((x<0)||(x>=800)||(y<0)||(y>=600))return;
  uint16_t mask=1<<((~x)&15);
  if(c) fb[y][x>>4]|= mask;
  else  fb[y][x>>4]&=~mask;
}

    float x = 2;
    float y = 1;
    float z = 1;
    float u = 2;
   
    float oldx,oldy,oldz,oldu;

    float dt = 0.0005;

    float a = 10;
    float b = 12;
    float c = 50;
    float d = 2;
    float e = 4;
       
    int xx,yy;
       
    int cnt = 0;
    int col = 1;

void loop(){
 
    oldx = x;
    oldy = y;
    oldz = z;
    oldu = u;
       
       
    x = oldx + dt * (oldy*oldz-a*oldx);
    y = oldy + dt * (b*oldy-oldx*oldz);
    z = oldz + dt * (oldx*oldy-c*oldz+d*oldu);
    u = oldu + dt * (oldx*oldz-e*oldu);
   
    xx = 400+1.5*x;
    yy = 300+1.3*y;
   
     if (cnt == 1000) {
col = rand()%2;
cnt = 0; }

    cnt++;
   
    if ((xx>=0)&(xx<=799)&(yy>=0)&(yy<=599)) putPixel(xx,yy,col);
   
}
Title: Re: VGA output
Post by: stimmer on Dec 12, 2012, 12:57 am
Thanks for the demos, though I won't be able to try the latest ones for another day or two: I've taken my VGA circuit off the breadboard, in preparation for turning it into a mini-shield :) I've attached an image of my first design below.

After that my intention is to start on a library. I still don't know whether to have colour and 1-bit monochrome as two separate libraries or to just have one big library for everything.
Title: Re: VGA output
Post by: bensom on Dec 20, 2012, 05:22 pm
I played with this a bit, reduced the color screen to 320x200 so it has some memory left for other things, like BASIC. Got to say: love it!
Title: Re: VGA output
Post by: stimmer on Dec 21, 2012, 02:28 am
Wow, that looks like an amazing project! 8)

Must be 20 years at least since I last saw line numbers  XD
Title: Re: VGA output
Post by: andycat on Jan 18, 2013, 10:43 pm
amazing work people, keep it up - my inner nerd is swooning - i want more details on embedded basic and fractals and vga shields!! ;-D
Title: Re: VGA output
Post by: BKnight760 on Jan 24, 2013, 05:17 am
I'm working on some code based off stimmer's modified code (320x240x8), but it seems that the Serial communication no longer works after setting up the timers.

In the setup() method, I started the Serial at 9600, and then did println() thoughout the setup() method, and found this block of code causes it to stop working.

What is it about this code that disables the serial output?  

Code: [Select]
 REG_PIOD_OWER= 0xff;
 REG_PMC_PCER0= 1<<27;  
 REG_PIOB_PDR = 1<<25;
 REG_PIOB_ABSR= 1<<25;
 REG_TC0_WPMR = 0x54494D00;
 REG_TC0_CMR0 = 0b00000000000010011100010000000000;
 //  REG_TC0_CMR0 = 0b00000000000001101100010000000000; // this inverts hsync
 REG_TC0_RC0  = 1334;
 REG_TC0_RA0  = 1174;  
 REG_TC0_CCR0 = 0b101;    
 REG_TC0_IER0 = 0b00010000;
 REG_TC0_IDR0 = 0b11101111;
 NVIC_EnableIRQ(TC0_IRQn);



Is there anything we can do to have this still work and have serial communication available?


--edit--

I did some further debug and found that it works all the way up to the point of calling:

Code: [Select]
NVIC_EnableIRQ(TC0_IRQn);
Title: Re: VGA output
Post by: stimmer on Jan 24, 2013, 12:21 pm
(My monitor is broken, so this project is on hiatus  :0 )

Which version of the code are you using? Specifically what is in the interrupt handler code? The interrupt code is (necessarily) quite long, which can cause trouble with other peripherals using interrupts such as serial. However, the later versions of the project will work properly with Serial at 9600, I know because I used it when debugging the code.
Title: Re: VGA output
Post by: bensom on Jan 24, 2013, 06:07 pm
I used the REG_PWM version, that works with serial!

Code: [Select]

void PWM_Handler()
{
  long dummy=REG_PWM_ISR1;
.
.
}
void setupVGA()
{
  pinMode(42,OUTPUT);   pinMode(43,OUTPUT);                     // vsync=42 hsync=43
  pinMode(34,OUTPUT);   pinMode(35,OUTPUT);                     // blue  (35=msb,34=lsb)
  pinMode(36,OUTPUT);   pinMode(37,OUTPUT);   pinMode(38,OUTPUT); // green (38=msb,37,36=lsb)
  pinMode(39,OUTPUT);   pinMode(40,OUTPUT);   pinMode(41,OUTPUT); // red   (41=msb,40,39=lsb)
  REG_PIOC_OWER= 0x3fc;
  REG_PMC_PCER0= 1<<27;

  REG_PIOA_PDR |=1<<20;
  REG_PIOA_ABSR|=1<<20;
  REG_PMC_PCER1= 1<<4;
  REG_PWM_WPCR= 0x50574dfc;
  REG_PWM_CLK= 0x00010001;
  REG_PWM_DIS= 1<<2;
  REG_PWM_CMR2=0x0;   //  REG_PWM_CMR2=0x200;  //to invert hsync polarity
  REG_PWM_CPRD2=2668;
  REG_PWM_CDTY2=2348;
  REG_PWM_SCM=0;
  REG_PWM_IER1=1<<2;
  REG_PWM_ENA= 1<<2; 
  NVIC_EnableIRQ(PWM_IRQn);
}



Title: Re: VGA output
Post by: stimmer on Feb 20, 2013, 01:52 pm
I have a new monitor, so this project is restarted  ]:D :D :smiley-mr-green:

I've been working on turning the code into a library, which makes it a lot easier to use. It's about as simple to use as the old TVout library was on the Uno. And I've added some simple text and graphics functions, as well as print library support (so you can use print and println for easy text output). The mini-shield design I posted about above works quite well, but the circuit is simple enough to be built on a breadboard too, just 13 resistors.

I am hoping to make a proper release of the library code in the next week or so. But until then here's a sneak preview of what you can expect.

Code example:
Code: [Select]

#include <VGA.h>

void setup() {
  VGA.begin(320,240,VGA_COLOUR);
}

void loop() { 
  VGA.setInk(random(256));
  VGA.setPaper(random(256));
  VGA.print(" Hello Arduino ");
}


Title: Re: VGA output
Post by: JLS1 on Feb 21, 2013, 09:04 am
Great info many thanks :-)

Kamil
Title: Re: VGA output
Post by: BKnight760 on Apr 22, 2013, 02:52 am
I reworked my code based off the REG_PWM version and am no longer having issues with the Serial connection.

My code is able to load a bitmap graphic off the SD card, read the bitmap and DIB headers and resize any image to the desired 2D-array size.  It has to down-sample from 24-bit color to 8-bit color, but still looks pretty good with only 256 color choices.

Currently, I'm loading a background image to fit the 320x240x8 framebuffer.

Then I load 2 smaller images to do some bit-blit.  I'm using images that are 24x32 pixels (also down-sized and down-sampled from larger images). 

Code: [Select]
void readBitmap(char* filePath, byte** pictureBuffer,int bufferWidth,int bufferHeight)
{

  SdFile myFile;
  boolean openedFile = myFile.open(filePath,O_RDWR);
  if (openedFile)
  {

    unsigned int FileSize=0;
    unsigned int Offset=0;


    Serial.print("Reading ");
    Serial.print(filePath);
    Serial.println(" bitmap header...");
    //Read Bitmap header
    for (int i=0;i<14;i++)
    {
      byte myByte=myFile.read();
      Serial.print("Byte ");
      Serial.print(i);
      Serial.print(": 0x");
      if (myByte<16)
      {
        //Pad with a leading zero, if needed.
        Serial.print("0");
      }
      Serial.println(myByte,HEX);

      //Bytes 2 through 5 are the file size
      if((i>=2) && (i<=5))
      {
        FileSize=FileSize+(((int)myByte)<<(8*(i-2)));
        Serial.print("FileSize: ");
        Serial.println(FileSize);
      }

      //Bytes 10 through 13 are the offset to the pixel data.
      if((i>=10) && (i<=14))
      {
        Offset=Offset+(((int)myByte)<<(8*(i-10)));
        Serial.print("Offset: ");
        Serial.println(Offset);
      }
    }

    Serial.print("Done reading ");
    Serial.print(filePath);
    Serial.println(" bitmap header.");


    Serial.print("Reading ");
    Serial.print(filePath);
    Serial.println(" DIB header...");

    unsigned int Width=0;
    unsigned int Height=0;
    unsigned int BitsPerPixel=0;
    //Read the DIB header
    for (int i=0;i<40;i++)
    {
      byte myByte=myFile.read();
      Serial.print("Byte ");
      Serial.print(i);
      Serial.print(": 0x");
      if (myByte<16)
      {
        //Pad with a leading zero, if needed.
        Serial.print("0");
      }
      Serial.println(myByte,HEX);


      //Bytes 4 through 7 are bitmap width in pixels
      if((i>=4) && (i<=7))
      {
        Width=Width+(((int)myByte)<<(8*(i-4)));
        Serial.print("Width: ");
        Serial.println(Width);
      }

      //Bytes 8 through 11 are bitmap height in pixels
      if((i>=8) && (i<=11))
      {
        Height=Height+(((int)myByte)<<(8*(i-8)));
        Serial.print("Height: ");
        Serial.println(Height);
      }

      //Bytes 14 through 15 are bitmap bits per pixel
      if((i>=14) && (i<=15))
      {
        BitsPerPixel=BitsPerPixel+(((int)myByte)<<(8*(i-14)));
        Serial.print("BitsPerPixel: ");
        Serial.println(BitsPerPixel);
      }


    }


    int BytesPerPixel=((FileSize-Offset)/Width)/Height;
    Serial.print("BytesPerPixel=");
    Serial.println(BytesPerPixel);


    Serial.print("Done reading ");
    Serial.print(filePath);
    Serial.println(" DIB header...");

    Serial.print("Loading ");
    Serial.print(filePath);
    Serial.println(" bitmap pixels...");
    myFile.seekSet(Offset+1);

    byte buf[Width*BytesPerPixel];

    for(int y=0;y<Height;y++)
    {
      //Serial.print("Loading Row: ");
      //Serial.print(y,DEC);
      //Serial.print(" / ");
      //Serial.println(Height,DEC);

      //Serial.print("Pointer to FB[y][0] = ");
      //Serial.println((int)&FrameBuffer[y][0],HEX);


      //Serial.print("Loading Pixel: ");
      //Serial.print(x,DEC);
      //Serial.print(" / ");
      //Serial.println(Width,DEC);


      //Read the entire row of pixels all at once.
      //This is a major performance upgrade.
      myFile.read(buf,sizeof(buf));

      //Convert the 3-bytes-per-pixel data into 1-byte-per-pixel format.
      for (int x=0;x<Width;x++){
        byte red=buf[x*3];
        byte green=buf[(x*3)+1];
        byte blue=buf[(x*3)+2];


        //Serial.print("Red = ");
        //Serial.println(red);

        byte redBits = (byte)map(red,0,255,0,7);
        //Serial.print("RedBits = ");
        //Serial.println(redBits);
        byte greenBits = (byte)map(green,0,255,0,7);
        byte blueBits = (byte)map(blue,0,255,0,3);

        pictureBuffer[(bufferHeight-1)-(int)(((double)y*(double)bufferHeight)/(double)Height)][(int)(((double)x*(double)bufferWidth)/(double)Width)]=(redBits<<5)+(greenBits<<2)+(blueBits);
      }

      //The Bitmap file format pads every row to a 4-byte (word)
      //boundary.  Calculate the padding, and skip it.
      int BytesInLastWord=((Width*BytesPerPixel)%4);
      int BytesOfPadding=0;
      if (BytesInLastWord>0)
      {
        BytesOfPadding=4-BytesInLastWord;
      }
      //Serial.print("Row should have ");
      //Serial.print(BytesOfPadding);
      //Serial.println(" bytes of padding.");

      for (int i=0;i<BytesOfPadding;i++)
      {
        //Skip the padding byte.
        myFile.read();
      }
    }
    myFile.close(); 

    /*
    for (int y=0;y<Height;y++)
     {
     for (int x=0;x<Width;x++)
     {
     if (FrameBuffer[y][x]<16)
     {
     //Pad the output with a leading zero.
     Serial.print("0");
     }
     Serial.print(FrameBuffer[y][x],HEX);
     Serial.print(",");
     }
     Serial.println();
     }
     */


  }
  else
  {
    Serial.print("Error opening file ");
    Serial.print(filePath);
    Serial.println(" for read.");
  }

  Serial.print("Done loading ");
  Serial.print(filePath);
  Serial.println(" bitmap pixels.");

}//End readBitmap method


I bit-blit the images using the following simple steps:

Code: [Select]
void loop(void) {

  if (millis()-starttime>100)
  {
    //Initialize our timer   
    starttime=millis();


    if (spriteDeployed==true)
    {
      //Erase the sprite by putting the background back.
      for (int y=0;y<32;y++)
      {
        for (int x=0;x<24;x++)
        {
          FrameBuffer[locationY+y][locationX+x]=background[y][x];
        }
      }
      spriteDeployed=false;
    }

    locationX=locationX+random(-5,6);
    if (locationX>320-24)
    {
      locationX=320-24;
    }
    if (locationX<0)
    {
      locationX=0;
    }

    locationY=locationY+random(-5,6);
    if (locationY>240-32)
    {
      locationY=240-32;
    }
    if (locationY<0)
    {
      locationY=0;
    }


    //Get the background for the new location
    for (int y=0;y<32;y++)
    {
      for (int x=0;x<24;x++)
      {
        background[y][x]=FrameBuffer[locationY+y][locationX+x];
      }
    }

    //Put Bit-Blit the sprite on the screen
    for (int y=0;y<32;y++)
    {
      for (int x=0;x<24;x++)
      {
        //The "And" (&=) operation allows for white background to be
        //transparent, and the black object to overwrite the background.
        FrameBuffer[locationY+y][locationX+x]&=Sprite[y][x];
       
        //The "Or" (|=) operation allows the whte background to remain
        //transparent, while overlaying the color object on the black area.
        FrameBuffer[locationY+y][locationX+x]|=SpriteMask[y][x];
      }
    }
    spriteDeployed=true;
  }

}//End loop


This all works, except there's a slight flicker to the display.  It's not bad, but bugs your eyes a little.  The pixels seem to shift slightly left and right as the screen refreshes.  It seems that the h-sync or v-sync timings must be off just slightly every once in a while.  Is that possible with the interrupts?  I'm trying to decide what to do to fix the image stability.  Any thoughts?
Title: Re: VGA output
Post by: stimmer on Apr 22, 2013, 03:39 am
Basically yes, the shimmering problem was caused by the interrupt not firing with exactly the same period each time, so each line is a random number of ticks late. What the mysterious piece of inline assembler at the start of the interrupt is trying to do is to synchronize the CPU with the timer. But it is not a good solution.

In the VGA library I tried a different solution. It uses two interrupts each line - the first puts the processor to sleep, so then when the second one fires it should be precisely on time. The display is much more steady (in most cases, rock steady). This broke the Serial support, but in the last few days I think I have made a breakthrough and got it working again. The other advantage to the VGA library is that it now uses DMA for the colour mode which is about 4x faster since the processor can continue to execute code while the screen is being displayed, plus the pixels are all the same width :)

Unfortunately I don't have standalone code of this approach as I had already turned the code into a library by then.
Title: Re: VGA output
Post by: graynomad on Apr 22, 2013, 04:42 am
@bensom
I see you have some BASIC source code displayed there, does that mean you have a BASIC interpreter running?

Does anybody have plans to port a BASIC interpreter?

______
Rob
Title: Re: VGA output
Post by: bensom on Apr 28, 2013, 04:07 am
@Graynomad Yes, it runs BASIC, a very limited version from the obfuscated C contests! http://www.youtube.com/watch?v=FRbr8ulNP5M (http://www.youtube.com/watch?v=FRbr8ulNP5M)

I was coding away on a bit more advanced version, parallel with a simple emulator running on windows but I got on to other things, so that is stalled at the moment. Don't know where to host that code, can send by mail or something if you like!

All inspired by the VGA lib thanks to @stimmer, great work! Just tried the PAL version on a little car DVD panel with medium succes. It shows very nice stable black and white, but lots of color fringe. I suspect my soldering, will try that again soon.
Also, doesn't composite video need a 75 ohm resistor to ground?

edit: Got the color working with an R 2R ladder made of 68 and 150 ohm resistors, looks much better now.
Title: Re: VGA output
Post by: stimmer on Apr 28, 2013, 01:00 pm
Composite video only needs the 75 ohm load resistor if the input to the TV is high impedance. Almost all TVs have a 75 ohm input impedance already so the load resistor isn't needed - the TV is the load :)

According to the data sheet there is a slight output resistance on the digital outs, you may find 82 ohm resistors work better than 68. Try it, it will either look better or worse. I did write a sketch to test how monotonic the DAC is - put a 75 ohm load resistor in place for this (doesn't have to be exactly 75 ohms) and connect the output to analog in 0:
Code: [Select]
// array runs lsb to msb, you can add/remove
// values according to the number of resistors
// in your DAC
char pins[]={34,35,36,37,38,39,40,41};

void writeval(int v){
  for(int i=0;i<sizeof(pins);i++){
    digitalWrite(pins[i],v&1);
    v>>=1;
  }
}

void setup() {
  Serial.begin(115200);
  analogReadResolution(12);
  for(int i=0;i<sizeof(pins);i++)
    pinMode(pins[i],OUTPUT);
}

void loop() {
  int l=0;
  for(int i=0;i<(1<<(sizeof(pins)));i++){
    writeval(i);
    delay(10);
    int m=analogRead(0);
    printf("%d : %d  d=%d\n",i,m,m-l);
    if(m<l)printf("!!!!!!ERROR!!!!!!!!!! non-monotonic\n");
    l=m;
  }
  delay(2000);
}


Because of the number of technical compromises that have to be made to get a colour composite signal at all, there will always be a lot of colour fringe. The output signal is way off spec in a number of areas. I aimed low with that project, the goal was VHS quality rather than broadcast quality ;)
Title: Re: VGA output
Post by: graynomad on Apr 28, 2013, 03:11 pm
Quote
a very limited version from the obfuscated C contests!

I hope you didn't have to work with the obfuscated source code.

I'm not personally interested in BASIC but it is very popular with many people and might be a way to convert Picaxe and Maximite users to Arduino.

The Maximite has a pretty good interpreter that was/is open source, maybe it's worth porting that across. For that matter there has to be 100s of interpreters around.

_____
Rob
Title: Re: VGA output
Post by: bensom on Apr 28, 2013, 08:11 pm
Rob, actually, I did de-obfuscate that interpreter, only to find the deobfuscated version when I was done, oh well. A sunday well spent. BASIC on the Due sure made my Apple][ days come back to me!
And yes, there are lots of BASIC interpreters to be found, sure one should fit the arduino due pretty well. I might continue on what I have, if it rains a lot this summer.

Stimmer, I did something similar, but looked at it with the scope, seems decently linear.
Code: [Select]

void setup() {
    pinMode(36,OUTPUT);    pinMode(37,OUTPUT);
    pinMode(38,OUTPUT);    pinMode(39,OUTPUT);
    pinMode(40,OUTPUT);    pinMode(41,OUTPUT);
    REG_PIOC_OWER = 0xFFFF;
}
int i=0;
void loop() { // C.4 - C.9
    REG_PIOC_ODSR = i<<4;
    if (++i>64) i=0;
}


I really like the VHS quality on this, 40 columns of text and all that! That space-age, Z80/6502 look :)
Will try with 82 ohm resistors, but unloaded the voltages seems pretty spot on, according to the composite video wiki page.
Title: Re: VGA output
Post by: beddy on Apr 30, 2013, 01:14 am
Hi everyone,

I have an idea but I not sure if it is possible. Let me to tell you... I imagine that on Arduino Due.

If I am using digital pin to control access to a RAM (address, data, ES and W/R pins ).
I could easier store data in this RAM.

With the VGA lib (modified) I'll enough time to get data from the RAM to built my bitmap or it's just a dream ?

Eddy

Title: Re: VGA output
Post by: graynomad on Apr 30, 2013, 01:26 am
Your first problem is that the Due doesn't really support the external memory function because they didn't break out all the pins. You can kludge something up but it's just that, a kludge, and I can't remember what (if any) limitations there are with that approach.

One of the guys has a thread about it on the forum here.

As for the timing I'm not sure, but as you can see it's working with internal RAM, external will be slower but I would think still fast enough.

One question is what will you do with all that RAM, it's not required for a text display or even a lo-res graphic display.

______
Rob


Title: Re: VGA output
Post by: beddy on Apr 30, 2013, 01:44 am
tks about your answer Graynomad,

Of course external RAM will be slower but may be enough to be just a bitmap.
If it's the case we could display a resolution better with more colors.
If you have a RAM you make a kind of double buffering.

About pins I read that Arduino Due have 54 digital I/O pin.
I don't know very well this product but I'm imaging :
10 pins for vga
8 pins for data RAM
and others for addressing RAM and control.



Title: Re: VGA output
Post by: graynomad on Apr 30, 2013, 01:58 am
Quote
8 pins for data RAM
and others for addressing RAM and control.


That's sort of correct BUT you have to have the right pins if you want real XM access, and the Arduino team did not see fit to provide them so you will have to dick with the board and solder wires in place.

You can of course bit bang the interface using any old pins but that will be incredibly slow in this context.

As I said though external RAM has been implemented by someone but I can't remember by who or where the post is.

IMO the Due as it stands is not an appropriate platform for hi-res VGA, but if you can properly implement XM it might be OK.

_____
Rob
Title: Re: VGA output
Post by: beddy on Apr 30, 2013, 02:07 am
ok tks

I found that

http://arduino.cc/forum/index.php/topic,20025.0.html
Title: Re: VGA output
Post by: graynomad on Apr 30, 2013, 04:17 am
That thread is about the Mega, an entirely different processor and as such of little use to you with a Due.

______
Rob
Title: Re: VGA output - put it on a 6.5" RGB automotive display!!
Post by: EarthMake on Dec 11, 2013, 10:23 pm
Stimmer,

Hats off for a job well done. I have a really cool sunlight readable Sharp 6.5" NTSC on my site at EarthMake for $69. It has an RGB input and NTSC timing. This means it should take a lot less bandwidth out of the due because ntsc is only 1.4318 MHz versus 25 MHz for vga. Check it out here:
http://earthmake.com/product/amt-002/
If it's something you want to play with email me at randy at earthlcd com and I'll get you one.

Randy

Title: Re: VGA output
Post by: stimmer on Dec 12, 2013, 02:01 am
Look at the VGA library thread (in my sig). NTSC is supported, but the bandwidth for NTSC is actually nearer 6MHz, so needs a sample frequency over 12MHz to generate (I use 14MHz). And as the VGA colour mode is half-resolution I use 14MHz for that too. So the bandwidth is the same, but as NTSC is a more complex signal it actually takes much more out of the Due, not less. (VGA can be done with DMA alone, but NTSC requires processing as well to do the mathematics).