From c317dd9cea48d3dbaeb145829a8a045ffba9fc55 Mon Sep 17 00:00:00 2001 From: eadmaster <925171+eadmaster@users.noreply.github.com> Date: Thu, 8 Aug 2024 20:34:37 +0200 Subject: [PATCH] reworked cc1101 init, added settings RfModule and RfFreq (#139), added subghz tx cmd --- platformio.ini | 75 +++++++++-- src/core/globals.h | 4 + src/core/main_menu.cpp | 4 + src/core/serialcmds.cpp | 53 +++++--- src/core/settings.cpp | 279 ++++++++++++++++++++++++---------------- src/core/settings.h | 4 + src/main.cpp | 7 +- src/modules/rf/rf.cpp | 212 +++++++++++++++++++----------- src/modules/rf/rf.h | 4 +- 9 files changed, 422 insertions(+), 220 deletions(-) diff --git a/platformio.ini b/platformio.ini index 577d6228..0dcb2e57 100644 --- a/platformio.ini +++ b/platformio.ini @@ -47,7 +47,8 @@ lib_deps = ESP8266SAM TinyGPSPlus tinyu-zhao/FFT@^0.0.1 - lsatan/SmartRC-CC1101-Driver-Lib@^2.5.7 + ;lsatan/SmartRC-CC1101-Driver-Lib@^2.5.7 + https://github.com/bmorcelli/SmartRC-CC1101-Driver-Lib [env:m5stack-cplus2] platform = espressif32 @@ -101,6 +102,15 @@ build_flags = -DRF_TX_PINS='{ {"M5 RF433T", GROVE_SDA}, {"G26",26}, {"G25",25}, {"G0",0}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' -DRF_RX_PINS='{ {"M5 RF433R", GROVE_SCL}, {"G26",26}, {"G25",25}, {"G0",0}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' + ; connection pins for CC1101 https://github.com/bmorcelli/io433/blob/master/platformio.ini + -DUSE_CC1101_VIA_SPI + -DCC1101_GDO0_PIN=25 + -DCC1101_SS_PIN=26 ; chip select + -DCC1101_MOSI_PIN=32 + -DCC1101_SCK_PIN=0 + -DCC1101_MISO_PIN=33 + ;-DCC1101_GDO2_PIN=-1 + ;Battery ADC read pin -DBAT_PIN=38 @@ -189,6 +199,15 @@ build_flags = -DRF_TX_PINS='{ {"M5 RF433T", GROVE_SDA}, {"G26",26}, {"G25",25}, {"G0",0}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' -DRF_RX_PINS='{ {"M5 RF433R", GROVE_SCL}, {"G26",26}, {"G25",25}, {"G0",0}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' + ; connection pins for CC1101 https://github.com/bmorcelli/io433/blob/master/platformio.ini + -DUSE_CC1101_VIA_SPI + -DCC1101_GDO0_PIN=25 + -DCC1101_SS_PIN=26 ; chip select + -DCC1101_MOSI_PIN=32 + -DCC1101_SCK_PIN=0 + -DCC1101_MISO_PIN=33 + ;-DCC1101_GDO2_PIN=-1 + ;Battery ADC read pin -DBAT_PIN=10 @@ -292,7 +311,16 @@ build_flags = ;Radio Frequency (one pin modules) pin setting -DRF_TX_PINS='{ {"M5 RF433T", GROVE_SDA}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' -DRF_RX_PINS='{ {"M5 RF433R", GROVE_SCL}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' - + -DUSE_CC1101_VIA_SPI + ; connection pins using microSD sniffer module https://www.sparkfun.com/products/9419 https://docs.m5stack.com/en/core/Cardputer + -DUSE_CC1101_VIA_SPI + -DCC1101_GDO0_PIN=GROVE_SDA + -DCC1101_SS_PIN=GROVE_SCL ; chip select + -DCC1101_MOSI_PIN=14 + -DCC1101_SCK_PIN=40 + -DCC1101_MISO_PIN=39 + ;-DCC1101_GDO2_PIN=-1 + ;Screen Setup -DHAS_SCREEN=1 -DROTATION=1 @@ -689,33 +717,50 @@ framework = arduino build_flags = ${common.build_flags} -DESP32S3DEVKITC1 - -DUSB_as_HID=1 + -DUSB_as_HID=1 ; needed for serial -DARDUINO_USB_CDC_ON_BOOT=1 + + ; grove pins + ; defaults from https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h + -DGROVE_SDA=8 ; default RF TX pin + -DGROVE_SCL=9 ; default IR/RF RX pin + ;-DALLOW_ALL_GPIO_FOR_IR_RF=1 ; Set this option to make use of all GPIOs, from 1 to 44 to be chosen, except TFT and SD pins + ; ir led pin + -DIR_TX_PINS='{{"M5 IR Mod", GROVE_SDA}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' + -DIR_RX_PINS='{{"M5 IR Mod", GROVE_SCL}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' -DLED=40 -DLED_ON=HIGH -DLED_OFF=LOW + + ;Radio Frequency (one pin modules) pin setting + -DRF_TX_PINS='{{"M5 RF433T", GROVE_SDA}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' + -DRF_RX_PINS='{{"M5 RF433R", GROVE_SCL}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' + ; sd card pins ; suggested https://github.com/espressif/esp-idf/tree/master/examples/storage/sd_card/sdmmc -DSDCARD_CS=-1 -DSDCARD_SCK=-1 -DSDCARD_MISO=-1 -DSDCARD_MOSI=-1 - ; grove pins (SDA=default TX pin, SCL=default RX pin, for both IR and RF) - ; defaults from https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h - -DGROVE_SDA=8 ; default RF TX pin - -DGROVE_SCL=9 ; default IR/RF RX pin + ; tft vars -DROTATION=1 -DBACKLIGHT=-1 ; tft backlight pin -DWIDTH=240 -DHEIGHT=135 -DMINBRIGHT=160 ; unused? - -DSMOOTH_FONT=1 -DTFT_DISPON=0x29 -DTFT_DISPOFF=0x28 + -DTFT_CS=-1 + -DTFT_DC=-1 + -DTFT_RST=-1 + -DTOUCH_CS=-1 + -DTFT_MOSI=-1 + -DTFT_SCLK=-1 + -DTFT_BL=-1 ; text sizes -DFP=1 -DFM=2 @@ -725,21 +770,23 @@ build_flags = ;-DUP_BTN=2 ; also work as ESC ;-DDW_BTN=3 ; also work as NEXT -DBTN_ALIAS='"OK"' + ;Microphone ;-DMIC_SPM1423=1 ; uncomment to enable Applicable for SPM1423 device ;-DPIN_CLK=-1 ;-DI2S_SCLK_PIN=-1 ;-DI2S_DATA_PIN=-1 ;-DPIN_DATA=-1 - ;CC1101 SPI connection pins, can use any on this board https://esp32.com/viewtopic.php?t=37729 + + ;CC1101 SPI connection pins ; best connection pins for higher speed https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/spi_master.html#gpio-matrix-and-io-mux -DUSE_CC1101_VIA_SPI - -DCC1101_GDO0_PIN=9 ; RFSend (SPI2_IOMUX_PIN_NUM_HD / FSPIHD) - -DCC1101_SS_PIN=10 - -DCC1101_MOSI_PIN=11 + -DCC1101_GDO0_PIN=9 + -DCC1101_SS_PIN=10 + -DCC1101_MOSI_PIN=11 -DCC1101_SCK_PIN=12 - -DCC1101_MISO_PIN=13 - -DCC1101_GDO2_PIN=14 ; RFRecv (SPI2_IOMUX_PIN_NUM_CS / FSPIWP) + -DCC1101_MISO_PIN=13 + ;-DCC1101_GDO2_PIN=14 ; optional lib_deps = ${common.lib_deps} diff --git a/src/core/globals.h b/src/core/globals.h index d977c99f..b5a1a3ba 100644 --- a/src/core/globals.h +++ b/src/core/globals.h @@ -89,6 +89,10 @@ extern int RfTx; extern int RfRx; +extern int RfModule; + +extern float RfFreq; + // Screen sleep control variables extern unsigned long previousMillis; extern bool isSleeping; diff --git a/src/core/main_menu.cpp b/src/core/main_menu.cpp index fc88ccc6..849eb8bc 100644 --- a/src/core/main_menu.cpp +++ b/src/core/main_menu.cpp @@ -183,6 +183,10 @@ void configOptions(){ {"Ir RX Pin", [=]() { gsetIrRxPin(true); saveConfigs();}}, {"RF TX Pin", [=]() { gsetRfTxPin(true); saveConfigs();}}, {"RF RX Pin", [=]() { gsetRfRxPin(true); saveConfigs();}}, +#ifdef USE_CC1101_VIA_SPI + {"RF Module", [=]() { setRFModuleMenu(); saveConfigs();}}, +#endif + {"RF Frequency", [=]() { setRFFreqMenu(); saveConfigs();}}, {"Sleep", [=]() { setSleepMode(); }}, {"Restart", [=]() { ESP.restart(); }}, {"Main Menu", [=]() { backToMenu(); }}, diff --git a/src/core/serialcmds.cpp b/src/core/serialcmds.cpp index 7a22fc8e..fa454794 100644 --- a/src/core/serialcmds.cpp +++ b/src/core/serialcmds.cpp @@ -82,12 +82,6 @@ void handleSerialCommands() { // try again on next iteration return; } - - //log_d(cmd_str.c_str()); - cmd_str.trim(); - // case-insensitive matching only without filename args -- TODO: better solution for this - if(cmd_str.indexOf("from_file ") == -1) - cmd_str.toLowerCase(); bool r = processSerialCommand(cmd_str); if(r) setup_gpio(); // temp fix for menu inf. loop @@ -96,15 +90,24 @@ void handleSerialCommands() { bool processSerialCommand(String cmd_str) { // return true on success, false on error + // TODO: rewrite using https://github.com/SpacehuhnTech/SimpleCLI (auto-generated help and args checking) + + cmd_str.trim(); - if(cmd_str == "" ) { // empty + if(cmd_str == "" || cmd_str.startsWith("#") || cmd_str.startsWith(";") || cmd_str.startsWith("/")) { + // ignore empty lines and comments return false; } + // case-insensitive matching only without filename args -- TODO: better solution for this + if(cmd_str.indexOf("from_file ") == -1) + cmd_str.toLowerCase(); + + // switch on cmd_str if(cmd_str.startsWith("ir") ) { - gsetIrTxPin(false); - //if(IrTx==0) IrTx = LED; // quickfix init issue? CARDPUTER is 44 + gsetIrTxPin(false); + //if(IrTx==0) IrTx = LED; // quickfix init issue? CARDPUTER is 44 // ir tx
// : NEC, NECext, NEC42, NEC42ext, Samsung32, RC6, RC5, RC5X, SIRC, SIRC15, SIRC20, Kaseikyo, RCA @@ -203,11 +206,13 @@ bool processSerialCommand(String cmd_str) { if(cmd_str.startsWith("rf") || cmd_str.startsWith("subghz" )) { - if(cmd_str.startsWith("subghz rx")) { - float frequency=433.92; // TODO: custom frequency passed as arg. valid ranges for cc1101: 300-348 MHZ, 387-464MHZ and 779-928MHZ. - //String frequency_arg = cmd_str.substring(strlen("subghz rx"), cmd_str.length()); - RCSwitch_Read_Raw(frequency); - return true; + if(cmd_str.startsWith("subghz rx")) { + const char* args = cmd_str.c_str() + strlen("subghz rx"); + float frequency=RfFreq; // global default + if(strlen(args)>1) sscanf(args, " %f", &frequency); + //Serial.print("frequency:"); + //Serial.println((int) frequency); + return RCSwitch_Read_Raw(frequency); } if(cmd_str.startsWith("subghz tx_from_file")) { String filepath = cmd_str.substring(strlen("subghz tx_from_file "), cmd_str.length()); @@ -219,13 +224,25 @@ bool processSerialCommand(String cmd_str) { // else file not found return false; } - /* TODO: + if(cmd_str.startsWith("subghz tx")) { // flipperzero-like cmd https://docs.flipper.net/development/cli/#wLVht // e.g. subghz tx 0000000000200001 868250000 403 10 // https://forum.flipper.net/t/friedland-libra-48249sl-wireless-doorbell-request/4528/20 // {hex_key} {frequency} {te} {count} - * //RCSwitch_send( hexStringToDecimal(txt.c_str()) , bits, pulse, protocol, repeat); - }*/ + // subghz tx 000000000044553C 433920000 174 10 + const char* args = cmd_str.c_str() + strlen("subghz tx"); + uint64_t key=0; + unsigned long frequency=433920000; + unsigned int te=0; + unsigned int count=10; + if(strlen(args)<=1) return false; + if(sscanf(args, " %llx %lu %u %u", &key, &frequency, &te, &count)<=0) return false; // missing 1 req arg + if(!initRfModule("tx", float(frequency/1000000.0))) return false; // check valid frequency and init the rf module + unsigned int bits=64; // TODO: compute from key + //RCSwitch_send( hexStringToDecimal(txt.c_str()) , bits, pulse, protocol, repeat); + RCSwitch_send( key, bits, te, 1, count ); + return true; + } if(cmd_str.startsWith("rfsend")) { // tasmota json command https://tasmota.github.io/docs/RF-Protocol/ @@ -265,6 +282,8 @@ bool processSerialCommand(String cmd_str) { //Serial.println(dataStr); //SerialPrintHexString(data); //Serial.println(bits); + + if(!initRfModule("tx")) return false; RCSwitch_send(data, bits, pulse, protocol, repeat); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 6ec7e03c..eb987d49 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -6,6 +6,8 @@ #include "sd_functions.h" #include "powerSave.h" #include +#include "modules/rf/rf.h" // for initRfModule + /* EEPROM ADDRESSES MAP @@ -233,6 +235,57 @@ void setUIColor(){ EEPROM.end(); } +/********************************************************************* +** Function: setRFModuleMenu +** Handles Menu to set the RF module in use +**********************************************************************/ +void setRFModuleMenu() { + // TODO: save the setting in the EEPROM too? + int result = 0; + + options = { + {"M5 RF433T/R", [&]() { result = 0; }}, + {"CC1101 via SPI", [&]() { result = 1; }}, + }; + delay(200); + loopOptions(options); + delay(200); + + RfModule=result; +} + +/********************************************************************* +** Function: setRFFreqMenu +** Handles Menu to set the default frequency for the RF module +**********************************************************************/ +void setRFFreqMenu() { + // TODO: save the setting in the EEPROM too? + float result = 433.92; + String freq_str = keyboard("433.92", 10, "Default frequency:"); + if(freq_str.length()>1) + if(sscanf(freq_str.c_str(), "%f", &result)==1) + { + if(RfModule!=1 && result>100 && result<1000 ) + { + // cannot verify the freq for these modules, just assume it is correct + RfFreq=result; + return; + } + else if(RfModule==1) + { + // check if valid frequency + if(initRfModule("tx", result)) + { + RfFreq=result; + return; + } + } + } + // else + displayError("Invalid frequency"); +} + + /********************************************************************* ** Function: setClock ** Handles Menu to set timezone to NTP @@ -569,127 +622,135 @@ int gsetRfRxPin(bool set){ void getConfigs() { bool EEPROMSave=false; int count=0; - if(setupSdCard()) { - if(!SD.exists(CONFIG_FILE)) { - File file; - file = SD.open(CONFIG_FILE, FILE_WRITE); - if(file) { - #if ROTATION >1 - file.print("[{\"rot\":3,\"dimmerSet\":10,\"bright\":100,\"wui_usr\":\"admin\",\"wui_pwd\":\"bruce\",\"Bruce_FGCOLOR\":43023,\"IrTx\":"+String(LED)+",\"IrRx\":"+String(GROVE_SCL)+",\"RfTx\":"+String(GROVE_SDA)+",\"RfRx\":"+String(GROVE_SCL)+",\"tmz\":3,\"wifi\":[{\"ssid\":\"myNetSSID\",\"pwd\":\"myNetPassword\"}]}]"); - #else - file.print("[{\"rot\":1,\"dimmerSet\":10,\"bright\":100,\"wui_usr\":\"admin\",\"wui_pwd\":\"bruce\",\"Bruce_FGCOLOR\":43023,\"IrTx\":"+String(LED)+",\"IrRx\":"+String(GROVE_SCL)+",\"RfTx\":"+String(GROVE_SDA)+",\"RfRx\":"+String(GROVE_SCL)+",\"tmz\":3,\"wifi\":[{\"ssid\":\"myNetSSID\",\"pwd\":\"myNetPassword\"}]}]"); - #endif - } - file.close(); - delay(50); - } else log_i("getConfigs: config.conf exists"); + FS* fs = &LittleFS; + if(setupSdCard()) fs = &SD; + if(!fs->exists(CONFIG_FILE)) { File file; - file = SD.open(CONFIG_FILE, FILE_READ); - if(file) { - // Deserialize the JSON document - DeserializationError error; - JsonObject setting; - error = deserializeJson(settings, file); - if (error) { - log_i("Failed to read file, using default configuration"); - goto Default; - } else log_i("getConfigs: deserialized correctly"); - - setting = settings[0]; - if(setting.containsKey("bright")) { bright = setting["bright"].as(); } else { count++; log_i("Fail"); } - if(setting.containsKey("dimmerSet")) { dimmerSet = setting["dimmerSet"].as(); } else { count++; log_i("Fail"); } - if(setting.containsKey("rot")) { rotation = setting["rot"].as(); } else { count++; log_i("Fail"); } - if(setting.containsKey("Bruce_FGCOLOR")) { FGCOLOR = setting["Bruce_FGCOLOR"].as(); } else { count++; log_i("Fail"); } - if(setting.containsKey("wui_usr")) { wui_usr = setting["wui_usr"].as(); } else { count++; log_i("Fail"); } - if(setting.containsKey("wui_pwd")) { wui_pwd = setting["wui_pwd"].as(); } else { count++; log_i("Fail"); } - - if(setting.containsKey("IrTx")) { IrTx = setting["IrTx"].as(); } else { count++; log_i("Fail"); } - if(setting.containsKey("IrRx")) { IrRx = setting["IrRx"].as(); } else { count++; log_i("Fail"); } - if(setting.containsKey("RfTx")) { RfTx = setting["RfTx"].as(); } else { count++; log_i("Fail"); } - if(setting.containsKey("RfRx")) { RfRx = setting["RfRx"].as(); } else { count++; log_i("Fail"); } - if(setting.containsKey("tmz")) { tmz = setting["tmz"].as(); } else { count++; log_i("Fail"); } - - if(!setting.containsKey("wifi")) { count++; log_i("Fail"); } - - log_i("Brightness: %d", bright); - setBrightness(bright); - if(dimmerSet<10) dimmerSet=10; - file.close(); - if(count>0) saveConfigs(); - - count=0; - EEPROM.begin(EEPROMSIZE); // open eeprom - if(EEPROM.read(0)!= rotation) { EEPROM.write(0, rotation); count++; } - if(EEPROM.read(1)!= dimmerSet) { EEPROM.write(1, dimmerSet); count++; } - if(EEPROM.read(2)!= bright) { EEPROM.write(2, bright); count++; } - if(EEPROM.read(6)!= IrTx) { EEPROM.write(6, IrTx); count++; } - if(EEPROM.read(7)!= IrRx) { EEPROM.write(7, IrRx); count++; } - if(EEPROM.read(8)!= RfTx) { EEPROM.write(8, RfTx); count++; } - if(EEPROM.read(9)!= RfRx) { EEPROM.write(9, RfRx); count++; } - if(EEPROM.read(10)!= tmz) { EEPROM.write(10, tmz); count++; } - if(EEPROM.read(11)!=(int((FGCOLOR >> 8) & 0x00FF))) {EEPROM.write(11, int((FGCOLOR >> 8) & 0x00FF)); count++; } - if(EEPROM.read(12)!= int(FGCOLOR & 0x00FF)) { EEPROM.write(12, int(FGCOLOR & 0x00FF)); count++; } - //If something changed, saves the changes on EEPROM. - if(count>0) { - if(!EEPROM.commit()) log_i("fail to write EEPROM"); // Store data to EEPROM - } else log_i("Wrote new conf to EEPROM"); - EEPROM.end(); - log_i("Using config.conf setup file"); - } else { - goto Default; - log_i("Using settings stored on EEPROM"); + file = fs->open(CONFIG_FILE, FILE_WRITE); + if(file) { + // init with default settings + #if ROTATION >1 + file.print("[{\"rot\":3,\"dimmerSet\":10,\"bright\":100,\"wui_usr\":\"admin\",\"wui_pwd\":\"bruce\",\"Bruce_FGCOLOR\":43023,\"IrTx\":"+String(LED)+",\"IrRx\":"+String(GROVE_SCL)+",\"RfTx\":"+String(GROVE_SDA)+",\"RfRx\":"+String(GROVE_SCL)+",\"tmz\":3,\"RfModule\":0,\"RfFreq\":433.92,\"wifi\":[{\"ssid\":\"myNetSSID\",\"pwd\":\"myNetPassword\"}]}]"); + #else + file.print("[{\"rot\":1,\"dimmerSet\":10,\"bright\":100,\"wui_usr\":\"admin\",\"wui_pwd\":\"bruce\",\"Bruce_FGCOLOR\":43023,\"IrTx\":"+String(LED)+",\"IrRx\":"+String(GROVE_SCL)+",\"RfTx\":"+String(GROVE_SDA)+",\"RfRx\":"+String(GROVE_SCL)+",\"tmz\":3,\"RfModule\":0,\"RfFreq\":433.92,\"wifi\":[{\"ssid\":\"myNetSSID\",\"pwd\":\"myNetPassword\"}]}]"); + #endif } + file.close(); + delay(50); + } else log_i("getConfigs: config.conf exists"); + + File file; + file = fs->open(CONFIG_FILE, FILE_READ); + if(file) { + // Deserialize the JSON document + DeserializationError error; + JsonObject setting; + error = deserializeJson(settings, file); + if (error) { + log_i("Failed to read file, using default configuration"); + goto Default; + } else log_i("getConfigs: deserialized correctly"); + + setting = settings[0]; + if(setting.containsKey("bright")) { bright = setting["bright"].as(); } else { count++; log_i("Fail"); } + if(setting.containsKey("dimmerSet")) { dimmerSet = setting["dimmerSet"].as(); } else { count++; log_i("Fail"); } + if(setting.containsKey("rot")) { rotation = setting["rot"].as(); } else { count++; log_i("Fail"); } + if(setting.containsKey("Bruce_FGCOLOR")) { FGCOLOR = setting["Bruce_FGCOLOR"].as(); } else { count++; log_i("Fail"); } + if(setting.containsKey("wui_usr")) { wui_usr = setting["wui_usr"].as(); } else { count++; log_i("Fail"); } + if(setting.containsKey("wui_pwd")) { wui_pwd = setting["wui_pwd"].as(); } else { count++; log_i("Fail"); } + + if(setting.containsKey("IrTx")) { IrTx = setting["IrTx"].as(); } else { count++; log_i("Fail"); } + if(setting.containsKey("IrRx")) { IrRx = setting["IrRx"].as(); } else { count++; log_i("Fail"); } + if(setting.containsKey("RfTx")) { RfTx = setting["RfTx"].as(); } else { count++; log_i("Fail"); } + if(setting.containsKey("RfRx")) { RfRx = setting["RfRx"].as(); } else { count++; log_i("Fail"); } + if(setting.containsKey("tmz")) { tmz = setting["tmz"].as(); } else { count++; log_i("Fail"); } + if(setting.containsKey("RfModule")){ RfModule= setting["RfModule"].as(); } else { count++; log_i("Fail"); } + if(setting.containsKey("RfFreq")) { RfFreq = setting["RfFreq"].as(); } else { count++; log_i("Fail"); } + + if(!setting.containsKey("wifi")) { count++; log_i("Fail"); } + + log_i("Brightness: %d", bright); + setBrightness(bright); + if(dimmerSet<10) dimmerSet=10; + file.close(); + if(count>0) saveConfigs(); + + count=0; + EEPROM.begin(EEPROMSIZE); // open eeprom + if(EEPROM.read(0)!= rotation) { EEPROM.write(0, rotation); count++; } + if(EEPROM.read(1)!= dimmerSet) { EEPROM.write(1, dimmerSet); count++; } + if(EEPROM.read(2)!= bright) { EEPROM.write(2, bright); count++; } + if(EEPROM.read(6)!= IrTx) { EEPROM.write(6, IrTx); count++; } + if(EEPROM.read(7)!= IrRx) { EEPROM.write(7, IrRx); count++; } + if(EEPROM.read(8)!= RfTx) { EEPROM.write(8, RfTx); count++; } + if(EEPROM.read(9)!= RfRx) { EEPROM.write(9, RfRx); count++; } + // TODO: add RfModule,RfFreq + if(EEPROM.read(10)!= tmz) { EEPROM.write(10, tmz); count++; } + if(EEPROM.read(11)!=(int((FGCOLOR >> 8) & 0x00FF))) {EEPROM.write(11, int((FGCOLOR >> 8) & 0x00FF)); count++; } + if(EEPROM.read(12)!= int(FGCOLOR & 0x00FF)) { EEPROM.write(12, int(FGCOLOR & 0x00FF)); count++; } + //If something changed, saves the changes on EEPROM. + if(count>0) { + if(!EEPROM.commit()) log_i("fail to write EEPROM"); // Store data to EEPROM + } else log_i("Wrote new conf to EEPROM"); + EEPROM.end(); + log_i("Using config.conf setup file"); + } else { + goto Default; + log_i("Using settings stored on EEPROM"); } - else { + Default: - //saveConfigs(); - Serial.println("Sd Unmounted. Using settings stored on EEPROM"); - } - //closeSdCard(); - Serial.println("Enf o Config"); + //saveConfigs(); + //Serial.println("Sd Unmounted. Using settings stored on EEPROM"); + //closeSdCard(); + Serial.println("End of Config"); } + /********************************************************************* ** Function: saveConfigs ** save configs into JSON config.conf file **********************************************************************/ void saveConfigs() { // Delete existing file, otherwise the configuration is appended to the file - if(setupSdCard()) { - JsonObject setting = settings[0]; - setting["bright"] = bright; - setting["dimmerSet"] = dimmerSet; - setting["rot"] = rotation; - setting["Bruce_FGCOLOR"] = FGCOLOR; - setting["wui_usr"] = wui_usr; - setting["wui_pwd"] = wui_pwd; - setting["IrTx"] = IrTx; - setting["IrRx"] = IrRx; - setting["RfTx"] = RfTx; - setting["RfRx"] = RfRx; - setting["tmz"] = tmz; - if(!setting.containsKey("wifi")) { - JsonArray WifiList = setting["wifi"].to(); - if(WifiList.size()<1) { - JsonObject WifiObj = WifiList.add(); - WifiObj["ssid"] = "myNetSSID"; - WifiObj["pwd"] = "myNetPassword"; - } + FS* fs = &LittleFS; + if(setupSdCard()) fs = &SD; // prefer SD card if available + + JsonObject setting = settings[0]; + setting["bright"] = bright; + setting["dimmerSet"] = dimmerSet; + setting["rot"] = rotation; + setting["Bruce_FGCOLOR"] = FGCOLOR; + setting["wui_usr"] = wui_usr; + setting["wui_pwd"] = wui_pwd; + setting["IrTx"] = IrTx; + setting["IrRx"] = IrRx; + setting["RfTx"] = RfTx; + setting["RfRx"] = RfRx; + setting["RfModule"] = RfModule; + setting["RfFreq"] = RfFreq; + setting["tmz"] = tmz; + if(!setting.containsKey("wifi")) { + JsonArray WifiList = setting["wifi"].to(); + if(WifiList.size()<1) { + JsonObject WifiObj = WifiList.add(); + WifiObj["ssid"] = "myNetSSID"; + WifiObj["pwd"] = "myNetPassword"; } - // Open file for writing - File file = SD.open(CONFIG_FILE, FILE_WRITE); - if (!file) { - log_i("Failed to create file"); - file.close(); - return; - } else log_i("config.conf created"); - // Serialize JSON to file - serializeJsonPretty(settings,Serial); - if (serializeJsonPretty(settings, file) < 5) { - log_i("Failed to write to file"); - } else log_i("config.conf written successfully"); - - // Close the file + } + // Open file for writing + File file = fs->open(CONFIG_FILE, FILE_WRITE); + if (!file) { + log_i("Failed to create file"); file.close(); - } else log_i("saveConfig: SdCard Unmounted."); + return; + } else log_i("config.conf created"); + // Serialize JSON to file + serializeJsonPretty(settings,Serial); + if (serializeJsonPretty(settings, file) < 5) { + log_i("Failed to write to file"); + } else log_i("config.conf written successfully"); + + // Close the file + file.close(); } diff --git a/src/core/settings.h b/src/core/settings.h index 844df535..2b871409 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -16,6 +16,10 @@ void setBrightnessMenu(); void setUIColor(); +void setRFModuleMenu(); + +void setRFFreqMenu(); + void setSleepMode(); void setDimmerTimeMenu(); diff --git a/src/main.cpp b/src/main.cpp index fd3d72a5..17a9f9bd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,8 @@ int IrTx; int IrRx; int RfTx; int RfRx; +int RfModule=0; // 0 - single-pinned, 1 - CC1101 +float RfFreq=433.92; int dimmerSet; int bright=100; int tmz=3; @@ -69,7 +71,8 @@ uint8_t buff[4096] = {0}; #include "core/settings.h" #include "core/main_menu.h" #include "core/serialcmds.h" -#include "modules/others/audio.h" +#include "modules/others/audio.h" // for playAudioFile +#include "modules/rf/rf.h" // for initCC1101once /********************************************************************* @@ -302,6 +305,7 @@ void loop() { tft.fillRect(0,0,WIDTH,HEIGHT,BGCOLOR); setupSdCard(); getConfigs(); + if(RfModule==1) initCC1101once(); while(1){ if (returnToMenu) { @@ -368,6 +372,7 @@ void loop() { void loop() { setupSdCard(); getConfigs(); + if(RfModule==1) initCC1101once(); if(!wifiConnected) { Serial.println("wifiConnect"); diff --git a/src/modules/rf/rf.cpp b/src/modules/rf/rf.cpp index 86a7a466..22f488eb 100644 --- a/src/modules/rf/rf.cpp +++ b/src/modules/rf/rf.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "PCA9554.h" #include "core/globals.h" #include "core/mykeyboard.h" @@ -187,19 +188,21 @@ void rf_jammerIntermittent() { //@IncursioHack - https://github.com/IncursioHack digitalWrite(RfTx, LOW); // Deactivate pin } -#ifdef USE_CC1101_VIA_SPI - #include -#endif - + void RCSwitch_send(uint64_t data, unsigned int bits, int pulse, int protocol, int repeat) { + // derived from https://github.com/LSatan/SmartRC-CC1101-Driver-Lib/blob/master/examples/Rc-Switch%20examples%20cc1101/SendDemo_cc1101/SendDemo_cc1101.ino + RCSwitch mySwitch = RCSwitch(); - #ifdef USE_CC1101_VIA_SPI + if(RfModule==1) { + //pinMode(CC1101_GDO0_PIN, OUTPUT); mySwitch.enableTransmit(CC1101_GDO0_PIN); - #else + ELECHOUSE_cc1101.setPA(12); // set TxPower. The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max! + ELECHOUSE_cc1101.SetTx(); + } else { mySwitch.enableTransmit(RfTx); - #endif + } mySwitch.setProtocol(protocol); // override if (pulse) { mySwitch.setPulseLength(pulse); } @@ -215,6 +218,11 @@ void RCSwitch_send(uint64_t data, unsigned int bits, int pulse, int protocol, in * */ mySwitch.disableTransmit(); + + if(RfModule==1) + ELECHOUSE_cc1101.setSidle(); + else + digitalWrite(RfTx, LED_OFF); } @@ -335,22 +343,19 @@ static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength) { return bin; } -void RCSwitch_Read_Raw(float frequency) { - RCSwitch rcswitch = RCSwitch(); - RfCodes received; - drawMainBorder(); - tft.setCursor(10, 28); - tft.setTextSize(FP); - tft.println("Waiting for signal."); - char hexString[64]; - -RestartRec: - // init receive + +void initCC1101once() { + // the init (); command may only be executed once in the entire program sequence. Otherwise problems can arise. https://github.com/LSatan/SmartRC-CC1101-Driver-Lib/issues/65 + #ifdef USE_CC1101_VIA_SPI // derived from https://github.com/LSatan/SmartRC-CC1101-Driver-Lib/blob/master/examples/Rc-Switch%20examples%20cc1101/ReceiveDemo_Advanced_cc1101/ReceiveDemo_Advanced_cc1101.ino ELECHOUSE_cc1101.setSpiPin(CC1101_SCK_PIN, CC1101_MISO_PIN, CC1101_MOSI_PIN, CC1101_SS_PIN); - ELECHOUSE_cc1101.setGDO(CC1101_GDO0_PIN, CC1101_GDO2_PIN); //Set Gdo0 (tx) and Gdo2 (rx) for serial transmission function. + #ifdef CC1101_GDO2_PIN + ELECHOUSE_cc1101.setGDO(CC1101_GDO0_PIN, CC1101_GDO2_PIN); //Set Gdo0 (tx) and Gdo2 (rx) for serial transmission function. + #else + ELECHOUSE_cc1101.setGDO0(CC1101_GDO0_PIN); // use Gdo0 for both Tx and Rx + #endif if (ELECHOUSE_cc1101.getCC1101()){ // Check the CC1101 Spi connection. Serial.println("cc1101 Connection OK"); } else { @@ -358,18 +363,93 @@ void RCSwitch_Read_Raw(float frequency) { return; } ELECHOUSE_cc1101.Init(); - ELECHOUSE_cc1101.setMHZ(frequency); - rcswitch.enableReceive(CC1101_GDO2_PIN); - ELECHOUSE_cc1101.SetRx(); #else - if(frequency!=433.92) { + Serial.println("Error: USE_CC1101_VIA_SPI not defined for this board"); + //TODO: interface using PCA9554 + #endif + return; +} + +bool initRfModule(String mode, float frequency) { + + if(RfModule == 1) { // CC1101 in use + if (ELECHOUSE_cc1101.getCC1101()){ // Check the CC1101 Spi connection. + Serial.println("cc1101 Connection OK"); + } else { + Serial.println("cc1101 Connection Error"); + return false; + } + + // make sure it is in idle state when changing frequency and other parameters + // "If any frequency programming register is altered when the frequency synthesizer is running, the synthesizer may give an undesired response. Hence, the frequency programming should only be updated when the radio is in the IDLE state." https://github.com/LSatan/SmartRC-CC1101-Driver-Lib/issues/65 + ELECHOUSE_cc1101.setSidle(); + + // use default frequency if no one is passed + if(!frequency) frequency = RfFreq; + + if(!(frequency>=300 && frequency<=928)) // TODO: check all supported subranges: 300-348 MHZ, 387-464MHZ and 779-928MHZ. + return false; + // else + ELECHOUSE_cc1101.setMHZ(frequency); + + /* MEMO: cannot change other params after this is executed -> moved in the caller func + if(mode=="tx") + ELECHOUSE_cc1101.setPA(12); // set TxPower. The following settings are possible depending + ELECHOUSE_cc1101.SetTx(); + else + ELECHOUSE_cc1101.SetRx(); + */ + + } else { + // single-pinned module + if(frequency!=RfFreq) { Serial.println("unsupported frequency"); - return; + return false; + } + + if(mode=="tx") { + gsetRfTxPin(false); + //if(RfTx==0) RfTx=GROVE_SDA; // quick fix + pinMode(RfTx, OUTPUT); + digitalWrite(RfTx, LED_OFF); + } else { + // Rx Mode + gsetRfRxPin(false); + //if(RfRx==0) RfRx=GROVE_SCL; // quick fix + pinMode(RfRx, INPUT); } - gsetRfRxPin(false); - pinMode(RfRx, INPUT); + } + // no error + return true; +} + + +bool RCSwitch_Read_Raw(float frequency) { + RCSwitch rcswitch = RCSwitch(); + RfCodes received; + + drawMainBorder(); + tft.setCursor(10, 28); + tft.setTextSize(FP); + tft.println("Waiting for signal."); + char hexString[64]; + + if(!frequency) frequency = RfFreq; // default from settings + +RestartRec: + // init receive + if(!initRfModule("rx", frequency)) return false; + if(RfModule == 1) { // CC1101 in use + #ifdef CC1101_GDO2_PIN + rcswitch.enableReceive(CC1101_GDO2_PIN); + #else + //pinMode(CC1101_GDO0_PIN, INPUT); + rcswitch.enableReceive(CC1101_GDO0_PIN); + #endif + ELECHOUSE_cc1101.SetRx(); + } else { rcswitch.enableReceive(RfRx); - #endif + } while(!checkEscPress()) { if(rcswitch.available()) { @@ -379,7 +459,7 @@ void RCSwitch_Read_Raw(float frequency) { //Serial.println("has value"); unsigned int* raw = rcswitch.getReceivedRawdata(); - received.frequency=int(frequency*1000000); + received.frequency=long(frequency*1000000); received.key=rcswitch.getReceivedValue(); received.protocol="RcSwitch"; received.preset=rcswitch.getReceivedProtocol(); @@ -428,7 +508,7 @@ void RCSwitch_Read_Raw(float frequency) { #ifndef HAS_SCREEN // headless mode, just print the file on serial and quit Serial.println(subfile_out); - return; + return true; #endif if(checkSelPress()) { @@ -481,6 +561,11 @@ void RCSwitch_Read_Raw(float frequency) { } Exit: delay(1); + + if(RfModule==1) + ELECHOUSE_cc1101.setSidle(); + + return true; } @@ -519,7 +604,7 @@ void RCSwitch_RAW_Bit_send(int nTransmitterPin, RfCodes data) { digitalWrite(nTransmitterPin, LOW); } } -void RCSwitch_RAW_send(int nTransmitterPin, int * ptrtransmittimings, struct Protocol protocol) { +void RCSwitch_RAW_send(int nTransmitterPin, int * ptrtransmittimings) { if (nTransmitterPin == -1) return; @@ -535,12 +620,10 @@ void RCSwitch_RAW_send(int nTransmitterPin, int * ptrtransmittimings, struct Pro while( ptrtransmittimings[currenttiming] ) { // && currenttiming < RCSWITCH_MAX_CHANGES if(ptrtransmittimings[currenttiming] >= 0) { currentlogiclevel = true; - //pulses = protocol.one; } else { // negative value currentlogiclevel = false; ptrtransmittimings[currenttiming] = (-1) * ptrtransmittimings[currenttiming]; // invert sign - //pulses = protocol.zero; } digitalWrite(nTransmitterPin, currentlogiclevel ? HIGH : LOW); @@ -587,18 +670,18 @@ void sendRfCommand(struct RfCodes rfcode) { FuriHalSubGhzPresetGFSK9_99KbAsync, //< GFSK, deviation 19.042969 kHz, 9.996Kb/s, asynchronous FuriHalSubGhzPresetCustom, //Custom Preset */ - struct Protocol rcswitch_protocol; + //struct Protocol rcswitch_protocol; int rcswitch_protocol_no = 1; if(preset == "FuriHalSubGhzPresetOok270Async") { rcswitch_protocol_no = 1; // pulseLength , syncFactor , zero , one, invertedSignal - rcswitch_protocol = { 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }; + //rcswitch_protocol = { 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }; modulation = 2; rxBW = 270; } else if(preset == "FuriHalSubGhzPresetOok650Async") { rcswitch_protocol_no = 2; - rcswitch_protocol = { 650, { 1, 10 }, { 1, 2 }, { 2, 1 }, false }; + //rcswitch_protocol = { 650, { 1, 10 }, { 1, 2 }, { 2, 1 }, false }; modulation = 2; rxBW = 650; } @@ -629,49 +712,22 @@ void sendRfCommand(struct RfCodes rfcode) { return; } - #ifndef USE_CC1101_VIA_SPI - // check supported frequency and modulation by the current module - if(frequency != 433920000) { - Serial.print("unsupported frequency: "); - Serial.println(frequency); - return; - } - // MEMO: frequency is fixed with some transmitters https://github.com/sui77/rc-switch/issues/256 - if(modulation != 2) { - Serial.print("unsupported modulation: "); - Serial.println(modulation); - return; + // init transmitter + if(!initRfModule("tx", frequency/1000000.0)) return; + if(RfModule == 1) { // CC1101 in use + // derived from https://github.com/LSatan/SmartRC-CC1101-Driver-Lib/blob/master/examples/Rc-Switch%20examples%20cc1101/SendDemo_cc1101/SendDemo_cc1101.ino + ELECHOUSE_cc1101.setModulation(modulation); + if(deviation) ELECHOUSE_cc1101.setDeviation(deviation); + if(rxBW) ELECHOUSE_cc1101.setRxBW(rxBW); // Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. Default is 812.50 kHz. + if(dataRate) ELECHOUSE_cc1101.setDRate(dataRate); + } else { + // other single-pinned modules in use + if(modulation != 2) { + Serial.print("unsupported modulation: "); + Serial.println(modulation); + return; + } } - - // init output pin - gsetRfTxPin(false); - //if(RfTx==0) RfTx=GROVE_SDA; // quick fix - pinMode(RfTx, OUTPUT); - digitalWrite(RfTx, LED_OFF); - - #else // USE_CC1101_VIA_SPI - // init cc1101 module - // derived from https://github.com/LSatan/SmartRC-CC1101-Driver-Lib/blob/master/examples/Rc-Switch%20examples%20cc1101/SendDemo_cc1101/SendDemo_cc1101.ino - - ELECHOUSE_cc1101.setSpiPin(CC1101_SCK_PIN, CC1101_MISO_PIN, CC1101_MOSI_PIN, CC1101_SS_PIN); - ELECHOUSE_cc1101.setGDO(CC1101_GDO0_PIN, CC1101_GDO2_PIN); //Set Gdo0 (tx) and Gdo2 (rx) for serial transmission function. - - if (ELECHOUSE_cc1101.getCC1101()){ // Check the CC1101 Spi connection. - Serial.println("cc1101 Connection OK"); - }else{ - Serial.println("cc1101 Connection Error"); - return; - } - - ELECHOUSE_cc1101.Init(); // must be set to initialize the cc1101! - ELECHOUSE_cc1101.setMHZ(frequency / 1000000.0); // e.g. 433.92. Here you can set your basic frequency. The lib calculates the frequency automatically (default = 433.92).The cc1101 can: 300-348 MHZ, 387-464MHZ and 779-928MHZ. Read More info from datasheet. - ELECHOUSE_cc1101.setModulation(modulation); - if(deviation) ELECHOUSE_cc1101.setDeviation(deviation); - if(rxBW) ELECHOUSE_cc1101.setRxBW(rxBW); // Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. Default is 812.50 kHz. - if(dataRate) ELECHOUSE_cc1101.setDRate(dataRate); - ELECHOUSE_cc1101.setPA(12); // set TxPower. The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max! - ELECHOUSE_cc1101.SetTx(); - #endif if(protocol == "RAW") { // count the number of elements of RAW_Data @@ -701,7 +757,7 @@ void sendRfCommand(struct RfCodes rfcode) { // send rf command displayRedStripe("Sending..",TFT_WHITE,FGCOLOR); - RCSwitch_RAW_send(RfTx, transmittimings, rcswitch_protocol); + RCSwitch_RAW_send(RfTx, transmittimings); free(transmittimings); } else if (protocol == "BinRAW") { diff --git a/src/modules/rf/rf.h b/src/modules/rf/rf.h index 99099090..5b602eb1 100644 --- a/src/modules/rf/rf.h +++ b/src/modules/rf/rf.h @@ -18,7 +18,9 @@ void rf_jammerIntermittent(); void rf_jammerFull(); void otherRFcodes(); bool txSubFile(FS *fs, String filepath); -void RCSwitch_Read_Raw(float frequency=433.92); +bool RCSwitch_Read_Raw(float frequency=0); void RCSwitch_send(uint64_t data, unsigned int bits, int pulse=0, int protocol=1, int repeat=10); void addToRecentCodes(struct RfCodes rfcode); void sendRfCommand(struct RfCodes rfcode); +bool initRfModule(String mode, float frequency=0); +void initCC1101once(); \ No newline at end of file