9 #include "MultiChannelDevice.h"
11 #include "actors/PWM.h"
15 #define LOGIC_INACTIVE 0
21 #define LOGIC_ORINVERS 6
22 #define LOGIC_ANDINVERS 7
26 #define LOGIC_PLUSINVERS 11
27 #define LOGIC_MINUSINVERS 12
28 #define LOGIC_MULINVERS 13
29 #define LOGIC_INVERSPLUS 14
30 #define LOGIC_INVERSMINUS 15
31 #define LOGIC_INVERSMUL 16
34 #undef AS_CM_JT_RAMPON
35 #define AS_CM_JT_RAMPON AS_CM_JT_REFON
36 #undef AS_CM_JT_RAMPOFF
37 #define AS_CM_JT_RAMPOFF AS_CM_JT_REFOFF
41 DEFREGISTER(DimmerReg1,CREG_AES_ACTIVE,CREG_TRANSMITTRYMAX,CREG_OVERTEMPLEVEL,
42 CREG_REDUCETEMPLEVEL,CREG_REDUCELEVEL,CREG_POWERUPACTION,CREG_STATUSINFO,
43 CREG_CHARACTERISTIC,CREG_LOGICCOMBINATION)
45 class DimmerList1 :
public RegList1<DimmerReg1> {
47 DimmerList1 (uint16_t addr) : RegList1<DimmerReg1>(addr) {}
60 logicCombination(LOGIC_OR);
64 DEFREGISTER(DimmerReg3,PREG_CTRAMPONOFF,PREG_CTDELAYONOFF,PREG_CTONOFF,
65 PREG_CONDVALUELOW,PREG_CONDVALUEHIGH,PREG_ONDELAYTIME,PREG_ONTIME,
66 PREG_OFFDELAYTIME,PREG_OFFTIME,PREG_ACTIONTYPE,PREG_JTONOFF,
67 PREG_JTDELAYONOFF,PREG_JTRAMPONOFF,PREG_DELAYMODE,PREG_OFFLEVEL,
68 PREG_ONMINLEVEL,PREG_ONLEVEL,PREG_RAMPSTARTSTEP,PREG_RAMPONTIME,
69 PREG_RAMPOFFTIME,PREG_DIMMINLEVEL,PREG_DIMMAXLEVEL,PREG_DIMSTEP,
70 PREG_OFFDELAYSTEP,PREG_OFFDELAYNEWTIME,PREG_OFFDELAYOLDTIME,
71 PREG_ELSEACTIONTYPE,PREG_ELSEJTONOFF,PREG_ELSEJTDELAYONOFF,
74 typedef RegList3<DimmerReg3> DimmerPeerList;
80 DimmerPeerList ssl = sh();
94 ssl.actionType(AS_CM_ACTIONTYPE_JUMP_TO_TARGET);
97 ssl.offDelayBlink(
true);
101 ssl.rampStartStep(10);
105 ssl.dimMaxLevel(200);
107 ssl.offDelayStep(10);
108 ssl.offDelayNewTime(5);
109 ssl.offDelayOldTime(5);
110 ssl.elseActionType(AS_CM_ACTIONTYPE_INACTIVE);
113 ssl.elseJtOn(AS_CM_JT_ONDELAY);
114 ssl.elseJtOff(AS_CM_JT_ONDELAY);
115 ssl.elseJtDlyOn(AS_CM_JT_ONDELAY);
116 ssl.elseJtDlyOff(AS_CM_JT_ONDELAY);
117 ssl.elseJtRampOn(AS_CM_JT_ONDELAY);
118 ssl.elseJtRampOff(AS_CM_JT_ONDELAY);
134 ssl.actionType(AS_CM_ACTIONTYPE_JUMP_TO_TARGET);
138 ssl.offDelayBlink(
true);
142 ssl.rampStartStep(10);
146 ssl.dimMaxLevel(200);
148 ssl.offDelayStep(10);
149 ssl.offDelayNewTime(5);
150 ssl.offDelayOldTime(5);
151 ssl.elseActionType(AS_CM_ACTIONTYPE_INACTIVE);
154 ssl.elseJtOn(AS_CM_JT_ONDELAY);
155 ssl.elseJtOff(AS_CM_JT_ONDELAY);
156 ssl.elseJtDlyOn(AS_CM_JT_ONDELAY);
157 ssl.elseJtDlyOff(AS_CM_JT_ONDELAY);
158 ssl.elseJtRampOn(AS_CM_JT_ONDELAY);
159 ssl.elseJtRampOff(AS_CM_JT_ONDELAY);
164 DimmerPeerList ssl = sh();
165 ssl.jtOn(AS_CM_JT_OFFDELAY);
166 ssl.jtOff(AS_CM_JT_OFF);
167 ssl.jtDlyOn(AS_CM_JT_RAMPOFF);
168 ssl.jtDlyOff(AS_CM_JT_RAMPOFF);
169 ssl.jtRampOn(AS_CM_JT_RAMPOFF);
170 ssl.jtRampOff(AS_CM_JT_OFF);
172 ssl.actionType(AS_CM_ACTIONTYPE_DOWNDIM);
177 DimmerPeerList ssl = sh();
178 ssl.jtOn(AS_CM_JT_ON);
179 ssl.jtOff(AS_CM_JT_ONDELAY);
180 ssl.jtDlyOn(AS_CM_JT_RAMPON);
181 ssl.jtDlyOff(AS_CM_JT_RAMPON);
182 ssl.jtRampOn(AS_CM_JT_ON);
183 ssl.jtRampOff(AS_CM_JT_RAMPON);
185 ssl.actionType(AS_CM_ACTIONTYPE_UPDIM);
190 DimmerPeerList ssl = sh();
191 ssl.jtOn(AS_CM_JT_OFFDELAY);
192 ssl.jtOff(AS_CM_JT_ONDELAY);
193 ssl.jtDlyOn(AS_CM_JT_RAMPON);
194 ssl.jtDlyOff(AS_CM_JT_RAMPOFF);
195 ssl.jtRampOn(AS_CM_JT_ON);
196 ssl.jtRampOff(AS_CM_JT_OFF);
198 ssl.actionType(AS_CM_ACTIONTYPE_TOGGLEDIM_TO_COUNTER);
206 #define DELAY_NO 0x00
207 #define DELAY_INFINITE 0xffffffff
209 class ChangedAlarm :
public Alarm {
213 virtual ~ChangedAlarm () {}
219 virtual void trigger (__attribute__((unused))
AlarmClock& clock) {
225 class RampAlarm :
public Alarm {
229 uint32_t delay, tack;
234 void list (DimmerPeerList l) { lst=l; delay=tack=0; destlevel=sm.status(); }
235 void init (uint8_t state,DimmerPeerList l) {
236 uint8_t destlevel = state == AS_CM_JT_RAMPOFF ? 0 : 200;
237 if( l.valid() ==
true ) {
238 destlevel = state == AS_CM_JT_RAMPOFF ? l.offLevel() : l.onLevel();
240 init(sm.getDelayForState(state,l),destlevel,l.valid() ? 0 : DELAY_INFINITE,l);
242 void init (uint32_t ramptime,uint8_t level,uint32_t dly,DimmerPeerList l=DimmerPeerList(0)) {
243 DPRINT(F(
"Ramp/Level: "));DDEC(ramptime);DPRINT(F(
"/"));DDECLN(level);
245 if( lst.valid() && sm.status() !=0 && sm.status() < lst.onMinLevel() ) {
246 sm.updateLevel(lst.onMinLevel());
249 destlevel = level==201 ? sm.lastonlevel : level;
251 sm.updateState(destlevel==0 ? AS_CM_JT_RAMPOFF : AS_CM_JT_RAMPON, delay);
252 uint8_t curlevel = sm.status();
254 if( curlevel > destlevel ) {
255 diff = curlevel - destlevel;
258 diff = destlevel - curlevel;
264 else if( ramptime > diff ) {
266 tack = ramptime / diff;
270 dx = uint8_t(diff / (ramptime > 0 ? ramptime : 1));
276 uint8_t curlevel = sm.status();
278 if( sm.status() != destlevel ) {
279 if( curlevel > destlevel ) {
280 uint8_t rest = curlevel - destlevel;
281 sm.updateLevel( curlevel - (rest < dx ? rest : dx));
284 uint8_t rest = destlevel - curlevel;
285 sm.updateLevel( curlevel + (rest < dx ? rest : dx));
289 if( sm.status() == destlevel ) {
290 uint8_t next = sm.getNextState();
291 if( delay == 0 && lst.valid() ==
true ) {
292 delay = sm.getDelayForState(next,lst);
294 sm.setState(next,delay,lst);
303 class BlinkAlarm :
public Alarm {
311 void init(DimmerPeerList l) {
312 if (!l.offDelayBlink())
return;
313 origlevel = sm.status();
315 diff = origlevel / 4;
321 sysclock.cancel(*
this);
322 sm.updateLevel(origlevel);
325 uint8_t destlevel = (sm.status() == origlevel) ? origlevel - diff : origlevel;
326 sm.updateLevel(destlevel);
332 void updateLevel (uint8_t newlevel) {
337 void updateState (uint8_t next,uint32_t delay) {
338 if( state != next ) {
339 switchState(state, next,delay);
341 if ( state == AS_CM_JT_ON || state == AS_CM_JT_OFF ) {
347 void triggerChanged () {
348 calarm.set(decis2ticks(list1.statusInfoMinDly()*5),sysclock);
351 void setState (uint8_t next,uint32_t delay,
const DimmerPeerList& lst=DimmerPeerList(0),uint8_t deep=0) {
353 if( next != AS_CM_JT_NONE && deep < 4) {
355 sysclock.cancel(alarm);
358 if (next == AS_CM_JT_OFFDELAY) blink.init(lst);
359 if (state == AS_CM_JT_OFFDELAY) blink.end();
360 updateState(next,delay);
362 if ( state == AS_CM_JT_RAMPON || state == AS_CM_JT_RAMPOFF ) {
363 alarm.init(state,lst);
367 if (delay == DELAY_NO) {
369 next = getNextState();
370 delay = getDelayForState(next,lst);
371 setState(next, delay, lst, ++deep);
373 else if (delay != DELAY_INFINITE) {
385 bool toggledimup : 1;
386 bool erroverheat : 1;
387 bool erroroverload : 1;
389 uint8_t level, lastonlevel;
396 DimmerStateMachine() : state(AS_CM_JT_NONE), change(
false), toggledimup(
true), erroverheat(
false), erroroverload(
false), errreduced(
false),
397 level(0), lastonlevel(200), alarm(*
this), blink(*
this), calarm(*
this), list1(0) {}
400 bool changed ()
const {
return change; }
401 void changed (
bool c) { change=c; }
403 void overheat(
bool value) {
407 void overload(
bool value){
408 erroroverload = value;
411 return erroroverload;
413 void reduced (
bool value) {
417 void setup(DimmerList1 l1) {
421 virtual void switchState(__attribute__ ((unused)) uint8_t oldstate,uint8_t newstate,__attribute__ ((unused)) uint32_t stateDelay) {
423 if( newstate == AS_CM_JT_ON ) {
428 void jumpToTarget(
const DimmerPeerList& lst) {
429 uint8_t next = getJumpTarget(state,lst);
431 if( next != AS_CM_JT_NONE ) {
433 uint32_t dly = getDelayForState(next,lst);
435 if( next == state && (next == AS_CM_JT_ON || next == AS_CM_JT_OFF) && dly < DELAY_INFINITE) {
436 bool minimal = next == AS_CM_JT_ON ? lst.onTimeMode() : lst.offTimeMode();
438 if( minimal ==
true ) {
440 uint32_t curdly = sysclock.get(alarm);
441 if( curdly == 0 || curdly > dly ) {
448 setState(next,dly,lst);
452 void toggleState () {
453 if( state == AS_CM_JT_OFF ) {
454 setLevel(lastonlevel,5,0xffff);
457 setLevel(0,5,0xffff);
461 uint8_t getNextState () {
463 case AS_CM_JT_ONDELAY:
return AS_CM_JT_RAMPON;
464 case AS_CM_JT_RAMPON:
return AS_CM_JT_ON;
465 case AS_CM_JT_ON:
return AS_CM_JT_OFFDELAY;
466 case AS_CM_JT_OFFDELAY:
return AS_CM_JT_RAMPOFF;
467 case AS_CM_JT_RAMPOFF:
return AS_CM_JT_OFF;
468 case AS_CM_JT_OFF:
return AS_CM_JT_ONDELAY;
470 return AS_CM_JT_NONE;
473 uint8_t getJumpTarget(uint8_t stat,
const DimmerPeerList& lst)
const {
475 case AS_CM_JT_ONDELAY:
return lst.jtDlyOn();
476 case AS_CM_JT_RAMPON:
return lst.jtRampOn();
477 case AS_CM_JT_ON:
return lst.jtOn();
478 case AS_CM_JT_OFFDELAY:
return lst.jtDlyOff();
479 case AS_CM_JT_RAMPOFF:
return lst.jtRampOff();
480 case AS_CM_JT_OFF:
return lst.jtOff();
482 return AS_CM_JT_NONE;
485 uint8_t getConditionForState(uint8_t stat,
const DimmerPeerList& lst)
const {
487 case AS_CM_JT_ONDELAY:
return lst.ctDlyOn();
488 case AS_CM_JT_RAMPON:
return lst.ctRampOn();
489 case AS_CM_JT_ON:
return lst.ctOn();
490 case AS_CM_JT_OFFDELAY:
return lst.ctDlyOff();
491 case AS_CM_JT_RAMPOFF:
return lst.ctRampOff();
492 case AS_CM_JT_OFF:
return lst.ctOff();
494 return AS_CM_CT_X_GE_COND_VALUE_LO;
497 uint32_t getDelayForState(uint8_t stat,
const DimmerPeerList& lst)
const {
498 if( lst.valid() ==
false ) {
499 return getDefaultDelay(stat);
503 case AS_CM_JT_ONDELAY: value = lst.onDly();
break;
504 case AS_CM_JT_RAMPON: value = lst.rampOnTime();
break;
505 case AS_CM_JT_ON: value = lst.onTime();
break;
506 case AS_CM_JT_OFFDELAY: value = lst.offDly();
break;
507 case AS_CM_JT_RAMPOFF: value = lst.rampOffTime();
break;
508 case AS_CM_JT_OFF: value = lst.offTime();
break;
510 return AskSinBase::byteTimeCvt(value);
513 uint32_t getDefaultDelay(uint8_t stat)
const {
517 return DELAY_INFINITE;
518 case AS_CM_JT_RAMPON:
519 case AS_CM_JT_RAMPOFF:
520 return decis2ticks(5);
525 bool delayActive ()
const {
return sysclock.get(alarm) > 0; }
527 void dimUp (
const DimmerPeerList& lst) {
528 uint8_t dx = lst.dimStep();
529 uint8_t newlevel = level+dx;
530 if( newlevel > lst.dimMaxLevel() ) {
531 newlevel = lst.dimMaxLevel();
533 updateState(AS_CM_JT_RAMPON,getDelayForState(AS_CM_JT_RAMPON, lst));
534 updateLevel(newlevel);
535 updateState(AS_CM_JT_ON,getDelayForState(AS_CM_JT_ON, lst));
538 void dimDown (
const DimmerPeerList& lst) {
539 uint8_t dx = lst.dimStep();
540 uint8_t newlevel = level - (dx < level ? dx : level);
541 if( newlevel < lst.dimMinLevel() ) {
542 newlevel = lst.dimMinLevel();
544 uint8_t newstate = newlevel > lst.onMinLevel() ? AS_CM_JT_RAMPON : AS_CM_JT_RAMPOFF;
545 updateState(newstate,getDelayForState(newstate, lst));
546 updateLevel(newlevel);
547 newstate = newlevel > lst.onMinLevel() ? AS_CM_JT_ON : AS_CM_JT_OFF;
548 updateState(newstate,getDelayForState(newstate, lst));
551 bool set (uint8_t value,uint16_t ramp,uint16_t delay) {
552 setLevel(value,ramp,delay);
556 void remote (
const DimmerPeerList& lst,uint8_t counter) {
558 switch (lst.actionType()) {
559 case AS_CM_ACTIONTYPE_JUMP_TO_TARGET:
562 case AS_CM_ACTIONTYPE_TOGGLE_TO_COUNTER:
563 setState((counter & 0x01) == 0x01 ? AS_CM_JT_RAMPON : AS_CM_JT_RAMPOFF, DELAY_INFINITE, lst);
565 case AS_CM_ACTIONTYPE_TOGGLE_INVERSE_TO_COUNTER:
566 setState((counter & 0x01) == 0x01 ? AS_CM_JT_RAMPON : AS_CM_JT_RAMPOFF, DELAY_INFINITE, lst);
568 case AS_CM_ACTIONTYPE_UPDIM:
571 case AS_CM_ACTIONTYPE_DOWNDIM:
574 case AS_CM_ACTIONTYPE_TOGGLEDIM:
575 if( toggledimup ==
true ) dimUp(lst);
577 toggledimup = ! toggledimup;
579 case AS_CM_ACTIONTYPE_TOGGLEDIM_TO_COUNTER:
580 (counter & 0x01) == 0x01 ? dimUp(lst) : dimDown(lst);
582 case AS_CM_ACTIONTYPE_TOGGLEDIM_TO_COUNTER_INVERSE:
583 (counter & 0x01) == 0x00 ? dimUp(lst) : dimDown(lst);
589 void sensor (
const DimmerPeerList& lst,uint8_t counter,uint8_t value) {
590 uint8_t cond = getConditionForState(state,lst);
593 case AS_CM_CT_X_GE_COND_VALUE_LO:
594 doit = (value >= lst.ctValLo());
596 case AS_CM_CT_X_GE_COND_VALUE_HI:
597 doit = (value >= lst.ctValHi());
599 case AS_CM_CT_X_LT_COND_VALUE_LO:
600 doit = (value < lst.ctValLo());
602 case AS_CM_CT_X_LT_COND_VALUE_HI:
603 doit = (value < lst.ctValHi());
605 case AS_CM_CT_COND_VALUE_LO_LE_X_LT_COND_VALUE_HI:
606 doit = ((lst.ctValLo() <= value) && (value < lst.ctValHi()));
608 case AS_CM_CT_X_LT_COND_VALUE_LO_OR_X_GE_COND_VALUE_HI:
609 doit =((value < lst.ctValLo()) || (value >= lst.ctValHi()));
620 void setLevel (uint8_t level, uint16_t ramp, uint16_t delay) {
622 sysclock.cancel(alarm);
624 alarm.destlevel=level;
626 setState(level==0 ? AS_CM_JT_OFF : AS_CM_JT_ON, AskSinBase::intTimeCvt(delay));
629 alarm.init(AskSinBase::intTimeCvt(ramp), level, AskSinBase::intTimeCvt(delay));
636 uint8_t status ()
const {
640 uint8_t flags ()
const {
641 uint8_t f = delayActive() ? 0x40 : 0x00;
642 if( erroverheat ==
true ) {
643 f |= AS_CM_EXTSTATE_OVERHEAT;
645 if( erroroverload ==
true) {
646 f |= AS_CM_EXTSTATE_OVERLOAD;
648 if( errreduced ==
true ) {
649 f |= AS_CM_EXTSTATE_REDUCED;
651 if( alarm.destlevel < level) {
652 f |= AS_CM_EXTSTATE_DOWN;
654 else if( alarm.destlevel > level) {
655 f |= AS_CM_EXTSTATE_UP;
661 template <
class HalType,
int PeerCount,
class List0Type=List0>
669 void setPhysical(uint8_t& p) {
673 void patchStatus (
Message& msg) {
674 if( msg.length() == 0x0e ) {
677 msg.data()[3] = *phys;
683 template<
class HalType,
class ChannelType,
int ChannelCount,
int VirtualCount,
class List0Type=List0>
692 static int const channelCount = ChannelCount;
693 static int const virtualCount = VirtualCount;
694 typedef ChannelType DimmerChannelType;
695 DimmerChannelType& dimmerChannel(uint8_t ch) {
696 return this->channel(ch);
701 template<
class HalType,
class DimChannelType,
class RmtChannelType,
int DimChannelCount,
int DimVirtualCount,
int RmtChannelCount,
class List0Type=List0>
710 for( uint8_t i=0; i<RmtChannelCount; ++i ) {
711 DeviceType::registerChannel(rmc[i], i+1);
713 for( uint8_t j=0; j<DimChannelCount; ++j ) {
714 DeviceType::registerChannel(dmc[j], j+RmtChannelCount+1);
720 static int const channelCount = DimChannelCount;
721 static int const virtualCount = DimVirtualCount;
722 typedef DimChannelType DimmerChannelType;
723 DimmerChannelType& dimmerChannel(uint8_t ch) {
724 return this->dmc[ch-1];
726 typedef RmtChannelType RemoteChannelType;
727 RemoteChannelType& remoteChannel(uint8_t re){
728 return this->rmc[re-1];
732 template<
class HalType,
class DimmerType,
class PWM>
736 PWM pwms[DimmerType::channelCount/DimmerType::virtualCount];
737 uint8_t physical[DimmerType::channelCount/DimmerType::virtualCount];
738 uint8_t factor[DimmerType::channelCount/DimmerType::virtualCount];
741 uint8_t overloadcounter;
743 class ChannelCombiner :
public Alarm {
747 virtual ~ChannelCombiner () {}
749 control.updatePhysical();
750 set(millis2ticks(10));
756 DimmerControl (DimmerType& dim) : dimmer(dim), counter(0), overloadcounter(0), cb(*
this) {}
759 uint8_t channelCount () {
return DimmerType::channelCount; }
760 uint8_t virtualCount () {
return DimmerType::virtualCount; }
761 uint8_t physicalCount () {
return DimmerType::channelCount/DimmerType::virtualCount; }
764 for( uint8_t i=1; i<=channelCount(); ++i ) {
765 if( i <= physicalCount() ){
766 dimmer.dimmerChannel(i).getList1().logicCombination(LOGIC_OR);
769 dimmer.dimmerChannel(i).getList1().logicCombination(LOGIC_INACTIVE);
774 bool init (HalType& hal,...) {
775 bool first = dimmer.init(hal);
776 if( first ==
true ) {
781 for( uint8_t i=0; i<physicalCount(); ++i ) {
782 uint8_t p = va_arg(argp,
int);
789 cb.trigger(sysclock);
793 bool init (HalType& hal,
const uint8_t pins[]) {
794 bool first = dimmer.init(hal);
795 if( first ==
true ) {
798 for( uint8_t i=0; i<physicalCount(); ++i ) {
799 pwms[i].init(pins[i]);
804 cb.trigger(sysclock);
808 PWM& pwm (uint8_t num) {
return pwms[num]; }
810 void initChannels () {
811 for( uint8_t i=1; i<=physicalCount(); ++i ) {
812 for( uint8_t j=i; j<=channelCount(); j+=physicalCount() ) {
813 dimmer.dimmerChannel(j).setPhysical(physical[i-1]);
814 bool powerup = dimmer.dimmerChannel(j).getList1().powerUpAction();
815 dimmer.dimmerChannel(j).setLevel(powerup ==
true ? 200 : 0,0,0xffff);
820 virtual void updatePhysical () {
822 for( uint8_t i=0; i<physicalCount(); ++i ) {
823 uint8_t value = (uint8_t)combineChannels(i+1);
824 value = (((uint16_t)factor[i] * (uint16_t)value) / 200);
825 if( physical[i] != value ) {
828 pwms[i].set(physical[i]);
833 uint16_t combineChannels (uint8_t start) {
834 if( virtualCount() == 1 ) {
835 return dimmer.dimmerChannel(start).status();
839 for( uint8_t i=start; i<=channelCount(); i+=physicalCount() ) {
840 uint8_t level = dimmer.dimmerChannel(i).status();
841 switch( dimmer.dimmerChannel(i).getList1().logicCombination() ) {
846 value = value > level ? value : level;
849 value = value < level ? value : level;
852 value = value==0 ? level : (level==0 ? value : 0);
855 value = 200 - (value > level ? value : level);
858 value = 200 - (value < level ? value : level);
862 value = value > level ? value : level;
864 case LOGIC_ANDINVERS:
866 value = value < level ? value : level;
870 if( value > 200 ) value = 200;
873 if( level > value ) value = 0;
877 value = value * level / 200;
879 case LOGIC_PLUSINVERS:
882 if( value > 200 ) value = 200;
885 case LOGIC_MINUSINVERS:
887 if( level > value ) value = 0;
890 case LOGIC_MULINVERS:
892 value = value * level / 200;
894 case LOGIC_INVERSPLUS:
896 if( value > 200 ) value = 200;
899 case LOGIC_INVERSMINUS:
900 if( level > value ) value = 0;
904 case LOGIC_INVERSMUL:
905 value = value * level / 200;
916 void setOverload (
bool overload=
false) {
922 for( uint8_t i=1; i<=physicalCount(); ++i ) {
923 typename DimmerType::DimmerChannelType& c = dimmer.dimmerChannel(i);
925 if((counter - overloadcounter) <= 2 ){
935 else if ( c.getoverload()) {
942 void setTemperature (uint16_t temp) {
944 for( uint8_t i=1; i<=physicalCount(); ++i ) {
945 typename DimmerType::DimmerChannelType& c = dimmer.dimmerChannel(i);
946 if( c.getList1().overTempLevel() <= t ) {
951 else if( c.getList1().reduceTempLevel() <= t ) {
952 factor[i-1] = c.getList1().reduceLevel();
966 template<
class HalType,
class DimmerType,
class PWM>
972 if( this->physicalCount() != 2 ) {
973 DPRINTLN(F(
"DualWhiteControl needs physical count == 2"));
979 virtual void updatePhysical () {
980 uint16_t bright = this->combineChannels(1);
981 uint16_t adjust = this->combineChannels(2);
983 if( this->physical[0] != bright || this->physical[1] != adjust) {
984 this->physical[0] = bright;
985 this->physical[1] = adjust;
989 uint8_t pwm0 = bright;
990 uint8_t pwm1 = bright;
992 pwm1 = (bright * adjust) / 100;
995 pwm0 = (bright * (200-adjust)) / 100;
997 this->pwms[0].set(pwm0);
998 this->pwms[1].set(pwm1);