diff --git a/README.md b/README.md index 770ced9..8db4309 100644 --- a/README.md +++ b/README.md @@ -1,163 +1,15 @@ -RadioHead Packet Radio library for embedded microprocessors -=========================================================== - -This is a fork of the original RadioHead Packet Radio library for embedded microprocessors. It provides a complete object-oriented library for sending and receiving packetized messages via a variety of common data radios and other transports on a range of embedded microprocessors. - -**Please read the full documentation and licensing from the original author [site][3]** - -### features added with this fork -================================= - -**Compatible with boards** - -[LoRasPI][10], [Raspberry PI Lora Gateway][12], [Dragino Lora GPS HAT][13] - -LoRasPI  -Raspberry PI Lora Gateway/Node  -Raspberry PI Lora Gateway/Node - -- Added moteino modem setting on RF69 to be compatible with lowpowerlab RF69 configuration library -- Added possibility to work with no IRQ connected for RF69 and RF95 - - for example to get one more GPIO free - - on Raspberry Pi, we do not have `attachInterrupt()` like with bcm2835 library -- Added samples for multiples Raspberry Pi boards with RF69 and RF95 modules such as - - [LoRasPI][10], simple RFM9x or RFM69HCW shield - - [iC880A or Linklabs Raspberry PI shield][11] with RFM9x or RFM69HCW onboard - - [Raspberry PI Lora Gateway][12] with multiple RFM9x or RFM69HCW shield - - [Dragino Lora shield][13] - - Sample code are in [rf95][21], [rf69][20], [nrf24][22] and [multi_server][23], note that old sample NRF24 sample has been moved to nrf24 folder for consistency. -- Added 2 samples test tools (for Raspberry PI) do detect RF69 and RF95 modules and check IRQ rising edge - - [spi_scan][9] sample code, scan and try to detect connected modules - - [irq_test][8] sample code, check a rising edge on a GPIO - -Sample code for Raspberry PI is located under [RadioHead/examples/raspi][7] folder. - -### Installation on Raspberry PI -================================ - -Clone repository -```shell -git clone https://github.com/hallard/RadioHead -``` - -**Connection and pins definition** - -Boards pins (Chip Select, IRQ line, Reset and LED) definition are set in the new [RadioHead/examples/raspi/RasPiBoards.h][24] file. In your code, you need to define board used and then, include the file definition like this -```cpp -// LoRasPi board -#define BOARD_LORASPI - -// Now we include RasPi_Boards.h so this will expose defined -// constants with CS/IRQ/RESET/on board LED pins definition -#include "../RasPiBoards.h" - -// Your code start here -#ifdef RF_RST_PIN -// Blah blah do reset line -#endif - -``` - -Then in your code you'll have exposed RF_CS_PIN, RF_IRQ_PIN, RF_RST_PIN and RF_LED_PIN and you'll be able to do some `#ifdef RF_LED_LIN` for example. See [rf95_client][25] sample code. - -So you have 3 options to define the pins you want - -- The board you have is already defined so just need to define it your source code (as explained above) -- You can add your board into [RasPiBoards.h][24] and then define it your source code as above -- You can manually define pins in your code and remove the board definition and `#include "../RasPiBoards.h"` - -To go further with examples : - -go to example folder here spi_scan -```shell -cd RadioHead/examples/raspi/spi_scan -``` -Build executable -```shell -root@pi03(rw):~/RadioHead/examples/raspi/spi_scan# make -g++ -DRASPBERRY_PI -DBCM2835_NO_DELAY_COMPATIBILITY -c -I../../.. spi_scan.c -g++ spi_scan.o -lbcm2835 -o spi_scan -root@pi03(rw):~/RadioHead/examples/raspi/spi_scan -``` -And run -```shell -root@pi03(rw):~/RadioHead/examples/raspi/spi_scan# ./spi_scan -Checking register(0x42) with CS=GPIO06 => Nothing! -Checking register(0x10) with CS=GPIO06 => Nothing! -Checking register(0x42) with CS=GPIO08 => SX1276 RF95/96 (V=0x12) -Checking register(0x10) with CS=GPIO08 => Nothing! -Checking register(0x42) with CS=GPIO07 => Nothing! -Checking register(0x10) with CS=GPIO07 => Nothing! -Checking register(0x42) with CS=GPIO26 => Nothing! -Checking register(0x10) with CS=GPIO26 => Nothing! -``` -And voila! with [LoRasPi][10] board RFM95 dedected on SPI with GPIO8 (CE0) - - -If I'm doing same test with [PI Lora Gateway][12] with 2 RFM95 (one 433MHz and one 868MHz) and one RFMHW69 433MHz on board like this - -Raspberry PI Lora Gateway/Node - -Here are the results when trying to detect the onboard modules: - -```shell -root@pi01(rw):~/RadioHead/examples/raspi/spi_scan# ./spi_scan -Checking register(0x42) with CS=GPIO06 => Nothing! -Checking register(0x10) with CS=GPIO06 => Nothing! -Checking register(0x42) with CS=GPIO08 => SX1276 RF95/96 (V=0x12) -Checking register(0x10) with CS=GPIO08 => Nothing! -Checking register(0x42) with CS=GPIO07 => SX1276 RF95/96 (V=0x12) -Checking register(0x10) with CS=GPIO07 => Nothing! -Checking register(0x42) with CS=GPIO26 => Unknown (V=0x01) -Checking register(0x10) with CS=GPIO26 => SX1231 RFM69 (V=0x24) -``` - -Voila! 3 modules are seen, now let's try listenning packets with PI Lora [Gateway][12]. - -My setup has another Raspberry Pi with RFM95 868MHZ [LoRasPI][10] shield running [`rf95_client`][25] sample and some [ULPnode][6] prototypes always running with on board RFM69 configured as Group ID 69 on 433MHz. I don't have a Lora 433MHz sender running so we won't receive anything on this one. - -Here the results starting from scratch - -**Client side** - -RF95 client - -**multi server side** - -RF95 client - -It works! - -### Difference with original Author repo -======================================== - -Due to easier maintenance to keep in sync with original author lib, I've got 2 repo: - -- My master one (this one) https://github.com/hallard/RadioHead that is the one you need if you want to use my projects or lib added features. -- The one above has been forked to https://github.com/ch2i/RadioHead where I put the original version released by the author. - -Like this, I can do Pull Request from [ch2i][4] to [hallard][1] to add new features added by the author to my version. This mean that this [one][4] is just a github copy version of the latest original done by Mike, I don't do any change on this one. I know it's not the best way, but I didn't found a better solution for now, if you have better idea, just let me know. - -[1]: https://github.com/hallard/RadioHead -[2]: https://hallard.me -[3]: http://www.airspayce.com/mikem/arduino/RadioHead/ -[4]: http://www.airspayce.com/mikem/arduino/RadioHead/RadioHead-1.61.zip -[5]: https://github.com/ch2i/RadioHead -[6]: http://hallard.me/category/ulpnode/ -[7]: https://github.com/hallard/RadioHead/tree/master/examples/raspi -[8]: https://github.com/hallard/RadioHead/tree/master/examples/raspi/irq_test -[9]: https://github.com/hallard/RadioHead/tree/master/examples/raspi/spi_scan - -[10]: https://github.com/hallard/LoRasPI -[11]: https://github.com/ch2i/iC880A-Raspberry-PI -[12]: https://github.com/hallard/RPI-Lora-Gateway -[13]: https://github.com/dragino/Lora - -[20]: https://github.com/hallard/RadioHead/tree/master/examples/raspi/rf69 -[21]: https://github.com/hallard/RadioHead/tree/master/examples/raspi/rf95 -[22]: https://github.com/hallard/RadioHead/tree/master/examples/raspi/nrf24 -[23]: https://github.com/hallard/RadioHead/tree/master/examples/raspi/multi_server -[24]: https://github.com/hallard/RadioHead/tree/master/examples/raspi/RasPiBoards.h -[25]: https://github.com/hallard/RadioHead/tree/master/examples/raspi/rf95/rf95_client.cpp - - +RadioHead Packet Radio library for embedded microprocessors +=========================================================== + +###Version 1.67 + +This is a copy of the original RadioHead Packet Radio library for embedded microprocessors. It provides a complete object-oriented library for sending and receiving packetized messages via a variety of common data radios and other transports on a range of embedded microprocessors. + +Please read the full documentation and licensing from the original author [site][3], here it's just a copy to keep in sync my custom featured [version][1] with this [original version][4]. + +**If you want to know what features have been added for my custom needs, please see my [repo version README][1]** + +[1]: https://github.com/hallard/RadioHead +[2]: https://hallard.me +[3]: http://www.airspayce.com/mikem/arduino/RadioHead/ +[4]: http://www.airspayce.com/mikem/arduino/RadioHead/RadioHead-1.67.zip diff --git a/RHGenericDriver.cpp b/RHGenericDriver.cpp index 0137f24..4956771 100644 --- a/RHGenericDriver.cpp +++ b/RHGenericDriver.cpp @@ -1,7 +1,7 @@ // RHGenericDriver.cpp // // Copyright (C) 2014 Mike McCauley -// $Id: RHGenericDriver.cpp,v 1.19 2015/12/11 01:10:24 mikem Exp $ +// $Id: RHGenericDriver.cpp,v 1.20 2017/01/12 23:58:00 mikem Exp $ #include @@ -72,7 +72,7 @@ bool RHGenericDriver::waitPacketSent(uint16_t timeout) bool RHGenericDriver::waitCAD() { if (!_cad_timeout) - return true; + return true; // Wait for any channel activity to finish or timeout // Sophisticated DCF function... @@ -83,7 +83,7 @@ bool RHGenericDriver::waitCAD() while (isChannelActive()) { if (millis() - t > _cad_timeout) - return false; + return false; delay(random(1, 10) * 100); // Should these values be configurable? Macros? } diff --git a/RHGenericDriver.h b/RHGenericDriver.h index f9b1765..1c8fc53 100644 --- a/RHGenericDriver.h +++ b/RHGenericDriver.h @@ -1,7 +1,7 @@ // RHGenericDriver.h // Author: Mike McCauley (mikem@airspayce.com) // Copyright (C) 2014 Mike McCauley -// $Id: RHGenericDriver.h,v 1.17 2016/04/04 01:40:12 mikem Exp $ +// $Id: RHGenericDriver.h,v 1.18 2017/01/12 23:58:00 mikem Exp $ #ifndef RHGenericDriver_h #define RHGenericDriver_h @@ -52,7 +52,7 @@ class RHGenericDriver RHModeIdle, ///< Transport is idle. RHModeTx, ///< Transport is in the process of transmitting a message. RHModeRx, ///< Transport is in the process of receiving a message. - RHModeCad ///< Transport is in the process of detecting channel activity (if supported) + RHModeCad ///< Transport is in the process of detecting channel activity (if supported) } RHMode; /// Constructor @@ -298,6 +298,10 @@ class RHGenericDriver volatile bool _cad; unsigned int _cad_timeout; + /// Channel activity detected + volatile bool _cad; + unsigned int _cad_timeout; + private: }; diff --git a/RHHardwareSPI.h b/RHHardwareSPI.h index c5c8fae..dc66c1a 100644 --- a/RHHardwareSPI.h +++ b/RHHardwareSPI.h @@ -2,7 +2,7 @@ // Author: Mike McCauley (mikem@airspayce.com) // Copyright (C) 2011 Mike McCauley // Contributed by Joanna Rutkowska -// $Id: RHHardwareSPI.h,v 1.9 2014/08/12 00:54:52 mikem Exp $ +// $Id: RHHardwareSPI.h,v 1.10 2017/01/12 23:58:00 mikem Exp $ #ifndef RHHardwareSPI_h #define RHHardwareSPI_h @@ -54,7 +54,7 @@ class RHHardwareSPI : public RHGenericSPI void end(); #else // not supported on ATTiny etc - uint8_t transfer(uint8_t data) {return 0;} + uint8_t transfer(uint8_t /*data*/) {return 0;} void begin(){} void end(){} diff --git a/RHReliableDatagram.cpp b/RHReliableDatagram.cpp index a69b091..b8aa22e 100644 --- a/RHReliableDatagram.cpp +++ b/RHReliableDatagram.cpp @@ -9,7 +9,7 @@ // // Author: Mike McCauley (mikem@airspayce.com) // Copyright (C) 2011 Mike McCauley -// $Id: RHReliableDatagram.cpp,v 1.15 2015/12/11 01:10:24 mikem Exp $ +// $Id: RHReliableDatagram.cpp,v 1.16 2017/01/12 23:58:00 mikem Exp $ #include @@ -22,6 +22,7 @@ RHReliableDatagram::RHReliableDatagram(RHGenericDriver& driver, uint8_t thisAddr _lastSequenceNumber = 0; _timeout = RH_DEFAULT_TIMEOUT; _retries = RH_DEFAULT_RETRIES; + memset(_seenIds, 0, sizeof(_seenIds)); } //////////////////////////////////////////////////////////////////// diff --git a/RH_ASK.cpp b/RH_ASK.cpp index a1cd14f..e7ca2de 100644 --- a/RH_ASK.cpp +++ b/RH_ASK.cpp @@ -1,7 +1,7 @@ // RH_ASK.cpp // // Copyright (C) 2014 Mike McCauley -// $Id: RH_ASK.cpp,v 1.19 2016/08/17 01:53:21 mikem Exp mikem $ +// $Id: RH_ASK.cpp,v 1.20 2017/01/12 23:58:00 mikem Exp $ #include #include @@ -483,7 +483,7 @@ bool RH_ASK::send(const uint8_t* data, uint8_t len) waitPacketSent(); if (!waitCAD()) - return false; // Check channel activity + return false; // Check channel activity // Encode the message length crc = RHcrc_ccitt_update(crc, count); diff --git a/RH_CC110.cpp b/RH_CC110.cpp index 0938ec7..29fdada 100644 --- a/RH_CC110.cpp +++ b/RH_CC110.cpp @@ -3,7 +3,7 @@ // Driver for Texas Instruments CC110L transceiver. // // Copyright (C) 2016 Mike McCauley -// $Id: RH_CC110.cpp,v 1.4 2016/01/02 01:46:34 mikem Exp $ +// $Id: RH_CC110.cpp,v 1.5 2017/01/12 23:58:00 mikem Exp $ #include @@ -302,7 +302,7 @@ bool RH_CC110::send(const uint8_t* data, uint8_t len) setModeIdle(); if (!waitCAD()) - return false; // Check channel activity + return false; // Check channel activity spiWriteRegister(RH_CC110_REG_3F_FIFO, len + RH_CC110_HEADER_LEN); spiWriteRegister(RH_CC110_REG_3F_FIFO,_txHeaderTo); diff --git a/RH_MRF89.cpp b/RH_MRF89.cpp index af386f5..d208b65 100644 --- a/RH_MRF89.cpp +++ b/RH_MRF89.cpp @@ -1,7 +1,7 @@ // RH_MRF89.cpp // // Copyright (C) 2015 Mike McCauley -// $Id: RH_MRF89.cpp,v 1.7 2015/12/31 04:23:12 mikem Exp $ +// $Id: RH_MRF89.cpp,v 1.8 2017/01/12 23:58:00 mikem Exp $ #include #define BAND_915 @@ -390,10 +390,10 @@ bool RH_MRF89::send(const uint8_t* data, uint8_t len) waitPacketSent(); // Make sure we dont interrupt an outgoing message setModeIdle(); - + if (!waitCAD()) - return false; // Check channel activity - + return false; // Check channel activity + // First octet is the length of the chip payload // 0 length messages are transmitted but never trigger a receive! spiWriteData(len + RH_MRF89_HEADER_LEN); diff --git a/RH_NRF24.cpp b/RH_NRF24.cpp index f4f59e8..380c57a 100644 --- a/RH_NRF24.cpp +++ b/RH_NRF24.cpp @@ -1,7 +1,7 @@ // NRF24.cpp // // Copyright (C) 2012 Mike McCauley -// $Id: RH_NRF24.cpp,v 1.22 2016/04/04 01:40:12 mikem Exp $ +// $Id: RH_NRF24.cpp,v 1.23 2017/01/12 23:58:00 mikem Exp $ #include @@ -189,7 +189,7 @@ bool RH_NRF24::send(const uint8_t* data, uint8_t len) return false; if (!waitCAD()) - return false; // Check channel activity + return false; // Check channel activity // Set up the headers _buf[0] = _txHeaderTo; diff --git a/RH_NRF51.cpp b/RH_NRF51.cpp index 6a52f78..95c0f5f 100644 --- a/RH_NRF51.cpp +++ b/RH_NRF51.cpp @@ -2,15 +2,20 @@ // // Per: nRF51_Series_Reference_manual v3.0.pdf // Copyright (C) 2012 Mike McCauley -// $Id: RH_NRF51.cpp,v 1.1 2015/07/01 00:46:05 mikem Exp $ +// $Id: RH_NRF51.cpp,v 1.3 2017/01/13 01:29:36 mikem Exp mikem $ -// Set by Arduino IDE when compiling for nRF51 chips: -#ifdef NRF51 +// Set by Arduino IDE and RadioHead.h when compiling for nRF51 or nRF52 chips: #include +#if RH_PLATFORM==RH_PLATFORM_NRF51 + + RH_NRF51::RH_NRF51() : _rxBufValid(false) +#if RH_NRF51_HAVE_ENCRYPTION + , _encrypting(false) +#endif { } @@ -20,11 +25,9 @@ bool RH_NRF51::init() NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; NRF_CLOCK->TASKS_HFCLKSTART = 1; /* Wait for the external oscillator to start up */ - while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) { } + while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) + ; - // Enables the DC/DC converter when the radio is enabled. Need this! - NRF_POWER->DCDCEN = 0x00000001; - // Disable and reset the radio NRF_RADIO->POWER = RADIO_POWER_POWER_Disabled; NRF_RADIO->POWER = RADIO_POWER_POWER_Enabled; @@ -47,7 +50,9 @@ bool RH_NRF51::init() NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos) | (RADIO_SHORTS_END_DISABLE_Enabled << RADIO_SHORTS_END_DISABLE_Pos); - NRF_RADIO->PCNF0 = ((8 << RADIO_PCNF0_LFLEN_Pos) & RADIO_PCNF0_LFLEN_Msk); // Payload length in bits + NRF_RADIO->PCNF0 = (8 << RADIO_PCNF0_LFLEN_Pos) // Payload size length in bits + | (1 << RADIO_PCNF0_S0LEN_Pos) // S0 is 1 octet + | (8 << RADIO_PCNF0_S1LEN_Pos); // S1 is 1 octet // Make sure we are powered down setModeIdle(); @@ -58,7 +63,7 @@ bool RH_NRF51::init() setChannel(2); // The default, in case it was set by another app without powering down setRF(RH_NRF51::DataRate2Mbps, RH_NRF51::TransmitPower0dBm); - + setEncryptionKey(NULL); return true; } @@ -131,7 +136,11 @@ void RH_NRF51::setModeIdle() { if (_mode != RHModeIdle) { + NRF_RADIO->EVENTS_DISABLED = 0U; NRF_RADIO->TASKS_DISABLE = 1; + while (NRF_RADIO->EVENTS_DISABLED == 0U) + ; // wait for the radio to be disabled + NRF_RADIO->EVENTS_END = 0U; _mode = RHModeIdle; } } @@ -141,10 +150,19 @@ void RH_NRF51::setModeRx() if (_mode != RHModeRx) { setModeIdle(); // Can only start RX from DISABLE state - // Radio will transition automatically to Disable state when a messageis received + +#if RH_NRF51_HAVE_ENCRYPTION + // Maybe set the AES CCA module for the correct encryption mode + if (_encrypting) + NRF_CCM->MODE = (CCM_MODE_MODE_Decryption << CCM_MODE_MODE_Pos); // Decrypt + NRF_CCM->MICSTATUS = 0; +#endif + + // Radio will transition automatically to Disable state when a message is received NRF_RADIO->PACKETPTR = (uint32_t)_buf; - NRF_RADIO->EVENTS_DISABLED = 0U; // So we can detect end of transmission + NRF_RADIO->EVENTS_READY = 0U; NRF_RADIO->TASKS_RXEN = 1; + NRF_RADIO->EVENTS_END = 0U; // So we can detect end of reception _mode = RHModeRx; } } @@ -154,10 +172,23 @@ void RH_NRF51::setModeTx() if (_mode != RHModeTx) { setModeIdle(); // Can only start RX from DISABLE state + + // Sigh: it seems that it takes longer to start the receiver than the transmitter for this type + // of radio, so if a message is received and an ACK or reply is sent to soon, the original transmitter + // may not see the reply. So we delay here to make sure the receiver is ready. + // Yes, I know this is very ugly + delay(1); + +#if RH_NRF51_HAVE_ENCRYPTION + // Maybe set the AES CCA module for the correct encryption mode + if (_encrypting) + NRF_CCM->MODE = (CCM_MODE_MODE_Encryption << CCM_MODE_MODE_Pos); // Encrypt +#endif // Radio will transition automatically to Disable state at the end of transmission NRF_RADIO->PACKETPTR = (uint32_t)_buf; - NRF_RADIO->EVENTS_DISABLED = 0U; // So we can detect end of transmission + NRF_RADIO->EVENTS_READY = 0U; NRF_RADIO->TASKS_TXEN = 1; + NRF_RADIO->EVENTS_END = 0U; // So we can detect end of transmission _mode = RHModeTx; } } @@ -167,19 +198,27 @@ bool RH_NRF51::send(const uint8_t* data, uint8_t len) if (len > RH_NRF51_MAX_MESSAGE_LEN) return false; +#if RH_NRF51_HAVE_ENCRYPTION + if (_encrypting && len > RH_NRF51_MAX_ENCRYPTED_MESSAGE_LEN) + return false; +#endif + if (!waitCAD()) - return false; // Check channel activity + return false; // Check channel activity // Set up the headers - _buf[0] = len + RH_NRF51_HEADER_LEN; - _buf[1] = _txHeaderTo; - _buf[2] = _txHeaderFrom; - _buf[3] = _txHeaderId; - _buf[4] = _txHeaderFlags; - memcpy(_buf+RH_NRF51_HEADER_LEN+1, data, len); - + _buf[0] = 0; // S0 + _buf[1] = len + RH_NRF51_HEADER_LEN; + _buf[2] = 0; // S1 + // The following octets are subject to encryption + _buf[3] = _txHeaderTo; + _buf[4] = _txHeaderFrom; + _buf[5] = _txHeaderId; + _buf[6] = _txHeaderFlags; + memcpy(_buf+RH_NRF51_HEADER_LEN, data, len); _rxBufValid = false; setModeTx(); + // Radio will return to Disabled state after transmission is complete _txGood++; return true; @@ -192,7 +231,7 @@ bool RH_NRF51::waitPacketSent() return false; // When the Disabled event occurs we know the transmission has completed - while (NRF_RADIO->EVENTS_DISABLED == 0U) + while (!NRF_RADIO->EVENTS_END) { YIELD; } @@ -226,13 +265,14 @@ bool RH_NRF51::printRegisters() // Check whether the latest received message is complete and uncorrupted void RH_NRF51::validateRxBuf() { - if (_buf[0] < 4) + if (_buf[1] < RH_NRF51_HEADER_LEN) return; // Too short to be a real message - // Extract the 4 headers - _rxHeaderTo = _buf[1]; - _rxHeaderFrom = _buf[2]; - _rxHeaderId = _buf[3]; - _rxHeaderFlags = _buf[4]; + // Extract the 4 headers following S0, LEN and S1 + _rxHeaderTo = _buf[3]; + _rxHeaderFrom = _buf[4]; + _rxHeaderId = _buf[5]; + _rxHeaderFlags = _buf[6]; + if (_promiscuous || _rxHeaderTo == _thisAddress || _rxHeaderTo == RH_BROADCAST_ADDRESS) @@ -242,6 +282,50 @@ void RH_NRF51::validateRxBuf() } } +void RH_NRF51::setEncryptionKey(uint8_t* key) +{ +#if RH_NRF51_HAVE_ENCRYPTION + if (key) + { + // Configure for on-the-fly encryption + // Set the key + memset(_encryption_cnf, 0, sizeof(_encryption_cnf)); + memcpy(_encryption_cnf, key, RH_NRF51_ENCRYPTION_KEY_LENGTH); + // AES configuration data area + // Note that the IV (Nonce) is not set, defaults to 0s + NRF_CCM->CNFPTR = (uint32_t)_encryption_cnf; + + // Set AES CCM input and putput buffers + // Make sure the _buf is encrypted and put back into _buf + NRF_CCM->INPTR = (uint32_t)_buf; + NRF_CCM->OUTPTR = (uint32_t)_buf; + // Also need to set SCRATCHPTR temp buffer os size 16+MAXPACKETSIZE in RAM + // FIXME: shared buffers if several radios + NRF_CCM->SCRATCHPTR = (uint32_t)_scratch; + + // SHORT from RADIO READY to AESCCM KSGEN using PPI predefined channel 24 + // Also RADIO ADDRESS to AESCCM CRYPT using PPI predefined channel 25 + NRF_PPI->CHENSET = (PPI_CHENSET_CH24_Enabled << PPI_CHENSET_CH24_Pos) + | (PPI_CHENSET_CH25_Enabled << PPI_CHENSET_CH25_Pos) + ; + + // SHORT from AESCCM ENDKSGEN to AESCCM CRYPT + NRF_CCM->SHORTS = (CCM_SHORTS_ENDKSGEN_CRYPT_Enabled << CCM_SHORTS_ENDKSGEN_CRYPT_Pos); + + // Enable the CCM module + NRF_CCM->ENABLE = (CCM_ENABLE_ENABLE_Enabled << CCM_ENABLE_ENABLE_Pos); + + _encrypting = true; + } + else + { + // Disable the CCM module + NRF_CCM->ENABLE = (CCM_ENABLE_ENABLE_Disabled << CCM_ENABLE_ENABLE_Pos); + _encrypting = false; + } +#endif +} + bool RH_NRF51::available() { if (!_rxBufValid) @@ -249,9 +333,16 @@ bool RH_NRF51::available() if (_mode == RHModeTx) return false; setModeRx(); - if (NRF_RADIO->EVENTS_DISABLED == 0U) + if (!NRF_RADIO->EVENTS_END) return false; // No message yet - if (NRF_RADIO->CRCSTATUS == ((RADIO_CRCSTATUS_CRCSTATUS_CRCError << RADIO_CRCSTATUS_CRCSTATUS_Pos) & RADIO_CRCSTATUS_CRCSTATUS_Msk)) + setModeIdle(); +#if RH_NRF51_HAVE_ENCRYPTION + // If encryption is enabled, the decrypted message is not available yet, and there seems + // to be no way to be sure when its ready, but a delay of 2ms is enough + if (_encrypting) + delay(2); +#endif + if (!NRF_RADIO->CRCSTATUS) { // Bad CRC, restart the radio _rxBad++; @@ -259,8 +350,8 @@ bool RH_NRF51::available() return false; } validateRxBuf(); - if (_rxBufValid) - setModeIdle(); // Got one + if (!_rxBufValid) + setModeRx(); // Try for another } return _rxBufValid; } @@ -268,7 +359,7 @@ bool RH_NRF51::available() void RH_NRF51::clearRxBuf() { _rxBufValid = false; - _buf[0] = 0; + _buf[1] = 0; } bool RH_NRF51::recv(uint8_t* buf, uint8_t* len) @@ -279,9 +370,9 @@ bool RH_NRF51::recv(uint8_t* buf, uint8_t* len) { // Skip the 4 headers that are at the beginning of the rxBuf // the payload length is the first octet in _buf - if (*len > _buf[0]-RH_NRF51_HEADER_LEN) - *len = _buf[0]-RH_NRF51_HEADER_LEN; - memcpy(buf, _buf+RH_NRF51_HEADER_LEN+1, *len); + if (*len > _buf[1]-RH_NRF51_HEADER_LEN) + *len = _buf[1]-RH_NRF51_HEADER_LEN; + memcpy(buf, _buf+RH_NRF51_HEADER_LEN, *len); } clearRxBuf(); // This message accepted and cleared return true; @@ -289,7 +380,21 @@ bool RH_NRF51::recv(uint8_t* buf, uint8_t* len) uint8_t RH_NRF51::maxMessageLength() { +#if RH_NRF51_HAVE_ENCRYPTION + if (_encrypting) + return RH_NRF51_MAX_ENCRYPTED_MESSAGE_LEN; +#endif return RH_NRF51_MAX_MESSAGE_LEN; } +float RH_NRF51::get_temperature() +{ + NRF_TEMP->EVENTS_DATARDY = 0; + NRF_TEMP->TASKS_START = 1; + + while (!NRF_TEMP->EVENTS_DATARDY) + ; + return NRF_TEMP->TEMP * 0.25; +} + #endif // NRF51 diff --git a/RH_NRF51.h b/RH_NRF51.h index aec6fbc..2b8042f 100644 --- a/RH_NRF51.h +++ b/RH_NRF51.h @@ -1,7 +1,7 @@ // RH_NRF51.h // Author: Mike McCauley // Copyright (C) 2015 Mike McCauley -// $Id: RH_NRF51.h,v 1.3 2015/08/14 21:20:12 mikem Exp $ +// $Id: RH_NRF51.h,v 1.4 2017/01/12 23:58:00 mikem Exp $ // #ifndef RH_NRF51_h @@ -15,32 +15,58 @@ // The length of the headers we add. // The headers are inside the nRF51 payload -#define RH_NRF51_HEADER_LEN 4 +// We add: +// S0 (not used) +// LEN +// S1 (not used) +// to +// from +// id +// flags +#define RH_NRF51_HEADER_LEN 7 // This is the maximum RadioHead user message length that can be supported by this library. Limited by // the supported message lengths in the nRF51 #define RH_NRF51_MAX_MESSAGE_LEN (RH_NRF51_MAX_PAYLOAD_LEN-RH_NRF51_HEADER_LEN) +// Define to be 1 if you want to support AES CCA encryption using the built-in +// encryption engine. +#define RH_NRF51_HAVE_ENCRYPTION 1 + +// When encryption is enabled, have a much shorter max message length +#define RH_NRF51_MAX_ENCRYPTED_MESSAGE_LEN (27-4) + +// The required length of the AES encryption key +#define RH_NRF51_ENCRYPTION_KEY_LENGTH 16 + +// This is the size of the CCM data structure for AES encryption +// REVISIT: use a struct? +#define RH_NRF51_AES_CCM_CNF_SIZE 33 + ///////////////////////////////////////////////////////////////////// /// \class RH_NRF51 RH_NRF51.h -/// \brief Send and receive addressed datagrams by nRF51 compatible transceivers. +/// \brief Send and receive addressed datagrams by nRF51 and nRF52 compatible transceivers. /// /// Supported transceivers include: /// - Nordic nRF51 based 2.4GHz radio modules, such as nRF51822 /// and other compatible chips, such as used in RedBearLabs devices like: /// http://store.redbearlab.com/products/redbearlab-nrf51822 /// http://store.redbearlab.com/products/blenano +/// and +/// Sparkfun nRF52832 breakout board, with Arduino 1.6.13 and +/// Sparkfun nRF52 boards manager 0.2.3 /// /// This base class provides basic functions for sending and receiving unaddressed, unreliable datagrams /// of arbitrary length to 254 octets per packet. Use one of the Manager classes to get addressing and /// acknowledgement reliability, routing, meshes etc. /// /// The nRF51822 (https://www.nordicsemi.com/eng/Products/Bluetooth-Smart-Bluetooth-low-energy/nRF51822) +/// and nRF52832 (https://learn.sparkfun.com/tutorials/nrf52832-breakout-board-hookup-guide) /// is a complete SoC (system on a chip) with ARM microprocessor and 2.4 GHz radio, which supports a range of channels /// and transmission bit rates. Chip antenna is on-board. /// /// This library provides functions for sending and receiving messages of up to 254 octets on any -/// frequency supported by the nRF51822, at a selected data rate. +/// frequency supported by the nRF51822/nRF52832, at a selected data rate. /// /// The nRF51 transceiver is configured to use Enhanced Shockburst with no acknowledgement and no retransmits. /// TXADDRESS and RXADDRESSES:RXADDR0 (ie pipe 0) are the logical address used. The on-air network address @@ -55,18 +81,20 @@ /// \par Packet Format /// /// All messages sent and received by this class conform to this packet format. It is NOT compatible -/// with the one used by RH_NRF24 and the nRF24L01 product specification, mainly because the nRF24 only suports +/// with the one used by RH_NRF24 and the nRF24L01 product specification, mainly because the nRF24 only supports /// 6 bits of message length. /// /// - 1 octets PREAMBLE /// - 3 to 5 octets NETWORK ADDRESS +/// - 1 octet S0 (not used, required if encryption used) /// - 8 bits PAYLOAD LENGTH -/// - 0 to 254 octets PAYLOAD, consisting of: +/// - 1 octet S1 (not used, required if encryption used) +/// - 0 to 251 octets PAYLOAD (possibly encrypted), consisting of: /// - 1 octet TO header /// - 1 octet FROM header /// - 1 octet ID header /// - 1 octet FLAGS header -/// - 0 to 250 octets of user message +/// - 0 to 247 octets of user message /// - 2 octets CRC (Algorithm x^16+x^12^x^5+1 with initial value 0xFFFF). /// /// \par Example programs @@ -75,6 +103,9 @@ /// /// The sample programs are designed to be built using Arduino 1.6.4 or later using the procedures outlined /// in http://redbearlab.com/getting-started-nrf51822/ +/// or with Sparkfun nRF52832 breakout board, with Arduino 1.6.13 and +/// Sparkfun nRF52 boards manager 0.2.3 using the procedures outlined in +/// https://learn.sparkfun.com/tutorials/nrf52832-breakout-board-hookup-guide /// /// \par Radio Performance /// @@ -172,10 +203,11 @@ class RH_NRF51 : public RHGenericDriver /// Sends data to the address set by setTransmitAddress() /// Sets the radio to TX mode. + /// Caution: when encryption is enabled, the maximum message length is reduced to 23 octets. /// \param [in] data Data bytes to send. /// \param [in] len Number of data bytes to send /// \return true on success (which does not necessarily mean the receiver got the message, only that the message was - /// successfully transmitted). + /// successfully transmitted). False if the message is too long or was otherwise not transmitted. bool send(const uint8_t* data, uint8_t len); /// Blocks until the current message (if any) @@ -213,10 +245,26 @@ class RH_NRF51 : public RHGenericDriver /// \return true if a valid message was copied to buf bool recv(uint8_t* buf, uint8_t* len); + /// Enables AES encryption and sets the AES encryption key, used + /// to encrypt and decrypt all messages using the on-chip AES CCM mode encryption engine. + /// The default is disabled. + /// In the AES configuration, the message counter and IV is always set to 0, which + /// means the same keystream is used for every message with a given key. + /// Caution: when encryption is enabled, the maximum message length is reduced to 23 octets. + /// \param[in] key The key to use. Must be 16 bytes long. The same key must be installed + /// in other instances of RH_RF51, otherwise communications will not work correctly. If key is NULL, + /// encryption is disabled, which is the default. + void setEncryptionKey(uint8_t* key = NULL); + /// The maximum message length supported by this driver /// \return The maximum message length supported by this driver uint8_t maxMessageLength(); + /// Reeads the current die temperature using the built in TEMP peripheral. + /// Blocks while the temperature is measured, which takes about 30 microseconds. + // \return the current die temperature in degrees C. + float get_temperature(); + protected: /// Examine the receive buffer to determine whether the message is for this node void validateRxBuf(); @@ -231,6 +279,18 @@ class RH_NRF51 : public RHGenericDriver /// True when there is a valid message in the buffer bool _rxBufValid; + +#if RH_NRF51_HAVE_ENCRYPTION + /// True if an AES key has been specified and that we are therfore encrypting + /// and decrypting messages on the fly + bool _encrypting; + + /// Scratch area for AES encryption + uint8_t _scratch[RH_NRF51_MAX_PAYLOAD_LEN+1+16]; + + /// Where the AES encryption key and IV are stored + uint8_t _encryption_cnf[RH_NRF51_AES_CCM_CNF_SIZE]; +#endif }; /// @example nrf51_client.pde diff --git a/RH_NRF905.cpp b/RH_NRF905.cpp index 04ee23f..3706e5c 100644 --- a/RH_NRF905.cpp +++ b/RH_NRF905.cpp @@ -1,7 +1,7 @@ // RH_NRF905.cpp // // Copyright (C) 2012 Mike McCauley -// $Id: RH_NRF905.cpp,v 1.6 2015/12/11 01:10:24 mikem Exp $ +// $Id: RH_NRF905.cpp,v 1.7 2017/01/12 23:58:00 mikem Exp $ #include @@ -144,7 +144,7 @@ bool RH_NRF905::send(const uint8_t* data, uint8_t len) return false; if (!waitCAD()) - return false; // Check channel activity + return false; // Check channel activity // Set up the headers _buf[0] = _txHeaderTo; diff --git a/RH_NRF905.h b/RH_NRF905.h index 26c35ac..e9ba85c 100644 --- a/RH_NRF905.h +++ b/RH_NRF905.h @@ -1,7 +1,7 @@ // RH_NRF905.h // Author: Mike McCauley (mikem@airspayce.com) // Copyright (C) 2014 Mike McCauley -// $Id: RH_NRF905.h,v 1.9 2016/04/04 01:40:12 mikem Exp $ +// $Id: RH_NRF905.h,v 1.10 2017/01/12 23:58:00 mikem Exp $ // #ifndef RH_NRF905_h @@ -339,10 +339,11 @@ class RH_NRF905 : public RHNRFSPIDriver /// Sends data to the address set by setTransmitAddress() /// Sets the radio to TX mode /// \param [in] data Data bytes to send. - /// \param [in] len Number of data bytes to set in teh TX buffer. The actual size of the - /// transmitted data payload is set by setPayloadSize + /// \param [in] len Number of data bytes to set in the TX buffer. The actual size of the + /// transmitted data payload is set by setPayloadSize. Maximum message length actually + /// transmitted is RH_NRF905_MAX_MESSAGE_LEN = 27. /// \return true on success (which does not necessarily mean the receiver got the message, only that the message was - /// successfully transmitted). + /// successfully transmitted). Returns false if the requested message length exceeds RH_NRF905_MAX_MESSAGE_LEN. bool send(const uint8_t* data, uint8_t len); /// Blocks until the current message (if any) diff --git a/RH_RF22.cpp b/RH_RF22.cpp index c4e4407..61ec1e2 100644 --- a/RH_RF22.cpp +++ b/RH_RF22.cpp @@ -1,7 +1,7 @@ // RH_RF22.cpp // // Copyright (C) 2011 Mike McCauley -// $Id: RH_RF22.cpp,v 1.26 2016/04/04 01:40:12 mikem Exp $ +// $Id: RH_RF22.cpp,v 1.27 2017/01/12 23:58:00 mikem Exp $ #include @@ -589,7 +589,7 @@ bool RH_RF22::send(const uint8_t* data, uint8_t len) waitPacketSent(); if (!waitCAD()) - return false; // Check channel activity + return false; // Check channel activity ATOMIC_BLOCK_START; spiWrite(RH_RF22_REG_3A_TRANSMIT_HEADER3, _txHeaderTo); diff --git a/RH_RF22.h b/RH_RF22.h index bb636ff..768853c 100644 --- a/RH_RF22.h +++ b/RH_RF22.h @@ -1,7 +1,7 @@ // RH_RF22.h // Author: Mike McCauley (mikem@airspayce.com) // Copyright (C) 2011 Mike McCauley -// $Id: RH_RF22.h,v 1.31 2016/08/17 01:53:21 mikem Exp mikem $ +// $Id: RH_RF22.h,v 1.31 2016/08/17 01:53:21 mikem Exp $ // #ifndef RH_RF22_h diff --git a/RH_RF24.cpp b/RH_RF24.cpp index 7233ba1..c340b31 100644 --- a/RH_RF24.cpp +++ b/RH_RF24.cpp @@ -1,7 +1,7 @@ // RH_RF24.cpp // // Copyright (C) 2011 Mike McCauley -// $Id: RH_RF24.cpp,v 1.17 2016/08/17 01:53:21 mikem Exp mikem $ +// $Id: RH_RF24.cpp,v 1.18 2017/01/12 23:58:00 mikem Exp $ #include // Generated with Silicon Labs WDS software: @@ -348,7 +348,7 @@ bool RH_RF24::send(const uint8_t* data, uint8_t len) setModeIdle(); // Prevent RX while filling the fifo if (!waitCAD()) - return false; // Check channel activity + return false; // Check channel activity // Put the payload in the FIFO // First the length in fixed length field 1. This wont appear in the receiver fifo since diff --git a/RH_RF24.h b/RH_RF24.h index dddc208..db49fc7 100644 --- a/RH_RF24.h +++ b/RH_RF24.h @@ -1,7 +1,7 @@ // RH_RF24.h // Author: Mike McCauley (mikem@airspayce.com) // Copyright (C) 2014 Mike McCauley -// $Id: RH_RF24.h,v 1.15 2016/08/17 01:53:21 mikem Exp mikem $ +// $Id: RH_RF24.h,v 1.15 2016/08/17 01:53:21 mikem Exp $ // // Supports RF24/RF26 and RFM24/RFM26 modules in FIFO mode // also Si4464/63/62/61/60-A1 diff --git a/RH_RF69.cpp b/RH_RF69.cpp index ce143d9..fe4e563 100644 --- a/RH_RF69.cpp +++ b/RH_RF69.cpp @@ -1,7 +1,7 @@ // RH_RF69.cpp // // Copyright (C) 2011 Mike McCauley -// $Id: RH_RF69.cpp,v 1.26 2015/12/11 01:10:24 mikem Exp $ +// $Id: RH_RF69.cpp,v 1.27 2017/01/12 23:58:00 mikem Exp $ #include @@ -547,7 +547,7 @@ bool RH_RF69::send(const uint8_t* data, uint8_t len) setModeIdle(); // Prevent RX while filling the fifo if (!waitCAD()) - return false; // Check channel activity + return false; // Check channel activity ATOMIC_BLOCK_START; digitalWrite(_slaveSelectPin, LOW); diff --git a/RH_RF69.h b/RH_RF69.h index ebb8bc2..98e8763 100644 --- a/RH_RF69.h +++ b/RH_RF69.h @@ -1,7 +1,7 @@ // RH_RF69.h // Author: Mike McCauley (mikem@airspayce.com) // Copyright (C) 2014 Mike McCauley -// $Id: RH_RF69.h,v 1.32 2016/07/07 00:02:53 mikem Exp $ +// $Id: RH_RF69.h,v 1.33 2017/01/12 23:58:00 mikem Exp $ // /// @@ -326,10 +326,16 @@ /// the marvellous high powered MinWireless-HW (with 20dBm output for excellent range) /// - the excellent Rocket Scream Mini Ultra Pro with the RFM69HCW /// http://www.rocketscream.com/blog/product/mini-ultra-pro-with-radio/ -/// - The excellent talk2 Whisper Node boards -/// (https://talk2.wisen.com.au/ and https://bitbucket.org/talk2/), -/// an Arduino Nano compatible board, which include an on-board RF69 radio, external antenna, -/// run on 2xAA batteries and support low power operations. RF69 examples work without modification. +/// - The excellent Talk2 Whisper Node boards +/// (https://talk2.wisen.com.au/ and https://bitbucket.org/talk2/whisper-node-avr), +/// an Arduino compatible board, which include an on-board RF69 radio, external antenna, +/// run on 2xAAA batteries and support low power operations. RF69 examples work without modification. +/// Use Arduino Board Manager to install the Talk2 code support as described in +/// https://bitbucket.org/talk2/whisper-node-avr +/// - The excellent Adafruit Feather. These are excellent boards that are available with a variety of radios. +/// We tested with the +/// Feather 32u4 with RFM69HCW radio, with Arduino IDE 1.6.8 and the Adafruit AVR Boards board manager version 1.6.10. +/// https://www.adafruit.com/products/3076 /// /// \par Overview /// @@ -512,6 +518,16 @@ /// RH_RF69 driver; /// \endcode /// +/// If you have a Feather 32u4 with RFM69HCW you need to initialise the driver like: +/// \code +/// RH_RF69 driver(8, 7); +/// \endcode +/// and since the radio is the high power HCW model, you must set the Tx power in the +/// range 14 to 20 like this: +/// \code +/// driver.setTxPower(14); +/// \endcode +/// /// It is possible to have 2 or more radios connected to one Arduino, provided /// each radio has its own SS and interrupt line (SCK, SDI and SDO are common /// to all radios) @@ -858,6 +874,8 @@ class RH_RF69 : public RHSPIDriver /// value on all nodes in your network. Nodes with different SyncWords set will never receive /// each others messages, so different SyncWords can be used to isolate different /// networks from each other. Default is { 0x2d, 0xd4 }. + /// Caution: tests here show that with a single sync word (ie where len == 1), + /// RFM69 reception can be unreliable. /// \param[in] syncWords Array of sync words, 1 to 4 octets long. NULL if no sync words to be used. /// \param[in] len Number of sync words to set, 1 to 4. 0 if no sync words to be used. void setSyncWords(const uint8_t* syncWords = NULL, uint8_t len = 0); @@ -866,7 +884,7 @@ class RH_RF69 : public RHSPIDriver /// to encrypt and decrypt all messages. The default is disabled. /// \param[in] key The key to use. Must be 16 bytes long. The same key must be installed /// in other instances of RF69, otherwise communications will not work correctly. If key is NULL, - /// encryption is disabled. + /// encryption is disabled, which is the default. void setEncryptionKey(uint8_t* key = NULL); /// Returns the time in millis since the most recent preamble was received, and when the most recent diff --git a/RH_RF95.cpp b/RH_RF95.cpp index 8beda8f..3f5e12f 100644 --- a/RH_RF95.cpp +++ b/RH_RF95.cpp @@ -1,7 +1,7 @@ // RH_RF95.cpp // // Copyright (C) 2011 Mike McCauley -// $Id: RH_RF95.cpp,v 1.11 2016/04/04 01:40:12 mikem Exp $ +// $Id: RH_RF95.cpp,v 1.12 2017/01/12 23:58:00 mikem Exp $ #include @@ -299,7 +299,7 @@ bool RH_RF95::send(const uint8_t* data, uint8_t len) setModeIdle(); if (!waitCAD()) - return false; // Check channel activity + return false; // Check channel activity // Position at the beginning of the FIFO spiWrite(RH_RF95_REG_0D_FIFO_ADDR_PTR, 0); @@ -506,3 +506,12 @@ bool RH_RF95::isChannelActive() return _cad; } + +void RH_RF95::enableTCXO() +{ + while ((spiRead(RH_RF95_REG_4B_TCXO) & RH_RF95_TCXO_TCXO_INPUT_ON) != RH_RF95_TCXO_TCXO_INPUT_ON) + { + sleep(); + spiWrite(RH_RF95_REG_4B_TCXO, (spiRead(RH_RF95_REG_4B_TCXO) | RH_RF95_TCXO_TCXO_INPUT_ON)); + } +} diff --git a/RH_RF95.h b/RH_RF95.h index acb99dc..2ed0c1f 100644 --- a/RH_RF95.h +++ b/RH_RF95.h @@ -6,7 +6,7 @@ // // Author: Mike McCauley (mikem@airspayce.com) // Copyright (C) 2014 Mike McCauley -// $Id: RH_RF95.h,v 1.12 2016/08/17 01:53:21 mikem Exp mikem $ +// $Id: RH_RF95.h,v 1.14 2017/01/13 01:29:36 mikem Exp mikem $ // #ifndef RH_RF95_h @@ -111,6 +111,7 @@ // RH_RF95_REG_01_OP_MODE 0x01 #define RH_RF95_LONG_RANGE_MODE 0x80 #define RH_RF95_ACCESS_SHARED_REG 0x40 +#define RH_RF95_LOW_FREQUENCY_MODE 0x08 #define RH_RF95_MODE 0x07 #define RH_RF95_MODE_SLEEP 0x00 #define RH_RF95_MODE_STDBY 0x01 @@ -152,9 +153,17 @@ // RH_RF95_REG_0C_LNA 0x0c #define RH_RF95_LNA_GAIN 0xe0 -#define RH_RF95_LNA_BOOST 0x03 -#define RH_RF95_LNA_BOOST_DEFAULT 0x00 -#define RH_RF95_LNA_BOOST_150PC 0x11 +#define RH_RF95_LNA_GAIN_G1 0x20 +#define RH_RF95_LNA_GAIN_G2 0x40 +#define RH_RF95_LNA_GAIN_G3 0x60 +#define RH_RF95_LNA_GAIN_G4 0x80 +#define RH_RF95_LNA_GAIN_G5 0xa0 +#define RH_RF95_LNA_GAIN_G6 0xc0 +#define RH_RF95_LNA_BOOST_LF 0x18 +#define RH_RF95_LNA_BOOST_LF_DEFAULT 0x00 +#define RH_RF95_LNA_BOOST_HF 0x03 +#define RH_RF95_LNA_BOOST_HF_DEFAULT 0x00 +#define RH_RF95_LNA_BOOST_HF_150PC 0x11 // RH_RF95_REG_11_IRQ_FLAGS_MASK 0x11 #define RH_RF95_RX_TIMEOUT_MASK 0x80 @@ -190,19 +199,24 @@ #define RH_RF95_FHSS_PRESENT_CHANNEL 0x3f // RH_RF95_REG_1D_MODEM_CONFIG1 0x1d -#define RH_RF95_BW 0xc0 -#define RH_RF95_BW_125KHZ 0x00 -#define RH_RF95_BW_250KHZ 0x40 -#define RH_RF95_BW_500KHZ 0x80 -#define RH_RF95_BW_RESERVED 0xc0 -#define RH_RF95_CODING_RATE 0x38 -#define RH_RF95_CODING_RATE_4_5 0x00 -#define RH_RF95_CODING_RATE_4_6 0x08 -#define RH_RF95_CODING_RATE_4_7 0x10 -#define RH_RF95_CODING_RATE_4_8 0x18 -#define RH_RF95_IMPLICIT_HEADER_MODE_ON 0x04 -#define RH_RF95_RX_PAYLOAD_CRC_ON 0x02 -#define RH_RF95_LOW_DATA_RATE_OPTIMIZE 0x01 +#define RH_RF95_BW 0xf0 + +#define RH_RF95_BW_7_8KHZ 0x00 +#define RH_RF95_BW_10_4KHZ 0x10 +#define RH_RF95_BW_15_6KHZ 0x20 +#define RH_RF95_BW_20_8KHZ 0x30 +#define RH_RF95_BW_31_25KHZ 0x40 +#define RH_RF95_BW_41_7KHZ 0x50 +#define RH_RF95_BW_62_5KHZ 0x60 +#define RH_RF95_BW_125KHZ 0x70 +#define RH_RF95_BW_250KHZ 0x80 +#define RH_RF95_BW_500KHZ 0x90 +#define RH_RF95_CODING_RATE 0x0e +#define RH_RF95_CODING_RATE_4_5 0x02 +#define RH_RF95_CODING_RATE_4_6 0x04 +#define RH_RF95_CODING_RATE_4_7 0x06 +#define RH_RF95_CODING_RATE_4_8 0x08 +#define RH_RF95_IMPLICIT_HEADER_MODE_ON 0x01 // RH_RF95_REG_1E_MODEM_CONFIG2 0x1e #define RH_RF95_SPREADING_FACTOR 0xf0 @@ -214,9 +228,13 @@ #define RH_RF95_SPREADING_FACTOR_2048CPS 0xb0 #define RH_RF95_SPREADING_FACTOR_4096CPS 0xc0 #define RH_RF95_TX_CONTINUOUS_MOE 0x08 -#define RH_RF95_AGC_AUTO_ON 0x04 + +#define RH_RF95_PAYLOAD_CRC_ON 0x04 #define RH_RF95_SYM_TIMEOUT_MSB 0x03 +// RH_RF95_REG_4B_TCXO 0x4b +#define RH_RF95_TCXO_TCXO_INPUT_ON 0x10 + // RH_RF95_REG_4D_PA_DAC 0x4d #define RH_RF95_PA_DAC_DISABLE 0x04 #define RH_RF95_PA_DAC_ENABLE 0x07 @@ -459,6 +477,14 @@ /// At 20dBm (100mW) with Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. /// (Default medium range) in the conditions described above. /// - Range over flat ground through heavy trees and vegetation approx 2km. +/// +/// Caution: the performance of this radio, especially with narrow bandwidths is strongly dependent on the +/// accuracy and stability of the chip clock. HopeRF and Semtech do not appear to +/// recommend bandwidths of less than 62.5 kHz +/// unless you have the optional Temperature Compensated Crystal Oscillator (TCXO) installed and +/// enabled on your radio module. See the refernece manual for more data. +/// Also https://lowpowerlab.com/forum/rf-range-antennas-rfm69-library/lora-library-experiences-range/15/ +/// and http://www.semtech.com/images/datasheet/an120014-xo-guidance-lora-modulation.pdf /// /// \par Transmitter Power /// @@ -716,6 +742,15 @@ class RH_RF95 : public RHSPIDriver /// \return true if channel is in use. virtual bool isChannelActive(); + /// Enable TCXO mode + /// Call this immediately after init(), to force your radio to use an external + /// frequency source, such as a Temperature Compensated Crystal Oscillator (TCXO). + /// See the comments in the main documentation about the sensitivity of this radio to + /// clock frequency especially when using narrow bandwidths. + /// Leaves the module in sleep mode. + /// Caution, this function has not been tested by us. + void enableTCXO(); + protected: /// This is a low level function to handle the interrupts for one instance of RH_RF95. /// Called automatically by isr*() diff --git a/RH_Serial.cpp b/RH_Serial.cpp index c7c3f5e..3a26251 100644 --- a/RH_Serial.cpp +++ b/RH_Serial.cpp @@ -1,7 +1,7 @@ // RH_Serial.cpp // // Copyright (C) 2014 Mike McCauley -// $Id: RH_Serial.cpp,v 1.12 2016/04/04 01:40:12 mikem Exp $ +// $Id: RH_Serial.cpp,v 1.13 2017/01/12 23:58:00 mikem Exp $ #include #if (RH_PLATFORM == RH_PLATFORM_STM32F2) @@ -201,7 +201,7 @@ bool RH_Serial::recv(uint8_t* buf, uint8_t* len) bool RH_Serial::send(const uint8_t* data, uint8_t len) { if (!waitCAD()) - return false; // Check channel activity + return false; // Check channel activity _txFcs = 0xffff; // Initial value _serial.write(DLE); // Not in FCS diff --git a/RH_TCP.cpp b/RH_TCP.cpp index 23d9181..317aad0 100644 --- a/RH_TCP.cpp +++ b/RH_TCP.cpp @@ -1,7 +1,7 @@ // RH_TCP.cpp // // Copyright (C) 2014 Mike McCauley -// $Id: RH_TCP.cpp,v 1.5 2015/08/13 02:45:47 mikem Exp $ +// $Id: RH_TCP.cpp,v 1.6 2017/01/12 23:58:00 mikem Exp $ #include @@ -255,7 +255,7 @@ bool RH_TCP::recv(uint8_t* buf, uint8_t* len) bool RH_TCP::send(const uint8_t* data, uint8_t len) { if (!waitCAD()) - return false; // Check channel activity (prob not possible for this driver?) + return false; // Check channel activity (prob not possible for this driver?) bool ret = sendPacket(data, len); delay(10); // Wait for transmit to succeed. REVISIT: depends on length and speed diff --git a/RadioHead.h b/RadioHead.h index 0d6ef30..ec29de0 100644 --- a/RadioHead.h +++ b/RadioHead.h @@ -1,7 +1,7 @@ // RadioHead.h // Author: Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY // Copyright (C) 2014 Mike McCauley -// $Id: RadioHead.h,v 1.57 2016/08/17 01:53:21 mikem Exp mikem $ +// $Id: RadioHead.h,v 1.59 2017/01/13 01:29:36 mikem Exp mikem $ /// \mainpage RadioHead Packet Radio library for embedded microprocessors /// @@ -10,7 +10,7 @@ /// via a variety of common data radios and other transports on a range of embedded microprocessors. /// /// The version of the package that this documentation refers to can be downloaded -/// from http://www.airspayce.com/mikem/arduino/RadioHead/RadioHead-1.62.zip +/// from http://www.airspayce.com/mikem/arduino/RadioHead/RadioHead-1.67.zip /// You can find the latest version at http://www.airspayce.com/mikem/arduino/RadioHead /// /// You can also find online help and discussion at @@ -87,6 +87,8 @@ /// /// - RH_NRF51 /// Works with Nordic nRF51 compatible 2.4 GHz SoC/devices such as the nRF51822. +/// Also works with Sparkfun nRF52832 breakout board, with Arduino 1.6.13 and +/// Sparkfun nRF52 boards manager 0.2.3 /// /// - RH_RF95 /// Works with Semtech SX1276/77/78/79, Modtronix inAir4 and inAir9, @@ -183,6 +185,10 @@ /// - nRF51 compatible Arm chips such as nRF51822 with Arduino 1.6.4 and later using the procedures /// in http://redbearlab.com/getting-started-nrf51822/ /// +/// - Adafruit Feather. These are excellent boards that are available with a variety of radios. We tested with the +/// Feather 32u4 with RFM69HCW radio, with Arduino IDE 1.6.8 and the Adafruit AVR Boards board manager version 1.6.10. +/// https://www.adafruit.com/products/3076 +/// /// - Raspberry Pi /// Uses BCM2835 library for GPIO http://www.airspayce.com/mikem/bcm2835/ /// Currently works only with RH_NRF24 driver or other drivers that do not require interrupt support. @@ -668,6 +674,32 @@ /// Implementation of RH_RF95::isChannelActive() allows the RF95 module to support /// Channel Activity Detection (CAD). Based on code contributed by Bent Guldbjerg Christensen. /// Implmentations of isChannelActive() plus documentation for other radio modules wil be welcomed. +/// \version 1.63 2016-10-20 +/// Testing with Adafruit Feather 32u4 with RFM69HCW. Updated documentation to reflect.
+/// \version 1.64 2016-12-10 +/// RHReliableDatagram now initialises _seenids. Fix from Ben Lim.
+/// In RH_NRF51, added get_temperature().
+/// In RH_NRF51, added support for AES packet encryption, which required a slight change +/// to the on-air message format.
+/// \version 1.65 2017-01-11 +/// Fixed a race condition with RH_NRF51 that prevented ACKs being reliably received.
+/// Removed code in RH_NRF51 that enabled the DC-DC converter. This seems not to be a necessary condition +/// for the radio to work and is now left to the application if that is required.
+/// Proven interoperation between nRF51822 and nRF52832.
+/// Modification and testing of RH_NRF51 so it works with nRF52 family processors, +/// such Sparkfun nRF52832 breakout board, with Arduino 1.6.13 and +/// Sparkfun nRF52 boards manager 0.2.3 using the procedures outlined in +/// https://learn.sparkfun.com/tutorials/nrf52832-breakout-board-hookup-guide
+/// Caution, the Sparkfun development system for Arduino is still immature. We had to +/// rebuild the nrfutil program since the supplied one was not suitable for +/// the Linux host we were developing on. See https://forum.sparkfun.com/viewtopic.php?f=32&t=45071 +/// Also, after downloading a sketch in the nRF52832, the program does not start executing cleanly: +/// you have to reset the processor again by pressing the reset button. +/// This appears to be a problem with nrfutil, rather than a bug in RadioHead. +/// \version 1.66 2017-01-15 +/// Fixed some errors in (unused) register definitions in RH_RF95.h.
+/// Fixed a problem that caused compilation errors in RH_NRF51 if the appropriate board +/// support was not installed. /// /// \author Mike McCauley. DO NOT CONTACT THE AUTHOR DIRECTLY. USE THE MAILING LIST GIVEN ABOVE @@ -676,7 +708,7 @@ // Official version numbers are maintained automatically by Makefile: #define RH_VERSION_MAJOR 1 -#define RH_VERSION_MINOR 62 +#define RH_VERSION_MINOR 67 // Symbolic names for currently supported platform types #define RH_PLATFORM_ARDUINO 1 @@ -688,6 +720,7 @@ #define RH_PLATFORM_STM32STD 7 #define RH_PLATFORM_STM32F4_HAL 8 #define RH_PLATFORM_RASPI 9 +// Also nRF52 family: #define RH_PLATFORM_NRF51 10 #define RH_PLATFORM_ESP8266 11 #define RH_PLATFORM_STM32F2 12 @@ -702,7 +735,7 @@ #elif defined(MPIDE) // Uno32 under old MPIDE, which has been discontinued: #define RH_PLATFORM RH_PLATFORM_UNO32 - #elif defined(NRF51) +#elif defined(NRF51) || defined(NRF52) #define RH_PLATFORM RH_PLATFORM_NRF51 #elif defined(ESP8266) #define RH_PLATFORM RH_PLATFORM_ESP8266 diff --git a/examples/nrf51/nrf51_client/nrf51_client.pde b/examples/nrf51/nrf51_client/nrf51_client.pde index 53fcd09..03e857b 100644 --- a/examples/nrf51/nrf51_client/nrf51_client.pde +++ b/examples/nrf51/nrf51_client/nrf51_client.pde @@ -8,7 +8,8 @@ // Tested on RedBearLabs nRF51822 and BLE Nano kit, built with Arduino 1.6.4. // See http://redbearlab.com/getting-started-nrf51822/ // for how to set up your Arduino build environment - +// Also tested with Sparkfun nRF52832 breakout board, witth Arduino 1.6.13 and +// Sparkfun nRF52 boards manager 0.2.3 #include // Singleton instance of the radio driver @@ -26,8 +27,14 @@ void setup() if (!nrf51.setChannel(1)) Serial.println("setChannel failed"); if (!nrf51.setRF(RH_NRF51::DataRate2Mbps, RH_NRF51::TransmitPower0dBm)) - Serial.println("setRF failed"); - nrf51.printRegisters(); + Serial.println("setRF failed"); + + // AES encryption can be enabled by setting the same key in the sender and receiver +// uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, +// 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; +// nrf51.setEncryptionKey(key); + +// nrf51.printRegisters(); } diff --git a/examples/nrf51/nrf51_reliable_datagram_client/nrf51_reliable_datagram_client.pde b/examples/nrf51/nrf51_reliable_datagram_client/nrf51_reliable_datagram_client.pde index 7ff4216..2f9c3ca 100644 --- a/examples/nrf51/nrf51_reliable_datagram_client/nrf51_reliable_datagram_client.pde +++ b/examples/nrf51/nrf51_reliable_datagram_client/nrf51_reliable_datagram_client.pde @@ -6,6 +6,8 @@ // Tested on RedBearLabs nRF51822 and BLE Nano kit, built with Arduino 1.6.4. // See http://redbearlab.com/getting-started-nrf51822/ // for how to set up your Arduino build environment +// Also tested with Sparkfun nRF52832 breakout board, witth Arduino 1.6.13 and +// Sparkfun nRF52 boards manager 0.2.3 #include #include diff --git a/examples/nrf51/nrf51_reliable_datagram_server/nrf51_reliable_datagram_server.pde b/examples/nrf51/nrf51_reliable_datagram_server/nrf51_reliable_datagram_server.pde index d2ac9fe..9e105b4 100644 --- a/examples/nrf51/nrf51_reliable_datagram_server/nrf51_reliable_datagram_server.pde +++ b/examples/nrf51/nrf51_reliable_datagram_server/nrf51_reliable_datagram_server.pde @@ -6,6 +6,8 @@ // Tested on RedBearLabs nRF51822 and BLE Nano kit, built with Arduino 1.6.4. // See http://redbearlab.com/getting-started-nrf51822/ // for how to set up your Arduino build environment +// Also tested with Sparkfun nRF52832 breakout board, witth Arduino 1.6.13 and +// Sparkfun nRF52 boards manager 0.2.3 #include diff --git a/examples/nrf51/nrf51_server/nrf51_server.pde b/examples/nrf51/nrf51_server/nrf51_server.pde index edf7784..f9b1f45 100644 --- a/examples/nrf51/nrf51_server/nrf51_server.pde +++ b/examples/nrf51/nrf51_server/nrf51_server.pde @@ -8,6 +8,8 @@ // Tested on RedBearLabs nRF51822 and BLE Nano kit, built with Arduino 1.6.4. // See http://redbearlab.com/getting-started-nrf51822/ // for how to set up your Arduino build environment +// Also tested with Sparkfun nRF52832 breakout board, witth Arduino 1.6.13 and +// Sparkfun nRF52 boards manager 0.2.3 #include @@ -27,6 +29,11 @@ void setup() Serial.println("setChannel failed"); if (!nrf51.setRF(RH_NRF51::DataRate2Mbps, RH_NRF51::TransmitPower0dBm)) Serial.println("setRF failed"); + + // AES encryption can be enabled by setting the same key in the sender and receiver +// uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, +// 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; +// nrf51.setEncryptionKey(key); } void loop() diff --git a/examples/rf69/rf69_client/rf69_client.pde b/examples/rf69/rf69_client/rf69_client.pde index f2701d5..0710b6b 100644 --- a/examples/rf69/rf69_client/rf69_client.pde +++ b/examples/rf69/rf69_client/rf69_client.pde @@ -17,10 +17,14 @@ // Singleton instance of the radio driver RH_RF69 rf69; //RH_RF69 rf69(15, 16); // For RF69 on PJRC breakout board with Teensy 3.1 +//RH_RF69 rf69(4, 2); // For MoteinoMEGA https://lowpowerlab.com/shop/moteinomega +//RH_RF69 rf69(8, 7); // Adafruit Feather 32u4 void setup() { Serial.begin(9600); + while (!Serial) + ; if (!rf69.init()) Serial.println("init failed"); // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM diff --git a/examples/rf69/rf69_reliable_datagram_client/rf69_reliable_datagram_client.pde b/examples/rf69/rf69_reliable_datagram_client/rf69_reliable_datagram_client.pde index 24b9238..4a7c79e 100644 --- a/examples/rf69/rf69_reliable_datagram_client/rf69_reliable_datagram_client.pde +++ b/examples/rf69/rf69_reliable_datagram_client/rf69_reliable_datagram_client.pde @@ -17,7 +17,8 @@ // Singleton instance of the radio driver RH_RF69 driver; //RH_RF69 driver(15, 16); // For RF69 on PJRC breakout board with Teensy 3.1 -//RH_RF69 rf69(4, 2); // For MoteinoMEGA https://lowpowerlab.com/shop/moteinomega +//RH_RF69 driver(4, 2); // For MoteinoMEGA https://lowpowerlab.com/shop/moteinomega +//RH_RF69 driver(8, 7); // Adafruit Feather 32u4 // Class to manage message delivery and receipt, using the driver declared above RHReliableDatagram manager(driver, CLIENT_ADDRESS); @@ -25,6 +26,8 @@ RHReliableDatagram manager(driver, CLIENT_ADDRESS); void setup() { Serial.begin(9600); + while (!Serial) + ; if (!manager.init()) Serial.println("init failed"); // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM diff --git a/examples/rf69/rf69_reliable_datagram_server/rf69_reliable_datagram_server.pde b/examples/rf69/rf69_reliable_datagram_server/rf69_reliable_datagram_server.pde index b1aef20..77e35ff 100644 --- a/examples/rf69/rf69_reliable_datagram_server/rf69_reliable_datagram_server.pde +++ b/examples/rf69/rf69_reliable_datagram_server/rf69_reliable_datagram_server.pde @@ -18,6 +18,7 @@ RH_RF69 driver; //RH_RF69 driver(15, 16); // For RF69 on PJRC breakout board with Teensy 3.1 //RH_RF69 rf69(4, 2); // For MoteinoMEGA https://lowpowerlab.com/shop/moteinomega +//RH_RF69 driver(8, 7); // Adafruit Feather 32u4 // Class to manage message delivery and receipt, using the driver declared above RHReliableDatagram manager(driver, SERVER_ADDRESS); @@ -25,6 +26,8 @@ RHReliableDatagram manager(driver, SERVER_ADDRESS); void setup() { Serial.begin(9600); + while (!Serial) + ; if (!manager.init()) Serial.println("init failed"); // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM diff --git a/examples/rf69/rf69_server/rf69_server.pde b/examples/rf69/rf69_server/rf69_server.pde index 05baccc..b056b6b 100644 --- a/examples/rf69/rf69_server/rf69_server.pde +++ b/examples/rf69/rf69_server/rf69_server.pde @@ -18,10 +18,13 @@ RH_RF69 rf69; //RH_RF69 rf69(15, 16); // For RF69 on PJRC breakout board with Teensy 3.1 //RH_RF69 rf69(4, 2); // For MoteinoMEGA https://lowpowerlab.com/shop/moteinomega +//RH_RF69 rf69(8, 7); // Adafruit Feather 32u4 void setup() { Serial.begin(9600); + while (!Serial) + ; if (!rf69.init()) Serial.println("init failed"); // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM diff --git a/project.cfg b/project.cfg index 8cf756b..722757c 100644 --- a/project.cfg +++ b/project.cfg @@ -1,4 +1,4 @@ -# Doxyfile 1.8.5 +# Doxyfile 1.8.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -70,15 +70,25 @@ OUTPUT_DIRECTORY = CREATE_SUBDIRS = NO +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese- -# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi, -# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en, -# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish, -# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, -# Turkish, Ukrainian and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English @@ -259,9 +269,12 @@ OPTIMIZE_OUTPUT_VHDL = NO # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # @@ -500,6 +513,13 @@ HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. @@ -521,7 +541,8 @@ SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member -# name. If set to NO the members will appear in declaration order. +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO @@ -659,8 +680,7 @@ LAYOUT_FILE = # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. Do not use file names with spaces, bibtex cannot handle them. See -# also \cite for info how to create references. +# search path. See also \cite for info how to create references. CITE_BIB_FILES = @@ -1049,13 +1069,15 @@ HTML_FOOTER = HTML_STYLESHEET = -# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- -# defined cascading style sheet that is included after the standard style sheets +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. -# Doxygen will copy the style sheet file to the output directory. For an example -# see the documentation. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra stylesheet files is of importance (e.g. the last +# stylesheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = @@ -1103,7 +1125,7 @@ HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. -# The default value is: NO. +# The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO @@ -1220,7 +1242,8 @@ GENERATE_CHI = NO CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( -# YES) or a normal table of contents ( NO) in the .chm file. +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1460,11 +1483,11 @@ SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using Javascript. There -# are two flavours of web server based searching depending on the -# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for -# searching and an index file used by the script. When EXTERNAL_SEARCH is -# enabled the indexing and searching needs to be provided by external tools. See -# the section "External Indexing and Searching" for details. +# are two flavors of web server based searching depending on the EXTERNAL_SEARCH +# setting. When disabled, doxygen will generate a PHP script for searching and +# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing +# and searching needs to be provided by external tools. See the section +# "External Indexing and Searching" for details. # The default value is: NO. # This tag requires that the tag SEARCHENGINE is set to YES. @@ -1592,17 +1615,19 @@ EXTRA_PACKAGES = # # Note: Only use a user-defined header if you know what you are doing! The # following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will -# replace them by respectively the title of the page, the current date and time, -# only the current date, the version number of doxygen, the project name (see -# PROJECT_NAME), or the project number (see PROJECT_NUMBER). +# $datetime, $date, $doxygenversion, $projectname, $projectnumber, +# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string, +# for the replacement values of the other commands the user is refered to +# HTML_HEADER. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the # generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. +# chapter. If it is left blank doxygen will generate a standard footer. See +# LATEX_HEADER for more information on how to generate a default footer and what +# special commands can be used inside the footer. # # Note: Only use a user-defined footer if you know what you are doing! # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1626,7 +1651,7 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = NO -# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate +# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate # the PDF file directly from the LaTeX files. Set this option to YES to get a # higher quality PDF documentation. # The default value is: YES. @@ -1752,6 +1777,13 @@ MAN_OUTPUT = man MAN_EXTENSION = .3 +# The MAN_SUBDIR tag determines the name of the directory created within +# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by +# MAN_EXTENSION with the initial . removed. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_SUBDIR = + # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it # will generate one additional man file for each entity documented in the real # man page(s). These additional files only source the real man page, but without @@ -1779,18 +1811,6 @@ GENERATE_XML = NO XML_OUTPUT = xml -# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a -# validating XML parser to check the syntax of the XML files. -# This tag requires that the tag GENERATE_XML is set to YES. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify a XML DTD, which can be used by a -# validating XML parser to check the syntax of the XML files. -# This tag requires that the tag GENERATE_XML is set to YES. - -XML_DTD = - # If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program # listings (including syntax highlighting and cross-referencing information) to # the XML output. Note that enabling this will significantly increase the size @@ -1818,6 +1838,15 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook +# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the +# program listings (including syntax highlighting and cross-referencing +# information) to the DOCBOOK output. Note that enabling this will significantly +# increase the size of the DOCBOOK output. +# The default value is: NO. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_PROGRAMLISTING = NO + #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- @@ -1937,9 +1966,9 @@ PREDEFINED = EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will -# remove all refrences to function-like macros that are alone on a line, have an -# all uppercase name, and do not end with a semicolon. Such function macros are -# typically used for boiler-plate code, and will confuse the parser if not +# remove all references to function-like macros that are alone on a line, have +# an all uppercase name, and do not end with a semicolon. Such function macros +# are typically used for boiler-plate code, and will confuse the parser if not # removed. # The default value is: YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. @@ -1959,7 +1988,7 @@ SKIP_FUNCTION_MACROS = YES # where loc1 and loc2 can be relative or absolute paths or URLs. See the # section "Linking to external documentation" for more information about the use # of tag files. -# Note: Each tag file must have an unique name (where the name does NOT include +# Note: Each tag file must have a unique name (where the name does NOT include # the path). If a tag file is not located in the directory in which doxygen is # run, you must also specify the path to the tagfile here. @@ -2019,6 +2048,13 @@ CLASS_DIAGRAMS = YES MSCGEN_PATH = +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. + +DIA_PATH = + # If set to YES, the inheritance and collaboration graphs will hide inheritance # and usage relations if the target is undocumented or is not a class. # The default value is: YES. @@ -2044,7 +2080,7 @@ HAVE_DOT = NO DOT_NUM_THREADS = 0 -# When you want a differently looking font n the dot files that doxygen +# When you want a differently looking font in the dot files that doxygen # generates you can specify the font name using DOT_FONTNAME. You need to make # sure dot is able to find the font, which can be done by putting it in a # standard location or by setting the DOTFONTPATH environment variable or by @@ -2219,6 +2255,21 @@ DOTFILE_DIRS = MSCFILE_DIRS = +# The DIAFILE_DIRS tag can be used to specify one or more directories that +# contain dia files that are included in the documentation (see the \diafile +# command). + +DIAFILE_DIRS = + +# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file. If left blank, it is assumed +# PlantUML is not used or called during a preprocessing step. Doxygen will +# generate a warning when it encounters a \startuml command in this case and +# will not generate output for the diagram. +# This tag requires that the tag HAVE_DOT is set to YES. + +PLANTUML_JAR_PATH = + # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes # that will be shown in the graph. If the number of nodes in a graph becomes # larger than this value, doxygen will truncate the graph, which is visualized