Subversion Repositories HomeAutomation

Rev

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