diff --git a/bindings/javascript/emscripten.cpp b/bindings/javascript/emscripten.cpp index c1d58bf..4794988 100644 --- a/bindings/javascript/emscripten.cpp +++ b/bindings/javascript/emscripten.cpp @@ -88,4 +88,11 @@ EMSCRIPTEN_BINDINGS(ggwave) { []() { ggwave_setLogFile(stderr); })); + + emscripten::function("toggleRxProtocol", emscripten::optional_override( + [](ggwave_Instance instance, + ggwave_TxProtocolId rxProtocolId, + int state) { + ggwave_toggleRxProtocol(instance, rxProtocolId, state); + })); } diff --git a/bindings/python/cggwave.pxd b/bindings/python/cggwave.pxd index 1ad79a5..9db4138 100644 --- a/bindings/python/cggwave.pxd +++ b/bindings/python/cggwave.pxd @@ -14,7 +14,21 @@ cdef extern from "ggwave.h" nogil: GGWAVE_TX_PROTOCOL_AUDIBLE_FASTEST, GGWAVE_TX_PROTOCOL_ULTRASOUND_NORMAL, GGWAVE_TX_PROTOCOL_ULTRASOUND_FAST, - GGWAVE_TX_PROTOCOL_ULTRASOUND_FASTEST + GGWAVE_TX_PROTOCOL_ULTRASOUND_FASTEST, + GGWAVE_TX_PROTOCOL_DT_NORMAL, + GGWAVE_TX_PROTOCOL_DT_FAST, + GGWAVE_TX_PROTOCOL_DT_FASTEST, + + GGWAVE_TX_PROTOCOL_CUSTOM_0, + GGWAVE_TX_PROTOCOL_CUSTOM_1, + GGWAVE_TX_PROTOCOL_CUSTOM_2, + GGWAVE_TX_PROTOCOL_CUSTOM_3, + GGWAVE_TX_PROTOCOL_CUSTOM_4, + GGWAVE_TX_PROTOCOL_CUSTOM_5, + GGWAVE_TX_PROTOCOL_CUSTOM_6, + GGWAVE_TX_PROTOCOL_CUSTOM_7, + GGWAVE_TX_PROTOCOL_CUSTOM_8, + GGWAVE_TX_PROTOCOL_CUSTOM_9 ctypedef struct ggwave_Parameters: int payloadLength @@ -49,3 +63,8 @@ cdef extern from "ggwave.h" nogil: char * outputBuffer); void ggwave_setLogFile(void * fptr); + + void ggwave_toggleRxProtocol( + ggwave_Instance instance, + ggwave_TxProtocolId rxProtocolId, + int state); diff --git a/bindings/python/ggwave.pyx b/bindings/python/ggwave.pyx index 46db396..0eec7eb 100644 --- a/bindings/python/ggwave.pyx +++ b/bindings/python/ggwave.pyx @@ -69,3 +69,6 @@ def disableLog(): def enableLog(): cggwave.ggwave_setLogFile(stderr); + +def toggleRxProtocol(instance, rxProtocolId, state): + cggwave.ggwave_toggleRxProtocol(instance, rxProtocolId, state); diff --git a/include/ggwave/ggwave.h b/include/ggwave/ggwave.h index 2cf6d60..e6b5687 100644 --- a/include/ggwave/ggwave.h +++ b/include/ggwave/ggwave.h @@ -253,6 +253,23 @@ extern "C" { char * outputBuffer, int outputSize); + // Toggle Rx protocols on and off + // + // instance - the GGWave instance to use + // rxProtocolId - Id of the Rx protocol to modify + // state - 0 - disable, 1 - enable + // + // If an Rx protocol is enabled, the GGWave instance will attempt to decode received + // data using this protocol. By default, all protocols are enabled. + // Use this function to restrict the number of Rx protocols used in the decoding + // process. This helps to reduce the number of false positives and improves the transmission + // accuracy, especially when the Tx/Rx protocol is known in advance. + // + GGWAVE_API void ggwave_toggleRxProtocol( + ggwave_Instance instance, + ggwave_TxProtocolId rxProtocolId, + int state); + #ifdef __cplusplus } diff --git a/src/ggwave.cpp b/src/ggwave.cpp index 081447b..2c0b629 100644 --- a/src/ggwave.cpp +++ b/src/ggwave.cpp @@ -25,6 +25,7 @@ namespace { FILE * g_fptr = stderr; std::map g_instances; +std::map g_rxProtocols; } extern "C" @@ -178,6 +179,27 @@ int ggwave_ndecode( return rxDataLength; } +extern "C" +void ggwave_toggleRxProtocol( + ggwave_Instance instance, + ggwave_TxProtocolId rxProtocolId, + int state) { + // if never called - initialize with all available protocols + if (g_rxProtocols.find(instance) == g_rxProtocols.end()) { + g_rxProtocols[instance] = GGWave::getTxProtocols(); + } + + if (state == 0) { + // disable Rx protocol + g_rxProtocols[instance].erase(rxProtocolId); + } else if (state == 1) { + // enable Rx protocol + g_rxProtocols[instance][rxProtocolId] = GGWave::getTxProtocols().at(rxProtocolId); + } + + g_instances[instance]->setRxProtocols(g_rxProtocols[instance]); +} + // // C++ implementation // diff --git a/tests/test-ggwave.c b/tests/test-ggwave.c index 82a457b..9f30f22 100644 --- a/tests/test-ggwave.c +++ b/tests/test-ggwave.c @@ -27,10 +27,10 @@ int main() { const char * payload = "test"; char decoded[16]; - int n = ggwave_encode(instance, payload, 4, GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, 50, NULL, 1); + int n = ggwave_encode(instance, payload, 4, GGWAVE_TX_PROTOCOL_AUDIBLE_FASTEST, 50, NULL, 1); char waveform[n]; - int ne = ggwave_encode(instance, payload, 4, GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, 50, waveform, 0); + int ne = ggwave_encode(instance, payload, 4, GGWAVE_TX_PROTOCOL_AUDIBLE_FASTEST, 50, waveform, 0); CHECK(ne > 0); // not enough output buffer size to store the decoded message @@ -39,12 +39,22 @@ int main() { // just enough size to store it ret = ggwave_ndecode(instance, waveform, sizeof(signed short)*ne, decoded, 4); - CHECK(ret == 4); // success + CHECK(ret == 4); // success // unsafe method - will write the decoded output to the output buffer regardless of the size ret = ggwave_decode(instance, waveform, sizeof(signed short)*ne, decoded); CHECK(ret == 4); + // disable Rx protocol + ggwave_toggleRxProtocol(instance, GGWAVE_TX_PROTOCOL_AUDIBLE_FASTEST, 0); + ret = ggwave_ndecode(instance, waveform, sizeof(signed short)*ne, decoded, 4); + CHECK(ret == -1); // fail + + // enable Rx protocol + ggwave_toggleRxProtocol(instance, GGWAVE_TX_PROTOCOL_AUDIBLE_FASTEST, 1); + ret = ggwave_ndecode(instance, waveform, sizeof(signed short)*ne, decoded, 4); + CHECK(ret == 4); // success + decoded[ret] = 0; // null-terminate the received data CHECK(strcmp(decoded, payload) == 0); diff --git a/tests/test-ggwave.py b/tests/test-ggwave.py index ec31cc3..400a1e3 100644 --- a/tests/test-ggwave.py +++ b/tests/test-ggwave.py @@ -17,3 +17,17 @@ res = ggwave.decode(instance, waveform) if res != payload.encode(): sys.exit(1) + +# disable the Rx protocol - the decoding should fail +ggwave.toggleRxProtocol(instance, rxProtocolId = 1, state = 0) +res = ggwave.decode(instance, waveform) + +if res != None: + sys.exit(1) + +# re-enable the Rx protocol - the decoding should succeed +ggwave.toggleRxProtocol(instance, rxProtocolId = 1, state = 1) +res = ggwave.decode(instance, waveform) + +if res != payload.encode(): + sys.exit(1)