mini-led-cube/firmware/main.c

111 lines
3 KiB
C
Raw Normal View History

/*
* CTHN.de MiniLEDCube
*
* By Kai Lauterbach (klaute at web dot de) 11/2011
2011-12-09 23:15:06 +01:00
*
* Based on http://mosfetkiller.de/?s=miniledcube
*
* License: General Public License (GPL v3)
*
*/
#include "main.h"
/*! \brief Main loop
*/
2012-01-04 16:30:54 +01:00
int __attribute__((OS_main)) main()
{
// Initialize the AVR and the USB connection.
init();
init_usb();
// Hauptschleife
for (;;)
{
usbPoll(); // keep connected
}
}
/*! \brief Initialize the AVR.
*/
void init()
{
// Init ports
DDRB = 0b11111111; // PB0-PB7: LED 1-8 (Kathode)
PORTB = 0b11111111; // HIGH
2011-12-24 18:30:04 +01:00
DDRD = 0b01111000; // PD6: LED 9 (Kathode); PD5-PD3: A-C (Anode)
PORTD = 0b01000000;
2011-12-24 18:30:04 +01:00
// Setup Timer-Interrupt "TIMER1" compare match interrupt
TIMSK = (1 << OCIE1A);
2011-12-24 18:30:04 +01:00
// Refreshrate is 100Hz of the whole LEDCube.
// The ISR comes up at 300Hz.
// Set the compare value to
2011-11-30 00:16:21 +01:00
// 625d = 0x271 = 0b00000010, 0b01110001
OCR1AH = 0b00000010;
OCR1AL = 0b01110001;
2011-12-24 18:30:04 +01:00
// Set prescale to 64 and clear the counter on compare match.
TCCR1B = (1 << CS11) | (1 << CS10) | (1 << WGM12);
2011-11-30 00:16:21 +01:00
sei(); // Enable interrupts global
}
2011-12-30 13:33:05 +01:00
/*! \brief TIMER1 interruptvector, called in a frequency of 300Hz.
*/
2011-11-05 16:52:02 +01:00
ISR (TIMER1_COMPA_vect)
{
if (!(--delay)) // decrease the counter and check if we are done with waiting
2011-12-18 19:35:47 +01:00
{
if (frmnum == MAX_EEPROM_FRAMES)
2011-12-18 19:35:47 +01:00
{
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 = 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 is zero value.
2011-12-27 11:46:16 +01:00
delay = (frame >> 24) & 0xf8;
2011-12-18 19:35:47 +01:00
}
2014-06-22 13:30:58 +02:00
// !!!Don't touch the 6th bit (9th LED wire)!!!
// PORTD = __, 9, C, B, A, D+, D-, __
2014-06-22 13:30:58 +02:00
PORTD &= 0b11000111; // delete bit 3 to 6 (bit 3 to 5 = layer 0 to 2
uint8_t tmp = level * 9; // calculate the position in the frame
2011-11-30 00:16:21 +01:00
// PORTB = 1..8
// 0 = led is on, 1 = led is off
2011-12-17 22:03:57 +01:00
PORTB = ~((frame >> tmp) & 0xff);
if ((((frame >> tmp) >> 8) & 0x01))
2014-06-22 13:30:58 +02:00
PORTD &= ~(1 << 6); // turn the 9th LED on
else
PORTD |= (1 << 6); // turn the 9th LED off
2014-06-22 13:30:58 +02:00
// set the current level to high
// at this point the LED pins are up to date so it's
// safe to reenable the level wire (A/B/C)
// this prevents wierd LED flashing which is not defined
// in the animation frame
PORTD |= ((1 << level) << 3);
2013-09-11 20:53:14 +02:00
// rotate through the 3 level
2011-12-17 22:03:57 +01:00
level++;
2014-06-22 13:30:58 +02:00
if (level > 2)
level = 0;
}