1 /* 2 * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com> 3 * Copyright (c) 2014 Intel Corporation. 4 * BLE Beaconing based on http://dmitry.gr/index.php?r=05.Projects&proj=11.%20Bluetooth%20LE%20fakery 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 #pragma once 26 27 #include <string> 28 #include <mraa/aio.hpp> 29 #include <mraa/common.hpp> 30 31 #include <mraa/gpio.hpp> 32 33 #include <mraa/spi.hpp> 34 #include <cstring> 35 36 #if defined(SWIGJAVA) || defined(JAVACALLBACK) 37 #include "Callback.h" 38 #endif 39 40 /* Memory Map */ 41 #define CONFIG 0x00 42 #define EN_AA 0x01 43 #define EN_RXADDR 0x02 44 #define SETUP_AW 0x03 45 #define SETUP_RETR 0x04 46 #define RF_CH 0x05 47 #define RF_SETUP 0x06 48 #define STATUS 0x07 49 #define OBSERVE_TX 0x08 50 #define CD 0x09 51 #define RX_ADDR_P0 0x0A 52 #define RX_ADDR_P1 0x0B 53 #define RX_ADDR_P2 0x0C 54 #define RX_ADDR_P3 0x0D 55 #define RX_ADDR_P4 0x0E 56 #define RX_ADDR_P5 0x0F 57 #define TX_ADDR 0x10 58 #define RX_PW_P0 0x11 59 #define RX_PW_P1 0x12 60 #define RX_PW_P2 0x13 61 #define RX_PW_P3 0x14 62 #define RX_PW_P4 0x15 63 #define RX_PW_P5 0x16 64 #define FIFO_STATUS 0x17 65 #define DYNPD 0x1C 66 #define FEATURE 0x1D 67 68 /* Bit Mnemonics */ 69 #define MASK_RX_DR 6 70 #define MASK_TX_DS 5 71 #define MASK_MAX_RT 4 72 #define EN_CRC 3 73 #define CRCO 2 74 #define PWR_UP 1 75 #define PRIM_RX 0 76 #define ENAA_P5 5 77 #define ENAA_P4 4 78 #define ENAA_P3 3 79 #define ENAA_P2 2 80 #define ENAA_P1 1 81 #define ENAA_P0 0 82 #define ERX_P5 5 83 #define ERX_P4 4 84 #define ERX_P3 3 85 #define ERX_P2 2 86 #define ERX_P1 1 87 #define ERX_P0 0 88 #define AW 0 89 #define ARD 4 90 #define ARC 0 91 #define PLL_LOCK 4 92 #define RF_DR 3 93 #define RF_PWR 1 94 #define LNA_HCURR 0 95 #define RX_DR 6 96 #define TX_DS 5 97 #define MAX_RT 4 98 #define RX_P_NO 1 99 #define TX_FULL 0 100 #define PLOS_CNT 4 101 #define ARC_CNT 0 102 #define TX_REUSE 6 103 #define FIFO_FULL 5 104 #define TX_EMPTY 4 105 #define RX_FULL 1 106 #define RX_EMPTY 0 107 108 /* Instruction Mnemonics */ 109 #define R_REGISTER 0x00 110 #define W_REGISTER 0x20 111 #define REGISTER_MASK 0x1F 112 #define R_RX_PAYLOAD 0x61 113 #define W_TX_PAYLOAD 0xA0 114 #define FLUSH_TX 0xE1 115 #define FLUSH_RX 0xE2 116 #define REUSE_TX_PL 0xE3 117 #define NOP 0xFF 118 119 #define RF_DR_LOW 5 120 #define RF_DR_HIGH 3 121 #define RF_PWR_LOW 1 122 #define RF_PWR_HIGH 2 123 124 /* Nrf24l settings */ 125 #define ADDR_LEN 5 126 #define _CONFIG ((1<<EN_CRC) | (0<<CRCO) ) 127 128 #define MAX_BUFFER 32 129 130 #define HIGH 1 131 #define LOW 0 132 133 /* BLE beaconing */ 134 #define BLE_MAC_0 0xEF 135 #define BLE_MAC_1 0xFF 136 #define BLE_MAC_2 0xC0 137 #define BLE_MAC_3 0xAA 138 #define BLE_MAC_4 0x18 139 #define BLE_MAC_5 0x00 140 141 #define BLE_PAYLOAD_OFFSET 13 142 143 namespace upm { 144 145 #if defined(SWIGJAVA) || defined(JAVACALLBACK) 146 typedef void (* funcPtrVoidVoid) (Callback *); 147 #else 148 typedef void (* funcPtrVoidVoid) (); 149 #endif 150 151 typedef enum { 152 NRF_250KBPS = 0, 153 NRF_1MBPS = 1, 154 NRF_2MBPS = 2, 155 } speed_rate_t; 156 157 typedef enum { 158 NRF_0DBM = 0, 159 NRF_6DBM = 1, 160 NRF_12DBM = 2, 161 NRF_18DBM = 3, 162 } power_t; 163 164 /** 165 * @brief NRF24L01 Transceiver library 166 * @defgroup nrf24l01 libupm-nrf24l01 167 * @ingroup seeed sparkfun spi wifi 168 */ 169 /** 170 * @library nrf24l01 171 * @sensor nrf24l01 172 * @comname NRF24L01 Transceiver 173 * @type wifi 174 * @man seeed sparkfun 175 * @web http://www.seeedstudio.com/depot/nRF24L01Module-p-1394.html 176 * @con spi 177 * 178 * id 179 * @brief API for the NRF24L01 Transceiver Module 180 * 181 * This module defines the NRF24L01 interface for libnrf24l01 182 * 183 * @image html nrf24l01.jpg 184 * @snippet nrf24l01-receiver.cxx Interesting 185 * @snippet nrf24l01-transmitter.cxx Interesting 186 * @snippet nrf24l01-broadcast.cxx Interesting 187 */ 188 class NRF24L01 { 189 public: 190 /** 191 * Instantiates an NRF24l01 object 192 * 193 * @param cs Chip select pin 194 */ 195 NRF24L01 (uint8_t cs, uint8_t ce); 196 197 /** 198 * Returns the name of the component 199 */ name()200 std::string name() 201 { 202 return m_name; 203 } 204 205 /** 206 * Initializes needed GPIO pins and SPI 207 * 208 * @param chipSelect Sets up the chip select pin 209 * @param chipEnable Sets up the chip enable pin 210 */ 211 void init (uint8_t chipSelect, uint8_t chipEnable); 212 213 /** 214 * Configures the NRF24L01 transceiver 215 */ 216 void configure (); 217 218 /** 219 * Sends the buffer data 220 * 221 * @param *value Pointer to the buffer 222 */ 223 void send (uint8_t * value); 224 225 /** 226 * Sends the data located in an inner bufer; the user must fill the 227 * m_txBuffer buffer 228 */ 229 void send (); 230 231 /** 232 * Sets a receiving address of the device 233 * 234 * @param addr 5-byte address 235 */ 236 void setSourceAddress (uint8_t * addr); 237 238 /** 239 * Sets a recipient address. The nrfSend method sends the data buffer 240 * to this address 241 * 242 * @param addr 5-byte address 243 */ 244 void setDestinationAddress (uint8_t * addr); 245 246 /** 247 * Sets a broadcasting address 248 * 249 * @param addr 5-byte address 250 */ 251 void setBroadcastAddress (uint8_t * addr); 252 253 /** 254 * Sets the payload size 255 * 256 * @param load Size of the payload (MAX 32) 257 */ 258 void setPayload (uint8_t load); 259 260 #if defined(SWIGJAVA) || defined(JAVACALLBACK) 261 /** 262 * Sets the handler to be called when data has been 263 * received 264 * @param call_obj Object used for callback - Java 265 */ 266 void setDataReceivedHandler (Callback *call_obj); 267 #else 268 /** 269 * Sets the handler to be called when data has been 270 * received 271 * @param handler Handler used for callback 272 */ 273 void setDataReceivedHandler (funcPtrVoidVoid handler); 274 #endif 275 /** 276 * Checks if the data has arrived 277 */ 278 bool dataReady (); 279 280 /** 281 * Checks if the transceiver is in the sending mode 282 */ 283 bool dataSending (); 284 285 /** 286 * Sinks all the arrived data into a provided buffer 287 * 288 * @param load Size of the payload (MAX 32) 289 */ 290 void getData (uint8_t * data); 291 292 /** 293 * Checks the transceiver state 294 */ 295 uint8_t getStatus (); 296 297 /** 298 * Checks if the receive stack is empty 299 */ 300 bool rxFifoEmpty (); 301 302 /** 303 * Powers the receiver up 304 */ 305 void rxPowerUp (); 306 307 /** 308 * Flushes the receive stack 309 */ 310 void rxFlushBuffer (); 311 312 /** 313 * Powers the transmitter up 314 */ 315 void txPowerUp (); 316 317 /** 318 * Powers everything down 319 */ 320 void powerDown (); 321 322 void setChannel (uint8_t channel); 323 324 void setPower (power_t power); 325 326 uint8_t setSpeedRate (speed_rate_t rate); 327 328 /** 329 * Flushes the transmit stack 330 */ 331 void txFlushBuffer (); 332 333 /** 334 * Pulling the method listening for the arrived data, 335 * dataRecievedHandler is triggered if data arrives 336 */ 337 void pollListener (); 338 339 /** 340 * Sets the chip enable pin to HIGH 341 */ 342 mraa::Result ceHigh (); 343 344 /** 345 * Sets the chip enable pin to LOW 346 */ 347 mraa::Result ceLow (); 348 349 /** 350 * Sets the chip select pin to LOW 351 */ 352 mraa::Result csOn (); 353 354 /** 355 * Sets the chip select pin to HIGH 356 */ 357 mraa::Result csOff (); 358 359 /** 360 * Configures the NRF24L01 transceiver to behave as a BLE 361 * (Bluetooth Low Energy) beaconing devcie. 362 */ 363 void setBeaconingMode (); 364 365 /** 366 * Beacons the provided message to BLE scanners. 367 * 368 * @param msg Beacons the provided message (max length is 16 bytes) 369 */ 370 void sendBeaconingMsg (uint8_t * msg); 371 372 uint8_t m_rxBuffer[MAX_BUFFER]; /**< Receive buffer */ 373 uint8_t m_txBuffer[MAX_BUFFER]; /**< Transmit buffer */ 374 uint8_t m_bleBuffer [32]; /**< BLE buffer */ 375 376 private: 377 #if defined(SWIGJAVA) || defined(JAVACALLBACK) 378 /**< Callback object to use for setting the handler from Java */ 379 Callback *callback_obj; 380 #endif 381 funcPtrVoidVoid dataReceivedHandler; /**< Data arrived handler */ 382 383 /** 384 * Writes bytes to an SPI device 385 */ 386 void writeBytes (uint8_t * dataout, uint8_t * datain, uint8_t len); 387 /** 388 * Sets the register value on an SPI device [one byte] 389 */ 390 void setRegister (uint8_t reg, uint8_t value); 391 /** 392 * Gets the register value from an SPI device [one byte] 393 */ 394 uint8_t getRegister (uint8_t reg); 395 /** 396 * Reads an array of bytes from the given starting position in NRF24L01 registers 397 */ 398 void readRegister (uint8_t reg, uint8_t * value, uint8_t len); 399 /** 400 * Writes an array of bytes into NRF24L01 registers 401 */ 402 void writeRegister (uint8_t reg, uint8_t * value, uint8_t len); 403 /** 404 * Sends a command to NRF24L01 405 */ 406 void sendCommand (uint8_t cmd); 407 408 void bleCrc (const uint8_t* data, uint8_t len, uint8_t* dst); 409 410 void bleWhiten (uint8_t* data, uint8_t len, uint8_t whitenCoeff); 411 412 void blePacketEncode(uint8_t* packet, uint8_t len, uint8_t chan); 413 414 uint8_t swapbits (uint8_t a); 415 416 mraa::Spi m_spi; 417 uint8_t m_ce; 418 uint8_t m_csn; 419 uint8_t m_channel; 420 uint8_t m_power; 421 uint8_t m_ptx; 422 uint8_t m_payload; 423 uint8_t m_localAddress[5]; 424 425 mraa::Gpio m_csnPinCtx; 426 mraa::Gpio m_cePinCtx; 427 428 std::string m_name; 429 }; 430 431 } 432