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