Subversion Repositories HomeAutomation

Rev

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

  1.  
  2. #include "act_dimmer230.h"
  3.  
  4. //#define USEDEMO
  5.  
  6. int8_t fadeSpeedCh1 = 0;
  7. uint8_t fadeSpeedFracCh1 = 0;
  8. uint8_t fadeTargetCh1 = 0;
  9. uint8_t fadeSpeedCntCh1 = 0;
  10.  
  11. #ifdef USEDEMO
  12. uint8_t demo = 0;
  13. //uint8_t demo = 2; //demo one way
  14. //uint8_t demo = 3; //disable demo
  15. uint8_t democnt = 0;
  16. #define DEMOSTEPS 2
  17. #define DEMOSTEPS2 1
  18. #endif
  19.  
  20. //#define MEASURE_PERIOD
  21. #ifdef MEASURE_PERIOD
  22. uint16_t periodTime = 0;
  23.             //measured during init (by taking the time difference between two zero cross)
  24.             //not used, bad idea, the powerStepTable below asumes 10000
  25. #endif
  26. uint16_t xcTimeDiff=0;
  27.             //zero cross sync (time between pos flank of xc-detection and real zero cross)
  28. uint8_t dimmerValueCh1 = 0;
  29.             //store in eeprom later
  30.             //value of 0 is zero output, value of 255 is max output (ACT_DIMMMER230_MIN_DIM, ACT_DIMMMER230_MAX_DIM)
  31. uint8_t state = ACT_DIMMMER230_STATE_IDLE;
  32. const uint16_t powerStepTable[] PROGMEM = {845, 1068, 1225, 1352, 1459, 1553, 1638, 1716, 1788, 1855, 1917, 1976, 2032, 2086, 2138, 2188, 2236, 2282, 2327, 2370, 2412, 2453, 2493, 2532, 2570, 2607, 2643, 2679, 2714, 2748, 2782, 2815, 2848, 2880, 2911, 2942, 2972, 3002, 3032, 3061, 3090, 3119, 3147, 3175, 3203, 3230, 3257, 3284, 3311, 3337, 3363, 3389, 3415, 3440, 3465, 3490, 3515, 3539, 3563, 3587, 3611, 3635, 3659, 3682, 3705, 3728, 3751, 3774, 3797, 3820, 3843, 3865, 3887, 3909, 3931, 3953, 3975, 3997, 4019, 4041, 4062, 4083, 4104, 4125, 4146, 4167, 4188, 4209, 4230, 4251, 4272, 4292, 4313, 4333, 4354, 4374, 4395, 4415, 4435, 4455, 4476, 4496, 4516, 4536, 4556, 4576, 4596, 4615, 4635, 4655, 4675, 4694, 4714, 4734, 4754, 4773, 4793, 4813, 4832, 4852, 4872, 4891, 4911, 4931, 4951, 4970, 4990};
  33.  
  34. #if act_dimmer230_SYNC>0
  35. uint8_t zeroCrossCnt = 0;
  36. #endif
  37.  
  38. ISR (TIMER1_COMPA_vect)
  39. {
  40.     //testa hur lång denna loop behöver vara
  41.     //verkar fungera upp till 249-250 sen blir det för korta pulser
  42.     act_dimmer230_CHAN1_PORT |= _BV(act_dimmer230_CHAN1_BIT);
  43.     uint8_t dummycnt = 40;
  44.     while (dummycnt > 0)
  45.     {
  46.         dummycnt++;
  47.         asm("nop");
  48.         asm("nop");
  49.     }
  50.     act_dimmer230_CHAN1_PORT &= ~_BV(act_dimmer230_CHAN1_BIT);         
  51.    
  52.     TIMSK1=0;                           //disable timer interrupt
  53.     state = ACT_DIMMMER230_STATE_IDLE;
  54. }
  55.  
  56. ISR (act_dimmer230_ZC_PCINT_vect)
  57. {
  58.     //only execute if zerocross pin is low
  59.     if (!(act_dimmer230_ZC_PIN&(1<<act_dimmer230_ZC_BIT)))
  60.     {
  61.         uint16_t newTimerVal = xcTimeDiff;
  62.  
  63.         //here new timer value is calculated
  64.  
  65.         if (dimmerValueCh1 > 0 && dimmerValueCh1 <= 127)
  66.         {
  67.             newTimerVal += ACT_DIMMMER230_PERIOD_TIME - pgm_read_word(&powerStepTable[dimmerValueCh1-1]);
  68.         }
  69.         else if (dimmerValueCh1 < 255)
  70.         {
  71.             newTimerVal += pgm_read_word(&powerStepTable[254-dimmerValueCh1]);
  72.         }
  73.         else if (dimmerValueCh1 == 255)
  74.         {
  75.             newTimerVal += 100; //almost max, to make sure we don't fire before zerocross
  76.         }
  77.        
  78.         if (newTimerVal > ACT_DIMMMER230_PERIOD_TIME)
  79.         {
  80.             newTimerVal -= ACT_DIMMMER230_PERIOD_TIME;
  81.         }
  82.  
  83.         if (dimmerValueCh1 > 0)
  84.         {
  85.             TCNT1 = 0;              //reset timer1 count register
  86.             OCR1A = newTimerVal;
  87.  
  88.             //enable timer and timer interrupt
  89.             TIFR1=(1<<OCF1A);       //clear interrupt flag before enabling interrupt
  90.             TIMSK1|=(1<<OCIE1A);
  91.  
  92.             state = ACT_DIMMMER230_STATE_TIMER_ON;
  93.         }
  94.        
  95.         fadeSpeedCntCh1++;
  96.         if (fadeSpeedCntCh1 == fadeSpeedFracCh1)
  97.         {
  98.             fadeSpeedCntCh1 = 0;
  99.             uint8_t tempDimVal = dimmerValueCh1;
  100.             dimmerValueCh1 += fadeSpeedCh1;
  101.             if ((fadeSpeedCh1 > 0 && (dimmerValueCh1 < tempDimVal || dimmerValueCh1 >= fadeTargetCh1)) ||
  102.                 (fadeSpeedCh1 < 0 && (dimmerValueCh1 > tempDimVal || dimmerValueCh1 <= fadeTargetCh1)))
  103.             {
  104.                 dimmerValueCh1 = fadeTargetCh1;
  105.                 fadeSpeedCh1 = 0;
  106.             }
  107.         }
  108.        
  109.        
  110. #if act_dimmer230_SYNC>0
  111.         zeroCrossCnt++;
  112.         if (zeroCrossCnt >= act_dimmer230_SYNC)
  113.         {
  114.             zeroCrossCnt = 0;
  115.             //TODO: send sync-message on can
  116.  
  117.             StdCan_Msg_t txMsg;
  118.             txMsg.Length = 6;
  119.             txMsg.Data[0] = (newTimerVal>>8)&0xff;
  120.             txMsg.Data[1] = newTimerVal&0xff;
  121.             //txMsg.Data[2] = (periodTime>>8)&0xff;
  122.             //txMsg.Data[3] = periodTime&0xff;
  123.             txMsg.Data[4] = (xcTimeDiff>>8)&0xff;
  124.             txMsg.Data[5] = xcTimeDiff&0xff;
  125.             StdCan_Put(&txMsg);
  126.  
  127. #ifdef USEDEMO
  128.             if (demo == 0 || demo == 2) {
  129.                 democnt++;
  130.                 if (democnt==DEMOSTEPS)
  131.                 {
  132.                     democnt = 0;
  133.                     uint8_t tempDim=dimmerValueCh1;
  134.                     dimmerValueCh1+=DEMOSTEPS2;
  135.                     if (dimmerValueCh1<tempDim && demo == 0) {
  136.                         dimmerValueCh1=ACT_DIMMMER230_MAX_DIM;
  137.                     }
  138.                 }
  139.                 if (dimmerValueCh1 == ACT_DIMMMER230_MAX_DIM && demo == 0) {
  140.                     demo = 1;
  141.                 }
  142.             } else if (demo == 1) {
  143.                 democnt++;
  144.                 if (democnt==DEMOSTEPS)
  145.                 {
  146.                     democnt = 0;
  147.                     uint8_t tempDim=dimmerValueCh1;
  148.                     dimmerValueCh1-=DEMOSTEPS2;
  149.                     if (dimmerValueCh1>tempDim) {
  150.                         dimmerValueCh1=ACT_DIMMMER230_MIN_DIM;
  151.                     }
  152.                 }
  153.                 if (dimmerValueCh1 == ACT_DIMMMER230_MIN_DIM) {
  154.                     demo = 0;
  155.                 }
  156.             }
  157. #endif //USEDEMO
  158.         }
  159. #endif     
  160.     }
  161. }
  162.  
  163. void act_dimmer230_Init(void)
  164. {
  165.     // set dimmer channel1 port to output 0
  166.     act_dimmer230_CHAN1_PORT &= ~_BV(act_dimmer230_CHAN1_BIT);
  167.     act_dimmer230_CHAN1_DDR |= _BV(act_dimmer230_CHAN1_BIT);
  168.     // set zero cross detection port to input, no pullup
  169.     act_dimmer230_ZC_PORT &= ~_BV(act_dimmer230_ZC_BIT);
  170.     act_dimmer230_ZC_DDR &= ~_BV(act_dimmer230_ZC_BIT);
  171.    
  172.     TIMSK1=0;                           //disable timer interrupt
  173.     TCCR1A=0;
  174.    
  175.     //wait for high (ac leaving zero cross)
  176.     while (!(act_dimmer230_ZC_PIN&(1<<act_dimmer230_ZC_BIT))) { }
  177.     TCCR1B=(1<<CS11);                   //enable timer, set to prescaler 8, must be changed if cpu freq is changed
  178.     //wait for low (ac approaching zero cross)
  179.     while (act_dimmer230_ZC_PIN&(1<<act_dimmer230_ZC_BIT)) { }
  180.     uint16_t timeAtFall = TCNT1;    //Timer_GetTicks();
  181.     //wait for high (ac leaving zero cross)
  182.     while (!(act_dimmer230_ZC_PIN&(1<<act_dimmer230_ZC_BIT))) { }
  183.     uint16_t timeAtRise = TCNT1;    //Timer_GetTicks();
  184.  
  185. #ifdef MEASURE_PERIOD
  186.     //wait for low (ac approaching zero cross)
  187.     while (act_dimmer230_ZC_PIN&(1<<act_dimmer230_ZC_BIT)) { }
  188.     //wait for high (ac leaving zero cross)
  189.     while (!(act_dimmer230_ZC_PIN&(1<<act_dimmer230_ZC_BIT))) { }
  190.     uint16_t timeAtRise2 = TCNT1;   //Timer_GetTicks();
  191.     if (timeAtRise < timeAtRise2) {
  192.         periodTime = timeAtRise2 - timeAtRise;
  193.     }
  194. #endif
  195.  
  196.     // warning, watch out for wrap around on timestamps (something is broken if wrapped)
  197.     if (timeAtFall < timeAtRise) {
  198.         //calculate time from falling edge to ac zero cross value
  199.         xcTimeDiff = timeAtRise-timeAtFall;
  200.         xcTimeDiff = xcTimeDiff >> 1; //divide by two
  201.     }
  202.  
  203.     //setup interrupt on zerocross, pcint
  204.     PCMSK0=(1<<act_dimmer230_ZC_PCINT_BIT);
  205.     PCIFR=(1<<act_dimmer230_ZC_PCIF);   //clear any pending interrupt before enabling interrupts
  206.     PCICR=(1<<act_dimmer230_ZC_PCIE);   //enable interrupt for PCINT
  207. }
  208.  
  209. void act_dimmer230_Process(void)
  210. {
  211.     ///TODO: Stuff that needs doing is done here
  212. }
  213.  
  214. void act_dimmer230_HandleMessage(StdCan_Msg_t *rxMsg)
  215. {
  216.     if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_ACT &&
  217.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_TO_OWNER &&
  218.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_ACT_DIMMER230 &&
  219.         rxMsg->Header.ModuleId == act_dimmer230_ID)
  220.     {
  221.         switch (rxMsg->Header.Command)
  222.         {
  223.         case CAN_MODULE_CMD_DIMMER230_DEMO:     // Demo(channel, speed, steps)
  224.             if (rxMsg->Length == 3) {
  225.                
  226.             }
  227.         break;
  228.        
  229.         case CAN_MODULE_CMD_DIMMER230_START_FADE:   // StartFade(channel, speed, direction), just an alias of ABS_FADE
  230.             if (rxMsg->Length == 3) {
  231.                 uint8_t channel = rxMsg->Data[0];
  232.                 uint8_t speed = rxMsg->Data[1];
  233.                 uint8_t direction = rxMsg->Data[2];
  234.                
  235.                 fadeSpeedCntCh1 = 0;
  236.                 fadeSpeedCh1 = 0;
  237.                 uint8_t endValue = 0;
  238.                 if (direction == 1) {
  239.                     endValue = ACT_DIMMMER230_MAX_DIM;
  240.                 } else if (direction == 0) {
  241.                     endValue = ACT_DIMMMER230_MIN_DIM;
  242.                 }
  243.                    
  244.                 if (speed == 0) {
  245.                     dimmerValueCh1 = endValue;  //set dimmer value immediately
  246.                 } else {
  247.                     fadeTargetCh1 = endValue;
  248.                     if (fadeTargetCh1 != dimmerValueCh1) {
  249.                         if ((speed&0x80) == 0) {
  250.                             fadeSpeedCh1 = speed&0x7f;
  251.                             fadeSpeedFracCh1 = 1;
  252.                         } else {
  253.                             fadeSpeedCh1 = 1;
  254.                             fadeSpeedFracCh1 = speed&0x7f;
  255.                         }
  256.                         if (fadeTargetCh1 < dimmerValueCh1) {
  257.                             fadeSpeedCh1 = -fadeSpeedCh1;
  258.                         }
  259.                     }
  260.                 }
  261.             }
  262.         break;
  263.  
  264.         case CAN_MODULE_CMD_DIMMER230_STOP_FADE:    // StopFade(channel)
  265.             if (rxMsg->Length == 1) {
  266.                 fadeSpeedCh1 = 0;
  267.             }
  268.         break;
  269.  
  270.         case CAN_MODULE_CMD_DIMMER230_ABS_FADE: // AbsFade(channel, speed, endValue)
  271.             if (rxMsg->Length == 3) {
  272.                 uint8_t channel = rxMsg->Data[0];
  273.                 uint8_t speed = rxMsg->Data[1];
  274.                 uint8_t endValue = rxMsg->Data[2];
  275.  
  276.                 fadeSpeedCntCh1 = 0;
  277.                 fadeSpeedCh1 = 0;
  278.                 if (speed == 0) {
  279.                     dimmerValueCh1 = endValue;  //set dimmer value immediately
  280.                 } else {
  281.                     fadeTargetCh1 = endValue;
  282.                     if (fadeTargetCh1 != dimmerValueCh1) {
  283.                         if ((speed&0x80) == 0) {
  284.                             fadeSpeedCh1 = speed&0x7f;
  285.                             fadeSpeedFracCh1 = 1;
  286.                         } else {
  287.                             fadeSpeedCh1 = 1;
  288.                             fadeSpeedFracCh1 = speed&0x7f;
  289.                         }
  290.                         if (fadeTargetCh1 < dimmerValueCh1) {
  291.                             fadeSpeedCh1 = -fadeSpeedCh1;
  292.                         }
  293.                     }
  294.                 }
  295.             }
  296.         break;
  297.  
  298.         case CAN_MODULE_CMD_DIMMER230_REL_FADE: // RelFade(channel, speed, direction, steps)
  299.             if (rxMsg->Length == 4) {
  300.                 uint8_t channel = rxMsg->Data[0];
  301.                 uint8_t speed = rxMsg->Data[1];
  302.                 uint8_t direction = rxMsg->Data[2];
  303.                 uint8_t steps = rxMsg->Data[3];
  304.                
  305.                 fadeSpeedCntCh1 = 0;
  306.                 fadeSpeedCh1 = 0;
  307.                 uint8_t tempDimVal = dimmerValueCh1;
  308.                 uint8_t tempDimVal2 = dimmerValueCh1;
  309.                 if (direction == 1) {                   //if increase
  310.                     tempDimVal2 += steps;               //calculate new value
  311.                     if (tempDimVal2 < tempDimVal) {     //make overflow test
  312.                         tempDimVal2 = ACT_DIMMMER230_MAX_DIM;
  313.                     }
  314.                 } else if (direction == 0) {            //if decrease
  315.                     tempDimVal2 -= steps;
  316.                     if (tempDimVal2 > tempDimVal) {
  317.                         tempDimVal2 = ACT_DIMMMER230_MIN_DIM;
  318.                     }
  319.                 }
  320.                 if (speed == 0) {
  321.                     dimmerValueCh1 = tempDimVal2;       //set dimmer value immediately
  322.                 } else {
  323.                     fadeTargetCh1 = tempDimVal2;        //set the fade target
  324.                    
  325.                     if (fadeTargetCh1 != dimmerValueCh1) {
  326.                         if ((speed&0x80) == 0) {
  327.                             fadeSpeedCh1 = speed&0x7f;
  328.                             fadeSpeedFracCh1 = 1;
  329.                         } else {
  330.                             fadeSpeedCh1 = 1;
  331.                             fadeSpeedFracCh1 = speed&0x7f;
  332.                         }
  333.                         if (fadeTargetCh1 < dimmerValueCh1) {
  334.                             fadeSpeedCh1 = -fadeSpeedCh1;
  335.                         }
  336.                     }
  337.                 }
  338.                
  339.             }
  340.         break;
  341. }
  342.     }
  343. }
  344.  
  345. void act_dimmer230_List(uint8_t ModuleSequenceNumber)
  346. {
  347.     StdCan_Msg_t txMsg;
  348.    
  349.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_ACT);
  350.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  351.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_ACT_DIMMER230;
  352.     txMsg.Header.ModuleId = act_dimmer230_ID;
  353.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  354.     txMsg.Length = 6;
  355.  
  356.     txMsg.Data[0] = NODE_HW_ID_BYTE0;
  357.     txMsg.Data[1] = NODE_HW_ID_BYTE1;
  358.     txMsg.Data[2] = NODE_HW_ID_BYTE2;
  359.     txMsg.Data[3] = NODE_HW_ID_BYTE3;
  360.    
  361.     txMsg.Data[4] = NUMBER_OF_MODULES;
  362.     txMsg.Data[5] = ModuleSequenceNumber;
  363.    
  364.     StdCan_Put(&txMsg);
  365. }
  366.