Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Project: usb led attiny85 firmware
- * Author: goebish
- * Creation Date: 2011-12-28
- */
- /*
- * Fuses:
- * - Low: F1
- * - High: DF
- * - Ext: FF
- * - Lock: FF
- */
- #define LED_PORT_DDR DDRB
- #define LED_PORT_OUTPUT PORTB
- #define R_BIT 1
- #define G_BIT 3
- #define B_BIT 4
- #include <avr/io.h>
- #include <avr/wdt.h>
- #include <avr/eeprom.h>
- #include <avr/interrupt.h> /* for sei() */
- #include <util/delay.h> /* for _delay_ms() */
- #include <stdlib.h> // for random functions
- #include <avr/pgmspace.h> /* required by usbdrv.h */
- extern "C"
- {
- #include "usbdrv.h"
- }
- #include "requests.h" /* The custom request numbers we use */
- /* ------------------------------------------------------------------------- */
- /* ----------------------------- USB interface ----------------------------- */
- /* ------------------------------------------------------------------------- */
- PROGMEM char usbHidReportDescriptor[22] = { /* USB report descriptor */
- 0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop)
- 0x09, 0x01, // USAGE (Vendor Usage 1)
- 0xa1, 0x01, // COLLECTION (Application)
- 0x15, 0x00, // LOGICAL_MINIMUM (0)
- 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
- 0x75, 0x08, // REPORT_SIZE (8)
- 0x95, 0x01, // REPORT_COUNT (1)
- 0x09, 0x00, // USAGE (Undefined)
- 0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
- 0xc0 // END_COLLECTION
- };
- /* The descriptor above is a dummy only, it silences the drivers. The report
- * it describes consists of one byte of undefined data.
- * We don't transfer our data through HID reports, we use custom requests
- * instead.
- */
- static uint8_t pwmCounter = 0;
- static uint8_t r = 0;
- static uint8_t g = 0;
- static uint8_t b = 0;
- static volatile uint8_t desired_r = 0;
- static volatile uint8_t desired_g = 0;
- static volatile uint8_t desired_b = 0;
- static uint8_t rb = 0;
- static uint8_t gb = 0;
- static uint8_t bb = 0;
- static volatile uint16_t fspeed = 4000; // fading speed
- static volatile uint32_t blinkPeriod=0;
- static volatile uint32_t blinkPeriod2=0;
- static volatile uint8_t currentMode = MODE_RANDOM;
- extern "C" usbMsgLen_t usbFunctionSetup(uchar data[8])
- {
- usbRequest_t *rq = (usbRequest_t *)data;
- if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_VENDOR)
- {
- switch(rq->bRequest)
- {
- case CUSTOM_RQ_SET_RED:
- desired_r = rq->wValue.bytes[0];
- break;
- case CUSTOM_RQ_SET_GREEN:
- desired_g = rq->wValue.bytes[0];
- break;
- case CUSTOM_RQ_SET_BLUE:
- desired_b = rq->wValue.bytes[0];
- break;
- case CUSTOM_RQ_SET_FADING_SPEED:
- fspeed = rq->wValue.bytes[0];
- fspeed *= fspeed;
- break;
- case CUSTOM_RQ_SET_MODE:
- currentMode = rq->wValue.bytes[0];
- break;
- case CUSTOM_RQ_SET_BLINK_PERIOD:
- blinkPeriod = rq->wValue.bytes[0];
- blinkPeriod *= blinkPeriod;
- blinkPeriod2 = blinkPeriod*2;
- break;
- }
- }
- return 0; /* default for not implemented requests: return no data back to host */
- }
- static void calibrateOscillator(void)
- {
- uchar step = 128;
- uchar trialValue = 0, optimumValue;
- int x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
- do{
- srand(trialValue + step);
- OSCCAL = trialValue + step;
- x = usbMeasureFrameLength();
- if(x < targetValue)
- trialValue += step;
- step >>= 1;
- }while(step > 0);
- optimumValue = trialValue;
- optimumDev = x;
- for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
- x = usbMeasureFrameLength() - targetValue;
- if(x < 0)
- x = -x;
- if(x < optimumDev){
- optimumDev = x;
- optimumValue = OSCCAL;
- }
- }
- OSCCAL = optimumValue;
- }
- extern "C" void usbEventResetReady(void)
- {
- cli();
- calibrateOscillator();
- sei();
- }
- // software PWM
- void update_leds()
- {
- static uint32_t cycle=0;
- if(blinkPeriod && ++cycle%blinkPeriod2>blinkPeriod)
- {
- PORTB &= ~(1 << R_BIT);
- PORTB &= ~(1 << G_BIT);
- PORTB &= ~(1 << B_BIT);
- return;
- }
- if (++pwmCounter == 0) {
- rb = r;
- gb = g;
- bb = b;
- if (rb > 0) {
- PORTB |= (1 << R_BIT);
- }
- if (gb > 0) {
- PORTB |= (1 << G_BIT);
- }
- if (bb > 0) {
- PORTB |= (1 << B_BIT);
- }
- }
- if (pwmCounter == rb) {
- PORTB &= ~(1 << R_BIT);
- }
- if (pwmCounter == gb) {
- PORTB &= ~(1 << G_BIT);
- }
- if (pwmCounter == bb) {
- PORTB &= ~(1 << B_BIT);
- }
- }
- void computeColor()
- {
- if(fspeed==0)
- {
- r = desired_r;
- g = desired_g;
- b = desired_b;
- }
- else
- {
- static uint16_t fcounter=0;
- if(++fcounter%(fspeed)==0)
- {
- if(r>desired_r)
- r--;
- else if(r<desired_r)
- r++;
- if(g>desired_g)
- g--;
- else if(g<desired_g)
- g++;
- if(b>desired_b)
- b--;
- else if(b<desired_b)
- b++;
- }
- }
- if(currentMode==MODE_RANDOM) // autonomous
- {
- if(r==desired_r && g==desired_g && b==desired_b)
- {
- desired_r=0;
- desired_g=0;
- desired_b=0;
- switch(rand()%10)
- {
- case 0: // red
- desired_r = 255;
- break;
- case 1: // green
- desired_g = 255;
- break;
- case 2: // blue
- desired_b = 255;
- break;
- case 3: // yellow
- desired_r = 255;
- desired_g = 255;
- break;
- case 4: // cyan
- desired_g = 255;
- desired_b = 255;
- break;
- case 5: // purple
- desired_r = 255;
- desired_b = 255;
- break;
- default:
- desired_r = rand()%255;
- desired_g = rand()%170;
- desired_b = rand()%90;
- }
- }
- }
- }
- int main(void)
- {
- uchar i;
- wdt_enable(WDTO_1S);
- usbInit();
- usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */
- i = 0;
- while(--i){ /* fake USB disconnect for > 250 ms */
- wdt_reset();
- _delay_ms(1);
- }
- usbDeviceConnect();
- LED_PORT_DDR |= _BV(R_BIT) | _BV(G_BIT) | _BV(B_BIT); /* make the LED bit an output */
- sei();
- for(;;){ /* main event loop */
- computeColor();
- update_leds();
- wdt_reset();
- usbPoll();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement