#include "effect.h" #include "font.h" #include #include #include #define CUBE_SIZE 8 #define CUBE_BYTES CUBE_SIZE*CUBE_SIZE #define AXIS_Z 2 #define AXIS_Y 1 #define AXIS_X 0 unsigned char leds[8][8]; volatile bool led_change = false; //unsigned char pow2[8] = { 1, 2, 4, 8, 16, 32, 64, 128 }; //const unsigned char pow2[8] = {128, 64, 32, 16, 8, 4, 2, 1}; /***************************************************************************** * ACCESSORS *****************************************************************************/ unsigned char inrange(int x, int y, int z) { if (x >= 0 && x < CUBE_SIZE && y >= 0 && y < CUBE_SIZE && z >= 0 && z < CUBE_SIZE) { return 1; } else { // One of the coordinates was outside the cube. return 0; } } bool get_led(unsigned char x, unsigned char y, unsigned char z) { /* assert(x >= 0 && x <= 7); assert(y >= 0 && y <= 7); assert(z >= 0 && z <= 7); */ if (inrange(x, y, z)) { return leds[y][z] & (1 << x); } return false; } void set_led(unsigned char x, unsigned char y, unsigned char z, bool on) { if (!inrange(x, y, z)) { return; } /* assert(x >= 0 && x <= 7); assert(y >= 0 && y <= 7); assert(z >= 0 && z <= 7); */ if (on) { leds[y][z] |= ((unsigned char)1) << x; } else { leds[y][z] &= ~(((unsigned char)1) << x); } } void clear_led() { memset(leds, 0, sizeof(leds)); } void set_voxel(int x, int y, int z) { set_led(x, y, z, true); } void clr_voxel(int x, int y, int z) { set_led(x, y, z, false); } void fill(char val) { memset(leds, val, sizeof(leds)); } void delay(unsigned t) { led_change = true; SDL_Delay(t); } /***************************************************************************** * EFFECTS *****************************************************************************/ void test_effect() { static int active_layer = 0; for (int k = 0; k < 8; ++k) { //std::cout << "boo" << std::endl; for (int j = 0; j < 8; ++j) { //std::cout << "boo2" << std::endl; if (k == active_layer) { //std::cerr << "active" << std::endl; leds[j][k] = 0xFF; } else leds[j][k] = 0; } } ++active_layer; if (active_layer >= 8) { active_layer = 0; } } void sendvoxels_z(int x, int y, int z, int delay) { assert(z == 0 || z == 7); if (z == 7) { for (int i = 0; i < 7; ++i) { set_led(x, y, i, false); set_led(x, y, i+1, true); led_change = true; SDL_Delay(delay); } } else { for(int i = 6; i >= 0; --i) { set_led(x, y, i + 1, false); set_led(x, y, i, true); led_change = true; SDL_Delay(delay); } } } void sendvoxels_random_z_effect(int maxiters, int delay, /* speed of movement */ int wait) /* delay between 2 movement */ { clear_led(); // clear the cube for (int j = 0; j < 8; ++j) { for (int i = 0; i < 8; ++i) { if (rand()%2) { set_led(i, j, 0, true); } else { set_led(i, j, 7, true); } } } int previous_x = 0, previous_y = 0; for (int n = 0; n < maxiters ; ++n ) { int x = rand()%8, y = rand()%8; if (previous_x == x && previous_y == y) { --n; continue; } if (get_led(x, y, 0)) { sendvoxels_z(x, y, 7, delay); } else if (get_led(x, y, 7)) { sendvoxels_z(x, y, 0, delay); } SDL_Delay(wait); } } void rain_effect(int iterations) { for (int i = 0; i < iterations ; ++i) { // clear layer 7 for (int j = 0 ; j < 8; ++j) { leds[j][7] = 0; } // place pixels at random x and y coord at layer 7 int n = rand()%4; for (int i2 = 0; i2 < n; ++i2) { set_led(rand()%8, rand()%8, 7, 1); } led_change = true; SDL_Delay(90); // shift down for (int k = 0; k < 7; ++k) { for (int j = 0 ; j < 8; ++j) { leds[j][k] = leds[j][k+1]; } } } } void set_plane(int axis, unsigned char index, bool on = true) { switch(axis) { case 0: // X for (int k = 0; k < 8; ++k) { for (int j = 0; j < 8; ++j) { set_led(index, j, k, on); } } break; case 1: // Y for (int k = 0; k < 8; ++k) { for (int i = 0; i < 8; ++i) { set_led(i, index, k, on); } } break; case 2: // Z for (int j = 0; j < 8; ++j) { for (int i = 0; i < 8; ++i) { set_led(i, j, index, on); } } break; default: assert(false); } } void planboing(int plane, int speed) { for (int i = 0; i < 8; ++i) { clear_led(); // clear cube set_plane(plane, i); led_change = true; SDL_Delay(speed); } for (int i = 7; i >= 0; --i) { clear_led(); // clear cube set_plane(plane, i); led_change = true; SDL_Delay(speed); } } // Shift the entire contents of the cube along an axis // This is great for effects where you want to draw something // on one side of the cube and have it flow towards the other // side. Like rain flowing down the Z axiz. void shift (char axis, int direction) { int i, x ,y; int ii, iii; //int state; for (i = 0; i < CUBE_SIZE; i++) { if (direction == -1) { ii = i; } else { ii = (7-i); } for (x = 0; x < CUBE_SIZE; x++) { for (y = 0; y < CUBE_SIZE; y++) { if (direction == -1) { iii = ii+1; } else { iii = ii-1; } if (axis == 2) { set_led(x, y, ii, get_led(x, y, iii)); //state = get_led(x,y,iii); //set_led(x,y,ii,state?false:true); } if (axis == 1) { set_led(x, ii, y, get_led(x, iii, y)); //state = get_led(x,iii,y); //altervoxel(x,ii,y,state); //set_led(x,ii,y,state?false:true); } if (axis == 0) { set_led(ii, y, x, get_led(iii, y, x)); //state = get_led(iii,y,x); //set_led(ii,y,x,state?false:true); } } } } if (direction == -1) { i = 7; } else { i = 0; } /* for (x = 0; x < CUBE_SIZE; x++) { for (y = 0; y < CUBE_SIZE; y++) { if (axis == AXIS_Z) set_led(x,y,i, false); if (axis == AXIS_Y) set_led(x,i,y, false); if (axis == AXIS_X) set_led(i,y,x, false); } } */ set_plane(axis, i, false); } // Flips a byte 180 degrees. // MSB becomes LSB, LSB becomes MSB. char flipbyte (char byte) { char flop = 0x00; flop = (flop & 0b11111110) | (0b00000001 & (byte >> 7)); flop = (flop & 0b11111101) | (0b00000010 & (byte >> 5)); flop = (flop & 0b11111011) | (0b00000100 & (byte >> 3)); flop = (flop & 0b11110111) | (0b00001000 & (byte >> 1)); flop = (flop & 0b11101111) | (0b00010000 & (byte << 1)); flop = (flop & 0b11011111) | (0b00100000 & (byte << 3)); flop = (flop & 0b10111111) | (0b01000000 & (byte << 5)); flop = (flop & 0b01111111) | (0b10000000 & (byte << 7)); return flop; } // Flip the cube 180 degrees along the y axis. void mirror_y (void) { unsigned char buffer[CUBE_SIZE][CUBE_SIZE]; unsigned char x,y,z; memcpy(buffer, leds, CUBE_BYTES); // copy the current cube into a buffer. //fill(0x00); clear_led(); for (z=0; zix2) { int tmp; tmp = ix1; ix1= ix2; ix2 = tmp; } *ox1 = ix1; *ox2 = ix2; } // Returns a byte with a row of 1's drawn in it. // byteline(2,5) gives 0b00111100 char byteline (int start, int end) { return ((0xff< 7 ? it2 - 8: 7 - it2; clear_led(); box_wireframe(0, 0, 0, xyz, xyz, xyz); if (flip > 0) mirror_z(); if (rot == 1 || rot == 3) mirror_y(); if (rot == 2 || rot == 3) mirror_x(); led_change = true; SDL_Delay(delay); } } } void effect_box_woopwoop (int delay, int grow) { int i,ii; //fill(0x00); clear_led(); for (i=0;i<4;i++) { ii = i; if (grow > 0) ii = 3-i; box_wireframe(4+ii,4+ii,4+ii,3-ii,3-ii,3-ii); led_change = true; SDL_Delay(delay); clear_led(); //delay_ms(delay); //fill(0x00); } } void draw_positions_axis (char axis, unsigned char positions[64], int invert) { int x, y, p; //fill(0x00); clear_led(); for (x=0; x<8; x++) { for (y=0; y<8; y++) { if (invert) { p = (7-positions[(x*8)+y]); } else { p = positions[(x*8)+y]; } //if (axis == AXIS_Z) if (axis == 2) set_led(x,y,p, true); if (axis == 1) set_led(x,p,y, true); if (axis == 0) set_led(p,y,x, true); } } } void effect_axis_updown_randsuspend(char axis, int delay, int sleep, int invert) { unsigned char positions[64]; unsigned char destinations[64]; int i,px; // Set 64 random positions for (i=0; i<64; i++) { positions[i] = 0; // Set all starting positions to 0 destinations[i] = rand()%8; } // Loop 8 times to allow destination 7 to reach all the way for (i=0; i<8; i++) { // For every iteration, move all position one step closer to their destination for (px=0; px<64; px++) { if (positions[px]destinations[px]) { positions[px]--; } } draw_positions_axis (axis, positions,invert); led_change = true; SDL_Delay(delay); //delay_ms(delay); } } void effect_stringfly2(const char* str) { //int x,y,i; unsigned char x,y,i; unsigned char chr[5]; int delay = 80; clear_led(); while (*str) { font_getchar(*str++, chr); // Put a character on the back of the cube for (x = 0; x < 5; x++) { for (y = 0; y < 8; y++) { if ((chr[x] & (0x80>>y))) { //setvoxel(7,x+2,y); //set_led(7,x+2,y); set_led(x+2, 7, y); } } } //led_change = true; //SDL_Delay(1000); //clear_led(); //continue; // Shift the entire contents of the cube forward by 6 steps // before placing the next character for (i = 0; i<6; i++) { led_change = true; //delay_ms(1000); //SDL_Delay(1000); SDL_Delay(delay); //shift(AXIS_X,-1); shift(1,-1); //set_plane(1, 7, false); } } //return; // Shift the last character out of the cube. for (i = 0; i<8; i++) { led_change = true; SDL_Delay(delay); //delay_ms(1000); //shift(AXIS_X,-1); shift(1,-1); } } float distance2d (float x1, float y1, float x2, float y2) { float dist; dist = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); return dist; } float distance3d (float x1, float y1, float z1, float x2, float y2, float z2) { float dist; dist = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2)); return dist; } // Display a sine wave running out from the center of the cube. void ripples (int iterations, int delay) { float distance, height, ripple_interval; int x,y,i; clear_led(); //fill(0x00); for (i=0;i