forked from zeitgeist87/RFReceiver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RFReceiver.cpp
137 lines (110 loc) · 3.35 KB
/
RFReceiver.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
#include "RFReceiver.h"
#if defined(__AVR__)
#include <util/crc16.h>
#endif
static inline uint16_t crc_update(uint16_t crc, uint8_t data) {
#if defined(__AVR__)
return _crc_ccitt_update(crc, data);
#else
// Source: http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__util__crc_1ga1c1d3ad875310cbc58000e24d981ad20.html
data ^= crc & 0xFF;
data ^= data << 4;
return ((((uint16_t)data << 8) | (crc >> 8)) ^ (uint8_t)(data >> 4)
^ ((uint16_t)data << 3));
#endif
}
static inline byte recoverByte(const byte b1, const byte b2, const byte b3) {
// Discard all bits that occur only once in the three input bytes
// Use all bits that are in b1 and b2
byte res = b1 & b2;
// Use all bits that are in b1 and b3
res |= b1 & b3;
// Use all bits that are in b2 and b3
res |= b2 & b3;
return res;
}
void RFReceiver::decodeByte(byte inputByte) {
if (!packageStarted)
return;
errorCorBuf[errorCorBufCount++] = inputByte;
if (errorCorBufCount != 3)
return;
errorCorBufCount = 0;
if (!byteCount) {
// Quickly decide if this is really a package or not
if (errorCorBuf[0] < MIN_PACKAGE_SIZE || errorCorBuf[0] > MAX_PACKAGE_SIZE ||
errorCorBuf[0] != errorCorBuf[1] || errorCorBuf[0] != errorCorBuf[2]) {
packageStarted = false;
return;
}
inputBufLen = errorCorBuf[0];
checksum = crc_update(checksum, inputBufLen);
} else {
byte data = recoverByte(errorCorBuf[0], errorCorBuf[1], errorCorBuf[2]);
inputBuf[byteCount - 1] = data;
// Calculate the checksum on the fly
checksum = crc_update(checksum, data);
if (byteCount == inputBufLen) {
byte senderId = inputBuf[inputBufLen - 4];
byte packageId = inputBuf[inputBufLen - 3];
// Ignore duplicate packages and check if the checksum is correct
if (!checksum && senderId <= MAX_SENDER_ID && prevPackageIds[senderId] != packageId) {
prevPackageIds[senderId] = packageId;
inputBufReady = true;
}
packageStarted = false;
return;
}
}
++byteCount;
}
void RFReceiver::handlePCInterrupt(int8_t pcIntNum, bool state) {
if (inputBufReady)
return;
++changeCount;
{
unsigned long time = micros();
if (time - lastTimestamp < pulseLimit)
return;
lastTimestamp = time;
}
shiftByte = (shiftByte >> 2) | ((changeCount - 1) << 6);
changeCount = 0;
if (packageStarted) {
bitCount += 2;
if (bitCount != 8)
return;
bitCount = 0;
decodeByte(shiftByte);
} else if (shiftByte == 0xE0) {
// New package starts here
bitCount = 0;
byteCount = 0;
errorCorBufCount = 0;
inputBufLen = 0;
checksum = 0xffff;
packageStarted = true;
}
}
byte RFReceiver::recvDataRaw(byte * data) {
while (!inputBufReady);
byte len = inputBufLen;
memcpy(data, inputBuf, len - 2);
// Enable the input as fast as possible
inputBufReady = false;
// The last two bytes contain the checksum, which is no longer needed
return len - 2;
}
byte RFReceiver::recvPackage(byte *data, byte *pSenderId, byte *pPackageId) {
for (;;) {
byte len = recvDataRaw(data);
byte senderId = data[len - 2];
byte packageId = data[len - 1];
if (pSenderId)
*pSenderId = senderId;
if (pPackageId)
*pPackageId = packageId;
// The last two bytes contain the sender and package ids
return len - 2;
}
}