├── .gitignore ├── printf.h ├── logitech-mouse.h ├── README.md ├── nRF24L01.h ├── RF24_config.h ├── logitech-mouse.cpp ├── RF24.cpp └── RF24.h /.gitignore: -------------------------------------------------------------------------------- 1 | test-logi-lib.ino -------------------------------------------------------------------------------- /printf.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 J. Coliz 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | version 2 as published by the Free Software Foundation. 7 | */ 8 | /* Galileo support from spaniakos */ 9 | 10 | /** 11 | * @file printf.h 12 | * 13 | * Setup necessary to direct stdout to the Arduino Serial library, which 14 | * enables 'printf' 15 | */ 16 | 17 | #ifndef __PRINTF_H__ 18 | #define __PRINTF_H__ 19 | 20 | #if defined (ARDUINO) && !defined (__arm__) && !defined(__ARDUINO_X86__) 21 | 22 | int serial_putc( char c, FILE * ) 23 | { 24 | Serial.write( c ); 25 | 26 | return c; 27 | } 28 | 29 | void printf_begin(void) 30 | { 31 | fdevopen( &serial_putc, 0 ); 32 | } 33 | 34 | #elif defined (__arm__) 35 | 36 | void printf_begin(void){} 37 | 38 | #elif defined(__ARDUINO_X86__) 39 | int serial_putc( char c, FILE * ) 40 | { 41 | Serial.write( c ); 42 | 43 | return c; 44 | } 45 | 46 | void printf_begin(void) 47 | { 48 | //JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port) 49 | stdout = freopen("/dev/ttyGS0","w",stdout); 50 | delay(500); 51 | printf("redirecting to Serial..."); 52 | 53 | //JESUS ----------------------------------------------------------- 54 | } 55 | #else 56 | #error This example is only for use on Arduino. 57 | #endif // ARDUINO 58 | 59 | #endif // __PRINTF_H__ 60 | -------------------------------------------------------------------------------- /logitech-mouse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2017 Ronan Gaillard 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | version 2 as published by the Free Software Foundation. 7 | */ 8 | 9 | #ifndef LOGITECH_MOUSE 10 | #define LOGITECH_MOUSE 11 | 12 | #include "nRF24L01.h" 13 | #include "RF24.h" 14 | 15 | #define DEFAULT_CE_PIN 8 16 | #define DEFAULT_CS_PIN 7 17 | #define CHANNEL 5 18 | #define PAYLOAD_SIZE 22 19 | #define PAIRING_MAC_ADDRESS 0xBB0ADCA575LL 20 | #define EEPROM_SUPPORT 21 | #define MAC_ADDRESS_EEPROM_ADDRESS 0 22 | 23 | #ifdef EEPROM_SUPPORT 24 | #include 25 | #endif 26 | 27 | class logiMouse 28 | { 29 | private : 30 | 31 | RF24 radio; 32 | 33 | void setChecksum(uint8_t *payload, uint8_t len); 34 | bool pairingStep(uint8_t *pairing_packet, uint8_t *pairing_packet_small, uint8_t *ack_payload, uint8_t timeout); 35 | void setAddress(uint8_t *address); 36 | void setAddress(uint64_t address); 37 | 38 | /* Pre-defined pairing packets */ 39 | uint8_t pairing_packet_1[22] = {0x15, 0x5F, 0x01, 0x84, 0x5E, 0x3A, 0xA2, 0x57, 0x08, 0x10, 0x25, 0x04, 0x00, 0x01, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xEC}; 40 | uint8_t pairing_packet_1_bis[5] = {0x15, 0x40, 0x01, 0x84, 0x26}; 41 | uint8_t pairing_packet_2[22] = {0x00, 0x5F, 0x02, 0x00, 0x00, 0x00, 0x00, 0x58, 0x8A, 0x51, 0xEA, 0x01, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; 42 | uint8_t pairing_packet_2_bis[5] = {0x00, 0x40, 0x02, 0x01, 0xbd}; 43 | uint8_t pairing_packet_3[22] = {0x00, 0x5F, 0x03, 0x01, 0x00, 0x04, 0x4D, 0x35, 0x31, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB6}; 44 | uint8_t pairing_packet_3_bis[5] = {0x00, 0x5F, 0x03, 0x01, 0x0f}; 45 | uint8_t pairing_packet_4[10] = {0x00, 0x0F, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA}; 46 | /* Enf of pre-defined pairing packets */ 47 | 48 | public : 49 | 50 | logiMouse(uint8_t _cepin, uint8_t _cspin); 51 | logiMouse(); 52 | 53 | bool begin(); 54 | 55 | bool pair(); 56 | bool pair(uint8_t timeout); 57 | bool reconnect(); 58 | 59 | void move(uint16_t x_move, uint16_t y_move); 60 | void move(uint16_t x_move, uint16_t y_move, bool leftClick, bool rightClick); 61 | void move(uint16_t x_move, uint16_t y_move, uint8_t scroll_v, uint8_t scroll_h); 62 | void move(uint16_t x_move, uint16_t y_move, uint8_t scroll_v, uint8_t scroll_h, bool leftClick, bool rightClick); 63 | void click(bool leftClick, bool rightClick); 64 | void scroll(uint8_t scroll_v, uint8_t scroll_h); 65 | void scroll(uint8_t scroll_v); 66 | }; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # logitech-mouse 2 | Use an arduino as a logitech wireless 🐭 3 | 4 | We managed to make an Arduino act like a Logitech wireless mouse using a NRF24. This work is based on our retroengineering work done in December 2016 and January 2017 during our school project @Supelec. 5 | 6 | ## Example 7 | 8 | This code makes the mouse move in circle on the screen. 9 | 10 | ```cpp 11 | #include "logitech-mouse.h" 12 | 13 | logiMouse myMouse; 14 | 15 | float mouseSpeed = 10.0f; 16 | float degreesToRadians = 2.0f*3.14f/360.0f; 17 | 18 | void setup() { 19 | Serial.begin(115200); 20 | 21 | Serial.println("Starting"); 22 | 23 | myMouse.begin(); 24 | 25 | Serial.println("Trying to reconnect"); 26 | 27 | if(myMouse.reconnect()) 28 | Serial.println("Reconnected using previous configuration !"); 29 | else 30 | { 31 | Serial.println("Unable to reconnect to dongle... Pairing with any dongle..."); 32 | myMouse.pair(); 33 | } 34 | 35 | Serial.println("Ready :)"); 36 | } 37 | 38 | void loop() { 39 | int x, y = 0; 40 | 41 | for(x = 0; x < 360; x+=5) { 42 | myMouse.move( (uint16_t)(mouseSpeed * cos( ((float)x) * degreesToRadians ) ), 43 | (uint16_t)(mouseSpeed * sin( ((float)x) * degreesToRadians ) )); 44 | 45 | delay(10); 46 | } 47 | } 48 | ``` 49 | 50 | ## Quick doc 51 | 52 | The class we created is called `logiMouse`. 53 | 54 | ### Methods 55 | 56 | #### General methods 57 | 58 | - `bool begin()` : inits NRF24 module for wireless communication 59 | - `bool pair()` : pairs Arduino with Logitech dongle (don't forget to put the dongle into pairing mode using the unifying desktop app), returns false if pairing failed 60 | - `bool pair(uint8_t)` : pairs with timeout (exits if pairing takes too much time) 61 | - `bool reconnect()` : reconnects to previously connected dongle (exits if dongle is not found), returns true if success 62 | 63 | #### Move methods 64 | 65 | - `void move(uint16_t x_move, uint16_t y_move)` : moves the mouse on the screen according to specified velocity (x,y) 66 | - `void move(uint16_t x_move, uint16_t y_move, bool leftClick, bool rightClick)` : moves the mouse on the screen according to specified velocity (x,y), and click according to booleans 67 | - `void move(uint16_t x_move, uint16_t y_move, uint8_t scroll_v, uint8_t scroll_h)` : moves and scrolls (see scrolls methods for more info) 68 | - `void move(uint16_t x_move, uint16_t y_move, uint8_t scroll_v, uint8_t scroll_h, bool leftClick, bool rightClick)` : moves, scrolls and clicks (see related methods for more info) 69 | 70 | #### Scroll methods 71 | 72 | - `void scroll(uint8_t scroll_v, uint8_t scroll_h)` : scrolls horizontally and vertically (_scroll_v_ and _scroll_h_ can be negative) 73 | - `void scroll(uint8_t scroll_v)` : scrolls vertically (_scroll_v_ can be negative) 74 | 75 | #### Click methods 76 | 77 | - `void click(bool leftClick, bool rightClick)` : clicks according to booleans 78 | 79 | 80 | ## Copyright 81 | 82 | The NRF24 lib included in this repo was written by Coliz , all rights reserved to him. 83 | 84 | We are the author of both files : `logitech-mouse.cpp` and `logitech-mouse.h` 85 | 86 | -------------------------------------------------------------------------------- /nRF24L01.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2007 Stefan Engelke 3 | Portions Copyright (C) 2011 Greg Copeland 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, copy, 9 | modify, merge, publish, distribute, sublicense, and/or sell copies 10 | of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* Memory Map */ 27 | #define NRF_CONFIG 0x00 28 | #define EN_AA 0x01 29 | #define EN_RXADDR 0x02 30 | #define SETUP_AW 0x03 31 | #define SETUP_RETR 0x04 32 | #define RF_CH 0x05 33 | #define RF_SETUP 0x06 34 | #define NRF_STATUS 0x07 35 | #define OBSERVE_TX 0x08 36 | #define CD 0x09 37 | #define RX_ADDR_P0 0x0A 38 | #define RX_ADDR_P1 0x0B 39 | #define RX_ADDR_P2 0x0C 40 | #define RX_ADDR_P3 0x0D 41 | #define RX_ADDR_P4 0x0E 42 | #define RX_ADDR_P5 0x0F 43 | #define TX_ADDR 0x10 44 | #define RX_PW_P0 0x11 45 | #define RX_PW_P1 0x12 46 | #define RX_PW_P2 0x13 47 | #define RX_PW_P3 0x14 48 | #define RX_PW_P4 0x15 49 | #define RX_PW_P5 0x16 50 | #define FIFO_STATUS 0x17 51 | #define DYNPD 0x1C 52 | #define FEATURE 0x1D 53 | 54 | /* Bit Mnemonics */ 55 | #define MASK_RX_DR 6 56 | #define MASK_TX_DS 5 57 | #define MASK_MAX_RT 4 58 | #define EN_CRC 3 59 | #define CRCO 2 60 | #define PWR_UP 1 61 | #define PRIM_RX 0 62 | #define ENAA_P5 5 63 | #define ENAA_P4 4 64 | #define ENAA_P3 3 65 | #define ENAA_P2 2 66 | #define ENAA_P1 1 67 | #define ENAA_P0 0 68 | #define ERX_P5 5 69 | #define ERX_P4 4 70 | #define ERX_P3 3 71 | #define ERX_P2 2 72 | #define ERX_P1 1 73 | #define ERX_P0 0 74 | #define AW 0 75 | #define ARD 4 76 | #define ARC 0 77 | #define PLL_LOCK 4 78 | #define RF_DR 3 79 | #define RF_PWR 6 80 | #define RX_DR 6 81 | #define TX_DS 5 82 | #define MAX_RT 4 83 | #define RX_P_NO 1 84 | #define TX_FULL 0 85 | #define PLOS_CNT 4 86 | #define ARC_CNT 0 87 | #define TX_REUSE 6 88 | #define FIFO_FULL 5 89 | #define TX_EMPTY 4 90 | #define RX_FULL 1 91 | #define RX_EMPTY 0 92 | #define DPL_P5 5 93 | #define DPL_P4 4 94 | #define DPL_P3 3 95 | #define DPL_P2 2 96 | #define DPL_P1 1 97 | #define DPL_P0 0 98 | #define EN_DPL 2 99 | #define EN_ACK_PAY 1 100 | #define EN_DYN_ACK 0 101 | 102 | /* Instruction Mnemonics */ 103 | #define R_REGISTER 0x00 104 | #define W_REGISTER 0x20 105 | #define REGISTER_MASK 0x1F 106 | #define ACTIVATE 0x50 107 | #define R_RX_PL_WID 0x60 108 | #define R_RX_PAYLOAD 0x61 109 | #define W_TX_PAYLOAD 0xA0 110 | #define W_ACK_PAYLOAD 0xA8 111 | #define FLUSH_TX 0xE1 112 | #define FLUSH_RX 0xE2 113 | #define REUSE_TX_PL 0xE3 114 | #define NOP 0xFF 115 | 116 | /* Non-P omissions */ 117 | #define LNA_HCURR 0 118 | 119 | /* P model memory Map */ 120 | #define RPD 0x09 121 | #define W_TX_PAYLOAD_NO_ACK 0xB0 122 | 123 | /* P model bit Mnemonics */ 124 | #define RF_DR_LOW 5 125 | #define RF_DR_HIGH 3 126 | #define RF_PWR_LOW 1 127 | #define RF_PWR_HIGH 2 128 | -------------------------------------------------------------------------------- /RF24_config.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Copyright (C) 2011 J. Coliz 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | version 2 as published by the Free Software Foundation. 8 | */ 9 | 10 | /* spaniakos 11 | Added __ARDUINO_X86__ support 12 | */ 13 | 14 | #ifndef __RF24_CONFIG_H__ 15 | #define __RF24_CONFIG_H__ 16 | 17 | /*** USER DEFINES: ***/ 18 | //#define FAILURE_HANDLING 19 | //#define SERIAL_DEBUG 20 | //#define MINIMAL 21 | //#define SPI_UART // Requires library from https://github.com/TMRh20/Sketches/tree/master/SPI_UART 22 | //#define SOFTSPI // Requires library from https://github.com/greiman/DigitalIO 23 | 24 | /**********************/ 25 | #define rf24_max(a,b) (a>b?a:b) 26 | #define rf24_min(a,b) (a 64 | 65 | // RF modules support 10 Mhz SPI bus speed 66 | const uint32_t RF24_SPI_SPEED = 10000000; 67 | 68 | #if defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__) 69 | #if defined SPI_UART 70 | #include 71 | #define _SPI uspi 72 | #elif defined SOFTSPI 73 | // change these pins to your liking 74 | // 75 | const uint8_t SOFT_SPI_MISO_PIN = 16; 76 | const uint8_t SOFT_SPI_MOSI_PIN = 15; 77 | const uint8_t SOFT_SPI_SCK_PIN = 14; 78 | const uint8_t SPI_MODE = 0; 79 | #define _SPI spi 80 | 81 | #else 82 | #include 83 | #define _SPI SPI 84 | #endif 85 | #else 86 | // Define _BV for non-Arduino platforms and for Arduino DUE 87 | #include 88 | #include 89 | #include 90 | 91 | 92 | #if defined(__arm__) || defined (__ARDUINO_X86__) 93 | #if defined (__arm__) && defined (SPI_UART) 94 | #include 95 | #define _SPI uspi 96 | #else 97 | #include 98 | #define _SPI SPI 99 | #endif 100 | #elif !defined(__arm__) && !defined (__ARDUINO_X86__) 101 | extern HardwareSPI SPI; 102 | #endif 103 | 104 | #define _BV(x) (1<<(x)) 105 | 106 | #endif 107 | 108 | #ifdef SERIAL_DEBUG 109 | #define IF_SERIAL_DEBUG(x) ({x;}) 110 | #else 111 | #define IF_SERIAL_DEBUG(x) 112 | #if defined(RF24_TINY) 113 | #define printf_P(...) 114 | #endif 115 | #endif 116 | 117 | #if defined (__ARDUINO_X86__) 118 | #define printf_P printf 119 | #define _BV(bit) (1<<(bit)) 120 | #endif 121 | 122 | // Progmem is Arduino-specific 123 | // Arduino DUE is arm and does not include avr/pgmspace 124 | #if defined (ARDUINO_ARCH_ESP8266) 125 | 126 | #define PSTR(x) (x) 127 | #define printf Serial.printf 128 | #define sprintf(...) os_sprintf( __VA_ARGS__ ) 129 | #define printf_P printf 130 | #define strlen_P strlen 131 | #define PROGMEM 132 | #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) 133 | #define pgm_read_word(p) (*(p)) 134 | #define PRIPSTR "%s" 135 | 136 | #elif defined(ARDUINO) && ! defined(__arm__) && !defined (__ARDUINO_X86__) || defined(XMEGA) 137 | #include 138 | #define PRIPSTR "%S" 139 | #else 140 | #if ! defined(ARDUINO) // This doesn't work on Arduino DUE 141 | typedef char const char; 142 | #else // Fill in pgm_read_byte that is used, but missing from DUE 143 | #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) 144 | #endif 145 | 146 | 147 | typedef uint16_t prog_uint16_t; 148 | #define PSTR(x) (x) 149 | #define printf_P printf 150 | #define strlen_P strlen 151 | #define PROGMEM 152 | #define pgm_read_word(p) (*(p)) 153 | 154 | #define PRIPSTR "%s" 155 | 156 | #endif 157 | 158 | #endif 159 | 160 | 161 | 162 | #endif // __RF24_CONFIG_H__ 163 | 164 | -------------------------------------------------------------------------------- /logitech-mouse.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2017 Ronan Gaillard 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | version 2 as published by the Free Software Foundation. 7 | */ 8 | 9 | #include "logitech-mouse.h" 10 | 11 | 12 | #ifdef EEPROM_SUPPORT 13 | #include 14 | #endif 15 | 16 | logiMouse::logiMouse(uint8_t _cepin, uint8_t _cspin) : radio(_cepin, _cspin) 17 | { 18 | 19 | } 20 | 21 | logiMouse::logiMouse() : logiMouse(DEFAULT_CE_PIN, DEFAULT_CS_PIN) 22 | { 23 | 24 | } 25 | 26 | void logiMouse::setAddress(uint64_t address) 27 | { 28 | setAddress((uint8_t *)&address); 29 | } 30 | 31 | void logiMouse::setAddress(uint8_t *address) 32 | { 33 | uint8_t address_dongle[5]; 34 | 35 | memcpy(address_dongle, address, 4); 36 | address_dongle[0] = 0; 37 | 38 | radio.stopListening(); 39 | radio.openReadingPipe(2, address_dongle); 40 | radio.openReadingPipe(1, address); 41 | radio.openWritingPipe(address); 42 | } 43 | 44 | bool logiMouse::begin() 45 | { 46 | uint8_t init_status = radio.begin(); 47 | 48 | if (init_status == 0 || init_status == 0xff) 49 | { 50 | return false; 51 | } 52 | 53 | radio.stopListening(); 54 | radio.setAutoAck(1); 55 | radio.setRetries(3, 1); 56 | radio.setPayloadSize(PAYLOAD_SIZE); 57 | radio.enableDynamicPayloads(); 58 | radio.enableAckPayload(); 59 | radio.enableDynamicAck(); 60 | radio.openWritingPipe(PAIRING_MAC_ADDRESS); 61 | radio.openReadingPipe(1, PAIRING_MAC_ADDRESS); 62 | radio.setChannel(CHANNEL); 63 | radio.setDataRate(RF24_2MBPS); 64 | radio.stopListening(); 65 | 66 | return true; 67 | } 68 | 69 | void logiMouse::setChecksum(uint8_t *payload, uint8_t len) 70 | { 71 | uint8_t checksum = 0; 72 | 73 | for (uint8_t i = 0; i < (len - 1); i++) 74 | checksum += payload[i]; 75 | 76 | payload[len - 1] = -checksum; 77 | } 78 | 79 | bool logiMouse::pairingStep(uint8_t *pairing_packet, uint8_t *pairing_packet_small, uint8_t *ack_payload, uint8_t timeout) 80 | { 81 | bool keep_going = true; 82 | uint8_t loop_counter = timeout; 83 | 84 | while (keep_going && (timeout == 0 || loop_counter > 0)) 85 | { 86 | if (radio.available()) 87 | break; 88 | 89 | while (!radio.write(pairing_packet, 22, 0) && (timeout == 0 || loop_counter > 0)) 90 | loop_counter--; 91 | 92 | if (radio.available()) 93 | break; 94 | 95 | while (keep_going && (timeout == 0 || loop_counter > 0)) 96 | { 97 | if (radio.write(pairing_packet_small, 5, 0)) 98 | if (radio.available()) 99 | keep_going = false; 100 | 101 | loop_counter--; 102 | } 103 | } 104 | 105 | radio.read(ack_payload, 22); 106 | 107 | return (timeout == 0 || loop_counter > 0); 108 | } 109 | 110 | bool logiMouse::pair() 111 | { 112 | return pair(0); 113 | } 114 | 115 | bool logiMouse::pair(uint8_t timeout) 116 | { 117 | uint8_t buffer[22]; 118 | uint8_t loop_counter = timeout; 119 | 120 | /* Pairing step 1 */ 121 | if(!pairingStep(pairing_packet_1, pairing_packet_1_bis, buffer, timeout)) 122 | return false; 123 | 124 | /* Generate dongle and device address */ 125 | uint8_t new_add[5]; 126 | 127 | for (int i = 0; i < 5; i++) 128 | new_add[i] = buffer[3 + (4 - i)]; 129 | 130 | setAddress(new_add); 131 | 132 | /* Pairing step 2 */ 133 | if(!pairingStep(pairing_packet_2, pairing_packet_2_bis, buffer, timeout)) 134 | return false; 135 | 136 | /* Pairing step 3 */ 137 | if(!pairingStep(pairing_packet_3, pairing_packet_3_bis, buffer, timeout)) 138 | return false; 139 | 140 | /* Pairing step 4 */ 141 | while (!radio.write(pairing_packet_4, 22, 0) && (timeout == 0 || loop_counter > 0) ) 142 | loop_counter--; 143 | 144 | if(!(timeout == 0 || loop_counter > 0)) 145 | return false; 146 | 147 | #ifdef EEPROM_SUPPORT 148 | /* Save address to eeprom */ 149 | for (int i = 0; i < 5; i++) 150 | { 151 | EEPROM.write(MAC_ADDRESS_EEPROM_ADDRESS + i, new_add[i]); 152 | } 153 | #endif 154 | } 155 | 156 | bool logiMouse::reconnect() 157 | { 158 | #ifndef EEPROM_SUPPORT 159 | #warning "EEPROM support is not enabled" 160 | return false; 161 | #else 162 | uint8_t new_add[5]; 163 | 164 | for (int i = 0; i < 5; i++) 165 | new_add[i] = EEPROM.read(MAC_ADDRESS_EEPROM_ADDRESS + i); 166 | 167 | setAddress(new_add); 168 | 169 | if(pair(255)) 170 | return true; 171 | else { 172 | setAddress(PAIRING_MAC_ADDRESS); 173 | return false; 174 | } 175 | 176 | #endif 177 | } 178 | 179 | void logiMouse::move(uint16_t x_move, uint16_t y_move) 180 | { 181 | move(x_move, y_move, false, false); 182 | } 183 | 184 | void logiMouse::move(uint16_t x_move, uint16_t y_move, bool leftClick, bool rightClick) 185 | { 186 | move(x_move, y_move, 0, 0, false, false); 187 | } 188 | 189 | void logiMouse::move(uint16_t x_move, uint16_t y_move, uint8_t scroll_v, uint8_t scroll_h) 190 | { 191 | move(x_move, y_move, scroll_v, scroll_h, false, false); 192 | } 193 | 194 | void logiMouse::move(uint16_t x_move, uint16_t y_move, uint8_t scroll_v, uint8_t scroll_h, bool leftClick, bool rightClick) 195 | { 196 | uint8_t mouse_payload[] = {0x00, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 197 | 198 | uint32_t cursor_velocity; 199 | 200 | cursor_velocity = ((uint32_t)y_move & 0xFFF) << 12 | (x_move & 0xFFF); 201 | 202 | memcpy(mouse_payload + 4, &cursor_velocity, 3); 203 | 204 | if(leftClick) 205 | mouse_payload[2] = 1; 206 | 207 | if(rightClick) 208 | mouse_payload[2] |= 1 << 1; 209 | 210 | mouse_payload[7] = scroll_v; 211 | mouse_payload[8] = scroll_h; 212 | 213 | setChecksum(mouse_payload, 10); 214 | while (!radio.write(mouse_payload, 10, 0)) 215 | { 216 | } 217 | 218 | 219 | radio.flush_rx(); 220 | } 221 | 222 | void logiMouse::click(bool leftClick, bool rightClick) { 223 | move(0, 0, leftClick, rightClick); 224 | } 225 | 226 | void logiMouse::scroll(uint8_t scroll_v, uint8_t scroll_h) 227 | { 228 | move(0, 0, scroll_v, scroll_h, false, false); 229 | } 230 | 231 | void logiMouse::scroll(uint8_t scroll_v) 232 | { 233 | scroll(scroll_v, 0); 234 | } 235 | -------------------------------------------------------------------------------- /RF24.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 J. Coliz 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | version 2 as published by the Free Software Foundation. 7 | */ 8 | 9 | #include "nRF24L01.h" 10 | #include "RF24_config.h" 11 | #include "RF24.h" 12 | 13 | /****************************************************************************/ 14 | 15 | void RF24::csn(bool mode) 16 | { 17 | 18 | #if defined (RF24_TINY) 19 | if (ce_pin != csn_pin) { 20 | digitalWrite(csn_pin,mode); 21 | } 22 | else { 23 | if (mode == HIGH) { 24 | PORTB |= (1<CSN HIGH 25 | delayMicroseconds(100); // allow csn to settle. 26 | } 27 | else { 28 | PORTB &= ~(1<CSN LOW 29 | delayMicroseconds(11); // allow csn to settle 30 | } 31 | } 32 | // Return, CSN toggle complete 33 | return; 34 | 35 | #elif defined(ARDUINO) && !defined (RF24_SPI_TRANSACTIONS) 36 | // Minimum ideal SPI bus speed is 2x data rate 37 | // If we assume 2Mbs data rate and 16Mhz clock, a 38 | // divider of 4 is the minimum we want. 39 | // CLK:BUS 8Mhz:2Mhz, 16Mhz:4Mhz, or 20Mhz:5Mhz 40 | 41 | #if !defined (SOFTSPI) 42 | _SPI.setBitOrder(MSBFIRST); 43 | _SPI.setDataMode(SPI_MODE0); 44 | _SPI.setClockDivider(SPI_CLOCK_DIV2); 45 | #endif 46 | #elif defined (RF24_RPi) 47 | if(!mode) 48 | _SPI.chipSelect(csn_pin); 49 | #endif 50 | 51 | #if !defined (RF24_LINUX) 52 | digitalWrite(csn_pin,mode); 53 | delayMicroseconds(csDelay); 54 | #endif 55 | 56 | } 57 | 58 | /****************************************************************************/ 59 | 60 | void RF24::ce(bool level) 61 | { 62 | //Allow for 3-pin use on ATTiny 63 | if (ce_pin != csn_pin) digitalWrite(ce_pin,level); 64 | } 65 | 66 | /****************************************************************************/ 67 | 68 | inline void RF24::beginTransaction() { 69 | #if defined (RF24_SPI_TRANSACTIONS) 70 | _SPI.beginTransaction(SPISettings(RF24_SPI_SPEED, MSBFIRST, SPI_MODE0)); 71 | #endif 72 | csn(LOW); 73 | } 74 | 75 | /****************************************************************************/ 76 | 77 | inline void RF24::endTransaction() { 78 | csn(HIGH); 79 | #if defined (RF24_SPI_TRANSACTIONS) 80 | _SPI.endTransaction(); 81 | #endif 82 | } 83 | 84 | /****************************************************************************/ 85 | 86 | uint8_t RF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len) 87 | { 88 | uint8_t status; 89 | 90 | #if defined (RF24_LINUX) 91 | beginTransaction(); //configures the spi settings for RPi, locks mutex and setting csn low 92 | uint8_t * prx = spi_rxbuff; 93 | uint8_t * ptx = spi_txbuff; 94 | uint8_t size = len + 1; // Add register value to transmit buffer 95 | 96 | *ptx++ = ( R_REGISTER | ( REGISTER_MASK & reg ) ); 97 | 98 | while (len--){ *ptx++ = NOP; } // Dummy operation, just for reading 99 | 100 | _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); 101 | 102 | status = *prx++; // status is 1st byte of receive buffer 103 | 104 | // decrement before to skip status byte 105 | while ( --size ){ *buf++ = *prx++; } 106 | endTransaction(); //unlocks mutex and setting csn high 107 | 108 | #else 109 | 110 | beginTransaction(); 111 | status = _SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) ); 112 | while ( len-- ){ 113 | *buf++ = _SPI.transfer(0xff); 114 | } 115 | endTransaction(); 116 | 117 | #endif 118 | 119 | return status; 120 | } 121 | 122 | /****************************************************************************/ 123 | 124 | uint8_t RF24::read_register(uint8_t reg) 125 | { 126 | uint8_t result; 127 | 128 | #if defined (RF24_LINUX) 129 | 130 | beginTransaction(); 131 | 132 | uint8_t * prx = spi_rxbuff; 133 | uint8_t * ptx = spi_txbuff; 134 | *ptx++ = ( R_REGISTER | ( REGISTER_MASK & reg ) ); 135 | *ptx++ = NOP ; // Dummy operation, just for reading 136 | 137 | _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); 138 | result = *++prx; // result is 2nd byte of receive buffer 139 | 140 | endTransaction(); 141 | #else 142 | 143 | beginTransaction(); 144 | _SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) ); 145 | result = _SPI.transfer(0xff); 146 | endTransaction(); 147 | 148 | #endif 149 | 150 | return result; 151 | } 152 | 153 | /****************************************************************************/ 154 | 155 | uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len) 156 | { 157 | uint8_t status; 158 | 159 | #if defined (RF24_LINUX) 160 | beginTransaction(); 161 | uint8_t * prx = spi_rxbuff; 162 | uint8_t * ptx = spi_txbuff; 163 | uint8_t size = len + 1; // Add register value to transmit buffer 164 | 165 | *ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) ); 166 | while ( len-- ) 167 | *ptx++ = *buf++; 168 | 169 | _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); 170 | status = *prx; // status is 1st byte of receive buffer 171 | endTransaction(); 172 | #else 173 | 174 | beginTransaction(); 175 | status = _SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) ); 176 | while ( len-- ) 177 | _SPI.transfer(*buf++); 178 | endTransaction(); 179 | 180 | #endif 181 | 182 | return status; 183 | } 184 | 185 | /****************************************************************************/ 186 | 187 | uint8_t RF24::write_register(uint8_t reg, uint8_t value) 188 | { 189 | uint8_t status; 190 | 191 | IF_SERIAL_DEBUG(printf_P(PSTR("write_register(%02x,%02x)\r\n"),reg,value)); 192 | 193 | #if defined (RF24_LINUX) 194 | beginTransaction(); 195 | uint8_t * prx = spi_rxbuff; 196 | uint8_t * ptx = spi_txbuff; 197 | *ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) ); 198 | *ptx = value ; 199 | 200 | _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); 201 | status = *prx++; // status is 1st byte of receive buffer 202 | endTransaction(); 203 | #else 204 | 205 | beginTransaction(); 206 | status = _SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) ); 207 | _SPI.transfer(value); 208 | endTransaction(); 209 | 210 | #endif 211 | 212 | return status; 213 | } 214 | 215 | /****************************************************************************/ 216 | 217 | uint8_t RF24::write_payload(const void* buf, uint8_t data_len, const uint8_t writeType) 218 | { 219 | uint8_t status; 220 | const uint8_t* current = reinterpret_cast(buf); 221 | 222 | data_len = rf24_min(data_len, payload_size); 223 | uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len; 224 | 225 | //printf("[Writing %u bytes %u blanks]",data_len,blank_len); 226 | IF_SERIAL_DEBUG( printf("[Writing %u bytes %u blanks]\n",data_len,blank_len); ); 227 | 228 | #if defined (RF24_LINUX) 229 | beginTransaction(); 230 | uint8_t * prx = spi_rxbuff; 231 | uint8_t * ptx = spi_txbuff; 232 | uint8_t size; 233 | size = data_len + blank_len + 1 ; // Add register value to transmit buffer 234 | 235 | *ptx++ = writeType; 236 | while ( data_len-- ) 237 | *ptx++ = *current++; 238 | while ( blank_len-- ) 239 | *ptx++ = 0; 240 | 241 | _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); 242 | status = *prx; // status is 1st byte of receive buffer 243 | endTransaction(); 244 | 245 | #else 246 | 247 | beginTransaction(); 248 | status = _SPI.transfer( writeType ); 249 | while ( data_len-- ) { 250 | _SPI.transfer(*current++); 251 | } 252 | while ( blank_len-- ) { 253 | _SPI.transfer(0); 254 | } 255 | endTransaction(); 256 | 257 | #endif 258 | 259 | return status; 260 | } 261 | 262 | /****************************************************************************/ 263 | 264 | uint8_t RF24::read_payload(void* buf, uint8_t data_len) 265 | { 266 | uint8_t status; 267 | uint8_t* current = reinterpret_cast(buf); 268 | 269 | if(data_len > payload_size) data_len = payload_size; 270 | uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len; 271 | 272 | //printf("[Reading %u bytes %u blanks]",data_len,blank_len); 273 | 274 | IF_SERIAL_DEBUG( printf("[Reading %u bytes %u blanks]\n",data_len,blank_len); ); 275 | 276 | #if defined (RF24_LINUX) 277 | beginTransaction(); 278 | uint8_t * prx = spi_rxbuff; 279 | uint8_t * ptx = spi_txbuff; 280 | uint8_t size; 281 | size = data_len + blank_len + 1; // Add register value to transmit buffer 282 | 283 | *ptx++ = R_RX_PAYLOAD; 284 | while(--size) 285 | *ptx++ = NOP; 286 | 287 | size = data_len + blank_len + 1; // Size has been lost during while, re affect 288 | 289 | _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); 290 | 291 | status = *prx++; // 1st byte is status 292 | 293 | if (data_len > 0) { 294 | while ( --data_len ) // Decrement before to skip 1st status byte 295 | *current++ = *prx++; 296 | 297 | *current = *prx; 298 | } 299 | endTransaction(); 300 | #else 301 | beginTransaction(); 302 | status = _SPI.transfer( R_RX_PAYLOAD ); 303 | //blank_len = status - data_len; 304 | while ( data_len-- ) { 305 | *current++ = _SPI.transfer(0xFF); 306 | } 307 | //printf("Excess data : "); 308 | while ( blank_len-- ) { 309 | _SPI.transfer(0xff); 310 | } 311 | Serial.println(); 312 | flush_rx(); 313 | endTransaction(); 314 | 315 | #endif 316 | 317 | return status; 318 | } 319 | 320 | /****************************************************************************/ 321 | 322 | uint8_t RF24::flush_rx(void) 323 | { 324 | return spiTrans( FLUSH_RX ); 325 | } 326 | 327 | /****************************************************************************/ 328 | 329 | uint8_t RF24::flush_tx(void) 330 | { 331 | return spiTrans( FLUSH_TX ); 332 | } 333 | 334 | /****************************************************************************/ 335 | 336 | uint8_t RF24::spiTrans(uint8_t cmd){ 337 | 338 | uint8_t status; 339 | 340 | beginTransaction(); 341 | status = _SPI.transfer( cmd ); 342 | endTransaction(); 343 | 344 | return status; 345 | } 346 | 347 | /****************************************************************************/ 348 | 349 | uint8_t RF24::get_status(void) 350 | { 351 | return spiTrans(NOP); 352 | } 353 | 354 | /****************************************************************************/ 355 | #if !defined (MINIMAL) 356 | void RF24::print_status(uint8_t status) 357 | { 358 | printf_P(PSTR("STATUS\t\t = 0x%02x RX_DR=%x TX_DS=%x MAX_RT=%x RX_P_NO=%x TX_FULL=%x\r\n"), 359 | status, 360 | (status & _BV(RX_DR))?1:0, 361 | (status & _BV(TX_DS))?1:0, 362 | (status & _BV(MAX_RT))?1:0, 363 | ((status >> RX_P_NO) & 0x07), 364 | (status & _BV(TX_FULL))?1:0 365 | ); 366 | } 367 | 368 | /****************************************************************************/ 369 | 370 | void RF24::print_observe_tx(uint8_t value) 371 | { 372 | printf_P(PSTR("OBSERVE_TX=%02x: POLS_CNT=%x ARC_CNT=%x\r\n"), 373 | value, 374 | (value >> PLOS_CNT) & 0x0F, 375 | (value >> ARC_CNT) & 0x0F 376 | ); 377 | } 378 | 379 | /****************************************************************************/ 380 | 381 | void RF24::print_byte_register(const char* name, uint8_t reg, uint8_t qty) 382 | { 383 | //char extra_tab = strlen_P(name) < 8 ? '\t' : 0; 384 | //printf_P(PSTR(PRIPSTR"\t%c ="),name,extra_tab); 385 | #if defined (RF24_LINUX) 386 | printf("%s\t =", name); 387 | #else 388 | printf_P(PSTR(PRIPSTR"\t ="),name); 389 | #endif 390 | while (qty--) 391 | printf_P(PSTR(" 0x%02x"),read_register(reg++)); 392 | printf_P(PSTR("\r\n")); 393 | } 394 | 395 | /****************************************************************************/ 396 | 397 | void RF24::print_address_register(const char* name, uint8_t reg, uint8_t qty) 398 | { 399 | 400 | #if defined (RF24_LINUX) 401 | printf("%s\t =",name); 402 | #else 403 | printf_P(PSTR(PRIPSTR"\t ="),name); 404 | #endif 405 | while (qty--) 406 | { 407 | uint8_t buffer[addr_width]; 408 | read_register(reg++,buffer,sizeof buffer); 409 | 410 | printf_P(PSTR(" 0x")); 411 | uint8_t* bufptr = buffer + sizeof buffer; 412 | while( --bufptr >= buffer ) 413 | printf_P(PSTR("%02x"),*bufptr); 414 | } 415 | 416 | printf_P(PSTR("\r\n")); 417 | } 418 | #endif 419 | /****************************************************************************/ 420 | 421 | RF24::RF24(uint8_t _cepin, uint8_t _cspin): 422 | ce_pin(_cepin), csn_pin(_cspin), p_variant(false), 423 | payload_size(32), dynamic_payloads_enabled(false), addr_width(5),csDelay(5)//,pipe0_reading_address(0) 424 | { 425 | pipe0_reading_address[0]=0; 426 | } 427 | 428 | /****************************************************************************/ 429 | 430 | #if defined (RF24_LINUX) && !defined (MRAA)//RPi constructor 431 | RF24::RF24(uint8_t _cepin, uint8_t _cspin, uint32_t _spi_speed): 432 | ce_pin(_cepin),csn_pin(_cspin),spi_speed(_spi_speed),p_variant(false), payload_size(32), dynamic_payloads_enabled(false),addr_width(5),csDelay(5)//,pipe0_reading_address(0) 433 | { 434 | pipe0_reading_address[0]=0; 435 | } 436 | #endif 437 | 438 | /****************************************************************************/ 439 | 440 | void RF24::setChannel(uint8_t channel) 441 | { 442 | const uint8_t max_channel = 125; 443 | write_register(RF_CH,rf24_min(channel,max_channel)); 444 | } 445 | 446 | uint8_t RF24::getChannel() 447 | { 448 | 449 | return read_register(RF_CH); 450 | } 451 | /****************************************************************************/ 452 | 453 | void RF24::setPayloadSize(uint8_t size) 454 | { 455 | payload_size = rf24_min(size,32); 456 | } 457 | 458 | /****************************************************************************/ 459 | 460 | uint8_t RF24::getPayloadSize(void) 461 | { 462 | return payload_size; 463 | } 464 | 465 | /****************************************************************************/ 466 | 467 | #if !defined (MINIMAL) 468 | 469 | static const char rf24_datarate_e_str_0[] PROGMEM = "1MBPS"; 470 | static const char rf24_datarate_e_str_1[] PROGMEM = "2MBPS"; 471 | static const char rf24_datarate_e_str_2[] PROGMEM = "250KBPS"; 472 | static const char * const rf24_datarate_e_str_P[] PROGMEM = { 473 | rf24_datarate_e_str_0, 474 | rf24_datarate_e_str_1, 475 | rf24_datarate_e_str_2, 476 | }; 477 | static const char rf24_model_e_str_0[] PROGMEM = "nRF24L01"; 478 | static const char rf24_model_e_str_1[] PROGMEM = "nRF24L01+"; 479 | static const char * const rf24_model_e_str_P[] PROGMEM = { 480 | rf24_model_e_str_0, 481 | rf24_model_e_str_1, 482 | }; 483 | static const char rf24_crclength_e_str_0[] PROGMEM = "Disabled"; 484 | static const char rf24_crclength_e_str_1[] PROGMEM = "8 bits"; 485 | static const char rf24_crclength_e_str_2[] PROGMEM = "16 bits" ; 486 | static const char * const rf24_crclength_e_str_P[] PROGMEM = { 487 | rf24_crclength_e_str_0, 488 | rf24_crclength_e_str_1, 489 | rf24_crclength_e_str_2, 490 | }; 491 | static const char rf24_pa_dbm_e_str_0[] PROGMEM = "PA_MIN"; 492 | static const char rf24_pa_dbm_e_str_1[] PROGMEM = "PA_LOW"; 493 | static const char rf24_pa_dbm_e_str_2[] PROGMEM = "PA_HIGH"; 494 | static const char rf24_pa_dbm_e_str_3[] PROGMEM = "PA_MAX"; 495 | static const char * const rf24_pa_dbm_e_str_P[] PROGMEM = { 496 | rf24_pa_dbm_e_str_0, 497 | rf24_pa_dbm_e_str_1, 498 | rf24_pa_dbm_e_str_2, 499 | rf24_pa_dbm_e_str_3, 500 | }; 501 | 502 | #if defined (RF24_LINUX) 503 | static const char rf24_csn_e_str_0[] = "CE0 (PI Hardware Driven)"; 504 | static const char rf24_csn_e_str_1[] = "CE1 (PI Hardware Driven)"; 505 | static const char rf24_csn_e_str_2[] = "CE2 (PI Hardware Driven)"; 506 | static const char rf24_csn_e_str_3[] = "Custom GPIO Software Driven"; 507 | static const char * const rf24_csn_e_str_P[] = { 508 | rf24_csn_e_str_0, 509 | rf24_csn_e_str_1, 510 | rf24_csn_e_str_2, 511 | rf24_csn_e_str_3, 512 | }; 513 | #endif 514 | 515 | void RF24::printDetails(void) 516 | { 517 | 518 | #if defined (RF24_RPi) 519 | printf("================ SPI Configuration ================\n" ); 520 | if (csn_pin < BCM2835_SPI_CS_NONE ){ 521 | printf("CSN Pin \t = %s\n",rf24_csn_e_str_P[csn_pin]); 522 | }else{ 523 | printf("CSN Pin \t = Custom GPIO%d%s\n", csn_pin, 524 | csn_pin==RPI_V2_GPIO_P1_26 ? " (CE1) Software Driven" : "" ); 525 | } 526 | printf("CE Pin \t = Custom GPIO%d\n", ce_pin ); 527 | printf("Clock Speed\t = " ); 528 | switch (spi_speed) 529 | { 530 | case BCM2835_SPI_SPEED_64MHZ : printf("64 Mhz"); break ; 531 | case BCM2835_SPI_SPEED_32MHZ : printf("32 Mhz"); break ; 532 | case BCM2835_SPI_SPEED_16MHZ : printf("16 Mhz"); break ; 533 | case BCM2835_SPI_SPEED_8MHZ : printf("8 Mhz"); break ; 534 | case BCM2835_SPI_SPEED_4MHZ : printf("4 Mhz"); break ; 535 | case BCM2835_SPI_SPEED_2MHZ : printf("2 Mhz"); break ; 536 | case BCM2835_SPI_SPEED_1MHZ : printf("1 Mhz"); break ; 537 | case BCM2835_SPI_SPEED_512KHZ: printf("512 KHz"); break ; 538 | case BCM2835_SPI_SPEED_256KHZ: printf("256 KHz"); break ; 539 | case BCM2835_SPI_SPEED_128KHZ: printf("128 KHz"); break ; 540 | case BCM2835_SPI_SPEED_64KHZ : printf("64 KHz"); break ; 541 | case BCM2835_SPI_SPEED_32KHZ : printf("32 KHz"); break ; 542 | case BCM2835_SPI_SPEED_16KHZ : printf("16 KHz"); break ; 543 | case BCM2835_SPI_SPEED_8KHZ : printf("8 KHz"); break ; 544 | default : printf("8 Mhz"); break ; 545 | } 546 | printf("\n================ NRF Configuration ================\n"); 547 | 548 | #endif //Linux 549 | 550 | print_status(get_status()); 551 | 552 | print_address_register(PSTR("RX_ADDR_P0-1"),RX_ADDR_P0,2); 553 | print_byte_register(PSTR("RX_ADDR_P2-5"),RX_ADDR_P2,4); 554 | print_address_register(PSTR("TX_ADDR\t"),TX_ADDR); 555 | 556 | print_byte_register(PSTR("RX_PW_P0-6"),RX_PW_P0,6); 557 | print_byte_register(PSTR("EN_AA\t"),EN_AA); 558 | print_byte_register(PSTR("EN_RXADDR"),EN_RXADDR); 559 | print_byte_register(PSTR("RF_CH\t"),RF_CH); 560 | print_byte_register(PSTR("RF_SETUP"),RF_SETUP); 561 | print_byte_register(PSTR("CONFIG\t"),NRF_CONFIG); 562 | print_byte_register(PSTR("DYNPD/FEATURE"),DYNPD,2); 563 | 564 | printf_P(PSTR("Data Rate\t = " PRIPSTR "\r\n"),pgm_read_word(&rf24_datarate_e_str_P[getDataRate()])); 565 | printf_P(PSTR("Model\t\t = " PRIPSTR "\r\n"),pgm_read_word(&rf24_model_e_str_P[isPVariant()])); 566 | printf_P(PSTR("CRC Length\t = " PRIPSTR "\r\n"),pgm_read_word(&rf24_crclength_e_str_P[getCRCLength()])); 567 | printf_P(PSTR("PA Power\t = " PRIPSTR "\r\n"), pgm_read_word(&rf24_pa_dbm_e_str_P[getPALevel()])); 568 | 569 | } 570 | 571 | #endif 572 | /****************************************************************************/ 573 | 574 | bool RF24::begin(void) 575 | { 576 | 577 | uint8_t setup=0; 578 | 579 | #if defined (RF24_LINUX) 580 | 581 | #if defined (MRAA) 582 | GPIO(); 583 | gpio.begin(ce_pin,csn_pin); 584 | #endif 585 | 586 | #ifdef RF24_RPi 587 | switch(csn_pin){ //Ensure valid hardware CS pin 588 | case 0: break; 589 | case 1: break; 590 | // Allow BCM2835 enums for RPi 591 | case 8: csn_pin = 0; break; 592 | case 7: csn_pin = 1; break; 593 | default: csn_pin = 0; break; 594 | } 595 | #endif 596 | 597 | _SPI.begin(csn_pin); 598 | 599 | pinMode(ce_pin,OUTPUT); 600 | ce(LOW); 601 | 602 | delay(100); 603 | 604 | #elif defined(LITTLEWIRE) 605 | pinMode(csn_pin,OUTPUT); 606 | _SPI.begin(); 607 | csn(HIGH); 608 | #elif defined(XMEGA_D3) 609 | if (ce_pin != csn_pin) pinMode(ce_pin,OUTPUT); 610 | _SPI.begin(csn_pin); 611 | ce(LOW); 612 | csn(HIGH); 613 | delay(200); 614 | #else 615 | // Initialize pins 616 | if (ce_pin != csn_pin) pinMode(ce_pin,OUTPUT); 617 | 618 | #if ! defined(LITTLEWIRE) 619 | if (ce_pin != csn_pin) 620 | #endif 621 | pinMode(csn_pin,OUTPUT); 622 | 623 | _SPI.begin(); 624 | ce(LOW); 625 | csn(HIGH); 626 | #if defined (__ARDUINO_X86__) 627 | delay(100); 628 | #endif 629 | #endif //Linux 630 | 631 | // Must allow the radio time to settle else configuration bits will not necessarily stick. 632 | // This is actually only required following power up but some settling time also appears to 633 | // be required after resets too. For full coverage, we'll always assume the worst. 634 | // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped. 635 | // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure. 636 | // WARNING: Delay is based on P-variant whereby non-P *may* require different timing. 637 | delay( 5 ) ; 638 | 639 | // Reset NRF_CONFIG and enable 16-bit CRC. 640 | write_register( NRF_CONFIG, 0x0C ) ; 641 | 642 | // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier 643 | // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet 644 | // sizes must never be used. See documentation for a more complete explanation. 645 | setRetries(5,15); 646 | 647 | // Reset value is MAX 648 | //setPALevel( RF24_PA_MAX ) ; 649 | 650 | // check for connected module and if this is a p nRF24l01 variant 651 | // 652 | if( setDataRate( RF24_250KBPS ) ) 653 | { 654 | p_variant = true ; 655 | } 656 | setup = read_register(RF_SETUP); 657 | /*if( setup == 0b00001110 ) // register default for nRF24L01P 658 | { 659 | p_variant = true ; 660 | }*/ 661 | 662 | // Then set the data rate to the slowest (and most reliable) speed supported by all 663 | // hardware. 664 | setDataRate( RF24_1MBPS ) ; 665 | 666 | // Initialize CRC and request 2-byte (16bit) CRC 667 | //setCRCLength( RF24_CRC_16 ) ; 668 | 669 | // Disable dynamic payloads, to match dynamic_payloads_enabled setting - Reset value is 0 670 | toggle_features(); 671 | write_register(FEATURE,0 ); 672 | write_register(DYNPD,0); 673 | 674 | // Reset current status 675 | // Notice reset and flush is the last thing we do 676 | write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); 677 | 678 | // Set up default configuration. Callers can always change it later. 679 | // This channel should be universally safe and not bleed over into adjacent 680 | // spectrum. 681 | setChannel(76); 682 | 683 | // Flush buffers 684 | flush_rx(); 685 | flush_tx(); 686 | 687 | powerUp(); //Power up by default when begin() is called 688 | 689 | // Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp ) 690 | // PTX should use only 22uA of power 691 | write_register(NRF_CONFIG, ( read_register(NRF_CONFIG) ) & ~_BV(PRIM_RX) ); 692 | 693 | // if setup is 0 or ff then there was no response from module 694 | return ( setup != 0 && setup != 0xff ); 695 | } 696 | 697 | /****************************************************************************/ 698 | 699 | void RF24::startListening(void) 700 | { 701 | #if !defined (RF24_TINY) && ! defined(LITTLEWIRE) 702 | powerUp(); 703 | #endif 704 | write_register(NRF_CONFIG, read_register(NRF_CONFIG) | _BV(PRIM_RX)); 705 | write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); 706 | ce(HIGH); 707 | // Restore the pipe0 adddress, if exists 708 | if (pipe0_reading_address[0] > 0){ 709 | write_register(RX_ADDR_P0, pipe0_reading_address, addr_width); 710 | }else{ 711 | closeReadingPipe(0); 712 | } 713 | 714 | // Flush buffers 715 | //flush_rx(); 716 | if(read_register(FEATURE) & _BV(EN_ACK_PAY)){ 717 | flush_tx(); 718 | } 719 | 720 | // Go! 721 | //delayMicroseconds(100); 722 | } 723 | 724 | /****************************************************************************/ 725 | static const uint8_t child_pipe_enable[] PROGMEM = 726 | { 727 | ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5 728 | }; 729 | 730 | void RF24::stopListening(void) 731 | { 732 | ce(LOW); 733 | 734 | delayMicroseconds(txDelay); 735 | 736 | if(read_register(FEATURE) & _BV(EN_ACK_PAY)){ 737 | delayMicroseconds(txDelay); //200 738 | flush_tx(); 739 | } 740 | //flush_rx(); 741 | write_register(NRF_CONFIG, ( read_register(NRF_CONFIG) ) & ~_BV(PRIM_RX) ); 742 | 743 | #if defined (RF24_TINY) || defined (LITTLEWIRE) 744 | // for 3 pins solution TX mode is only left with additonal powerDown/powerUp cycle 745 | if (ce_pin == csn_pin) { 746 | powerDown(); 747 | powerUp(); 748 | } 749 | #endif 750 | write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[0]))); // Enable RX on pipe0 751 | 752 | //delayMicroseconds(100); 753 | 754 | } 755 | 756 | /****************************************************************************/ 757 | 758 | void RF24::powerDown(void) 759 | { 760 | ce(LOW); // Guarantee CE is low on powerDown 761 | write_register(NRF_CONFIG,read_register(NRF_CONFIG) & ~_BV(PWR_UP)); 762 | } 763 | 764 | /****************************************************************************/ 765 | 766 | //Power up now. Radio will not power down unless instructed by MCU for config changes etc. 767 | void RF24::powerUp(void) 768 | { 769 | uint8_t cfg = read_register(NRF_CONFIG); 770 | 771 | // if not powered up then power up and wait for the radio to initialize 772 | if (!(cfg & _BV(PWR_UP))){ 773 | write_register(NRF_CONFIG, cfg | _BV(PWR_UP)); 774 | 775 | // For nRF24L01+ to go from power down mode to TX or RX mode it must first pass through stand-by mode. 776 | // There must be a delay of Tpd2stby (see Table 16.) after the nRF24L01+ leaves power down mode before 777 | // the CEis set high. - Tpd2stby can be up to 5ms per the 1.0 datasheet 778 | delay(5); 779 | } 780 | } 781 | 782 | /******************************************************************/ 783 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 784 | void RF24::errNotify(){ 785 | #if defined (SERIAL_DEBUG) || defined (RF24_LINUX) 786 | printf_P(PSTR("RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.\r\n")); 787 | #endif 788 | #if defined (FAILURE_HANDLING) 789 | failureDetected = 1; 790 | #else 791 | delay(5000); 792 | #endif 793 | } 794 | #endif 795 | /******************************************************************/ 796 | 797 | //Similar to the previous write, clears the interrupt flags 798 | bool RF24::write( const void* buf, uint8_t len, const bool multicast ) 799 | { 800 | //Start Writing 801 | startFastWrite(buf,len,multicast); 802 | 803 | //Wait until complete or failed 804 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 805 | uint32_t timer = millis(); 806 | #endif 807 | 808 | while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { 809 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 810 | if(millis() - timer > 95){ 811 | errNotify(); 812 | #if defined (FAILURE_HANDLING) 813 | return 0; 814 | #else 815 | delay(100); 816 | #endif 817 | } 818 | #endif 819 | } 820 | 821 | ce(LOW); 822 | 823 | uint8_t status = write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); 824 | 825 | //Max retries exceeded 826 | if( status & _BV(MAX_RT)){ 827 | flush_tx(); //Only going to be 1 packet int the FIFO at a time using this method, so just flush 828 | return 0; 829 | } 830 | //TX OK 1 or 0 831 | return 1; 832 | } 833 | 834 | bool RF24::write( const void* buf, uint8_t len ){ 835 | return write(buf,len,0); 836 | } 837 | /****************************************************************************/ 838 | 839 | //For general use, the interrupt flags are not important to clear 840 | bool RF24::writeBlocking( const void* buf, uint8_t len, uint32_t timeout ) 841 | { 842 | //Block until the FIFO is NOT full. 843 | //Keep track of the MAX retries and set auto-retry if seeing failures 844 | //This way the FIFO will fill up and allow blocking until packets go through 845 | //The radio will auto-clear everything in the FIFO as long as CE remains high 846 | 847 | uint32_t timer = millis(); //Get the time that the payload transmission started 848 | 849 | while( ( get_status() & ( _BV(TX_FULL) ))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or timeout 850 | 851 | if( get_status() & _BV(MAX_RT)){ //If MAX Retries have been reached 852 | reUseTX(); //Set re-transmit and clear the MAX_RT interrupt flag 853 | if(millis() - timer > timeout){ return 0; } //If this payload has exceeded the user-defined timeout, exit and return 0 854 | } 855 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 856 | if(millis() - timer > (timeout+95) ){ 857 | errNotify(); 858 | #if defined (FAILURE_HANDLING) 859 | return 0; 860 | #endif 861 | } 862 | #endif 863 | 864 | } 865 | 866 | //Start Writing 867 | startFastWrite(buf,len,0); //Write the payload if a buffer is clear 868 | 869 | return 1; //Return 1 to indicate successful transmission 870 | } 871 | 872 | /****************************************************************************/ 873 | 874 | void RF24::reUseTX(){ 875 | write_register(NRF_STATUS,_BV(MAX_RT) ); //Clear max retry flag 876 | spiTrans( REUSE_TX_PL ); 877 | ce(LOW); //Re-Transfer packet 878 | ce(HIGH); 879 | } 880 | 881 | /****************************************************************************/ 882 | 883 | bool RF24::writeFast( const void* buf, uint8_t len, const bool multicast ) 884 | { 885 | //Block until the FIFO is NOT full. 886 | //Keep track of the MAX retries and set auto-retry if seeing failures 887 | //Return 0 so the user can control the retrys and set a timer or failure counter if required 888 | //The radio will auto-clear everything in the FIFO as long as CE remains high 889 | 890 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 891 | uint32_t timer = millis(); 892 | #endif 893 | 894 | while( ( get_status() & ( _BV(TX_FULL) ))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or fail 895 | 896 | if( get_status() & _BV(MAX_RT)){ 897 | //reUseTX(); //Set re-transmit 898 | write_register(NRF_STATUS,_BV(MAX_RT) ); //Clear max retry flag 899 | return 0; //Return 0. The previous payload has been retransmitted 900 | //From the user perspective, if you get a 0, just keep trying to send the same payload 901 | } 902 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 903 | if(millis() - timer > 95 ){ 904 | errNotify(); 905 | #if defined (FAILURE_HANDLING) 906 | return 0; 907 | #endif 908 | } 909 | #endif 910 | } 911 | //Start Writing 912 | startFastWrite(buf,len,multicast); 913 | 914 | return 1; 915 | } 916 | 917 | bool RF24::writeFast( const void* buf, uint8_t len ){ 918 | return writeFast(buf,len,0); 919 | } 920 | 921 | /****************************************************************************/ 922 | 923 | //Per the documentation, we want to set PTX Mode when not listening. Then all we do is write data and set CE high 924 | //In this mode, if we can keep the FIFO buffers loaded, packets will transmit immediately (no 130us delay) 925 | //Otherwise we enter Standby-II mode, which is still faster than standby mode 926 | //Also, we remove the need to keep writing the config register over and over and delaying for 150 us each time if sending a stream of data 927 | 928 | void RF24::startFastWrite( const void* buf, uint8_t len, const bool multicast, bool startTx){ //TMRh20 929 | 930 | //write_payload( buf,len); 931 | write_payload( buf, len,multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ; 932 | if(startTx){ 933 | ce(HIGH); 934 | } 935 | 936 | } 937 | 938 | /****************************************************************************/ 939 | 940 | //Added the original startWrite back in so users can still use interrupts, ack payloads, etc 941 | //Allows the library to pass all tests 942 | void RF24::startWrite( const void* buf, uint8_t len, const bool multicast ){ 943 | 944 | // Send the payload 945 | 946 | //write_payload( buf, len ); 947 | write_payload( buf, len,multicast? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ; 948 | ce(HIGH); 949 | #if defined(CORE_TEENSY) || !defined(ARDUINO) || defined (RF24_SPIDEV) || defined (RF24_DUE) 950 | delayMicroseconds(10); 951 | #endif 952 | ce(LOW); 953 | 954 | 955 | } 956 | 957 | /****************************************************************************/ 958 | 959 | bool RF24::rxFifoFull(){ 960 | return read_register(FIFO_STATUS) & _BV(RX_FULL); 961 | } 962 | /****************************************************************************/ 963 | 964 | bool RF24::txStandBy(){ 965 | 966 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 967 | uint32_t timeout = millis(); 968 | #endif 969 | while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ 970 | if( get_status() & _BV(MAX_RT)){ 971 | write_register(NRF_STATUS,_BV(MAX_RT) ); 972 | ce(LOW); 973 | flush_tx(); //Non blocking, flush the data 974 | return 0; 975 | } 976 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 977 | if( millis() - timeout > 95){ 978 | errNotify(); 979 | #if defined (FAILURE_HANDLING) 980 | return 0; 981 | #endif 982 | } 983 | #endif 984 | } 985 | 986 | ce(LOW); //Set STANDBY-I mode 987 | return 1; 988 | } 989 | 990 | /****************************************************************************/ 991 | 992 | bool RF24::txStandBy(uint32_t timeout, bool startTx){ 993 | 994 | if(startTx){ 995 | stopListening(); 996 | ce(HIGH); 997 | } 998 | uint32_t start = millis(); 999 | 1000 | while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ 1001 | if( get_status() & _BV(MAX_RT)){ 1002 | write_register(NRF_STATUS,_BV(MAX_RT) ); 1003 | ce(LOW); //Set re-transmit 1004 | ce(HIGH); 1005 | if(millis() - start >= timeout){ 1006 | ce(LOW); flush_tx(); return 0; 1007 | } 1008 | } 1009 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 1010 | if( millis() - start > (timeout+95)){ 1011 | errNotify(); 1012 | #if defined (FAILURE_HANDLING) 1013 | return 0; 1014 | #endif 1015 | } 1016 | #endif 1017 | } 1018 | 1019 | 1020 | ce(LOW); //Set STANDBY-I mode 1021 | return 1; 1022 | 1023 | } 1024 | 1025 | /****************************************************************************/ 1026 | 1027 | void RF24::maskIRQ(bool tx, bool fail, bool rx){ 1028 | 1029 | uint8_t config = read_register(NRF_CONFIG); 1030 | /* clear the interrupt flags */ 1031 | config &= ~(1 << MASK_MAX_RT | 1 << MASK_TX_DS | 1 << MASK_RX_DR); 1032 | /* set the specified interrupt flags */ 1033 | config |= fail << MASK_MAX_RT | tx << MASK_TX_DS | rx << MASK_RX_DR; 1034 | write_register(NRF_CONFIG, config); 1035 | } 1036 | 1037 | /****************************************************************************/ 1038 | 1039 | uint8_t RF24::getDynamicPayloadSize(void) 1040 | { 1041 | uint8_t result = 0; 1042 | 1043 | #if defined (RF24_LINUX) 1044 | spi_txbuff[0] = R_RX_PL_WID; 1045 | spi_rxbuff[1] = 0xff; 1046 | beginTransaction(); 1047 | _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); 1048 | result = spi_rxbuff[1]; 1049 | endTransaction(); 1050 | #else 1051 | beginTransaction(); 1052 | _SPI.transfer( R_RX_PL_WID ); 1053 | result = _SPI.transfer(0xff); 1054 | endTransaction(); 1055 | #endif 1056 | 1057 | if(result > 32) { flush_rx(); delay(2); return 0; } 1058 | return result; 1059 | } 1060 | 1061 | /****************************************************************************/ 1062 | 1063 | bool RF24::available(void) 1064 | { 1065 | return available(NULL); 1066 | } 1067 | 1068 | /****************************************************************************/ 1069 | 1070 | bool RF24::available(uint8_t* pipe_num) 1071 | { 1072 | if (!( read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){ 1073 | 1074 | // If the caller wants the pipe number, include that 1075 | if ( pipe_num ){ 1076 | uint8_t status = get_status(); 1077 | *pipe_num = ( status >> RX_P_NO ) & 0x07; 1078 | } 1079 | return 1; 1080 | } 1081 | 1082 | 1083 | return 0; 1084 | 1085 | 1086 | } 1087 | 1088 | /****************************************************************************/ 1089 | 1090 | uint8_t RF24::read( void* buf, uint8_t len ){ 1091 | uint8_t result; 1092 | // Fetch the payload 1093 | result = read_payload( buf, len ); 1094 | 1095 | //Clear the two possible interrupt flags with one command 1096 | write_register(NRF_STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS) ); 1097 | return result; 1098 | } 1099 | 1100 | /****************************************************************************/ 1101 | 1102 | void RF24::whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready) 1103 | { 1104 | // Read the status & reset the status in one easy call 1105 | // Or is that such a good idea? 1106 | uint8_t status = write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); 1107 | 1108 | // Report to the user what happened 1109 | tx_ok = status & _BV(TX_DS); 1110 | tx_fail = status & _BV(MAX_RT); 1111 | rx_ready = status & _BV(RX_DR); 1112 | } 1113 | 1114 | /****************************************************************************/ 1115 | 1116 | void RF24::openWritingPipe(uint64_t value) 1117 | { 1118 | // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) 1119 | // expects it LSB first too, so we're good. 1120 | 1121 | write_register(RX_ADDR_P0, reinterpret_cast(&value), addr_width); 1122 | write_register(TX_ADDR, reinterpret_cast(&value), addr_width); 1123 | 1124 | 1125 | //const uint8_t max_payload_size = 32; 1126 | //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size)); 1127 | write_register(RX_PW_P0,payload_size); 1128 | } 1129 | 1130 | /****************************************************************************/ 1131 | void RF24::openWritingPipe(const uint8_t *address) 1132 | { 1133 | // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) 1134 | // expects it LSB first too, so we're good. 1135 | 1136 | write_register(RX_ADDR_P0,address, addr_width); 1137 | write_register(TX_ADDR, address, addr_width); 1138 | 1139 | //const uint8_t max_payload_size = 32; 1140 | //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size)); 1141 | write_register(RX_PW_P0,payload_size); 1142 | } 1143 | 1144 | /****************************************************************************/ 1145 | static const uint8_t child_pipe[] PROGMEM = 1146 | { 1147 | RX_ADDR_P0, RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5 1148 | }; 1149 | static const uint8_t child_payload_size[] PROGMEM = 1150 | { 1151 | RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5 1152 | }; 1153 | 1154 | 1155 | void RF24::openReadingPipe(uint8_t child, uint64_t address) 1156 | { 1157 | // If this is pipe 0, cache the address. This is needed because 1158 | // openWritingPipe() will overwrite the pipe 0 address, so 1159 | // startListening() will have to restore it. 1160 | if (child == 0){ 1161 | memcpy(pipe0_reading_address,&address,addr_width); 1162 | } 1163 | 1164 | if (child <= 6) 1165 | { 1166 | // For pipes 2-5, only write the LSB 1167 | if ( child < 2 ) 1168 | write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast(&address), addr_width); 1169 | else 1170 | write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast(&address), 1); 1171 | 1172 | write_register(pgm_read_byte(&child_payload_size[child]),payload_size); 1173 | 1174 | // Note it would be more efficient to set all of the bits for all open 1175 | // pipes at once. However, I thought it would make the calling code 1176 | // more simple to do it this way. 1177 | write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); 1178 | } 1179 | } 1180 | 1181 | /****************************************************************************/ 1182 | void RF24::setAddressWidth(uint8_t a_width){ 1183 | 1184 | if(a_width -= 2){ 1185 | write_register(SETUP_AW,a_width%4); 1186 | addr_width = (a_width%4) + 2; 1187 | }else{ 1188 | write_register(SETUP_AW,0); 1189 | addr_width = 2; 1190 | } 1191 | 1192 | } 1193 | 1194 | /****************************************************************************/ 1195 | 1196 | void RF24::openReadingPipe(uint8_t child, const uint8_t *address) 1197 | { 1198 | // If this is pipe 0, cache the address. This is needed because 1199 | // openWritingPipe() will overwrite the pipe 0 address, so 1200 | // startListening() will have to restore it. 1201 | if (child == 0){ 1202 | memcpy(pipe0_reading_address,address,addr_width); 1203 | } 1204 | if (child <= 6) 1205 | { 1206 | // For pipes 2-5, only write the LSB 1207 | if ( child < 2 ){ 1208 | write_register(pgm_read_byte(&child_pipe[child]), address, addr_width); 1209 | }else{ 1210 | write_register(pgm_read_byte(&child_pipe[child]), address, 1); 1211 | } 1212 | write_register(pgm_read_byte(&child_payload_size[child]),payload_size); 1213 | 1214 | // Note it would be more efficient to set all of the bits for all open 1215 | // pipes at once. However, I thought it would make the calling code 1216 | // more simple to do it this way. 1217 | write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); 1218 | 1219 | } 1220 | } 1221 | 1222 | /****************************************************************************/ 1223 | 1224 | void RF24::closeReadingPipe( uint8_t pipe ) 1225 | { 1226 | write_register(EN_RXADDR,read_register(EN_RXADDR) & ~_BV(pgm_read_byte(&child_pipe_enable[pipe]))); 1227 | } 1228 | 1229 | /****************************************************************************/ 1230 | 1231 | void RF24::toggle_features(void) 1232 | { 1233 | beginTransaction(); 1234 | _SPI.transfer( ACTIVATE ); 1235 | _SPI.transfer( 0x73 ); 1236 | endTransaction(); 1237 | } 1238 | 1239 | /****************************************************************************/ 1240 | 1241 | void RF24::enableDynamicPayloads(void) 1242 | { 1243 | // Enable dynamic payload throughout the system 1244 | 1245 | //toggle_features(); 1246 | write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) ); 1247 | 1248 | 1249 | IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); 1250 | 1251 | // Enable dynamic payload on all pipes 1252 | // 1253 | // Not sure the use case of only having dynamic payload on certain 1254 | // pipes, so the library does not support it. 1255 | write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0)); 1256 | 1257 | dynamic_payloads_enabled = true; 1258 | } 1259 | 1260 | /****************************************************************************/ 1261 | 1262 | void RF24::enableAckPayload(void) 1263 | { 1264 | // 1265 | // enable ack payload and dynamic payload features 1266 | // 1267 | 1268 | //toggle_features(); 1269 | write_register(FEATURE,read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) ); 1270 | 1271 | IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); 1272 | 1273 | // 1274 | // Enable dynamic payload on pipes 0 & 1 1275 | // 1276 | 1277 | write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P1) | _BV(DPL_P0)); 1278 | dynamic_payloads_enabled = true; 1279 | } 1280 | 1281 | /****************************************************************************/ 1282 | 1283 | void RF24::enableDynamicAck(void){ 1284 | // 1285 | // enable dynamic ack features 1286 | // 1287 | //toggle_features(); 1288 | write_register(FEATURE,read_register(FEATURE) | _BV(EN_DYN_ACK) ); 1289 | 1290 | IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); 1291 | 1292 | 1293 | } 1294 | 1295 | /****************************************************************************/ 1296 | 1297 | void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len) 1298 | { 1299 | const uint8_t* current = reinterpret_cast(buf); 1300 | 1301 | uint8_t data_len = rf24_min(len,32); 1302 | 1303 | #if defined (RF24_LINUX) 1304 | beginTransaction(); 1305 | uint8_t * ptx = spi_txbuff; 1306 | uint8_t size = data_len + 1 ; // Add register value to transmit buffer 1307 | *ptx++ = W_ACK_PAYLOAD | ( pipe & 0x07 ); 1308 | while ( data_len-- ){ 1309 | *ptx++ = *current++; 1310 | } 1311 | 1312 | _SPI.transfern( (char *) spi_txbuff, size); 1313 | endTransaction(); 1314 | #else 1315 | beginTransaction(); 1316 | _SPI.transfer(W_ACK_PAYLOAD | ( pipe & 0x07 ) ); 1317 | 1318 | while ( data_len-- ) 1319 | _SPI.transfer(*current++); 1320 | endTransaction(); 1321 | 1322 | #endif 1323 | 1324 | } 1325 | 1326 | /****************************************************************************/ 1327 | 1328 | bool RF24::isAckPayloadAvailable(void) 1329 | { 1330 | return ! (read_register(FIFO_STATUS) & _BV(RX_EMPTY)); 1331 | } 1332 | 1333 | /****************************************************************************/ 1334 | 1335 | bool RF24::isPVariant(void) 1336 | { 1337 | return p_variant ; 1338 | } 1339 | 1340 | /****************************************************************************/ 1341 | 1342 | void RF24::setAutoAck(bool enable) 1343 | { 1344 | if ( enable ) 1345 | write_register(EN_AA, 0x3F); 1346 | else 1347 | write_register(EN_AA, 0); 1348 | } 1349 | 1350 | /****************************************************************************/ 1351 | 1352 | void RF24::setAutoAck( uint8_t pipe, bool enable ) 1353 | { 1354 | if ( pipe <= 6 ) 1355 | { 1356 | uint8_t en_aa = read_register( EN_AA ) ; 1357 | if( enable ) 1358 | { 1359 | en_aa |= _BV(pipe) ; 1360 | } 1361 | else 1362 | { 1363 | en_aa &= ~_BV(pipe) ; 1364 | } 1365 | write_register( EN_AA, en_aa ) ; 1366 | } 1367 | } 1368 | 1369 | /****************************************************************************/ 1370 | 1371 | bool RF24::testCarrier(void) 1372 | { 1373 | return ( read_register(CD) & 1 ); 1374 | } 1375 | 1376 | /****************************************************************************/ 1377 | 1378 | bool RF24::testRPD(void) 1379 | { 1380 | return ( read_register(RPD) & 1 ) ; 1381 | } 1382 | 1383 | /****************************************************************************/ 1384 | 1385 | void RF24::setPALevel(uint8_t level) 1386 | { 1387 | 1388 | uint8_t setup = read_register(RF_SETUP) & 0xF8; 1389 | 1390 | if(level > 3){ // If invalid level, go to max PA 1391 | level = (RF24_PA_MAX << 1) + 1; // +1 to support the SI24R1 chip extra bit 1392 | }else{ 1393 | level = (level << 1) + 1; // Else set level as requested 1394 | } 1395 | 1396 | 1397 | write_register( RF_SETUP, setup |= level ) ; // Write it to the chip 1398 | } 1399 | 1400 | /****************************************************************************/ 1401 | 1402 | uint8_t RF24::getPALevel(void) 1403 | { 1404 | 1405 | return (read_register(RF_SETUP) & (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH))) >> 1 ; 1406 | } 1407 | 1408 | /****************************************************************************/ 1409 | 1410 | bool RF24::setDataRate(rf24_datarate_e speed) 1411 | { 1412 | bool result = false; 1413 | uint8_t setup = read_register(RF_SETUP) ; 1414 | 1415 | // HIGH and LOW '00' is 1Mbs - our default 1416 | setup &= ~(_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)) ; 1417 | 1418 | #if defined(__arm__) || defined (RF24_LINUX) || defined (__ARDUINO_X86__) 1419 | txDelay=250; 1420 | #else //16Mhz Arduino 1421 | txDelay=85; 1422 | #endif 1423 | if( speed == RF24_250KBPS ) 1424 | { 1425 | // Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0 1426 | // Making it '10'. 1427 | setup |= _BV( RF_DR_LOW ) ; 1428 | #if defined(__arm__) || defined (RF24_LINUX) || defined (__ARDUINO_X86__) 1429 | txDelay=450; 1430 | #else //16Mhz Arduino 1431 | txDelay=155; 1432 | #endif 1433 | } 1434 | else 1435 | { 1436 | // Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1 1437 | // Making it '01' 1438 | if ( speed == RF24_2MBPS ) 1439 | { 1440 | setup |= _BV(RF_DR_HIGH); 1441 | #if defined(__arm__) || defined (RF24_LINUX) || defined (__ARDUINO_X86__) 1442 | txDelay=190; 1443 | #else //16Mhz Arduino 1444 | txDelay=65; 1445 | #endif 1446 | } 1447 | } 1448 | write_register(RF_SETUP,setup); 1449 | 1450 | // Verify our result 1451 | if ( read_register(RF_SETUP) == setup ) 1452 | { 1453 | result = true; 1454 | } 1455 | return result; 1456 | } 1457 | 1458 | /****************************************************************************/ 1459 | 1460 | rf24_datarate_e RF24::getDataRate( void ) 1461 | { 1462 | rf24_datarate_e result ; 1463 | uint8_t dr = read_register(RF_SETUP) & (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)); 1464 | 1465 | // switch uses RAM (evil!) 1466 | // Order matters in our case below 1467 | if ( dr == _BV(RF_DR_LOW) ) 1468 | { 1469 | // '10' = 250KBPS 1470 | result = RF24_250KBPS ; 1471 | } 1472 | else if ( dr == _BV(RF_DR_HIGH) ) 1473 | { 1474 | // '01' = 2MBPS 1475 | result = RF24_2MBPS ; 1476 | } 1477 | else 1478 | { 1479 | // '00' = 1MBPS 1480 | result = RF24_1MBPS ; 1481 | } 1482 | return result ; 1483 | } 1484 | 1485 | /****************************************************************************/ 1486 | 1487 | void RF24::setCRCLength(rf24_crclength_e length) 1488 | { 1489 | uint8_t config = read_register(NRF_CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ; 1490 | 1491 | // switch uses RAM (evil!) 1492 | if ( length == RF24_CRC_DISABLED ) 1493 | { 1494 | // Do nothing, we turned it off above. 1495 | } 1496 | else if ( length == RF24_CRC_8 ) 1497 | { 1498 | config |= _BV(EN_CRC); 1499 | } 1500 | else 1501 | { 1502 | config |= _BV(EN_CRC); 1503 | config |= _BV( CRCO ); 1504 | } 1505 | write_register( NRF_CONFIG, config ) ; 1506 | } 1507 | 1508 | /****************************************************************************/ 1509 | 1510 | rf24_crclength_e RF24::getCRCLength(void) 1511 | { 1512 | rf24_crclength_e result = RF24_CRC_DISABLED; 1513 | 1514 | uint8_t config = read_register(NRF_CONFIG) & ( _BV(CRCO) | _BV(EN_CRC)) ; 1515 | uint8_t AA = read_register(EN_AA); 1516 | 1517 | if ( config & _BV(EN_CRC ) || AA) 1518 | { 1519 | if ( config & _BV(CRCO) ) 1520 | result = RF24_CRC_16; 1521 | else 1522 | result = RF24_CRC_8; 1523 | } 1524 | 1525 | return result; 1526 | } 1527 | 1528 | /****************************************************************************/ 1529 | 1530 | void RF24::disableCRC( void ) 1531 | { 1532 | uint8_t disable = read_register(NRF_CONFIG) & ~_BV(EN_CRC) ; 1533 | write_register( NRF_CONFIG, disable ) ; 1534 | } 1535 | 1536 | /****************************************************************************/ 1537 | void RF24::setRetries(uint8_t delay, uint8_t count) 1538 | { 1539 | write_register(SETUP_RETR,(delay&0xf)< 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | version 2 as published by the Free Software Foundation. 7 | */ 8 | 9 | /** 10 | * @file RF24.h 11 | * 12 | * Class declaration for RF24 and helper enums 13 | */ 14 | 15 | #ifndef __RF24_H__ 16 | #define __RF24_H__ 17 | 18 | #include "RF24_config.h" 19 | 20 | #if defined (RF24_LINUX) || defined (LITTLEWIRE) 21 | #include "utility/includes.h" 22 | #elif defined SOFTSPI 23 | #include 24 | #endif 25 | 26 | /** 27 | * Power Amplifier level. 28 | * 29 | * For use with setPALevel() 30 | */ 31 | typedef enum { RF24_PA_MIN = 0,RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_PA_ERROR } rf24_pa_dbm_e ; 32 | 33 | /** 34 | * Data rate. How fast data moves through the air. 35 | * 36 | * For use with setDataRate() 37 | */ 38 | typedef enum { RF24_1MBPS = 0, RF24_2MBPS, RF24_250KBPS } rf24_datarate_e; 39 | 40 | /** 41 | * CRC Length. How big (if any) of a CRC is included. 42 | * 43 | * For use with setCRCLength() 44 | */ 45 | typedef enum { RF24_CRC_DISABLED = 0, RF24_CRC_8, RF24_CRC_16 } rf24_crclength_e; 46 | 47 | /** 48 | * Driver for nRF24L01(+) 2.4GHz Wireless Transceiver 49 | */ 50 | 51 | class RF24 52 | { 53 | private: 54 | #ifdef SOFTSPI 55 | SoftSPI spi; 56 | #elif defined (SPI_UART) 57 | SPIUARTClass uspi; 58 | #endif 59 | 60 | #if defined (RF24_LINUX) || defined (XMEGA_D3) /* XMEGA can use SPI class */ 61 | SPI spi; 62 | #endif 63 | #if defined (MRAA) 64 | GPIO gpio; 65 | #endif 66 | 67 | uint8_t ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */ 68 | uint8_t csn_pin; /**< SPI Chip select */ 69 | uint16_t spi_speed; /**< SPI Bus Speed */ 70 | #if defined (RF24_LINUX) || defined (XMEGA_D3) 71 | uint8_t spi_rxbuff[32+1] ; //SPI receive buffer (payload max 32 bytes) 72 | uint8_t spi_txbuff[32+1] ; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command) 73 | #endif 74 | bool p_variant; /* False for RF24L01 and true for RF24L01P */ 75 | uint8_t payload_size; /**< Fixed size of payloads */ 76 | bool dynamic_payloads_enabled; /**< Whether dynamic payloads are enabled. */ 77 | uint8_t pipe0_reading_address[5]; /**< Last address set on pipe 0 for reading. */ 78 | uint8_t addr_width; /**< The address width to use - 3,4 or 5 bytes. */ 79 | 80 | 81 | protected: 82 | /** 83 | * SPI transactions 84 | * 85 | * Common code for SPI transactions including CSN toggle 86 | * 87 | */ 88 | inline void beginTransaction(); 89 | 90 | inline void endTransaction(); 91 | 92 | public: 93 | 94 | /** 95 | * @name Primary public interface 96 | * 97 | * These are the main methods you need to operate the chip 98 | */ 99 | /**@{*/ 100 | 101 | /** 102 | * Arduino Constructor 103 | * 104 | * Creates a new instance of this driver. Before using, you create an instance 105 | * and send in the unique pins that this chip is connected to. 106 | * 107 | * @param _cepin The pin attached to Chip Enable on the RF module 108 | * @param _cspin The pin attached to Chip Select 109 | */ 110 | RF24(uint8_t _cepin, uint8_t _cspin); 111 | //#if defined (RF24_LINUX) 112 | 113 | /** 114 | * Optional Linux Constructor 115 | * 116 | * Creates a new instance of this driver. Before using, you create an instance 117 | * and send in the unique pins that this chip is connected to. 118 | * 119 | * @param _cepin The pin attached to Chip Enable on the RF module 120 | * @param _cspin The pin attached to Chip Select 121 | * @param spispeed For RPi, the SPI speed in MHZ ie: BCM2835_SPI_SPEED_8MHZ 122 | */ 123 | 124 | RF24(uint8_t _cepin, uint8_t _cspin, uint32_t spispeed ); 125 | //#endif 126 | 127 | #if defined (RF24_LINUX) 128 | virtual ~RF24() {}; 129 | #endif 130 | 131 | /** 132 | * Begin operation of the chip 133 | * 134 | * Call this in setup(), before calling any other methods. 135 | * @code radio.begin() @endcode 136 | */ 137 | bool begin(void); 138 | 139 | /** 140 | * Start listening on the pipes opened for reading. 141 | * 142 | * 1. Be sure to call openReadingPipe() first. 143 | * 2. Do not call write() while in this mode, without first calling stopListening(). 144 | * 3. Call available() to check for incoming traffic, and read() to get it. 145 | * 146 | * @code 147 | * Open reading pipe 1 using address CCCECCCECC 148 | * 149 | * byte address[] = { 0xCC,0xCE,0xCC,0xCE,0xCC }; 150 | * radio.openReadingPipe(1,address); 151 | * radio.startListening(); 152 | * @endcode 153 | */ 154 | void startListening(void); 155 | 156 | /** 157 | * Stop listening for incoming messages, and switch to transmit mode. 158 | * 159 | * Do this before calling write(). 160 | * @code 161 | * radio.stopListening(); 162 | * radio.write(&data,sizeof(data)); 163 | * @endcode 164 | */ 165 | void stopListening(void); 166 | 167 | /** 168 | * Check whether there are bytes available to be read 169 | * @code 170 | * if(radio.available()){ 171 | * radio.read(&data,sizeof(data)); 172 | * } 173 | * @endcode 174 | * @return True if there is a payload available, false if none is 175 | */ 176 | bool available(void); 177 | 178 | /** 179 | * Read the available payload 180 | * 181 | * The size of data read is the fixed payload size, see getPayloadSize() 182 | * 183 | * @note I specifically chose 'void*' as a data type to make it easier 184 | * for beginners to use. No casting needed. 185 | * 186 | * @note No longer boolean. Use available to determine if packets are 187 | * available. Interrupt flags are now cleared during reads instead of 188 | * when calling available(). 189 | * 190 | * @param buf Pointer to a buffer where the data should be written 191 | * @param len Maximum number of bytes to read into the buffer 192 | * 193 | * @code 194 | * if(radio.available()){ 195 | * radio.read(&data,sizeof(data)); 196 | * } 197 | * @endcode 198 | * @return No return value. Use available(). 199 | */ 200 | uint8_t read( void* buf, uint8_t len ); 201 | 202 | /** 203 | * Be sure to call openWritingPipe() first to set the destination 204 | * of where to write to. 205 | * 206 | * This blocks until the message is successfully acknowledged by 207 | * the receiver or the timeout/retransmit maxima are reached. In 208 | * the current configuration, the max delay here is 60-70ms. 209 | * 210 | * The maximum size of data written is the fixed payload size, see 211 | * getPayloadSize(). However, you can write less, and the remainder 212 | * will just be filled with zeroes. 213 | * 214 | * TX/RX/RT interrupt flags will be cleared every time write is called 215 | * 216 | * @param buf Pointer to the data to be sent 217 | * @param len Number of bytes to be sent 218 | * 219 | * @code 220 | * radio.stopListening(); 221 | * radio.write(&data,sizeof(data)); 222 | * @endcode 223 | * @return True if the payload was delivered successfully false if not 224 | */ 225 | bool write( const void* buf, uint8_t len ); 226 | 227 | /** 228 | * New: Open a pipe for writing via byte array. Old addressing format retained 229 | * for compatibility. 230 | * 231 | * Only one writing pipe can be open at once, but you can change the address 232 | * you'll write to. Call stopListening() first. 233 | * 234 | * Addresses are assigned via a byte array, default is 5 byte address length 235 | s * 236 | * @code 237 | * uint8_t addresses[][6] = {"1Node","2Node"}; 238 | * radio.openWritingPipe(addresses[0]); 239 | * @endcode 240 | * @code 241 | * uint8_t address[] = { 0xCC,0xCE,0xCC,0xCE,0xCC }; 242 | * radio.openWritingPipe(address); 243 | * address[0] = 0x33; 244 | * radio.openReadingPipe(1,address); 245 | * @endcode 246 | * @see setAddressWidth 247 | * 248 | * @param address The address of the pipe to open. Coordinate these pipe 249 | * addresses amongst nodes on the network. 250 | */ 251 | 252 | void openWritingPipe(const uint8_t *address); 253 | 254 | /** 255 | * Open a pipe for reading 256 | * 257 | * Up to 6 pipes can be open for reading at once. Open all the required 258 | * reading pipes, and then call startListening(). 259 | * 260 | * @see openWritingPipe 261 | * @see setAddressWidth 262 | * 263 | * @note Pipes 0 and 1 will store a full 5-byte address. Pipes 2-5 will technically 264 | * only store a single byte, borrowing up to 4 additional bytes from pipe #1 per the 265 | * assigned address width. 266 | * @warning Pipes 1-5 should share the same address, except the first byte. 267 | * Only the first byte in the array should be unique, e.g. 268 | * @code 269 | * uint8_t addresses[][6] = {"1Node","2Node"}; 270 | * openReadingPipe(1,addresses[0]); 271 | * openReadingPipe(2,addresses[1]); 272 | * @endcode 273 | * 274 | * @warning Pipe 0 is also used by the writing pipe. So if you open 275 | * pipe 0 for reading, and then startListening(), it will overwrite the 276 | * writing pipe. Ergo, do an openWritingPipe() again before write(). 277 | * 278 | * @param number Which pipe# to open, 0-5. 279 | * @param address The 24, 32 or 40 bit address of the pipe to open. 280 | */ 281 | 282 | void openReadingPipe(uint8_t number, const uint8_t *address); 283 | 284 | /**@}*/ 285 | /** 286 | * @name Advanced Operation 287 | * 288 | * Methods you can use to drive the chip in more advanced ways 289 | */ 290 | /**@{*/ 291 | 292 | /** 293 | * Print a giant block of debugging information to stdout 294 | * 295 | * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h 296 | * The printf.h file is included with the library for Arduino. 297 | * @code 298 | * #include 299 | * setup(){ 300 | * Serial.begin(115200); 301 | * printf_begin(); 302 | * ... 303 | * } 304 | * @endcode 305 | */ 306 | void printDetails(void); 307 | 308 | /** 309 | * Test whether there are bytes available to be read in the 310 | * FIFO buffers. 311 | * 312 | * @param[out] pipe_num Which pipe has the payload available 313 | * 314 | * @code 315 | * uint8_t pipeNum; 316 | * if(radio.available(&pipeNum)){ 317 | * radio.read(&data,sizeof(data)); 318 | * Serial.print("Got data on pipe"); 319 | * Serial.println(pipeNum); 320 | * } 321 | * @endcode 322 | * @return True if there is a payload available, false if none is 323 | */ 324 | bool available(uint8_t* pipe_num); 325 | 326 | /** 327 | * Check if the radio needs to be read. Can be used to prevent data loss 328 | * @return True if all three 32-byte radio buffers are full 329 | */ 330 | bool rxFifoFull(); 331 | 332 | /** 333 | * Enter low-power mode 334 | * 335 | * To return to normal power mode, call powerUp(). 336 | * 337 | * @note After calling startListening(), a basic radio will consume about 13.5mA 338 | * at max PA level. 339 | * During active transmission, the radio will consume about 11.5mA, but this will 340 | * be reduced to 26uA (.026mA) between sending. 341 | * In full powerDown mode, the radio will consume approximately 900nA (.0009mA) 342 | * 343 | * @code 344 | * radio.powerDown(); 345 | * avr_enter_sleep_mode(); // Custom function to sleep the device 346 | * radio.powerUp(); 347 | * @endcode 348 | */ 349 | void powerDown(void); 350 | 351 | /** 352 | * Leave low-power mode - required for normal radio operation after calling powerDown() 353 | * 354 | * To return to low power mode, call powerDown(). 355 | * @note This will take up to 5ms for maximum compatibility 356 | */ 357 | void powerUp(void) ; 358 | 359 | /** 360 | * Write for single NOACK writes. Optionally disables acknowledgements/autoretries for a single write. 361 | * 362 | * @note enableDynamicAck() must be called to enable this feature 363 | * 364 | * Can be used with enableAckPayload() to request a response 365 | * @see enableDynamicAck() 366 | * @see setAutoAck() 367 | * @see write() 368 | * 369 | * @param buf Pointer to the data to be sent 370 | * @param len Number of bytes to be sent 371 | * @param multicast Request ACK (0), NOACK (1) 372 | */ 373 | bool write( const void* buf, uint8_t len, const bool multicast ); 374 | 375 | /** 376 | * This will not block until the 3 FIFO buffers are filled with data. 377 | * Once the FIFOs are full, writeFast will simply wait for success or 378 | * timeout, and return 1 or 0 respectively. From a user perspective, just 379 | * keep trying to send the same data. The library will keep auto retrying 380 | * the current payload using the built in functionality. 381 | * @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto 382 | * retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO 383 | * to clear by issuing txStandBy() or ensure appropriate time between transmissions. 384 | * 385 | * @code 386 | * Example (Partial blocking): 387 | * 388 | * radio.writeFast(&buf,32); // Writes 1 payload to the buffers 389 | * txStandBy(); // Returns 0 if failed. 1 if success. Blocks only until MAX_RT timeout or success. Data flushed on fail. 390 | * 391 | * radio.writeFast(&buf,32); // Writes 1 payload to the buffers 392 | * txStandBy(1000); // Using extended timeouts, returns 1 if success. Retries failed payloads for 1 seconds before returning 0. 393 | * @endcode 394 | * 395 | * @see txStandBy() 396 | * @see write() 397 | * @see writeBlocking() 398 | * 399 | * @param buf Pointer to the data to be sent 400 | * @param len Number of bytes to be sent 401 | * @return True if the payload was delivered successfully false if not 402 | */ 403 | bool writeFast( const void* buf, uint8_t len ); 404 | 405 | /** 406 | * WriteFast for single NOACK writes. Disables acknowledgements/autoretries for a single write. 407 | * 408 | * @note enableDynamicAck() must be called to enable this feature 409 | * @see enableDynamicAck() 410 | * @see setAutoAck() 411 | * 412 | * @param buf Pointer to the data to be sent 413 | * @param len Number of bytes to be sent 414 | * @param multicast Request ACK (0) or NOACK (1) 415 | */ 416 | bool writeFast( const void* buf, uint8_t len, const bool multicast ); 417 | 418 | /** 419 | * This function extends the auto-retry mechanism to any specified duration. 420 | * It will not block until the 3 FIFO buffers are filled with data. 421 | * If so the library will auto retry until a new payload is written 422 | * or the user specified timeout period is reached. 423 | * @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto 424 | * retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO 425 | * to clear by issuing txStandBy() or ensure appropriate time between transmissions. 426 | * 427 | * @code 428 | * Example (Full blocking): 429 | * 430 | * radio.writeBlocking(&buf,32,1000); //Wait up to 1 second to write 1 payload to the buffers 431 | * txStandBy(1000); //Wait up to 1 second for the payload to send. Return 1 if ok, 0 if failed. 432 | * //Blocks only until user timeout or success. Data flushed on fail. 433 | * @endcode 434 | * @note If used from within an interrupt, the interrupt should be disabled until completion, and sei(); called to enable millis(). 435 | * @see txStandBy() 436 | * @see write() 437 | * @see writeFast() 438 | * 439 | * @param buf Pointer to the data to be sent 440 | * @param len Number of bytes to be sent 441 | * @param timeout User defined timeout in milliseconds. 442 | * @return True if the payload was loaded into the buffer successfully false if not 443 | */ 444 | bool writeBlocking( const void* buf, uint8_t len, uint32_t timeout ); 445 | 446 | /** 447 | * This function should be called as soon as transmission is finished to 448 | * drop the radio back to STANDBY-I mode. If not issued, the radio will 449 | * remain in STANDBY-II mode which, per the data sheet, is not a recommended 450 | * operating mode. 451 | * 452 | * @note When transmitting data in rapid succession, it is still recommended by 453 | * the manufacturer to drop the radio out of TX or STANDBY-II mode if there is 454 | * time enough between sends for the FIFOs to empty. This is not required if auto-ack 455 | * is enabled. 456 | * 457 | * Relies on built-in auto retry functionality. 458 | * 459 | * @code 460 | * Example (Partial blocking): 461 | * 462 | * radio.writeFast(&buf,32); 463 | * radio.writeFast(&buf,32); 464 | * radio.writeFast(&buf,32); //Fills the FIFO buffers up 465 | * bool ok = txStandBy(); //Returns 0 if failed. 1 if success. 466 | * //Blocks only until MAX_RT timeout or success. Data flushed on fail. 467 | * @endcode 468 | * @see txStandBy(unsigned long timeout) 469 | * @return True if transmission is successful 470 | * 471 | */ 472 | bool txStandBy(); 473 | 474 | /** 475 | * This function allows extended blocking and auto-retries per a user defined timeout 476 | * @code 477 | * Fully Blocking Example: 478 | * 479 | * radio.writeFast(&buf,32); 480 | * radio.writeFast(&buf,32); 481 | * radio.writeFast(&buf,32); //Fills the FIFO buffers up 482 | * bool ok = txStandBy(1000); //Returns 0 if failed after 1 second of retries. 1 if success. 483 | * //Blocks only until user defined timeout or success. Data flushed on fail. 484 | * @endcode 485 | * @note If used from within an interrupt, the interrupt should be disabled until completion, and sei(); called to enable millis(). 486 | * @param timeout Number of milliseconds to retry failed payloads 487 | * @return True if transmission is successful 488 | * 489 | */ 490 | bool txStandBy(uint32_t timeout, bool startTx = 0); 491 | 492 | /** 493 | * Write an ack payload for the specified pipe 494 | * 495 | * The next time a message is received on @p pipe, the data in @p buf will 496 | * be sent back in the acknowledgement. 497 | * @see enableAckPayload() 498 | * @see enableDynamicPayloads() 499 | * @warning Only three of these can be pending at any time as there are only 3 FIFO buffers.
Dynamic payloads must be enabled. 500 | * @note Ack payloads are handled automatically by the radio chip when a payload is received. Users should generally 501 | * write an ack payload as soon as startListening() is called, so one is available when a regular payload is received. 502 | * @note Ack payloads are dynamic payloads. This only works on pipes 0&1 by default. Call 503 | * enableDynamicPayloads() to enable on all pipes. 504 | * 505 | * @param pipe Which pipe# (typically 1-5) will get this response. 506 | * @param buf Pointer to data that is sent 507 | * @param len Length of the data to send, up to 32 bytes max. Not affected 508 | * by the static payload set by setPayloadSize(). 509 | */ 510 | void writeAckPayload(uint8_t pipe, const void* buf, uint8_t len); 511 | 512 | /** 513 | * Determine if an ack payload was received in the most recent call to 514 | * write(). The regular available() can also be used. 515 | * 516 | * Call read() to retrieve the ack payload. 517 | * 518 | * @return True if an ack payload is available. 519 | */ 520 | bool isAckPayloadAvailable(void); 521 | 522 | /** 523 | * Call this when you get an interrupt to find out why 524 | * 525 | * Tells you what caused the interrupt, and clears the state of 526 | * interrupts. 527 | * 528 | * @param[out] tx_ok The send was successful (TX_DS) 529 | * @param[out] tx_fail The send failed, too many retries (MAX_RT) 530 | * @param[out] rx_ready There is a message waiting to be read (RX_DS) 531 | */ 532 | void whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready); 533 | 534 | /** 535 | * Non-blocking write to the open writing pipe used for buffered writes 536 | * 537 | * @note Optimization: This function now leaves the CE pin high, so the radio 538 | * will remain in TX or STANDBY-II Mode until a txStandBy() command is issued. Can be used as an alternative to startWrite() 539 | * if writing multiple payloads at once. 540 | * @warning It is important to never keep the nRF24L01 in TX mode with FIFO full for more than 4ms at a time. If the auto 541 | * retransmit/autoAck is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO 542 | * to clear by issuing txStandBy() or ensure appropriate time between transmissions. 543 | * 544 | * @see write() 545 | * @see writeFast() 546 | * @see startWrite() 547 | * @see writeBlocking() 548 | * 549 | * For single noAck writes see: 550 | * @see enableDynamicAck() 551 | * @see setAutoAck() 552 | * 553 | * @param buf Pointer to the data to be sent 554 | * @param len Number of bytes to be sent 555 | * @param multicast Request ACK (0) or NOACK (1) 556 | * @return True if the payload was delivered successfully false if not 557 | */ 558 | void startFastWrite( const void* buf, uint8_t len, const bool multicast, bool startTx = 1 ); 559 | 560 | /** 561 | * Non-blocking write to the open writing pipe 562 | * 563 | * Just like write(), but it returns immediately. To find out what happened 564 | * to the send, catch the IRQ and then call whatHappened(). 565 | * 566 | * @see write() 567 | * @see writeFast() 568 | * @see startFastWrite() 569 | * @see whatHappened() 570 | * 571 | * For single noAck writes see: 572 | * @see enableDynamicAck() 573 | * @see setAutoAck() 574 | * 575 | * @param buf Pointer to the data to be sent 576 | * @param len Number of bytes to be sent 577 | * @param multicast Request ACK (0) or NOACK (1) 578 | * 579 | */ 580 | void startWrite( const void* buf, uint8_t len, const bool multicast ); 581 | 582 | /** 583 | * This function is mainly used internally to take advantage of the auto payload 584 | * re-use functionality of the chip, but can be beneficial to users as well. 585 | * 586 | * The function will instruct the radio to re-use the data in the FIFO buffers, 587 | * and instructs the radio to re-send once the timeout limit has been reached. 588 | * Used by writeFast and writeBlocking to initiate retries when a TX failure 589 | * occurs. Retries are automatically initiated except with the standard write(). 590 | * This way, data is not flushed from the buffer until switching between modes. 591 | * 592 | * @note This is to be used AFTER auto-retry fails if wanting to resend 593 | * using the built-in payload reuse features. 594 | * After issuing reUseTX(), it will keep reending the same payload forever or until 595 | * a payload is written to the FIFO, or a flush_tx command is given. 596 | */ 597 | void reUseTX(); 598 | 599 | /** 600 | * Empty the transmit buffer. This is generally not required in standard operation. 601 | * May be required in specific cases after stopListening() , if operating at 250KBPS data rate. 602 | * 603 | * @return Current value of status register 604 | */ 605 | uint8_t flush_tx(void); 606 | 607 | /** 608 | * Test whether there was a carrier on the line for the 609 | * previous listening period. 610 | * 611 | * Useful to check for interference on the current channel. 612 | * 613 | * @return true if was carrier, false if not 614 | */ 615 | bool testCarrier(void); 616 | 617 | /** 618 | * Test whether a signal (carrier or otherwise) greater than 619 | * or equal to -64dBm is present on the channel. Valid only 620 | * on nRF24L01P (+) hardware. On nRF24L01, use testCarrier(). 621 | * 622 | * Useful to check for interference on the current channel and 623 | * channel hopping strategies. 624 | * 625 | * @code 626 | * bool goodSignal = radio.testRPD(); 627 | * if(radio.available()){ 628 | * Serial.println(goodSignal ? "Strong signal > 64dBm" : "Weak signal < 64dBm" ); 629 | * radio.read(0,0); 630 | * } 631 | * @endcode 632 | * @return true if signal => -64dBm, false if not 633 | */ 634 | bool testRPD(void) ; 635 | 636 | /** 637 | * Test whether this is a real radio, or a mock shim for 638 | * debugging. Setting either pin to 0xff is the way to 639 | * indicate that this is not a real radio. 640 | * 641 | * @return true if this is a legitimate radio 642 | */ 643 | bool isValid() { return ce_pin != 0xff && csn_pin != 0xff; } 644 | 645 | /** 646 | * Close a pipe after it has been previously opened. 647 | * Can be safely called without having previously opened a pipe. 648 | * @param pipe Which pipe # to close, 0-5. 649 | */ 650 | void closeReadingPipe( uint8_t pipe ) ; 651 | 652 | /** 653 | * Enable error detection by un-commenting #define FAILURE_HANDLING in RF24_config.h 654 | * If a failure has been detected, it usually indicates a hardware issue. By default the library 655 | * will cease operation when a failure is detected. 656 | * This should allow advanced users to detect and resolve intermittent hardware issues. 657 | * 658 | * In most cases, the radio must be re-enabled via radio.begin(); and the appropriate settings 659 | * applied after a failure occurs, if wanting to re-enable the device immediately. 660 | * 661 | * Usage: (Failure handling must be enabled per above) 662 | * @code 663 | * if(radio.failureDetected){ 664 | * radio.begin(); // Attempt to re-configure the radio with defaults 665 | * radio.failureDetected = 0; // Reset the detection value 666 | * radio.openWritingPipe(addresses[1]); // Re-configure pipe addresses 667 | * radio.openReadingPipe(1,addresses[0]); 668 | * report_failure(); // Blink leds, send a message, etc. to indicate failure 669 | * } 670 | * @endcode 671 | */ 672 | //#if defined (FAILURE_HANDLING) 673 | bool failureDetected; 674 | //#endif 675 | 676 | /**@}*/ 677 | 678 | /**@}*/ 679 | /** 680 | * @name Optional Configurators 681 | * 682 | * Methods you can use to get or set the configuration of the chip. 683 | * None are required. Calling begin() sets up a reasonable set of 684 | * defaults. 685 | */ 686 | /**@{*/ 687 | 688 | /** 689 | * Set the address width from 3 to 5 bytes (24, 32 or 40 bit) 690 | * 691 | * @param a_width The address width to use: 3,4 or 5 692 | */ 693 | 694 | void setAddressWidth(uint8_t a_width); 695 | 696 | /** 697 | * Set the number and delay of retries upon failed submit 698 | * 699 | * @param delay How long to wait between each retry, in multiples of 250us, 700 | * max is 15. 0 means 250us, 15 means 4000us. 701 | * @param count How many retries before giving up, max 15 702 | */ 703 | void setRetries(uint8_t delay, uint8_t count); 704 | 705 | /** 706 | * Set RF communication channel 707 | * 708 | * @param channel Which RF channel to communicate on, 0-125 709 | */ 710 | void setChannel(uint8_t channel); 711 | 712 | /** 713 | * Get RF communication channel 714 | * 715 | * @return The currently configured RF Channel 716 | */ 717 | uint8_t getChannel(void); 718 | 719 | /** 720 | * Set Static Payload Size 721 | * 722 | * This implementation uses a pre-stablished fixed payload size for all 723 | * transmissions. If this method is never called, the driver will always 724 | * transmit the maximum payload size (32 bytes), no matter how much 725 | * was sent to write(). 726 | * 727 | * @todo Implement variable-sized payloads feature 728 | * 729 | * @param size The number of bytes in the payload 730 | */ 731 | void setPayloadSize(uint8_t size); 732 | 733 | /** 734 | * Get Static Payload Size 735 | * 736 | * @see setPayloadSize() 737 | * 738 | * @return The number of bytes in the payload 739 | */ 740 | uint8_t getPayloadSize(void); 741 | 742 | /** 743 | * Get Dynamic Payload Size 744 | * 745 | * For dynamic payloads, this pulls the size of the payload off 746 | * the chip 747 | * 748 | * @note Corrupt packets are now detected and flushed per the 749 | * manufacturer. 750 | * @code 751 | * if(radio.available()){ 752 | * if(radio.getDynamicPayloadSize() < 1){ 753 | * // Corrupt payload has been flushed 754 | * return; 755 | * } 756 | * radio.read(&data,sizeof(data)); 757 | * } 758 | * @endcode 759 | * 760 | * @return Payload length of last-received dynamic payload 761 | */ 762 | uint8_t getDynamicPayloadSize(void); 763 | 764 | /** 765 | * Enable custom payloads on the acknowledge packets 766 | * 767 | * Ack payloads are a handy way to return data back to senders without 768 | * manually changing the radio modes on both units. 769 | * 770 | * @note Ack payloads are dynamic payloads. This only works on pipes 0&1 by default. Call 771 | * enableDynamicPayloads() to enable on all pipes. 772 | */ 773 | void enableAckPayload(void); 774 | 775 | /** 776 | * Enable dynamically-sized payloads 777 | * 778 | * This way you don't always have to send large packets just to send them 779 | * once in a while. This enables dynamic payloads on ALL pipes. 780 | * 781 | */ 782 | void enableDynamicPayloads(void); 783 | 784 | /** 785 | * Enable dynamic ACKs (single write multicast or unicast) for chosen messages 786 | * 787 | * @note To enable full multicast or per-pipe multicast, use setAutoAck() 788 | * 789 | * @warning This MUST be called prior to attempting single write NOACK calls 790 | * @code 791 | * radio.enableDynamicAck(); 792 | * radio.write(&data,32,1); // Sends a payload with no acknowledgement requested 793 | * radio.write(&data,32,0); // Sends a payload using auto-retry/autoACK 794 | * @endcode 795 | */ 796 | void enableDynamicAck(); 797 | 798 | /** 799 | * Determine whether the hardware is an nRF24L01+ or not. 800 | * 801 | * @return true if the hardware is nRF24L01+ (or compatible) and false 802 | * if its not. 803 | */ 804 | bool isPVariant(void) ; 805 | 806 | /** 807 | * Enable or disable auto-acknowlede packets 808 | * 809 | * This is enabled by default, so it's only needed if you want to turn 810 | * it off for some reason. 811 | * 812 | * @param enable Whether to enable (true) or disable (false) auto-acks 813 | */ 814 | void setAutoAck(bool enable); 815 | 816 | /** 817 | * Enable or disable auto-acknowlede packets on a per pipeline basis. 818 | * 819 | * AA is enabled by default, so it's only needed if you want to turn 820 | * it off/on for some reason on a per pipeline basis. 821 | * 822 | * @param pipe Which pipeline to modify 823 | * @param enable Whether to enable (true) or disable (false) auto-acks 824 | */ 825 | void setAutoAck( uint8_t pipe, bool enable ) ; 826 | 827 | /** 828 | * Set Power Amplifier (PA) level to one of four levels: 829 | * RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX 830 | * 831 | * The power levels correspond to the following output levels respectively: 832 | * NRF24L01: -18dBm, -12dBm,-6dBM, and 0dBm 833 | * 834 | * SI24R1: -6dBm, 0dBm, 3dBM, and 7dBm. 835 | * 836 | * @param level Desired PA level. 837 | */ 838 | void setPALevel ( uint8_t level ); 839 | 840 | /** 841 | * Fetches the current PA level. 842 | * 843 | * NRF24L01: -18dBm, -12dBm, -6dBm and 0dBm 844 | * SI24R1: -6dBm, 0dBm, 3dBm, 7dBm 845 | * 846 | * @return Returns values 0 to 3 representing the PA Level. 847 | */ 848 | uint8_t getPALevel( void ); 849 | 850 | /** 851 | * Set the transmission data rate 852 | * 853 | * @warning setting RF24_250KBPS will fail for non-plus units 854 | * 855 | * @param speed RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps 856 | * @return true if the change was successful 857 | */ 858 | bool setDataRate(rf24_datarate_e speed); 859 | 860 | /** 861 | * Fetches the transmission data rate 862 | * 863 | * @return Returns the hardware's currently configured datarate. The value 864 | * is one of 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS, as defined in the 865 | * rf24_datarate_e enum. 866 | */ 867 | rf24_datarate_e getDataRate( void ) ; 868 | 869 | /** 870 | * Set the CRC length 871 | *
CRC checking cannot be disabled if auto-ack is enabled 872 | * @param length RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit 873 | */ 874 | void setCRCLength(rf24_crclength_e length); 875 | 876 | /** 877 | * Get the CRC length 878 | *
CRC checking cannot be disabled if auto-ack is enabled 879 | * @return RF24_CRC_DISABLED if disabled or RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit 880 | */ 881 | rf24_crclength_e getCRCLength(void); 882 | 883 | /** 884 | * Disable CRC validation 885 | * 886 | * @warning CRC cannot be disabled if auto-ack/ESB is enabled. 887 | */ 888 | void disableCRC( void ) ; 889 | 890 | /** 891 | * The radio will generate interrupt signals when a transmission is complete, 892 | * a transmission fails, or a payload is received. This allows users to mask 893 | * those interrupts to prevent them from generating a signal on the interrupt 894 | * pin. Interrupts are enabled on the radio chip by default. 895 | * 896 | * @code 897 | * Mask all interrupts except the receive interrupt: 898 | * 899 | * radio.maskIRQ(1,1,0); 900 | * @endcode 901 | * 902 | * @param tx_ok Mask transmission complete interrupts 903 | * @param tx_fail Mask transmit failure interrupts 904 | * @param rx_ready Mask payload received interrupts 905 | */ 906 | void maskIRQ(bool tx_ok,bool tx_fail,bool rx_ready); 907 | 908 | /** 909 | * 910 | * The driver will delay for this duration when stopListening() is called 911 | * 912 | * When responding to payloads, faster devices like ARM(RPi) are much faster than Arduino: 913 | * 1. Arduino sends data to RPi, switches to RX mode 914 | * 2. The RPi receives the data, switches to TX mode and sends before the Arduino radio is in RX mode 915 | * 3. If AutoACK is disabled, this can be set as low as 0. If AA/ESB enabled, set to 100uS minimum on RPi 916 | * 917 | * @warning If set to 0, ensure 130uS delay after stopListening() and before any sends 918 | */ 919 | 920 | uint32_t txDelay; 921 | 922 | /** 923 | * 924 | * On all devices but Linux and ATTiny, a small delay is added to the CSN toggling function 925 | * 926 | * This is intended to minimise the speed of SPI polling due to radio commands 927 | * 928 | * If using interrupts or timed requests, this can be set to 0 Default:5 929 | */ 930 | 931 | uint32_t csDelay; 932 | 933 | /**@}*/ 934 | /** 935 | * @name Deprecated 936 | * 937 | * Methods provided for backwards compabibility. 938 | */ 939 | /**@{*/ 940 | 941 | 942 | /** 943 | * Open a pipe for reading 944 | * @note For compatibility with old code only, see new function 945 | * 946 | * @warning Pipes 1-5 should share the first 32 bits. 947 | * Only the least significant byte should be unique, e.g. 948 | * @code 949 | * openReadingPipe(1,0xF0F0F0F0AA); 950 | * openReadingPipe(2,0xF0F0F0F066); 951 | * @endcode 952 | * 953 | * @warning Pipe 0 is also used by the writing pipe. So if you open 954 | * pipe 0 for reading, and then startListening(), it will overwrite the 955 | * writing pipe. Ergo, do an openWritingPipe() again before write(). 956 | * 957 | * @param number Which pipe# to open, 0-5. 958 | * @param address The 40-bit address of the pipe to open. 959 | */ 960 | void openReadingPipe(uint8_t number, uint64_t address); 961 | 962 | /** 963 | * Open a pipe for writing 964 | * @note For compatibility with old code only, see new function 965 | * 966 | * Addresses are 40-bit hex values, e.g.: 967 | * 968 | * @code 969 | * openWritingPipe(0xF0F0F0F0F0); 970 | * @endcode 971 | * 972 | * @param address The 40-bit address of the pipe to open. 973 | */ 974 | void openWritingPipe(uint64_t address); 975 | 976 | /** 977 | * Empty the receive buffer 978 | * 979 | * @return Current value of status register 980 | */ 981 | uint8_t flush_rx(void); 982 | 983 | private: 984 | 985 | /** 986 | * @name Low-level internal interface. 987 | * 988 | * Protected methods that address the chip directly. Regular users cannot 989 | * ever call these. They are documented for completeness and for developers who 990 | * may want to extend this class. 991 | */ 992 | /**@{*/ 993 | 994 | /** 995 | * Set chip select pin 996 | * 997 | * Running SPI bus at PI_CLOCK_DIV2 so we don't waste time transferring data 998 | * and best of all, we make use of the radio's FIFO buffers. A lower speed 999 | * means we're less likely to effectively leverage our FIFOs and pay a higher 1000 | * AVR runtime cost as toll. 1001 | * 1002 | * @param mode HIGH to take this unit off the SPI bus, LOW to put it on 1003 | */ 1004 | void csn(bool mode); 1005 | 1006 | /** 1007 | * Set chip enable 1008 | * 1009 | * @param level HIGH to actively begin transmission or LOW to put in standby. Please see data sheet 1010 | * for a much more detailed description of this pin. 1011 | */ 1012 | void ce(bool level); 1013 | 1014 | /** 1015 | * Read a chunk of data in from a register 1016 | * 1017 | * @param reg Which register. Use constants from nRF24L01.h 1018 | * @param buf Where to put the data 1019 | * @param len How many bytes of data to transfer 1020 | * @return Current value of status register 1021 | */ 1022 | uint8_t read_register(uint8_t reg, uint8_t* buf, uint8_t len); 1023 | 1024 | /** 1025 | * Read single byte from a register 1026 | * 1027 | * @param reg Which register. Use constants from nRF24L01.h 1028 | * @return Current value of register @p reg 1029 | */ 1030 | uint8_t read_register(uint8_t reg); 1031 | 1032 | /** 1033 | * Write a chunk of data to a register 1034 | * 1035 | * @param reg Which register. Use constants from nRF24L01.h 1036 | * @param buf Where to get the data 1037 | * @param len How many bytes of data to transfer 1038 | * @return Current value of status register 1039 | */ 1040 | uint8_t write_register(uint8_t reg, const uint8_t* buf, uint8_t len); 1041 | 1042 | /** 1043 | * Write a single byte to a register 1044 | * 1045 | * @param reg Which register. Use constants from nRF24L01.h 1046 | * @param value The new value to write 1047 | * @return Current value of status register 1048 | */ 1049 | uint8_t write_register(uint8_t reg, uint8_t value); 1050 | 1051 | /** 1052 | * Write the transmit payload 1053 | * 1054 | * The size of data written is the fixed payload size, see getPayloadSize() 1055 | * 1056 | * @param buf Where to get the data 1057 | * @param len Number of bytes to be sent 1058 | * @return Current value of status register 1059 | */ 1060 | uint8_t write_payload(const void* buf, uint8_t len, const uint8_t writeType); 1061 | 1062 | /** 1063 | * Read the receive payload 1064 | * 1065 | * The size of data read is the fixed payload size, see getPayloadSize() 1066 | * 1067 | * @param buf Where to put the data 1068 | * @param len Maximum number of bytes to read 1069 | * @return Current value of status register 1070 | */ 1071 | uint8_t read_payload(void* buf, uint8_t len); 1072 | 1073 | /** 1074 | * Retrieve the current status of the chip 1075 | * 1076 | * @return Current value of status register 1077 | */ 1078 | uint8_t get_status(void); 1079 | 1080 | #if !defined (MINIMAL) 1081 | /** 1082 | * Decode and print the given status to stdout 1083 | * 1084 | * @param status Status value to print 1085 | * 1086 | * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h 1087 | */ 1088 | void print_status(uint8_t status); 1089 | 1090 | /** 1091 | * Decode and print the given 'observe_tx' value to stdout 1092 | * 1093 | * @param value The observe_tx value to print 1094 | * 1095 | * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h 1096 | */ 1097 | void print_observe_tx(uint8_t value); 1098 | 1099 | /** 1100 | * Print the name and value of an 8-bit register to stdout 1101 | * 1102 | * Optionally it can print some quantity of successive 1103 | * registers on the same line. This is useful for printing a group 1104 | * of related registers on one line. 1105 | * 1106 | * @param name Name of the register 1107 | * @param reg Which register. Use constants from nRF24L01.h 1108 | * @param qty How many successive registers to print 1109 | */ 1110 | void print_byte_register(const char* name, uint8_t reg, uint8_t qty = 1); 1111 | 1112 | /** 1113 | * Print the name and value of a 40-bit address register to stdout 1114 | * 1115 | * Optionally it can print some quantity of successive 1116 | * registers on the same line. This is useful for printing a group 1117 | * of related registers on one line. 1118 | * 1119 | * @param name Name of the register 1120 | * @param reg Which register. Use constants from nRF24L01.h 1121 | * @param qty How many successive registers to print 1122 | */ 1123 | void print_address_register(const char* name, uint8_t reg, uint8_t qty = 1); 1124 | #endif 1125 | /** 1126 | * Turn on or off the special features of the chip 1127 | * 1128 | * The chip has certain 'features' which are only available when the 'features' 1129 | * are enabled. See the datasheet for details. 1130 | */ 1131 | void toggle_features(void); 1132 | 1133 | /** 1134 | * Built in spi transfer function to simplify repeating code repeating code 1135 | */ 1136 | 1137 | uint8_t spiTrans(uint8_t cmd); 1138 | 1139 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 1140 | void errNotify(void); 1141 | #endif 1142 | 1143 | /**@}*/ 1144 | 1145 | }; 1146 | 1147 | 1148 | /** 1149 | * @example GettingStarted.ino 1150 | * For Arduino
1151 | * Updated: TMRh20 2014
1152 | * 1153 | * This is an example of how to use the RF24 class to communicate on a basic level. Configure and write this sketch to two 1154 | * different nodes. Put one of the nodes into 'transmit' mode by connecting with the serial monitor and
1155 | * sending a 'T'. The ping node sends the current time to the pong node, which responds by sending the value 1156 | * back. The ping node can then see how long the whole cycle took.
1157 | * @note For a more efficient call-response scenario see the GettingStarted_CallResponse.ino example. 1158 | * @note When switching between sketches, the radio may need to be powered down to clear settings that are not "un-set" otherwise 1159 | */ 1160 | 1161 | /** 1162 | * @example gettingstarted.cpp 1163 | * For Linux
1164 | * Updated: TMRh20 2014
1165 | * 1166 | * This is an example of how to use the RF24 class to communicate on a basic level. Configure and write this sketch to two 1167 | * different nodes. Put one of the nodes into 'transmit' mode by connecting with the serial monitor and
1168 | * sending a 'T'. The ping node sends the current time to the pong node, which responds by sending the value 1169 | * back. The ping node can then see how long the whole cycle took.
1170 | * @note For a more efficient call-response scenario see the GettingStarted_CallResponse.ino example. 1171 | */ 1172 | 1173 | /** 1174 | * @example GettingStarted_CallResponse.ino 1175 | * For Arduino
1176 | * New: TMRh20 2014
1177 | * 1178 | * This example continues to make use of all the normal functionality of the radios including 1179 | * the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
1180 | * This allows very fast call-response communication, with the responding radio never having to 1181 | * switch out of Primary Receiver mode to send back a payload, but having the option to switch to
1182 | * primary transmitter if wanting to initiate communication instead of respond to a commmunication. 1183 | */ 1184 | 1185 | /** 1186 | * @example gettingstarted_call_response.cpp 1187 | * For Linux
1188 | * New: TMRh20 2014
1189 | * 1190 | * This example continues to make use of all the normal functionality of the radios including 1191 | * the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
1192 | * This allows very fast call-response communication, with the responding radio never having to 1193 | * switch out of Primary Receiver mode to send back a payload, but having the option to switch to
1194 | * primary transmitter if wanting to initiate communication instead of respond to a commmunication. 1195 | */ 1196 | 1197 | /** 1198 | * @example GettingStarted_HandlingData.ino 1199 | * Dec 2014 - TMRh20
1200 | * 1201 | * This example demonstrates how to send multiple variables in a single payload and work with data. As usual, it is 1202 | * generally important to include an incrementing value like millis() in the payloads to prevent errors. 1203 | */ 1204 | 1205 | /** 1206 | * @example Transfer.ino 1207 | * For Arduino
1208 | * This example demonstrates half-rate transfer using the FIFO buffers
1209 | * 1210 | * It is an example of how to use the RF24 class. Write this sketch to two 1211 | * different nodes. Put one of the nodes into 'transmit' mode by connecting
1212 | * with the serial monitor and sending a 'T'. The data transfer will begin, 1213 | * with the receiver displaying the payload count. (32Byte Payloads)
1214 | */ 1215 | 1216 | /** 1217 | * @example transfer.cpp 1218 | * For Linux
1219 | * This example demonstrates half-rate transfer using the FIFO buffers
1220 | * 1221 | * It is an example of how to use the RF24 class. Write this sketch to two 1222 | * different nodes. Put one of the nodes into 'transmit' mode by connecting
1223 | * with the serial monitor and sending a 'T'. The data transfer will begin, 1224 | * with the receiver displaying the payload count. (32Byte Payloads)
1225 | */ 1226 | 1227 | /** 1228 | * @example TransferTimeouts.ino 1229 | * New: TMRh20
1230 | * This example demonstrates the use of and extended timeout period and 1231 | * auto-retries/auto-reUse to increase reliability in noisy or low signal scenarios.
1232 | * 1233 | * Write this sketch to two different nodes. Put one of the nodes into 'transmit' 1234 | * mode by connecting with the serial monitor and sending a 'T'. The data
1235 | * transfer will begin, with the receiver displaying the payload count and the 1236 | * data transfer rate. 1237 | */ 1238 | 1239 | /** 1240 | * @example starping.pde 1241 | * 1242 | * This sketch is a more complex example of using the RF24 library for Arduino. 1243 | * Deploy this on up to six nodes. Set one as the 'pong receiver' by tying the 1244 | * role_pin low, and the others will be 'ping transmit' units. The ping units 1245 | * unit will send out the value of millis() once a second. The pong unit will 1246 | * respond back with a copy of the value. Each ping unit can get that response 1247 | * back, and determine how long the whole cycle took. 1248 | * 1249 | * This example requires a bit more complexity to determine which unit is which. 1250 | * The pong receiver is identified by having its role_pin tied to ground. 1251 | * The ping senders are further differentiated by a byte in eeprom. 1252 | */ 1253 | 1254 | /** 1255 | * @example pingpair_ack.ino 1256 | * Update: TMRh20
1257 | * This example continues to make use of all the normal functionality of the radios including 1258 | * the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
1259 | * This allows very fast call-response communication, with the responding radio never having to 1260 | * switch out of Primary Receiver mode to send back a payload, but having the option to if wanting
1261 | * to initiate communication instead of respond to a commmunication. 1262 | */ 1263 | 1264 | /** 1265 | * @example pingpair_irq.ino 1266 | * Update: TMRh20
1267 | * This is an example of how to user interrupts to interact with the radio, and a demonstration 1268 | * of how to use them to sleep when receiving, and not miss any payloads.
1269 | * The pingpair_sleepy example expands on sleep functionality with a timed sleep option for the transmitter. 1270 | * Sleep functionality is built directly into my fork of the RF24Network library
1271 | */ 1272 | 1273 | /** 1274 | * @example pingpair_irq_simple.ino 1275 | * Dec 2014 - TMRh20
1276 | * This is an example of how to user interrupts to interact with the radio, with bidirectional communication. 1277 | */ 1278 | 1279 | /** 1280 | * @example pingpair_sleepy.ino 1281 | * Update: TMRh20
1282 | * This is an example of how to use the RF24 class to create a battery- 1283 | * efficient system. It is just like the GettingStarted_CallResponse example, but the
1284 | * ping node powers down the radio and sleeps the MCU after every 1285 | * ping/pong cycle, and the receiver sleeps between payloads.
1286 | */ 1287 | 1288 | /** 1289 | * @example rf24ping85.ino 1290 | * New: Contributed by https://github.com/tong67
1291 | * This is an example of how to use the RF24 class to communicate with ATtiny85 and other node.
1292 | */ 1293 | 1294 | /** 1295 | * @example timingSearch3pin.ino 1296 | * New: Contributed by https://github.com/tong67
1297 | * This is an example of how to determine the correct timing for ATtiny when using only 3-pins 1298 | */ 1299 | 1300 | /** 1301 | * @example pingpair_dyn.ino 1302 | * 1303 | * This is an example of how to use payloads of a varying (dynamic) size on Arduino. 1304 | */ 1305 | 1306 | /** 1307 | * @example pingpair_dyn.cpp 1308 | * 1309 | * This is an example of how to use payloads of a varying (dynamic) size on Linux. 1310 | */ 1311 | 1312 | /** 1313 | * @example pingpair_dyn.py 1314 | * 1315 | * This is a python example for RPi of how to use payloads of a varying (dynamic) size. 1316 | */ 1317 | 1318 | /** 1319 | * @example scanner.ino 1320 | * 1321 | * Example to detect interference on the various channels available. 1322 | * This is a good diagnostic tool to check whether you're picking a 1323 | * good channel for your application. 1324 | * 1325 | * Inspired by cpixip. 1326 | * See http://arduino.cc/forum/index.php/topic,54795.0.html 1327 | */ 1328 | 1329 | /** 1330 | * @mainpage Optimized High Speed Driver for nRF24L01(+) 2.4GHz Wireless Transceiver 1331 | * 1332 | * @section Goals Design Goals 1333 | * 1334 | * This library fork is designed to be... 1335 | * @li More compliant with the manufacturer specified operation of the chip, while allowing advanced users 1336 | * to work outside the recommended operation. 1337 | * @li Utilize the capabilities of the radio to their full potential via Arduino 1338 | * @li More reliable, responsive, bug-free and feature rich 1339 | * @li Easy for beginners to use, with well documented examples and features 1340 | * @li Consumed with a public interface that's similar to other Arduino standard libraries 1341 | * 1342 | * @section News News 1343 | * 1344 | * **Dec 2015**
1345 | * - ESP8266 support via Arduino IDE 1346 | * - Particle Photon/Core fork available 1347 | * - ATTiny2313/4313 support added 1348 | * - Python 3 support added 1349 | * - RF24 added to Arduino library manager 1350 | * - RF24 added to PlatformIO library manager 1351 | * 1352 | * **March 2015**
1353 | * - Uses SPI transactions on Arduino 1354 | * - New layout for easier portability: Break out defines & includes for individual platforms to RF24/utility 1355 | * - MRAA support added ( Galileo, Edison, etc) 1356 | * - Generic Linux support (SPIDEV) support 1357 | * - Support for RPi 2 added 1358 | * - Major Documentation cleanup & update (Move all docs to github.io) 1359 | * 1360 | * 1361 | * If issues are discovered with the documentation, please report them here 1362 | * 1363 | *
1364 | * @section Useful Useful References 1365 | * 1366 | * 1367 | * @li RF24 Class Documentation 1368 | * @li Download 1369 | * @li Source Code 1370 | * @li My Blog: RF24 Optimization Overview 1371 | * @li My Blog: RPi/Linux w/RF24Gateway 1372 | * @li Chip Datasheet 1373 | * 1374 | * **Additional Information and Add-ons** 1375 | * 1376 | * @li RF24Network: OSI Network Layer for multi-device communication. Create a home sensor network. 1377 | * @li RF24Mesh: Dynamic Mesh Layer for RF24Network 1378 | * @li RF24Ethernet: TCP/IP Radio Mesh Networking (shares Arduino Ethernet API) 1379 | * @li RF24Audio: Realtime Wireless Audio streaming 1380 | * @li All TMRh20 Documentation Main Page 1381 | * 1382 | * **More Information and RF24 Based Projects** 1383 | * 1384 | * @li Project Blog: TMRh20.blogspot.com 1385 | * @li Maniacal Bits Blog 1386 | * @li MySensors.org (User friendly sensor networks/IoT) 1387 | * @li RF24Node_MsgProto (MQTT) 1388 | * @li RF24SensorNet 1389 | * @li Home Automation for Geeks 1390 | * @li Original Maniacbug RF24Network Blog Post 1391 | * @li ManiacBug on GitHub (Original Library Author) 1392 | * 1393 | * 1394 | *
1395 | * 1396 | * @section Platform_Support Platform Support Pages 1397 | * 1398 | * @li Arduino (Uno, Nano, Mega, Due, Galileo, etc) 1399 | * @li ATTiny 1400 | * @li Linux devices( RPi , Linux SPI userspace device, MRAA supported boards ( Galileo, Edison, etc), LittleWire) 1401 | * @li Cross-compilation for linux devices 1402 | * @li Python wrapper available for Linux devices 1403 | * 1404 | *
1405 | * **General µC Pin layout** (See the individual board support pages for more info) 1406 | * 1407 | * The table below shows how to connect the the pins of the NRF24L01(+) to different boards. 1408 | * CE and CSN are configurable. 1409 | * 1410 | * | PIN | NRF24L01 | Arduino UNO | ATtiny25/45/85 [0] | ATtiny44/84 [1] | LittleWire [2] | RPI | RPi -P1 Connector | 1411 | * |-----|----------|-------------|--------------------|-----------------|-------------------------|------------|-------------------| 1412 | * | 1 | GND | GND | pin 4 | pin 14 | GND | rpi-gnd | (25) | 1413 | * | 2 | VCC | 3.3V | pin 8 | pin 1 | regulator 3.3V required | rpi-3v3 | (17) | 1414 | * | 3 | CE | digIO 7 | pin 2 | pin 12 | pin to 3.3V | rpi-gpio22 | (15) | 1415 | * | 4 | CSN | digIO 8 | pin 3 | pin 11 | RESET | rpi-gpio8 | (24) | 1416 | * | 5 | SCK | digIO 13 | pin 7 | pin 9 | SCK | rpi-sckl | (23) | 1417 | * | 6 | MOSI | digIO 11 | pin 6 | pin 7 | MOSI | rpi-mosi | (19) | 1418 | * | 7 | MISO | digIO 12 | pin 5 | pin 8 | MISO | rpi-miso | (21) | 1419 | * | 8 | IRQ | - | - | - | - | - | - | 1420 | * 1421 | * @li [0] https://learn.sparkfun.com/tutorials/tiny-avr-programmer-hookup-guide/attiny85-use-hints 1422 | * @li [1] http://highlowtech.org/?p=1695 1423 | * @li [2] http://littlewire.cc/ 1424 | *


1425 | * 1426 | * 1427 | * 1428 | * 1429 | * @page Arduino Arduino 1430 | * 1431 | * RF24 is fully compatible with Arduino boards
1432 | * See http://www.arduino.cc/en/Reference/Board and http://arduino.cc/en/Reference/SPI for more information 1433 | * 1434 | * RF24 makes use of the standard hardware SPI pins (MISO,MOSI,SCK) and requires two additional pins, to control 1435 | * the chip-select and chip-enable functions.
1436 | * These pins must be chosen and designated by the user, in RF24 radio(ce_pin,cs_pin); and can use any 1437 | * available pins. 1438 | * 1439 | *
1440 | * @section ARD_DUE Arduino Due 1441 | * 1442 | * RF24 makes use of the extended SPI functionality available on the Arduino Due, and requires one of the 1443 | * defined hardware SS/CS pins to be designated in RF24 radio(ce_pin,cs_pin);
1444 | * See http://arduino.cc/en/Reference/DueExtendedSPI for more information 1445 | * 1446 | * Initial Due support taken from https://github.com/mcrosson/RF24/tree/due 1447 | * 1448 | *
1449 | * @section Alternate_SPI Alternate SPI Support 1450 | * 1451 | * RF24 supports alternate SPI methods, in case the standard hardware SPI pins are otherwise unavailable. 1452 | * 1453 | *
1454 | * **Software Driven SPI** 1455 | * 1456 | * Software driven SPI is provided by the DigitalIO library 1457 | * 1458 | * Setup:
1459 | * 1. Install the digitalIO library
1460 | * 2. Open RF24_config.h in a text editor. Uncomment the line #define SOFTSPI
1461 | * 3. In your sketch, add #include DigitalIO.h 1462 | * 1463 | * @note Note: Pins are listed as follows and can be modified by editing the RF24_config.h file
1464 | * 1465 | * const uint8_t SOFT_SPI_MISO_PIN = 16; 1466 | * const uint8_t SOFT_SPI_MOSI_PIN = 15; 1467 | * const uint8_t SOFT_SPI_SCK_PIN = 14; 1468 | * 1469 | *
1470 | * **Alternate Hardware (UART) Driven SPI** 1471 | * 1472 | * The Serial Port (UART) on Arduino can also function in SPI mode, and can double-buffer data, while the 1473 | * default SPI hardware cannot. 1474 | * 1475 | * The SPI_UART library is available at https://github.com/TMRh20/Sketches/tree/master/SPI_UART 1476 | * 1477 | * Enabling: 1478 | * 1. Install the SPI_UART library 1479 | * 2. Edit RF24_config.h and uncomment #define SPI_UART 1480 | * 3. In your sketch, add @code #include @endcode 1481 | * 1482 | * SPI_UART SPI Pin Connections: 1483 | * | NRF |Arduino Uno Pin| 1484 | * |-----|---------------| 1485 | * | MOSI| TX(0) | 1486 | * | MISO| RX(1) | 1487 | * | SCK | XCK(4) | 1488 | * | CE | User Specified| 1489 | * | CSN | User Specified| 1490 | * 1491 | * 1492 | * @note SPI_UART on Mega boards requires soldering to an unused pin on the chip.
See 1493 | * https://github.com/TMRh20/RF24/issues/24 for more information on SPI_UART. 1494 | * 1495 | * @page ATTiny ATTiny 1496 | * 1497 | * ATTiny support is built into the library, so users are not required to include SPI.h in their sketches
1498 | * See the included rf24ping85 example for pin info and usage 1499 | * 1500 | * Some versions of Arduino IDE may require a patch to allow use of the full program space on ATTiny
1501 | * See https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC for ATTiny patch 1502 | * 1503 | * ATTiny board support initially added from https://github.com/jscrane/RF24 1504 | * 1505 | * @section Hardware Hardware Configuration 1506 | * By tong67 ( https://github.com/tong67 ) 1507 | * 1508 | * **ATtiny25/45/85 Pin map with CE_PIN 3 and CSN_PIN 4** 1509 | * @code 1510 | * +-\/-+ 1511 | * NC PB5 1|o |8 Vcc --- nRF24L01 VCC, pin2 --- LED --- 5V 1512 | * nRF24L01 CE, pin3 --- PB3 2| |7 PB2 --- nRF24L01 SCK, pin5 1513 | * nRF24L01 CSN, pin4 --- PB4 3| |6 PB1 --- nRF24L01 MOSI, pin6 1514 | * nRF24L01 GND, pin1 --- GND 4| |5 PB0 --- nRF24L01 MISO, pin7 1515 | * +----+ 1516 | * @endcode 1517 | * 1518 | *
1519 | * **ATtiny25/45/85 Pin map with CE_PIN 3 and CSN_PIN 3** => PB3 and PB4 are free to use for application
1520 | * Circuit idea from http://nerdralph.blogspot.ca/2014/01/nrf24l01-control-with-3-attiny85-pins.html
1521 | * Original RC combination was 1K/100nF. 22K/10nF combination worked better.
1522 | * For best settletime delay value in RF24::csn() the timingSearch3pin.ino sketch can be used.
1523 | * This configuration is enabled when CE_PIN and CSN_PIN are equal, e.g. both 3
1524 | * Because CE is always high the power consumption is higher than for 5 pins solution
1525 | * @code 1526 | * ^^ 1527 | * +-\/-+ nRF24L01 CE, pin3 ------| // 1528 | * PB5 1|o |8 Vcc --- nRF24L01 VCC, pin2 ------x----------x--|<|-- 5V 1529 | * NC PB3 2| |7 PB2 --- nRF24L01 SCK, pin5 --|<|---x-[22k]--| LED 1530 | * NC PB4 3| |6 PB1 --- nRF24L01 MOSI, pin6 1n4148 | 1531 | * nRF24L01 GND, pin1 -x- GND 4| |5 PB0 --- nRF24L01 MISO, pin7 | 1532 | * | +----+ | 1533 | * |-----------------------------------------------||----x-- nRF24L01 CSN, pin4 1534 | * 10nF 1535 | * @endcode 1536 | * 1537 | *
1538 | * **ATtiny24/44/84 Pin map with CE_PIN 8 and CSN_PIN 7**
1539 | * Schematic provided and successfully tested by Carmine Pastore (https://github.com/Carminepz)
1540 | * @code 1541 | * +-\/-+ 1542 | * nRF24L01 VCC, pin2 --- VCC 1|o |14 GND --- nRF24L01 GND, pin1 1543 | * PB0 2| |13 AREF 1544 | * PB1 3| |12 PA1 1545 | * PB3 4| |11 PA2 --- nRF24L01 CE, pin3 1546 | * PB2 5| |10 PA3 --- nRF24L01 CSN, pin4 1547 | * PA7 6| |9 PA4 --- nRF24L01 SCK, pin5 1548 | * nRF24L01 MISO, pin7 --- PA6 7| |8 PA5 --- nRF24L01 MOSI, pin6 1549 | * +----+ 1550 | * @endcode 1551 | * 1552 | *
1553 | * **ATtiny2313/4313 Pin map with CE_PIN 12 and CSN_PIN 13**
1554 | * @code 1555 | * +-\/-+ 1556 | * PA2 1|o |20 VCC --- nRF24L01 VCC, pin2 1557 | * PD0 2| |19 PB7 --- nRF24L01 SCK, pin5 1558 | * PD1 3| |18 PB6 --- nRF24L01 MOSI, pin6 1559 | * PA1 4| |17 PB5 --- nRF24L01 MISO, pin7 1560 | * PA0 5| |16 PB4 --- nRF24L01 CSN, pin4 1561 | * PD2 6| |15 PB3 --- nRF24L01 CE, pin3 1562 | * PD3 7| |14 PB2 1563 | * PD4 8| |13 PB1 1564 | * PD5 9| |12 PB0 1565 | * nRF24L01 GND, pin1 --- GND 10| |11 PD6 1566 | * +----+ 1567 | * @endcode 1568 | * 1569 | *


1570 | * 1571 | * 1572 | * 1573 | * 1574 | * 1575 | * 1576 | * @page Linux Linux devices 1577 | * 1578 | * Generic Linux devices are supported via SPIDEV, MRAA, RPi native via BCM2835, or using LittleWire. 1579 | * 1580 | * @note The SPIDEV option should work with most Linux systems supporting spi userspace device.
1581 | * 1582 | *
1583 | * @section AutoInstall Automated Install 1584 | *(**Designed & Tested on RPi** - Defaults to SPIDEV on devices supporting it) 1585 | * 1586 | * 1587 | * 1. Install prerequisites if there are any (MRAA, LittleWire libraries, setup SPI device etc) 1588 | * 2. Download the install.sh file from http://tmrh20.github.io/RF24Installer/RPi/install.sh 1589 | * @code wget http://tmrh20.github.io/RF24Installer/RPi/install.sh @endcode 1590 | * 3. Make it executable 1591 | * @code chmod +x install.sh @endcode 1592 | * 4. Run it and choose your options 1593 | * @code ./install.sh @endcode 1594 | * 5. Run an example from one of the libraries 1595 | * @code 1596 | * cd rf24libs/RF24/examples_linux 1597 | * @endcode 1598 | * Edit the gettingstarted example, to set your pin configuration 1599 | * @code nano gettingstarted.cpp 1600 | * make 1601 | * sudo ./gettingstarted 1602 | * @endcode 1603 | * 1604 | *
1605 | * @section ManInstall Manual Install 1606 | * 1. Install prerequisites if there are any (MRAA, LittleWire libraries, setup SPI device etc) 1607 | * @note See the MRAA documentation for more info on installing MRAA
1608 | * 2. Make a directory to contain the RF24 and possibly RF24Network lib and enter it 1609 | * @code 1610 | * mkdir ~/rf24libs 1611 | * cd ~/rf24libs 1612 | * @endcode 1613 | * 3. Clone the RF24 repo 1614 | * @code git clone https://github.com/tmrh20/RF24.git RF24 @endcode 1615 | * 4. Change to the new RF24 directory 1616 | * @code cd RF24 @endcode 1617 | * 5. Configure build environment using @code ./configure @endcode script. It auto detectes device and build environment. For overriding autodetections, use command-line switches, see @code ./configure --help @endcode for description. 1618 | * 6. Build the library, and run an example file 1619 | * @code sudo make install @endcode 1620 | * @code 1621 | * cd examples_linux 1622 | * @endcode 1623 | * Edit the gettingstarted example, to set your pin configuration 1624 | * @code nano gettingstarted.cpp 1625 | * make 1626 | * sudo ./gettingstarted 1627 | * @endcode 1628 | * 1629 | *

1630 | * 1631 | * @page MRAA MRAA 1632 | * 1633 | * MRAA is a Low Level Skeleton Library for Communication on GNU/Linux platforms
1634 | * See http://iotdk.intel.com/docs/master/mraa/index.html for more information 1635 | * 1636 | * RF24 supports all MRAA supported platforms, but might not be tested on each individual platform due to the wide range of hardware support:
1637 | * Report an RF24 bug or issue 1638 | * 1639 | * @section Setup Setup and installation 1640 | * 1. Install the MRAA lib 1641 | * 2. As per your device, SPI may need to be enabled 1642 | * 3. Follow Linux installation steps to install RF24 libraries 1643 | * 1644 | * 1645 | *


1646 | * 1647 | * 1648 | * 1649 | * 1650 | * @page RPi Raspberry Pi 1651 | * 1652 | * RF24 supports a variety of Linux based devices via various drivers. Some boards like RPi can utilize multiple methods 1653 | * to drive the GPIO and SPI functionality. 1654 | * 1655 | *
1656 | * @section PreConfig Potential PreConfiguration 1657 | * 1658 | * If SPI is not already enabled, load it on boot: 1659 | * @code sudo raspi-config @endcode 1660 | * A. Update the tool via the menu as required
1661 | * B. Select **Advanced** and **enable the SPI kernel module**
1662 | * C. Update other software and libraries 1663 | * @code sudo apt-get update @endcode 1664 | * @code sudo apt-get upgrade @endcode 1665 | *

1666 | * 1667 | * @section Build Build Options 1668 | * The default build on Raspberry Pi utilizes the included **BCM2835** driver from http://www.airspayce.com/mikem/bcm2835 1669 | * 1. @code sudo make install -B @endcode 1670 | * 1671 | * Build using the **MRAA** library from http://iotdk.intel.com/docs/master/mraa/index.html
1672 | * MRAA is not included. See the MRAA platform page for more information. 1673 | * 1674 | * 1. Install, and build MRAA 1675 | * @code 1676 | * git clone https://github.com/intel-iot-devkit/mraa.git 1677 | * cd mraa 1678 | * mkdir build 1679 | * cd build 1680 | * cmake .. -DBUILDSWIGNODE=OFF 1681 | * sudo make install 1682 | * @endcode 1683 | * 1684 | * 2. Complete the install
1685 | * @code nano /etc/ld.so.conf @endcode 1686 | * Add the line @code /usr/local/lib/arm-linux-gnueabihf @endcode 1687 | * Run @code sudo ldconfig @endcode 1688 | * 1689 | * 3. Install RF24, using MRAA 1690 | * @code 1691 | * ./configure --driver=MRAA 1692 | * sudo make install -B 1693 | * @endcode 1694 | * See the gettingstarted example for an example of pin configuration 1695 | * 1696 | * Build using **SPIDEV** 1697 | * 1698 | * 1. Make sure that spi device support is enabled and /dev/spidev\.\ is present 1699 | * 2. Install RF24, using SPIDEV 1700 | * @code 1701 | * ./configure --driver=SPIDEV 1702 | * sudo make install -B 1703 | * @endcode 1704 | * 3. See the gettingstarted example for an example of pin configuration 1705 | * 1706 | *
1707 | * @section Pins Connections and Pin Configuration 1708 | * 1709 | * 1710 | * Using pin 15/GPIO 22 for CE, pin 24/GPIO8 (CE0) for CSN 1711 | * 1712 | * Can use either RPi CE0 or CE1 pins for radio CSN.
1713 | * Choose any RPi output pin for radio CE pin. 1714 | * 1715 | * **BCM2835 Constructor:** 1716 | * @code 1717 | * RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ); 1718 | * or 1719 | * RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS1, BCM2835_SPI_SPEED_8MHZ); 1720 | * 1721 | * RPi B+: 1722 | * RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ); 1723 | * or 1724 | * RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_26, BCM2835_SPI_SPEED_8MHZ); 1725 | * 1726 | * General: 1727 | * RF24 radio(22,0); 1728 | * or 1729 | * RF24 radio(22,1); 1730 | * 1731 | * @endcode 1732 | * See the gettingstarted example for an example of pin configuration 1733 | * 1734 | * See http://www.airspayce.com/mikem/bcm2835/index.html for BCM2835 class documentation. 1735 | *

1736 | * **MRAA Constructor:** 1737 | * 1738 | * @code RF24 radio(15,0); @endcode 1739 | * 1740 | * See http://iotdk.intel.com/docs/master/mraa/rasppi.html 1741 | *

1742 | * **SPI_DEV Constructor** 1743 | * 1744 | * @code RF24 radio(22,0); @endcode 1745 | * In general, use @code RF24 radio(, *10+); @endcode for proper SPIDEV constructor to address correct spi device at /dev/spidev\.\ 1746 | * 1747 | * See http://pi.gadgetoid.com/pinout 1748 | * 1749 | * **Pins:** 1750 | * 1751 | * | PIN | NRF24L01 | RPI | RPi -P1 Connector | 1752 | * |-----|----------|------------|-------------------| 1753 | * | 1 | GND | rpi-gnd | (25) | 1754 | * | 2 | VCC | rpi-3v3 | (17) | 1755 | * | 3 | CE | rpi-gpio22 | (15) | 1756 | * | 4 | CSN | rpi-gpio8 | (24) | 1757 | * | 5 | SCK | rpi-sckl | (23) | 1758 | * | 6 | MOSI | rpi-mosi | (19) | 1759 | * | 7 | MISO | rpi-miso | (21) | 1760 | * | 8 | IRQ | - | - | 1761 | * 1762 | * 1763 | * 1764 | * 1765 | *

1766 | **************** 1767 | * 1768 | * Based on the arduino lib from J. Coliz
1769 | * the library was berryfied by Purinda Gunasekara
1770 | * then forked from github stanleyseow/RF24 to https://github.com/jscrane/RF24-rpi
1771 | * Network lib also based on https://github.com/farconada/RF24Network 1772 | * 1773 | * 1774 | * 1775 | * 1776 | *


1777 | * 1778 | * 1779 | * 1780 | * @page Python Python Wrapper (by https://github.com/mz-fuzzy) 1781 | * 1782 | * @note Both python2 and python3 are supported. 1783 | * 1784 | * @section Install Installation: 1785 | * 1786 | * 1. Install the python-dev (or python3-dev) and boost libraries 1787 | * @code sudo apt-get install python-dev libboost-python-dev @endcode 1788 | * @note For python3 in Raspbian, it's needed to manually link python boost library, like this: 1789 | * @code sudo ln -s /usr/lib/arm-linux-gnueabihf/libboost_python-py34.so /usr/lib/arm-linux-gnueabihf/libboost_python3.so @endcode 1790 | * 1791 | * 2. Install python-setuptools (or python3-setuptools) 1792 | * @code sudo apt-get install python-setuptools @endcode 1793 | * 1794 | * 3. Build the library 1795 | * @code ./setup.py build @endcode 1796 | * @note Build takes several minutes on arm-based machines. Machines with RAM <1GB may need to increase amount of swap for build. 1797 | * 1798 | * 4. Install the library 1799 | * @code sudo ./setup.py install @endcode 1800 | * See the additional
Platform Support pages for information on connecting your hardware
1801 | * See the included example for usage information. 1802 | * 1803 | * 5. Running the Example 1804 | * Edit the pingpair_dyn.py example to configure the appropriate pins per the above documentation: 1805 | * @code nano pingpair_dyn.py @endcode 1806 | * Configure another device, Arduino or RPi with the pingpair_dyn example
1807 | * Run the example 1808 | * @code sudo ./pingpair_dyn.py @endcode 1809 | * 1810 | *


1811 | * 1812 | * @page CrossCompile Linux cross-compilation 1813 | * 1814 | * RF24 library supports cross-compilation. Advantages of cross-compilation: 1815 | * - development tools don't have to be installed on target machine 1816 | * - resources of target machine don't have to be sufficient for compilation 1817 | * - compilation time can be reduced for large projects 1818 | * 1819 | * Following prerequisites need to be assured: 1820 | * - ssh passwordless access to target machine (https://linuxconfig.org/passwordless-ssh) 1821 | * - sudo of a remote user without password (http://askubuntu.com/questions/334318/sudoers-file-enable-nopasswd-for-user-all-commands) 1822 | * - cross-compilation toolchain for your target machine; for RPi 1823 | * @code git clone https://github.com/raspberrypi/tools rpi_tools @endcode 1824 | * and cross-compilation tools must be in PATH, for example 1825 | * @code export PATH=$PATH:/your/dir/rpi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin @endcode 1826 | * 1827 | * @section CxSteps Cross compilation steps: 1828 | * 1. clone RF24 to a machine for cross-compilation 1829 | * @code 1830 | * git clone https://github.com/TMRh20/RF24 1831 | * cd RF24 1832 | * @endcode 1833 | * 2. configure for cross compilation 1834 | * @code ./configure --remote=pi@target_linux_host @endcode 1835 | * eventually 1836 | * @code ./configure --remote=pi@target_linux_host --driver= @endcode 1837 | * 3. build 1838 | * @code make @endcode 1839 | * 4. (opt) install library to cross-compilation machine into cross-exvironment - important for compilation of examples 1840 | * @code sudo make install @endcode 1841 | * 5. upload library to target machine 1842 | * @code make upload @endcode 1843 | * 6. (opt) compile examples 1844 | * @code 1845 | * cd examples_linux 1846 | * make 1847 | * @endcode 1848 | * 7. (opt) upload examples to target machine 1849 | * @code make upload @endcode 1850 | * 1851 | * @section CxStepsPython Cross comilation steps for python wrapper 1852 | * 1853 | * Prerequisites: 1854 | * - Python setuptools must be installed on both target and cross-compilation machines 1855 | * @code sudo pip install setuptools @endcode 1856 | * or 1857 | * @code sudo apt-get install python-setuptools @endcode 1858 | * 1859 | * Installation steps: 1860 | * 1. Assure having libboost-python-dev library in your cross-compilation environment. Alternatively, you can install it into your target machine and copy /usr and /lib directories to the cross-compilation machine. 1861 | * For example 1862 | * @code 1863 | * mkdir -p rpi_root && rsync -a pi@target_linux_host:/usr :/lib rpi_root 1864 | * export CFLAGS="--sysroot=/your/dir/rpi_root -I/your/dir/rpi_root/usr/include/python2.7/" 1865 | * @endcode 1866 | * 1867 | * 2. Build the python wrapper 1868 | * @code 1869 | * cd pyRF24 1870 | * ./setup.py build --compiler=crossunix 1871 | * @endcode 1872 | * 1873 | * 3. Make the egg package 1874 | * @code ./setup.py bdist_egg --plat-name=cross @endcode 1875 | * dist/RF24--cross.egg should be created. 1876 | * 1877 | * 4. Upload it to the target machine and install there: 1878 | * @code 1879 | * scp dist/RF24-*-cross.egg pi@target_linux_host: 1880 | * ssh pi@target_linux_host 'sudo easy_install RF24-*-cross.egg' 1881 | * @endcode 1882 | * 1883 | *


1884 | * 1885 | * @page ATXMEGA ATXMEGA 1886 | * 1887 | * The RF24 driver can be build as a static library with Atmel Studio 7 in order to be included as any other library in another program for the XMEGA family. 1888 | * 1889 | * Currently only the ATXMEGA D3 family is implemented. 1890 | * 1891 | * @section Preparation 1892 | * 1893 | * Create an empty GCC Static Library project in AS7.
1894 | * As not all files are required, copy the following directory structure in the project: 1895 | * 1896 | * @code 1897 | * utility\ 1898 | * ATXMegaD3\ 1899 | * compatibility.c 1900 | * compatibility.h 1901 | * gpio.cpp 1902 | * gpio.h 1903 | * gpio_helper.c 1904 | * gpio_helper.h 1905 | * includes.h 1906 | * RF24_arch_config.h 1907 | * spi.cpp 1908 | * spi.h 1909 | * nRF24L01.h 1910 | * printf.h 1911 | * RF24.cpp 1912 | * RF24.h 1913 | * RF24_config.h 1914 | * @endcode 1915 | * 1916 | * @section Usage 1917 | * 1918 | * Add the library to your project!
1919 | * In the file where the **main()** is put the following in order to update the millisecond functionality: 1920 | * 1921 | * @code 1922 | * ISR(TCE0_OVF_vect) 1923 | * { 1924 | * update_milisec(); 1925 | * } 1926 | * @endcode 1927 | * 1928 | * Declare the rf24 radio with **RF24 radio(XMEGA_PORTC_PIN3, XMEGA_SPI_PORT_C);** 1929 | * 1930 | * First parameter is the CE pin which can be any available pin on the uC. 1931 | * 1932 | * Second parameter is the CS which can be on port C (**XMEGA_SPI_PORT_C**) or on port D (**XMEGA_SPI_PORT_D**). 1933 | * 1934 | * Call the **__start_timer()** to start the millisecond timer. 1935 | * 1936 | * @note Note about the millisecond functionality:
1937 | * 1938 | * The millisecond functionality is based on the TCE0 so don't use these pins as IO.
1939 | * The operating frequency of the uC is 32MHz. If you have other frequency change the TCE0 registers appropriatly in function **__start_timer()** in **compatibility.c** file for your frequency. 1940 | * 1941 | * @page Portability RF24 Portability 1942 | * 1943 | * The RF24 radio driver mainly utilizes the Arduino API for GPIO, SPI, and timing functions, which are easily replicated 1944 | * on various platforms.
Support files for these platforms are stored under RF24/utility, and can be modified to provide 1945 | * the required functionality. 1946 | * 1947 | *
1948 | * @section Hardware_Templates Basic Hardware Template 1949 | * 1950 | * **RF24/utility** 1951 | * 1952 | * The RF24 library now includes a basic hardware template to assist in porting to various platforms.
The following files can be included 1953 | * to replicate standard Arduino functions as needed, allowing devices from ATTiny to Raspberry Pi to utilize the same core RF24 driver. 1954 | * 1955 | * | File | Purpose | 1956 | * |--------------------|------------------------------------------------------------------------------| 1957 | * | RF24_arch_config.h | Basic Arduino/AVR compatibility, includes for remaining support files, etc | 1958 | * | includes.h | Linux only. Defines specific platform, include correct RF24_arch_config file | 1959 | * | spi.h | Provides standardized SPI ( transfer() ) methods | 1960 | * | gpio.h | Provides standardized GPIO ( digitalWrite() ) methods | 1961 | * | compatibility.h | Provides standardized timing (millis(), delay()) methods | 1962 | * | your_custom_file.h | Provides access to custom drivers for spi,gpio, etc | 1963 | * 1964 | *
1965 | * Examples are provided via the included hardware support templates in **RF24/utility**
1966 | * See the modules page for examples of class declarations 1967 | * 1968 | *
1969 | * @section Device_Detection Device Detection 1970 | * 1971 | * 1. The main detection for Linux devices is done in the configure script, with the includes.h from the proper hardware directory copied to RF24/utility/includes.h
1972 | * 2. Secondary detection is completed in RF24_config.h, causing the include.h file to be included for all supported Linux devices
1973 | * 3. RF24.h contains the declaration for SPI and GPIO objects 'spi' and 'gpio' to be used for porting-in related functions. 1974 | * 1975 | *
1976 | * @section Ported_Code Code 1977 | * To have your ported code included in this library, or for assistance in porting, create a pull request or open an issue at https://github.com/TMRh20/RF24 1978 | * 1979 | * 1980 | *


1981 | */ 1982 | 1983 | #endif // __RF24_H__ 1984 | 1985 | --------------------------------------------------------------------------------