Subversion Repositories HomeAutomation

Rev

Rev 810 | Blame | Compare with Previous | 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.  * TODO: Better CAN Integration, Failsafe mode, Tempsensors etc.
  9.  * Also, check current/destination intensity better when in a program?
  10.  *
  11.  * A little comment here :)
  12.  */
  13.  
  14.  
  15. /*-----------------------------------------------------------------------------
  16.  * Includes
  17.  *---------------------------------------------------------------------------*/
  18. /* system files */
  19. #include <avr/interrupt.h>
  20. #include <inttypes.h>
  21. #include <stdio.h>
  22. #include <avr/pgmspace.h> //To allow read/write from flash
  23.  
  24. #include <math.h>
  25.  
  26. #include <drivers/timer/timebase.h>
  27.  
  28. #include <config.h> // All configuration parameters
  29. #include <bios.h>   // BIOS interface declarations, including CAN structure and ID defines.
  30.  
  31. #include <string.h> //for memcpy
  32. /* lib files */
  33. #include <bios.h>
  34. //#include <funcdefs/funcdefs.h>
  35.  
  36. //#include <settings.h>
  37.  
  38. /*----------------------------------------------------------------------------
  39.  * Defines
  40.  * -------------------------------------------------------------------------*/
  41.  
  42. //Working on implementing all of these...
  43.  
  44. #define RGBLED_CMD_STATUS           0x00    /* Get status */
  45. #define RGBLED_CMD_SETRGB           0x01    /* Set RGB Triplet */
  46. #define RGBLED_CMD_CHANGERGB        0x02    /* Change RGB +/- */
  47. #define RGBLED_CMD_SETPROGRAM       0x03    /* Set program */
  48. #define RGBLED_CMD_SETFADESPEED     0x04    /* Set fadespeed */
  49. #define RGBLED_CMD_SETDIMSPEED      0x05    /* Set dimspeed */
  50. #define RGBLED_CMD_SETINTENS        0x10    /* Set intensity */
  51.  
  52. #define APP_TYPE    CAN_APPTYPES_RGBLED
  53. #define APP_VERSION 0x0001
  54.  
  55. #define GROUP_ID    0x01L // FIXME
  56. #define TRUE 1
  57. #define FALSE !TRUE
  58.  
  59.  
  60. /*----------------------------------------------------------------------------
  61.  * Ehm, struct?
  62.  * -------------------------------------------------------------------------*/
  63. typedef struct
  64. {
  65.     uint8_t R;
  66.     uint8_t G;
  67.     uint8_t B;
  68.     uint8_t Intens;
  69. } Color;
  70.  
  71. /*-----------------------------------------------------------------------------
  72.  * Programs! There will be a better way to add programs here.. some day.
  73.  *---------------------------------------------------------------------------*/
  74.  
  75. //Special combinations that means something special
  76. //The combinations are useless for lighting anyway
  77. //So we might as well use them!
  78. //0x00, 0x00, 0x00, 0x00 means end of program, keep looping it
  79. //0x00, 0x00, 0x00, 0x01 means end of program, halt
  80.  
  81. Color pgm1[] PROGMEM = {
  82. {0xff,0x00,0x00,0x64},
  83. {0xff,0xff,0x00,0x10},
  84. {0x00,0xff,0x00,0xa0},
  85. {0x00,0xff,0xff,0x7f},
  86. {0x00,0x00,0xff,0x7f},
  87. {0xff,0x00,0xff,0x40},
  88. {0x00,0x00,0x00,0x00}
  89. };
  90.  
  91. Color pgm2[] PROGMEM = {
  92. {0xff,0x00,0x00,0x00},
  93. {0xff,0xff,0x00,0x00},
  94. {0xff,0xff,0xff,0x00},
  95. {0xa0,0x00,0xa0,0x00},
  96. {0x00,0x00,0xff,0x00},
  97. {0x00,0x00,0x00,0x00}
  98. };
  99.  
  100. Color pgm3[] PROGMEM = {
  101. {0xff,0xff,0xff,0x00},
  102. {0x00,0x00,0x00,0x01}
  103. };
  104.  
  105. Color* programs[] PROGMEM = {
  106. (Color*)pgm1,
  107. (Color*)pgm2,
  108. (Color*)pgm3
  109. };
  110.  
  111.  
  112.  
  113. /*-----------------------------------------------------------------------------
  114.  * Global variables
  115.  *---------------------------------------------------------------------------*/
  116. uint32_t timeStamp; //TimeStamp to keep track of time
  117. uint32_t dimStamp;  //Timestamp to keep track of dimmer changes
  118.  
  119. Color currColor;    //Current color
  120. Color destColor;    //Destination color
  121.  
  122. uint16_t fadeSpeed; //Fadingspeed. 16bit for reaaaally slow fading. Sets the speed of colorchange.
  123. uint8_t dimSpeed;       //Dimmer speed. Sets the speed of intensitychange.
  124.  
  125. uint8_t currProgram;    //This variable keeps track of what program is currently running.
  126. 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
  127.  
  128. Can_Message_t txMsg;    //Transmit message storage
  129.  
  130. volatile Can_Message_t rxMsg; // Message storage
  131. volatile uint8_t rxMsgFull;   // Synchronization flag
  132.  
  133. uint8_t lastr;
  134. uint8_t lastg;
  135. uint8_t lastb;
  136.  
  137. /*----------------------------------------------------------------------------
  138.  * Functions
  139.  * -------------------------------------------------------------------------*/
  140. void updateLED(void);
  141. void reformatRGB(uint8_t R, uint8_t G, uint8_t B, uint8_t setBright);
  142. void changeColor(int8_t amount, uint8_t* color);
  143. void fade(uint8_t* current, uint8_t* destination);
  144.  
  145.  
  146. /* Takes care of incoming messages and parses them if this node is adressed */
  147. void can_receive(Can_Message_t *msg)
  148. { // CAN callback function
  149.     if (!rxMsgFull) {
  150.         memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
  151.         rxMsgFull = 1;
  152.     }
  153. }
  154.  
  155.  
  156. /*-----------------------------------------------------------------------------
  157.  * Main Program
  158.  *---------------------------------------------------------------------------*/
  159. int main(void) {
  160.  
  161. //Setting up OC1A, 16 bit counter used as 8 bit.
  162.     TCCR1A |= (1<<COM1A1) | (1<<WGM11); /* Set OC1A at TOP, mode 14 */
  163.     TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS11)| (1<<CS10); /* Timer uses main system clock with ? prescale */
  164.     ICR1 = 256; //8 bit precision to match the other two counters.
  165.     OCR1A = 0;  //0% as standard
  166.     DDRB |= (1<<PB1); /* Enable pin as output */
  167. //Setting up OC0A
  168.     TCCR0A |= (1<<COM0A1)|(1<<WGM01)|(1<<WGM00); /* Set OC0A at TOP, Mode 7 */
  169.     TCCR0B |= (1<<CS01)|  (1<<CS00); /* Prescaler updating now */
  170.     OCR0A = 0;  //0% standard
  171.     DDRD |= (1<<PD6);
  172. //Setting up OC0B
  173.     TCCR0A |= (1<<COM0B1);
  174.     OCR0B = 0;
  175.     DDRD |= (1<<PD5);
  176.  
  177. //Initialize variables
  178.     fadeSpeed = 40;
  179.     dimSpeed = 10;
  180.     timeStamp = 0;
  181.     dimStamp = 0;
  182.  
  183.     reformatRGB(0x00,0x00,0x00,1);
  184.     destColor.Intens = 0xa0;
  185.     currColor = destColor;
  186.  
  187. //Just temporary for now, they keep track of some kind of demo-program.
  188.     currProgram = 1;
  189.     programMode = 0;
  190.     uint16_t temp_adress = pgm_read_word(&programs[currProgram-1]); //Get adress for program 0
  191.  
  192.     sei();
  193.  
  194.     BIOS_CanCallback = &can_receive;
  195.  
  196.  
  197. //Send a message that we are alive!
  198.     txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID);
  199.     txMsg.DataLength = 4;
  200.     txMsg.RemoteFlag = 0;
  201.     txMsg.ExtendedFlag = 1;
  202.     txMsg.Data.words[0] = APP_TYPE;
  203.     txMsg.Data.words[1] = APP_VERSION;
  204.     BIOS_CanSend(&txMsg);
  205.  
  206. //Lets get timebase up and running
  207.     Timebase_Init();
  208.  
  209.  
  210.     /* main loop */
  211.     while (1) {
  212.        
  213.         /* Time to fade color? */
  214.         if ((Timebase_CurrentTime() - timeStamp) >= fadeSpeed) {
  215.             fade(&currColor.R, &destColor.R);          
  216.             fade(&currColor.G, &destColor.G);
  217.             fade(&currColor.B, &destColor.B);
  218.  
  219.             timeStamp = Timebase_CurrentTime();
  220.             updateLED();
  221.         }
  222.  
  223.  
  224.         /* Time to fade intensity? */
  225.         if (Timebase_CurrentTime() - dimStamp >= dimSpeed) {
  226.             fade(&currColor.Intens, &destColor.Intens);
  227.             dimStamp = Timebase_CurrentTime();
  228.             updateLED();
  229.         }
  230.  
  231.  
  232.         /* Program management */
  233.         if (currProgram != 0) { //Check if a program is currently running
  234.             if ((currColor.R == destColor.R)&(currColor.G == destColor.G)&(currColor.B == destColor.B)&(currColor.Intens == destColor.Intens)){//Is the current sequence finished?
  235.                 //Now we have to check if the program is finished and if we should loop
  236.                 if ((pgm_read_byte(temp_adress)==0)&(pgm_read_byte(temp_adress+1)==0)&(pgm_read_byte(temp_adress+2)==0)){
  237.                     //The program has ended! Shall we loop it?
  238.                     if (pgm_read_byte(temp_adress+3)==0){
  239.                         //Yes, let's loop it
  240.                         temp_adress = pgm_read_word(&programs[currProgram-1]);
  241.                     } else {
  242.                         //No, halt!
  243.                         currProgram = 0;
  244.                     }
  245.                 } else {
  246.                     //The program has not ended, let's get the next RGB-triplet!
  247.                     destColor.R = pgm_read_byte(temp_adress);
  248.                     destColor.G = pgm_read_byte(temp_adress + 1);
  249.                     destColor.B = pgm_read_byte(temp_adress + 2);
  250.                     if (programMode == 1){
  251.                         destColor.Intens = pgm_read_byte(temp_adress + 3);
  252.                     }
  253.  
  254.                     temp_adress = temp_adress + 4;             
  255.                 }
  256.  
  257.             }
  258.  
  259.         }
  260.  
  261.  
  262.         /* Check if any messages has been recieved */
  263.         if (rxMsgFull) {
  264.             uint16_t acttype;
  265.             uint8_t rgbledid;          
  266.        
  267.             if ( ((rxMsg.Id & CAN_MASK_CLASS)>>CAN_SHIFT_CLASS) == CAN_ACT){
  268.                 // Actuator package
  269.                 acttype =(uint16_t)((rxMsg.Id & CAN_MASK_ACT_TYPE) >> CAN_SHIFT_ACT_TYPE);
  270.                 rgbledid = (uint8_t)((rxMsg.Id & CAN_MASK_ACT_ID) >> CAN_SHIFT_ACT_ID);
  271.                
  272.                 if ((acttype == ACT_TYPE_RGBLED) && (rgbledid == THISRGBLEDID)) {                                                          
  273.                     // This is a message for this rgbled
  274.                     if( rxMsg.Data.bytes[0] == RGBLED_CMD_SETPROGRAM ){
  275.                         /* Set a program! Untested! */
  276.                         currProgram = rxMsg.Data.bytes[1];
  277.                         temp_adress = pgm_read_word(&programs[currProgram-1]);             
  278.                     } else if ( rxMsg.Data.bytes[0] == RGBLED_CMD_SETINTENS ){
  279.                         /* Set intensity! Works!*/
  280.                         if (rxMsg.Data.bytes[1] == TRUE){
  281.                             currColor.Intens = rxMsg.Data.bytes[2];                
  282.                         }
  283.                         destColor.Intens = rxMsg.Data.bytes[2];
  284.                         if (rxMsg.Data.bytes[3] != 0){
  285.                             dimSpeed = rxMsg.Data.bytes[3];
  286.                         }
  287.                     } else if( rxMsg.Data.bytes[0] == RGBLED_CMD_SETRGB) {
  288.                         /* Set RGB-triplet! */
  289.                         reformatRGB(rxMsg.Data.bytes[2],rxMsg.Data.bytes[3],rxMsg.Data.bytes[4],0);
  290.                         if (rxMsg.Data.bytes[5] != 0){
  291.                             destColor.Intens = rxMsg.Data.bytes[5];
  292.                         }
  293.                         if (rxMsg.Data.bytes[1] == TRUE){
  294.                             currColor = destColor;
  295.                         }
  296.  
  297.                         if (rxMsg.Data.bytes[7] != 0){
  298.                             fadeSpeed = rxMsg.Data.bytes[6] * 255 + rxMsg.Data.bytes[7];
  299.                         }
  300.                         currProgram = 0;               
  301.                     }
  302.                    
  303.                 }
  304.             }
  305.             rxMsgFull = 0; //  
  306.  
  307.         }
  308.         /* Done checking incoming packages */
  309.  
  310.     }
  311.    
  312.     return 0;
  313. }
  314.  
  315.  
  316.  
  317.  
  318. /************************************************************************************************
  319.  *     updateLED updates the PWM counter values and thus changes the color of the RGBLED.       *
  320.  *     It doesn't reculculate anything, except the values to write to the PWM registers.        *
  321.  *     TODO: Get rid of the tempcontainer!                                                      *
  322.  ************************************************************************************************/
  323. void updateLED(){
  324.     uint8_t tempcontainer;
  325.    
  326.     tempcontainer = currColor.R * currColor.Intens / 0xff;  //I really want to skip this, don't know how yet though.
  327.     OCR1A = tempcontainer;
  328.     OCR0A = currColor.G * currColor.Intens / 0xff;
  329.     OCR0B = currColor.B * currColor.Intens / 0xff;
  330.    
  331.     //Just for debug
  332.     Can_Message_t txMsg;
  333.     txMsg.Id = 0x55;
  334.     txMsg.RemoteFlag = 0;
  335.     txMsg.ExtendedFlag = 1;
  336.     txMsg.DataLength = 4;
  337.     txMsg.Data.bytes[0] = currColor.R * currColor.Intens / 0xff;
  338.     txMsg.Data.bytes[1] = currColor.G * currColor.Intens / 0xff;
  339.     txMsg.Data.bytes[2] = currColor.B * currColor.Intens / 0xff;
  340.     txMsg.Data.bytes[3] = currColor.Intens;
  341.  
  342.     //BIOS_CanSend(&txMsg); //Strictly for debug..
  343.  
  344. }
  345.  
  346.  
  347.  
  348. /************************************************************************************************
  349.  *     reformatRGB sets a new target RGB triplet to fade to. It reformats it so that            *
  350.  *     the highest color always gets 0xff. Brightness is recalculated.                          *
  351.  *     if setBright is set to 0, the brightness will not be updated.                            *
  352.  *     TODO: Smarter 16-bit arithmetics would be nice.                                          *
  353.  ************************************************************************************************/
  354. void reformatRGB(uint8_t R, uint8_t G, uint8_t B, uint8_t setBright){
  355.     uint8_t maxvalue;
  356.     uint16_t tempcontainer;
  357.  
  358.     if ((R>=G)&(R>=B)){
  359.         maxvalue = R;
  360.     } else if ((G>=R)&(G>=B)){
  361.         maxvalue = G;
  362.     } else {
  363.         maxvalue = B;
  364.     }
  365.  
  366.     tempcontainer = R * 255;
  367.     destColor.R = tempcontainer/maxvalue;
  368.     tempcontainer = G * 255;
  369.     destColor.G = tempcontainer/maxvalue;
  370.     tempcontainer = B * 255;
  371.     destColor.B = tempcontainer/maxvalue;
  372.  
  373.     if (setBright){
  374.         destColor.Intens = maxvalue;
  375.     }
  376. }
  377.  
  378.  
  379. /************************************************************************************************
  380.  *     fade takes two pointers, current and destination and fades current                       *
  381.  *     one tick closer to destination.                                                          *
  382.  ************************************************************************************************/
  383. void fade(uint8_t* current, uint8_t* destination){
  384.     if (*current > *destination){
  385.         *current = *current - 1;
  386.     } else if (*current < *destination){
  387.         *current = *current + 1;
  388.     }
  389. }
  390.  
  391.  
  392. /************************************************************************************************
  393.  *     changeColor changes a color accord to amount. -127>127.                                  *
  394.  *     color is either dest och curr R,G,B.                                                     *
  395.  *     Maybe TODO: If red is already 255 and we want to increase it, decrease the other ones.   *
  396.  ************************************************************************************************/
  397. void changeColor(int8_t amount, uint8_t* color){
  398.     if ( ((amount > 0)&(*color < 255)) || ((amount < 0)&(*color > 0)) ) //Se till att vi inte slår över *color
  399.     *color = *color + amount;
  400. }
  401.  
  402.