/* (c) copyright N.C. 2011 */ // ATMEL ATMEGA8 // // +-\/-+ // (RESET) PC6 1| |28 PC5 (ADC5/SCL) // (RXD) PD0 2| |27 PC4 (ADC4/SDA) // (TXD) PD1 3| |26 PC3 (ADC3) // (INT0) PD2 4| |25 PC2 (ADC2) // (INT1) PD3 5| |24 PC1 (ADC1) // (XCK/T0) PD4 6| |23 PC0 (ADC0) // VCC 7| |22 GND // GND 8| |21 AREF // (XTAL1/TOSC1) PB6 9| |20 AVCC // (XTAL2/TOSC2) PB7 10| |19 PB5 (SCK) // (T1) PD5 11| |18 PB4 (MISO) // (AIN0) PD6 12| |17 PB3 (MOSI/OC2) // (AIN1) PD7 13| |16 PB2 (SS/OC1B) // (ICP1) PB0 14| |15 PB1 (OC1A) // +----+ extern "C" { #include #include #include // rand } //char myrand() //{ // static short rand = 0; // rand=(rand*109+89)%251; // return rand; //} int myrand() { return rand(); } #define CUBE_SIZE 8 //#define AXIS_X 1 //#define AXIS_Y 2 //#define AXIS_Z 3 volatile unsigned char cube[8][8]; //volatile unsigned char current_layer = 0; extern volatile unsigned char current_layer; volatile bool in_wait = false; volatile unsigned char fb[CUBE_SIZE][CUBE_SIZE]; /***************************************************************************** * TIME MANAGEMENT *****************************************************************************/ #define F_CPU 8000000UL #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) #define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) // the prescaler is set so that timer0 ticks every 64 clock cycles, and the // the overflow handler is called every 256 ticks. #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) // the whole number of milliseconds per timer0 overflow #define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) // the fractional number of milliseconds per timer0 overflow. we shift right // by three to fit these numbers into a byte. (for the clock speeds we care // about - 8 and 16 MHz - this doesn't lose precision.) #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) #define FRACT_MAX (1000 >> 3) //volatile uint32_t timer0_overflow_count = 0; volatile uint32_t timer0_millis = 0; //static uint8_t timer0_fract = 0; ISR(TIMER0_OVF_vect) { // copy these to local variables so they can be stored in registers // (volatile variables must be read from memory on every access) uint32_t m = timer0_millis; //uint8_t f = timer0_fract; static uint8_t timer0_fract = 0; m += MILLIS_INC; //f += FRACT_INC; timer0_fract += FRACT_INC; //if (f >= FRACT_MAX) { if (timer0_fract >= FRACT_MAX) { //f -= FRACT_MAX; timer0_fract -= FRACT_MAX; ++m; } //timer0_fract = f; timer0_millis = m; //timer0_overflow_count++; //static uint32_t last_time = 0; //if (timer0_overflow_count & 0x1) //if (m - last_time >= 5) { //debounce_keys(); // called nearly each 2ms (0,002048s) //last_time = m; //} } /* inline uint32_t millis() { uint32_t m; uint8_t oldSREG = SREG; // disable interrupts while we read timer0_millis or we might get an // inconsistent value (e.g. in the middle of a write to timer0_millis) cli(); m = timer0_millis; SREG = oldSREG; return m; } */ inline uint32_t millis() { return timer0_millis; } void delay(uint32_t ms) { in_wait = true; uint32_t time1 = millis(); while ((millis()) - time1 < ms); in_wait = false; } //void delay_ms(uint16_t x) //{ // in_wait = true; // uint8_t y, z; // for ( ; x > 0 ; x--){ // for ( y = 0 ; y < 90 ; y++){ // for ( z = 0 ; z < 6 ; z++){ // asm volatile ("nop"); // } // } // } // in_wait = false; //} /***************************************************************************** * 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 (unsigned char z = 0; z < 8; ++z) { for (unsigned char y = 0; y < 8; ++y) { cube[y][z] = 0; } } } /***************************************************************************** * RENDER *****************************************************************************/ //ISR(TIMER2_COMP_vect) //{ // //if (!in_wait) return; // PORTC &= ~0x28; // layer and latch low // unsigned 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*/) { // PORTC &= ~0x10; // //PORTD = (PORTD & ~0x80) | ((val2 << (7-i)) & 0x80); // PORTB = (PORTB & ~0x01) | ((val >> i) & 0x01); // //PORTB |= 0x01; // // //PORTD |= 0x80; // //PORTD = (PORTD & ~0x40) | (((val << (7-i)) & 0x80) >> 1); // PORTC |= 0x10; // } // } // // PORTC = (PORTC & ~0x07) | current_layer_; // ++current_layer_; // current_layer = current_layer_ & 0x07; // // PORTC |= 0x28; // layer and latch high //} ISR(TIMER2_COMP_vect) { //if (!in_wait) return; PORTC &= ~0x28; // layer and latch low unsigned char current_layer_ = current_layer; for (unsigned char j = 7; j < 255; --j) { //for (char j = 0; j < 4; ++j) { unsigned char val = cube[j][current_layer_]; PORTC &= ~0x10; PORTB = (PORTB & ~0x01) | ((val ) & 0x01); PORTC |= 0x10; PORTC &= ~0x10; PORTB = (PORTB & ~0x01) | ((val >> 1) & 0x01); PORTC |= 0x10; PORTC &= ~0x10; PORTB = (PORTB & ~0x01) | ((val >> 2) & 0x01); PORTC |= 0x10; PORTC &= ~0x10; PORTB = (PORTB & ~0x01) | ((val >> 3) & 0x01); PORTC |= 0x10; PORTC &= ~0x10; PORTB = (PORTB & ~0x01) | ((val >> 4) & 0x01); PORTC |= 0x10; PORTC &= ~0x10; PORTB = (PORTB & ~0x01) | ((val >> 5) & 0x01); PORTC |= 0x10; PORTC &= ~0x10; PORTB = (PORTB & ~0x01) | ((val >> 6) & 0x01); PORTC |= 0x10; PORTC &= ~0x10; PORTB = (PORTB & ~0x01) | ((val >> 7) & 0x01); //PORTD = val; PORTC |= 0x10; } PORTC = (PORTC & ~0x07) | current_layer_ | 0x28; ++current_layer_; if (current_layer_ > 7) current_layer_ = 0; //current_layer = current_layer_ & 0x07; current_layer = current_layer_; //PORTC |= 0x28; // layer and latch high } //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) // //setvoxel(x,y,p); // set_led(x, y, p, true); // // if (axis == AXIS_Y) // //setvoxel(x,p,y); // set_led(x,p,y, true); // // if (axis == AXIS_X) // set_led(p,y,x, true); // } // } // //} //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 = myrand()%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); // // } // //} /***************************************************************************** * MAIN *****************************************************************************/ #include "main.h" #include "effect.h" #include "draw.h" int main() { /* * ======================================================================= * Initialisation * ======================================================================= */ //*** init time management TCNT0 = 0; // init timer count to 0 TCCR0 |= 0x03; // prescaler: 64 TIMSK |= 0x01; // enable timer 0 overflow interrupt // Timer 2 // Frame buffer interrupt // 14745600/128/11 = 10472.72 interrupts per second // 10472.72/8 = 1309 frames per second OCR2 = 11; // interrupt at counter = 10 TCCR2 |= (1 << CS20) | (0 << CS21) | (1 << CS22); // Prescaler = 128. TCCR2 |= (1 << WGM21); // CTC mode. Reset counter when OCR2 is reached. TCNT2 = 0x00; // initial counter value = 0; TIMSK |= (1 << OCIE2); // Enable CTC interrupt PORTD = 0; PORTB = 0; PORTC = 0; DDRD = 0xff; DDRB = 0xff; DDRC = 0xff; //*** set interupts sei(); /* * ======================================================================= * MAIN LOOP * ======================================================================= */ for (;;) { //clear_led(); //delay_ms(1000); for (unsigned char z = 0; z < 8; ++z) { for (unsigned char y = 0; y < 8; ++y) { cube[y][z] = 0xFF; } } //continue; delay(1000); // Show the effects in a predefined order //for (char i=0; i