#include "WProgram.h" #line 1 "test.pde" // On the Arduino board, digital pins are also used // for the analog output (software PWM). Analog input // pins are a separate set. // ATMEL ATMEGA8 & 168 / ARDUINO // // +-\/-+ // PC6 1| |28 PC5 (AI 5) // (D 0) PD0 2| |27 PC4 (AI 4) // (D 1) PD1 3| |26 PC3 (AI 3) // (D 2) PD2 4| |25 PC2 (AI 2) // PWM+ (D 3) PD3 5| |24 PC1 (AI 1) // (D 4) PD4 6| |23 PC0 (AI 0) // VCC 7| |22 GND // GND 8| |21 AREF // PB6 9| |20 AVCC // PB7 10| |19 PB5 (D 13) // PWM+ (D 5) PD5 11| |18 PB4 (D 12) // PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM // (D 7) PD7 13| |16 PB2 (D 10) PWM // (D 8) PB0 14| |15 PB1 (D 9) PWM // +----+ // // (PWM+ indicates the additional PWM pins on the ATmega168.) #define CUBE_SIZE 8 #define AXIS_X 1 #define AXIS_Y 2 #define AXIS_Z 3 void setup() { Serial.begin(9600); delay(1000); Serial.println("begin"); DDRB = 0xFF; DDRD = 0xFC; PORTB = 0; PORTD &= 0x03; // Reset any PWM configuration that the arduino may have set up automagically! TCCR2A = 0x00; TCCR2B = 0x00; TCCR2A |= (0x01 << WGM21); // CTC mode. clear counter on TCNT2 == OCR2A OCR2A = 50; // Interrupt every 25600th cpu cycle (256*100) TCNT2 = 0x00; // start counting at 0 TCCR2B |= (0x01 << CS22) | (0x01 << CS21); // Start the clock with a 256 prescaler TIMSK2 |= (0x01 << OCIE2A); } volatile unsigned char cube[8][8]; volatile unsigned char current_layer = 0; ISR (TIMER2_COMPA_vect) { PORTB &= ~0x21; // layer and latch low char current_layer_ = current_layer; //for (char j = 0; j < 8; ++j) { for (char j = 0; j < 4; ++j) { unsigned char val = cube[7-j][current_layer_]; unsigned char val2 = cube[3-j][current_layer_]; for (char i = 0; i < 8; ++i/*, val >>= 1*/) { PORTB &= ~0x02; PORTD = (PORTD & ~0x80) | ((val2 << (7-i)) & 0x80); //PORTD |= 0x80; PORTD = (PORTD & ~0x40) | (((val << (7-i)) & 0x80) >> 1); PORTB |= 0x02; } } PORTB = (PORTB & ~0x1C) | (current_layer_ << 2); ++current_layer_; current_layer = current_layer_ & 0x07; PORTB |= 0x21; // layer and latch high } /***************************************************************************** * 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 cube[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) { cube[y][z] |= ((unsigned char)1) << x; } else { cube[y][z] &= ~(((unsigned char)1) << x); } } void clear_led() { for (char z = 0; z < 8; ++z) { for (char y = 0; y < 8; ++y) { cube[y][z] = 0; } } } // Set a single voxel to ON void setvoxel(int x, int y, int z) { if (inrange(x,y,z)) cube[y][z] |= (1 << x); } unsigned char getvoxel(int x, int y, int z) { if (inrange(x,y,z)) { if (cube[y][z] & (1 << x)) { return 0x01; } else { return 0x00; } } else { return 0x00; } } // Set a single voxel to ON void clrvoxel(int x, int y, int z) { if (inrange(x,y,z)) cube[y][z] &= ~(1 << x); } // In some effect we want to just take bool and write it to a voxel // this function calls the apropriate voxel manipulation function. void altervoxel(int x, int y, int z, int state) { if (state == 1) { setvoxel(x,y,z); } else { clrvoxel(x,y,z); } } // 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 < 8; i++) { if (direction == -1) { ii = i; } else { ii = (7-i); } for (x = 0; x < 8; x++) { for (y = 0; y < 8; y++) { if (direction == -1) { iii = ii+1; } else { iii = ii-1; } if (axis == AXIS_Z) { state = getvoxel(x,y,iii); altervoxel(x,y,ii,state); } if (axis == AXIS_Y) { state = getvoxel(x,iii,y); altervoxel(x,ii,y,state); } if (axis == AXIS_X) { state = getvoxel(iii,y,x); altervoxel(ii,y,x,state); } } } } if (direction == -1) { i = 7; } else { i = 0; } for (x = 0; x < 8; x++) { for (y = 0; y < 8; y++) { if (axis == AXIS_Z) clrvoxel(x,y,i); if (axis == AXIS_Y) clrvoxel(x,i,y); if (axis == AXIS_X) clrvoxel(i,y,x); } } } // Delay loop. // This is not calibrated to milliseconds, // but we had allready made to many effects using this // calibration when we figured it might be a good idea // to calibrate it. void delay_ms(uint16_t x) { uint8_t y, z; for ( ; x > 0 ; x--){ for ( y = 0 ; y < 90 ; y++){ for ( z = 0 ; z < 6 ; z++){ asm volatile ("nop"); } } } } void effect_rain (int iterations) { int i, ii; int rnd_x; int rnd_y; int rnd_num; for (ii=0;ii? 0x32,0x49,0x79,0x41,0x3e,0x7e,0x11,0x11,0x11,0x7e, // @A 0x7f,0x49,0x49,0x49,0x36,0x3e,0x41,0x41,0x41,0x22, // BC 0x7f,0x41,0x41,0x22,0x1c,0x7f,0x49,0x49,0x49,0x41, // DE 0x7f,0x09,0x09,0x09,0x01,0x3e,0x41,0x49,0x49,0x7a, // FG 0x7f,0x08,0x08,0x08,0x7f,0x00,0x41,0x7f,0x41,0x00, // HI 0x20,0x40,0x41,0x3f,0x01,0x7f,0x08,0x14,0x22,0x41, // JK 0x7f,0x40,0x40,0x40,0x40,0x7f,0x02,0x0c,0x02,0x7f, // LM 0x7f,0x04,0x08,0x10,0x7f,0x3e,0x41,0x41,0x41,0x3e, // NO 0x7f,0x09,0x09,0x09,0x06,0x3e,0x41,0x51,0x21,0x5e, // PQ 0x7f,0x09,0x19,0x29,0x46,0x46,0x49,0x49,0x49,0x31, // RS 0x01,0x01,0x7f,0x01,0x01,0x3f,0x40,0x40,0x40,0x3f, // TU 0x1f,0x20,0x40,0x20,0x1f,0x3f,0x40,0x38,0x40,0x3f, // VW 0x63,0x14,0x08,0x14,0x63,0x07,0x08,0x70,0x08,0x07, // XY 0x61,0x51,0x49,0x45,0x43,0x00,0x7f,0x41,0x41,0x00, // Z[ 0x02,0x04,0x08,0x10,0x20,0x00,0x41,0x41,0x7f,0x00, // \] 0x04,0x02,0x01,0x02,0x04,0x40,0x40,0x40,0x40,0x40, // ^_ 0x00,0x01,0x02,0x04,0x00,0x20,0x54,0x54,0x54,0x78, // `a 0x7f,0x48,0x44,0x44,0x38,0x38,0x44,0x44,0x44,0x20, // bc 0x38,0x44,0x44,0x48,0x7f,0x38,0x54,0x54,0x54,0x18, // de 0x08,0x7e,0x09,0x01,0x02,0x0c,0x52,0x52,0x52,0x3e, // fg 0x7f,0x08,0x04,0x04,0x78,0x00,0x44,0x7d,0x40,0x00, // hi 0x20,0x40,0x44,0x3d,0x00,0x7f,0x10,0x28,0x44,0x00, // jk 0x00,0x41,0x7f,0x40,0x00,0x7c,0x04,0x18,0x04,0x78, // lm 0x7c,0x08,0x04,0x04,0x78,0x38,0x44,0x44,0x44,0x38, // no 0x7c,0x14,0x14,0x14,0x08,0x08,0x14,0x14,0x18,0x7c, // pq 0x7c,0x08,0x04,0x04,0x08,0x48,0x54,0x54,0x54,0x20, // rs 0x04,0x3f,0x44,0x40,0x20,0x3c,0x40,0x40,0x20,0x7c, // tu 0x1c,0x20,0x40,0x20,0x1c,0x3c,0x40,0x30,0x40,0x3c, // vw 0x44,0x28,0x10,0x28,0x44,0x0c,0x50,0x50,0x50,0x3c, // xy 0x44,0x64,0x54,0x4c,0x44 // z }; volatile const unsigned char bitmaps[6][8] /*EEMEM*/ = { {0xc3,0xc3,0x00,0x18,0x18,0x81,0xff,0x7e}, // smiley 3 small {0x3c,0x42,0x81,0x81,0xc3,0x24,0xa5,0xe7}, // Omega {0x00,0x04,0x06,0xff,0xff,0x06,0x04,0x00}, // Arrow {0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81}, // X {0xBD,0xA1,0xA1,0xB9,0xA1,0xA1,0xA1,0x00}, // ifi {0xEF,0x48,0x4B,0x49,0x4F,0x00,0x00,0x00} // TG }; const unsigned char paths[44] /*PROGMEM */= {0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x67,0x57,0x47,0x37,0x27,0x17, 0x04,0x03,0x12,0x21,0x30,0x40,0x51,0x62,0x73,0x74,0x65,0x56,0x47,0x37,0x26,0x15}; // circle, len 16, offset 28 /* void font_getpath (unsigned char path, unsigned char *destination, int length) { int i; int offset = 0; if (path == 1) offset=28; for (i = 0; i < length; i++) destination[i] = pgm_read_byte(&paths[i+offset]); } */ // Fill a value into all 64 byts of the cube buffer // Mostly used for clearing. fill(0x00) // or setting all on. fill(0xff) void fill (unsigned char pattern) { int z; int y; for (z=0;z<8;z++) { for (y=0;y<8;y++) { cube[z][y] = pattern; } } } void font_getchar (char chr, unsigned char dst[5]) { //uint8_t i; unsigned char i; chr -= 32; // our bitmap font starts at ascii char 32. for (i = 0; i < 5; i++) //dst[i] = (unsigned char)eeprom_read_byte((uint8_t*)&font[(chr*5)+i]); dst[i] = font[(chr*5)+i]; } void effect_stringfly2(const char* str) { //int x,y,i; unsigned char x,y,i; unsigned char chr[5]; const 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, 0, y, true); } } } //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++) { //delay_ms(1000); //SDL_Delay(1000); delay(DELAY); shift(AXIS_Y,1); //shift(1,-1); //set_plane(1, 7, false); } } //return; // Shift the last character out of the cube. for (i = 0; i<8; i++) { delay(DELAY); //delay_ms(1000); shift(AXIS_Y,1); //shift(1,-1); } } // Sets all voxels along a X/Y plane at a given point // on axis Z void setplane_z (int z) { int i; if (z>=0 && z<8) { for (i=0;i<8;i++) cube[z][i] = 0xff; } } // Clears voxels in the same manner as above void clrplane_z (int z) { int i; if (z>=0 && z<8) { for (i=0;i<8;i++) cube[z][i] = 0x00; } } void setplane_x (int x) { int z; int y; if (x>=0 && x<8) { for (z=0;z<8;z++) { for (y=0;y<8;y++) { cube[z][y] |= (1 << x); } } } } void clrplane_x (int x) { int z; int y; if (x>=0 && x<8) { for (z=0;z<8;z++) { for (y=0;y<8;y++) { cube[z][y] &= ~(1 << x); } } } } void setplane_y (int y) { int z; if (y>=0 && y<8) { for (z=0;z<8;z++) cube[z][y] = 0xff; } } void clrplane_y (int y) { int z; if (y>=0 && y<8) { for (z=0;z<8;z++) cube[z][y] = 0x00; } } void setplane (char axis, unsigned char i) { switch (axis) { case AXIS_X: setplane_x(i); break; case AXIS_Y: setplane_y(i); break; case AXIS_Z: setplane_z(i); break; } } // Draw a plane on one axis and send it back and forth once. void effect_planboing (int plane, int speed) { int i; for (i=0;i<8;i++) { fill(0x00); setplane(plane, i); delay_ms(speed); } for (i=7;i>=0;i--) { fill(0x00); setplane(plane,i); delay_ms(speed); } } void effect_blinky2() { int i,r; fill(0x00); for (r=0;r<2;r++) { i = 750; while (i>0) { fill(0x00); delay(i/5); fill(0xff); delay(20); i = i - (15+(1000/(i/10))); } delay(500); i = 750; while (i>0) { fill(0x00); delay((751-i)/5); fill(0xff); delay(20); i = i - (15+(1000/(i/10))); } } } // Set or clear exactly 512 voxels in a random order. void effect_random_filler (int delay, int state) { int x,y,z; int loop = 0; if (state == 1) { fill(0x00); } else { fill(0xff); } while (loop<511) { x = rand()%8; y = rand()%8; z = rand()%8; if ((state == 0 && getvoxel(x,y,z) == 0x01) || (state == 1 && getvoxel(x,y,z) == 0x00)) { altervoxel(x,y,z,state); delay_ms(delay); loop++; } } } void draw_positions_axis (char axis, unsigned char positions[64], int invert) { int x, y, p; fill(0x00); 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) setvoxel(x,y,p); if (axis == AXIS_Y) setvoxel(x,p,y); if (axis == AXIS_X) setvoxel(p,y,x); } } } void effect_boxside_randsend_parallel (char axis, int origin, int delay, int mode) { int i; int done; unsigned char cubepos[64]; unsigned char pos[64]; int notdone = 1; int notdone2 = 1; int sent = 0; for (i=0;i<64;i++) { pos[i] = 0; } while (notdone) { if (mode == 1) { notdone2 = 1; while (notdone2 && sent<64) { i = rand()%64; if (pos[i] == 0) { sent++; pos[i] += 1; notdone2 = 0; } } } else if (mode == 2) { if (sent<64) { pos[sent] += 1; sent++; } } done = 0; for (i=0;i<64;i++) { if (pos[i] > 0 && pos[i] <7) { pos[i] += 1; } if (pos[i] == 7) done++; } if (done == 64) notdone = 0; for (i=0;i<64;i++) { if (origin == 0) { cubepos[i] = pos[i]; } else { cubepos[i] = (7-pos[i]); } } delay_ms(delay); draw_positions_axis(axis,cubepos,0); } } /***************************************************************************** * LOOP TEST *****************************************************************************/ void loop() { //for (char i = 0; i < 8; ++i) { //PORTB = (PORTB & ~0x1C) | ((i & 0x07) << 2); //display(i); //delay(2); //Serial.println(layer, DEC); //delay(1000); //} clear_led(); //delay_ms(1000); delay(1000); //return; for (char z = 0; z < 8; ++z) { for (char y = 0; y < 8; ++y) { for (char x = 0; x < 8; ++x) { set_led(x, y, z, true); delay(5); delay(100); //delay(500); //delay(1000); //delay_ms(1000); } } } delay(1000); //delay_ms(1000); clear_led(); /* effect_stringfly2("test de texte - c'est trop super genial et tout " "yeahhh!!!!!"); */ effect_planboing(AXIS_Z, 700); effect_planboing(AXIS_Y, 700); effect_planboing(AXIS_X, 700); effect_blinky2(); effect_random_filler(75,1); effect_random_filler(75,0); for (char i = 0; i < 10; ++i) { effect_boxside_randsend_parallel (AXIS_X, 0, 950, 2); effect_boxside_randsend_parallel (AXIS_X, 1, 950, 2); effect_boxside_randsend_parallel (AXIS_Y, 0, 950, 2); effect_boxside_randsend_parallel (AXIS_Y, 1, 950, 2); effect_boxside_randsend_parallel (AXIS_Z, 0, 950, 2); effect_boxside_randsend_parallel (AXIS_Z, 1, 950, 2); } //effect_rain(1000) } #line 1 "ardmake/hardware/cores/arduino/main.cxx" int main(void) { init(); setup(); for (;;) loop(); return 0; }