Skip to content

Commit

Permalink
waver v1.5.2 : add option to shift the base tx/rx freqency
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ggerganov committed Jul 10, 2022
1 parent f2c8231 commit 3591285
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 19 deletions.
7 changes: 7 additions & 0 deletions examples/arduino-tx/arduino-tx.ino
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ void setup() {
// Protocols to use for TX
GGWave::Protocols::tx().only(GGWAVE_PROTOCOL_MT_FASTEST);

// Sometimes, the speaker might not be able to produce frequencies in the Mono-tone range of 1-2 kHz.
// In such cases, you can shift the base frequency up by changing the "freqStart" parameter of the protocol.
// Make sure that in the receiver (for example, the "Waver" app) the base frequency is shifted by the same amount.
// Here we shift the frequency by +48 bins. Each bin is equal to 48000/1024 = 46.875 Hz.
// So the base frequency is shifted by +2250 Hz.
//GGWave::Protocols::tx()[GGWAVE_PROTOCOL_MT_FASTEST].freqStart += 48;

// Initialize the ggwave instance and print the memory usage
ggwave.prepare(p);
Serial.println(ggwave.heapSize());
Expand Down
94 changes: 76 additions & 18 deletions examples/waver/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ struct Input {
dst.update = true;
dst.flags.needReinit = true;
dst.sampleRateOffset = std::move(this->sampleRateOffset);
dst.freqStartShift = std::move(this->freqStartShift);
dst.payloadLength = std::move(this->payloadLength);
dst.directSequenceSpread = std::move(this->directSequenceSpread);
}
Expand Down Expand Up @@ -266,6 +267,7 @@ struct Input {

// reinit
float sampleRateOffset = 0;
int freqStartShift = 0;
int payloadLength = -1;

// spectrum
Expand Down Expand Up @@ -636,10 +638,19 @@ void updateCore() {
if (inputCurrent.flags.needReinit) {
static auto sampleRateInpOld = ggWave->sampleRateInp();
static auto sampleRateOutOld = ggWave->sampleRateOut();
static auto freqStartShiftOld = 0;

auto sampleFormatInpOld = ggWave->sampleFormatInp();
auto sampleFormatOutOld = ggWave->sampleFormatOut();
auto rxProtocolsOld = ggWave->rxProtocols();

for (int i = 0; i < GGWAVE_PROTOCOL_COUNT; ++i) {
GGWave::Protocols::tx()[i].freqStart = std::max(1, GGWave::Protocols::tx()[i].freqStart + inputCurrent.freqStartShift - freqStartShiftOld);
rxProtocolsOld[i].freqStart = std::max(1, rxProtocolsOld[i].freqStart + inputCurrent.freqStartShift - freqStartShiftOld);
}

freqStartShiftOld = inputCurrent.freqStartShift;

GGWave::OperatingMode mode = GGWAVE_OPERATING_MODE_RX_AND_TX;
if (inputCurrent.directSequenceSpread) mode |= GGWAVE_OPERATING_MODE_USE_DSS;

Expand Down Expand Up @@ -853,6 +864,8 @@ void renderMain() {
int protocolId = GGWAVE_PROTOCOL_AUDIBLE_FAST;
bool isSampleRateOffset = false;
float sampleRateOffset = -512.0f;
bool isFreqStartShift = false;
int freqStartShift = 48;
bool isFixedLength = false;
bool directSequenceSpread = false;
int payloadLength = 16;
Expand Down Expand Up @@ -1055,7 +1068,7 @@ void renderMain() {

if (windowId == WindowId::Settings) {
ImGui::BeginChild("Settings:main", ImGui::GetContentRegionAvail(), true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
ImGui::Text("Waver v1.5.1");
ImGui::Text("Waver v1.5.2");
ImGui::Separator();

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

// fixed-length
Expand All @@ -1204,65 +1220,107 @@ void renderMain() {
if (settings.isFixedLength) {
ImGui::SameLine();
ImGui::PushItemWidth(0.5*ImGui::GetContentRegionAvailWidth());
if (ImGui::SliderInt("Bytes", &settings.payloadLength, 1, GGWave::kMaxLengthFixed)) {
if (ImGui::DragInt("Bytes", &settings.payloadLength, 1, 1, GGWave::kMaxLengthFixed)) {
g_buffer.inputUI.update = true;
g_buffer.inputUI.flags.needReinit = true;
g_buffer.inputUI.payloadLength = settings.isFixedLength ? settings.payloadLength : -1;
}
ImGui::PopItemWidth();
}

// Output sample-rate offset
ImGui::Text("%s", "");
// Direct-sequence spread
//ImGui::Text("%s", "");
{
auto posSave = ImGui::GetCursorScreenPos();
ImGui::Text("%s", "");
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
ImGui::PushTextWrapPos();
ImGui::TextDisabled("Modify the output Sampling Rate");
ImGui::TextDisabled("Direct-sequence spread");
ImGui::PopTextWrapPos();
}
{
auto posSave = ImGui::GetCursorScreenPos();
ImGui::Text("Pitch shift: ");
ImGui::Text("Use DSS: ");
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
}
if (ImGui::Checkbox("##output-sample-rate-offset", &settings.isSampleRateOffset)) {
if (ImGui::Checkbox("##direct-sequence-spread", &settings.directSequenceSpread)) {
g_buffer.inputUI.update = true;
g_buffer.inputUI.flags.needReinit = true;
g_buffer.inputUI.sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0;
g_buffer.inputUI.directSequenceSpread = settings.directSequenceSpread;
}

if (settings.isSampleRateOffset) {
// FreqStart offset
//ImGui::Text("%s", "");
{
auto posSave = ImGui::GetCursorScreenPos();
ImGui::Text("%s", "");
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
ImGui::PushTextWrapPos();
ImGui::TextDisabled("Apply tx/rx frequency shift");
ImGui::PopTextWrapPos();
}
{
auto posSave = ImGui::GetCursorScreenPos();
ImGui::Text("Freq shift: ");
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
}
if (ImGui::Checkbox("##freq-start-offset", &settings.isFreqStartShift)) {
g_buffer.inputUI.update = true;
g_buffer.inputUI.flags.needReinit = true;
g_buffer.inputUI.freqStartShift = settings.isFreqStartShift ? settings.freqStartShift : 0;
}

if (settings.isFreqStartShift) {
ImGui::SameLine();
ImGui::PushItemWidth(0.5*ImGui::GetContentRegionAvailWidth());
if (ImGui::SliderFloat("Samples", &settings.sampleRateOffset, -1000, 1000, "%.0f")) {
if (ImGui::DragInt("bins", &settings.freqStartShift, 1, -64, 64, "%d")) {
g_buffer.inputUI.update = true;
g_buffer.inputUI.flags.needReinit = true;
g_buffer.inputUI.sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0;
g_buffer.inputUI.freqStartShift = settings.isFreqStartShift ? settings.freqStartShift : 0;
}
ImGui::PopItemWidth();

{
auto posSave = ImGui::GetCursorScreenPos();
ImGui::Text("");
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
}
{
const float df = statsCurrent.sampleRate/statsCurrent.samplesPerFrame;
ImGui::Text("%6.2f Hz", df*settings.freqStartShift);
}
}

// Direct-sequence spread
ImGui::Text("%s", "");
// Output sample-rate offset
//ImGui::Text("%s", "");
{
auto posSave = ImGui::GetCursorScreenPos();
ImGui::Text("%s", "");
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
ImGui::PushTextWrapPos();
ImGui::TextDisabled("Direct-sequence spread");
ImGui::TextDisabled("Modify the output Sampling Rate");
ImGui::PopTextWrapPos();
}
{
auto posSave = ImGui::GetCursorScreenPos();
ImGui::Text("Use DSS: ");
ImGui::Text("Pitch shift: ");
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
}
if (ImGui::Checkbox("##direct-sequence-spread", &settings.directSequenceSpread)) {
if (ImGui::Checkbox("##output-sample-rate-offset", &settings.isSampleRateOffset)) {
g_buffer.inputUI.update = true;
g_buffer.inputUI.flags.needReinit = true;
g_buffer.inputUI.directSequenceSpread = settings.directSequenceSpread;
g_buffer.inputUI.sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0;
}

if (settings.isSampleRateOffset) {
ImGui::SameLine();
ImGui::PushItemWidth(0.5*ImGui::GetContentRegionAvailWidth());
if (ImGui::SliderFloat("Samples", &settings.sampleRateOffset, -1000, 1000, "%.0f")) {
g_buffer.inputUI.update = true;
g_buffer.inputUI.flags.needReinit = true;
g_buffer.inputUI.sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0;
}
ImGui::PopItemWidth();
}

// rx protocols
Expand Down
2 changes: 1 addition & 1 deletion snap/snapcraft.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

name: waver
version: '1.5.1'
version: '1.5.2'
summary: Data over sound
description: |
Waver allows you to send and receive text messages from nearby devices through sound waves.
Expand Down

0 comments on commit 3591285

Please sign in to comment.