diff --git a/firmware/globals.h b/firmware/globals.h index b9dfb1a..d24fafe 100644 --- a/firmware/globals.h +++ b/firmware/globals.h @@ -1,6 +1,6 @@ /* CTHN.de MiniLEDCube * - * Kai Lauterbach (klaute at web dot de) + * By Kai Lauterbach (klaute at web dot de) 11/2011 * * License: General Public License (GPL v3) * diff --git a/firmware/main.c b/firmware/main.c index 9beac36..67c1799 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -1,6 +1,7 @@ -/* CTHN.de MiniLEDCube +/* + * CTHN.de MiniLEDCube * - * Kai Lauterbach (klaute at web dot de) + * By Kai Lauterbach (klaute at web dot de) 11/2011 * * Based on http://mosfetkiller.de/?s=miniledcube * @@ -10,16 +11,14 @@ #include "main.h" -// Main +// Main loop int __attribute__((OS_main)) main() { - // Initialisierung + // Initialize the AVR and the USB connection. init(); init_usb(); - //frame = 0x07ffffff; - mode = 2; // Hauptschleife for (;;) @@ -31,74 +30,75 @@ main() // Initialisierung void init() { - // Ports vorbereiten - DDRB = 0b11111111; // PB0-PB7: LED 1-8 (Kathoden) + // Init ports + DDRB = 0b11111111; // PB0-PB7: LED 1-8 (Kathode) PORTB = 0b11111111; // HIGH DDRD = 0b01111000; // PD6: LED 9 (Kathode); PD5-PD3: A-C (Anoden) PORTD = 0b01000000; - // Timer-Interrupt "TIMER1" vorbereiten + // Setup Timer-Interrupt "TIMER1" + TIMSK |= (1 << OCIE1A); - set_bit(TIMSK, OCIE1A); // Interrupt für ISR COMPA - //set_bit(TCCR1B, WGM12); // Überlauf wird unten gesetzt - - // Animations-Geschwindigkeit - // (vergleichswert bei dem der Interrupt ausgelöst wird) + // Refreshrate is 100Hz + // Set the compare value // 625d = 0x271 = 0b00000010, 0b01110001 OCR1AH = 0b00000010; OCR1AL = 0b01110001; // anpassen auf reihenweise ausgabe - // Vorteiler durch 64 (0x011) ----> CS12=0, CS11=1, CS10=1 - //clear_bit(TCCR1B, CS12); // Prescaler 64 - //set_bit(TCCR1B, CS11); - //set_bit(TCCR1B, CS10); + // prescale is 64 (0x011) ----> CS12=0, CS11=1, CS10=1 TCCR1B |= (1 << CS11) | (1 << CS10) | (1 << WGM12); - sei(); // Set enable interrupt bit (Muss gesetzt werden damit es überhaupt aufgerufen wird) + sei(); // Enable interrupts global } -// Interruptvektor von TIMER1 +// TIMER1 Interruptvector ISR (TIMER1_COMPA_vect) { - delay--; - if ( !delay ) + delay--; // decrease the delay counter + if ( !delay ) // check if we are done with waiting { - if (frmnum == 32) + if (frmnum == MAX_EEPROM_FRAMES) { - if (mode == 1) - mode = 0; - frmnum = 0; + 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 loadEEPROMFrame(frmnum); frmnum++; } } - delay = delay_max; + delay = delay_max; // start counting from the top of the maximum delay } // PORTD = __, 9, C, B, A,D+,D-,__ - PORTD &= 0b10000111; // 7tes Bit löschen (Leitung 9) und alle Ebenen deaktivieren - PORTD |= (1 << 6) | ((1 << level) << 3); // level setzen (Ebene A=0, B=1, C=2) + PORTD &= 0b10000111; // delete bit 3 to 6 (bit 3 to 5 = layer 0 to 2; bit 6 = wire 9 to the LEDs) + PORTD |= (1 << 6) | ((1 << level) << 3); // set the current level and pin 6 to high (9th LEDs off) - uint8_t tmp = level * 9; + uint8_t tmp = level * 9; // calculate the position in the frame // PORTB = 1..8 - // 0 = leuchtet, 1 = leuchtet nicht (invertiert!) + // 0 = led is on, 1 = led is off PORTB = ~((frame >> tmp) & 0xff); if ( (((frame >> tmp) >> 8) & 0x01) ) - PORTD &= ~(1 << 6); // 9. led setzen falls notwendig + PORTD &= ~(1 << 6); // turn the 9th LED on if required + // rotate through the 3 level level++; if (level > 2) level = 0; } +/** + * Simple function to load a single frame out of the EEPROM. + */ void loadEEPROMFrame(uint8_t f) { frame = eeprom_read_dword( &eep_anim[f] ); diff --git a/firmware/main.h b/firmware/main.h index cff2aa6..731871e 100644 --- a/firmware/main.h +++ b/firmware/main.h @@ -1,6 +1,7 @@ -/* CTHN.de MiniLEDCube +/* + * CTHN.de MiniLEDCube * - * Kai Lauterbach (klaute at web dot de) + * By Kai Lauterbach (klaute at web dot de) 11/2011 * * Based on http://mosfetkiller.de/?s=miniledcube * @@ -14,31 +15,28 @@ // Includes #include "globals.h" -//#include "type.h" - #include #include #include // Cube-Data -uint32_t frame = 0xffffffff; -// Bit Offset in Cube-Data -uint8_t level; // Aktive Ebene -uint8_t mode; -uint8_t frmnum; -uint8_t delay; -uint8_t delay_max; +uint32_t frame; -//cube_t *cube; -uint32_t eep_anim[32] EEMEM; +uint8_t level; // current layer +uint8_t mode = MODE_ANIMATION_LOOP; // firmware mode +uint8_t frmnum; // frame nummber in the animation loop +uint8_t delay; // delay in ISR calls between changing to the next animation frame +uint8_t delay_max = STARTUP_DELAY_MAX; // maximum delay between the animation frames -// Prototypen +// eeprom array of the animation +uint32_t eep_anim[MAX_EEPROM_FRAMES] EEMEM; + +// function prototypes void init(void); +void loadEEPROMFrame(uint8_t); extern void init_usb(void); extern void usbPoll(void); -void loadEEPROMFrame(uint8_t); - #endif // __main_h__ diff --git a/firmware/requests.h b/firmware/requests.h index 3548621..fd9aa9f 100644 --- a/firmware/requests.h +++ b/firmware/requests.h @@ -1,11 +1,13 @@ -/* Name: requests.h - * Project: custom-class, a basic USB example - * Author: Christian Starkjohann - * Creation Date: 2008-04-09 - * Tabsize: 4 - * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - * This Revision: $Id: requests.h 692 2008-11-07 15:07:40Z cs $ +/* + * CTHN.de MiniLEDCube + * + * requests.h by Kai Lauterbach + * + * Based on project: hid-custom-rq example by Christian Starkjohann + * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH + * + * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) + * */ /* This header is shared between the firmware and the host software. It @@ -18,8 +20,7 @@ #define CUSTOM_RQ_SET_FRAME 1 #define CUSTOM_RQ_EEPROM_STORE_FRAME 2 -#define CUSTOM_RQ_EEPROM_SET_FRAME 3 -#define CUSTOM_RQ_SET_MODE 4 -#define CUSTOM_RQ_SET_DELAY 5 +#define CUSTOM_RQ_SET_MODE 3 +#define CUSTOM_RQ_SET_DELAY 4 #endif /* __REQUESTS_H_INCLUDED__ */ diff --git a/firmware/usb.c b/firmware/usb.c index 8c1a2d5..3b00389 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -1,9 +1,13 @@ -/* Name: usb.h by Kai Lauterbach - * Based on Project: hid-custom-rq example - * Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $ - * Author: Christian Starkjohann - * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) +/* + * CTHN.de MiniLEDCube + * + * usb.h by Kai Lauterbach 11/2011 + * + * Based on project: hid-custom-rq example by Christian Starkjohann + * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH + * + * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) + * */ #include "usb.h" @@ -19,12 +23,16 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) if ( rq->bRequest == CUSTOM_RQ_SET_FRAME ) { + // because of the code size we have to transfer one frame in + // two steps (control messages) if ( rq->wIndex.bytes[0] == 0 ) { + // the lower word frame = (frame & (uint32_t)0xffff0000) | ( rq->wValue.bytes[0] + (rq->wValue.bytes[1] << 8) ); } else { + // the high word frame = (frame & (uint32_t)0x0000ffff) | ((uint32_t)( rq->wValue.bytes[0] + (rq->wValue.bytes[1] << 8) ) << 16); @@ -32,13 +40,19 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) } else if ( rq->bRequest == CUSTOM_RQ_EEPROM_STORE_FRAME ) { + // save the actual frame to the eeprom + // don't forget to send a frame first eeprom_write_dword( &eep_anim[ rq->wIndex.bytes[0] ], frame ); } else if ( rq->bRequest == CUSTOM_RQ_SET_DELAY ) { + // set the maximum delay between two frames + // as a multiply of ISR calls delay_max = rq->wValue.bytes[0]; } else if ( rq->bRequest == CUSTOM_RQ_SET_MODE ) { - mode = rq->wValue.bytes[0]; // 0 = stop; 1 = single; 2 = loop + // set the firmware mode + // 0 = stop; 1 = single; 2 = loop + mode = rq->wValue.bytes[0]; } } diff --git a/firmware/usb.h b/firmware/usb.h index eabc2a2..d8d2445 100644 --- a/firmware/usb.h +++ b/firmware/usb.h @@ -1,10 +1,13 @@ -/* Name: usb.h by Kai Lauterbach - * Based on Project: hid-custom-rq example - * Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $ - * Author: Christian Starkjohann - * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - * This +/* + * CTHN.de MiniLEDCube + * + * usb.c by Kai Lauterbach 11/2011 + * + * Based on project: hid-custom-rq example by Christian Starkjohann + * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH + * + * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) + * */ #ifndef __usb_h__ @@ -18,17 +21,6 @@ #include "globals.h" -//#include "type.h" - -/* -This example should run on most AVRs with only little changes. No special -hardware resources except INT0 are used. You may have to change usbconfig.h for -different I/O pins for USB. Please note that USB D+ must be the INT0 pin, or -at least be connected to INT0 as well. -We assume that an LED is connected to port B bit 0. If you connect it to a -different port or bit, change the macros below: -*/ - #include "usbconfig.h" #include "usbdrv.h" #include "requests.h" /* The custom request numbers we use */ @@ -57,7 +49,7 @@ PROGMEM char usbHidReportDescriptor[22] = { /* USB report descriptor */ void init_usb(void); -extern uint32_t eep_anim[32] EEMEM; +extern uint32_t eep_anim[MAX_EEPROM_FRAMES] EEMEM; // usb buffer extern uint32_t frame; // Framebuffer @@ -65,7 +57,7 @@ extern uint8_t delay_max; // delay in ISR aufrufen extern uint8_t mode; // FW mode //extern cube_t *cube; -extern void loadEEPROMFrame(uint8_t f); +extern void loadEEPROMFrame(uint8_t); #endif // __usb_h__