Skip to content

Commit

Permalink
Merge pull request #82 from eadmaster/serialcmds
Browse files Browse the repository at this point in the history
eadmaster added subghz submenu, keyboard shortcuts (#64)
  • Loading branch information
pr3y authored Jul 25, 2024
2 parents b8c5614 + 7a4c96c commit 1daf0e7
Show file tree
Hide file tree
Showing 7 changed files with 323 additions and 4 deletions.
3 changes: 2 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ build_flags =
-DLH=8
-DLW=6
-DCONFIG_FILE='"/config.conf"'

lib_deps =
WireGuard-ESP32
IRremoteESP8266
Expand All @@ -34,6 +33,8 @@ lib_deps =
Timezone
ESP32Time
bblanchon/ArduinoJson
rc-switch
;https://github.com/Martin-Laclaustra/rc-switch.git#transmittimingsarray


[env:m5stack-cplus2]
Expand Down
1 change: 1 addition & 0 deletions src/core/main_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 31 additions & 1 deletion src/core/mykeyboard.cpp
Original file line number Diff line number Diff line change
@@ -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 */
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -570,4 +600,4 @@ String keyboard(String mytext, int maxSize, String msg) {
}


#endif //If not STICK_C
#endif //If not STICK_C
6 changes: 5 additions & 1 deletion src/core/mykeyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ bool checkPrevPress();

bool checkSelPress();

bool checkEscPress();
bool checkEscPress();

void checkShortcutPress();

bool checkAnyKeyPress();
2 changes: 2 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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--;
Expand Down
278 changes: 278 additions & 0 deletions src/modules/rf/rf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <RCSwitch.h>

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<data.length(); i++) {
if(isspace(data[i])) {
if(curr_word == "") continue; // skip if empty
// else append to transmittimings
//transmittimings[transmittimings_idx] = curr_word.toInt(); // does not handle negative numbers
transmittimings[transmittimings_idx] = atoi(curr_word.c_str());
//if(transmittimings[transmittimings_idx]==0) invalid int?
transmittimings_idx += 1;
curr_word = ""; // reset

} else {
curr_word += data[i]; // append to current word
}
}
transmittimings[transmittimings_idx] = 0; // termination

// send rf command
displayRedStripe("Sending..",TFT_WHITE,FGCOLOR);
//mySwitch.send(transmittimings); // req. forked ver
RCSwitch_RAW_send(RfTx, transmittimings, rcswitch_protocol);
free(transmittimings);
}
else if(protocol == "RcSwitch") {
data.replace(" ", ""); // remove spaces
uint64_t data_val = strtoul(data.c_str(), nullptr, 16);
int bits = data.length() * 4;
int pulse = rfcode.te; // not sure about this...
int repeat = 10;
/*
Serial.print("RcSwitch: ");
Serial.println(data);
Serial.println(bits);
Serial.println(pulse);
Serial.println(rcswitch_protocol_no);
* */
displayRedStripe("Sending..",TFT_WHITE,FGCOLOR);
RCSwitch_send(data_val, bits, pulse, rcswitch_protocol_no, repeat);
}
else {
Serial.print("unsupported protocol: ");
Serial.println(protocol);
return;
}

digitalWrite(RfTx, LED_OFF);
}


RfCodes recent_rfcodes[16]; // TODO: save/load in EEPROM
int recent_rfcodes_last_used = 0; // TODO: save/load in EEPROM

void addToRecentCodes(struct RfCodes rfcode) {
// copy rfcode -> 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);
}

5 changes: 4 additions & 1 deletion src/modules/rf/rf.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ const int PCA9554TRX_PIN = 0;

void rf_spectrum();
void rf_jammerIntermittent();
void rf_jammerFull();
void rf_jammerFull();
void otherRFcodes();

void RCSwitch_send(uint64_t data, unsigned int bits, int pulse=0, int protocol=1, int repeat=10);

0 comments on commit 1daf0e7

Please sign in to comment.