/* (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 #include "main.h" #include "effect.h" #include "launch_effect.h" //#include "draw.h" } //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 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); 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; PORTD &= ~0x20; // layer and latch low unsigned char current_layer_ = current_layer; for (unsigned char j = 0; j < 8; ++j) { //for (char j = 0; j < 4; ++j) { unsigned char val = cube[j][current_layer_]; PORTD &= ~0x10; PORTC = val; PORTD = (PORTD & ~0xC0) | (val & 0xC0); PORTD |= 0x10; } PORTB = (PORTB & ~0x07) | current_layer_; PORTD |= 0x20; ++current_layer_; current_layer = current_layer_ & 0x07; //if (current_layer_ > 7) current_layer_ = 0; //current_layer = current_layer_; //PORTC |= 0x28; // layer and latch high } void tmp2cube (void); // Take input from a computer and load it onto the cube buffer void rs232(void) { int tempval; int x = 0; int y = 0; int escape = 0; while (1) { // Switch state on red LED for debugging // Should switch state every time the code // is waiting for a byte to be received. //LED_PORT ^= LED_RED; // Wait until a byte has been received while ( !(UCSRA & (1<> 8; //UBRRL = BAUD_PRESCALE; //// UCSRC - USART control register //// bit 7-6 sync/ascyn 00 = async, 01 = sync //// bit 5-4 parity 00 = disabled //// bit 3 stop bits 0 = 1 bit 1 = 2 bits //// bit 2-1 frame length 11 = 8 //// bit 0 clock polarity = 0 ////UCSRC = 0b10000110; //// Enable RS232, tx and rx //UCSRB = (1<>8); UBRRL = (uint8_t)(BAUD_PRESCALLER); UCSRC = (1<