SVGA Three Ply Orbit Fractal
/* 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)®_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);
}