crashtest-r0ket/firmware/applications/life.c

213 lines
4.7 KiB
C

#include <sysinit.h>
#include "basic/basic.h"
#include "lcd/backlight.h"
#include "lcd/render.h"
#include "lcd/display.h"
#include "lcd/allfonts.h"
#define BITSET_X (RESX+2)
#define BITSET_Y (RESY+2)
#define BITSET_SIZE (BITSET_X*BITSET_Y)
#include "cbitset.h"
typedef uint8_t uchar;
unsigned char rnd1();
void draw_rect(char x0, char y0, char x1, char y1) {
for(char x=x0; x<=x1; ++x) {
lcdSetPixel(x,y0,true);
lcdSetPixel(x,y1,true);
}
for(char y=y0+1; y<y1; ++y) {
lcdSetPixel(x0,y,true);
lcdSetPixel(x1,y,true);
}
}
void fill_rect(char x0, char y0, char x1, char y1) {
for(char x=x0; x<=x1; ++x) {
for(char y=y0; y<=y1; ++y) {
lcdSetPixel(x,y,true);
}
}
}
#define STARTVALUE 10
struct bitset _buf1,*buf1=&_buf1;
struct bitset _buf2,*buf2=&_buf2;
struct bitset *life =&_buf1;
struct bitset *new =&_buf2;
void swap_areas() {
struct bitset *tmp=life;
life=new;
new=tmp;
}
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) {
bitset_set2(area,x,y,value);
}
}
}
bool find_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) {
if(bitset_get2(area,x,y)==value) return true;
}
}
return false;
}
uint32_t sum_area(struct bitset *area, uchar x0, uchar y0, uchar x1, uchar y1) {
uint32_t sum=0;
for(uchar x=x0; x<=x1; ++x) {
for(uchar y=y0; y<=y1; ++y) {
sum+=bitset_get2(area,x,y);
}
}
return sum;
}
void draw_area() {
for(uchar x=0; x<RESX; ++x) {
for(uchar y=0; y<RESY; ++y) {
lcdSetPixel(x,y,lcdGetPixel(x,y)^bitset_get2(life,x+1,y+1));
}
}
}
void calc_area() {
#ifdef SIMULATOR
static unsigned long iter=0;
fprintf(stderr,"Iteration %d \n",++iter);
#endif
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)));
}
}
swap_areas();
}
int pattern=0;
#define PATTERNCOUNT 3
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;
case 1:
for(int i=0; i<RESX/2; ++i) bitset_set2(life,i,0,1);
bitset_set2(life,40,40,1);
bitset_set2(life,41,40,1);
bitset_set2(life,41,41,1);
break;
case 2:
bitset_set2(life,40,40,1);
bitset_set2(life,41,40,1);
bitset_set2(life,42,40,1);
bitset_set2(life,42,41,1);
bitset_set2(life,42,42,1);
bitset_set2(life,40,41,1);
bitset_set2(life,40,42,1);
break;
}
}
void random_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) {
bitset_set2(area,x,y,rnd1()<value);
}
}
}
#define LEDINTERVAL 1
uint8_t ledcycle=3;
void nextledcycle() {
ledcycle=(ledcycle+1)%(8*LEDINTERVAL);
uint8_t a=ledcycle/LEDINTERVAL;
switch(a) {
case 0: gpioSetValue (RB_LED0, CFG_LED_ON); break;
case 4: gpioSetValue (RB_LED0, CFG_LED_OFF); break;
case 1: gpioSetValue (RB_LED1, CFG_LED_ON); break;
case 5: gpioSetValue (RB_LED1, CFG_LED_OFF); break;
case 2: gpioSetValue (RB_LED2, CFG_LED_ON); break;
case 6: gpioSetValue (RB_LED2, CFG_LED_OFF); break;
case 3: gpioSetValue (RB_LED3, CFG_LED_ON); break;
case 7: gpioSetValue (RB_LED3, CFG_LED_OFF); break;
}
}
uchar stepmode=0;
uchar randdensity=0;
//uint8_t bl=0;
void main_life(void) {
backlightInit();
reset_area();
lcdFill(0);
font = &Font_Orbitron14pt;
DoString(20,20,"NICK");
gpioSetValue (RB_LED0, CFG_LED_ON);
gpioSetValue (RB_LED1, CFG_LED_ON);
gpioSetValue (RB_LED2, CFG_LED_ON);
gpioSetValue (RB_LED3, CFG_LED_ON);
while (1) {
// checkISP();
uint32_t button=(stepmode?getInputWait():getInput());
if(button!=BTN_ENTER) randdensity=0;
switch(button) {
case BTN_DOWN:
stepmode=1;
nextledcycle();
break;
case BTN_RIGHT:
stepmode=0;
break;
case BTN_LEFT:
reset_area();
break;
case BTN_ENTER:
randdensity+=8;
random_area(life,1,1,RESX,RESY,randdensity);
stepmode=1;
break;
case BTN_UP:
pattern=(pattern+1)%PATTERNCOUNT;
reset_area();
stepmode=1;
break;
}
// bl=(bl+1)%101;
// backlightSetBrightness(bl);
draw_area(); // xor life pattern over display content
lcdDisplay();
draw_area(); // xor life pattern again to restore original display content
lcdShift(1,-2,1);
delayms(10);
calc_area();
}
return;
}