diff --git a/README-tmpl.md b/README-tmpl.md index ea2394e..77bc2c3 100644 --- a/README-tmpl.md +++ b/README-tmpl.md @@ -16,6 +16,8 @@ Click on the images below to hear what it sounds like: +https://user-images.githubusercontent.com/1991296/166411509-5e1b9bcb-3655-40b1-9dc3-9bec72889dcf.mp4 + ## Details This library allows you to communicate small amounts of data between air-gapped devices using sound. It implements a simple FSK-based transmission protocol that can be easily integrated in various projects. The bandwidth rate is between 8-16 bytes/sec depending on the protocol parameters. Error correction codes (ECC) are used to improve demodulation robustness. diff --git a/examples/r2t2/main.cpp b/examples/r2t2/main.cpp index 0d8013c..7c9e416 100644 --- a/examples/r2t2/main.cpp +++ b/examples/r2t2/main.cpp @@ -16,12 +16,17 @@ #include #include -void processTone(int fd, double freq_hz, long duration_ms, bool useBeep, bool printTones) { +void processTone(int fd, double freq_hz, long duration_ms, bool useBeep, bool printTones, bool printArduino) { if (printTones) { printf("TONE %8.2f Hz %5ld ms\n", freq_hz, duration_ms); return; } + if (printArduino) { + printf("tone(kPinSpeaker, %8.2f); delay(%4ld);\n", freq_hz, duration_ms); + return; + } + if (useBeep) { static char cmd[128]; snprintf(cmd, 128, "beep -f %g -l %ld", freq_hz, duration_ms); @@ -36,24 +41,29 @@ void processTone(int fd, double freq_hz, long duration_ms, bool useBeep, bool pr } int main(int argc, char** argv) { - printf("Usage: %s [-tN] [-lN]\n", argv[0]); + printf("Usage: %s [-p] [-b] [-tN] [-lN]\n", argv[0]); printf(" -p - print tones, no playback\n"); - //printf(" -b - use 'beep' command\n"); + printf(" -A - print Arduino code\n"); + printf(" -b - use 'beep' command\n"); printf(" -tN - transmission protocol\n"); printf(" -lN - fixed payload length of size N, N in [1, %d]\n", GGWave::kMaxLengthFixed); printf("\n"); const GGWave::TxProtocols protocols = { - { GGWAVE_TX_PROTOCOL_CUSTOM_0, { "[R2T2] Normal", 64, 9, 1, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_1, { "[R2T2] Fast", 64, 6, 1, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_2, { "[R2T2] Fastest", 64, 3, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_0, { "[R2T2] Normal", 64, 9, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_1, { "[R2T2] Fast", 64, 6, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_2, { "[R2T2] Fastest", 64, 3, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_3, { "[R2T2] Low Normal", 16, 9, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_4, { "[R2T2] Low Fast", 16, 6, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_5, { "[R2T2] Low Fastest", 16, 3, 1, } }, }; - auto argm = parseCmdArguments(argc, argv); - bool printTones = argm.find("p") != argm.end(); - bool useBeep = false; //argm.find("b") != argm.end(); - int txProtocolId = argm["t"].empty() ? GGWAVE_TX_PROTOCOL_CUSTOM_0 : std::stoi(argm["t"]); - int payloadLength = argm["l"].empty() ? 16 : std::stoi(argm["l"]); + const auto argm = parseCmdArguments(argc, argv); + const bool printTones = argm.count("p") > 0; + const bool printArduino = argm.count("A") > 0; + const bool useBeep = argm.count("b") > 0; + const int txProtocolId = argm.count("t") == 0 ? GGWAVE_TX_PROTOCOL_CUSTOM_0 : std::stoi(argm.at("t")); + const int payloadLength = argm.count("l") == 0 ? 16 : std::stoi(argm.at("l")); GGWave ggWave({ payloadLength, @@ -87,7 +97,7 @@ int main(int argc, char** argv) { printf("Selecting Tx protocol %d\n", txProtocolId); int fd = 1; - if (useBeep == false && printTones == false) { + if (useBeep == false && printTones == false && printArduino == false) { if (ioctl(fd, KDMKTONE, 0)) { fd = open(CONSOLE, O_RDONLY); } @@ -129,7 +139,7 @@ int main(int argc, char** argv) { const auto & tone = tonesCur.front(); if (tone.freq_hz != lastF) { if (nFrames > 0) { - processTone(fd, lastF, nFrames*tone.duration_ms, useBeep, printTones); + processTone(fd, lastF, nFrames*tone.duration_ms, useBeep, printTones, printArduino); } nFrames = 0; lastF = tone.freq_hz; @@ -139,7 +149,7 @@ int main(int argc, char** argv) { if (nFrames > 0) { const auto & tone = tones.front().front(); - processTone(fd, lastF, nFrames*tone.duration_ms, useBeep, printTones); + processTone(fd, lastF, nFrames*tone.duration_ms, useBeep, printTones, printArduino); } return 0; diff --git a/examples/r2t2/r2t2-rx.cpp b/examples/r2t2/r2t2-rx.cpp index 9189d22..38636d9 100644 --- a/examples/r2t2/r2t2-rx.cpp +++ b/examples/r2t2/r2t2-rx.cpp @@ -309,21 +309,30 @@ int main(int argc, char** argv) { if (argv[1]) { GGWave_setDefaultCaptureDeviceName(argv[1]); } +#else + printf("Usage: %s [-cN] [-lN]\n", argv[0]); + printf(" -cN - select capture device N\n"); + printf(" -lN - fixed payload length of size N, N in [1, %d]\n", GGWave::kMaxLengthFixed); + printf("\n"); #endif const GGWave::TxProtocols protocols = { - { GGWAVE_TX_PROTOCOL_CUSTOM_0, { "[R2T2] Normal", 64, 9, 1, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_1, { "[R2T2] Fast", 64, 6, 1, } }, - { GGWAVE_TX_PROTOCOL_CUSTOM_2, { "[R2T2] Fastest", 64, 3, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_0, { "[R2T2] Normal", 64, 9, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_1, { "[R2T2] Fast", 64, 6, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_2, { "[R2T2] Fastest", 64, 3, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_3, { "[R2T2] Low Normal", 16, 9, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_4, { "[R2T2] Low Fast", 16, 6, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_5, { "[R2T2] Low Fastest", 16, 3, 1, } }, }; - auto argm = parseCmdArguments(argc, argv); - int captureId = argm["c"].empty() ? 0 : std::stoi(argm["c"]); + const auto argm = parseCmdArguments(argc, argv); + const int captureId = argm.count("c") == 0 ? 0 : std::stoi(argm.at("c")); + const int payloadLength = argm.count("l") == 0 ? 16 : std::stoi(argm.at("l")); bool isInitialized = false; g_doInit = [&]() { - if (GGWave_init(0, captureId, 16, 0) == false) { + if (GGWave_init(0, captureId, payloadLength, 0) == false) { fprintf(stderr, "Failed to initialize GGWave\n"); return false; } @@ -331,6 +340,7 @@ int main(int argc, char** argv) { g_ggWave->setRxProtocols(protocols); isInitialized = true; + printf("Listening for payload with length = %d bytes ..\n", payloadLength); return true; };