Subversion Repositories HomeAutomation

Rev

Blame | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * CAN RGB LED. This application is used to control a RGB LED.
  3.  * Still under heavy development
  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/interrupt.h>
  21. #include <inttypes.h>
  22. #include <stdio.h>
  23. #include <bios.h>
  24. #include <avr/pgmspace.h> //To allow read/write from flash
  25.  
  26. /* lib files */
  27. //#include <can.h>
  28. //#include <serial.h>
  29. //#include <timebase.h>
  30. //#include <math.h> //Not sure this is needed anymore..
  31.  
  32. /*----------------------------------------------------------------------------
  33.  * Defines
  34.  * -------------------------------------------------------------------------*/
  35.  
  36. //Not implemented yet. Will be implementet when I build a canUSB :)
  37.  
  38. #define RGBLED_CMD_GET      0x1400
  39. #define RGBLED_CMD_SEND     0x1401
  40.  
  41. #define RGBLED_CMD_STATUS       0x00    /* Get status */
  42. #define RGBLED_CMD_SETRGB       0x01    /* Set RGB Triplet */
  43. #define RGBLED_CMD_CHANGERGB  0x02  /* Change RGB +/- */
  44. #define RGBLED_CMD_SETINTENS  0x10  /* Set intensity */
  45.  
  46. /*----------------------------------------------------------------------------
  47.  * Ehm, struct?
  48.  * -------------------------------------------------------------------------*/
  49. typedef struct
  50. {
  51.     uint8_t R;
  52.     uint8_t G;
  53.     uint8_t B;
  54.     uint8_t Intens;
  55. } Color;
  56.  
  57. /*-----------------------------------------------------------------------------
  58.  * Programs! There will be a better way to add programs here.. some day.
  59.  *---------------------------------------------------------------------------*/
  60.  
  61. //Special combinations that means something special
  62. //The combinations are useless for lighting anyway
  63. //So we might as well use them!
  64. //0x00, 0x00, 0x00, 0x00 means end of program, keep looping it
  65. //0x00, 0x00, 0x00, 0x01 means end of program, halt
  66.  
  67. Color pgm1[] PROGMEM = {
  68. {0xff,0x00,0x00,0x64},
  69. {0xff,0xff,0x00,0x10},
  70. {0x00,0xff,0x00,0xa0},
  71. {0x00,0xff,0xff,0x7f},
  72. {0x00,0x00,0xff,0x7f},
  73. {0xff,0x00,0xff,0x40},
  74. {0x00,0x00,0x00,0x00}
  75. };
  76.  
  77. Color pgm2[] PROGMEM = {
  78. {0xff,0x00,0x00,0x00},
  79. {0xff,0xff,0x00,0x00},
  80. {0xff,0xff,0xff,0x00},
  81. {0xa0,0x00,0xa0,0x00},
  82. {0x00,0x00,0xff,0x00},
  83. {0x00,0x00,0x00,0x00}
  84. };
  85.  
  86. Color pgm3[] PROGMEM = {
  87. {0xff,0xff,0xff,0x00},
  88. {0x00,0x00,0x00,0x01}
  89. };
  90.  
  91. Color* programs[] PROGMEM = {
  92. (Color*)pgm1,
  93. (Color*)pgm2,
  94. (Color*)pgm3
  95. };
  96.  
  97.  
  98.  
  99. /*-----------------------------------------------------------------------------
  100.  * Variables
  101.  *---------------------------------------------------------------------------*/
  102. uint32_t timeStamp; //TimeStamp to keep track of time
  103. uint32_t dimStamp;  //Timestamp to keep track of dimmer changes
  104. uint32_t time;      //Temptime for converting (TODO)
  105.  
  106. Color currColor;    //Current color
  107. Color destColor;    //Destination color
  108.  
  109. uint16_t fadeSpeed; //Fadingspeed. 16bit for reaaaally slow fading. Sets the speed of colorchange.
  110. uint8_t dimSpeed;       //Dimmer speed. Sets the speed of intensitychange.
  111.  
  112. uint8_t currProgram;    //This variable keeps track of what program is currently running.
  113. 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
  114.  
  115. /*----------------------------------------------------------------------------
  116.  * Functions
  117.  * -------------------------------------------------------------------------*/
  118. void updateLED();
  119. void reformatRGB(uint8_t R, uint8_t G, uint8_t B, uint8_t setBright);
  120. void changeColor(int8_t amount, uint8_t* color);
  121. void fade(uint8_t* current, uint8_t* destination);
  122.  
  123.  
  124. void can_receive(Can_Message_t *msg) {
  125.     //What should we do when can recieve?
  126. }
  127.  
  128. /*-----------------------------------------------------------------------------
  129.  * Main Program
  130.  *---------------------------------------------------------------------------*/
  131. int main(void) {
  132. //  Timebase_Init();
  133. //  Serial_Init();
  134. //  Can_Init();
  135.  
  136. //Setting up OC1A, 16 bit counter used as 8 bit.
  137.     TCCR1A |= (1<<COM1A1) | (1<<WGM11); /* Set OC1A at TOP, mode 14 */
  138.     TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS12); /* Timer uses main system clock with ? prescale */
  139.     ICR1 = 256; //8 bit precision to match the other two counters.
  140.     OCR1A = 0;  //0% as standard
  141.     DDRB |= (1<<PB1); /* Enable pin as output */
  142. //Setting up OC0A
  143.     TCCR0A |= (1<<COM0A1)|(1<<WGM01)|(1<<WGM00); /* Set OC0A at TOP, Mode 7 */
  144.     TCCR0B |= (1<<CS02); /* Prescaler updating now */
  145.     OCR0A = 0;  //0% standard
  146.     DDRD |= (1<<PD6);
  147. //Setting up OC0B
  148.     TCCR0A |= (1<<COM0B1);
  149.     OCR0B = 0;
  150.     DDRD |= (1<<PD5);
  151.  
  152. //Initialize variables
  153.     fadeSpeed = 10;
  154.     dimSpeed = 10;
  155.     timeStamp = 0;
  156.     dimStamp = 0;
  157. //  Can_Message_t rxMsg;   
  158.  
  159.     reformatRGB(0x00,0xff,0x00,1);
  160.     destColor.Intens = 100;
  161.     currColor = destColor;
  162.  
  163. //Just temporary for now, they keep track of some kind of demo-program.
  164.     currProgram = 1;
  165.     programMode = 0;
  166.     uint16_t temp_adress = pgm_read_word(&programs[currProgram-1]); //Get adress for program 0
  167.  
  168.     sei();
  169.  
  170.     bios->can_callback = &can_receive;
  171.  
  172. //Lets send out that we're alive
  173.     Can_Message_t txMsg;
  174.     txMsg.Id = 0x42; //booted!
  175.     txMsg.DataLength = 4;
  176.     txMsg.RemoteFlag = 0;
  177.     txMsg.ExtendedFlag = 1;
  178.     txMsg.Data.words[0] = 0x13;
  179.     txMsg.Data.words[1] = 0x13;
  180.     bios->can_send(&txMsg);
  181. //Data sent.
  182.  
  183. //Just temporary
  184. //  currColor.R = 0;
  185. //  destColor.R = 100;
  186.  
  187.  
  188.     /* main loop */
  189.     while (1) {
  190.        
  191.         /* Time to fade color? */
  192.         time = bios->timebase_get();
  193.         if ((time - timeStamp) >= fadeSpeed) {
  194.             fade(&currColor.R, &destColor.R);          
  195.             fade(&currColor.G, &destColor.G);
  196.             fade(&currColor.B, &destColor.B);
  197.  
  198.             timeStamp = bios->timebase_get();
  199.             updateLED();
  200.         }
  201.  
  202.  
  203.         /* Time to fade intensity? */
  204. //      if (Timebase_PassedTimeMillis(dimStamp) >= dimSpeed) {
  205. //          fade(&currColor.Intens, &destColor.Intens);
  206. //          dimStamp = Timebase_CurrentTime();
  207. //          updateLED();
  208. //      }
  209.  
  210.  
  211.         /* Program management */
  212.         if (currProgram != 0) { //Check if a program is currently running
  213.             if ((currColor.R == destColor.R)&(currColor.G == destColor.G)&(currColor.B == destColor.B)&(currColor.Intens == destColor.Intens)){//Is the current sequence finished?
  214.                 //Now we have to check if the program is finished and if we should loop
  215.                 if ((pgm_read_byte(temp_adress)==0)&(pgm_read_byte(temp_adress+1)==0)&(pgm_read_byte(temp_adress+2)==0)){
  216.                     //The program has ended! Shall we loop it?
  217.                     if (pgm_read_byte(temp_adress+3)==0){
  218.                         //Yes, let's loop it
  219.                         temp_adress = pgm_read_word(&programs[currProgram-1]);
  220.                     } else {
  221.                         //No, halt!
  222.                         currProgram = 0;
  223.                     }
  224.                 } else {
  225.                     //The program has not ended, let's get the next RGB-triplet!
  226.                     destColor.R = pgm_read_byte(temp_adress);
  227.                     destColor.G = pgm_read_byte(temp_adress + 1);
  228.                     destColor.B = pgm_read_byte(temp_adress + 2);
  229.                     if (programMode == 1){
  230.                         destColor.Intens = pgm_read_byte(temp_adress + 3);
  231.                     }
  232.  
  233.                     temp_adress = temp_adress + 4;             
  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 = 4;
  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.     bios->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.