forked from Arduino-IRremote/Arduino-IRremote
-
Notifications
You must be signed in to change notification settings - Fork 0
/
irRecv.cpp
235 lines (196 loc) · 6.43 KB
/
irRecv.cpp
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#include "IRremote.h"
#include "IRremoteInt.h"
#ifdef IR_TIMER_USE_ESP32
hw_timer_t *timer;
void IRTimer(); // defined in IRremote.cpp
#endif
//+=============================================================================
// Decodes the received IR message
// Returns 0 if no data ready, 1 if data ready.
// Results of decoding are stored in results
//
int IRrecv::decode (decode_results *results)
{
results->rawbuf = irparams.rawbuf;
results->rawlen = irparams.rawlen;
results->overflow = irparams.overflow;
if (irparams.rcvstate != STATE_STOP) return false ;
#if DECODE_NEC
DBG_PRINTLN("Attempting NEC decode");
if (decodeNEC(results)) return true ;
#endif
#if DECODE_SONY
DBG_PRINTLN("Attempting Sony decode");
if (decodeSony(results)) return true ;
#endif
#if DECODE_SANYO
DBG_PRINTLN("Attempting Sanyo decode");
if (decodeSanyo(results)) return true ;
#endif
#if DECODE_MITSUBISHI
DBG_PRINTLN("Attempting Mitsubishi decode");
if (decodeMitsubishi(results)) return true ;
#endif
#if DECODE_RC5
DBG_PRINTLN("Attempting RC5 decode");
if (decodeRC5(results)) return true ;
#endif
#if DECODE_RC6
DBG_PRINTLN("Attempting RC6 decode");
if (decodeRC6(results)) return true ;
#endif
#if DECODE_PANASONIC
DBG_PRINTLN("Attempting Panasonic decode");
if (decodePanasonic(results)) return true ;
#endif
#if DECODE_LG
DBG_PRINTLN("Attempting LG decode");
if (decodeLG(results)) return true ;
#endif
#if DECODE_JVC
DBG_PRINTLN("Attempting JVC decode");
if (decodeJVC(results)) return true ;
#endif
#if DECODE_SAMSUNG
DBG_PRINTLN("Attempting SAMSUNG decode");
if (decodeSAMSUNG(results)) return true ;
#endif
#if DECODE_WHYNTER
DBG_PRINTLN("Attempting Whynter decode");
if (decodeWhynter(results)) return true ;
#endif
#if DECODE_AIWA_RC_T501
DBG_PRINTLN("Attempting Aiwa RC-T501 decode");
if (decodeAiwaRCT501(results)) return true ;
#endif
#if DECODE_DENON
DBG_PRINTLN("Attempting Denon decode");
if (decodeDenon(results)) return true ;
#endif
#if DECODE_LEGO_PF
DBG_PRINTLN("Attempting Lego Power Functions");
if (decodeLegoPowerFunctions(results)) return true ;
#endif
// decodeHash returns a hash on any input.
// Thus, it needs to be last in the list.
// If you add any decodes, add them before this.
if (decodeHash(results)) return true ;
// Throw away and start over
resume();
return false;
}
//+=============================================================================
IRrecv::IRrecv (int recvpin)
{
irparams.recvpin = recvpin;
irparams.blinkflag = 0;
}
IRrecv::IRrecv (int recvpin, int blinkpin)
{
irparams.recvpin = recvpin;
irparams.blinkpin = blinkpin;
pinMode(blinkpin, OUTPUT);
irparams.blinkflag = 0;
}
//+=============================================================================
// initialization
//
void IRrecv::enableIRIn ( )
{
// Interrupt Service Routine - Fires every 50uS
#ifdef ESP32
// ESP32 has a proper API to setup timers, no weird chip macros needed
// simply call the readable API versions :)
// 3 timers, choose #1, 80 divider nanosecond precision, 1 to count up
timer = timerBegin(1, 80, 1);
timerAttachInterrupt(timer, &IRTimer, 1);
// every 50ns, autoreload = true
timerAlarmWrite(timer, 50, true);
timerAlarmEnable(timer);
#else
cli();
// Setup pulse clock timer interrupt
// Prescale /8 (16M/8 = 0.5 microseconds per tick)
// Therefore, the timer interval can range from 0.5 to 128 microseconds
// Depending on the reset value (255 to 0)
TIMER_CONFIG_NORMAL();
// Timer2 Overflow Interrupt Enable
TIMER_ENABLE_INTR;
TIMER_RESET;
sei(); // enable interrupts
#endif
// Initialize state machine variables
irparams.rcvstate = STATE_IDLE;
irparams.rawlen = 0;
// Set pin modes
pinMode(irparams.recvpin, INPUT);
}
//+=============================================================================
// Enable/disable blinking of pin 13 on IR processing
//
void IRrecv::blink13 (int blinkflag)
{
irparams.blinkflag = blinkflag;
if (blinkflag) pinMode(BLINKLED, OUTPUT) ;
}
//+=============================================================================
// Return if receiving new IR signals
//
bool IRrecv::isIdle ( )
{
return (irparams.rcvstate == STATE_IDLE || irparams.rcvstate == STATE_STOP) ? true : false;
}
//+=============================================================================
// Restart the ISR state machine
//
void IRrecv::resume ( )
{
irparams.rcvstate = STATE_IDLE;
irparams.rawlen = 0;
}
//+=============================================================================
// hashdecode - decode an arbitrary IR code.
// Instead of decoding using a standard encoding scheme
// (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value.
//
// The algorithm: look at the sequence of MARK signals, and see if each one
// is shorter (0), the same length (1), or longer (2) than the previous.
// Do the same with the SPACE signals. Hash the resulting sequence of 0's,
// 1's, and 2's to a 32-bit value. This will give a unique value for each
// different code (probably), for most code systems.
//
// http://arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html
//
// Compare two tick values, returning 0 if newval is shorter,
// 1 if newval is equal, and 2 if newval is longer
// Use a tolerance of 20%
//
int IRrecv::compare (unsigned int oldval, unsigned int newval)
{
if (newval < oldval * .8) return 0 ;
else if (oldval < newval * .8) return 2 ;
else return 1 ;
}
//+=============================================================================
// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param
// Converts the raw code values into a 32-bit hash code.
// Hopefully this code is unique for each button.
// This isn't a "real" decoding, just an arbitrary value.
//
#define FNV_PRIME_32 16777619
#define FNV_BASIS_32 2166136261
long IRrecv::decodeHash (decode_results *results)
{
long hash = FNV_BASIS_32;
// Require at least 6 samples to prevent triggering on noise
if (results->rawlen < 6) return false ;
for (int i = 1; (i + 2) < results->rawlen; i++) {
int value = compare(results->rawbuf[i], results->rawbuf[i+2]);
// Add value into the hash
hash = (hash * FNV_PRIME_32) ^ value;
}
results->value = hash;
results->bits = 32;
results->decode_type = UNKNOWN;
return true;
}