|
@@ -1,6 +1,7 @@
|
1
|
1
|
/*
|
2
|
2
|
* Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
|
3
|
3
|
* Copyright (c) 2014 Intel Corporation.
|
|
4
|
+ * BLE Beaconing based on http://dmitry.gr/index.php?r=05.Projects&proj=11.%20Bluetooth%20LE%20fakery
|
4
|
5
|
*
|
5
|
6
|
* Permission is hereby granted, free of charge, to any person obtaining
|
6
|
7
|
* a copy of this software and associated documentation files (the
|
|
@@ -30,12 +31,12 @@
|
30
|
31
|
|
31
|
32
|
using namespace upm;
|
32
|
33
|
|
33
|
|
-NRF24l01::NRF24l01 (uint8_t cs) {
|
|
34
|
+NRF24L01::NRF24L01 (uint8_t cs, uint8_t ce) {
|
34
|
35
|
mraa_init();
|
35
|
|
- nrfInitModule (cs, 8);
|
|
36
|
+ init (cs, ce);
|
36
|
37
|
}
|
37
|
38
|
|
38
|
|
-NRF24l01::~NRF24l01 () {
|
|
39
|
+NRF24L01::~NRF24L01 () {
|
39
|
40
|
mraa_result_t error = MRAA_SUCCESS;
|
40
|
41
|
error = mraa_spi_stop(m_spi);
|
41
|
42
|
if (error != MRAA_SUCCESS) {
|
|
@@ -52,12 +53,12 @@ NRF24l01::~NRF24l01 () {
|
52
|
53
|
}
|
53
|
54
|
|
54
|
55
|
void
|
55
|
|
-NRF24l01::nrfInitModule (uint8_t chip_select, uint8_t chip_enable) {
|
|
56
|
+NRF24L01::init (uint8_t chip_select, uint8_t chip_enable) {
|
56
|
57
|
mraa_result_t error = MRAA_SUCCESS;
|
57
|
58
|
|
58
|
|
- m_csn = chip_select;
|
59
|
|
- m_ce = chip_enable;
|
60
|
|
- m_channel = 1;
|
|
59
|
+ m_csn = chip_select;
|
|
60
|
+ m_ce = chip_enable;
|
|
61
|
+ m_channel = 99;
|
61
|
62
|
|
62
|
63
|
m_csnPinCtx = mraa_gpio_init (m_csn);
|
63
|
64
|
if (m_csnPinCtx == NULL) {
|
|
@@ -81,239 +82,454 @@ NRF24l01::nrfInitModule (uint8_t chip_select, uint8_t chip_enable) {
|
81
|
82
|
mraa_result_print (error);
|
82
|
83
|
}
|
83
|
84
|
|
84
|
|
- nrfCELow ();
|
|
85
|
+ ceLow();
|
|
86
|
+ csOff ();
|
|
87
|
+
|
85
|
88
|
m_spi = mraa_spi_init (0);
|
86
|
89
|
}
|
87
|
90
|
|
88
|
91
|
void
|
89
|
|
-NRF24l01::nrfConfigModule() {
|
|
92
|
+NRF24L01::configure () {
|
90
|
93
|
/* Set RF channel */
|
91
|
|
- nrfConfigRegister (RF_CH, m_channel);
|
|
94
|
+ setRegister (RF_CH, m_channel);
|
92
|
95
|
|
93
|
96
|
/* Set length of incoming payload */
|
94
|
|
- nrfConfigRegister (RX_PW_P0, m_payload);
|
95
|
|
- nrfConfigRegister (RX_PW_P1, m_payload);
|
|
97
|
+ setRegister (RX_PW_P0, m_payload);
|
|
98
|
+
|
96
|
99
|
/* Set length of incoming payload for broadcast */
|
97
|
|
- nrfConfigRegister (RX_PW_P2, m_payload);
|
|
100
|
+ setRegister (RX_PW_P1, m_payload);
|
98
|
101
|
|
99
|
102
|
/* Start receiver */
|
100
|
|
- nrfPowerUpRX ();
|
101
|
|
- nrfFlushRX ();
|
|
103
|
+ rxPowerUp ();
|
|
104
|
+ rxFlushBuffer ();
|
102
|
105
|
}
|
103
|
106
|
|
104
|
|
-/* Clocks only one byte into the given MiRF register */
|
105
|
107
|
void
|
106
|
|
-NRF24l01::nrfConfigRegister(uint8_t reg, uint8_t value) {
|
107
|
|
- nrfCSOn ();
|
108
|
|
- mraa_spi_write (m_spi, W_REGISTER | (REGISTER_MASK & reg));
|
109
|
|
- mraa_spi_write (m_spi, value);
|
110
|
|
- nrfCSOff ();
|
111
|
|
-}
|
|
108
|
+NRF24L01::send (uint8_t * value) {
|
|
109
|
+ uint8_t status;
|
|
110
|
+ status = getStatus();
|
112
|
111
|
|
113
|
|
-void
|
114
|
|
-NRF24l01::nrfPowerUpRX() {
|
115
|
|
- m_ptx = 0;
|
116
|
|
- nrfCELow();
|
117
|
|
- nrfConfigRegister(CONFIG, NRF_CONFIG | ( (1<<PWR_UP) | (1<<PRIM_RX) ) );
|
118
|
|
- nrfCEHigh();
|
119
|
|
- nrfConfigRegister(STATUS,(1 << TX_DS) | (1 << MAX_RT));
|
120
|
|
-}
|
|
112
|
+ while (m_ptx) {
|
|
113
|
+ status = getStatus();
|
121
|
114
|
|
122
|
|
-void
|
123
|
|
-NRF24l01::nrfFlushRX() {
|
124
|
|
- nrfCSOn ();
|
125
|
|
- mraa_spi_write (m_spi, FLUSH_RX);
|
126
|
|
- nrfCSOff ();
|
127
|
|
-}
|
|
115
|
+ if((status & ((1 << TX_DS) | (1 << MAX_RT)))){
|
|
116
|
+ m_ptx = 0;
|
|
117
|
+ break;
|
|
118
|
+ }
|
|
119
|
+ } // Wait until last paket is send
|
128
|
120
|
|
129
|
|
-/* Sets the receiving address */
|
130
|
|
-void
|
131
|
|
-NRF24l01::nrfSetRXaddr(uint8_t * addr) {
|
132
|
|
- nrfCELow();
|
133
|
|
- nrfWriteRegister(RX_ADDR_P1, addr, ADDR_LEN);
|
134
|
|
- nrfCEHigh();
|
|
121
|
+ ceLow ();
|
|
122
|
+ txPowerUp (); // Set to transmitter mode , Power up
|
|
123
|
+ txFlushBuffer ();
|
|
124
|
+
|
|
125
|
+ csOn ();
|
|
126
|
+ mraa_spi_write (m_spi, W_TX_PAYLOAD); // Write cmd to write payload
|
|
127
|
+ writeBytes (value, NULL, m_payload); // Write payload
|
|
128
|
+ csOff ();
|
|
129
|
+ ceHigh(); // Start transmission
|
|
130
|
+
|
|
131
|
+ while (dataSending ()) { }
|
|
132
|
+
|
|
133
|
+ usleep (10000);
|
135
|
134
|
}
|
136
|
135
|
|
137
|
|
-/* Sets the transmitting address */
|
138
|
136
|
void
|
139
|
|
-NRF24l01::nrfSetTXaddr(uint8_t * addr)
|
140
|
|
-{
|
141
|
|
- /* RX_ADDR_P0 must be set to the sending addr for auto ack to work. */
|
142
|
|
- nrfWriteRegister (RX_ADDR_P0, addr, ADDR_LEN);
|
143
|
|
- nrfWriteRegister (TX_ADDR, addr, ADDR_LEN);
|
|
137
|
+NRF24L01::send () {
|
|
138
|
+ send (m_txBuffer);
|
144
|
139
|
}
|
145
|
140
|
|
146
|
|
-/* The broadcast address should be 0xFFFFF */
|
147
|
141
|
void
|
148
|
|
-NRF24l01::nrfSetBroadcastAddr (uint8_t * addr) {
|
149
|
|
- nrfCELow ();
|
150
|
|
- nrfWriteRegister (RX_ADDR_P2, addr, ADDR_LEN);
|
151
|
|
- nrfCEHigh ();
|
|
142
|
+NRF24L01::setSourceAddress (uint8_t * addr) {
|
|
143
|
+ ceLow ();
|
|
144
|
+ writeRegister (RX_ADDR_P0, addr, ADDR_LEN);
|
|
145
|
+ ceHigh ();
|
152
|
146
|
}
|
153
|
147
|
|
154
|
148
|
void
|
155
|
|
-NRF24l01::nrfSetPayload (uint8_t load) {
|
156
|
|
- m_payload = load;
|
|
149
|
+NRF24L01::setDestinationAddress (uint8_t * addr) {
|
|
150
|
+ writeRegister (TX_ADDR, addr, ADDR_LEN);
|
157
|
151
|
}
|
158
|
152
|
|
159
|
153
|
void
|
160
|
|
-NRF24l01::nrfWriteRegister(uint8_t reg, uint8_t * value, uint8_t len)
|
161
|
|
-{
|
162
|
|
- nrfCSOn ();
|
163
|
|
- mraa_spi_write (m_spi, W_REGISTER | (REGISTER_MASK & reg));
|
164
|
|
- nrfTransmitSync(value, len);
|
165
|
|
- nrfCSOff ();
|
|
154
|
+NRF24L01::setBroadcastAddress (uint8_t * addr) {
|
|
155
|
+ writeRegister (RX_ADDR_P1, addr, ADDR_LEN);
|
166
|
156
|
}
|
167
|
157
|
|
168
|
158
|
void
|
169
|
|
-NRF24l01::nrfTransmitSync(uint8_t *dataout, uint8_t len){
|
170
|
|
- uint8_t i;
|
171
|
|
- for(i = 0; i < len; i++) {
|
172
|
|
- mraa_spi_write (m_spi, dataout[i]);
|
173
|
|
- }
|
|
159
|
+NRF24L01::setPayload (uint8_t payload) {
|
|
160
|
+ m_payload = payload;
|
174
|
161
|
}
|
175
|
162
|
|
176
|
|
-/* Checks if data is available for reading */
|
177
|
163
|
bool
|
178
|
|
-NRF24l01::nrfDataReady() {
|
179
|
|
- uint8_t status = nrfGetStatus();
|
|
164
|
+NRF24L01::dataReady () {
|
|
165
|
+ /* See note in getData() function - just checking RX_DR isn't good enough */
|
|
166
|
+ uint8_t status = getStatus();
|
|
167
|
+ /* We can short circuit on RX_DR, but if it's not set, we still need
|
|
168
|
+ * to check the FIFO for any pending packets */
|
180
|
169
|
if ( status & (1 << RX_DR) ) {
|
181
|
170
|
return 1;
|
182
|
171
|
}
|
183
|
172
|
|
184
|
|
- return !nrfRXFifoEmpty();
|
|
173
|
+ return !rxFifoEmpty();
|
185
|
174
|
}
|
186
|
175
|
|
187
|
|
-uint8_t
|
188
|
|
-NRF24l01::nrfGetStatus () {
|
189
|
|
- uint8_t rv;
|
190
|
|
- nrfReadRegister (STATUS, &rv, 1);
|
191
|
|
- return rv;
|
|
176
|
+bool
|
|
177
|
+NRF24L01::dataSending () {
|
|
178
|
+ uint8_t status;
|
|
179
|
+ if(m_ptx) { // Sending mode.
|
|
180
|
+ status = getStatus();
|
|
181
|
+ /* if sending successful (TX_DS) or max retries exceded (MAX_RT). */
|
|
182
|
+ if((status & ((1 << TX_DS) | (1 << MAX_RT)))){
|
|
183
|
+ rxPowerUp ();
|
|
184
|
+ return false;
|
|
185
|
+ }
|
|
186
|
+ return true;
|
|
187
|
+ }
|
|
188
|
+ return false;
|
192
|
189
|
}
|
193
|
190
|
|
194
|
|
-/* Reads an array of bytes from the given start position in the MiRF registers. */
|
195
|
191
|
void
|
196
|
|
-NRF24l01::nrfReadRegister (uint8_t reg, uint8_t * value, uint8_t len)
|
197
|
|
-{
|
198
|
|
- nrfCSOn ();
|
199
|
|
- mraa_spi_write (m_spi, R_REGISTER | (REGISTER_MASK & reg));
|
200
|
|
- nrfTransferSync (value, value, len);
|
201
|
|
- nrfCSOff ();
|
|
192
|
+NRF24L01::getData (uint8_t * data) {
|
|
193
|
+ csOn ();
|
|
194
|
+ /* Send cmd to read rx payload */
|
|
195
|
+ mraa_spi_write (m_spi, R_RX_PAYLOAD);
|
|
196
|
+ /* Read payload */
|
|
197
|
+ writeBytes (data, data, m_payload);
|
|
198
|
+ csOff ();
|
|
199
|
+ /* NVI: per product spec, p 67, note c:
|
|
200
|
+ * "The RX_DR IRQ is asserted by a new packet arrival event. The procedure
|
|
201
|
+ * for handling this interrupt should be: 1) read payload through SPI,
|
|
202
|
+ * 2) clear RX_DR IRQ, 3) read FIFO_STATUS to check if there are more
|
|
203
|
+ * payloads available in RX FIFO, 4) if there are more data in RX FIFO,
|
|
204
|
+ * repeat from step 1)."
|
|
205
|
+ * So if we're going to clear RX_DR here, we need to check the RX FIFO
|
|
206
|
+ * in the dataReady() function */
|
|
207
|
+ /* Reset status register */
|
|
208
|
+ setRegister (STATUS, (1<<RX_DR));
|
202
|
209
|
}
|
203
|
210
|
|
204
|
|
-void
|
205
|
|
-NRF24l01::nrfTransferSync (uint8_t *dataout,uint8_t *datain,uint8_t len) {
|
206
|
|
- uint8_t i;
|
207
|
|
- for(i = 0;i < len;i++) {
|
208
|
|
- datain[i] = mraa_spi_write (m_spi, dataout[i]);
|
209
|
|
- }
|
|
211
|
+uint8_t
|
|
212
|
+NRF24L01::getStatus() {
|
|
213
|
+ return getRegister (STATUS);
|
210
|
214
|
}
|
211
|
215
|
|
212
|
216
|
bool
|
213
|
|
-NRF24l01::nrfRXFifoEmpty () {
|
214
|
|
- uint8_t fifo_status;
|
215
|
|
- nrfReadRegister (FIFO_STATUS, &fifo_status, sizeof(fifo_status));
|
216
|
|
- return (fifo_status & (1 << RX_EMPTY));
|
|
217
|
+NRF24L01::rxFifoEmpty () {
|
|
218
|
+ uint8_t fifoStatus = getRegister (FIFO_STATUS);
|
|
219
|
+ return (fifoStatus & (1 << RX_EMPTY));
|
217
|
220
|
}
|
218
|
221
|
|
219
|
|
-/* Reads payload bytes into data array */
|
220
|
222
|
void
|
221
|
|
-NRF24l01::nrfGetData (uint8_t * data)
|
222
|
|
-{
|
223
|
|
- nrfCSOn ();
|
224
|
|
- /* Send cmd to read rx payload */
|
225
|
|
- mraa_spi_write (m_spi, R_RX_PAYLOAD);
|
226
|
|
- /* Read payload */
|
227
|
|
- nrfTransferSync(data, data, m_payload);
|
228
|
|
- nrfCSOff ();
|
229
|
|
- nrfConfigRegister(STATUS, (1<<RX_DR));
|
|
223
|
+NRF24L01::rxPowerUp () {
|
|
224
|
+ m_ptx = 0;
|
|
225
|
+ ceLow ();
|
|
226
|
+ setRegister (CONFIG, _CONFIG | ( (1 << PWR_UP) | (1 << PRIM_RX) ));
|
|
227
|
+ ceHigh ();
|
|
228
|
+ setRegister (STATUS, (1 << TX_DS) | (1 << MAX_RT));
|
230
|
229
|
}
|
231
|
230
|
|
232
|
|
-/* Sends a data package to the default address. Be sure to send the correct
|
233
|
|
- * amount of bytes as configured as payload on the receiver. */
|
234
|
231
|
void
|
235
|
|
-NRF24l01::nrfSend(uint8_t * value) {
|
236
|
|
- uint8_t status;
|
237
|
|
- status = nrfGetStatus();
|
238
|
|
-
|
239
|
|
- while (m_ptx) {
|
240
|
|
- status = nrfGetStatus();
|
241
|
|
-
|
242
|
|
- if((status & ((1 << TX_DS) | (1 << MAX_RT)))){
|
243
|
|
- m_ptx = 0;
|
244
|
|
- break;
|
245
|
|
- }
|
246
|
|
- } // Wait until last paket is send
|
247
|
|
-
|
248
|
|
- nrfCELow();
|
249
|
|
- nrfPowerUpTX(); // Set to transmitter mode , Power up
|
250
|
|
- nrfCSOn ();
|
251
|
|
- mraa_spi_write (m_spi, FLUSH_TX); // Write cmd to flush tx fifo
|
252
|
|
- nrfCSOff ();
|
253
|
|
-
|
254
|
|
- nrfCSOn ();
|
255
|
|
- mraa_spi_write (m_spi, W_TX_PAYLOAD); // Write cmd to write payload
|
256
|
|
- nrfTransmitSync(value, m_payload); // Write payload
|
257
|
|
- nrfCSOff ();
|
258
|
|
- nrfCEHigh(); // Start transmission
|
|
232
|
+NRF24L01::rxFlushBuffer () {
|
|
233
|
+ sendCommand (FLUSH_RX);
|
259
|
234
|
}
|
260
|
235
|
|
261
|
236
|
void
|
262
|
|
-NRF24l01::nrfSend () {
|
263
|
|
- nrfSend (m_txBuffer);
|
|
237
|
+NRF24L01::txPowerUp () {
|
|
238
|
+ m_ptx = 1;
|
|
239
|
+ setRegister (CONFIG, _CONFIG | ( (1 << PWR_UP) | (0 << PRIM_RX) ));
|
264
|
240
|
}
|
265
|
241
|
|
266
|
|
-bool
|
267
|
|
-NRF24l01::nrfIsSending () {
|
268
|
|
- uint8_t status;
|
269
|
|
- if (m_ptx) { // Sending mode.
|
270
|
|
- status = nrfGetStatus();
|
271
|
|
- /* if sending successful (TX_DS) or max retries exceded (MAX_RT). */
|
272
|
|
- if((status & ((1 << TX_DS) | (1 << MAX_RT)))){
|
273
|
|
- nrfPowerUpRX();
|
274
|
|
- return false;
|
275
|
|
- }
|
276
|
|
- return true;
|
277
|
|
- }
|
278
|
|
- return false;
|
|
242
|
+void
|
|
243
|
+NRF24L01::powerDown(){
|
|
244
|
+ ceLow ();
|
|
245
|
+ setRegister (CONFIG, _CONFIG);
|
279
|
246
|
}
|
280
|
247
|
|
281
|
248
|
void
|
282
|
|
-NRF24l01::nrfPowerUpTX () {
|
283
|
|
- m_ptx = 1;
|
284
|
|
- nrfConfigRegister (CONFIG, NRF_CONFIG | ( (1<<PWR_UP) | (0<<PRIM_RX) ) );
|
|
249
|
+NRF24L01::setChannel (uint8_t channel) {
|
|
250
|
+ m_channel = channel;
|
|
251
|
+ setRegister (RF_CH, channel);
|
285
|
252
|
}
|
286
|
253
|
|
287
|
254
|
void
|
288
|
|
-NRF24l01::nrfPowerDown () {
|
289
|
|
- nrfCELow ();
|
290
|
|
- nrfConfigRegister (CONFIG, NRF_CONFIG);
|
|
255
|
+NRF24L01::setPower (power_t power) {
|
|
256
|
+ uint8_t setupRegisterData = 0;
|
|
257
|
+
|
|
258
|
+ switch (power) {
|
|
259
|
+ case NRF_0DBM:
|
|
260
|
+ m_power = 3;
|
|
261
|
+ break;
|
|
262
|
+ case NRF_6DBM:
|
|
263
|
+ m_power = 2;
|
|
264
|
+ break;
|
|
265
|
+ case NRF_12DBM:
|
|
266
|
+ m_power = 1;
|
|
267
|
+ break;
|
|
268
|
+ case NRF_18DBM:
|
|
269
|
+ m_power = 0;
|
|
270
|
+ break;
|
|
271
|
+ }
|
|
272
|
+
|
|
273
|
+ setupRegisterData = getRegister (RF_SETUP); // Read current value.
|
|
274
|
+ setupRegisterData &= 0xFC; // Erase the old value;
|
|
275
|
+ setupRegisterData |= (m_power & 0x3);
|
|
276
|
+ setRegister (RF_SETUP, setupRegisterData); // Write the new value.
|
|
277
|
+}
|
|
278
|
+
|
|
279
|
+uint8_t
|
|
280
|
+NRF24L01::setSpeedRate (speed_rate_t rate) {
|
|
281
|
+ uint8_t setupRegisterData = 0;
|
|
282
|
+
|
|
283
|
+ setupRegisterData = getRegister (RF_SETUP); // Read current value.
|
|
284
|
+ setupRegisterData &= ~((1 << RF_DR_LOW) | (1 << RF_DR_HIGH));
|
|
285
|
+
|
|
286
|
+ switch (rate) {
|
|
287
|
+ case NRF_250KBPS:
|
|
288
|
+ setupRegisterData |= (1 << RF_DR_LOW) ;
|
|
289
|
+ break;
|
|
290
|
+ case NRF_1MBPS:
|
|
291
|
+ break;
|
|
292
|
+ case NRF_2MBPS:
|
|
293
|
+ setupRegisterData |= (1 << RF_DR_HIGH);
|
|
294
|
+ break;
|
|
295
|
+ }
|
|
296
|
+
|
|
297
|
+ setRegister (RF_SETUP, setupRegisterData); // Write the new value.
|
|
298
|
+
|
|
299
|
+ if (setupRegisterData == getRegister (RF_SETUP)) {
|
|
300
|
+ return 0x0;
|
|
301
|
+ }
|
|
302
|
+
|
|
303
|
+ return 0x1;
|
291
|
304
|
}
|
292
|
305
|
|
293
|
306
|
mraa_result_t
|
294
|
|
-NRF24l01::nrfCEHigh () {
|
|
307
|
+NRF24L01::ceHigh () {
|
295
|
308
|
return mraa_gpio_write (m_cePinCtx, HIGH);
|
296
|
309
|
}
|
297
|
310
|
|
298
|
311
|
mraa_result_t
|
299
|
|
-NRF24l01::nrfCELow () {
|
|
312
|
+NRF24L01::ceLow () {
|
300
|
313
|
return mraa_gpio_write (m_cePinCtx, LOW);
|
301
|
314
|
}
|
302
|
315
|
|
303
|
316
|
mraa_result_t
|
304
|
|
-NRF24l01::nrfCSOn () {
|
|
317
|
+NRF24L01::csOn () {
|
305
|
318
|
return mraa_gpio_write (m_csnPinCtx, LOW);
|
306
|
319
|
}
|
307
|
320
|
|
308
|
321
|
mraa_result_t
|
309
|
|
-NRF24l01::nrfCSOff () {
|
|
322
|
+NRF24L01::csOff () {
|
310
|
323
|
return mraa_gpio_write (m_csnPinCtx, HIGH);
|
311
|
324
|
}
|
312
|
325
|
|
313
|
326
|
void
|
314
|
|
-NRF24l01::nrfListenForChannel() {
|
315
|
|
- if(!nrfIsSending() && nrfDataReady()) {
|
316
|
|
- nrfGetData(m_rxBuffer);
|
317
|
|
- dataRecievedHandler(); /* let know that data arrived */
|
|
327
|
+NRF24L01::pollListener() {
|
|
328
|
+ if (dataReady()) {
|
|
329
|
+ getData (m_rxBuffer);
|
|
330
|
+ dataRecievedHandler (); /* let know that data arrived */
|
|
331
|
+ }
|
|
332
|
+}
|
|
333
|
+
|
|
334
|
+void
|
|
335
|
+NRF24L01::txFlushBuffer () {
|
|
336
|
+ sendCommand (FLUSH_TX);
|
|
337
|
+}
|
|
338
|
+
|
|
339
|
+void
|
|
340
|
+NRF24L01::setBeaconingMode () {
|
|
341
|
+ setRegister (CONFIG, 0x12); // on, no crc, int on RX/TX done
|
|
342
|
+ setRegister (EN_AA, 0x00); // no auto-acknowledge
|
|
343
|
+ setRegister (EN_RXADDR, 0x00); // no RX
|
|
344
|
+ setRegister (SETUP_AW, 0x02); // 5-byte address
|
|
345
|
+ setRegister (SETUP_RETR, 0x00); // no auto-retransmit
|
|
346
|
+ setRegister (RF_SETUP, 0x06); // 1MBps at 0dBm
|
|
347
|
+ setRegister (STATUS, 0x3E); // clear various flags
|
|
348
|
+ setRegister (DYNPD, 0x00); // no dynamic payloads
|
|
349
|
+ setRegister (FEATURE, 0x00); // no features
|
|
350
|
+ setRegister (RX_PW_P0, 32); // always RX 32 bytes
|
|
351
|
+ setRegister (EN_RXADDR, 0x01); // RX on pipe 0
|
|
352
|
+
|
|
353
|
+ uint8_t addr[4] = { swapbits(0x8E), swapbits(0x89), swapbits(0xBE), swapbits(0xD6)};
|
|
354
|
+ writeRegister (TX_ADDR, addr, 4);
|
|
355
|
+ writeRegister (RX_ADDR_P0, addr, 4);
|
|
356
|
+
|
|
357
|
+ uint8_t index = 0;
|
|
358
|
+ m_bleBuffer[index++] = 0x42; // PDU type, given address is random
|
|
359
|
+ m_bleBuffer[index++] = 0x1B; // 6+3+2+16 = 27 bytes of payload
|
|
360
|
+
|
|
361
|
+ m_bleBuffer[index++] = BLE_MAC_0;
|
|
362
|
+ m_bleBuffer[index++] = BLE_MAC_1;
|
|
363
|
+ m_bleBuffer[index++] = BLE_MAC_2;
|
|
364
|
+ m_bleBuffer[index++] = BLE_MAC_3;
|
|
365
|
+ m_bleBuffer[index++] = BLE_MAC_4;
|
|
366
|
+ m_bleBuffer[index++] = BLE_MAC_5;
|
|
367
|
+
|
|
368
|
+ m_bleBuffer[index++] = 2; // flags (LE-only, limited discovery mode)
|
|
369
|
+ m_bleBuffer[index++] = 0x01;
|
|
370
|
+ m_bleBuffer[index++] = 0x05;
|
|
371
|
+
|
|
372
|
+ m_bleBuffer[index++] = 17;
|
|
373
|
+ m_bleBuffer[index++] = 0x08;
|
|
374
|
+}
|
|
375
|
+
|
|
376
|
+void
|
|
377
|
+NRF24L01::sendBeaconingMsg (uint8_t * msg) {
|
|
378
|
+ const uint8_t chRf[] = {2, 26,80};
|
|
379
|
+ const uint8_t chLe[] = {37,38,39};
|
|
380
|
+ uint8_t index = BLE_PAYLOAD_OFFSET + 16;
|
|
381
|
+
|
|
382
|
+ memcpy (&m_bleBuffer[BLE_PAYLOAD_OFFSET], msg, 16);
|
|
383
|
+ m_bleBuffer[index++] = 0x55;
|
|
384
|
+ m_bleBuffer[index++] = 0x55;
|
|
385
|
+ m_bleBuffer[index++] = 0x55;
|
|
386
|
+
|
|
387
|
+ uint8_t channel = 0;
|
|
388
|
+ while (++channel != sizeof(chRf)) {
|
|
389
|
+ setRegister (RF_CH, chRf[channel]);
|
|
390
|
+ setRegister (STATUS, 0x6E); //clear flags
|
|
391
|
+
|
|
392
|
+ blePacketEncode (m_bleBuffer, index, chLe[channel]);
|
|
393
|
+
|
|
394
|
+ sendCommand (FLUSH_TX); // Clear RX Fifo
|
|
395
|
+ sendCommand (FLUSH_RX); // Clear TX Fifo
|
|
396
|
+
|
|
397
|
+ csOn ();
|
|
398
|
+ mraa_spi_write (m_spi, W_TX_PAYLOAD); // Write cmd to write payload
|
|
399
|
+ writeBytes (m_bleBuffer, NULL, 32); // Write payload
|
|
400
|
+ csOff ();
|
|
401
|
+
|
|
402
|
+ setRegister (CONFIG, 0x12); // tx on
|
|
403
|
+ ceHigh (); // Start transmission
|
|
404
|
+ usleep (10000);
|
|
405
|
+ ceLow ();
|
318
|
406
|
}
|
319
|
407
|
}
|
|
408
|
+
|
|
409
|
+/*
|
|
410
|
+ * ---------------
|
|
411
|
+ * PRIVATE SECTION
|
|
412
|
+ * ---------------
|
|
413
|
+ */
|
|
414
|
+
|
|
415
|
+void
|
|
416
|
+NRF24L01::writeBytes (uint8_t * dataout, uint8_t * datain, uint8_t len) {
|
|
417
|
+ for (uint8_t i = 0; i < len; i++) {
|
|
418
|
+ if (datain != NULL) {
|
|
419
|
+ datain[i] = mraa_spi_write (m_spi, dataout[i]);
|
|
420
|
+ } else {
|
|
421
|
+ mraa_spi_write (m_spi, dataout[i]);
|
|
422
|
+ }
|
|
423
|
+ }
|
|
424
|
+}
|
|
425
|
+
|
|
426
|
+void
|
|
427
|
+NRF24L01::setRegister (uint8_t reg, uint8_t value) {
|
|
428
|
+ csOn ();
|
|
429
|
+ mraa_spi_write (m_spi, W_REGISTER | (REGISTER_MASK & reg));
|
|
430
|
+ mraa_spi_write (m_spi, value);
|
|
431
|
+ csOff ();
|
|
432
|
+}
|
|
433
|
+
|
|
434
|
+uint8_t
|
|
435
|
+NRF24L01::getRegister (uint8_t reg) {
|
|
436
|
+ uint8_t data = 0;
|
|
437
|
+
|
|
438
|
+ csOn ();
|
|
439
|
+ mraa_spi_write (m_spi, R_REGISTER | (REGISTER_MASK & reg));
|
|
440
|
+ data = mraa_spi_write (m_spi, data);
|
|
441
|
+ csOff ();
|
|
442
|
+
|
|
443
|
+ return data;
|
|
444
|
+}
|
|
445
|
+
|
|
446
|
+void
|
|
447
|
+NRF24L01::readRegister (uint8_t reg, uint8_t * value, uint8_t len) {
|
|
448
|
+ csOn ();
|
|
449
|
+ mraa_spi_write (m_spi, R_REGISTER | (REGISTER_MASK & reg));
|
|
450
|
+ writeBytes (value, value, len);
|
|
451
|
+ csOff ();
|
|
452
|
+}
|
|
453
|
+
|
|
454
|
+void
|
|
455
|
+NRF24L01::writeRegister (uint8_t reg, uint8_t * value, uint8_t len) {
|
|
456
|
+ csOn ();
|
|
457
|
+ mraa_spi_write (m_spi, W_REGISTER | (REGISTER_MASK & reg));
|
|
458
|
+ writeBytes (value, NULL, len);
|
|
459
|
+ csOff ();
|
|
460
|
+}
|
|
461
|
+
|
|
462
|
+void
|
|
463
|
+NRF24L01::sendCommand (uint8_t cmd) {
|
|
464
|
+ csOn ();
|
|
465
|
+ mraa_spi_write (m_spi, cmd);
|
|
466
|
+ csOff ();
|
|
467
|
+}
|
|
468
|
+
|
|
469
|
+void
|
|
470
|
+NRF24L01::bleCrc (const uint8_t* data, uint8_t len, uint8_t* dst) {
|
|
471
|
+ uint8_t v, t, d;
|
|
472
|
+ while(len--) {
|
|
473
|
+ d = *data++;
|
|
474
|
+ for(v = 0; v < 8; v++, d >>= 1){
|
|
475
|
+ t = dst[0] >> 7;
|
|
476
|
+ dst[0] <<= 1;
|
|
477
|
+ if(dst[1] & 0x80) dst[0] |= 1;
|
|
478
|
+ dst[1] <<= 1;
|
|
479
|
+ if(dst[2] & 0x80) dst[1] |= 1;
|
|
480
|
+ dst[2] <<= 1;
|
|
481
|
+
|
|
482
|
+ if(t != (d & 1)) {
|
|
483
|
+ dst[2] ^= 0x5B;
|
|
484
|
+ dst[1] ^= 0x06;
|
|
485
|
+ }
|
|
486
|
+ }
|
|
487
|
+ }
|
|
488
|
+}
|
|
489
|
+
|
|
490
|
+void
|
|
491
|
+NRF24L01::bleWhiten (uint8_t* data, uint8_t len, uint8_t whitenCoeff) {
|
|
492
|
+ uint8_t m;
|
|
493
|
+ while(len--) {
|
|
494
|
+ for(m = 1; m; m <<= 1) {
|
|
495
|
+ if(whitenCoeff & 0x80){
|
|
496
|
+ whitenCoeff ^= 0x11;
|
|
497
|
+ (*data) ^= m;
|
|
498
|
+ }
|
|
499
|
+ whitenCoeff <<= 1;
|
|
500
|
+ }
|
|
501
|
+ data++;
|
|
502
|
+ }
|
|
503
|
+}
|
|
504
|
+
|
|
505
|
+void
|
|
506
|
+NRF24L01::blePacketEncode(uint8_t* packet, uint8_t len, uint8_t chan) {
|
|
507
|
+ //length is of packet, including crc. pre-populate crc in packet with initial crc value!
|
|
508
|
+ uint8_t i, dataLen = len - 3;
|
|
509
|
+
|
|
510
|
+ bleCrc(packet, dataLen, packet + dataLen);
|
|
511
|
+ for(i = 0; i < 3; i++, dataLen++) {
|
|
512
|
+ packet[dataLen] = swapbits(packet[dataLen]);
|
|
513
|
+ }
|
|
514
|
+
|
|
515
|
+ bleWhiten(packet, len, (swapbits(chan) | 2));
|
|
516
|
+ for(i = 0; i < len; i++) {
|
|
517
|
+ packet[i] = swapbits(packet[i]);
|
|
518
|
+ }
|
|
519
|
+}
|
|
520
|
+
|
|
521
|
+uint8_t
|
|
522
|
+NRF24L01::swapbits(uint8_t a) {
|
|
523
|
+ uint8_t v = 0;
|
|
524
|
+
|
|
525
|
+ if(a & 0x80) v |= 0x01;
|
|
526
|
+ if(a & 0x40) v |= 0x02;
|
|
527
|
+ if(a & 0x20) v |= 0x04;
|
|
528
|
+ if(a & 0x10) v |= 0x08;
|
|
529
|
+ if(a & 0x08) v |= 0x10;
|
|
530
|
+ if(a & 0x04) v |= 0x20;
|
|
531
|
+ if(a & 0x02) v |= 0x40;
|
|
532
|
+ if(a & 0x01) v |= 0x80;
|
|
533
|
+
|
|
534
|
+ return v;
|
|
535
|
+}
|