forked from bengtmartensson/Infrared4Arduino
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIrReceiverSampler.cpp
140 lines (124 loc) · 4.52 KB
/
IrReceiverSampler.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
#include "IrReceiverSampler.h"
#include <IRLibTimer.h>
uint32_t IrReceiverSampler::millisecs2ticks(milliseconds_t ms) {
return (1000UL * (uint32_t) ms) / microsPerTick;
}
milliseconds_t IrReceiverSampler::ticks2millisecs(uint32_t tix) {
return (milliseconds_t) ((tix * microsPerTick)/1000UL);
}
IrReceiverSampler *IrReceiverSampler::instance = NULL;
IrReceiverSampler::IrReceiverSampler(size_t captureLength,
pin_t pin_,
boolean pullup,
microseconds_t markExcess,
milliseconds_t beginningTimeout,
milliseconds_t endingTimeout) : IrReceiver(captureLength, pin_, pullup, markExcess) {
setBeginningTimeout(beginningTimeout);
setEndingTimeout(endingTimeout);
durationData = new microseconds_t[bufferSize];
dataLength = 0;
timer = 0;
receiverState = STATE_IDLE;
}
IrReceiverSampler *IrReceiverSampler::newIrReceiverSampler(size_t captureLength,
pin_t pin,
boolean pullup,
microseconds_t markExcess,
milliseconds_t beginningTimeout,
milliseconds_t endingTimeout) {
if (instance != NULL || pin == invalidPin)
return NULL;
instance = new IrReceiverSampler(captureLength, pin, pullup, markExcess, beginningTimeout, endingTimeout);
return instance;
}
void IrReceiverSampler::deleteInstance() {
delete instance;
instance = NULL;
}
IrReceiverSampler::~IrReceiverSampler() {
delete [] durationData;
}
/*
* The original IRrecv which uses 50us timer driven interrupts to sample input pin.
*/
void IrReceiverSampler::reset() {
receiverState = STATE_IDLE;
dataLength = 0;
}
void IrReceiverSampler::enable() {
reset();
noInterrupts();
IR_RECV_CONFIG_TICKS();
IR_RECV_ENABLE_INTR;
interrupts();
}
void IrReceiverSampler::disable() {
IR_RECV_DISABLE_INTR;
}
void IrReceiverSampler::setEndingTimeout(milliseconds_t timeOut) {
endingTimeoutInTicks = millisecs2ticks(timeOut);
}
void IrReceiverSampler::setBeginningTimeout(milliseconds_t timeOut) {
beginningTimeoutInTicks = millisecs2ticks(timeOut);
}
milliseconds_t IrReceiverSampler::getEndingTimeout() const {
return ticks2millisecs(endingTimeoutInTicks);
}
milliseconds_t IrReceiverSampler::getBeginningTimeout() const {
return ticks2millisecs(beginningTimeoutInTicks);
}
/** Interrupt routine. It collects data into the data buffer. */
ISR(IR_RECV_INTR_NAME) {
IrReceiverSampler *recv = IrReceiverSampler::getInstance();
IrReceiver::irdata_t irdata = recv->readIr();
recv->timer++; // One more 50us tick
if (recv->dataLength >= recv->getBufferSize()) {
// Buffer full
recv->receiverState = IrReceiverSampler::STATE_STOP;
}
switch (recv->receiverState) {
case IrReceiverSampler::STATE_IDLE: // Looking for first mark
if (irdata == IrReceiver::IR_MARK) {
// Got the first mark, record duration and start recording transmission
recv->dataLength = 0;
recv->timer = 0;
recv->receiverState = IrReceiverSampler::STATE_MARK;
} else {
if (recv->timer >= recv->beginningTimeoutInTicks) {
recv->durationData[recv->dataLength] = recv->timer;
recv->timer = 0;
recv->receiverState = IrReceiverSampler::STATE_STOP;
}
}
break;
case IrReceiverSampler::STATE_MARK:
if (irdata == IrReceiver::IR_SPACE) {
// MARK ended, record time
recv->durationData[recv->dataLength++] = recv->timer;
recv->timer = 0;
recv->receiverState = IrReceiverSampler::STATE_SPACE;
}
break;
case IrReceiverSampler::STATE_SPACE:
if (irdata == IrReceiver::IR_MARK) {
// SPACE just ended, record it
recv->durationData[recv->dataLength++] = recv->timer;
recv->timer = 0;
recv->receiverState = IrReceiverSampler::STATE_MARK;
} else {
// still silence, is it over?
if (recv->timer > recv->endingTimeoutInTicks) {
// big SPACE, indicates gap between codes
recv->durationData[recv->dataLength++] = recv->timer;
//recv->timer = 0;
recv->receiverState = IrReceiverSampler::STATE_STOP;
}
}
break;
case IrReceiverSampler::STATE_STOP:
break;
default:
// should not happen
break;
}
}