Repository navigation
Expand file tree
/
Copy pathxbee_control.cpp
More file actions
131 lines (117 loc) · 4.18 KB
/
Copy pathxbee_control.cpp
File metadata and controls
131 lines (117 loc) · 4.18 KB
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
#include "xbee_control.h"
namespace {
int hexNibble(char c) {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
return -1;
}
// Parses exactly byteCount*2 hex characters from hex into outBytes.
// Returns false (leaving outBytes untouched) on any non-hex character or
// a string shorter than expected.
bool hexStringToBytes(const char *hex, uint8_t *outBytes, size_t byteCount) {
for (size_t i = 0; i < byteCount; i++) {
const int hi = hexNibble(hex[i * 2]);
const int lo = hi >= 0 ? hexNibble(hex[i * 2 + 1]) : -1;
if (hi < 0 || lo < 0) return false;
outBytes[i] = static_cast<uint8_t>((hi << 4) | lo);
}
return true;
}
void bytesToHexString(const uint8_t *bytes, size_t byteCount, char *outHex) {
constexpr char kDigits[] = "0123456789ABCDEF";
for (size_t i = 0; i < byteCount; i++) {
outHex[i * 2] = kDigits[bytes[i] >> 4];
outHex[i * 2 + 1] = kDigits[bytes[i] & 0x0F];
}
outHex[byteCount * 2] = '\0';
}
} // namespace
bool XbeeControl::leaveNetwork() {
// "NR0": local network reset — forces the module to leave its current
// network and search again per its (about-to-change) ID setting.
uint8_t value[] = {0};
return spi_.sendAtCommand("NR", value, sizeof(value), nullptr, 0, nullptr);
}
bool XbeeControl::setPanId(const char *panId) {
uint8_t panIdBytes[8];
if (!hexStringToBytes(panId, panIdBytes, sizeof(panIdBytes))) {
return false;
}
if (!spi_.sendAtCommand("ID", panIdBytes, sizeof(panIdBytes), nullptr, 0,
nullptr)) {
return false;
}
// "WR": commit to the module's own flash. Once written, the module
// remembers this PAN ID across power cycles on its own — nothing needs
// to re-apply it at boot, and it never changes again until this method
// is called again for a different droid.
return spi_.sendAtCommand("WR", nullptr, 0, nullptr, 0, nullptr);
}
bool XbeeControl::rejoinNetwork() {
// "AC": apply pending parameter changes now, triggering the module to
// act on the new ID and (re)associate rather than waiting for its next
// natural re-read of that setting.
return spi_.sendAtCommand("AC", nullptr, 0, nullptr, 0, nullptr);
}
bool XbeeControl::queryByteParameter(const char *command,
uint8_t *outValue) {
uint8_t value[1];
uint8_t valueLength = 0;
if (!spi_.sendAtCommand(command, nullptr, 0, value, sizeof(value),
&valueLength) ||
valueLength != sizeof(value)) {
return false;
}
*outValue = value[0];
return true;
}
bool XbeeControl::writeByteParameter(const char *command, uint8_t value) {
return spi_.sendAtCommand(command, &value, sizeof(value), nullptr, 0,
nullptr);
}
bool XbeeControl::commitAndApply() {
// "WR" so the settings survive power cycles, "AC" so they take effect
// now.
return spi_.sendAtCommand("WR", nullptr, 0, nullptr, 0, nullptr) &&
spi_.sendAtCommand("AC", nullptr, 0, nullptr, 0, nullptr);
}
bool XbeeControl::querySerialLow(char *outHex, size_t outHexCapacity) {
if (outHexCapacity < 9) {
return false; // 8 hex chars + null
}
uint8_t value[4];
uint8_t valueLength = 0;
if (!spi_.sendAtCommand("SL", nullptr, 0, value, sizeof(value),
&valueLength) ||
valueLength != sizeof(value)) {
return false;
}
bytesToHexString(value, sizeof(value), outHex);
return true;
}
bool XbeeControl::queryPanId(char *outHex, size_t outHexCapacity) {
if (outHexCapacity < 17) {
return false; // 16 hex chars + null
}
uint8_t value[8];
uint8_t valueLength = 0;
if (!spi_.sendAtCommand("ID", nullptr, 0, value, sizeof(value),
&valueLength) ||
valueLength != sizeof(value)) {
return false;
}
bytesToHexString(value, sizeof(value), outHex);
return true;
}
bool XbeeControl::queryLocalRssiDbm(int *outDbm) {
uint8_t value[1];
uint8_t valueLength = 0;
if (!spi_.sendAtCommand("DB", nullptr, 0, value, sizeof(value),
&valueLength) ||
valueLength != sizeof(value)) {
return false;
}
*outDbm = -static_cast<int>(value[0]);
return true;
}