Subversion Repositories HomeAutomation

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1.  
  2. #include "act_RGBW.h"
  3.  
  4. #define RED 0
  5. #define GREEN 1
  6. #define BLUE 2
  7. #define WHITE 3
  8. #define ALGO_FREQ       5
  9. #define ADC_W   5
  10. #define ADC_R   4
  11. #define ADC_G   2
  12. #define ADC_B   0
  13.  
  14. #define OCR_W   OCR1B
  15. #define OCR_R   OCR1A
  16. #define OCR_G   OCR0A
  17. #define OCR_B   OCR0B
  18.  
  19. #define MAX_CURRENT_W   250UL
  20. #define MAX_ADC_W       MAX_CURRENT_W*4UL*1024UL/5000UL
  21.  
  22. #define MAX_CURRENT_R   50UL
  23. #define MAX_ADC_R       MAX_CURRENT_R*4UL*3UL*1024UL/5000UL
  24.  
  25. #define MAX_CURRENT_G   50UL
  26. #define MAX_ADC_G       MAX_CURRENT_G*4UL*3UL*1024UL/5000UL
  27.  
  28. #define MAX_CURRENT_B   50UL
  29. #define MAX_ADC_B       MAX_CURRENT_B*4UL*3UL*1024UL/5000UL
  30. uint16_t pwmValue[4];
  31. uint16_t adcValue[4];
  32. uint8_t sendInfo[4] = {0,0,0,0};
  33.  
  34. int8_t fadeSpeed[4] = {0,0,0,0};
  35. uint8_t fadeSpeedFrac[4] = {0,0,0,0};
  36. uint16_t fadeTarget[4] = {0,0,0,0};
  37. uint8_t fadeSpeedCnt[4] = {0,0,0,0};
  38.  
  39. uint16_t demoEndValue[4] = {0,0,0,0};
  40. uint16_t demoHighValue[4] = {0,0,0,0};
  41. uint8_t demoState[4] = {ACT_RGBW_DEMO_STATE_NOT_RUNNING, ACT_RGBW_DEMO_STATE_NOT_RUNNING, ACT_RGBW_DEMO_STATE_NOT_RUNNING,                  ACT_RGBW_DEMO_STATE_NOT_RUNNING};
  42.  
  43. uint8_t channel_to_send = 1;
  44. void calculatePWM(uint8_t timer);
  45. #ifdef act_RGBW_USEEEPROM
  46. #include "act_RGBW_eeprom.h"
  47. struct eeprom_act_RGBW EEMEM eeprom_act_RGBW =
  48. {
  49.     {
  50.         ///TODO: Define initialization values on the EEPROM variables here, this will generate a *.eep file that can be used to store this values to the node, can in future be done with a EEPROM module and the make-scrips. Write the values in the exact same order as the struct is defined in the *.h file.
  51.         0x0000, // ch 1
  52.         0x0000, // ch 2
  53.         0x0000, // ch 3
  54.         0x0000  // ch 4
  55.     },
  56.     0   // crc, must be a correct value, but this will also be handled by the EEPROM module or make scripts
  57. };
  58. #endif
  59.  
  60. #if act_RGBW_ENABLE_FADE == 1
  61. void act_RGBW_timer_callback(uint8_t timer)
  62. {
  63.     uint8_t channel = 0;
  64.     for (channel = 0; channel < 4; channel++) {
  65.         /* Check demo states */
  66.         if (pwmValue[channel] == fadeTarget[channel]) {
  67.             switch (demoState[channel])
  68.             {
  69.             case ACT_RGBW_DEMO_STATE_NOT_RUNNING:
  70.             break;
  71.             case ACT_RGBW_DEMO_STATE_DECREASE:
  72.                 demoState[channel] = ACT_RGBW_DEMO_STATE_INCREASE;
  73.                 fadeTarget[channel] = demoHighValue[channel];
  74.                 fadeSpeed[channel] = -fadeSpeed[channel];
  75.             break;
  76.             case ACT_RGBW_DEMO_STATE_INCREASE:
  77.                 demoState[channel] = ACT_RGBW_DEMO_STATE_GOBACK;
  78.                 fadeTarget[channel] = demoEndValue[channel];
  79.                 fadeSpeed[channel] = -fadeSpeed[channel];
  80.             break;
  81.             case ACT_RGBW_DEMO_STATE_GOBACK:
  82.                 demoState[channel] = ACT_RGBW_DEMO_STATE_NOT_RUNNING;
  83.             break;
  84.             }
  85.         }
  86.        
  87.         /* Change the dimmerValue according to the current fading */
  88.         fadeSpeedCnt[channel]++;
  89.         if (fadeSpeedCnt[channel] == fadeSpeedFrac[channel] && pwmValue[channel] != (fadeTarget[channel]))
  90.         {
  91.             fadeSpeedCnt[channel] = 0;
  92.             uint16_t tempDimVal = pwmValue[channel];
  93.             pwmValue[channel] += (fadeSpeed[channel]*39);
  94.             if ((fadeSpeed[channel] > 0 && (pwmValue[channel] < tempDimVal || pwmValue[channel] >= (fadeTarget[channel]))) ||
  95.                 (fadeSpeed[channel] < 0 && (pwmValue[channel] > tempDimVal || pwmValue[channel] <= (fadeTarget[channel]))))
  96.             {
  97.                 pwmValue[channel] = (fadeTarget[channel]);
  98.             }
  99.             /* if targetvalue was reached then send the netinfo packet */
  100.             if (pwmValue[channel] == fadeTarget[channel])
  101.             {
  102.                 sendInfo[channel] = 1;
  103.             }
  104.         }
  105.     }
  106.  
  107. }
  108. #endif
  109.  
  110.  
  111. void act_RGBW_Init(void)
  112. {
  113. #ifdef act_RGBW_USEEEPROM
  114.     if (EEDATA_OK)
  115.     {
  116.       ///TODO: Use stored data to set initial values for the module
  117.       pwmValue[0] = eeprom_read_word(EEDATA16.ch1);
  118.       pwmValue[1] = eeprom_read_word(EEDATA16.ch2);
  119.       pwmValue[2] = eeprom_read_word(EEDATA16.ch3);
  120.       pwmValue[3] = eeprom_read_word(EEDATA16.ch4);
  121.     } else
  122.     {   //The CRC of the EEPROM is not correct, store default values and update CRC
  123.       eeprom_write_word_crc(EEDATA16.ch1, 0x0000, WITHOUT_CRC);
  124.       eeprom_write_word_crc(EEDATA16.ch2, 0x0000, WITHOUT_CRC);
  125.       eeprom_write_word_crc(EEDATA16.ch3, 0x0000, WITHOUT_CRC);
  126.       eeprom_write_word_crc(EEDATA16.ch4, 0x0000, WITHOUT_CRC);
  127.       EEDATA_UPDATE_CRC;
  128.     }
  129. #endif
  130.     ADC_Init();
  131.     TCCR1A = 0;
  132.     TCCR1B = 0;
  133.     TCCR0A = 0;
  134.     TCCR0B = 0;
  135.  
  136.     /* set up pwm values */
  137.     /*
  138.     cli();
  139.     #if act_RGBW_CH1_COM>0
  140.     OCR_1=(uint16_t)(pwmValue[0]*act_RGBW_CH1_FACT)>>8;
  141.     #endif
  142.     #if act_RGBW_CH2_COM>0
  143.     OCR_2=(uint16_t)(pwmValue[1]*act_RGBW_CH2_FACT)>>8;
  144.     #endif
  145.     #if act_RGBW_CH3_COM>0
  146.     OCR_3=(uint16_t)(pwmValue[2]*act_RGBW_CH3_FACT)>>8;
  147.     #endif
  148.     #if act_RGBW_CH4_COM>0
  149.     OCR_4=(uint16_t)(pwmValue[3]*act_RGBW_CH4_FACT)>>8;
  150.     #endif
  151.     sei();
  152.     */
  153.     ADC_Init();
  154.  
  155.     TCCR1A = 0;
  156.     TCCR1B = 0;
  157.     TCCR1A |= (1 << WGM10) | (0 << WGM11);  //8-bit pwm with top=0xff
  158.     TCCR1B |= (1 << WGM12);     //fast pwm
  159.    
  160.     cli();
  161.     OCR1A = 0;  // set on time (tp)
  162.     OCR1B = 0;  // set on time (tp)
  163.     sei();
  164.     TCCR1A |= (1<<COM1A1);      //enable output compare
  165.     TCCR1A |= (1<<COM1B1);      //enable output compare
  166.     TCCR1B |= (1 << CS10);      //enable timer, prescaler=1
  167.     TCCR0A |= (1<<WGM01)|(1<<WGM00);
  168.     TCCR0B |= (1<<CS00);
  169.     cli();
  170.     OCR0A = 0;  // set on time (tp)
  171.     OCR0B = 0;  // set on time (tp)
  172.     sei();
  173.     TCCR0A |= (1<<COM0B1)|(1<<COM0A1);
  174.    
  175.     gpio_clr_pin(EXP_B);
  176.     gpio_clr_pin(EXP_C);
  177.     gpio_clr_pin(EXP_F);
  178.     gpio_clr_pin(EXP_G);
  179.    
  180.     gpio_set_out(EXP_B);
  181.     gpio_set_out(EXP_C);
  182.     gpio_set_out(EXP_F);
  183.     gpio_set_out(EXP_G);
  184.    
  185.    
  186.     Timer_SetTimeout(act_RGBW_FADE_TIMER, 10, TimerTypeFreeRunning, &act_RGBW_timer_callback);
  187.     Timer_SetTimeout(act_RGBW_REGULATOR_TIMER, ALGO_FREQ, TimerTypeFreeRunning, calculatePWM);
  188.     /* Setup timeout for sending the status packet */
  189.     Timer_SetTimeout(act_RGBW_SEND_STATUS_TIMEOUT, act_RGBW_SEND_STATUS_INTERVAL_S*1000, TimerTypeFreeRunning, 0);
  190. }
  191.  
  192. void calculatePWM(uint8_t timer) {
  193.     uint16_t adcMeasurment;
  194.    
  195.     //Calculate ADC-value
  196.     adcValue[WHITE] = (0x3ff&((MAX_ADC_W*pwmValue[WHITE])/10000));
  197.     if (pwmValue[WHITE] == 0) adcValue[WHITE] = 0;
  198.     adcValue[RED] = (0x3ff&((MAX_ADC_W*pwmValue[RED])/10000));
  199.     if (pwmValue[RED] == 0) adcValue[RED] = 0;
  200.     adcValue[BLUE] = (0x3ff&((MAX_ADC_W*pwmValue[BLUE])/10000));
  201.     if (pwmValue[BLUE] == 0) adcValue[BLUE] = 0;
  202.     adcValue[GREEN] = (0x3ff&((MAX_ADC_W*pwmValue[GREEN])/10000));
  203.     if (pwmValue[GREEN] == 0) adcValue[GREEN] = 0;
  204.     //printf("adc: %d %d %d %d\n",adcValue[WHITE],adcValue[RED],adcValue[BLUE],adcValue[GREEN]);
  205.        
  206.     adcMeasurment = ADC_Get(ADC_W);
  207.     if (adcMeasurment > MAX_ADC_W+50)
  208.         OCR_W=0;
  209.     else if (adcMeasurment > adcValue[WHITE]+16 && OCR_W > 1)
  210.         OCR_W-=2;
  211.     else if (adcMeasurment < adcValue[WHITE]-5 && OCR_W < 255)
  212.         OCR_W++;
  213.     else if (adcMeasurment > adcValue[WHITE]+5 && OCR_W >= 1)
  214.         OCR_W -=1;
  215. //printf("0: %d\n",adcMeasurment);
  216.     adcMeasurment = ADC_Get(ADC_R);
  217. //printf("1: %d\n",adcMeasurment);
  218.     if (adcMeasurment > MAX_ADC_R+50)
  219.         OCR_R=0;
  220.     else if (adcMeasurment > adcValue[RED]+16 && OCR_R > 1)
  221.         OCR_R-=2;
  222.     else if (adcMeasurment < adcValue[RED]-5 && OCR_R < 255)
  223.         OCR_R++;
  224.     else if (adcMeasurment > adcValue[RED]+5 && OCR_R >= 1)
  225.         OCR_R -=1;
  226.  
  227.     adcMeasurment = ADC_Get(ADC_G);
  228. //printf("1: %d\n",adcMeasurment);
  229.     if (adcMeasurment > MAX_ADC_G+50)
  230.         OCR_G=0;
  231.     else if (adcMeasurment > adcValue[GREEN]+16 && OCR_G > 1)
  232.         OCR_G-=2;
  233.     else if (adcMeasurment < adcValue[GREEN]-5 && OCR_G < 255)
  234.         OCR_G++;
  235.     else if (adcMeasurment > adcValue[GREEN]+5 && OCR_G >= 1)
  236.         OCR_G -=1;
  237.  
  238.     adcMeasurment = ADC_Get(ADC_B);
  239. //printf("2: %d\n",adcMeasurment);
  240.     if (adcMeasurment > MAX_ADC_B+50)
  241.         OCR_B=0;
  242.     else if (adcMeasurment > adcValue[BLUE]+16 && OCR_B > 1)
  243.         OCR_B-=2;
  244.     else if (adcMeasurment < adcValue[BLUE]-5 && OCR_B < 255)
  245.         OCR_B++;
  246.     else if (adcMeasurment > adcValue[BLUE]+5 && OCR_B >= 1)
  247.         OCR_B -=1;
  248.    
  249.  
  250.     cli();
  251.    
  252.     if (OCR_W==0)
  253.     {
  254.         TCCR1A&=~((1<<COM1B1));
  255.     }
  256.     else
  257.     {
  258.         TCCR1A |= (1<<COM1B1);      //enable output compare
  259.     }
  260.     if (OCR_R==0)
  261.     {
  262.         TCCR1A&=~((1<<COM1A1));
  263.     }
  264.     else
  265.     {
  266.         TCCR1A |= (1<<COM1A1);      //enable output compare
  267.     }
  268.     if (OCR_G==0)
  269.     {
  270.         TCCR0A &= ~((1<<COM0A0)|(1<<COM0A1));
  271.     }
  272.     else
  273.     {
  274.         TCCR0A|=(1<<COM0A1);
  275.     }
  276.     if (OCR_B==0)
  277.     {
  278.         TCCR0A &= ~((1<<COM0B0)|(1<<COM0B1));
  279.     }
  280.     else
  281.     {
  282.         TCCR0A|=(1<<COM0B1);
  283.     }
  284.     sei();
  285.    
  286.    
  287. }
  288.  
  289. void act_RGBW_Process(void)
  290. {
  291.     if (Timer_Expired(act_RGBW_SEND_STATUS_TIMEOUT))
  292.     {
  293.         if (channel_to_send >4) {
  294.             channel_to_send=1;
  295.         }
  296.         sendInfo[channel_to_send-1] = 1;
  297.         channel_to_send++;
  298.        
  299.         StdCan_Msg_t txMsg;
  300.         StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_ACT);
  301.         StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  302.         txMsg.Header.ModuleType = CAN_MODULE_TYPE_ACT_RGBDRIVER;
  303.         txMsg.Header.ModuleId = 1;
  304.         txMsg.Header.Command = CAN_MODULE_CMD_RGBDRIVER_DEBUG;
  305.         txMsg.Length = 8;
  306.         //txMsg.Data[0] = (uint8_t)(ADC_Get(5)>>2);
  307.         //txMsg.Data[0] = (uint8_t)((ADC_Get(ADC_W)>>2)&0xff);
  308.         //txMsg.Data[1] = (uint8_t)((ADC_Get(ADC_R)>>2)&0xff);
  309.         //txMsg.Data[2] = (uint8_t)((ADC_Get(ADC_G)>>2)&0xff);
  310.         //txMsg.Data[3] = (uint8_t)((ADC_Get(ADC_B)>>2)&0xff);
  311.         txMsg.Data[0] = (uint8_t)((adcValue[WHITE]>>2)&0xff);
  312.         txMsg.Data[1] = (uint8_t)((adcValue[RED]>>2)&0xff);
  313.         txMsg.Data[2] = (uint8_t)((adcValue[GREEN]>>2)&0xff);
  314.         txMsg.Data[3] = (uint8_t)((adcValue[BLUE]>>2)&0xff);
  315.         txMsg.Data[4] = (uint8_t)((MAX_ADC_W>>2)&0xff);
  316.         txMsg.Data[5] = (uint8_t)((MAX_ADC_R>>2)&0xff);
  317.         txMsg.Data[6] = (uint8_t)((MAX_ADC_G>>2)&0xff);
  318.         txMsg.Data[7] = (uint8_t)((MAX_ADC_B>>2)&0xff);
  319.         //txMsg.Data[4] = (uint8_t)((adcValue[WHITE]>>2)&0xff);
  320.         //txMsg.Data[5] = (uint8_t)((adcValue[RED]>>2)&0xff);
  321.         //txMsg.Data[6] = (uint8_t)((adcValue[GREEN]>>2)&0xff);
  322.         //txMsg.Data[7] = (uint8_t)((adcValue[BLUE]>>2)&0xff);
  323.        
  324.         StdCan_Put(&txMsg);
  325.        
  326.     }
  327.     /* Send netinfo packet (if pwmvalue has changed, and periodically) */
  328.     uint8_t index;
  329.     for(index =0;index < 4; index++){
  330.         if (pwmValue[index] > 10000) {
  331.             pwmValue[index] = 10000;
  332.         }
  333.         if (sendInfo[index])
  334.         {
  335.             sendInfo[index] = 0;
  336.             StdCan_Msg_t txMsg;
  337.             StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_ACT);
  338.             StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  339.             txMsg.Header.ModuleType = CAN_MODULE_TYPE_ACT_RGBW;
  340.             txMsg.Header.ModuleId = act_RGBW_ID;
  341.             txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PWM;
  342.             txMsg.Length = 3;
  343.             txMsg.Data[0] = index+1;
  344.             txMsg.Data[1] = (0xff&(pwmValue[index]>>8));
  345.             txMsg.Data[2] = (0xff&(pwmValue[index]));
  346.             StdCan_Put(&txMsg);
  347.         }
  348.     }
  349.    
  350.     if (Timer_Expired(act_RGBW_STORE_VALUE_TIMEOUT))
  351.     {
  352.         if (pwmValue[0] != eeprom_read_word(EEDATA16.ch1))
  353.         {
  354.             eeprom_write_word_crc(EEDATA16.ch1, pwmValue[0], WITH_CRC);
  355.         }
  356.         if (pwmValue[1] != eeprom_read_word(EEDATA16.ch2))
  357.         {
  358.             eeprom_write_word_crc(EEDATA16.ch2, pwmValue[1], WITH_CRC);
  359.         }
  360.         if (pwmValue[2] != eeprom_read_word(EEDATA16.ch3))
  361.         {
  362.             eeprom_write_word_crc(EEDATA16.ch3, pwmValue[2], WITH_CRC);
  363.         }
  364.         if (pwmValue[3] != eeprom_read_word(EEDATA16.ch4))
  365.         {
  366.             eeprom_write_word_crc(EEDATA16.ch4, pwmValue[3], WITH_CRC);
  367.         }
  368.     }
  369. }
  370.  
  371. void act_RGBW_HandleMessage(StdCan_Msg_t *rxMsg)
  372. {
  373.     if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_ACT &&
  374.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_TO_OWNER &&
  375.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_ACT_RGBW &&
  376.         rxMsg->Header.ModuleId == act_RGBW_ID)
  377.     {
  378.         switch (rxMsg->Header.Command)
  379.         {
  380.         case CAN_MODULE_CMD_PHYSICAL_PWM:
  381.             if (rxMsg->Length == 3) {
  382.                 uint8_t channel = rxMsg->Data[0];
  383.                 pwmValue[channel-1] = (rxMsg->Data[1]<<8)+(rxMsg->Data[2]);
  384.             }
  385.            
  386.         break;
  387. #if act_RGBW_ENABLE_FADE == 1
  388.         case CAN_MODULE_CMD_RGBW_DEMO:      /* Demo(channel, speed, steps) */
  389.             if (rxMsg->Length == 4) {
  390.                 uint8_t channel = rxMsg->Data[0]-1;
  391.                 uint8_t speed = rxMsg->Data[1];
  392.                 uint16_t steps = (rxMsg->Data[2]<<8)+(rxMsg->Data[3]);
  393.                
  394.                 fadeSpeedCnt[channel] = 0;
  395.                 fadeSpeed[channel] = 0;
  396.                 if (speed == 0) {
  397.                     /* do nothing */
  398.                 } else {
  399.                     uint16_t diffToMin = pwmValue[channel] - ACT_RGBW_MIN_DIM;
  400.                     uint16_t diffToMax = ACT_RGBW_MAX_DIM - pwmValue[channel];
  401.                
  402.                     demoEndValue[channel] = pwmValue[channel];
  403.                     if (diffToMin >= steps && diffToMax >= steps)
  404.                     {
  405.                         /* not close to min or max */
  406.                         fadeTarget[channel] = pwmValue[channel] - steps;
  407.                         demoHighValue[channel] = pwmValue[channel] + steps;
  408.                     }
  409.                     else if (diffToMin >= steps)
  410.                     {
  411.                         /* close to max */
  412.                         fadeTarget[channel] = pwmValue[channel] - steps - steps + diffToMax;
  413.                         demoHighValue[channel] = ACT_RGBW_MAX_DIM;
  414.                     }
  415.                     else if (diffToMax >= steps)
  416.                     {
  417.                         /* close to min */
  418.                         fadeTarget[channel] = ACT_RGBW_MIN_DIM;
  419.                         demoHighValue[channel] = pwmValue[channel] + steps + steps - diffToMin;
  420.                     }
  421.                     demoState[channel] = ACT_RGBW_DEMO_STATE_DECREASE;
  422.                
  423.                     if ((speed&0x80) == 0x80) {
  424.                         fadeSpeed[channel] = (speed&0x7f)+1;
  425.                         fadeSpeedFrac[channel] = 1;
  426.                     } else {
  427.                         fadeSpeed[channel] = 1;
  428.                         fadeSpeedFrac[channel] = 0x80-(speed&0x7f);
  429.                     }
  430.                     if (fadeTarget[channel] <= pwmValue[channel]) {
  431.                         fadeSpeed[channel] = -fadeSpeed[channel];
  432.                     }
  433.                 }
  434.             }
  435.         break;
  436.        
  437.         case CAN_MODULE_CMD_RGBW_START_FADE:    /* StartFade(channel, speed, direction) */
  438.             if (rxMsg->Length == 3) {
  439.                
  440.                 uint8_t channel = rxMsg->Data[0]-1;
  441.                 uint8_t speed = rxMsg->Data[1];
  442.                 uint8_t direction = rxMsg->Data[2];
  443.                 demoState[channel] = ACT_RGBW_DEMO_STATE_NOT_RUNNING;
  444.                 fadeSpeedCnt[channel] = 0;
  445.                 fadeSpeed[channel] = 0;
  446.                 uint16_t endValue = 0;
  447.                 if (direction == CAN_MODULE_ENUM_RGBW_START_FADE_DIRECTION_INCREASE) {
  448.                     endValue = ACT_RGBW_MAX_DIM;
  449.                 } else if (direction == CAN_MODULE_ENUM_RGBW_START_FADE_DIRECTION_DECREASE) {
  450.                     endValue = ACT_RGBW_MIN_DIM;
  451.                 }
  452.                    
  453.                 if (speed == 0) {
  454.                     pwmValue[channel] = endValue;   /* set dimmer value immediately */
  455.                     sendInfo[channel] = 1;      /* send netinfo with the current dimmervalue*/
  456.                 } else {
  457.                     fadeTarget[channel] = endValue;
  458.                     if (fadeTarget[channel] != pwmValue[channel]) {
  459.                         if ((speed&0x80) == 0x80) {
  460.                             fadeSpeed[channel] = (speed&0x7f)+1;
  461.                             fadeSpeedFrac[channel] = 1;
  462.                         } else {
  463.                             fadeSpeed[channel] = 1;
  464.                             fadeSpeedFrac[channel] = 0x80-(speed&0x7f);
  465.                         }
  466.                         if (fadeTarget[channel] < pwmValue[channel]) {
  467.                             fadeSpeed[channel] = -fadeSpeed[channel];
  468.                         }
  469.                     }
  470.                 }
  471.             }
  472.         break;
  473.  
  474.         case CAN_MODULE_CMD_RGBW_STOP_FADE: /* StopFade(channel) */
  475.             if (rxMsg->Length == 1) {
  476.                 uint8_t channel = rxMsg->Data[0]-1;
  477.                 demoState[channel] = ACT_RGBW_DEMO_STATE_NOT_RUNNING;
  478.                 fadeSpeed[channel] = 0;
  479.                 sendInfo[channel] = 1;      /* send netinfo with the current dimmervalue*/
  480.             }
  481.         break;
  482.  
  483.         case CAN_MODULE_CMD_RGBW_ABS_FADE:  /* AbsFade(channel, speed, endValue) */
  484.             if (rxMsg->Length == 4) {
  485.                 uint8_t channel = rxMsg->Data[0]-1;
  486.                 uint8_t speed = rxMsg->Data[1];
  487.                 uint16_t endValue = (rxMsg->Data[2]<<8)+(rxMsg->Data[3]);
  488.                 demoState[channel] = ACT_RGBW_DEMO_STATE_NOT_RUNNING;
  489.                 fadeSpeedCnt[channel] = 0;
  490.                 fadeSpeed[channel] = 0;
  491.                 if (speed == 0) {
  492.                     pwmValue[channel] = endValue;   /* set dimmer value immediately */
  493.                     sendInfo[channel] = 1;      /* send netinfo with the current dimmervalue*/
  494.                 } else {
  495.                     fadeTarget[channel] = endValue;
  496.                     if (fadeTarget[channel] != pwmValue[channel]) {
  497.                         if ((speed&0x80) == 0x80) {
  498.                             fadeSpeed[channel] = (speed&0x7f)+1;
  499.                             fadeSpeedFrac[channel] = 1;
  500.                         } else {
  501.                             fadeSpeed[channel] = 1;
  502.                             fadeSpeedFrac[channel] = 0x80-(speed&0x7f);
  503.                         }
  504.                         if (fadeTarget[channel] < pwmValue[channel]) {
  505.                             fadeSpeed[channel] = -fadeSpeed[channel];
  506.                         }
  507.                     }
  508.                 }
  509.                 //printf("abs fade %d %d %d!\n",fadeTarget[channel], endValue ,pwmValue[channel] );
  510.             }
  511.         break;
  512.  
  513.         case CAN_MODULE_CMD_RGBW_REL_FADE:  /* RelFade(channel, speed, direction, steps) */
  514.             if (rxMsg->Length == 5) {
  515.                
  516.                 uint8_t channel = rxMsg->Data[0]-1;
  517.                 uint8_t speed = rxMsg->Data[1];
  518.                 uint8_t direction = rxMsg->Data[2];
  519.                 uint16_t steps = (rxMsg->Data[3]<<8)+(rxMsg->Data[4]);
  520.                
  521.                 demoState[channel] = ACT_RGBW_DEMO_STATE_NOT_RUNNING;
  522.                 fadeSpeedCnt[channel] = 0;
  523.                 fadeSpeed[channel] = 0;
  524.                 uint16_t tempDimVal = pwmValue[channel];
  525.                 uint16_t tempDimVal2 = pwmValue[channel];
  526.                 if (direction == CAN_MODULE_ENUM_RGBW_REL_FADE_DIRECTION_INCREASE) {                    /* if increase */
  527.                     tempDimVal2 += steps;               /* calculate new value */
  528.                     if (tempDimVal2 < tempDimVal) {     /* make overflow test */
  529.                         tempDimVal2 = ACT_RGBW_MAX_DIM;
  530.                     }
  531.                 } else if (direction == CAN_MODULE_ENUM_RGBW_REL_FADE_DIRECTION_DECREASE) {         /* if decrease */
  532.                     tempDimVal2 -= steps;
  533.                     if (tempDimVal2 > tempDimVal) {
  534.                         tempDimVal2 = ACT_RGBW_MIN_DIM;
  535.                     }
  536.                 }
  537.                 if (speed == 0) {
  538.                     pwmValue[channel] = tempDimVal2;        /* set dimmer value immediately */
  539.                     sendInfo[channel] = 1;              /* send netinfo with the current dimmervalue*/
  540.                 } else {
  541.                     fadeTarget[channel] = tempDimVal2;      /* set the fade target */
  542.                    
  543.                     if (fadeTarget[channel] != pwmValue[channel]) {
  544.                         if ((speed&0x80) == 0x80) {
  545.                             fadeSpeed[channel] = (speed&0x7f)+1;
  546.                             fadeSpeedFrac[channel] = 1;
  547.                         } else {
  548.                             fadeSpeed[channel] = 1;
  549.                             fadeSpeedFrac[channel] = 0x80-(speed&0x7f);
  550.                         }
  551.                         if (fadeTarget[channel] < pwmValue[channel]) {
  552.                             fadeSpeed[channel] = -fadeSpeed[channel];
  553.                         }
  554.                     }
  555.                 }
  556.             }
  557.         break;
  558. #endif
  559.         }
  560.     }
  561. }
  562.  
  563. void act_RGBW_List(uint8_t ModuleSequenceNumber)
  564. {
  565.     StdCan_Msg_t txMsg;
  566.    
  567.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_ACT); ///TODO: Change this to the actual class type
  568.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  569.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_ACT_RGBW; ///TODO: Change this to the actual module type
  570.     txMsg.Header.ModuleId = act_RGBW_ID;
  571.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  572.     txMsg.Length = 6;
  573.  
  574.     txMsg.Data[0] = NODE_HW_ID_BYTE0;
  575.     txMsg.Data[1] = NODE_HW_ID_BYTE1;
  576.     txMsg.Data[2] = NODE_HW_ID_BYTE2;
  577.     txMsg.Data[3] = NODE_HW_ID_BYTE3;
  578.    
  579.     txMsg.Data[4] = NUMBER_OF_MODULES;
  580.     txMsg.Data[5] = ModuleSequenceNumber;
  581.    
  582.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  583. }
  584.