-
Notifications
You must be signed in to change notification settings - Fork 0
/
UHFRecv.cpp
179 lines (157 loc) · 4.41 KB
/
UHFRecv.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
#include "UHFRecv.h"
/* Default constructor */
UHFRecv::UHFRecv(): _uhfSerial(Serial1)
{
_baudRate = DEFAULT_BAUD_RATE; //< 57600 bps
_protocol = DEFAULT_PROTOCOL; //< 8N1
_ctlPin = DEFAULT_RS485_CTL_PIN; //< 4
}
UHFRecv::UHFRecv(HardwareSerial& serial, const long baudRate, const byte ctlPin):
_uhfSerial(serial)
{
_baudRate = baudRate;
_ctlPin = ctlPin;
_protocol = DEFAULT_PROTOCOL;
}
/* Full customisation for UHFRecv() */
UHFRecv::UHFRecv(HardwareSerial& serial, const long baudRate,
const SerialProtocol protocol, const byte ctlPin): _uhfSerial(serial)
{
_baudRate = baudRate;
_protocol = protocol;
_ctlPin = ctlPin;
}
/**
* @public
* @brief Initialise PK-UHF101 Receiver
*/
void UHFRecv::begin()
{
pinMode(_ctlPin, OUTPUT);
_uhfSerial.begin(_baudRate, _protocol);
digitalWrite(_ctlPin, RS485_RECEIVE);
}
/**
* @public
* @brief Set command for cards inventory
*/
byte* UHFRecv::setCommand(const byte readerAddr,
const byte addrTid, const byte lenTid)
{
// see `doc/Protocols` for more commands
const byte command = 0x01; //< Inventory command
// size of the command (exclude the size itself)
_inventoryCmd[0] = sizeof(_inventoryCmd) - 1;
_inventoryCmd[1] = readerAddr;
_inventoryCmd[2] = command;
_inventoryCmd[3] = addrTid;
_inventoryCmd[4] = lenTid;
UHFRecv::Crc crc = _calculateCrc(_inventoryCmd, sizeof(_inventoryCmd) - 2);
_inventoryCmd[5] = highByte(crc);
_inventoryCmd[6] = lowByte(crc);
return _inventoryCmd;
}
/* Get inventory command's size */
const size_t UHFRecv::getSizeCommand()
{
return sizeof(_inventoryCmd);
}
/**
* @public
* @brief Ensure the preservation of data.
*/
bool UHFRecv::isDataPreserved(byte* receivedData, size_t size)
{
UHFRecv::Crc reCalCrc = UHFRecv::_calculateCrc(receivedData, size - 2);
UHFRecv::Crc receivedCrc = 0x00;
if (receivedData[RE_STATUS_INDEX] == ERR_CRC)
return false;
else {
// Merge 2 checksum bytes into 16-bit CRC-16
byte lowByte = receivedData[size - 2];
byte highByte = receivedData[size - 1];
if (isLittleEndian())
receivedCrc = (lowByte << 8) | highByte;
else
receivedCrc = (highByte << 8) | lowByte;
/*
* If the calculated CRC-16 and the received CRC-16 are not the same,
* then the data from reader to RS485 are not preserved.
*/
return (receivedCrc != reCalCrc) ? false : true;
}
}
/**
* @public
* @brief Get bytes of data from UHF reader
*/
Status UHFRecv::getRawData(byte* reData, byte* request, size_t size)
{
digitalWrite(_ctlPin, RS485_TRANSMIT);
_uhfSerial.write(request, size);
delay(10); //< [WARNING] This delay is VERY IMPORTANT
digitalWrite(_ctlPin, RS485_RECEIVE);
byte i = 0;
while (_uhfSerial.available() > 0) {
reData[i] = _uhfSerial.read();
if (reData[i] < 0) //< return -1 if no data is read
return ERR_READ_RS485;
i++;
}
delay(2); //< [WARNING] This delay is VERY IMPORTANT
return STATUS_SUCCESS;
}
/**
* @public
* @brief Debug function - print bytes of data read from RS485 with base
*/
void UHFRecv::_debugPrintRawData(byte* reData, size_t size, byte base)
{
for (byte i = 0; i < size; i++) {
Serial.print(reData[i], base);
Serial.print(" ");
}
Serial.println();
}
/**
* @public
* @brief Debug function - print bytes of data (HEX) read from RS485
*/
void UHFRecv::_debugPrintRawData(byte* reData, size_t size)
{
for (byte i = 0; i < size; i++) {
Serial.print(reData[i], HEX);
Serial.print(" ");
}
Serial.println();
}
/**
* @private
* @brief CRC-16 Calculator (polynomial of 0x8408)
*/
UHFRecv::Crc UHFRecv::_calculateCrc(byte* data, size_t size)
{
_crc = 0xFFFF;
for (size_t i = 0; i < size; i++) {
_crc ^= data[i];
for (byte j = 0; j < 8; j++) {
if (_crc & 0x0001)
_crc = (_crc >> 1) ^ 0x8408; //< Fixed polynomial
else
_crc = _crc >> 1;
}
}
/* return the result based on the endianess of the system */
if (isLittleEndian())
return _crc >> 8 | _crc << 8;
else
return _crc;
}
/**
* @brief Check the system endianess
*/
bool isLittleEndian()
{
byte endianess = 0x0001;
return (bool)(*(byte *)&(endianess)); //< True if the system is little endian
}