Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
5.3 KiB

  1. /*
  2. Radio
  3. RFM69 Radio Manager for ESP8266
  4. Based on sample code by Felix Rusu - http://LowPowerLab.com/contact
  5. Copyright (C) 2016 by Xose Pérez <xose dot perez at gmail dot com>
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. Requires encapsulating any reference to SPCR and SPSR in SPIFlash.cpp
  17. in an #if clause like this:
  18. #if defined(SPCR) & defined(SPSR)
  19. ...
  20. #endif
  21. */
  22. #include "RFM69Manager.h"
  23. bool RFM69Manager::initialize(uint8_t frequency, uint8_t nodeID, uint8_t networkID, const char* key, uint8_t gatewayID, int16_t targetRSSI) {
  24. bool ret = RFM69_ATC::initialize(frequency, nodeID, networkID);
  25. encrypt(key);
  26. _gatewayID = gatewayID;
  27. if (_gatewayID > 0) enableAutoPower(targetRSSI);
  28. if (_isRFM69HW) setHighPower();
  29. #if RADIO_DEBUG
  30. char buff[50];
  31. sprintf(buff, "[RADIO] Working at %d Mhz", frequency == RF69_433MHZ ? 433 : frequency == RF69_868MHZ ? 868 : 915);
  32. Serial.println(buff);
  33. Serial.print(F("[RADIO] Node: "));
  34. Serial.println(nodeID);
  35. Serial.print(F("[RADIO] Network: "));
  36. Serial.println(networkID);
  37. if (gatewayID == 0) {
  38. Serial.println("[RADIO] This node is a gateway");
  39. } else {
  40. Serial.print(F("[RADIO] Gateway: "));
  41. Serial.println(gatewayID);
  42. }
  43. Serial.println(F("[RADIO] Auto Transmission Control (ATC) enabled"));
  44. #endif
  45. return ret;
  46. }
  47. void RFM69Manager::promiscuous(bool promiscuous) {
  48. RFM69_ATC::promiscuous(promiscuous);
  49. #if RADIO_DEBUG
  50. if (_promiscuousMode) {
  51. Serial.println(F("[RADIO] Promiscuous mode ON"));
  52. } else {
  53. Serial.println(F("[RADIO] Promiscuous mode OFF"));
  54. }
  55. #endif
  56. }
  57. // overriding select the RFM69 transceiver (save SPI settings, set CS low)
  58. void RFM69Manager::select() {
  59. noInterrupts();
  60. #if defined (SPCR) && defined (SPSR)
  61. // save current SPI settings
  62. _SPCR = SPCR;
  63. _SPSR = SPSR;
  64. #endif
  65. // set RFM69 SPI settings
  66. SPI.setDataMode(SPI_MODE0);
  67. SPI.setBitOrder(MSBFIRST);
  68. #if defined(ARDUINO_ARCH_ESP8266)
  69. SPI.setClockDivider(SPI_CLOCK_DIV2); // speeding it up for the ESP8266
  70. #else
  71. SPI.setClockDivider(SPI_CLOCK_DIV4);
  72. #endif
  73. digitalWrite(_slaveSelectPin, LOW);
  74. }
  75. void RFM69Manager::onMessage(TMessageCallback fn) {
  76. _callback = fn;
  77. }
  78. void RFM69Manager::separator(char sep) {
  79. _separator = sep;
  80. }
  81. bool RFM69Manager::loop() {
  82. boolean ret = false;
  83. if (receiveDone()) {
  84. uint8_t senderID = SENDERID;
  85. uint8_t targetID = _promiscuousMode ? TARGETID : _address;
  86. int16_t rssi = RSSI;
  87. uint8_t length = DATALEN;
  88. char buffer[length + 1];
  89. strncpy(buffer, (const char *) DATA, length);
  90. buffer[length] = 0;
  91. // Do not send ACKs in promiscuous mode,
  92. // we want to listen without being heard
  93. if (!_promiscuousMode) {
  94. if (ACKRequested()) sendACK();
  95. }
  96. uint8_t parts = 1;
  97. for (uint8_t i=0; i<length; i++) {
  98. if (buffer[i] == _separator) ++parts;
  99. }
  100. if (parts > 1) {
  101. char sep[2] = {_separator, 0};
  102. uint8_t packetID = 0;
  103. char * name = strtok(buffer, sep);
  104. char * value = strtok(NULL, sep);
  105. if (parts > 2) {
  106. char * packet = strtok(NULL, sep);
  107. packetID = atoi(packet);
  108. }
  109. _message.messageID = ++_receiveCount;
  110. _message.packetID = packetID;
  111. _message.senderID = senderID;
  112. _message.targetID = targetID;
  113. _message.name = name;
  114. _message.value = value;
  115. _message.rssi = rssi;
  116. ret = true;
  117. if (_callback != NULL) {
  118. _callback(&_message);
  119. }
  120. }
  121. }
  122. return ret;
  123. }
  124. bool RFM69Manager::send(uint8_t destinationID, char * name, char * value, uint8_t retries, bool requestACK) {
  125. char message[RF69_MAX_DATA_LEN];
  126. #if SEND_PACKET_ID
  127. if (++_sendCount == 0) _sendCount = 1;
  128. snprintf(message, RF69_MAX_DATA_LEN-1, "%s%c%s%c%d", name, _separator, value, _separator, _sendCount);
  129. #else
  130. snprintf(message, RF69_MAX_DATA_LEN-1, "%s%c%s", name, _separator, value);
  131. #endif
  132. #if RADIO_DEBUG
  133. Serial.print(F("[RADIO] Sending: "));
  134. Serial.print(message);
  135. #endif
  136. bool ret = true;
  137. if (retries > 0) {
  138. ret = sendWithRetry(destinationID, message, strlen(message), retries);
  139. } else {
  140. RFM69_ATC::send(destinationID, message, strlen(message), requestACK);
  141. }
  142. #if RADIO_DEBUG
  143. if (ret) {
  144. Serial.println(" OK");
  145. } else {
  146. Serial.println(" KO");
  147. }
  148. #endif
  149. return ret;
  150. }