-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathInterRemote.cpp
145 lines (119 loc) · 3.17 KB
/
InterRemote.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
#include <Arduino.h>
#include "InterRemote.h"
//Big thanks to https://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino/
IRPacket irPacket = {0};
IRRemote irRemote = {0};
volatile unsigned int irBuffer[IR_BUFF_LEN]; //stores timings - volatile because changed by ISR
volatile unsigned int irBuffPos = 0; //Pointer thru irBuffer - volatile because changed by ISR
void handleInterupt()
{
if (irBuffPos < IR_BUFF_LEN)
irBuffer[irBuffPos++] = micros(); //just continually record the time-stamp of signal transitions
}
bool lenMatch(int actualTime, int correctTime, float tolerance)
{
return abs((int) (actualTime - correctTime)) <= (correctTime * tolerance);
}
void irInit()
{
pinMode(IR_PIN, INPUT);
//Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(IR_PIN), handleInterupt, CHANGE);
}
void irDecodeNEC()
{
detachInterrupt(digitalPinToInterrupt(IR_PIN)); // External Interrupt Request 0 Disable
irRemote.state = S_INVALID;
irRemote.pos = 0;
irPacket = {0};
uint8_t transmissionBegin = 0;
for (int i = 1; i < irBuffPos; i++)
{
switch (irRemote.state)
{
case S_AGC:
if (lenMatch(irBuffer[i] - irBuffer[i - 1], NEC_SPACER, TOLERANCE))
{
transmissionBegin = i;
irRemote.state = S_SPACER;
break;
}
else if (lenMatch(irBuffer[i] - irBuffer[i - 1], NEC_REPEAT, TOLERANCE))
{
irRemote.state = S_REPEAT;
break;
}
case S_SPACER:
if (lenMatch(irBuffer[i] - irBuffer[i - 1], NEC_BURST, TOLERANCE))
{
irRemote.state = S_CODE;
irRemote.pos = 0;
irPacket = {0};
break;
}
case S_CODE:
if((i - transmissionBegin) % 2 == 0)
{
if (lenMatch(irBuffer[i] - irBuffer[i - 1], NEC_ONE, TOLERANCE))
{
if (irRemote.pos < 16)
irPacket.address |= (1UL << irRemote.pos++);
else if (irRemote.pos < 32)
irPacket.command |= (1UL << (irRemote.pos++ - 16));
else
irRemote.state = S_DONE;
break;
}
else if (lenMatch(irBuffer[i] - irBuffer[i - 1], NEC_ZERO, TOLERANCE))
{
if (irRemote.pos < 32)
irRemote.pos++;
else
irRemote.state = S_DONE;
break;
}
}
else
{
if (lenMatch(irBuffer[i] - irBuffer[i - 1], NEC_BURST, TOLERANCE))
break;
}
default:
if(irRemote.pos < 32)
{
irRemote.state = S_INVALID;
break;
}
case S_DONE:
irRemote.state = S_DONE;
goto done;
case S_REPEAT:
break;
}
//Search for begin of transmission
if (abs((int) irBuffer[i] - irBuffer[i - 1] - NEC_AGC) <= (NEC_AGC * TOLERANCE))
irRemote.state = S_AGC;
//Serial.print(i);
//Serial.print(": ");
//Serial.print(abs((int) irBuffer[i] - irBuffer[i - 1]));
//Serial.print(", State: ");
//Serial.println(irRemote.state);
}
done:
//Serial.print("Done: ");
//Serial.print(irPacket.address, HEX);
//Serial.print(", ");
//Serial.print(irPacket.command, HEX);
//Serial.print("(");
//Serial.print(irRemote.state);
//Serial.println(")");
irBuffPos = 0;
attachInterrupt(digitalPinToInterrupt(IR_PIN), handleInterupt, CHANGE); // External Interrupt Request 0 Enable
}
bool irAvailable()
{
if (irBuffPos < 128)
return false;
irDecodeNEC();
return true;
}