Skip to content

Commit 3591285

Browse files
committed
waver v1.5.2 : add option to shift the base tx/rx freqency
This can be used to easily change the frequency range of a protocols. Make sure that the transmitter and receiver are using the same exact shift.
1 parent f2c8231 commit 3591285

File tree

3 files changed

+84
-19
lines changed

3 files changed

+84
-19
lines changed

examples/arduino-tx/arduino-tx.ino

+7
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ void setup() {
8989
// Protocols to use for TX
9090
GGWave::Protocols::tx().only(GGWAVE_PROTOCOL_MT_FASTEST);
9191

92+
// Sometimes, the speaker might not be able to produce frequencies in the Mono-tone range of 1-2 kHz.
93+
// In such cases, you can shift the base frequency up by changing the "freqStart" parameter of the protocol.
94+
// Make sure that in the receiver (for example, the "Waver" app) the base frequency is shifted by the same amount.
95+
// Here we shift the frequency by +48 bins. Each bin is equal to 48000/1024 = 46.875 Hz.
96+
// So the base frequency is shifted by +2250 Hz.
97+
//GGWave::Protocols::tx()[GGWAVE_PROTOCOL_MT_FASTEST].freqStart += 48;
98+
9299
// Initialize the ggwave instance and print the memory usage
93100
ggwave.prepare(p);
94101
Serial.println(ggwave.heapSize());

examples/waver/common.cpp

+76-18
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ struct Input {
236236
dst.update = true;
237237
dst.flags.needReinit = true;
238238
dst.sampleRateOffset = std::move(this->sampleRateOffset);
239+
dst.freqStartShift = std::move(this->freqStartShift);
239240
dst.payloadLength = std::move(this->payloadLength);
240241
dst.directSequenceSpread = std::move(this->directSequenceSpread);
241242
}
@@ -266,6 +267,7 @@ struct Input {
266267

267268
// reinit
268269
float sampleRateOffset = 0;
270+
int freqStartShift = 0;
269271
int payloadLength = -1;
270272

271273
// spectrum
@@ -636,10 +638,19 @@ void updateCore() {
636638
if (inputCurrent.flags.needReinit) {
637639
static auto sampleRateInpOld = ggWave->sampleRateInp();
638640
static auto sampleRateOutOld = ggWave->sampleRateOut();
641+
static auto freqStartShiftOld = 0;
642+
639643
auto sampleFormatInpOld = ggWave->sampleFormatInp();
640644
auto sampleFormatOutOld = ggWave->sampleFormatOut();
641645
auto rxProtocolsOld = ggWave->rxProtocols();
642646

647+
for (int i = 0; i < GGWAVE_PROTOCOL_COUNT; ++i) {
648+
GGWave::Protocols::tx()[i].freqStart = std::max(1, GGWave::Protocols::tx()[i].freqStart + inputCurrent.freqStartShift - freqStartShiftOld);
649+
rxProtocolsOld[i].freqStart = std::max(1, rxProtocolsOld[i].freqStart + inputCurrent.freqStartShift - freqStartShiftOld);
650+
}
651+
652+
freqStartShiftOld = inputCurrent.freqStartShift;
653+
643654
GGWave::OperatingMode mode = GGWAVE_OPERATING_MODE_RX_AND_TX;
644655
if (inputCurrent.directSequenceSpread) mode |= GGWAVE_OPERATING_MODE_USE_DSS;
645656

@@ -853,6 +864,8 @@ void renderMain() {
853864
int protocolId = GGWAVE_PROTOCOL_AUDIBLE_FAST;
854865
bool isSampleRateOffset = false;
855866
float sampleRateOffset = -512.0f;
867+
bool isFreqStartShift = false;
868+
int freqStartShift = 48;
856869
bool isFixedLength = false;
857870
bool directSequenceSpread = false;
858871
int payloadLength = 16;
@@ -1055,7 +1068,7 @@ void renderMain() {
10551068

10561069
if (windowId == WindowId::Settings) {
10571070
ImGui::BeginChild("Settings:main", ImGui::GetContentRegionAvail(), true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
1058-
ImGui::Text("Waver v1.5.1");
1071+
ImGui::Text("Waver v1.5.2");
10591072
ImGui::Separator();
10601073

10611074
ImGui::Text("%s", "");
@@ -1177,7 +1190,10 @@ void renderMain() {
11771190
{
11781191
const float df = statsCurrent.sampleRate/statsCurrent.samplesPerFrame;
11791192
const auto & protocol = settings.txProtocols[settings.protocolId];
1180-
ImGui::Text("%6.2f Hz - %6.2f Hz", df*protocol.freqStart, df*(protocol.freqStart + float(2*16*protocol.bytesPerTx)/protocol.extra));
1193+
const auto freqStart = std::max(1, protocol.freqStart + (settings.isFreqStartShift ? settings.freqStartShift : 0));
1194+
const float f0 = df*freqStart;
1195+
const float f1 = df*(freqStart + float(2*16*protocol.bytesPerTx)/protocol.extra);
1196+
ImGui::Text("%6.2f Hz - %6.2f Hz", f0, f1);
11811197
}
11821198

11831199
// fixed-length
@@ -1204,65 +1220,107 @@ void renderMain() {
12041220
if (settings.isFixedLength) {
12051221
ImGui::SameLine();
12061222
ImGui::PushItemWidth(0.5*ImGui::GetContentRegionAvailWidth());
1207-
if (ImGui::SliderInt("Bytes", &settings.payloadLength, 1, GGWave::kMaxLengthFixed)) {
1223+
if (ImGui::DragInt("Bytes", &settings.payloadLength, 1, 1, GGWave::kMaxLengthFixed)) {
12081224
g_buffer.inputUI.update = true;
12091225
g_buffer.inputUI.flags.needReinit = true;
12101226
g_buffer.inputUI.payloadLength = settings.isFixedLength ? settings.payloadLength : -1;
12111227
}
12121228
ImGui::PopItemWidth();
12131229
}
12141230

1215-
// Output sample-rate offset
1216-
ImGui::Text("%s", "");
1231+
// Direct-sequence spread
1232+
//ImGui::Text("%s", "");
12171233
{
12181234
auto posSave = ImGui::GetCursorScreenPos();
12191235
ImGui::Text("%s", "");
12201236
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
12211237
ImGui::PushTextWrapPos();
1222-
ImGui::TextDisabled("Modify the output Sampling Rate");
1238+
ImGui::TextDisabled("Direct-sequence spread");
12231239
ImGui::PopTextWrapPos();
12241240
}
12251241
{
12261242
auto posSave = ImGui::GetCursorScreenPos();
1227-
ImGui::Text("Pitch shift: ");
1243+
ImGui::Text("Use DSS: ");
12281244
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
12291245
}
1230-
if (ImGui::Checkbox("##output-sample-rate-offset", &settings.isSampleRateOffset)) {
1246+
if (ImGui::Checkbox("##direct-sequence-spread", &settings.directSequenceSpread)) {
12311247
g_buffer.inputUI.update = true;
12321248
g_buffer.inputUI.flags.needReinit = true;
1233-
g_buffer.inputUI.sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0;
1249+
g_buffer.inputUI.directSequenceSpread = settings.directSequenceSpread;
12341250
}
12351251

1236-
if (settings.isSampleRateOffset) {
1252+
// FreqStart offset
1253+
//ImGui::Text("%s", "");
1254+
{
1255+
auto posSave = ImGui::GetCursorScreenPos();
1256+
ImGui::Text("%s", "");
1257+
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
1258+
ImGui::PushTextWrapPos();
1259+
ImGui::TextDisabled("Apply tx/rx frequency shift");
1260+
ImGui::PopTextWrapPos();
1261+
}
1262+
{
1263+
auto posSave = ImGui::GetCursorScreenPos();
1264+
ImGui::Text("Freq shift: ");
1265+
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
1266+
}
1267+
if (ImGui::Checkbox("##freq-start-offset", &settings.isFreqStartShift)) {
1268+
g_buffer.inputUI.update = true;
1269+
g_buffer.inputUI.flags.needReinit = true;
1270+
g_buffer.inputUI.freqStartShift = settings.isFreqStartShift ? settings.freqStartShift : 0;
1271+
}
1272+
1273+
if (settings.isFreqStartShift) {
12371274
ImGui::SameLine();
12381275
ImGui::PushItemWidth(0.5*ImGui::GetContentRegionAvailWidth());
1239-
if (ImGui::SliderFloat("Samples", &settings.sampleRateOffset, -1000, 1000, "%.0f")) {
1276+
if (ImGui::DragInt("bins", &settings.freqStartShift, 1, -64, 64, "%d")) {
12401277
g_buffer.inputUI.update = true;
12411278
g_buffer.inputUI.flags.needReinit = true;
1242-
g_buffer.inputUI.sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0;
1279+
g_buffer.inputUI.freqStartShift = settings.isFreqStartShift ? settings.freqStartShift : 0;
12431280
}
12441281
ImGui::PopItemWidth();
1282+
1283+
{
1284+
auto posSave = ImGui::GetCursorScreenPos();
1285+
ImGui::Text("");
1286+
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
1287+
}
1288+
{
1289+
const float df = statsCurrent.sampleRate/statsCurrent.samplesPerFrame;
1290+
ImGui::Text("%6.2f Hz", df*settings.freqStartShift);
1291+
}
12451292
}
12461293

1247-
// Direct-sequence spread
1248-
ImGui::Text("%s", "");
1294+
// Output sample-rate offset
1295+
//ImGui::Text("%s", "");
12491296
{
12501297
auto posSave = ImGui::GetCursorScreenPos();
12511298
ImGui::Text("%s", "");
12521299
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
12531300
ImGui::PushTextWrapPos();
1254-
ImGui::TextDisabled("Direct-sequence spread");
1301+
ImGui::TextDisabled("Modify the output Sampling Rate");
12551302
ImGui::PopTextWrapPos();
12561303
}
12571304
{
12581305
auto posSave = ImGui::GetCursorScreenPos();
1259-
ImGui::Text("Use DSS: ");
1306+
ImGui::Text("Pitch shift: ");
12601307
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
12611308
}
1262-
if (ImGui::Checkbox("##direct-sequence-spread", &settings.directSequenceSpread)) {
1309+
if (ImGui::Checkbox("##output-sample-rate-offset", &settings.isSampleRateOffset)) {
12631310
g_buffer.inputUI.update = true;
12641311
g_buffer.inputUI.flags.needReinit = true;
1265-
g_buffer.inputUI.directSequenceSpread = settings.directSequenceSpread;
1312+
g_buffer.inputUI.sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0;
1313+
}
1314+
1315+
if (settings.isSampleRateOffset) {
1316+
ImGui::SameLine();
1317+
ImGui::PushItemWidth(0.5*ImGui::GetContentRegionAvailWidth());
1318+
if (ImGui::SliderFloat("Samples", &settings.sampleRateOffset, -1000, 1000, "%.0f")) {
1319+
g_buffer.inputUI.update = true;
1320+
g_buffer.inputUI.flags.needReinit = true;
1321+
g_buffer.inputUI.sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0;
1322+
}
1323+
ImGui::PopItemWidth();
12661324
}
12671325

12681326
// rx protocols

snap/snapcraft.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
name: waver
3-
version: '1.5.1'
3+
version: '1.5.2'
44
summary: Data over sound
55
description: |
66
Waver allows you to send and receive text messages from nearby devices through sound waves.

0 commit comments

Comments
 (0)