diff --git a/examples/arduino-rx-web/arduino-rx-web.cpp b/examples/arduino-rx-web/arduino-rx-web.cpp index 907a0e8..c731784 100644 --- a/examples/arduino-rx-web/arduino-rx-web.cpp +++ b/examples/arduino-rx-web/arduino-rx-web.cpp @@ -344,12 +344,12 @@ int main(int argc, char** argv) { #endif const GGWave::TxProtocols protocols = { - { GGWAVE_TX_PROTOCOL_CUSTOM_0, { "[R2T2] Normal", 64, 9, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_1, { "[R2T2] Fast", 64, 6, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_2, { "[R2T2] Fastest", 64, 3, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_3, { "[R2T2] Low Normal", 16, 9, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_4, { "[R2T2] Low Fast", 16, 6, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_5, { "[R2T2] Low Fastest", 16, 3, 1, 2, } }, + { "[R2T2] Normal", 64, 9, 1, 2, true, }, + { "[R2T2] Fast", 64, 6, 1, 2, true, }, + { "[R2T2] Fastest", 64, 3, 1, 2, true, }, + { "[R2T2] Low Normal", 16, 9, 1, 2, true, }, + { "[R2T2] Low Fast", 16, 6, 1, 2, true, }, + { "[R2T2] Low Fastest", 16, 3, 1, 2, true, }, }; const auto argm = parseCmdArguments(argc, argv); diff --git a/examples/ggwave-cli/main.cpp b/examples/ggwave-cli/main.cpp index 9ed5b35..9b597ee 100644 --- a/examples/ggwave-cli/main.cpp +++ b/examples/ggwave-cli/main.cpp @@ -37,8 +37,9 @@ int main(int argc, char** argv) { printf("Available Tx protocols:\n"); const auto & protocols = GGWave::getTxProtocols(); - for (const auto & protocol : protocols) { - printf(" -t%d : %s\n", protocol.first, protocol.second.name); + for (int i = 0; i < (int) protocols.size(); ++i) { + const auto & protocol = protocols[i]; + printf(" %d - %s\n", i, protocol.name); } if (txProtocolId < 0) { diff --git a/examples/ggwave-to-file/main.cpp b/examples/ggwave-to-file/main.cpp index 5e53a6b..c4e5c3b 100644 --- a/examples/ggwave-to-file/main.cpp +++ b/examples/ggwave-to-file/main.cpp @@ -19,8 +19,9 @@ int main(int argc, char** argv) { fprintf(stderr, " Available protocols:\n"); const auto & protocols = GGWave::getTxProtocols(); - for (const auto & protocol : protocols) { - fprintf(stderr, " %d - %s\n", protocol.first, protocol.second.name); + for (int i = 0; i < (int) protocols.size(); ++i) { + const auto & protocol = protocols[i]; + fprintf(stderr, " %d - %s\n", i, protocol.name); } fprintf(stderr, "\n"); diff --git a/examples/r2t2/main.cpp b/examples/r2t2/main.cpp index 670413e..4401070 100644 --- a/examples/r2t2/main.cpp +++ b/examples/r2t2/main.cpp @@ -53,12 +53,12 @@ int main(int argc, char** argv) { printf("\n"); const GGWave::TxProtocols protocols = { - { GGWAVE_TX_PROTOCOL_CUSTOM_0, { "[R2T2] Normal", 64, 9, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_1, { "[R2T2] Fast", 64, 6, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_2, { "[R2T2] Fastest", 64, 3, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_3, { "[R2T2] Low Normal", 16, 9, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_4, { "[R2T2] Low Fast", 16, 6, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_5, { "[R2T2] Low Fastest", 16, 3, 1, 2, } }, + { "[R2T2] Normal", 64, 9, 1, 2, true, }, + { "[R2T2] Fast", 64, 6, 1, 2, true, }, + { "[R2T2] Fastest", 64, 3, 1, 2, true, }, + { "[R2T2] Low Normal", 16, 9, 1, 2, true, }, + { "[R2T2] Low Fast", 16, 6, 1, 2, true, }, + { "[R2T2] Low Fastest", 16, 3, 1, 2, true, }, }; const auto argm = parseCmdArguments(argc, argv); @@ -81,21 +81,13 @@ int main(int argc, char** argv) { }); printf("Available Tx protocols:\n"); - for (const auto & protocol : protocols) { - printf(" -t%-2d : %-16s", protocol.first, protocol.second.name); - if (protocol.first == GGWAVE_TX_PROTOCOL_CUSTOM_0) { - printf(" (8.5 sec)\n"); - } else if (protocol.first == GGWAVE_TX_PROTOCOL_CUSTOM_1) { - printf(" (5.7 sec)\n"); - } else if (protocol.first == GGWAVE_TX_PROTOCOL_CUSTOM_2) { - printf(" (2.9 sec)\n"); - } else { - printf("\n"); - } + for (int i = 0; i < (int) protocols.size(); ++i) { + const auto & protocol = protocols[i]; + printf(" -t%-2d : %-16s\n", i, protocol.name); } printf("\n"); - if (protocols.find(GGWave::TxProtocolId(txProtocolId)) == protocols.end()) { + if (txProtocolId < 0 || txProtocolId >= (int) protocols.size()) { fprintf(stderr, "Unknown Tx protocol %d\n", txProtocolId); return -3; } diff --git a/examples/r2t2/r2t2-rx.cpp b/examples/r2t2/r2t2-rx.cpp index cfee5e2..ea44065 100644 --- a/examples/r2t2/r2t2-rx.cpp +++ b/examples/r2t2/r2t2-rx.cpp @@ -322,12 +322,12 @@ int main(int argc, char** argv) { #endif const GGWave::TxProtocols protocols = { - { GGWAVE_TX_PROTOCOL_CUSTOM_0, { "[R2T2] Normal", 64, 9, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_1, { "[R2T2] Fast", 64, 6, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_2, { "[R2T2] Fastest", 64, 3, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_3, { "[R2T2] Low Normal", 16, 9, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_4, { "[R2T2] Low Fast", 16, 6, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_5, { "[R2T2] Low Fastest", 16, 3, 1, 2, } }, + { "[R2T2] Normal", 64, 9, 1, 2, true, }, + { "[R2T2] Fast", 64, 6, 1, 2, true, }, + { "[R2T2] Fastest", 64, 3, 1, 2, true, }, + { "[R2T2] Low Normal", 16, 9, 1, 2, true, }, + { "[R2T2] Low Fast", 16, 6, 1, 2, true, }, + { "[R2T2] Low Fastest", 16, 3, 1, 2, true, }, }; const auto argm = parseCmdArguments(argc, argv); diff --git a/examples/waver/common.cpp b/examples/waver/common.cpp index df32c70..2db7eed 100644 --- a/examples/waver/common.cpp +++ b/examples/waver/common.cpp @@ -870,9 +870,7 @@ void renderMain() { float volume = 0.10f; GGWave::TxProtocols txProtocols; - GGWave::RxProtocols rxProtocols; - std::map rxProtocolSelected; }; static WindowId windowId = WindowId::Messages; @@ -964,9 +962,6 @@ void renderMain() { if (stateCurrent.flags.newTxProtocols) { settings.txProtocols = std::move(stateCurrent.txProtocols); settings.rxProtocols = settings.txProtocols; - for (auto & rxProtocol : settings.rxProtocols) { - settings.rxProtocolSelected[rxProtocol.first] = true; - } } stateCurrent.flags.clear(); stateCurrent.update = false; @@ -1153,8 +1148,10 @@ void renderMain() { } if (ImGui::BeginCombo("##txProtocol", settings.txProtocols.at(GGWave::TxProtocolId(settings.protocolId)).name)) { for (int i = 0; i < (int) settings.txProtocols.size(); ++i) { + const auto & txProtocol = settings.txProtocols.at(GGWave::TxProtocolId(i)); + if (txProtocol.name == nullptr) continue; const bool isSelected = (settings.protocolId == i); - if (ImGui::Selectable(settings.txProtocols.at(GGWave::TxProtocolId(i)).name, isSelected)) { + if (ImGui::Selectable(txProtocol.name, isSelected)) { settings.protocolId = i; } @@ -1289,11 +1286,12 @@ void renderMain() { } { ImGui::PushID("RxProtocols"); - for (const auto & rxProtocol : settings.rxProtocols) { + for (auto & rxProtocol : settings.rxProtocols) { + if (rxProtocol.name == nullptr) continue; auto posSave = ImGui::GetCursorScreenPos(); ImGui::Text("%s", ""); ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y }); - if (ImGui::Checkbox(rxProtocol.second.name, &settings.rxProtocolSelected.at(rxProtocol.first))) { + if (ImGui::Checkbox(rxProtocol.name, &rxProtocol.enabled)) { updateRxProtocols = true; } } @@ -1303,11 +1301,7 @@ void renderMain() { if (updateRxProtocols) { g_buffer.inputUI.update = true; g_buffer.inputUI.flags.changeRxProtocols = true; - g_buffer.inputUI.rxProtocols.clear(); - for (const auto & rxProtocol : settings.rxProtocols) { - if (settings.rxProtocolSelected.at(rxProtocol.first) == false) continue; - g_buffer.inputUI.rxProtocols[rxProtocol.first] = rxProtocol.second; - } + g_buffer.inputUI.rxProtocols = settings.rxProtocols; } ScrollWhenDraggingOnVoid(ImVec2(0.0f, -mouse_delta.y), ImGuiMouseButton_Left); diff --git a/include/ggwave/ggwave.h b/include/ggwave/ggwave.h index 0720b1b..6ec7d66 100644 --- a/include/ggwave/ggwave.h +++ b/include/ggwave/ggwave.h @@ -58,6 +58,8 @@ extern "C" { GGWAVE_TX_PROTOCOL_CUSTOM_7, GGWAVE_TX_PROTOCOL_CUSTOM_8, GGWAVE_TX_PROTOCOL_CUSTOM_9, + + GGWAVE_TX_PROTOCOL_COUNT, } ggwave_TxProtocolId; // Operating modes of ggwave @@ -301,8 +303,8 @@ extern "C" { // #include +#include #include -#include class GGWave { public: @@ -335,29 +337,39 @@ public: int bytesPerTx; // number of bytes in a chunk of data int extra; // 2 if this is a mono-tone protocol, 1 otherwise + bool enabled; + int nDataBitsPerTx() const { return 8*bytesPerTx; } }; using RxProtocol = TxProtocol; - using TxProtocols = std::map; - using RxProtocols = std::map; + using TxProtocols = std::vector; + using RxProtocols = std::vector; - static const TxProtocols & getTxProtocols() { - static const TxProtocols kTxProtocols { - { GGWAVE_TX_PROTOCOL_AUDIBLE_NORMAL, { "Normal", 40, 9, 3, 1, } }, - { GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, { "Fast", 40, 6, 3, 1, } }, - { GGWAVE_TX_PROTOCOL_AUDIBLE_FASTEST, { "Fastest", 40, 3, 3, 1, } }, - { GGWAVE_TX_PROTOCOL_ULTRASOUND_NORMAL, { "[U] Normal", 320, 9, 3, 1, } }, - { GGWAVE_TX_PROTOCOL_ULTRASOUND_FAST, { "[U] Fast", 320, 6, 3, 1, } }, - { GGWAVE_TX_PROTOCOL_ULTRASOUND_FASTEST, { "[U] Fastest", 320, 3, 3, 1, } }, - { GGWAVE_TX_PROTOCOL_DT_NORMAL, { "[DT] Normal", 24, 9, 1, 1, } }, - { GGWAVE_TX_PROTOCOL_DT_FAST, { "[DT] Fast", 24, 6, 1, 1, } }, - { GGWAVE_TX_PROTOCOL_DT_FASTEST, { "[DT] Fastest", 24, 3, 1, 1, } }, - { GGWAVE_TX_PROTOCOL_MT_NORMAL, { "[MT] Normal", 24, 9, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_MT_FAST, { "[MT] Fast", 24, 6, 1, 2, } }, - { GGWAVE_TX_PROTOCOL_MT_FASTEST, { "[MT] Fastest", 24, 3, 1, 2, } }, - }; + static TxProtocols & getTxProtocols() { + static TxProtocols kTxProtocols(GGWAVE_TX_PROTOCOL_COUNT); + + static bool kInitialized = false; + if (kInitialized == false) { + for (auto & txProtocol : kTxProtocols) { + txProtocol.enabled = false; + } + + kTxProtocols[GGWAVE_TX_PROTOCOL_AUDIBLE_NORMAL] = { "Normal", 40, 9, 3, 1, true, }; + kTxProtocols[GGWAVE_TX_PROTOCOL_AUDIBLE_FAST] = { "Fast", 40, 6, 3, 1, true, }; + kTxProtocols[GGWAVE_TX_PROTOCOL_AUDIBLE_FASTEST] = { "Fastest", 40, 3, 3, 1, true, }; + kTxProtocols[GGWAVE_TX_PROTOCOL_ULTRASOUND_NORMAL] = { "[U] Normal", 320, 9, 3, 1, true, }; + kTxProtocols[GGWAVE_TX_PROTOCOL_ULTRASOUND_FAST] = { "[U] Fast", 320, 6, 3, 1, true, }; + kTxProtocols[GGWAVE_TX_PROTOCOL_ULTRASOUND_FASTEST] = { "[U] Fastest", 320, 3, 3, 1, true, }; + kTxProtocols[GGWAVE_TX_PROTOCOL_DT_NORMAL] = { "[DT] Normal", 24, 9, 1, 1, true, }; + kTxProtocols[GGWAVE_TX_PROTOCOL_DT_FAST] = { "[DT] Fast", 24, 6, 1, 1, true, }; + kTxProtocols[GGWAVE_TX_PROTOCOL_DT_FASTEST] = { "[DT] Fastest", 24, 3, 1, 1, true, }; + kTxProtocols[GGWAVE_TX_PROTOCOL_MT_NORMAL] = { "[MT] Normal", 24, 9, 1, 2, true, }; + kTxProtocols[GGWAVE_TX_PROTOCOL_MT_FAST] = { "[MT] Fast", 24, 6, 1, 2, true, }; + kTxProtocols[GGWAVE_TX_PROTOCOL_MT_FASTEST] = { "[MT] Fastest", 24, 3, 1, 2, true, }; + kInitialized = true; + } return kTxProtocols; } @@ -447,9 +459,9 @@ public: // Tx static TxProtocolId getDefaultTxProtocolId() { return GGWAVE_TX_PROTOCOL_AUDIBLE_FAST; } - static const TxProtocol & getDefaultTxProtocol() { return getTxProtocols().at(getDefaultTxProtocolId()); } - static const TxProtocol & getTxProtocol(int id) { return getTxProtocols().at(TxProtocolId(id)); } - static const TxProtocol & getTxProtocol(TxProtocolId id) { return getTxProtocols().at(id); } + static const TxProtocol & getDefaultTxProtocol() { return getTxProtocols()[getDefaultTxProtocolId()]; } + static const TxProtocol & getTxProtocol(int id) { return getTxProtocols()[id]; } + static const TxProtocol & getTxProtocol(TxProtocolId id) { return getTxProtocols()[id]; } // get a list of the tones generated for the last waveform // diff --git a/src/ggwave.cpp b/src/ggwave.cpp index 908d025..b0649a0 100644 --- a/src/ggwave.cpp +++ b/src/ggwave.cpp @@ -177,10 +177,10 @@ void ggwave_toggleRxProtocol( if (state == 0) { // disable Rx protocol - g_rxProtocols[instance].erase(rxProtocolId); + g_rxProtocols[instance][rxProtocolId].enabled = false; } else if (state == 1) { // enable Rx protocol - g_rxProtocols[instance][rxProtocolId] = GGWave::getTxProtocols().at(rxProtocolId); + g_rxProtocols[instance][rxProtocolId].enabled = true; } g_instances[instance]->setRxProtocols(g_rxProtocols[instance]); @@ -1453,9 +1453,11 @@ void GGWave::decode_variable() { const int step = m_samplesPerFrame/stepsPerFrame; bool isValid = false; - for (const auto & rxProtocolPair : m_rx->rxProtocols) { - const auto & rxProtocolId = rxProtocolPair.first; - const auto & rxProtocol = rxProtocolPair.second; + for (int rxProtocolId = 0; rxProtocolId < (int) m_rx->rxProtocols.size(); ++rxProtocolId) { + const auto & rxProtocol = m_rx->rxProtocols[rxProtocolId]; + if (rxProtocol.enabled == false) { + continue; + } // skip Rx protocol if it is mono-tone if (rxProtocol.extra == 2) { @@ -1600,11 +1602,15 @@ void GGWave::decode_variable() { if (m_rx->receivingData == false) { bool isReceiving = false; - for (const auto & rxProtocol : getTxProtocols()) { + for (const auto & rxProtocol : m_rx->rxProtocols) { + if (rxProtocol.enabled == false) { + continue; + } + int nDetectedMarkerBits = m_nBitsInMarker; for (int i = 0; i < m_nBitsInMarker; ++i) { - double freq = bitFreq(rxProtocol.second, i); + double freq = bitFreq(rxProtocol, i); int bin = round(freq*m_ihzPerSample); if (i%2 == 0) { @@ -1615,7 +1621,7 @@ void GGWave::decode_variable() { } if (nDetectedMarkerBits == m_nBitsInMarker) { - m_rx->markerFreqStart = rxProtocol.second.freqStart; + m_rx->markerFreqStart = rxProtocol.freqStart; isReceiving = true; break; } @@ -1649,11 +1655,15 @@ void GGWave::decode_variable() { } else { bool isEnded = false; - for (const auto & rxProtocol : getTxProtocols()) { + for (const auto & rxProtocol : m_rx->rxProtocols) { + if (rxProtocol.enabled == false) { + continue; + } + int nDetectedMarkerBits = m_nBitsInMarker; for (int i = 0; i < m_nBitsInMarker; ++i) { - double freq = bitFreq(rxProtocol.second, i); + double freq = bitFreq(rxProtocol, i); int bin = round(freq*m_ihzPerSample); if (i%2 == 0) { @@ -1717,9 +1727,11 @@ void GGWave::decode_fixed() { } bool isValid = false; - for (const auto & rxProtocolPair : m_rx->rxProtocols) { - const auto & rxProtocolId = rxProtocolPair.first; - const auto & rxProtocol = rxProtocolPair.second; + for (int rxProtocolId = 0; rxProtocolId < (int) m_rx->rxProtocols.size(); ++rxProtocolId) { + const auto & rxProtocol = m_rx->rxProtocols[rxProtocolId]; + if (rxProtocol.enabled == false) { + continue; + } const int binStart = rxProtocol.freqStart; const int binDelta = 16; @@ -1844,23 +1856,32 @@ void GGWave::decode_fixed() { int GGWave::maxFramesPerTx() const { int res = 0; for (const auto & protocol : getTxProtocols()) { - res = std::max(res, protocol.second.framesPerTx); + if (protocol.enabled == false) { + continue; + } + res = std::max(res, protocol.framesPerTx); } return res; } int GGWave::minBytesPerTx() const { - int res = getTxProtocols().begin()->second.bytesPerTx; + int res = 1; for (const auto & protocol : getTxProtocols()) { - res = std::min(res, protocol.second.bytesPerTx); + if (protocol.enabled == false) { + continue; + } + res = std::min(res, protocol.bytesPerTx); } return res; } int GGWave::maxBytesPerTx() const { - int res = getTxProtocols().begin()->second.bytesPerTx; + int res = 1; for (const auto & protocol : getTxProtocols()) { - res = std::max(res, protocol.second.bytesPerTx); + if (protocol.enabled == false) { + continue; + } + res = std::max(res, protocol.bytesPerTx); } return res; } diff --git a/tests/test-ggwave.cpp b/tests/test-ggwave.cpp index 5b4ef53..0a337c5 100644 --- a/tests/test-ggwave.cpp +++ b/tests/test-ggwave.cpp @@ -8,6 +8,7 @@ #include #include #include +#include float frand() { return float(rand()%RAND_MAX)/RAND_MAX; } @@ -227,7 +228,7 @@ int main(int argc, char ** argv) { parameters.sampleRateInp = srInp; GGWave instanceInp(parameters); - instanceInp.setRxProtocols({{GGWAVE_TX_PROTOCOL_DT_FASTEST, instanceInp.getTxProtocol(GGWAVE_TX_PROTOCOL_DT_FASTEST)}}); + instanceInp.setRxProtocols({instanceInp.getTxProtocol(GGWAVE_TX_PROTOCOL_DT_FASTEST)}); instanceInp.decode(buffer.data(), buffer.size()); GGWave::TxRxData result; @@ -248,11 +249,12 @@ int main(int argc, char ** argv) { if (formatInp != GGWAVE_SAMPLE_FORMAT_F32) continue; } for (const auto & txProtocol : GGWave::getTxProtocols()) { - printf("Testing: protocol = %s, in = %d, out = %d\n", txProtocol.second.name, formatInp, formatOut); + if (txProtocol.enabled == false) continue; + printf("Testing: protocol = %s, in = %d, out = %d\n", txProtocol.name, formatInp, formatOut); for (int length = 1; length <= (int) payload.size(); ++length) { // mono-tone protocols with variable length are not supported - if (txProtocol.second.extra == 2) { + if (txProtocol.extra == 2) { break; } @@ -263,8 +265,8 @@ int main(int argc, char ** argv) { parameters.sampleFormatOut = formatOut; GGWave instance(parameters); - instance.setRxProtocols({{txProtocol.first, txProtocol.second}}); - instance.init(length, payload.data(), txProtocol.second, 25); + instance.setRxProtocols({txProtocol}); + instance.init(length, payload.data(), txProtocol, 25); const auto expectedSize = instance.encodeSize_bytes(); const auto nBytes = instance.encode(); printf("Expected = %d, actual = %d\n", expectedSize, nBytes); @@ -290,8 +292,8 @@ int main(int argc, char ** argv) { parameters.sampleFormatOut = formatOut; GGWave instance(parameters); - instance.setRxProtocols({{txProtocol.first, txProtocol.second}}); - instance.init(length, payload.data(), txProtocol.second, 10); + instance.setRxProtocols({txProtocol}); + instance.init(length, payload.data(), txProtocol, 10); const auto expectedSize = instance.encodeSize_bytes(); const auto nBytes = instance.encode(); printf("Expected = %d, actual = %d\n", expectedSize, nBytes);