Subversion Repositories HomeAutomation

Rev

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