diff --git a/README.md b/README.md index 689de3ef..75846c9a 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ You may use: ## 2. Receiver / Transmitter / Transceiver -We mainly use RXB6 receiver. +As a starting point, you can use the RXB6 receiver. It is simple, steady, running on 3.3v, easy to find and cheap. Many other receivers will do! @@ -31,6 +31,29 @@ Simply *** Please avoid generic noname receiver *** ![Receivers](https://github.com/cpainchaud/RFLink32/blob/master/pictures/RFLink-ESP_Receivers.jpg "Receivers") +For more advanced behavior and reliability, the following receivers are also supported when used with an ESP32 board: + +* SX1278 +* SX1276 +* RFM69CW +* RFM69HCW +* CC1101 + +Those advanced receivers require a few pins to be connected to the host, here are the recommended pin assignments: + +| Name | ESP32 | SX1278/6 | RFM69(H)CW | CC1101 | +|---------------|-------|----------|------------|--------| +| | 3v3 | VCC | 3.3V | VCC | +| | GND | GND | GND | GND | +| | 18 | SCK | SCK | SCK | +| | 19 | MISO | MISO | MISO | +| | 23 | MOSI | MOSI | MOSI | +| pins::RX_RESET| 4¹ | NRESET | RESET | | +| pins::RX_CS | 5¹ | NSS | NSS | CSN | +| pins::RX_DATA
pins::TX_DATA | 26¹ | DIO2 | DIO2 | GDO0 | + +¹ *These must be configured in the web portal, values suggested here are proven to work reliably.* + ## 3. OLED display You can use an OLED display! We used SSD1306 128x64 I2C screen for our testings. diff --git a/RFLink/1_Radio.cpp b/RFLink/1_Radio.cpp index acdb3341..b3b2fcc7 100644 --- a/RFLink/1_Radio.cpp +++ b/RFLink/1_Radio.cpp @@ -21,6 +21,7 @@ Module radioLibModule(5, -1, 4, -1); SX1278 *radio_SX1278 = nullptr; SX1276 *radio_SX1276 = nullptr; RF69 *radio_RFM69 = nullptr; +CC1101 *radio_CC1101 = nullptr; #endif #define setPinMode(pin, mode) if (pin != -1) pinMode(pin, mode) @@ -96,6 +97,7 @@ namespace RFLink { namespace Radio { "RFM69HCW", "SX1278", "SX1276", + "CC1101", #endif "EOF" // this is always the last one and matches index HardareType::HW_EOF_t }; @@ -357,7 +359,15 @@ namespace RFLink { namespace Radio { } else { value = item->getLongIntValue(); - if (value < 0 || value > 500000 ) { + + long maxValue = 500000; + switch (newHardwareId) + { + case HardwareType::HW_CC1101_t: + maxValue = 812000; + } + + if (value < 0 || value > maxValue ) { Serial.println(F("Invalid rxBandwidth provided, resetting to default value")); if(item->canBeNull) { item->deleteJsonRecord(); @@ -436,6 +446,9 @@ namespace RFLink { namespace Radio { case HardwareType::HW_SX1276_t: radio_SX1276->setFrequency(newFrequency / 1000000.0); break; + case HardwareType::HW_CC1101_t: + radio_CC1101->setFrequency(newFrequency / 1000000.0); + break; #endif default: @@ -575,6 +588,8 @@ namespace RFLink { namespace Radio { set_Radio_mode_SX1278(new_State, force); else if( hardware == HardwareType::HW_SX1276_t ) set_Radio_mode_SX1276(new_State, force); + else if( hardware == HardwareType::HW_CC1101_t ) + set_Radio_mode_CC1101(new_State, force); #endif // RFLINK_NO_RADIOLIB_SUPPORT else Serial.printf_P(PSTR("Error while trying to switch Radio state: unknown hardware id '%i'\r\n"), new_State); @@ -852,6 +867,66 @@ namespace RFLink { namespace Radio { current_State = new_State; } } + + void set_Radio_mode_CC1101(States new_State, bool force) + { + // @TODO : review compatibility with ASYNC mode + if (current_State != new_State || force) + { + switch (new_State) + { + case Radio_OFF: { + ::detachInterrupt(digitalPinToInterrupt(pins::RX_NA)); + + if( RFLink::Signal::params::async_mode_enabled ) + RFLink::Signal::AsyncSignalScanner::stopScanning(); + + auto success = radio_CC1101->standby(); + if(success != 0 ){ + Serial.printf_P(PSTR("Failed to switch to standby mode (code=%i), we will try to reinitialize it later\r\n"), (int) success); + hardwareProperlyInitialized = false; + } + break; + } + + case Radio_RX: { + + auto success = radio_CC1101->receiveDirectAsync(); + if(success != 0 ) { + Serial.printf_P(PSTR("ERROR: CC1101 receiveDirect()=%i, we will try to reinitialize it later\r\n"), (int) success); + hardwareProperlyInitialized = false; + } + + pinMode(pins::RX_DATA, INPUT); + + if( RFLink::Signal::params::async_mode_enabled ) + RFLink::Signal::AsyncSignalScanner::startScanning(); + + break; + } + + case Radio_TX: { + + if( RFLink::Signal::params::async_mode_enabled ) + RFLink::Signal::AsyncSignalScanner::stopScanning(); + + pinMode(pins::TX_DATA, OUTPUT); + + auto success = radio_CC1101->transmitDirectAsync(); + if(success != 0 ) { + Serial.printf_P(PSTR("Failed to switch to TX mode (code=%i), we will try to reinitialize it later\r\n"), (int) success); + hardwareProperlyInitialized = false; + } + + break; + } + + case Radio_NA: + break; + } + current_State = new_State; + } + } #endif // RFLINK_NO_RADIOLIB_SUPPORT @@ -863,6 +938,8 @@ namespace RFLink { namespace Radio { return radio_SX1276->getRSSI(true); if(hardware == HardwareType::HW_RFM69CW_t || hardware == HardwareType::HW_RFM69HCW_t) return radio_RFM69->getRSSI(); + if(hardware == HardwareType::HW_CC1101_t) + return radio_CC1101->getRSSI(); #endif return -9999.0F; @@ -902,6 +979,9 @@ namespace RFLink { namespace Radio { else if(newHardware == HardwareType::HW_RFM69CW_t || newHardware == HardwareType::HW_RFM69HCW_t){ success = initialize_RFM69(); } + else if(newHardware == HardwareType::HW_CC1101_t){ + success = initialize_CC1101(); + } #endif else { RFLink::sendRawPrint(F("Unsupported hardwareId=")); @@ -1129,6 +1209,43 @@ namespace RFLink { namespace Radio { return finalResult == 0; } + + bool initialize_CC1101() { + + radioLibModule = Module(pins::RX_CS, -1, pins::RX_RESET, pins::RX_NA); + if(radio_CC1101 == nullptr) + radio_CC1101 = new CC1101(&radioLibModule); + else + *radio_CC1101 = &radioLibModule; + + int finalResult = 0; + + auto result = radio_CC1101->begin( (float)params::frequency/1000000, + (float)params::bitrate/1000, + 50.0F, + (float)params::rxBandwidth/1000, + 7, 16); + Serial.printf_P(PSTR("Initialized CC1101(freq=%.2fMhz,br=%.3fkbps,rxbw=%.1fkhz)=%i\r\n"), + (float)params::frequency/1000000, + (float)params::bitrate/1000, + (float)params::rxBandwidth/1000, + result); + finalResult |= result; + + result = radio_CC1101->setOOK(true); + Serial.printf_P(PSTR("CC1101 SetOOK(true)=%i\r\n"), result); + finalResult |= result; + + result = radio_CC1101->setPromiscuousMode(true); + Serial.printf_P(PSTR("CC1101 setPromiscuousMode(true)=%i\r\n"), result); + finalResult |= result; + + result = radio_CC1101->disableSyncWordFiltering(true); + Serial.printf_P(PSTR("CC1101 disableSyncWordFiltering(true)=%i\r\n"), result); + finalResult |= result; + + return finalResult == 0; + } #endif // RFLINK_NO_RADIOLIB_SUPPORT diff --git a/RFLink/1_Radio.h b/RFLink/1_Radio.h index 5cd9ce3a..78ba9b53 100644 --- a/RFLink/1_Radio.h +++ b/RFLink/1_Radio.h @@ -183,6 +183,7 @@ namespace RFLink { namespace Radio { HW_RFM69HCW_t, HW_SX1278_t, HW_SX1276_t, + HW_CC1101_t, #endif HW_EOF_t, }; @@ -254,6 +255,10 @@ namespace RFLink { namespace Radio { * don't use directly unless you know what you are doing. * */ void set_Radio_mode_SX1276(States new_state, bool force=false); + /** + * don't use directly unless you know what you are doing. + * */ + void set_Radio_mode_CC1101(States new_state, bool force=false); /** * don't use directly unless you know what you are doing. @@ -283,7 +288,7 @@ namespace RFLink { namespace Radio { bool initialize_SX1278(); bool initialize_SX1276(); bool initialize_RFM69(); - + bool initialize_CC1101(); }} diff --git a/RFLink/2_Signal.cpp b/RFLink/2_Signal.cpp index def4d515..25e70676 100644 --- a/RFLink/2_Signal.cpp +++ b/RFLink/2_Signal.cpp @@ -25,6 +25,7 @@ namespace RFLink RawSignalStruct RawSignal = {0, 0, 0, 0, 0UL, false, -9999.0F, EndReasons::Unknown}; // current message #define SLICER_DEFAULT_RFM69 Slicer_enum::Legacy + #define SLICER_DEFAULT_CC1101 Slicer_enum::Legacy #define SLICER_DEFAULT_SX1278 Slicer_enum::RSSI_Advanced namespace commands @@ -1176,6 +1177,8 @@ namespace RFLink runtime::appliedSlicer = SLICER_DEFAULT_SX1278; else if(Radio::hardware == Radio::HardwareType::HW_RFM69HCW_t || Radio::hardware == Radio::HardwareType::HW_RFM69CW_t ) runtime::appliedSlicer = SLICER_DEFAULT_RFM69; + else if(Radio::hardware == Radio::HardwareType::HW_CC1101_t ) + runtime::appliedSlicer = SLICER_DEFAULT_CC1101; #endif } else {