Advertisement
goebish

USB mood light firmware

Sep 16th, 2012
637
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.28 KB | None | 0 0
  1. /* Project: usb led attiny85 firmware
  2.  * Author: goebish
  3.  * Creation Date: 2011-12-28
  4.  */
  5.  
  6. /*
  7. *  Fuses:
  8. *       - Low:  F1
  9. *       - High: DF
  10. *       - Ext:  FF
  11. *       - Lock: FF
  12. */
  13.  
  14. #define LED_PORT_DDR        DDRB
  15. #define LED_PORT_OUTPUT     PORTB
  16. #define R_BIT            1
  17. #define G_BIT            3
  18. #define B_BIT            4
  19.  
  20. #include <avr/io.h>
  21. #include <avr/wdt.h>
  22. #include <avr/eeprom.h>
  23. #include <avr/interrupt.h>  /* for sei() */
  24. #include <util/delay.h>     /* for _delay_ms() */
  25. #include <stdlib.h> // for random functions
  26.  
  27. #include <avr/pgmspace.h>   /* required by usbdrv.h */
  28. extern "C"
  29. {
  30.     #include "usbdrv.h"
  31. }
  32.  
  33. #include "requests.h"       /* The custom request numbers we use */
  34.  
  35. /* ------------------------------------------------------------------------- */
  36. /* ----------------------------- USB interface ----------------------------- */
  37. /* ------------------------------------------------------------------------- */
  38.  
  39. PROGMEM char usbHidReportDescriptor[22] = {    /* USB report descriptor */
  40.     0x06, 0x00, 0xff,              // USAGE_PAGE (Generic Desktop)
  41.     0x09, 0x01,                    // USAGE (Vendor Usage 1)
  42.     0xa1, 0x01,                    // COLLECTION (Application)
  43.     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
  44.     0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
  45.     0x75, 0x08,                    //   REPORT_SIZE (8)
  46.     0x95, 0x01,                    //   REPORT_COUNT (1)
  47.     0x09, 0x00,                    //   USAGE (Undefined)
  48.     0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)
  49.     0xc0                           // END_COLLECTION
  50. };
  51. /* The descriptor above is a dummy only, it silences the drivers. The report
  52.  * it describes consists of one byte of undefined data.
  53.  * We don't transfer our data through HID reports, we use custom requests
  54.  * instead.
  55.  */
  56. static uint8_t pwmCounter = 0;
  57. static uint8_t r = 0;
  58. static uint8_t g = 0;
  59. static uint8_t b = 0;
  60.  
  61. static volatile uint8_t desired_r = 0;
  62. static volatile uint8_t desired_g = 0;
  63. static volatile uint8_t desired_b = 0;
  64.  
  65. static uint8_t rb = 0;
  66. static uint8_t gb = 0;
  67. static uint8_t bb = 0;
  68.  
  69. static volatile uint16_t fspeed = 4000; // fading speed
  70. static volatile uint32_t blinkPeriod=0;
  71. static volatile uint32_t blinkPeriod2=0;
  72.  
  73. static volatile uint8_t currentMode = MODE_RANDOM;
  74.  
  75. extern "C" usbMsgLen_t usbFunctionSetup(uchar data[8])
  76. {
  77.     usbRequest_t    *rq = (usbRequest_t *)data;
  78.   if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_VENDOR)
  79.     {
  80.         switch(rq->bRequest)
  81.         {
  82.         case CUSTOM_RQ_SET_RED:
  83.             desired_r = rq->wValue.bytes[0];
  84.             break; 
  85.         case CUSTOM_RQ_SET_GREEN:
  86.             desired_g = rq->wValue.bytes[0];
  87.             break; 
  88.         case CUSTOM_RQ_SET_BLUE:
  89.             desired_b = rq->wValue.bytes[0];
  90.             break; 
  91.         case CUSTOM_RQ_SET_FADING_SPEED:
  92.             fspeed = rq->wValue.bytes[0];
  93.             fspeed *= fspeed;
  94.             break;
  95.         case CUSTOM_RQ_SET_MODE:
  96.             currentMode = rq->wValue.bytes[0];
  97.             break;
  98.         case CUSTOM_RQ_SET_BLINK_PERIOD:
  99.             blinkPeriod = rq->wValue.bytes[0];
  100.             blinkPeriod *= blinkPeriod;
  101.             blinkPeriod2 = blinkPeriod*2;
  102.             break;
  103.         }
  104.   }
  105.   return 0;   /* default for not implemented requests: return no data back to host */
  106. }
  107.  
  108. static void calibrateOscillator(void)
  109. {
  110.     uchar       step = 128;
  111.     uchar       trialValue = 0, optimumValue;
  112.     int         x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
  113.   do{
  114.       srand(trialValue + step);
  115.       OSCCAL = trialValue + step;
  116.       x = usbMeasureFrameLength();    
  117.       if(x < targetValue)            
  118.         trialValue += step;
  119.       step >>= 1;
  120.   }while(step > 0);
  121.   optimumValue = trialValue;
  122.   optimumDev = x;
  123.   for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
  124.     x = usbMeasureFrameLength() - targetValue;
  125.     if(x < 0)
  126.       x = -x;
  127.     if(x < optimumDev){
  128.       optimumDev = x;
  129.       optimumValue = OSCCAL;
  130.     }
  131.   }
  132.   OSCCAL = optimumValue;
  133. }
  134.  
  135. extern "C" void usbEventResetReady(void)
  136. {
  137.   cli();
  138.   calibrateOscillator();
  139.   sei();
  140. }
  141.  
  142. // software PWM
  143. void update_leds()
  144. {
  145.   static uint32_t cycle=0;
  146.   if(blinkPeriod && ++cycle%blinkPeriod2>blinkPeriod)
  147.   {
  148.         PORTB &= ~(1 << R_BIT);
  149.         PORTB &= ~(1 << G_BIT);
  150.         PORTB &= ~(1 << B_BIT);
  151.         return;
  152.   }
  153.   if (++pwmCounter == 0) {    
  154.     rb = r;
  155.     gb = g;
  156.     bb = b;
  157.     if (rb > 0) {        
  158.       PORTB |= (1 << R_BIT);
  159.     }
  160.     if (gb > 0) {
  161.       PORTB |= (1 << G_BIT);
  162.     }
  163.     if (bb > 0) {
  164.       PORTB |= (1 << B_BIT);
  165.     }
  166.   }
  167.   if (pwmCounter == rb) {    
  168.     PORTB &= ~(1 << R_BIT);
  169.   }
  170.   if (pwmCounter == gb) {
  171.     PORTB &= ~(1 << G_BIT);
  172.   }
  173.   if (pwmCounter == bb) {
  174.     PORTB &= ~(1 << B_BIT);
  175.   }
  176. }
  177.  
  178. void computeColor()
  179. {
  180.     if(fspeed==0)
  181.     {
  182.         r = desired_r;
  183.         g = desired_g;
  184.         b = desired_b;
  185.     }
  186.     else
  187.     {
  188.         static uint16_t fcounter=0;
  189.         if(++fcounter%(fspeed)==0)
  190.         {
  191.             if(r>desired_r)
  192.                 r--;
  193.             else if(r<desired_r)
  194.                 r++;
  195.             if(g>desired_g)
  196.                 g--;
  197.             else if(g<desired_g)
  198.                 g++;
  199.             if(b>desired_b)
  200.                 b--;
  201.             else if(b<desired_b)
  202.                 b++;
  203.         }  
  204.     }
  205.     if(currentMode==MODE_RANDOM) // autonomous
  206.     {
  207.         if(r==desired_r && g==desired_g && b==desired_b)
  208.         {
  209.             desired_r=0;
  210.             desired_g=0;
  211.             desired_b=0;
  212.             switch(rand()%10)
  213.             {
  214.                 case 0: // red
  215.                     desired_r = 255;
  216.                     break;
  217.                 case 1: // green
  218.                     desired_g = 255;
  219.                     break;
  220.                 case 2: // blue
  221.                     desired_b = 255;
  222.                     break;
  223.                 case 3: // yellow
  224.                     desired_r = 255;
  225.                     desired_g = 255;
  226.                     break;
  227.                 case 4: // cyan
  228.                     desired_g = 255;
  229.                     desired_b = 255;
  230.                     break;
  231.                 case 5: // purple
  232.                     desired_r = 255;
  233.                     desired_b = 255;
  234.                     break;
  235.                 default:
  236.                     desired_r = rand()%255;
  237.                     desired_g = rand()%170;
  238.                     desired_b = rand()%90;     
  239.             }
  240.         }
  241.     }
  242. }
  243.  
  244. int main(void)
  245. {
  246.     uchar   i;
  247.   wdt_enable(WDTO_1S);
  248.   usbInit();
  249.   usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
  250.   i = 0;
  251.   while(--i){             /* fake USB disconnect for > 250 ms */
  252.     wdt_reset();
  253.     _delay_ms(1);
  254.   }
  255.   usbDeviceConnect();
  256.   LED_PORT_DDR |= _BV(R_BIT) | _BV(G_BIT) | _BV(B_BIT);   /* make the LED bit an output */
  257.   sei();
  258.   for(;;){                /* main event loop */
  259.         computeColor();
  260.         update_leds();
  261.     wdt_reset();
  262.     usbPoll();
  263.   }
  264.   return 0;
  265. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement