#include #include #include #include #include #include #include #define MAXHEIGHT 200 bool stop = false; uint8_t moduleToRun = 1; size_t image_size_profile(int profile, int width, int height) { size_t size = sizeof(bopti_image_t); if(profile == 0 || profile == 1) // PX_RGB565, PX_RGB565A size += width * height * 2; else if(profile == 2) // PX_P8 size += 512 + width * height; else if(profile == 3) // PX_P4 size += 32 + ((width + 1) / 2) * height; return size; } int get_pixel(bopti_image_t const *img, int x, int y) { if((unsigned)x >= img->width || (unsigned)y >= img->height) return 0; uint8_t *bytes = (void *)img->data; if(img->profile <= 1) return img->data[y * img->width + x]; if(img->profile == 2) return bytes[y * img->width + x + 512]; if(img->profile == 3) { int s = (img->width + 1) >> 1; int i = y * s + (x >> 1) + 32; if(x & 1) return bytes[i] & 0x0f; else return bytes[i] >> 4; } return 0; } void set_pixel(bopti_image_t *img, int x, int y, int color) { if((unsigned)x >= img->width || (unsigned)y >= img->height) return; uint8_t *bytes = (void *)img->data; if(img->profile <= 1) img->data[y * img->width + x] = color; else if(img->profile == 2) bytes[y * img->width + x + 512] = color; else if(img->profile == 3) { int s = (img->width + 1) >> 1; int i = y * s + (x >> 1) + 32; if(x & 1) bytes[i] = (bytes[i] & 0xf0) | (color & 0x0f); else bytes[i] = (bytes[i] & 0x0f) | ((color & 0x0f) << 4); } } bopti_image_t *screen; uint16_t palette[256]; size_t palette_size = 512; uint8_t imagedata[DWIDTH*MAXHEIGHT]; /********************************\ * PLASMA EFFECT - MODULE 1 * * Specific data and structures * \********************************/ static int aSin[512]; uint8_t index; static uint16_t pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0, tpos1, tpos2, tpos3, tpos4; uint16_t x; void init_module1( void ) { for(int i=0; i<64; ++i) { palette[i] = C_RGB( i<<2, 255 - ((i << 2) + 1), 0 ); palette[i+64] = C_RGB( 255, (i << 2) + 1, 0 ); palette[i+128] = C_RGB( 255 - ((i << 2) + 1), 255 - ((i << 2) + 1), 0 ); palette[i+192] = C_RGB( 0, (i << 2) + 1, 0 ); } memcpy(screen->data, palette, palette_size); for (int i = 0; i < 512; i++) { float rad = ((float)i * 0.703125) * 0.0174532; /* 360 / 512 * degree to rad, 360 degrees spread over 512 values to be able to use AND 512-1 instead of using modulo 360*/ aSin[i] = sin(rad) * 1024; /*using fixed point math with 1024 as base*/ } } void run_module1( void ) { uint8_t *image = imagedata; tpos4 = pos4; tpos3 = pos3; for (int i = 0; i < MAXHEIGHT; ++i) { tpos1 = pos1 + 5; tpos2 = pos2 + 3; tpos3 &= 511; tpos4 &= 511; for (int j = 0; j < DWIDTH; ++j) { tpos1 &= 511; tpos2 &= 511; x = aSin[tpos1] + aSin[tpos2] + aSin[tpos3] + aSin[tpos4]; /*actual plasma calculation*/ index = 128 + (x >> 4); /*fixed point multiplication but optimized so basically it says (x * (64 * 1024) / (1024 * 1024)), x is already multiplied by 1024*/ *image++ = index; tpos1 += 5; tpos2 += 3; } tpos4 += 3; tpos3 += 1; } void* pos = screen->data; pos+=palette_size; memcpy(pos, imagedata, DWIDTH*MAXHEIGHT); dimage(0,0,screen); pos1 +=9; pos3 +=8; } /********************************\ * BLOBS EFFECT - MODULE 2 * * Specific data and structures * \********************************/ #define BLOB_RADIUS 30 #define BLOB_DRADIUS (BLOB_RADIUS * 2) #define BLOB_SRADIUS (BLOB_RADIUS * BLOB_RADIUS) #define NUMBER_OF_BLOBS 30 //40 uint8_t blob[BLOB_DRADIUS][BLOB_DRADIUS]; typedef struct { uint16_t xpos,ypos; int8_t xdel,ydel; } BLOB; static BLOB blobs[NUMBER_OF_BLOBS]; void init_blob(BLOB *blob) { blob->xpos = rand() % DWIDTH; //(DWIDTH >> 1) - BLOB_RADIUS; blob->ypos = rand() % MAXHEIGHT; //(MAXHEIGHT >> 1) - BLOB_RADIUS; while(blob->xdel==0 && blob->ydel==0) { blob->xdel = -2+rand() % 5; blob->ydel = -2+rand() % 5; } } void init_module2( void ) { uint32_t distance_squared; float fraction; for (int i = 0; i < 32; ++i) { palette[i] = C_RGB( i, i, i); } memcpy(screen->data, palette, palette_size); for (int i = -BLOB_RADIUS; i < BLOB_RADIUS; ++i) { for (int j = -BLOB_RADIUS; j < BLOB_RADIUS; ++j) { distance_squared = i * i + j * j; if (distance_squared <= BLOB_SRADIUS) { fraction = (float)distance_squared / (float)BLOB_SRADIUS; blob[i + BLOB_RADIUS][j + BLOB_RADIUS] = pow((1.0 - (fraction * fraction)), 4.0) * 32.0; } else blob[i + BLOB_RADIUS][j + BLOB_RADIUS] = 0; } } for (int i = 0; i < NUMBER_OF_BLOBS; i++) init_blob(blobs + i); } void run_module2( void ) { uint8_t* image = imagedata; uint32_t start; //dma_memset(image, 0x01, DWIDTH*MAXHEIGHT); // set 1 to clear the screen as 0 is transparency for(int i=0; i 0 && blobs[k].xpos < DWIDTH - BLOB_DRADIUS && blobs[k].ypos > 0 && blobs[k].ypos < MAXHEIGHT - BLOB_DRADIUS) { start = blobs[k].xpos + blobs[k].ypos * DWIDTH; for (int i = 0; i < BLOB_DRADIUS; ++i) { for (int j = 0; j < BLOB_DRADIUS; ++j) { if (image[start + j] + blob[i][j] > 31) image[start + j] = 31; else image[start + j] += blob[i][j]; } start += DWIDTH; } } else init_blob(blobs + k); } void* pos = screen->data; pos+=palette_size; memcpy(pos, imagedata, DWIDTH*MAXHEIGHT); dimage(0,0,screen); } /********************************\ * LENS EFFECT - MODULE 3 * * Specific data and structures * \********************************/ #define LENS_WIDTH 120 #define LENS_ZOOM 20 extern bopti_image_t bglens; static uint32_t lens[LENS_WIDTH][LENS_WIDTH]; int x3 = 16, y3 = 16; int xd = 1, yd = 1; void init_module3( void ) { int i, x, y, r, d; r = LENS_WIDTH/2; d = LENS_ZOOM; for (y = 0; y < LENS_WIDTH >> 1; y++) { for (x = 0; x < LENS_WIDTH >> 1; x++) { int ix, iy, offset; if ((x * x + y * y) < (r * r)) { float shift = d/sqrt(d*d - (x*x + y*y - r*r)); ix = x * shift - x; iy = y * shift - y; } else { ix = 0; iy = 0; } offset = (iy * DWIDTH + ix); lens[LENS_WIDTH/2 - y][LENS_WIDTH/2 - x] = -offset; lens[LENS_WIDTH/2 + y][LENS_WIDTH/2 + x] = offset; offset = (-iy * DWIDTH + ix); lens[LENS_WIDTH/2 + y][LENS_WIDTH/2 - x] = -offset; lens[LENS_WIDTH/2 - y][LENS_WIDTH/2 + x] = offset; } } memcpy( screen->data, bglens.data, palette_size ); } void apply_lens(int ox, int oy) { uint8_t* image = imagedata; uint8_t* back = bglens.data; back+=palette_size; memcpy(image, back, DWIDTH*MAXHEIGHT); int x, y, temp, pos; for (y = 0; y < LENS_WIDTH; y++) { temp = (y + oy) * DWIDTH + ox; for (x = 0; x < LENS_WIDTH; x++) { pos = temp + x; image[pos] = back[pos + lens[y][x]]; } } } void run_module3() { //dimage(0,0, &bglens); apply_lens(x3, y3); /* shift the coordinates around */ x3 += xd; y3 += yd; if (x3 > (DWIDTH - LENS_WIDTH - 1) || x3 < 1) xd = -xd; if (y3 > (MAXHEIGHT - LENS_WIDTH - 1) || y3 < 1) yd = -yd; void* pos = screen->data; pos+=palette_size; memcpy(pos, imagedata, DWIDTH*MAXHEIGHT); dimage(0,0,screen); } /********************************\ * STARFIELD EFFECT - MODULE 4 * * Specific data and structures * \********************************/ #define NUMBER_OF_STARS 1024 typedef struct { float xpos, ypos; short zpos, speed; uint8_t color; } STAR; static STAR stars[NUMBER_OF_STARS]; uint16_t centerx, centery; void init_star(STAR* star, int i) { star->xpos = -10.0 + rand() % 21; star->ypos = -10.0 + rand() % 21; star->xpos *= 3072.0; star->ypos *= 3072.0; star->zpos = i; star->speed = 2 + rand() % 5; star->color = i >> 2; } void init_module4() { palette[0] = 0x0000; for (int i = 0; i < 255; ++i) { palette[i] = C_RGB( i, i, i); } memcpy(screen->data, palette, palette_size); for (int i = 0; i < NUMBER_OF_STARS; i++) { init_star(stars + i, i + 1); } } void run_module4() { uint8_t* image = imagedata; uint32_t start; int tempx, tempy; void* pos = screen->data; pos+=palette_size; centerx = DWIDTH >> 1; centery = MAXHEIGHT >> 1; //dma_memset(image, 0x01, DWIDTH*MAXHEIGHT); // set 1 to clear the screen as 0 is transparency for(int i=0; i DWIDTH || tempy < 1 || tempy > MAXHEIGHT ) { init_star(stars + i, i + 1); continue; } *((uint8_t*)imagedata + (tempy * DWIDTH) + tempx) = stars[i].color; } memcpy(pos, imagedata, DWIDTH*MAXHEIGHT); dimage(0,0,screen); } /********************************\ * RAINDROPS EFFECT - MODULE 5 * * Specific data and structures * \********************************/ extern bopti_image_t bglens2; static const int max_array = DWIDTH * MAXHEIGHT; static const short amplitudes[4] = { -250, -425, -350, -650}; static short wavemap[DWIDTH * MAXHEIGHT]; static short old_wavemap[DWIDTH * MAXHEIGHT]; static short *p_old = old_wavemap; static short *p_new = wavemap; short *address_new, *address_old, *temp; short height, xdiff; uint8_t *pscreen, *pimage; void init_module5() { for (int i = 0; i < max_array; ++i) { wavemap[i] = 0; old_wavemap[i] = 0; } } void start_drop() { uint32_t v,w; static const uint16_t b = DWIDTH - 10; static const uint16_t c = DWIDTH * 10; static const uint32_t d = (DWIDTH * MAXHEIGHT) - (DWIDTH * 10); static uint8_t amp_index = 0; /* borders are invalid so keep trying till valid value*/ do { v = rand() % max_array; w = v % DWIDTH; } while (w < 10 || w > b || v < c || v > d); wavemap[v] = amplitudes[amp_index++]; amp_index &= 4; } void run_module5() { uint16_t t; start_drop(); t = DWIDTH + 1; address_new = p_new + t; address_old = p_old + t; for (int i = 1; i < MAXHEIGHT - 1; ++i) { for (int j = 1; j < DWIDTH - 1; ++j) { height = 0; height += *(address_new + DWIDTH); height += *(address_new - 1); height += *(address_new + 1); height += *(address_new - DWIDTH); height >>= 1; height -= *address_old; height -= height >> 5; *address_old = height; address_new++; address_old++; } address_new += 2; /* next scanline starting at pos 1 */ address_old += 2; } t = DWIDTH + 1; address_old = p_old + t; pscreen = (uint8_t*)imagedata + t; pimage = (uint8_t*)bglens2.data + palette_size + t; /* draw waves */ for (int i = 1; i < MAXHEIGHT - 1; ++i) { for (int j = 1; j < DWIDTH - 1; ++j) { xdiff = *(address_old + 1) - *(address_old); *pscreen = *(pimage + xdiff); address_old++; pscreen++; pimage++; } address_old += 2; pscreen += 2; /* next scanline starting at pos 1 */ pimage += 2; } /* swap wave tables */ temp = p_new; p_new = p_old; p_old = temp; void* pos = screen->data; memcpy(pos, bglens2.data, palette_size); pos+=palette_size; memcpy(pos, imagedata, DWIDTH*MAXHEIGHT); dimage(0,0,screen); } /********************************\ * MATRIX EFFECT - MODULE 6 * * Specific data and structures * \********************************/ #define NUMBER_OF_STRIPS 80 #define CHAR_HEIGHT 14 #define CHAR_WIDTH 9 extern font_t matrix; typedef struct { int x; int y; int speed; int len; char str[32]; } STRIP; static STRIP strips[NUMBER_OF_STRIPS]; void init_strip(STRIP* strip ) { strip->len = 5 + rand() % 28; strip->x = rand() % 45; strip->y = -1*strip->len*CHAR_HEIGHT; strip->speed = 1+rand() % 5; for( int j=0; j< strips->len; j++ ) strip->str[j] = '!' + rand() % 96; } void init_module6() { for( int k=0; k< NUMBER_OF_STRIPS; k++) { init_strip(strips + k); } } void run_module6( void ) { for( int k=0; k< NUMBER_OF_STRIPS; k++) { strips[k].y += strips[k].speed; } dfont(&matrix); for( int k=0; k< NUMBER_OF_STRIPS; k++) { for( int j=0; j< strips[k].len; j++ ) if (strips[k].y - j*CHAR_HEIGHT<=200-CHAR_HEIGHT) { if(j==0) dprint( strips[k].x*CHAR_WIDTH, strips[k].y - j*CHAR_HEIGHT, C_WHITE, "%c", strips[k].str[j] ); else if(j==0) dprint( strips[k].x*CHAR_WIDTH, strips[k].y - j*CHAR_HEIGHT, C_RGB(150,255,150) , "%c", strips[k].str[j] ); else if(j==0) dprint( strips[k].x*CHAR_WIDTH, strips[k].y - j*CHAR_HEIGHT, C_RGB(50,255,50), "%c", strips[k].str[j] ); else dprint( strips[k].x*CHAR_WIDTH, strips[k].y - j*CHAR_HEIGHT, C_GREEN, "%c", strips[k].str[j] ); } if (strips[k].y - strips[k].len*CHAR_HEIGHT>200-CHAR_HEIGHT) init_strip( strips + k ); } } static void get_minimum_inputs( void ) { key_event_t ev; while((ev = pollevent()).type != KEYEV_NONE) { } if(keydown(KEY_EXIT)) stop=true; if(keydown(KEY_F1)) { init_module1(); moduleToRun = 1; } if(keydown(KEY_F2)) { init_module2(); moduleToRun = 2; } if(keydown(KEY_F3)) { init_module3(); moduleToRun = 3; } if(keydown(KEY_F4)) { init_module4(); moduleToRun = 4; } if(keydown(KEY_F5)) { init_module5(); moduleToRun = 5; } if(keydown(KEY_F6)) { init_module6(); moduleToRun = 6; } } int main(void) { srand( rtc_ticks() ); size_t size = image_size_profile( 2, DWIDTH, MAXHEIGHT); screen = malloc( size ); screen->profile = 2; screen->alpha = 0; screen->width = DWIDTH; screen->height = MAXHEIGHT; init_module1(); while(!stop) { dclear(C_BLACK); if (moduleToRun==1) run_module1(); else if (moduleToRun==2) run_module2(); else if (moduleToRun==3) run_module3(); else if (moduleToRun==4) run_module4(); else if (moduleToRun==5) run_module5(); else if (moduleToRun==6) run_module6(); dprint_opt(33, 212, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_CENTER, "PLASMA" ); dprint_opt(99, 212, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_CENTER, "BLOBS" ); dprint_opt(165, 212, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_CENTER, "LENS" ); dprint_opt(231, 212, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_CENTER, "STARS" ); dprint_opt(297, 212, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_CENTER, "RAIN" ); dprint_opt(363, 212, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_CENTER, "MATRIX" ); dupdate(); get_minimum_inputs(); } //free( screen ); return 1; }