VGA output

Mira-Gumowski Fractal nice colour example :slight_smile:

/* 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; }

}

Hopalong Orbit Fractal example :slight_smile:

/* 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; }

}

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

/* 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;
      }
    }
  }
           
}

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.

/* 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);
  }
           
}

Great news - SVGA 800x600x1bpp is possible :grin: Connections are the same as 640x480 above (Video out on SPI MOSI, VSync on pin 42 and HSync on pin 43)

/* 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);             
}

Hi Stimmer

800x600 is great work many thanks :slight_smile:

Kamil

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

SVGA Hopalong Orbit Fractal :slight_smile:

/* 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);
}

SVGA Three Ply Orbit Fractal :slight_smile:

/* 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);
}

JLS1:
Hi Stimmer

800x600 is great work many thanks :slight_smile:

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.

Thanks info

Kamil

SVGA Quadrup Two Orbit Fractal :slight_smile:

/* 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);
}

SVGA New Strange Attractor :slight_smile:

Update !

/* 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);
    
    }
}

SVGA Novel 4D chaotic attractor :slight_smile:

/* 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);
    
}

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 :slight_smile: 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.

duevga.png

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!

Wow, that looks like an amazing project! 8)

Must be 20 years at least since I last saw line numbers XD

amazing work people, keep it up - my inner nerd is swooning - i want more details on embedded basic and fractals and vga shields!! ;-D

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?

  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:

NVIC_EnableIRQ(TC0_IRQn);

(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.

I used the REG_PWM version, that works with serial!

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);
}