/* * CTHN.de MiniLEDCube * * By Kai Lauterbach (klaute at web dot de) 11/2011 * * Based on http://mosfetkiller.de/?s=miniledcube * * License: General Public License (GPL v3) * */ #include "main.h" /*! \brief Initialize the AVR. */ static inline void init(void) { // Init ports DDRB = 0xFF; // PB0-PB7: LED 1-8 (Kathode) PORTB = 0xFF; // HIGH DDRD = 0x78; // PD6: LED 9 (Kathode); PD5-PD3: A-C (Anode) PORTD = 0x40; // Setup Timer-Interrupt "TIMER1" compare match // Refresh-rate is 100Hz of the whole LEDCube. // The timer fires at 300Hz. // Set the compare value to // 625d = 0x271 OCR1A = 0x271; // Set prescaler to 64 and CTC mode TCCR1B = (1 << CS11) | (1 << CS10) | (1 << WGM12); sei(); // Enable interrupts global } /*! \brief Main loop */ int __attribute__((OS_main)) main() { uint8_t level = 0x00; uint8_t frmnum = 0x00; uint8_t delay = 0x00; // Initialize the AVR and the USB connection. init(); init_usb(); // main loop for (;;) { usbPoll(); // keep connected if (TIFR & (1 << OCF1A)) { TIFR = (1 << OCF1A); cli(); if (!(--delay)) { // decrease the counter and check if we are done with waiting if (frmnum == MAX_EEPROM_FRAMES) { if (mode == MODE_ANIMATION_SINGLE) { mode = MODE_ANIMATION_STOP; // stop the animation after we have reached the 31th frame } frmnum = 0; // always start at the first frame } else { if (mode) { // if we are in an animation mode we have to load a frame out of the eeprom // and increase the counter frame.all = eeprom_read_dword(&eep_anim[frmnum]); frmnum++; } } // Just shift right by 24 instead of 27 to multiply the delay by 8. // Possible delays are 8 16 24 32 and so on. A zero delay isn't possible. // Zero means that a delay of 255 happens because the delay variable was decreased first before testing // it's zero value. delay = frame.bytes[3] & 0xf8; } // PORTD = __, 9, C, B, A, D+, D-, __ PORTD &= ~((1 << PORTD5) | (1 << PORTD4) | (1 << PORTD3) | (1 << PORTD2)); // delete bit 3 to 6 (bit 3 to 5 = layer 0 to 2 // PORTB = 1..8 uint32_t tmp_frame = (frame.all >> (uint8_t)(level * 9)); // 0 = led is on, 1 = led is off PORTB = ~((uint8_t)tmp_frame); if (!(tmp_frame & 0x100)) { PORTD |= (1 << PORTD6); // turn the 9th LED off } else { PORTD &= ~(1 << PORTD6); // turn the 9th LED on } // set the current level to high // at this point the LED pins are up to date so it's // safe to re-enable the level wire (A/B/C) // this prevents weird LED flashing which is not defined // in the animation frame PORTD |= ((1 << level) << 3); // set the current level // rotate through the 3 level level++; if (level > 2) { level = 0; } sei(); } } }