Subversion Repositories HomeAutomation

Rev

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