Subversion Repositories HomeAutomation

Rev

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

  1.  
  2. #include "act_hwPWM.h"
  3. #include <avr/pgmspace.h>
  4.  
  5. uint16_t pwmValue[4];
  6. uint8_t sendInfo[4] = {0,0,0,0};
  7.  
  8. int8_t fadeSpeed[4] = {0,0,0,0};
  9. uint8_t fadeSpeedFrac[4] = {0,0,0,0};
  10. uint16_t fadeTarget[4] = {0,0,0,0};
  11. uint8_t fadeSpeedCnt[4] = {0,0,0,0};
  12.  
  13. uint16_t demoEndValue[4] = {0,0,0,0};
  14. uint16_t demoHighValue[4] = {0,0,0,0};
  15. uint8_t demoState[4] = {ACT_HWPWM_DEMO_STATE_NOT_RUNNING, ACT_HWPWM_DEMO_STATE_NOT_RUNNING, ACT_HWPWM_DEMO_STATE_NOT_RUNNING, ACT_HWPWM_DEMO_STATE_NOT_RUNNING};
  16.  
  17. static uint16_t lookuptable[256] PROGMEM =
  18. {
  19.   0,4, 8,12,  17,  21   ,  25   ,  30   ,  34   ,  39   ,  43   ,  48   ,  52   ,  57   ,  62   ,  67   ,  72   ,  77   ,  82   ,  87   ,  93   ,  98   ,  104  ,  109  , 115   ,  120  ,  126  ,  132  ,  138  ,  144  ,  150  ,  156  ,  162  ,  169  ,  175  ,  182  ,  188  ,  195  ,  202  ,  209  ,  216  ,  223  ,  230  ,  237  ,  245  , 252   ,  260  ,  267  ,  275  ,  283  ,  291  ,  299  ,  308  ,  316  ,  325  ,  333  ,  342  ,  351  ,  360  ,  369  ,  378  ,  388  ,  397  ,  407  ,  417  ,  427  , 437   ,  447  ,  457  ,  468  ,  478  ,  489  ,  500  ,  511  ,  523  ,  534  ,  546  ,  557  ,  569  ,  581  ,  594  ,  606  ,  619  ,  632  ,  645  ,  658  ,  671  , 685   ,  698  ,  712  ,  726  ,  741  ,  755  ,  770  ,  785  ,  800  ,  815  ,  831  ,  847  ,  863  ,  879  ,  896  ,  912  ,  929  ,  946  ,  964  ,  982  ,  999  , 1018  ,  1036 ,  1055 ,  1074 ,  1093 ,  1113 ,  1132 ,  1152 ,  1173 ,  1193 ,  1214 ,  1236 ,  1257 ,  1279 ,  1301 ,  1324 ,  1346 ,  1369 ,  1393 ,  1417 ,  1441 , 1465  ,  1490 ,  1515 ,  1540 ,  1566 ,  1593 ,  1619 ,  1646 ,  1673 ,  1701 ,  1729 ,  1758 ,  1787 ,  1816 ,  1846 ,  1876 ,  1907 ,  1938 ,  1969 ,  2001 ,  2033 , 2066  ,  2099 ,  2133 ,  2167 ,  2202 ,  2237 ,  2273 ,  2309 ,  2346 ,  2383 ,  2421 ,  2459 ,  2498 ,  2538 ,  2577 ,  2618 ,  2659 ,  2701 ,  2743 ,  2786 ,  2829 , 2873  ,  2918 ,  2963 ,  3009 ,  3056 ,  3103 ,  3151 ,  3200 ,  3249 ,  3299 ,  3350 ,  3402 ,  3454 ,  3507 ,  3560 ,  3615 ,  3670 ,  3726 ,  3783 ,  3840 ,  3899 , 3958  ,  4018 ,  4079 ,  4141 ,  4203 ,  4267 ,  4331 ,  4397 ,  4463 ,  4530 ,  4598 ,  4667 ,  4737 ,  4808 ,  4881 ,  4954 ,  5028 ,  5103 ,  5179 ,  5257 ,  5335 , 5415  ,  5495 ,  5577 ,  5660 ,  5744 ,  5830 ,  5916 ,  6004 ,  6093 ,  6183 ,  6275 ,  6368 ,  6462 ,  6557 ,  6654 ,  6752 ,  6852 ,  6953 ,  7055 ,  7159 ,  7265 , 7371  ,  7480 ,  7590 ,  7701 ,  7814 ,  7929 ,  8045 ,  8163 ,  8283 ,  8404 , 8527  ,  8652 ,  8778 ,  8906 ,  9036 ,  9168 ,  9302 ,  9438 ,  9575 ,  9715 , 9856  ,
  20.   10000 ,
  21. };
  22.  
  23.  
  24. #if act_hwPWM_USEEEPROM==1
  25. #include "act_hwPWM_eeprom.h"
  26. struct eeprom_act_hwPWM EEMEM eeprom_act_hwPWM =
  27. {
  28.     {
  29.         ///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.
  30.         0x0000, // ch 1
  31.         0x0000, // ch 2
  32.         0x0000, // ch 3
  33.         0x0000  // ch 4
  34.     },
  35.     0   // crc, must be a correct value, but this will also be handled by the EEPROM module or make scripts
  36. };
  37. #endif
  38.  
  39. #if act_hwPWM_ENABLE_FADE == 1
  40. void act_hwPWM_timer_callback(uint8_t timer)
  41. {
  42.     uint8_t channel = 0;
  43.     for (channel = 0; channel < 4; channel++) {
  44.         /* Check demo states */
  45.         if (pwmValue[channel] == fadeTarget[channel]) {
  46.             switch (demoState[channel])
  47.             {
  48.             case ACT_HWPWM_DEMO_STATE_NOT_RUNNING:
  49.             break;
  50.             case ACT_HWPWM_DEMO_STATE_DECREASE:
  51.                 demoState[channel] = ACT_HWPWM_DEMO_STATE_INCREASE;
  52.                 fadeTarget[channel] = demoHighValue[channel];
  53.                 fadeSpeed[channel] = -fadeSpeed[channel];
  54.             break;
  55.             case ACT_HWPWM_DEMO_STATE_INCREASE:
  56.                 demoState[channel] = ACT_HWPWM_DEMO_STATE_GOBACK;
  57.                 fadeTarget[channel] = demoEndValue[channel];
  58.                 fadeSpeed[channel] = -fadeSpeed[channel];
  59.             break;
  60.             case ACT_HWPWM_DEMO_STATE_GOBACK:
  61.                 demoState[channel] = ACT_HWPWM_DEMO_STATE_NOT_RUNNING;
  62.             break;
  63.             }
  64.         }
  65.        
  66.         /* Change the dimmerValue according to the current fading */
  67.         fadeSpeedCnt[channel]++;
  68.         if (fadeSpeedCnt[channel] == fadeSpeedFrac[channel] && pwmValue[channel] != (fadeTarget[channel]))
  69.         {
  70.             fadeSpeedCnt[channel] = 0;
  71.             uint16_t tempDimVal = pwmValue[channel];
  72.             pwmValue[channel] += (fadeSpeed[channel]*39);
  73.             if ((fadeSpeed[channel] > 0 && (pwmValue[channel] < tempDimVal || pwmValue[channel] >= (fadeTarget[channel]))) ||
  74.                 (fadeSpeed[channel] < 0 && (pwmValue[channel] > tempDimVal || pwmValue[channel] <= (fadeTarget[channel]))))
  75.             {
  76.                 pwmValue[channel] = (fadeTarget[channel]);
  77.             }
  78.             if (pwmValue[channel] > 10000) {
  79.                 pwmValue[channel] = 10000;
  80.             }
  81.             /* if targetvalue was reached then send the netinfo packet */
  82.             if (pwmValue[channel] == fadeTarget[channel])
  83.             {
  84.                 sendInfo[channel] = 1;
  85.             }
  86.         }
  87.     }
  88.  
  89. }
  90. #endif
  91.  
  92.  
  93. void act_hwPWM_Init(void)
  94. {
  95. #if act_hwPWM_USEEEPROM==1
  96.     if (EEDATA_OK)
  97.     {
  98.       ///TODO: Use stored data to set initial values for the module
  99.       pwmValue[0] = eeprom_read_word(EEDATA16.ch1);
  100.       pwmValue[1] = eeprom_read_word(EEDATA16.ch2);
  101.       pwmValue[2] = eeprom_read_word(EEDATA16.ch3);
  102.       pwmValue[3] = eeprom_read_word(EEDATA16.ch4);
  103.     } else
  104.     {   //The CRC of the EEPROM is not correct, store default values and update CRC
  105.       eeprom_write_word_crc(EEDATA16.ch1, 0x0000, WITHOUT_CRC);
  106.       eeprom_write_word_crc(EEDATA16.ch2, 0x0000, WITHOUT_CRC);
  107.       eeprom_write_word_crc(EEDATA16.ch3, 0x0000, WITHOUT_CRC);
  108.       eeprom_write_word_crc(EEDATA16.ch4, 0x0000, WITHOUT_CRC);
  109.       EEDATA_UPDATE_CRC;
  110.     }
  111. #endif
  112.     TCCR1A = 0;
  113.     TCCR1B = 0;
  114.     TCCR0A = 0;
  115.     TCCR0B = 0;
  116.  
  117.     /* set up pwm values */
  118.     cli();
  119.     #if act_hwPWM_CH1_COM>0
  120.     OCR_1=(uint16_t)(pwmValue[0]*act_hwPWM_CH1_FACT)>>8;
  121.     #endif
  122.     #if act_hwPWM_CH2_COM>0
  123.     OCR_2=(uint16_t)(pwmValue[1]*act_hwPWM_CH2_FACT)>>8;
  124.     #endif
  125.     #if act_hwPWM_CH3_COM>0
  126.     OCR_3=(uint16_t)(pwmValue[2]*act_hwPWM_CH3_FACT)>>8;
  127.     #endif
  128.     #if act_hwPWM_CH4_COM>0
  129.     OCR_4=(uint16_t)(pwmValue[3]*act_hwPWM_CH4_FACT)>>8;
  130.     #endif
  131.     sei();
  132.  
  133.     /* set up waveform generation mode for timer 1 */
  134.     #if act_hwPWM_CH1_COM>0
  135.     TCCR1A=((act_hwPWM_CH1_WGM&0x03)<<WGM00);
  136.     TCCR1B=(((act_hwPWM_CH1_WGM>>2)&0x03)<<WGM12);
  137.     #elif act_hwPWM_CH2_COM>0
  138.     TCCR1A=((act_hwPWM_CH2_WGM&0x03)<<WGM00);
  139.     TCCR1B=(((act_hwPWM_CH2_WGM>>2)&0x03)<<WGM12);
  140.     #endif
  141.  
  142.     /* enable outputs for timer 1 */
  143.     #if act_hwPWM_CH1_COM>0
  144.     gpio_set_out(EXP_B);
  145.     #endif
  146.     #if act_hwPWM_CH2_COM>0
  147.     gpio_set_out(EXP_C);
  148.     #endif
  149.  
  150.     /* set up counter mode for timer 1 */
  151.     #if act_hwPWM_CH1_COM>0 || act_hwPWM_CH2_COM>0
  152.     if (pwmValue[0]>0)
  153.     {
  154.         TCCR1A|=(act_hwPWM_CH1_COM<<COM1B0);
  155.     }
  156.     if (pwmValue[1]>0)
  157.     {
  158.         TCCR1A|=(act_hwPWM_CH2_COM<<COM1A0);
  159.     }
  160.     ICR1 = 0xffff;
  161.     #endif
  162.  
  163.     /* enable timer 1 */
  164.     #if act_hwPWM_CH1_COM>0
  165.     TCCR1B|=(act_hwPWM_CH1_CS<<CS10);
  166.     #elif act_hwPWM_CH2_COM>0
  167.     TCCR1B|=(act_hwPWM_CH2_CS<<CS10);
  168.     #endif
  169.  
  170.  
  171.     /* set up waveform generation mode for timer 0 */
  172.     #if act_hwPWM_CH3_COM>0
  173.     TCCR0A=((act_hwPWM_CH3_WGM&0x03)<<WGM00);
  174.     TCCR0B=(((act_hwPWM_CH3_WGM>>2)&0x01)<<WGM02);
  175.     #elif act_hwPWM_CH4_COM>0
  176.     TCCR0A=((act_hwPWM_CH4_WGM&0x03)<<WGM00);
  177.     TCCR0B=(((act_hwPWM_CH4_WGM>>2)&0x01)<<WGM02);
  178.     #endif
  179.  
  180.     /* enable outputs for timer 0 */
  181.     #if act_hwPWM_CH3_COM>0
  182.     gpio_set_out(EXP_F);
  183.     #endif
  184.     #if act_hwPWM_CH4_COM>0
  185.     gpio_set_out(EXP_G);
  186.     #endif
  187.  
  188.     /* set up counter mode for timer 0 */
  189.     #if act_hwPWM_CH3_COM>0 || act_hwPWM_CH4_COM>0
  190.     if (pwmValue[2]>0)
  191.     {
  192.         TCCR0A|=(act_hwPWM_CH3_COM<<COM0A0);
  193.     }
  194.     if (pwmValue[3]>0)
  195.     {
  196.         TCCR0A|=(act_hwPWM_CH4_COM<<COM0B0);
  197.     }
  198.     #endif
  199.  
  200.     /* enable timer 0 */
  201.     #if act_hwPWM_CH3_COM>0
  202.     TCCR0B|=(act_hwPWM_CH3_CS<<CS00);
  203.     #elif act_hwPWM_CH4_COM>0
  204.     TCCR0B|=(act_hwPWM_CH4_CS<<CS00);
  205.     #endif
  206.     //printf("1A %x, 1B %x, 0A %x, 0B %x\n", TCCR1A, TCCR1B, TCCR0A, TCCR0B);
  207.    
  208. #if act_hwPWM_ENABLE_FADE == 1
  209.     Timer_SetTimeout(act_hwPWM_FADE_TIMER, 10, TimerTypeFreeRunning, &act_hwPWM_timer_callback);
  210. #endif
  211.    
  212.     /* Setup timeout for sending the status packet */
  213.     Timer_SetTimeout(act_hwPWM_SEND_STATUS_TIMEOUT, act_hwPWM_SEND_STATUS_INTERVAL_S*1000, TimerTypeFreeRunning, 0);
  214.     //printf("Hello world!\n");
  215. }
  216. uint8_t channel_to_send = 1;
  217. void act_hwPWM_Process(void)
  218. {
  219.     if (Timer_Expired(act_hwPWM_SEND_STATUS_TIMEOUT))
  220.     {
  221.         if (channel_to_send >4) {
  222.           #if act_hwPWM_CH1_COM==0
  223.           channel_to_send = 2;
  224.               #if act_hwPWM_CH2_COM==0
  225.               channel_to_send = 3;
  226.               #if act_hwPWM_CH3_COM==0
  227.                   channel_to_send = 4;
  228.               #else
  229.                   channel_to_send=3;
  230.                 #endif 
  231.               #else
  232.                   channel_to_send=2;
  233.             #endif     
  234.              
  235.           #else
  236.             channel_to_send=1;
  237.           #endif       
  238.        
  239.         }
  240.         sendInfo[channel_to_send-1] = 1;
  241.         channel_to_send++;
  242. #if act_hwPWM_CH1_COM==0
  243.           if (channel_to_send == 1)
  244.             channel_to_send++;
  245. #endif     
  246. #if act_hwPWM_CH2_COM==0
  247.           if (channel_to_send == 2)
  248.             channel_to_send++;
  249. #endif 
  250. #if act_hwPWM_CH3_COM==0
  251.           if (channel_to_send == 3)
  252.             channel_to_send++;
  253. #endif 
  254. #if act_hwPWM_CH4_COM==0
  255.           if (channel_to_send == 4)
  256.             channel_to_send++;
  257. #endif 
  258.        
  259.        
  260.     }
  261.     /* Send netinfo packet (if pwmvalue has changed, and periodically) */
  262.     uint8_t index;
  263.     for(index =0;index < 4; index++){
  264.         if (pwmValue[index] > ACT_HWPWM_MAX_DIM) {
  265.             pwmValue[index] = ACT_HWPWM_MAX_DIM;
  266.         }
  267.         if (sendInfo[index])
  268.         {
  269.             sendInfo[index] = 0;
  270.             StdCan_Msg_t txMsg;
  271.             StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_ACT);
  272.             StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  273.             txMsg.Header.ModuleType = CAN_MODULE_TYPE_ACT_HWPWM;
  274.             txMsg.Header.ModuleId = act_hwPWM_ID;
  275.             txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PWM;
  276.             txMsg.Length = 3;
  277.             txMsg.Data[0] = index;
  278.             txMsg.Data[1] = (0xff&(pwmValue[index]>>8));
  279.             txMsg.Data[2] = (0xff&(pwmValue[index]));
  280.             StdCan_Put(&txMsg);
  281.         }
  282.     }
  283.    
  284.     if (Timer_Expired(act_hwPWM_STORE_VALUE_TIMEOUT))
  285.     {
  286.         if (pwmValue[0] != eeprom_read_word(EEDATA16.ch1))
  287.         {
  288.             eeprom_write_word_crc(EEDATA16.ch1, pwmValue[0], WITH_CRC);
  289.         }
  290.         if (pwmValue[1] != eeprom_read_word(EEDATA16.ch2))
  291.         {
  292.             eeprom_write_word_crc(EEDATA16.ch2, pwmValue[1], WITH_CRC);
  293.         }
  294.         if (pwmValue[2] != eeprom_read_word(EEDATA16.ch3))
  295.         {
  296.             eeprom_write_word_crc(EEDATA16.ch3, pwmValue[2], WITH_CRC);
  297.         }
  298.         if (pwmValue[3] != eeprom_read_word(EEDATA16.ch4))
  299.         {
  300.             eeprom_write_word_crc(EEDATA16.ch4, pwmValue[3], WITH_CRC);
  301.         }
  302.     }
  303.                    
  304. #if act_hwPWM_CH1_COM>0
  305. # if act_hwPWM_CH1_LED>0
  306. #  define CH1_calculation ((lookuptable[pwmValue[0]/39-1]*act_hwPWM_CH1_FACT)>>8)
  307. # else
  308. #  define CH1_calculation ((pwmValue[0]*act_hwPWM_CH1_FACT)>>8)
  309. # endif
  310.     if (OCR_1 != (uint16_t)CH1_calculation) {
  311.         cli(); 
  312.         OCR_1=(uint16_t)CH1_calculation;
  313.         if (OCR_1==0)
  314.         {
  315.             TCCR1A&=~((1<<COM1B0)|(1<<COM1B1));
  316.         }
  317.         else
  318.         {
  319.             TCCR1A|=(act_hwPWM_CH1_COM<<COM1B0);
  320.         }
  321.         sei();
  322.         Timer_SetTimeout(act_hwPWM_STORE_VALUE_TIMEOUT, act_hwPWM_STORE_VALUE_TIMEOUT_TIME*1000, TimerTypeOneShot, 0);
  323.     }
  324. #endif
  325. #if act_hwPWM_CH2_COM>0
  326. # if act_hwPWM_CH2_LED>0
  327. #  define CH2_calculation ((uint32_t)((lookuptable[pwmValue[1]/39-1]*act_hwPWM_CH2_FACT)>>8))
  328. # else
  329. #  define CH2_calculation ((uint32_t)((pwmValue[1]*act_hwPWM_CH2_FACT)>>8))
  330. # endif
  331.     if (OCR_2 != (uint16_t)CH2_calculation) {
  332.         cli(); 
  333.         OCR_2=(uint16_t)CH2_calculation;
  334.         if (OCR_2==0)
  335.         {
  336.             TCCR1A&=~((1<<COM1A0)|(1<<COM1A1));
  337.         }
  338.         else
  339.         {
  340.             TCCR1A|=(act_hwPWM_CH2_COM<<COM1A0);
  341.         }
  342.         sei();
  343.         Timer_SetTimeout(act_hwPWM_STORE_VALUE_TIMEOUT, act_hwPWM_STORE_VALUE_TIMEOUT_TIME*1000, TimerTypeOneShot, 0);
  344.     }
  345. #endif
  346. #if act_hwPWM_CH3_COM>0
  347. # if act_hwPWM_CH3_LED>0
  348. #  define CH3_calculation ((lookuptable[pwmValue[2]/39-1]*act_hwPWM_CH3_FACT)>>8)
  349. # else
  350. #  define CH3_calculation ((pwmValue[2]*act_hwPWM_CH3_FACT)>>8)
  351. # endif
  352.     if (OCR_3 != (uint16_t)CH3_calculation) {
  353.         cli(); 
  354.         OCR_3=(uint16_t)CH3_calculation;
  355.         if (OCR_3==0)
  356.         {
  357.             TCCR0A &= ~((1<<COM0A0)|(1<<COM0A1));
  358.         }
  359.         else
  360.         {
  361.             TCCR0A|=(act_hwPWM_CH3_COM<<COM0A0);
  362.         }
  363.         sei();
  364.         Timer_SetTimeout(act_hwPWM_STORE_VALUE_TIMEOUT, act_hwPWM_STORE_VALUE_TIMEOUT_TIME*1000, TimerTypeOneShot, 0);
  365.     }
  366. #endif
  367. #if act_hwPWM_CH4_COM>0
  368. # if act_hwPWM_CH4_LED>0
  369. #  define CH4_calculation ((lookuptable[pwmValue[3]/39-1]*act_hwPWM_CH4_FACT)>>8)
  370. # else
  371. #  define CH4_calculation ((pwmValue[3]*act_hwPWM_CH4_FACT)>>8)
  372. # endif
  373.     if (OCR_4 != (uint16_t)CH4_calculation) {
  374.         cli(); 
  375.         OCR_4=(uint16_t)CH4_calculation;
  376.         if (OCR_4==0)
  377.         {
  378.             TCCR0A &= ~((1<<COM0B0)|(1<<COM0B1));
  379.         }
  380.         else
  381.         {
  382.             TCCR0A|=(act_hwPWM_CH4_COM<<COM0B0);
  383.         }
  384.         sei();
  385.         Timer_SetTimeout(act_hwPWM_STORE_VALUE_TIMEOUT, act_hwPWM_STORE_VALUE_TIMEOUT_TIME*1000, TimerTypeOneShot, 0);
  386.     }
  387. #endif
  388. }
  389.  
  390. void act_hwPWM_HandleMessage(StdCan_Msg_t *rxMsg)
  391. {
  392.     if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_ACT &&
  393.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_TO_OWNER &&
  394.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_ACT_HWPWM &&
  395.         rxMsg->Header.ModuleId == act_hwPWM_ID)
  396.     {
  397.         uint8_t channel = 0;
  398.         switch (rxMsg->Header.Command)
  399.         {
  400.         case CAN_MODULE_CMD_PHYSICAL_PWM:
  401.             if (rxMsg->Length == 3) {
  402.                 channel = rxMsg->Data[0];
  403.                 pwmValue[channel] = (rxMsg->Data[1]<<8)+(rxMsg->Data[2]);
  404.             }
  405.            
  406.         break;
  407. #if act_hwPWM_ENABLE_FADE == 1
  408.         case CAN_MODULE_CMD_HWPWM_DEMO:     /* Demo(channel, speed, steps) */
  409.             if (rxMsg->Length == 4) {
  410.                 channel = rxMsg->Data[0];
  411.                 uint8_t speed = rxMsg->Data[1];
  412.                 uint16_t steps = (rxMsg->Data[2]<<8)+(rxMsg->Data[3]);
  413.                
  414.                 fadeSpeedCnt[channel] = 0;
  415.                 fadeSpeed[channel] = 0;
  416.                 if (speed == 0) {
  417.                     /* do nothing */
  418.                 } else {
  419.                     uint16_t diffToMin = pwmValue[channel] - ACT_HWPWM_MIN_DIM;
  420.                     uint16_t diffToMax = ACT_HWPWM_MAX_DIM - pwmValue[channel];
  421.                
  422.                     demoEndValue[channel] = pwmValue[channel];
  423.                     if (diffToMin >= steps && diffToMax >= steps)
  424.                     {
  425.                         /* not close to min or max */
  426.                         fadeTarget[channel] = pwmValue[channel] - steps;
  427.                         demoHighValue[channel] = pwmValue[channel] + steps;
  428.                     }
  429.                     else if (diffToMin >= steps)
  430.                     {
  431.                         /* close to max */
  432.                         fadeTarget[channel] = pwmValue[channel] - steps - steps + diffToMax;
  433.                         demoHighValue[channel] = ACT_HWPWM_MAX_DIM;
  434.                     }
  435.                     else if (diffToMax >= steps)
  436.                     {
  437.                         /* close to min */
  438.                         fadeTarget[channel] = ACT_HWPWM_MIN_DIM;
  439.                         demoHighValue[channel] = pwmValue[channel] + steps + steps - diffToMin;
  440.                     }
  441.                     demoState[channel] = ACT_HWPWM_DEMO_STATE_DECREASE;
  442.                
  443.                     if ((speed&0x80) == 0x80) {
  444.                         fadeSpeed[channel] = (speed&0x7f)+1;
  445.                         fadeSpeedFrac[channel] = 1;
  446.                     } else {
  447.                         fadeSpeed[channel] = 1;
  448.                         fadeSpeedFrac[channel] = 0x80-(speed&0x7f);
  449.                     }
  450.                     if (fadeTarget[channel] <= pwmValue[channel]) {
  451.                         fadeSpeed[channel] = -fadeSpeed[channel];
  452.                     }
  453.                 }
  454.             }
  455.         break;
  456.        
  457.         case CAN_MODULE_CMD_HWPWM_START_FADE:   /* StartFade(channel, speed, direction) */
  458.             if (rxMsg->Length == 3) {
  459.                
  460.                 channel = rxMsg->Data[0];
  461.                 uint8_t speed = rxMsg->Data[1];
  462.                 uint8_t direction = rxMsg->Data[2];
  463.                 demoState[channel] = ACT_HWPWM_DEMO_STATE_NOT_RUNNING;
  464.                 fadeSpeedCnt[channel] = 0;
  465.                 fadeSpeed[channel] = 0;
  466.                 uint16_t endValue = 0;
  467.                 if (direction == CAN_MODULE_ENUM_HWPWM_START_FADE_DIRECTION_INCREASE) {
  468.                     endValue = ACT_HWPWM_MAX_DIM;
  469.                 } else if (direction == CAN_MODULE_ENUM_HWPWM_START_FADE_DIRECTION_DECREASE) {
  470.                     endValue = ACT_HWPWM_MIN_DIM;
  471.                 }
  472.                    
  473.                 if (speed == 0) {
  474.                     pwmValue[channel] = endValue;   /* set dimmer value immediately */
  475.                     sendInfo[channel] = 1;      /* send netinfo with the current dimmervalue*/
  476.                 } else {
  477.                     fadeTarget[channel] = endValue;
  478.                     if (fadeTarget[channel] != pwmValue[channel]) {
  479.                         if ((speed&0x80) == 0x80) {
  480.                             fadeSpeed[channel] = (speed&0x7f)+1;
  481.                             fadeSpeedFrac[channel] = 1;
  482.                         } else {
  483.                             fadeSpeed[channel] = 1;
  484.                             fadeSpeedFrac[channel] = 0x80-(speed&0x7f);
  485.                         }
  486.                         if (fadeTarget[channel] < pwmValue[channel]) {
  487.                             fadeSpeed[channel] = -fadeSpeed[channel];
  488.                         }
  489.                     }
  490.                 }
  491.             }
  492.         break;
  493.  
  494.         case CAN_MODULE_CMD_HWPWM_STOP_FADE:    /* StopFade(channel) */
  495.             if (rxMsg->Length == 1) {
  496.                 channel = rxMsg->Data[0];
  497.                 demoState[channel] = ACT_HWPWM_DEMO_STATE_NOT_RUNNING;
  498.                 fadeSpeed[channel] = 0;
  499.                 sendInfo[channel] = 1;      /* send netinfo with the current dimmervalue*/
  500.             }
  501.         break;
  502.  
  503.         case CAN_MODULE_CMD_HWPWM_ABS_FADE: /* AbsFade(channel, speed, endValue) */
  504.             if (rxMsg->Length == 4) {
  505.                 channel = rxMsg->Data[0];
  506.                 uint8_t speed = rxMsg->Data[1];
  507.                 uint16_t endValue = (rxMsg->Data[2]<<8)+(rxMsg->Data[3]);
  508.                 demoState[channel] = ACT_HWPWM_DEMO_STATE_NOT_RUNNING;
  509.                 fadeSpeedCnt[channel] = 0;
  510.                 fadeSpeed[channel] = 0;
  511.                 if (speed == 0) {
  512.                     pwmValue[channel] = endValue;   /* set dimmer value immediately */
  513.                     sendInfo[channel] = 1;      /* send netinfo with the current dimmervalue*/
  514.                 } else {
  515.                     fadeTarget[channel] = endValue;
  516.                     if (fadeTarget[channel] != pwmValue[channel]) {
  517.                         if ((speed&0x80) == 0x80) {
  518.                             fadeSpeed[channel] = (speed&0x7f)+1;
  519.                             fadeSpeedFrac[channel] = 1;
  520.                         } else {
  521.                             fadeSpeed[channel] = 1;
  522.                             fadeSpeedFrac[channel] = 0x80-(speed&0x7f);
  523.                         }
  524.                         if (fadeTarget[channel] < pwmValue[channel]) {
  525.                             fadeSpeed[channel] = -fadeSpeed[channel];
  526.                         }
  527.                     }
  528.                 }
  529.                 //printf("abs fade %d %d %d!\n",fadeTarget[channel], endValue ,pwmValue[channel] );
  530.             }
  531.         break;
  532.  
  533.         case CAN_MODULE_CMD_HWPWM_REL_FADE: /* RelFade(channel, speed, direction, steps) */
  534.             if (rxMsg->Length == 5) {
  535.                
  536.                 channel = rxMsg->Data[0];
  537.                 uint8_t speed = rxMsg->Data[1];
  538.                 uint8_t direction = rxMsg->Data[2];
  539.                 uint16_t steps = (rxMsg->Data[3]<<8)+(rxMsg->Data[4]);
  540.                
  541.                 demoState[channel] = ACT_HWPWM_DEMO_STATE_NOT_RUNNING;
  542.                 fadeSpeedCnt[channel] = 0;
  543.                 fadeSpeed[channel] = 0;
  544.                 uint16_t tempDimVal = pwmValue[channel];
  545.                 uint16_t tempDimVal2 = pwmValue[channel];
  546.                 if (direction == CAN_MODULE_ENUM_HWPWM_REL_FADE_DIRECTION_INCREASE) {                   /* if increase */
  547.                     tempDimVal2 += steps;               /* calculate new value */
  548.                     if (tempDimVal2 < tempDimVal) {     /* make overflow test */
  549.                         tempDimVal2 = ACT_HWPWM_MAX_DIM;
  550.                     }
  551.                 } else if (direction == CAN_MODULE_ENUM_HWPWM_REL_FADE_DIRECTION_DECREASE) {            /* if decrease */
  552.                     tempDimVal2 -= steps;
  553.                     if (tempDimVal2 > tempDimVal) {
  554.                         tempDimVal2 = ACT_HWPWM_MIN_DIM;
  555.                     }
  556.                 }
  557.                 if (speed == 0) {
  558.                     pwmValue[channel] = tempDimVal2;        /* set dimmer value immediately */
  559.                     sendInfo[channel] = 1;              /* send netinfo with the current dimmervalue*/
  560.                 } else {
  561.                     fadeTarget[channel] = tempDimVal2;      /* set the fade target */
  562.                    
  563.                     if (fadeTarget[channel] != pwmValue[channel]) {
  564.                         if ((speed&0x80) == 0x80) {
  565.                             fadeSpeed[channel] = (speed&0x7f)+1;
  566.                             fadeSpeedFrac[channel] = 1;
  567.                         } else {
  568.                             fadeSpeed[channel] = 1;
  569.                             fadeSpeedFrac[channel] = 0x80-(speed&0x7f);
  570.                         }
  571.                         if (fadeTarget[channel] < pwmValue[channel]) {
  572.                             fadeSpeed[channel] = -fadeSpeed[channel];
  573.                         }
  574.                     }
  575.                 }
  576.             }
  577.         break;
  578. #endif
  579.  
  580.         }
  581.     }
  582. }
  583.  
  584. void act_hwPWM_List(uint8_t ModuleSequenceNumber)
  585. {
  586.     StdCan_Msg_t txMsg;
  587.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_ACT);
  588.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  589.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_ACT_HWPWM;
  590.     txMsg.Header.ModuleId = act_hwPWM_ID;
  591.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  592.     txMsg.Length = 6;
  593.  
  594.     uint32_t HwId=BIOS_GetHwId();
  595.     txMsg.Data[0] = HwId&0xff;
  596.     txMsg.Data[1] = (HwId>>8)&0xff;
  597.     txMsg.Data[2] = (HwId>>16)&0xff;
  598.     txMsg.Data[3] = (HwId>>24)&0xff;
  599.    
  600.     txMsg.Data[4] = NUMBER_OF_MODULES;
  601.     txMsg.Data[5] = ModuleSequenceNumber;
  602.  
  603.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  604. }
  605.