diff options
Diffstat (limited to 'avr-test2/src/main.cpp')
-rw-r--r-- | avr-test2/src/main.cpp | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/avr-test2/src/main.cpp b/avr-test2/src/main.cpp new file mode 100644 index 0000000..dfebb37 --- /dev/null +++ b/avr-test2/src/main.cpp @@ -0,0 +1,450 @@ +/* (c) copyright N.C. 2011 + * vim: ts=2 sw=2 et ai + */ + +// 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 <avr/io.h> +#include <avr/interrupt.h> + +#include <stdlib.h> // 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) +{ + PORTD &= ~0x08; // layer down, should be done before latch + PORTD &= ~0x20; // latch low + unsigned char current_layer_ = current_layer; + for (unsigned char j = 0; j < 8; ++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; + PORTD |= 0x08; // layer, should be done in the end and must be after latch +} + +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<<RXC)) ); + + // Load the received byte from rs232 into a buffer. + tempval = UDR; + + // Uncommet this to echo data back to the computer + // for debugging purposes. + //UDR = tempval; + + // Every time the cube receives a 0xff byte, + // it goes into sync escape mode. + // if a 0x00 byte is then received, the x and y counters + // are reset to 0. This way the x and y counters are + // always the same on the computer and in the cube. + // To send an 0xff byte, you have to send it twice! + + // Go into sync escape mode + if (tempval == 0xff) + { + // Wait for the next byte + while ( !(UCSRA & (1<<RXC)) ); + // Get the next byte + tempval = UDR; + + // Sync signal is received. + // Reset x and y counters to 0. + if (tempval == 0x00) + { + x = 0; + y = 0; + escape = 1; + } + // if no 0x00 byte is received, proceed with + // the byte we just received. + } + + if (escape == 0) + { + // Load data into the current position in the buffer + fb[x][y] = tempval; + + // Check if we have reached the limits of the buffer array. + if (y == 7) + { + if (x == 7) + { + // All data is loaded. Reset both counters + y = 0; + x = 0; + // Copy the data onto the cube. + tmp2cube(); + } else + { + // A layer is loaded, reset y and increment x. + x++; + y = 0; + } + } else + { + // We are in the middle of loading a layer. increment y. + y++; + } + + } else + { + escape = 0; + } + } +} + + + + +/***************************************************************************** + * MAIN + *****************************************************************************/ + +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; + + /* + * ======================================================================= + * Serial port init + * ======================================================================= + */ + + // Initiate uart + // USART Baud rate is defined in MYUBRR + //UBRRH = BAUD_PRESCALE >> 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<<RXEN)|(1<<TXEN); + //UCSRC=(1<<URSEL)|(3<<UCSZ0); + ////UDR = 0x00; // send an empty byte to indicate powerup. + +#if 1 +#define BAUDRATE 38400 +#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1) + UBRRH = (uint8_t)(BAUD_PRESCALLER>>8); + UBRRL = (uint8_t)(BAUD_PRESCALLER); + //UBRRH = (uint8_t)(0); + //UBRRL = (uint8_t)(0); + UCSRC = (1<<URSEL)|(3<<UCSZ0); + UCSRB = (1<<RXEN)|(1<<TXEN); +#undef BAUDRATE +#undef BAUD_PRESCALLER +#endif + + //*** set interupts + sei(); + + /* + * ======================================================================= + * MAIN LOOP + * ======================================================================= + */ + + //while (1) { delay(1000); UDR = 'a'; } + //while (1) { UDR = 'a'; } + //DDRD |= 0x02; while (1) { delay(1000); PORTD ^= 0x02; } + + rs232(); + //while (1) + //{ + // // Show the effects in a predefined order + // for (char i=0; i<EFFECTS_TOTAL; i++) + // launch_effect(i); + + // // Show the effects in a random order. + // // Comment the two lines above and uncomment this + // // if you want the effects in a random order. + // //launch_effect(rand()%EFFECTS_TOTAL); + //} + + + 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(5000); + + clear_led(); + 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); + } + } + } + + // Show the effects in a predefined order + //for (char i=0; i<EFFECTS_TOTAL; i++) + //launch_effect(i); + //sendvoxels_rand_z(20,220,2000); + //effect_rain(100); + //effect_random_filler(5,1); + //effect_z_updown(20,1000); + //effect_wormsqueeze (2, AXIS_Z, -1, 100, 1000); + //effect_blinky2(); + + + // Show the effects in a random order. + // Comment the two lines above and uncomment this + // if you want the effects in a random order. + //launch_effect(rand()%EFFECTS_TOTAL); + + //effect_boxside_randsend_parallel (AXIS_X, 0, 150, 1); + //effect_boxside_randsend_parallel (AXIS_X, 1, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Y, 0, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Y, 1, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Z, 0, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Z, 1, 150, 1); + + + //delay(1000); + //PORTB ^= 0x01; + } + + return 0; // normally never return, just to be complient with c99 standard +} |