-
Notifications
You must be signed in to change notification settings - Fork 71
/
Copy pathRemote.h
154 lines (128 loc) · 4.6 KB
/
Remote.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//- -----------------------------------------------------------------------------------------------------------------------
// AskSin++
// 2017-04-12 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//- -----------------------------------------------------------------------------------------------------------------------
#ifndef __REMOTE_H__
#define __REMOTE_H__
#include "Channel.h"
#include "ChannelList.h"
#include "Button.h"
#include "Message.h"
#include "Register.h"
namespace as {
DEFREGISTER(RemoteReg1,CREG_LONGPRESSTIME,CREG_AES_ACTIVE,CREG_DOUBLEPRESSTIME)
class RemoteList1 : public RegList1<RemoteReg1> {
public:
RemoteList1 (uint16_t addr) : RegList1<RemoteReg1>(addr) {}
void defaults () {
clear();
longPressTime(1);
// aesActive(false);
// doublePressTime(0);
}
};
template<class HALTYPE,int PEERCOUNT,class List0Type=List0,class List1Type=RemoteList1,class ButtonType=Button>
class RemoteChannel : public Channel<HALTYPE,List1Type,EmptyList,DefList4,PEERCOUNT,List0Type>, public ButtonType {
private:
uint8_t repeatcnt;
volatile bool isr;
public:
typedef Channel<HALTYPE,List1Type,EmptyList,DefList4,PEERCOUNT,List0Type> BaseChannel;
RemoteChannel () : BaseChannel(), repeatcnt(0), isr(false) {}
virtual ~RemoteChannel () {}
ButtonType& button () { return *(ButtonType*)this; }
uint8_t status () const {
return 0;
}
uint8_t flags () const {
return 0;
}
void repeatCount (uint8_t cnt) {
repeatcnt = cnt;
}
uint8_t repeatCount () const {
return repeatcnt;
}
virtual void state(uint8_t s) {
DHEX(BaseChannel::number());
ButtonType::state(s);
RemoteEventMsg& msg = (RemoteEventMsg&)this->device().message();
msg.init(this->device().nextcount(),this->number(),repeatcnt,(s==ButtonType::longreleased || s==ButtonType::longpressed),this->device().battery().low());
if( s == ButtonType::released || s == ButtonType::longreleased) {
// send the message to every peer
this->device().sendPeerEvent(msg,*this);
repeatcnt++;
}
else if (s == ButtonType::longpressed) {
// broadcast the message
this->device().broadcastPeerEvent(msg,*this);
}
}
uint8_t state() const {
return Button::state();
}
bool pressed () const {
uint8_t s = state();
return s == Button::pressed || s == Button::debounce || s == Button::longpressed;
}
bool configChanged() {
//we have to add 300ms to the value set in CCU!
uint16_t _longpressTime = 300 + (this->getList1().longPressTime() * 100);
//DPRINT("longpressTime = ");DDECLN(_longpressTime);
this->setLongPressTime(millis2ticks(_longpressTime));
if( this->canDoublePress() == true ) {
uint16_t _doublepressTime = this->getList1().doublePressTime() * 100;
this->setDoublePressTime(millis2ticks(_doublepressTime));
}
return true;
}
};
template<class DeviceType,int DownChannel,int UpChannel>
class RemoteEncoder : public BaseEncoder, public Alarm {
int8_t last;
DeviceType& sdev;
public:
RemoteEncoder(DeviceType& d) : BaseEncoder(), Alarm(0), last(0), sdev(d) {}
virtual ~RemoteEncoder() {}
void process () {
int8_t dir = read();
if( dir != 0 ) {
if( dir < 0 ) dir = -1;
else dir = 1;
sysclock.cancel(*this);
if( last != 0 && last != dir ) {
trigger(sysclock);
}
sdev.channel(dir < 0 ? DownChannel : UpChannel).state(StateButton<>::longpressed);
set(millis2ticks(400));
last = dir;
sysclock.add(*this);
}
}
virtual void trigger (__attribute__((unused)) AlarmClock& clock) {
if( last != 0 ) {
sdev.channel(last < 0 ? DownChannel : UpChannel).state(StateButton<>::longreleased);
last = 0;
}
}
};
#define remoteISR(device,chan,pin) class device##chan##ISRHandler { \
public: \
static void isr () { device.channel(chan).irq(); } \
}; \
device.channel(chan).button().init(pin); \
if( digitalPinToInterrupt(pin) == NOT_AN_INTERRUPT ) \
enableInterrupt(pin,device##chan##ISRHandler::isr,CHANGE); \
else \
attachInterrupt(digitalPinToInterrupt(pin),device##chan##ISRHandler::isr,CHANGE);
#define remoteChannelISR(chan,pin) class __##pin##ISRHandler { \
public: \
static void isr () { chan.irq(); } \
}; \
chan.button().init(pin); \
if( digitalPinToInterrupt(pin) == NOT_AN_INTERRUPT ) \
enableInterrupt(pin,__##pin##ISRHandler::isr,CHANGE); \
else \
attachInterrupt(digitalPinToInterrupt(pin),__##pin##ISRHandler::isr,CHANGE);
}
#endif