diff --git a/src/TV-B-Gone.cpp b/src/TV-B-Gone.cpp index 80e8ff2d..77e28aa7 100644 --- a/src/TV-B-Gone.cpp +++ b/src/TV-B-Gone.cpp @@ -205,10 +205,12 @@ struct Codes { uint32_t frequency; //float duty_cycle; String data; + String filepath; }; Codes codes[50]; + void resetCodesArray() { for (int i = 0; i < 25; i++) { codes[i].name = ""; @@ -219,32 +221,73 @@ void resetCodesArray() { codes[i].frequency = 0; //codes[i].duty_cycle = 0.0; codes[i].data = ""; + codes[i].filepath = ""; } } + +Codes recent_ircodes[16]; +int recent_ircodes_last_used = 0; // TODO: save/load in EEPROM + +void addToRecentCodes(struct Codes ircode) { + // copy rfcode -> recent_ircodes[recent_ircodes_last_used] + recent_ircodes[recent_ircodes_last_used] = ircode; + recent_ircodes_last_used += 1; + if(recent_ircodes_last_used == 16) recent_ircodes_last_used = 0; // cycle +} + +struct Codes selectRecentIrMenu() { + // show menu with filenames + options = { }; + bool exit = false; + struct Codes selected_code; + for(int i=0; i<16; i++) { + if(recent_ircodes[i].filepath=="") continue; // not inited + // else + options.push_back({ recent_ircodes[i].filepath.c_str(), [i, &selected_code](){ selected_code = recent_ircodes[i]; }}); + } + options.push_back({ "Main Menu" , [&](){ exit=true; }}); + delay(200); + loopOptions(options); + return(selected_code); +} + void otherIRcodes() { resetCodesArray(); int total_codes = 0; String filepath; File databaseFile; - FS *fs; - if(setupSdCard()) { - bool teste=false; - options = { - {"SD Card", [&]() { fs=&SD; }}, + FS *fs = NULL; + struct Codes selected_code; + options = { + {"Recent", [&]() { selected_code = selectRecentIrMenu(); }}, {"LittleFS", [&]() { fs=&LittleFS; }}, - }; - delay(200); - loopOptions(options); - delay(200); - - } else fs=&LittleFS; + }; + if(setupSdCard()) options.push_back({"SD Card", [&]() { fs=&SD; }}); - filepath = loopSD(*fs, true); + delay(200); + loopOptions(options); + delay(200); + + if(fs == NULL) { // recent menu was selected + if(selected_code.filepath!="") { // a code was selected, switch on code type + if(selected_code.type=="raw") sendRawCommand(selected_code.frequency, selected_code.data); + else if(selected_code.protocol=="NECext") sendNECextCommand(selected_code.address, selected_code.command); + else if(selected_code.protocol=="NEC") sendNECCommand(selected_code.address, selected_code.command); + else if(selected_code.protocol=="RC5") sendRC5Command(selected_code.address, selected_code.command); + else if(selected_code.protocol.startsWith("Samsung")) sendSamsungCommand(selected_code.address, selected_code.command); + else if(selected_code.protocol=="SIRC") sendSonyCommand(selected_code.address, selected_code.command); + } + return; + // no need to proceed, go back + } + + filepath = loopSD(*fs, true, "IR"); databaseFile = fs->open(filepath, FILE_READ); drawMainBorder(); + pinMode(IrTx, OUTPUT); - //digitalWrite(IrTx, LED_ON); + //digitalWrite(IrTx, LED_OFF); if (!databaseFile) { Serial.println("Failed to open database file."); @@ -262,7 +305,6 @@ void otherIRcodes() { loopOptions(options); delay(200); - String line; // Mode to choose and send command by command limitted to 50 commands @@ -272,7 +314,7 @@ void otherIRcodes() { line = databaseFile.readStringUntil('\n'); txt=line.substring(line.indexOf(":") + 1); txt.trim(); - if(line.startsWith("name:")) codes[total_codes].name = txt; + if(line.startsWith("name:")) { codes[total_codes].name = txt; codes[total_codes].filepath = filepath.substring( 1 + filepath.lastIndexOf("/") ) + " " + txt;} if(line.startsWith("type:")) codes[total_codes].type = txt; if(line.startsWith("protocol:")) codes[total_codes].protocol = txt; if(line.startsWith("address:")) codes[total_codes].address = txt; @@ -284,17 +326,17 @@ void otherIRcodes() { options = { }; bool exit = false; for(int i=0; i<=total_codes; i++) { - if(codes[i].type=="raw") options.push_back({ codes[i].name.c_str(), [=](){ sendRawCommand(codes[i].frequency, codes[i].data); }}); - if(codes[i].protocol=="NECext") options.push_back({ codes[i].name.c_str(), [=](){ sendNECextCommand(codes[i].address, codes[i].command); }}); - if(codes[i].protocol=="NEC") options.push_back({ codes[i].name.c_str(), [=](){ sendNECCommand(codes[i].address, codes[i].command); }}); - if(codes[i].protocol=="RC5") options.push_back({ codes[i].name.c_str(), [=](){ sendRC5Command(codes[i].address, codes[i].command); }}); - if(codes[i].protocol.startsWith("Samsung")) options.push_back({ codes[i].name.c_str(), [=](){ sendSamsungCommand(codes[i].address, codes[i].command); }}); - if(codes[i].protocol=="SIRC") options.push_back({ codes[i].name.c_str(), [=](){ sendSonyCommand(codes[i].address, codes[i].command); }}); + if(codes[i].type=="raw") options.push_back({ codes[i].name.c_str(), [=](){ sendRawCommand(codes[i].frequency, codes[i].data); addToRecentCodes(codes[i]); }}); + if(codes[i].protocol=="NECext") options.push_back({ codes[i].name.c_str(), [=](){ sendNECextCommand(codes[i].address, codes[i].command); addToRecentCodes(codes[i]); }}); + if(codes[i].protocol=="NEC") options.push_back({ codes[i].name.c_str(), [=](){ sendNECCommand(codes[i].address, codes[i].command); addToRecentCodes(codes[i]); }}); + if(codes[i].protocol=="RC5") options.push_back({ codes[i].name.c_str(), [=](){ sendRC5Command(codes[i].address, codes[i].command); addToRecentCodes(codes[i]); }}); + if(codes[i].protocol.startsWith("Samsung")) options.push_back({ codes[i].name.c_str(), [=](){ sendSamsungCommand(codes[i].address, codes[i].command); addToRecentCodes(codes[i]); }}); + if(codes[i].protocol=="SIRC") options.push_back({ codes[i].name.c_str(), [=](){ sendSonyCommand(codes[i].address, codes[i].command); addToRecentCodes(codes[i]); }}); } options.push_back({ "Main Menu" , [&](){ exit=true; }}); databaseFile.close(); - digitalWrite(IrTx, LED_OFF); + //digitalWrite(IrTx, LED_OFF); while (1) { delay(200); loopOptions(options); @@ -303,7 +345,6 @@ void otherIRcodes() { } } - else { // SPAM all codes of the file int codes_sent=0; diff --git a/src/rf.cpp b/src/rf.cpp index c8b0bd37..264f5f65 100644 --- a/src/rf.cpp +++ b/src/rf.cpp @@ -355,7 +355,7 @@ void addToRecentCodes(struct RfCodes rfcode) { if(recent_rfcodes_last_used == 16) recent_rfcodes_last_used = 0; // cycle } -struct RfCodes selectRecentMenu() { +struct RfCodes selectRecentRfMenu() { // show menu with filenames options = { }; bool exit = false; @@ -376,10 +376,10 @@ void otherRFcodes() { FS *fs = NULL; String filepath = ""; struct RfCodes selected_code; - options = { - {"Recent", [&]() { selected_code = selectRecentMenu(); }}, + options = { + {"Recent", [&]() { selected_code = selectRecentRfMenu(); }}, {"LittleFS", [&]() { fs=&LittleFS; }}, - }; + }; if(setupSdCard()) options.push_back({"SD Card", [&]() { fs=&SD; }}); delay(200); @@ -392,12 +392,10 @@ void otherRFcodes() { // no need to proceed, go back } - filepath = loopSD(*fs, true); + filepath = loopSD(*fs, true, "SUB"); databaseFile = fs->open(filepath, FILE_READ); drawMainBorder(); - selected_code.filepath = filepath.substring( 1 + filepath.lastIndexOf("/") ); - if (!databaseFile) { Serial.println("Failed to open database file."); displayError("Fail to open file"); @@ -405,6 +403,7 @@ void otherRFcodes() { 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; diff --git a/src/sd_functions.cpp b/src/sd_functions.cpp index be5d7191..2d85b432 100644 --- a/src/sd_functions.cpp +++ b/src/sd_functions.cpp @@ -301,7 +301,7 @@ void sortList(String fileList[][3], int fileListCount) { ** Function name: sortList ** Description: sort files for name ***************************************************************************************/ -void readFs(FS fs, String folder, String result[][3]) { +void readFs(FS fs, String folder, String result[][3], String allowed_ext) { int allFilesCount = 0; while(allFilesCount