diff --git a/platformio.ini b/platformio.ini index 35d3a61d..c6ed2aae 100644 --- a/platformio.ini +++ b/platformio.ini @@ -22,7 +22,6 @@ build_flags = -DLH=8 -DLW=6 -DCONFIG_FILE='"/config.conf"' - lib_deps = WireGuard-ESP32 IRremoteESP8266 @@ -34,6 +33,8 @@ lib_deps = Timezone ESP32Time bblanchon/ArduinoJson + rc-switch + ;https://github.com/Martin-Laclaustra/rc-switch.git#transmittimingsarray [env:m5stack-cplus2] diff --git a/src/core/main_menu.cpp b/src/core/main_menu.cpp index 5d47c981..0f8d3244 100644 --- a/src/core/main_menu.cpp +++ b/src/core/main_menu.cpp @@ -87,6 +87,7 @@ void rfOptions(){ options = { //{"Scan/copy", [=]() { displayRedStripe("Scan/Copy"); }}, //{"Replay", [=]() { displayRedStripe("Replay"); }}, + {"Custom SubGhz", [=]() { otherRFcodes(); }}, {"Spectrum", [=]() { rf_spectrum(); }}, //@IncursioHack {"Jammer Itmt", [=]() { rf_jammerIntermittent(); }}, //@IncursioHack {"Jammer Full", [=]() { rf_jammerFull(); }}, //@IncursioHack diff --git a/src/core/mykeyboard.cpp b/src/core/mykeyboard.cpp index bc259f7b..68209e6f 100644 --- a/src/core/mykeyboard.cpp +++ b/src/core/mykeyboard.cpp @@ -1,5 +1,9 @@ #include "mykeyboard.h" #include "powerSave.h" +#include "modules/others/TV-B-Gone.h" +#include "modules/rf/rf.h" +#include "modules/others/bad_usb.h" +#include "modules/others/webInterface.h" /* Verifies Upper Btn to go to previous item */ @@ -83,6 +87,32 @@ bool checkEscPress(){ else { return false; } } +bool checkAnyKeyPress() { +#if defined (CARDPUTER) // If any key is pressed, it'll jump the boot screen + Keyboard.update(); + if(Keyboard.isPressed()) + #else + if(digitalRead(SEL_BTN)==LOW) // If M5 key is pressed, it'll jump the boot screen + #endif + return true; + // else + return false; + +} + +void checkShortcutPress(){ + // some shortctus to quickly starts apps +#if defined (CARDPUTER) + Keyboard.update(); + if(Keyboard.isKeyPressed('i')) otherIRcodes(); + if(Keyboard.isKeyPressed('r') || Keyboard.isKeyPressed('s')) otherRFcodes(); + if(Keyboard.isKeyPressed('b')) usb_setup(); // badusb + if(Keyboard.isKeyPressed('w')) loopOptionsWebUi(); +// TODO: other boards +// TODO: user-configurable +#endif +} + #ifndef STICK_C /* Starts keyboard to type data */ String keyboard(String mytext, int maxSize, String msg) { @@ -570,4 +600,4 @@ String keyboard(String mytext, int maxSize, String msg) { } -#endif //If not STICK_C \ No newline at end of file +#endif //If not STICK_C diff --git a/src/core/mykeyboard.h b/src/core/mykeyboard.h index 19e5f9e4..8f5e60e8 100644 --- a/src/core/mykeyboard.h +++ b/src/core/mykeyboard.h @@ -10,4 +10,8 @@ bool checkPrevPress(); bool checkSelPress(); -bool checkEscPress(); \ No newline at end of file +bool checkEscPress(); + +void checkShortcutPress(); + +bool checkAnyKeyPress(); diff --git a/src/main.cpp b/src/main.cpp index 4d3d066b..b3a10d1e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -253,6 +253,8 @@ void loop() { delay(200); } + checkShortcutPress(); // shortctus to quickly start apps without navigating the menus + if (checkPrevPress()) { if(index==0) index = opt - 1; else if(index>0) index--; diff --git a/src/modules/rf/rf.cpp b/src/modules/rf/rf.cpp index 914a9dd6..caa3c345 100644 --- a/src/modules/rf/rf.cpp +++ b/src/modules/rf/rf.cpp @@ -151,4 +151,282 @@ void rf_jammerIntermittent() { //@IncursioHack - https://github.com/IncursioHack } +struct RfCodes { + uint32_t frequency = 0; + String protocol = ""; + String preset = ""; + String data = ""; + int te = 0; + String filepath = ""; +}; + + +#include + +void RCSwitch_send(uint64_t data, unsigned int bits, int pulse, int protocol, int repeat) +{ + RCSwitch mySwitch = RCSwitch(); + mySwitch.enableTransmit(RfTx); + mySwitch.setProtocol(protocol); + if (pulse) { mySwitch.setPulseLength(pulse); } + mySwitch.setPulseLength(pulse); + mySwitch.setRepeatTransmit(repeat); + mySwitch.send(data, bits); +} + +struct HighLow { + uint8_t high; // 1 + uint8_t low; //31 +}; + +struct Protocol { + uint16_t pulseLength; // base pulse length in microseconds, e.g. 350 + HighLow syncFactor; + HighLow zero; + HighLow one; + bool invertedSignal; +}; + +// ported from https://github.com/sui77/rc-switch/blob/3a536a172ab752f3c7a58d831c5075ca24fd920b/RCSwitch.cpp + +void RCSwitch_RAW_send(int nTransmitterPin, int * ptrtransmittimings, struct Protocol protocol) { + if (nTransmitterPin == -1) + return; + + if (!ptrtransmittimings) + return; + + bool currentlogiclevel = true; + int nRepeatTransmit = 1; + //HighLow pulses ; + + for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) { + unsigned int currenttiming = 0; + 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); + delayMicroseconds( ptrtransmittimings[currenttiming] ); + + /* + uint8_t firstLogicLevel = (protocol.invertedSignal) ? LOW : HIGH; + uint8_t secondLogicLevel = (protocol.invertedSignal) ? HIGH : LOW; + + digitalWrite(nTransmitterPin, firstLogicLevel); + delayMicroseconds( protocol.pulseLength * pulses.high); + digitalWrite(nTransmitterPin, secondLogicLevel); + delayMicroseconds( protocol.pulseLength * pulses.low); + * */ + + Serial.print(ptrtransmittimings[currenttiming]); + Serial.print("="); + Serial.println(currentlogiclevel); + + currenttiming++; + } + digitalWrite(nTransmitterPin, LOW); + } // end for +} + + +void sendRfCommand(struct RfCodes rfcode) { + uint32_t frequency = rfcode.frequency; + String protocol = rfcode.protocol; + String preset = rfcode.preset; + String data = rfcode.data; +/* + Serial.println("sendRawRfCommand"); + Serial.println(data); + Serial.println(frequency); + Serial.println(preset); + Serial.println(protocol); + */ + 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 + // TODO: add frequency switching via CC1101 https://github.com/LSatan/SmartRC-CC1101-Driver-Lib + + // Radio preset name (configures modulation, bandwidth, filters, etc.). + 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 }; + } + else if(preset == "FuriHalSubGhzPresetOok650Async") { + rcswitch_protocol_no = 2; + rcswitch_protocol = { 650, { 1, 10 }, { 1, 2 }, { 2, 1 }, false }; + } + else { + Serial.print("unsupported preset: "); + Serial.println(preset); + return; + } + /* supported flipper presets: + FuriHalSubGhzPresetIDLE, // < default configuration + FuriHalSubGhzPresetOok270Async, ///< OOK, bandwidth 270kHz, asynchronous + FuriHalSubGhzPresetOok650Async, ///< OOK, bandwidth 650kHz, asynchronous + FuriHalSubGhzPreset2FSKDev238Async, //< FM, deviation 2.380371 kHz, asynchronous + FuriHalSubGhzPreset2FSKDev476Async, //< FM, deviation 47.60742 kHz, asynchronous + FuriHalSubGhzPresetMSK99_97KbAsync, //< MSK, deviation 47.60742 kHz, 99.97Kb/s, asynchronous + FuriHalSubGhzPresetGFSK9_99KbAsync, //< GFSK, deviation 19.042969 kHz, 9.996Kb/s, asynchronous + FuriHalSubGhzPresetCustom, //Custom Preset + */ + + // init output pin + digitalWrite(RfTx, LED_OFF); + if(RfTx==0) RfTx=GROVE_SDA; // quick fix + pinMode(RfTx, OUTPUT); + + if(protocol == "RAW") { + // alloc buffer for transmittimings + int* transmittimings = (int *) calloc(sizeof(int), data.length()); // should be smaller the data.length() + size_t transmittimings_idx = 0; + + // split data into words, convert to int, and store them in transmittimings + String curr_word = ""; + int curr_val = 0; + for(int i=0; i recent_rfcodes[recent_rfcodes_last_used] + recent_rfcodes[recent_rfcodes_last_used] = rfcode; + recent_rfcodes_last_used += 1; + if(recent_rfcodes_last_used == 16) recent_rfcodes_last_used = 0; // cycle +} + +struct RfCodes selectRecentRfMenu() { + // show menu with filenames + options = { }; + bool exit = false; + struct RfCodes selected_code; + for(int i=0; i<16; i++) { + if(recent_rfcodes[i].filepath=="") continue; // not inited + // else + options.push_back({ recent_rfcodes[i].filepath.c_str(), [i, &selected_code](){ selected_code = recent_rfcodes[i]; }}); + } + options.push_back({ "Main Menu" , [&](){ exit=true; }}); + delay(200); + loopOptions(options); + return(selected_code); +} + +void otherRFcodes() { + File databaseFile; + FS *fs = NULL; + String filepath = ""; + struct RfCodes selected_code; + options = { + {"Recent", [&]() { selected_code = selectRecentRfMenu(); }}, + {"LittleFS", [&]() { fs=&LittleFS; }}, + }; + if(setupSdCard()) options.push_back({"SD Card", [&]() { fs=&SD; }}); + + delay(200); + loopOptions(options); + delay(200); + + if(fs == NULL) { // recent menu was selected + if(selected_code.filepath!="") sendRfCommand(selected_code); // a code was selected + return; + // no need to proceed, go back + } + + //filepath = loopSD(*fs, true, "SUB"); + filepath = loopSD(*fs, true); + databaseFile = fs->open(filepath, FILE_READ); + drawMainBorder(); + + if (!databaseFile) { + Serial.println("Failed to open database file."); + displayError("Fail to open file"); + delay(2000); + return; + } + Serial.println("Opened sub file."); + selected_code.filepath = filepath.substring( 1 + filepath.lastIndexOf("/") ); + + // format specs: https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/file_formats/SubGhzFileFormats.md + String line; + String txt; + while (databaseFile.available() ) { + line = databaseFile.readStringUntil('\n'); + txt=line.substring(line.indexOf(":") + 1); + txt.trim(); + if(line.startsWith("Protocol:")) selected_code.protocol = txt; + if(line.startsWith("Preset:")) selected_code.preset = txt; + if(line.startsWith("Frequency:")) selected_code.frequency = txt.toInt(); + if(line.startsWith("TE:")) selected_code.te = txt.toInt(); + if(line.startsWith("RAW_Data:") || line.startsWith("Key:")) { selected_code.data += txt; } + } + databaseFile.close(); + + addToRecentCodes(selected_code); + sendRfCommand(selected_code); + + // TODO: menu to resend command/pick another file from the same dir? + + digitalWrite(RfTx, LED_OFF); +} diff --git a/src/modules/rf/rf.h b/src/modules/rf/rf.h index a5116b51..75053a86 100644 --- a/src/modules/rf/rf.h +++ b/src/modules/rf/rf.h @@ -15,4 +15,7 @@ const int PCA9554TRX_PIN = 0; void rf_spectrum(); void rf_jammerIntermittent(); -void rf_jammerFull(); \ No newline at end of file +void rf_jammerFull(); +void otherRFcodes(); + +void RCSwitch_send(uint64_t data, unsigned int bits, int pulse=0, int protocol=1, int repeat=10);