8 #include "AlarmClock.h"
11 #ifdef ARDUINO_ARCH_AVR
12 typedef uint8_t WiringPinMode;
17 template <u
int8_t OFFSTATE=HIGH,u
int8_t ONSTATE=LOW,WiringPinMode MODE=INPUT_PULLUP>
20 #define DEBOUNCETIME millis2ticks(50)
38 virtual void trigger(__attribute__((unused))
AlarmClock& clock) {
47 uint16_t longpresstime;
52 Alarm(0), stat(none), pinstate(OFFSTATE), pin(0), longpresstime(millis2ticks(400)), ca(*this) {
57 void setLongPressTime(uint16_t t) {
65 virtual void trigger(AlarmClock& clock) {
66 uint8_t nextstate = invalid;
67 uint16_t nexttick = 0;
76 if (pinstate == ONSTATE) {
78 nexttick = longpresstime - DEBOUNCETIME;
81 nexttick = DEBOUNCETIME;
87 if( pinstate == ONSTATE) {
88 nextstate = longpressed;
89 nexttick = longpresstime;
99 if( nextstate != invalid ) {
104 virtual void state(uint8_t s) {
106 case released: DPRINTLN(F(
" released"));
break;
107 case pressed: DPRINTLN(F(
" pressed"));
break;
108 case debounce: DPRINTLN(F(
" debounce"));
break;
109 case longpressed: DPRINTLN(F(
" longpressed"));
break;
110 case longreleased: DPRINTLN(F(
" longreleased"));
break;
111 default: DPRINTLN(F(
""));
break;
116 uint8_t state()
const {
127 uint8_t ps = digitalRead(pin);
128 if( pinstate != ps ) {
130 uint16_t nexttick = 0;
131 uint8_t nextstate = state();
134 nextstate = debounce;
135 nexttick = DEBOUNCETIME;
140 if (pinstate == OFFSTATE) {
141 nextstate = state() == pressed ? released : longreleased;
142 nexttick = DEBOUNCETIME;
148 if( nexttick != 0 ) {
149 sysclock.cancel(*
this);
153 if( nextstate != state () ) {
159 void init(uint8_t pin) {
166 typedef StateButton<HIGH,LOW,INPUT_PULLUP> Button;
168 template <
class DEVTYPE,u
int8_t OFFSTATE=HIGH,u
int8_t ONSTATE=LOW,WiringPinMode MODE=INPUT_PULLUP>
174 ConfigButton (DEVTYPE& dev,uint8_t longpresstime=3) : device(dev) {
175 this->setLongPressTime(seconds2ticks(longpresstime));
178 virtual void state (uint8_t s) {
179 uint8_t old = ButtonType::state();
180 ButtonType::state(s);
181 if( s == ButtonType::released ) {
182 device.startPairing();
184 else if( s == ButtonType::longpressed ) {
185 if( old == ButtonType::longpressed ) {
186 if( device.getList0().localResetDisable() ==
false ) {
191 device.led().set(LedStates::key_long);
197 template <
class DEVTYPE,u
int8_t OFFSTATE=HIGH,u
int8_t ONSTATE=LOW,WiringPinMode MODE=INPUT_PULLUP>
204 this->setLongPressTime(seconds2ticks(longpresstime));
207 virtual void state (uint8_t s) {
208 uint8_t old = ButtonType::state();
209 ButtonType::state(s);
210 if( s == ButtonType::released ) {
212 uint8_t cnt = device.nextcount();
213 msg.init(cnt,1,cnt,
false,
false);
214 device.getDeviceID(msg.to());
215 device.getDeviceID(msg.from());
217 if( device.process(msg) == false ) {
218 DPRINTLN(F(
"No self peer. Create internal peering to toggle state!"));
221 else if( s == ButtonType::longreleased ) {
222 device.startPairing();
224 else if( s == ButtonType::longpressed ) {
225 if( old == ButtonType::longpressed ) {
226 if( device.getList0().localResetDisable() ==
false ) {
231 device.led().set(LedStates::key_long);
237 device.getDeviceID(
self);
242 template <
class DEVTYPE,u
int8_t OFFSTATE=HIGH,u
int8_t ONSTATE=LOW,WiringPinMode MODE=INPUT_PULLUP>
245 uint8_t num, counter;
249 InternalButton (DEVTYPE& dev,uint8_t n,uint8_t longpresstime=4) : device(dev), num(n), counter(0) {
250 this->setLongPressTime(decis2ticks(longpresstime));
253 virtual void state (uint8_t s) {
254 ButtonType::state(s);
255 if( s == ButtonType::released ) {
258 else if( s == ButtonType::longpressed ) {
262 else if( s == ButtonType::longreleased ) {
268 uint8_t cnt = device.nextcount();
269 msg.init(cnt,num,counter,lg,
false);
270 device.getDeviceID(msg.to());
271 device.getDeviceID(msg.from());
277 device.getDeviceID(
self);
278 return Peer(
self,num);
294 uint8_t data = digitalRead(datapin);
295 counter += data == LOW ? 1 : -1;
297 void init (uint8_t cpin,uint8_t dpin) {
298 pinMode(cpin, INPUT_PULLUP);
299 pinMode(dpin, INPUT_PULLUP);
304 ATOMIC_BLOCK( ATOMIC_RESTORESTATE )
313 template<
class DeviceType>
320 void init (uint8_t sw) {
323 void init (uint8_t cpin,uint8_t dpin) {
324 BaseEncoder::init(cpin,dpin);
326 template<
class ChannelType>
327 void process (ChannelType& channel) {
330 typename ChannelType::List3 l3 = channel.getList3(this->peer());
332 if( dx > 0 ) channel.dimUp(l3.sh());
333 else channel.dimDown(l3.sh());
339 #define buttonISR(btn,pin) class btn##ISRHandler { \
341 static void isr () { btn.irq(); } \
344 if( digitalPinToInterrupt(pin) == NOT_AN_INTERRUPT ) \
345 enableInterrupt(pin,btn##ISRHandler::isr,CHANGE); \
347 attachInterrupt(digitalPinToInterrupt(pin),btn##ISRHandler::isr,CHANGE);
349 #define encoderISR(enc,clkpin,datapin) class enc##ENCISRHandler { \
351 static void isr () { enc.encirq(); } \
353 enc.init(clkpin,datapin); \
354 if( digitalPinToInterrupt(clkpin) == NOT_AN_INTERRUPT ) \
355 enableInterrupt(clkpin,enc##ENCISRHandler::isr,FALLING); \
357 attachInterrupt(digitalPinToInterrupt(clkpin),enc##ENCISRHandler::isr,FALLING);