Subversion Repositories HomeAutomation

Rev

Rev 409 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * CAN RGB LED. This version is not using BIOS and is therefor obselete. New version with bios is
  3.  * quite a lot better.
  4.  *
  5.  * @date    2007-02-10
  6.  * @author  Martin Nordén
  7.  *
  8.  * Set RGB: <byte0 RGBLED_CMD_SETRGB> <byte 1 Set/Fade> <byte2 R> <byte3 G> <byte4 B>
  9.  * Change RGB: <byte 0 RGBLED_CMD_CHANGERGB> <byte 1 int R> <byte 2 int G> <byte 3 int B>  (Note that they are all signed)
  10.  * Set Intens: <byte0 RGBLED_CMD_SETINTENS> <byte1 Set/Fade> <byte2 Intens> (<byte3 dimSpeed>)
  11.  *
  12.  * TODO: Better CAN Integration, Failsafe mode, Tempsensors etc.
  13.  */
  14.  
  15.  
  16. /*-----------------------------------------------------------------------------
  17.  * Includes
  18.  *---------------------------------------------------------------------------*/
  19. /* system files */
  20. #include <avr/io.h>
  21. #include <avr/interrupt.h>
  22. #include <avr/wdt.h>
  23. #include <stdio.h>
  24. #include <avr/pgmspace.h> //To allow read/write from flash
  25. /* lib files */
  26. #include <can.h>
  27. #include <serial.h>
  28. #include <timebase.h>
  29. #include <math.h> //Not sure this is needed anymore..
  30.  
  31. /*----------------------------------------------------------------------------
  32.  * Defines
  33.  * -------------------------------------------------------------------------*/
  34.  
  35. //Not implemented yet. Will be implementet when I build a canUSB :)
  36.  
  37. #define RGBLED_CMD_GET      0x1400
  38. #define RGBLED_CMD_SEND     0x1401
  39.  
  40. #define RGBLED_CMD_STATUS       0x00    /* Get status */
  41. #define RGBLED_CMD_SETRGB       0x01    /* Set RGB Triplet */
  42. #define RGBLED_CMD_CHANGERGB  0x02  /* Change RGB +/- */
  43. #define RGBLED_CMD_SETINTENS  0x10  /* Set intensity */
  44.  
  45. /*----------------------------------------------------------------------------
  46.  * Ehm, struct?
  47.  * -------------------------------------------------------------------------*/
  48. typedef struct
  49. {
  50.     uint8_t R;
  51.     uint8_t G;
  52.     uint8_t B;
  53.     uint8_t Intens;
  54. } Color;
  55.  
  56. /*-----------------------------------------------------------------------------
  57.  * Programs! There will be a better way to add programs here.. some day.
  58.  *---------------------------------------------------------------------------*/
  59.  
  60. //Special combinations that means something special
  61. //The combinations are useless for lighting anyway
  62. //So we might as well use them!
  63. //0x00, 0x00, 0x00, 0x00 means end of program, keep looping it
  64. //0x00, 0x00, 0x00, 0x01 means end of program, halt
  65.  
  66. Color pgm1[] PROGMEM = {
  67. {0xff,0x00,0x00,0x64},
  68. {0xff,0xff,0x00,0x10},
  69. {0x00,0xff,0x00,0xa0},
  70. {0x00,0xff,0xff,0x7f},
  71. {0x00,0x00,0xff,0x7f},
  72. {0xff,0x00,0xff,0x40},
  73. {0x00,0x00,0x00,0x00}
  74. };
  75.  
  76. Color pgm2[] PROGMEM = {
  77. {0xff,0x00,0x00,0x00},
  78. {0xff,0xff,0x00,0x00},
  79. {0xff,0xff,0xff,0x00},
  80. {0xa0,0x00,0xa0,0x00},
  81. {0x00,0x00,0xff,0x00},
  82. {0x00,0x00,0x00,0x00}
  83. };
  84.  
  85. Color pgm3[] PROGMEM = {
  86. {0xff,0xff,0xff,0x00},
  87. {0x00,0x00,0x00,0x01}
  88. };
  89.  
  90. Color* programs[] PROGMEM = {
  91. (Color*)pgm1,
  92. (Color*)pgm2,
  93. (Color*)pgm3
  94. };
  95.  
  96.  
  97.  
  98. /*-----------------------------------------------------------------------------
  99.  * Variables
  100.  *---------------------------------------------------------------------------*/
  101. uint32_t timeStamp; //TimeStamp to keep track of time
  102. uint32_t dimStamp;  //Timestamp to keep track of dimmer changes
  103.  
  104. Color currColor;    //Current color
  105. Color destColor;    //Destination color
  106.  
  107. uint16_t fadeSpeed; //Fadingspeed. 16bit for reaaaally slow fading. Sets the speed of colorchange.
  108. uint8_t dimSpeed;       //Dimmer speed. Sets the speed of intensitychange.
  109.  
  110. uint8_t currProgram;    //This variable keeps track of what program is currently running.
  111. uint8_t programMode;    //This keeps track of what mode we are currently using. 0: the program obeyes the current brightness, 1: the program is allowed to set it's own brightness
  112.  
  113. /*----------------------------------------------------------------------------
  114.  * Functions
  115.  * -------------------------------------------------------------------------*/
  116. void updateLED();
  117. void reformatRGB(uint8_t R, uint8_t G, uint8_t B, uint8_t setBright);
  118. void changeColor(int8_t amount, uint8_t* color);
  119. void fade(uint8_t* current, uint8_t* destination);
  120.  
  121. /*-----------------------------------------------------------------------------
  122.  * Main Program
  123.  *---------------------------------------------------------------------------*/
  124. int main(void) {
  125.     Timebase_Init();
  126.     Serial_Init();
  127.     Can_Init();
  128.  
  129. //Setting up OC1A, 16 bit counter used as 8 bit.
  130.     TCCR1A |= (1<<COM1A1) | (1<<WGM11); /* Set OC1A at TOP, mode 14 */
  131.     TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS12); /* Timer uses main system clock with ? prescale */
  132.     ICR1 = 256; //8 bit precision to match the other two counters.
  133.     OCR1A = 0;  //0% as standard
  134.     DDRB |= (1<<PB1); /* Enable pin as output */
  135. //Setting up OC0A
  136.     TCCR0A |= (1<<COM0A1)|(1<<WGM01)|(1<<WGM00); /* Set OC0A at TOP, Mode 7 */
  137.     TCCR0B |= (1<<CS02); /* Prescaler updating now */
  138.     OCR0A = 0;  //0% standard
  139.     DDRD |= (1<<PD6);
  140. //Setting up OC0B
  141.     TCCR0A |= (1<<COM0B1);
  142.     OCR0B = 0;
  143.     DDRD |= (1<<PD5);
  144.  
  145. //Initialize variables
  146.     fadeSpeed = 10;
  147.     dimSpeed = 10;
  148.     timeStamp = 0;
  149.     dimStamp = 0;
  150.     Can_Message_t rxMsg;   
  151.  
  152.     reformatRGB(0x00,0xff,0x00,1);
  153.     destColor.Intens = 250;
  154.     currColor = destColor;
  155.  
  156. //Just temporary for now, they keep track of some kind of demo-program.
  157.     currProgram = 1;
  158.     programMode = 0;
  159.     uint16_t temp_adress = pgm_read_word(&programs[currProgram-1]); //Get adress for program 0
  160.  
  161.     sei();
  162.  
  163.     /* main loop */
  164.     while (1) {
  165.         /* service the CAN routines */
  166.         Can_Service();
  167.  
  168.         /* Time to fade color? */
  169.         if (Timebase_PassedTimeMillis(timeStamp) >= fadeSpeed) {
  170.             fade(&currColor.R, &destColor.R);          
  171.             fade(&currColor.G, &destColor.G);
  172.             fade(&currColor.B, &destColor.B);
  173.  
  174.             timeStamp = Timebase_CurrentTime();
  175.             updateLED();
  176.         }
  177.  
  178.  
  179.         /* Time to fade intensity? */
  180.         if (Timebase_PassedTimeMillis(dimStamp) >= dimSpeed) {
  181.             fade(&currColor.Intens, &destColor.Intens);
  182.             dimStamp = Timebase_CurrentTime();
  183.             updateLED();
  184.         }
  185.  
  186.  
  187.         /* Program management */
  188.         if (currProgram != 0){ //Check if a program is currently running
  189.             if ((currColor.R == destColor.R)&(currColor.G == destColor.G)&(currColor.B == destColor.B)&(currColor.Intens == destColor.Intens)){//Is the current sequence finished?
  190.                 //Now we have to check if the program is finished and if we should loop
  191.                 if ((pgm_read_byte(temp_adress)==0)&(pgm_read_byte(temp_adress+1)==0)&(pgm_read_byte(temp_adress+2)==0)){
  192.                     //The program has ended! Shall we loop it?
  193.                     if (pgm_read_byte(temp_adress+3)==0){
  194.                         //Yes, let's loop it
  195.                         temp_adress = pgm_read_word(&programs[currProgram-1]);
  196.                     } else {
  197.                         //No, halt!
  198.                         currProgram = 0;
  199.                     }
  200.                 } else {
  201.                     //The program has not ended, let's get the next RGB-triplet!
  202.                     destColor.R = pgm_read_byte(temp_adress);
  203.                     destColor.G = pgm_read_byte(temp_adress + 1);
  204.                     destColor.B = pgm_read_byte(temp_adress + 2);
  205.                     if (programMode == 1){
  206.                         destColor.Intens = pgm_read_byte(temp_adress + 3);
  207.                     }
  208.  
  209.                     temp_adress = temp_adress + 4;             
  210.                 }
  211.             }
  212.         }
  213.  
  214.         /* check if any messages have been received */
  215.         /* A lot of remote control crap going on here now for testing */
  216.         while (Can_Receive(&rxMsg) == CAN_OK) {
  217.             if ((rxMsg.Data.bytes[0] == 0xf)&(rxMsg.Data.bytes[3] == 0x01)){
  218.                 currProgram = 1;
  219.                 temp_adress = pgm_read_word(&programs[currProgram-1]);
  220.             }
  221.  
  222.             if ((rxMsg.Data.bytes[0] == 0xf)&(rxMsg.Data.bytes[3] == 0x02)){
  223.                 currProgram = 2;
  224.                 temp_adress = pgm_read_word(&programs[currProgram-1]);
  225.             }
  226.  
  227.             if ((rxMsg.Data.bytes[0] == 0xf)&(rxMsg.Data.bytes[3] == 0x03)){
  228.                 currProgram = 3;
  229.                 temp_adress = pgm_read_word(&programs[currProgram-1]);
  230.             }
  231.  
  232.             if ((rxMsg.Data.bytes[0] == 0xf)&(rxMsg.Data.bytes[3] == 0x00)){
  233.                 currProgram = 0;
  234.             }
  235.  
  236.  
  237.  
  238.         }
  239.  
  240.     }
  241.    
  242.     return 0;
  243. }
  244.  
  245.  
  246.  
  247.  
  248. /************************************************************************************************
  249.  *     updateLED updates the PWM counter values and thus changes the color of the RGBLED.       *
  250.  *     It doesn't reculculate anything, except the values to write to the PWM registers.        *
  251.  *     TODO: Get rid of the tempcontainer!                                  *
  252.  ************************************************************************************************/
  253. void updateLED(){
  254.     uint8_t tempcontainer;
  255.  
  256.     tempcontainer = currColor.R * currColor.Intens / 255;   //I really want to skip this, don't know how yet though.
  257.     OCR1A = tempcontainer; 
  258.       OCR0A = currColor.G * currColor.Intens / 255;
  259.     OCR0B = currColor.B * currColor.Intens / 255;      
  260.  
  261. /*     
  262.     //Bara för debugcrap
  263.     Can_Message_t txMsg;
  264.     txMsg.Id = 0x55;
  265.     txMsg.RemoteFlag = 0;
  266.     txMsg.ExtendedFlag = 1;
  267.     txMsg.DataLength = 8;
  268.     txMsg.Data.bytes[0] = currColor.R;
  269.     txMsg.Data.bytes[1] = currColor.G;
  270.     txMsg.Data.bytes[2] = currColor.B;
  271.     txMsg.Data.bytes[3] = currColor.Intens;
  272.  
  273.     Can_Send(&txMsg);
  274. */
  275. }
  276.  
  277.  
  278.  
  279. /************************************************************************************************
  280.  *     reformatRGB sets a new target RGB triplet to fade to. It reformats it so that            *
  281.  *     the highest color always gets 0xff. Brightness is recalculated.                          *
  282.  *     if setBright is set to 0, the brightness will not be updated.                    *
  283.  *     TODO: Smarter 16-bit arithmetics would be nice. Also a pointer to struct to be updated.  *
  284.  ************************************************************************************************/
  285. void reformatRGB(uint8_t R, uint8_t G, uint8_t B, uint8_t setBright){
  286.     uint8_t maxvalue;
  287.     uint16_t tempcontainer;
  288.  
  289.     if ((R>=G)&(R>=B)){
  290.         maxvalue = R;
  291.     } else if ((G>=R)&(G>=B)){
  292.         maxvalue = G;
  293.     } else {
  294.         maxvalue = B;
  295.     }
  296.  
  297.     tempcontainer = R * 255;
  298.     destColor.R = tempcontainer/maxvalue;
  299.     tempcontainer = G * 255;
  300.     destColor.G = tempcontainer/maxvalue;
  301.     tempcontainer = B * 255;
  302.     destColor.B = tempcontainer/maxvalue;
  303.  
  304.     if (setBright){
  305.         destColor.Intens = maxvalue;
  306.     }
  307. }
  308.  
  309.  
  310. /************************************************************************************************
  311.  *     fade takes two pointers, current and destination and fades current               *
  312.  *     one tick closer to destination.                                                        *
  313.  ************************************************************************************************/
  314. void fade(uint8_t* current, uint8_t* destination){
  315.     if (*current > *destination){
  316.         *current = *current - 1;
  317.     } else if (*current < *destination){
  318.         *current = *current + 1;
  319.     }
  320. }
  321.  
  322.  
  323. /************************************************************************************************
  324.  *     changeColor changes a color accord to amount. -127>127.                                  *
  325.  *     color is either dest och curr R,G,B.                                                     *
  326.  *     Maybe TODO: If red is already 255 and we want to increase it, decrease the other ones.   *
  327.  ************************************************************************************************/
  328. void changeColor(int8_t amount, uint8_t* color){
  329.     if ( ((amount > 0)&(*color < 255)) || ((amount < 0)&(*color > 0)) ) //Se till att vi inte slår över *color
  330.     *color = *color + amount;
  331. }
  332.  
  333.