diff --git a/firmware/l0dable/nick_life.c b/firmware/l0dable/nick_life.c index b4d1382..50b47b7 100644 --- a/firmware/l0dable/nick_life.c +++ b/firmware/l0dable/nick_life.c @@ -28,22 +28,19 @@ typedef uint8_t uchar; int pattern=0; #define PATTERNCOUNT 3 +#define LCDSHIFT_EVERY_N 10 + uchar stepmode=0; uchar randdensity=0; -//uint8_t bl=0; - -struct bitset _buf1,*buf1=&_buf1; -struct bitset _buf2,*buf2=&_buf2; - -struct bitset *life =&_buf1; -struct bitset *new =&_buf2; +static unsigned long iter=0; +struct bitset _life; +#define life (&_life) static void draw_area(); static void calc_area(); static void random_area(struct bitset *area, uchar x0, uchar y0, uchar x1, uchar y1,uchar value); static void reset_area(); -static void nextledcycle(); void ram(void) { getInputWaitRelease(); @@ -54,19 +51,29 @@ void ram(void) { setExtFont(GLOBAL(nickfont)); DoString(20,20,GLOBAL(nickname)); -#if 0 - gpioSetValue (RB_LED0, CFG_LED_ON); - gpioSetValue (RB_LED1, CFG_LED_ON); - gpioSetValue (RB_LED2, CFG_LED_ON); - gpioSetValue (RB_LED3, CFG_LED_ON); -#endif + char stepmode=0; while (1) { draw_area(); // xor life pattern over display content lcdDisplay(); draw_area(); // xor life pattern again to restore original display content - lcdShift(1,-2,1); - if(getInputRaw()) - return; + if(iter%LCDSHIFT_EVERY_N==0) lcdShift(1,-2,1); + char key=stepmode?getInputWait():getInputRaw(); + stepmode=0; + switch(key) { + case BTN_LEFT: + return; + case BTN_DOWN: + stepmode=1; + getInputWaitRelease(); + break; + case BTN_ENTER: + pattern=(pattern+1)%PATTERNCOUNT; + case BTN_UP: + stepmode=1; + reset_area(); + getInputWaitRelease(); + break; + } delayms_queue_plus(10,0); calc_area(); } @@ -132,13 +139,6 @@ static void fill_rect(char x0, char y0, char x1, char y1) { } } -#define STARTVALUE 10 -static void swap_areas() { - struct bitset *tmp=life; - life=new; - new=tmp; -} - static void fill_area(struct bitset *area, uchar x0, uchar y0, uchar x1, uchar y1,uchar value) { for(uchar x=x0; x<=x1; ++x) { for(uchar y=y0; y<=y1; ++y) { @@ -174,50 +174,80 @@ static void draw_area() { } } +static void copy_col(uint8_t columnindex, uint8_t *columnbuffer) { + for(uchar y=0; y<=RESY+1; ++y) { + columnbuffer[y]=bitset_get2(life,columnindex,y); + } +} + static void calc_area() { + ++iter; #ifdef SIMULATOR - static unsigned long iter=0; - fprintf(stderr,"Iteration %d \n",++iter); + fprintf(stderr,"Iteration %d \n",iter); #endif + // sweeping mutation point + static uint8_t xiter=0; + static uint8_t yiter=0; + xiter=(xiter+1)%RESX; + if(xiter==0) yiter=(yiter+1)%RESY; + bitset_set2(life,xiter+1,yiter+1,1); + + // remember just two columns + // these donĀ“t have to be static, so if the stack is big enoguh put them there and save another 200 bytes? + static uint8_t _a[RESY+2],*left=_a; + static uint8_t _b[RESY+2],*middle=_b; + copy_col(0,left); + copy_col(1,middle); for(uchar x=1; x<=RESX; ++x) { for(uchar y=1; y<=RESY; ++y) { - uchar sum=sum_area(life,x-1,y-1,x+1,y+1)-bitset_get2(life,x,y); - bitset_set2(new,x,y,sum==3||(sum==2&&bitset_get2(life,x,y))); + uchar sum=bitset_get2(life,x+1,y-1)+bitset_get2(life,x+1,y)+bitset_get2(life,x+1,y+1)+ + left[y-1]+left[y]+left[y+1]+middle[y-1]+middle[y+1]; + bitset_set2(life,x,y,sum==3||(sum==2&&bitset_get2(life,x,y))); } + // temp-less swap of buffer pointers + left+=(uint32_t)middle; + middle=left-(uint32_t)middle; + left=left-(uint32_t)middle; + copy_col(x+1,middle); } - swap_areas(); } static void reset_area() { - fill_area(life,0,0,RESX+1,RESY+1,0); - fill_area(new,0,0,RESX+1,RESY+1,0); - - switch(pattern) { - case 0: - bitset_set2(life,41,40,1); - bitset_set2(life,42,40,1); - bitset_set2(life,41,41,1); - bitset_set2(life,40,41,1); - bitset_set2(life,41,42,1); - break; + fill_area(life,0,0,RESX+1,RESY+1,0); + + switch(pattern) { + case 0: // R pentomino + bitset_set2(life,41,40,1); + bitset_set2(life,42,40,1); + bitset_set2(life,41,41,1); + bitset_set2(life,40,41,1); + bitset_set2(life,41,42,1); + break; + case 1: // block in the center, continuous generators at the edges + for(int i=0; i