-
Notifications
You must be signed in to change notification settings - Fork 35
/
RFQCC1101.h
261 lines (204 loc) · 8.37 KB
/
RFQCC1101.h
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#ifndef RFQUACK_PROJECT_RFQCC1101_H
#define RFQUACK_PROJECT_RFQCC1101_H
#include "RadioLibWrapper.h"
#include "rfquack_logging.h"
class RFQCC1101 : public RadioLibWrapper<CC1101> {
public:
// introduce CC1101 overloads
using CC1101::setPreambleLength;
using CC1101::fixedPacketLengthMode;
using CC1101::setOutputPower;
using CC1101::setPromiscuousMode;
using CC1101::variablePacketLengthMode;
using CC1101::setCrcFiltering;
using CC1101::setRxBandwidth;
using CC1101::setFrequency;
using CC1101::setBitRate;
using CC1101::setFrequencyDeviation;
using CC1101::getFrequencyDeviation;
RFQCC1101(Module *module) : RadioLibWrapper(module, "CC1101") {}
int16_t begin() override {
int16_t state = RadioLibWrapper::begin();
if (state != RADIOLIB_ERR_NONE) return state;
// Set MAX_DVGA_GAIN: Disable the highest step amplification,
// This will prevent noise to be amplified and trigger the CS.
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_AGCCTRL2, RADIOLIB_CC1101_MAX_DVGA_GAIN_1, 7, 6);
// Same as above could be achieved by reducing the LNA again. Both seem to work well, just pick one.
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_AGCCTRL2, RADIOLIB_CC1101_LNA_GAIN_REDUCE_17_1_DB, 5, 3);
// MAGN_TARGET: Set the target for the amplifier loop.
//state |= SPIsetRegValue(CC1101_REG_AGCCTRL2, CC1101_MAGN_TARGET_33_DB, 2, 0);
// Remove whitening
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL0, RADIOLIB_CC1101_WHITE_DATA_OFF, 6, 6);
// Do not append status byte
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL1, RADIOLIB_CC1101_APPEND_STATUS_OFF, 2, 2);
return state;
}
int16_t setFrequency(float freq) override {
return CC1101::setFrequency(freq);
}
int16_t setBitRate(float br) override {
return CC1101::setBitRate(br);
}
int16_t setRxBandwidth(float rxBw) override {
return CC1101::setRxBandwidth(rxBw);
}
int16_t setFrequencyDeviation(float freqDev) override {
return CC1101::setFrequencyDeviation(freqDev);
}
int16_t setOutputPower(uint32_t txPower) override {
return CC1101::setOutputPower((uint8_t)txPower);
}
int16_t variablePacketLengthMode(uint8_t maxLen) override {
return CC1101::variablePacketLengthMode(maxLen);
}
int16_t setPreambleLength(uint32_t preambleLength) override {
return CC1101::setPreambleLength((uint8_t)preambleLength);
}
int16_t setEncoding(uint8_t encoding) override {
return CC1101::setEncoding(encoding);
}
int16_t setSyncWord(uint8_t *bytes, pb_size_t size) override {
if (size == 0) {
// Warning: as side effect this also disables preamble generation /
// detection. CC1101 Datasheet states: "It is not possible to only
// insert preamble or only insert a sync word"
RFQUACK_LOG_TRACE(F("Preamble and SyncWord filtering disabled."))
_syncWords[0] = 0;
_syncWords[1] = 0;
return CC1101::disableSyncWordFiltering();
}
// Call to base method.
int16_t state = CC1101::setSyncWord(bytes, size, 0, true);
if (state == RADIOLIB_ERR_NONE) {
memcpy(_syncWords, bytes, size);
_syncWordLength = size;
}
return state;
}
int16_t getSyncWord(uint8_t *bytes, pb_size_t *size) override {
if (CC1101::_promiscuous) {
// No sync words when in promiscuous mode.
*size = 0;
return RADIOLIB_ERR_NONE;
} else {
*size = _syncWordLength;
memcpy(bytes, _syncWords, (size_t)*size);
}
return RADIOLIB_ERR_NONE;
}
int16_t receiveMode() override {
if (_mode == rfquack_Mode_RX) {
return RADIOLIB_ERR_NONE;
}
// Set mode to standby (needed to flush fifo)
standby();
// Flush RX FIFO
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
_mode = rfquack_Mode_RX;
// Stay in RX mode after a packet is received.
uint8_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_MCSM1, RADIOLIB_CC1101_RXOFF_RX, 3, 2);
// set GDO0 mapping. Asserted when RX FIFO > THR.
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0, RADIOLIB_CC1101_GDOX_RX_FIFO_FULL_OR_PKT_END);
// Set THR to 4 bytes
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_FIFOTHR, RADIOLIB_CC1101_FIFO_THR_TX_61_RX_4, 3, 0);
if (state != RADIOLIB_ERR_NONE) return state;
// Issue receive mode.
SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
_mode = rfquack_Mode_RX;
return RADIOLIB_ERR_NONE;
}
void scal() {
SPIsendCommand(RADIOLIB_CC1101_CMD_CAL);
}
bool isIncomingDataAvailable() override {
// Makes sense only if in RX mode.
if (_mode != rfquack_Mode_RX) {
return false;
}
// GDO0 is asserted if:
// "RX FIFO is filled at or above the RX FIFO threshold or the end of packet is reached"
return digitalRead(_mod->getIrq());
}
int16_t readData(uint8_t *data, size_t len) override {
// Exit if not in RX mode.
if (_mode != rfquack_Mode_RX) {
RFQUACK_LOG_TRACE(F("Trying to readData without being in RX mode."))
return ERR_WRONG_MODE;
}
return CC1101::readData(data, len);
}
int16_t setModulation(rfquack_Modulation modulation) override {
if (modulation == rfquack_Modulation_OOK) {
return CC1101::setOOK(true);
}
if (modulation == rfquack_Modulation_FSK2) {
return CC1101::setOOK(false);
}
return RADIOLIB_ERR_UNSUPPORTED_ENCODING;
}
int16_t getModulation(char *modulation) override {
if (CC1101::_modulation == RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK) {
strcpy(modulation, "OOK");
return RADIOLIB_ERR_NONE;
}
if (CC1101::_modulation == RADIOLIB_CC1101_MOD_FORMAT_2_FSK) {
strcpy(modulation, "FSK2");
return RADIOLIB_ERR_NONE;
}
return RADIOLIB_ERR_UNSUPPORTED_ENCODING;
}
int16_t jamMode() override {
// If the TX FIFO is empty, the modulator will continue to send preamble bytes until the first
// byte is written to the TX FIFO.
// Set a sync word (no sync words means no preamble generation)
byte syncW[] = {0xFF, 0xFF};
uint16_t state = this->setSyncWord(syncW, 2);
if (state != RADIOLIB_ERR_NONE) return state;
// Enable FSK mode with 0 frequency deviation
state = this->setModulation(rfquack_Modulation_FSK2);
state |= this->setFrequencyDeviation(0);
if (state != RADIOLIB_ERR_NONE) return state;
// Set bitrate to 1
state = this->setBitRate(1);
if (state != RADIOLIB_ERR_NONE) return state;
// Put radio in TX Mode
state = this->transmitMode();
if (state != RADIOLIB_ERR_NONE) return state;
// Put radio in fixed len mode
state = this->fixedPacketLengthMode(1);
if (state != RADIOLIB_ERR_NONE) return state;
// Transmit an empty packet.
rfquack_Packet packet = rfquack_Packet_init_zero;
packet.data.bytes[0] = 0xFF;
packet.data.size = 0;
this->transmit(&packet);
return RADIOLIB_ERR_NONE;
}
float getRSSI(float *rssi) override {
CC1101::_rawRSSI = SPIreadRegister(RADIOLIB_CC1101_REG_RSSI);
*rssi = CC1101::getRSSI();
return RADIOLIB_ERR_NONE;
}
int16_t isCarrierDetected(bool *isDetected) override {
uint8_t pktStatus = SPIreadRegister(RADIOLIB_CC1101_REG_PKTSTATUS);
*isDetected = (pktStatus & 0x40);
return RADIOLIB_ERR_NONE;
}
void writeRegister(rfquack_register_address_t reg, rfquack_register_value_t value, uint8_t msb, uint8_t lsb) override {
SPIsetRegValue((uint8_t) reg, (uint8_t) value, msb, lsb, 0);
}
void removeInterrupts() override {
detachInterrupt(digitalPinToInterrupt(_mod->getIrq()));
}
void setRxInterruptAction(void (*func)(void *)) {
attachInterruptArg(digitalPinToInterrupt(_mod->getIrq()), func, (void *) (&_receivedFlag), RISING);
}
void setTxInterruptAction(void (*func)(void *)) {
attachInterruptArg(digitalPinToInterrupt(_mod->getIrq()), func, (void *) (&_transmittedFlag), RISING);
}
private:
// Config variables not provided by RadioLib, initialised with default values
byte _syncWords[RADIOLIB_CC1101_DEFAULT_SW_LEN] = RADIOLIB_CC1101_DEFAULT_SW;
uint8_t _syncWordLength = RADIOLIB_CC1101_DEFAULT_SW_LEN;
};
#endif //RFQUACK_PROJECT_RFQCC1101_H