mirror of
https://github.com/ggerganov/ggwave.git
synced 2026-02-06 16:47:59 +08:00
remove-stl : start removing stl completely
This commit is contained in:
@@ -12,6 +12,7 @@ static const char channels = 1;
|
||||
|
||||
// default PCM output frequency
|
||||
static const int frequency = 6000;
|
||||
static const int samplesPerFrame = 128;
|
||||
|
||||
static const int qpow = 9;
|
||||
static const int qmax = 1 << qpow;
|
||||
@@ -23,6 +24,10 @@ volatile int qsize = 0;
|
||||
// Buffer to read samples into, each sample is 16-bits
|
||||
TSample sampleBuffer[qmax];
|
||||
|
||||
volatile int err = 0;
|
||||
|
||||
GGWave * g_ggwave = nullptr;
|
||||
|
||||
// helper function to output the generated GGWave waveform via a buzzer
|
||||
void send_text(GGWave & ggwave, uint8_t pin, const char * text, GGWave::TxProtocolId protocolId) {
|
||||
ggwave.init(text, protocolId);
|
||||
@@ -73,15 +78,11 @@ void setup() {
|
||||
// - a 16 kHz sample rate for the Arduino Nano 33 BLE Sense
|
||||
// - a 32 kHz or 64 kHz sample rate for the Arduino Portenta Vision Shields
|
||||
if (!PDM.begin(channels, frequency)) {
|
||||
Serial.println("Failed to start PDM!");
|
||||
Serial.println(F("Failed to start PDM!"));
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
|
||||
volatile int err = 0;
|
||||
|
||||
void loop() {
|
||||
Serial.println("trying to create ggwave instance");
|
||||
Serial.println(F("Trying to create ggwave instance"));
|
||||
|
||||
auto p = GGWave::getDefaultParameters();
|
||||
|
||||
@@ -89,7 +90,7 @@ void loop() {
|
||||
p.sampleRateInp = frequency;
|
||||
p.sampleRateOut = frequency;
|
||||
p.sampleRate = frequency;
|
||||
p.samplesPerFrame = 128;
|
||||
p.samplesPerFrame = samplesPerFrame;
|
||||
p.sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I16;
|
||||
p.sampleFormatOut = GGWAVE_SAMPLE_FORMAT_I16;
|
||||
p.operatingMode = (ggwave_OperatingMode) (GGWAVE_OPERATING_MODE_RX | GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_USE_DSS | GGWAVE_OPERATING_MODE_TX_ONLY_TONES);
|
||||
@@ -97,22 +98,28 @@ void loop() {
|
||||
GGWave::Protocols::tx().only({GGWAVE_PROTOCOL_MT_FASTEST, GGWAVE_PROTOCOL_DT_FASTEST});
|
||||
GGWave::Protocols::rx().only({GGWAVE_PROTOCOL_MT_FASTEST, GGWAVE_PROTOCOL_DT_FASTEST});
|
||||
|
||||
GGWave ggwave(p);
|
||||
static GGWave ggwave(p);
|
||||
ggwave.setLogFile(nullptr);
|
||||
|
||||
Serial.println("Instance initialized");
|
||||
g_ggwave = &ggwave;
|
||||
|
||||
Serial.println(F("Instance initialized"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
auto & ggwave = *g_ggwave;
|
||||
|
||||
int nr = 0;
|
||||
int niter = 0;
|
||||
|
||||
GGWave::TxRxData result;
|
||||
while (true) {
|
||||
while (qsize >= p.samplesPerFrame) {
|
||||
while (qsize >= samplesPerFrame) {
|
||||
auto tStart = millis();
|
||||
|
||||
ggwave.decode(sampleBuffer + qhead, p.samplesPerFrame*kSampleSize_bytes);
|
||||
qsize -= p.samplesPerFrame;
|
||||
qhead += p.samplesPerFrame;
|
||||
ggwave.decode(sampleBuffer + qhead, samplesPerFrame*kSampleSize_bytes);
|
||||
qsize -= samplesPerFrame;
|
||||
qhead += samplesPerFrame;
|
||||
if (qhead >= qmax) {
|
||||
qhead = 0;
|
||||
}
|
||||
@@ -120,10 +127,10 @@ void loop() {
|
||||
auto tEnd = millis();
|
||||
if (++niter % 10 == 0) {
|
||||
// print the time it took the last decode() call to complete
|
||||
// should be smaller than p.samplesPerFrame/frequency seconds
|
||||
// for example: p.samplesPerFrame = 128, frequency = 6000 => not more than 20 ms
|
||||
// should be smaller than samplesPerFrame/frequency seconds
|
||||
// for example: samplesPerFrame = 128, frequency = 6000 => not more than 20 ms
|
||||
Serial.println(tEnd - tStart);
|
||||
if (tEnd - tStart > 1000*(float(p.samplesPerFrame)/frequency)) {
|
||||
if (tEnd - tStart > 1000*(float(samplesPerFrame)/frequency)) {
|
||||
Serial.println("Warning: decode() took too long to execute!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,19 @@ const int kPinSpeaker = 10;
|
||||
const int kPinButton0 = 2;
|
||||
const int kPinButton1 = 4;
|
||||
|
||||
const int samplesPerFrame = 128;
|
||||
const int sampleRate = 6000;
|
||||
|
||||
GGWave * g_ggwave = nullptr;
|
||||
|
||||
void send_text(GGWave & ggwave, uint8_t pin, const char * text, GGWave::TxProtocolId protocolId) {
|
||||
ggwave.init(text, protocolId);
|
||||
ggwave.encode();
|
||||
|
||||
const auto & tones = ggwave.txTones();
|
||||
//Serial.println(tones.size());
|
||||
float freq_hz = -1.0f;
|
||||
//float frameDuration_ms = (1000.0*samplesPerFrame)/sampleRate;
|
||||
float duration_ms = -1.0f;
|
||||
for (int i = 0; i < (int) tones.size(); ++i) {
|
||||
if (tones[i].size() == 0) continue;
|
||||
@@ -28,6 +35,7 @@ void send_text(GGWave & ggwave, uint8_t pin, const char * text, GGWave::TxProtoc
|
||||
duration_ms = 0.0f;
|
||||
}
|
||||
duration_ms += curTone.duration_ms;
|
||||
//duration_ms += frameDuration_ms;
|
||||
}
|
||||
|
||||
if (duration_ms > 0) {
|
||||
@@ -41,6 +49,33 @@ void send_text(GGWave & ggwave, uint8_t pin, const char * text, GGWave::TxProtoc
|
||||
|
||||
void setup() {
|
||||
Serial.begin(57600);
|
||||
|
||||
pinMode(kPinLed0, OUTPUT);
|
||||
pinMode(kPinSpeaker, OUTPUT);
|
||||
pinMode(kPinButton0, INPUT);
|
||||
pinMode(kPinButton1, INPUT);
|
||||
|
||||
Serial.println(F("Trying to create ggwave instance"));
|
||||
|
||||
auto p = GGWave::getDefaultParameters();
|
||||
p.payloadLength = 16;
|
||||
p.sampleRateInp = sampleRate;
|
||||
p.sampleRateOut = sampleRate;
|
||||
p.sampleRate = sampleRate;
|
||||
p.samplesPerFrame = samplesPerFrame;
|
||||
p.sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I16;
|
||||
p.sampleFormatOut = GGWAVE_SAMPLE_FORMAT_U8;
|
||||
p.operatingMode = (ggwave_OperatingMode) (GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_TX_ONLY_TONES | GGWAVE_OPERATING_MODE_USE_DSS);
|
||||
|
||||
GGWave::Protocols::tx().only(GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
delay(1000);
|
||||
static GGWave ggwave(p);
|
||||
ggwave.setLogFile(nullptr);
|
||||
Serial.println(ggwave.heapSize());
|
||||
|
||||
g_ggwave = &ggwave;
|
||||
|
||||
Serial.println(F("Instance initialized"));
|
||||
}
|
||||
|
||||
char txt[16];
|
||||
@@ -48,86 +83,72 @@ int pressed = 0;
|
||||
bool isDown = false;
|
||||
|
||||
void loop() {
|
||||
Serial.println("hello");
|
||||
auto & ggwave = *g_ggwave;
|
||||
|
||||
auto p = GGWave::getDefaultParameters();
|
||||
p.payloadLength = 16;
|
||||
p.sampleRateInp = 6000;
|
||||
p.sampleRateOut = 6000;
|
||||
p.sampleRate = 6000;
|
||||
p.samplesPerFrame = 128;
|
||||
p.sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I16;
|
||||
p.sampleFormatOut = GGWAVE_SAMPLE_FORMAT_U8;
|
||||
p.operatingMode = (ggwave_OperatingMode) (GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_TX_ONLY_TONES | GGWAVE_OPERATING_MODE_USE_DSS);
|
||||
//Serial.println(F("hello"));
|
||||
|
||||
GGWave::Protocols::tx().only(GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
GGWave ggwave(p);
|
||||
|
||||
pinMode(kPinLed0, OUTPUT);
|
||||
pinMode(kPinSpeaker, OUTPUT);
|
||||
pinMode(kPinButton0, INPUT);
|
||||
pinMode(kPinButton1, INPUT);
|
||||
|
||||
delay(3000);
|
||||
delay(1000);
|
||||
|
||||
////Serial.println(F("sending .."));
|
||||
digitalWrite(kPinLed0, HIGH);
|
||||
send_text(ggwave, kPinSpeaker, "Hello!", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
digitalWrite(kPinLed0, LOW);
|
||||
////Serial.println(F("done .."));
|
||||
|
||||
delay(2000);
|
||||
//delay(2000);
|
||||
|
||||
digitalWrite(kPinLed0, HIGH);
|
||||
send_text(ggwave, kPinSpeaker, "This is a", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
send_text(ggwave, kPinSpeaker, "ggwave demo", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
digitalWrite(kPinLed0, LOW);
|
||||
//digitalWrite(kPinLed0, HIGH);
|
||||
//send_text(ggwave, kPinSpeaker, "This is a", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
//send_text(ggwave, kPinSpeaker, "ggwave demo", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
//digitalWrite(kPinLed0, LOW);
|
||||
|
||||
delay(2000);
|
||||
//delay(2000);
|
||||
|
||||
digitalWrite(kPinLed0, HIGH);
|
||||
send_text(ggwave, kPinSpeaker, "The arduino", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
delay(200);
|
||||
send_text(ggwave, kPinSpeaker, "transmits data", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
delay(200);
|
||||
send_text(ggwave, kPinSpeaker, "using sound", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
delay(200);
|
||||
send_text(ggwave, kPinSpeaker, "through a buzzer", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
digitalWrite(kPinLed0, LOW);
|
||||
//digitalWrite(kPinLed0, HIGH);
|
||||
//send_text(ggwave, kPinSpeaker, "The arduino", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
//delay(200);
|
||||
//send_text(ggwave, kPinSpeaker, "transmits data", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
//delay(200);
|
||||
//send_text(ggwave, kPinSpeaker, "using sound", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
//delay(200);
|
||||
//send_text(ggwave, kPinSpeaker, "through a buzzer", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
//digitalWrite(kPinLed0, LOW);
|
||||
|
||||
delay(1000);
|
||||
//delay(1000);
|
||||
|
||||
digitalWrite(kPinLed0, HIGH);
|
||||
send_text(ggwave, kPinSpeaker, "The sound is", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
delay(200);
|
||||
send_text(ggwave, kPinSpeaker, "decoded in a", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
delay(200);
|
||||
send_text(ggwave, kPinSpeaker, "web page.", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
digitalWrite(kPinLed0, LOW);
|
||||
//digitalWrite(kPinLed0, HIGH);
|
||||
//send_text(ggwave, kPinSpeaker, "The sound is", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
//delay(200);
|
||||
//send_text(ggwave, kPinSpeaker, "decoded in a", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
//delay(200);
|
||||
//send_text(ggwave, kPinSpeaker, "web page.", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
//digitalWrite(kPinLed0, LOW);
|
||||
|
||||
delay(1000);
|
||||
//delay(1000);
|
||||
|
||||
digitalWrite(kPinLed0, HIGH);
|
||||
send_text(ggwave, kPinSpeaker, "Press the button!", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
digitalWrite(kPinLed0, LOW);
|
||||
//digitalWrite(kPinLed0, HIGH);
|
||||
//send_text(ggwave, kPinSpeaker, "Press the button!", GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
//digitalWrite(kPinLed0, LOW);
|
||||
|
||||
while (true) {
|
||||
int but0 = digitalRead(kPinButton0);
|
||||
int but1 = digitalRead(kPinButton1);
|
||||
//while (true) {
|
||||
// int but0 = digitalRead(kPinButton0);
|
||||
// int but1 = digitalRead(kPinButton1);
|
||||
|
||||
if (but1 == LOW && isDown == false) {
|
||||
delay(200);
|
||||
++pressed;
|
||||
isDown = true;
|
||||
} else if (but1 == HIGH) {
|
||||
isDown = false;
|
||||
}
|
||||
// if (but1 == LOW && isDown == false) {
|
||||
// delay(200);
|
||||
// ++pressed;
|
||||
// isDown = true;
|
||||
// } else if (but1 == HIGH) {
|
||||
// isDown = false;
|
||||
// }
|
||||
|
||||
if (but0 == LOW) {
|
||||
snprintf(txt, 16, "Pressed: %d", pressed);
|
||||
// if (but0 == LOW) {
|
||||
// snprintf(txt, 16, "Pressed: %d", pressed);
|
||||
|
||||
digitalWrite(kPinLed0, HIGH);
|
||||
send_text(ggwave, kPinSpeaker, txt, GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
digitalWrite(kPinLed0, LOW);
|
||||
pressed = 0;
|
||||
}
|
||||
}
|
||||
// digitalWrite(kPinLed0, HIGH);
|
||||
// send_text(ggwave, kPinSpeaker, txt, GGWAVE_PROTOCOL_MT_FASTEST);
|
||||
// digitalWrite(kPinLed0, LOW);
|
||||
// pressed = 0;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -1122,9 +1122,9 @@ void renderMain() {
|
||||
ImGui::Text("Tx Protocol: ");
|
||||
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
|
||||
}
|
||||
if (ImGui::BeginCombo("##txProtocol", settings.txProtocols.at(GGWave::TxProtocolId(settings.protocolId)).name)) {
|
||||
if (ImGui::BeginCombo("##txProtocol", settings.txProtocols[settings.protocolId].name)) {
|
||||
for (int i = 0; i < (int) settings.txProtocols.size(); ++i) {
|
||||
const auto & txProtocol = settings.txProtocols.at(GGWave::TxProtocolId(i));
|
||||
const auto & txProtocol = settings.txProtocols[i];
|
||||
if (txProtocol.name == nullptr) continue;
|
||||
const bool isSelected = (settings.protocolId == i);
|
||||
if (ImGui::Selectable(txProtocol.name, isSelected)) {
|
||||
@@ -1144,7 +1144,7 @@ void renderMain() {
|
||||
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
|
||||
}
|
||||
{
|
||||
const auto & protocol = settings.txProtocols.at(GGWave::TxProtocolId(settings.protocolId));
|
||||
const auto & protocol = settings.txProtocols[settings.protocolId];
|
||||
ImGui::Text("%4.2f B/s", (float(0.715f*protocol.bytesPerTx)/(protocol.framesPerTx*statsCurrent.samplesPerFrame))*statsCurrent.sampleRate);
|
||||
}
|
||||
|
||||
@@ -1155,7 +1155,7 @@ void renderMain() {
|
||||
}
|
||||
{
|
||||
const float df = statsCurrent.sampleRate/statsCurrent.samplesPerFrame;
|
||||
const auto & protocol = settings.txProtocols.at(GGWave::TxProtocolId(settings.protocolId));
|
||||
const auto & protocol = settings.txProtocols[settings.protocolId];
|
||||
ImGui::Text("%6.2f Hz - %6.2f Hz", df*protocol.freqStart, df*(protocol.freqStart + 2*16*protocol.bytesPerTx));
|
||||
}
|
||||
|
||||
@@ -1262,7 +1262,8 @@ void renderMain() {
|
||||
}
|
||||
{
|
||||
ImGui::PushID("RxProtocols");
|
||||
for (auto & rxProtocol : settings.rxProtocols) {
|
||||
for (int i = 0; i < settings.rxProtocols.size(); ++i) {
|
||||
auto & rxProtocol = settings.rxProtocols[i];
|
||||
if (rxProtocol.name == nullptr) continue;
|
||||
auto posSave = ImGui::GetCursorScreenPos();
|
||||
ImGui::Text("%s", "");
|
||||
@@ -1349,7 +1350,7 @@ void renderMain() {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled("|");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored({ 0.0f, 0.6f, 0.4f, interp }, "%s", settings.txProtocols.at(GGWave::TxProtocolId(message.protocolId)).name);
|
||||
ImGui::TextColored({ 0.0f, 0.6f, 0.4f, interp }, "%s", settings.txProtocols[message.protocolId].name);
|
||||
ImGui::SameLine();
|
||||
if (message.dss) {
|
||||
ImGui::TextColored({ 0.4f, 0.6f, 0.4f, interp }, "DSS");
|
||||
@@ -1597,7 +1598,7 @@ void renderMain() {
|
||||
pos0.x += style.ItemInnerSpacing.x;
|
||||
pos0.y += 0.5*style.ItemInnerSpacing.y;
|
||||
static char tmp[128];
|
||||
snprintf(tmp, 128, "Send message using '%s'", settings.txProtocols.at(GGWave::TxProtocolId(settings.protocolId)).name);
|
||||
snprintf(tmp, 128, "Send message using '%s'", settings.txProtocols[settings.protocolId].name);
|
||||
drawList->AddText(pos0, ImGui::ColorConvertFloat4ToU32({0.0f, 0.6f, 0.4f, 1.0f}), tmp);
|
||||
}
|
||||
}
|
||||
@@ -2114,7 +2115,7 @@ void renderMain() {
|
||||
break;
|
||||
}
|
||||
|
||||
const auto & protocol = settings.txProtocols.at(GGWave::TxProtocolId(msg.protocolId));
|
||||
const auto & protocol = settings.txProtocols[msg.protocolId];
|
||||
const int msgLength_bytes = settings.isFixedLength ? 1.4f*settings.payloadLength : 1.4f*msg.data.size() + GGWave::kDefaultEncodedDataOffset;
|
||||
const int msgLength_frames = settings.isFixedLength ?
|
||||
((msgLength_bytes + protocol.bytesPerTx - 1)/protocol.bytesPerTx)*protocol.framesPerTx :
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
# define GGWAVE_API
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO)
|
||||
#define GGWAVE_CONFIG_FEW_PROTOCOLS
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -35,12 +39,14 @@ extern "C" {
|
||||
|
||||
// Protocol ids
|
||||
typedef enum {
|
||||
#ifndef GGWAVE_CONFIG_FEW_PROTOCOLS
|
||||
GGWAVE_PROTOCOL_AUDIBLE_NORMAL,
|
||||
GGWAVE_PROTOCOL_AUDIBLE_FAST,
|
||||
GGWAVE_PROTOCOL_AUDIBLE_FASTEST,
|
||||
GGWAVE_PROTOCOL_ULTRASOUND_NORMAL,
|
||||
GGWAVE_PROTOCOL_ULTRASOUND_FAST,
|
||||
GGWAVE_PROTOCOL_ULTRASOUND_FASTEST,
|
||||
#endif
|
||||
GGWAVE_PROTOCOL_DT_NORMAL,
|
||||
GGWAVE_PROTOCOL_DT_FAST,
|
||||
GGWAVE_PROTOCOL_DT_FASTEST,
|
||||
@@ -48,6 +54,7 @@ extern "C" {
|
||||
GGWAVE_PROTOCOL_MT_FAST,
|
||||
GGWAVE_PROTOCOL_MT_FASTEST,
|
||||
|
||||
#ifndef GGWAVE_CONFIG_FEW_PROTOCOLS
|
||||
GGWAVE_PROTOCOL_CUSTOM_0,
|
||||
GGWAVE_PROTOCOL_CUSTOM_1,
|
||||
GGWAVE_PROTOCOL_CUSTOM_2,
|
||||
@@ -59,6 +66,7 @@ extern "C" {
|
||||
GGWAVE_PROTOCOL_CUSTOM_8,
|
||||
GGWAVE_PROTOCOL_CUSTOM_9,
|
||||
|
||||
#endif
|
||||
GGWAVE_PROTOCOL_COUNT,
|
||||
} ggwave_ProtocolId;
|
||||
|
||||
@@ -320,8 +328,44 @@ extern "C" {
|
||||
// C++ interface
|
||||
//
|
||||
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
template <typename T>
|
||||
struct ggvector {
|
||||
private:
|
||||
T * m_data;
|
||||
int m_size;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
ggvector(T * data, int size) : m_data(data), m_size(size) {}
|
||||
|
||||
T & operator[](int i) {
|
||||
return m_data[i];
|
||||
}
|
||||
|
||||
const T & operator[](int i) const {
|
||||
return m_data[i];
|
||||
}
|
||||
|
||||
int size() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
T * data() const {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
T * begin() const {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
T * end() const {
|
||||
return m_data + m_size;
|
||||
}
|
||||
};
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
class GGWave {
|
||||
@@ -351,10 +395,10 @@ public:
|
||||
struct Protocol {
|
||||
const char * name; // string identifier of the protocol
|
||||
|
||||
int freqStart; // FFT bin index of the lowest frequency
|
||||
int framesPerTx; // number of frames to transmit a single chunk of data
|
||||
int bytesPerTx; // number of bytes in a chunk of data
|
||||
int extra; // 2 if this is a mono-tone protocol, 1 otherwise
|
||||
int16_t freqStart; // FFT bin index of the lowest frequency
|
||||
int8_t framesPerTx; // number of frames to transmit a single chunk of data
|
||||
int8_t bytesPerTx; // number of bytes in a chunk of data
|
||||
int8_t extra; // 2 if this is a mono-tone protocol, 1 otherwise
|
||||
|
||||
bool enabled;
|
||||
|
||||
@@ -369,8 +413,40 @@ public:
|
||||
using TxProtocols = Protocols;
|
||||
using RxProtocols = Protocols;
|
||||
|
||||
struct Protocols : public std::vector<Protocol> {
|
||||
using std::vector<Protocol>::vector;
|
||||
struct Protocols {
|
||||
Protocol data[GGWAVE_PROTOCOL_COUNT];
|
||||
|
||||
int size() const {
|
||||
return GGWAVE_PROTOCOL_COUNT;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
Protocol & operator[](ProtocolId id) {
|
||||
return data[id];
|
||||
}
|
||||
|
||||
Protocol & operator[](int id) {
|
||||
return data[id];
|
||||
}
|
||||
|
||||
const Protocol & operator[](ProtocolId id) const {
|
||||
return data[id];
|
||||
}
|
||||
|
||||
const Protocol & operator[](int id) const {
|
||||
return data[id];
|
||||
}
|
||||
|
||||
Protocols & operator=(const std::initializer_list<Protocol> & list) {
|
||||
int i = 0;
|
||||
for (auto & p : list) {
|
||||
data[i++] = p;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void enableAll();
|
||||
void disableAll();
|
||||
@@ -380,38 +456,41 @@ public:
|
||||
void only(std::initializer_list<ProtocolId> ids);
|
||||
|
||||
static Protocols & kDefault() {
|
||||
static Protocols kProtocols(GGWAVE_PROTOCOL_COUNT);
|
||||
static Protocols protocols;
|
||||
|
||||
static bool kInitialized = false;
|
||||
if (kInitialized == false) {
|
||||
for (auto & protocol : kProtocols) {
|
||||
protocol.name = nullptr;
|
||||
protocol.enabled = false;
|
||||
static bool initialized = false;
|
||||
if (initialized == false) {
|
||||
for (int i = 0; i < GGWAVE_PROTOCOL_COUNT; ++i) {
|
||||
protocols.data[i].name = nullptr;
|
||||
protocols.data[i].enabled = false;
|
||||
}
|
||||
|
||||
kProtocols[GGWAVE_PROTOCOL_AUDIBLE_NORMAL] = { "Normal", 40, 9, 3, 1, true, };
|
||||
kProtocols[GGWAVE_PROTOCOL_AUDIBLE_FAST] = { "Fast", 40, 6, 3, 1, true, };
|
||||
kProtocols[GGWAVE_PROTOCOL_AUDIBLE_FASTEST] = { "Fastest", 40, 3, 3, 1, true, };
|
||||
kProtocols[GGWAVE_PROTOCOL_ULTRASOUND_NORMAL] = { "[U] Normal", 320, 9, 3, 1, true, };
|
||||
kProtocols[GGWAVE_PROTOCOL_ULTRASOUND_FAST] = { "[U] Fast", 320, 6, 3, 1, true, };
|
||||
kProtocols[GGWAVE_PROTOCOL_ULTRASOUND_FASTEST] = { "[U] Fastest", 320, 3, 3, 1, true, };
|
||||
kProtocols[GGWAVE_PROTOCOL_DT_NORMAL] = { "[DT] Normal", 24, 9, 1, 1, true, };
|
||||
kProtocols[GGWAVE_PROTOCOL_DT_FAST] = { "[DT] Fast", 24, 6, 1, 1, true, };
|
||||
kProtocols[GGWAVE_PROTOCOL_DT_FASTEST] = { "[DT] Fastest", 24, 3, 1, 1, true, };
|
||||
kProtocols[GGWAVE_PROTOCOL_MT_NORMAL] = { "[MT] Normal", 24, 9, 1, 2, true, };
|
||||
kProtocols[GGWAVE_PROTOCOL_MT_FAST] = { "[MT] Fast", 24, 6, 1, 2, true, };
|
||||
kProtocols[GGWAVE_PROTOCOL_MT_FASTEST] = { "[MT] Fastest", 24, 3, 1, 2, true, };
|
||||
#ifndef GGWAVE_CONFIG_FEW_PROTOCOLS
|
||||
protocols.data[GGWAVE_PROTOCOL_AUDIBLE_NORMAL] = { "Normal", 40, 9, 3, 1, true, };
|
||||
protocols.data[GGWAVE_PROTOCOL_AUDIBLE_FAST] = { "Fast", 40, 6, 3, 1, true, };
|
||||
protocols.data[GGWAVE_PROTOCOL_AUDIBLE_FASTEST] = { "Fastest", 40, 3, 3, 1, true, };
|
||||
protocols.data[GGWAVE_PROTOCOL_ULTRASOUND_NORMAL] = { "[U] Normal", 320, 9, 3, 1, true, };
|
||||
protocols.data[GGWAVE_PROTOCOL_ULTRASOUND_FAST] = { "[U] Fast", 320, 6, 3, 1, true, };
|
||||
protocols.data[GGWAVE_PROTOCOL_ULTRASOUND_FASTEST] = { "[U] Fastest", 320, 3, 3, 1, true, };
|
||||
#endif
|
||||
protocols.data[GGWAVE_PROTOCOL_DT_NORMAL] = { "[DT] Normal", 24, 9, 1, 1, true, };
|
||||
protocols.data[GGWAVE_PROTOCOL_DT_FAST] = { "[DT] Fast", 24, 6, 1, 1, true, };
|
||||
protocols.data[GGWAVE_PROTOCOL_DT_FASTEST] = { "[DT] Fastest", 24, 3, 1, 1, true, };
|
||||
protocols.data[GGWAVE_PROTOCOL_MT_NORMAL] = { "[MT] Normal", 24, 9, 1, 2, true, };
|
||||
protocols.data[GGWAVE_PROTOCOL_MT_FAST] = { "[MT] Fast", 24, 6, 1, 2, true, };
|
||||
protocols.data[GGWAVE_PROTOCOL_MT_FASTEST] = { "[MT] Fastest", 24, 3, 1, 2, true, };
|
||||
|
||||
kInitialized = true;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return kProtocols;
|
||||
return protocols;
|
||||
}
|
||||
|
||||
static TxProtocols & tx();
|
||||
static RxProtocols & rx();
|
||||
};
|
||||
|
||||
// TODO: need more efficient way to store this
|
||||
struct ToneData {
|
||||
float freq_hz;
|
||||
float duration_ms;
|
||||
@@ -533,6 +612,8 @@ public:
|
||||
SampleFormat sampleFormatInp() const;
|
||||
SampleFormat sampleFormatOut() const;
|
||||
|
||||
int heapSize() const;
|
||||
|
||||
//
|
||||
// Tx
|
||||
//
|
||||
@@ -699,14 +780,86 @@ private:
|
||||
TxRxData m_dataEncoded;
|
||||
TxRxData m_workRSLength; // Reed-Solomon work buffers
|
||||
TxRxData m_workRSData;
|
||||
TxRxData m_dssMagic;
|
||||
|
||||
// Impl
|
||||
struct Rx;
|
||||
Rx * m_rx;
|
||||
|
||||
struct Tx;
|
||||
Tx * m_tx;
|
||||
struct Rx {
|
||||
bool receiving = false;
|
||||
bool analyzing = false;
|
||||
|
||||
int nMarkersSuccess = 0;
|
||||
int markerFreqStart = 0;
|
||||
int recvDuration_frames = 0;
|
||||
|
||||
int framesLeftToAnalyze = 0;
|
||||
int framesLeftToRecord = 0;
|
||||
int framesToAnalyze = 0;
|
||||
int framesToRecord = 0;
|
||||
int samplesNeeded = 0;
|
||||
|
||||
std::vector<float> fftOut; // complex
|
||||
std::vector<int> fftWorkI;
|
||||
std::vector<float> fftWorkF;
|
||||
|
||||
bool hasNewRxData = false;
|
||||
bool hasNewSpectrum = false;
|
||||
bool hasNewAmplitude = false;
|
||||
|
||||
Spectrum spectrum;
|
||||
Amplitude amplitude;
|
||||
Amplitude amplitudeResampled;
|
||||
TxRxData amplitudeTmp;
|
||||
|
||||
int dataLength = 0;
|
||||
|
||||
TxRxData data;
|
||||
RxProtocol protocol;
|
||||
RxProtocolId protocolId;
|
||||
RxProtocols protocols;
|
||||
|
||||
// variable-length decoding
|
||||
int historyId = 0;
|
||||
|
||||
Amplitude amplitudeAverage;
|
||||
std::vector<Amplitude> amplitudeHistory;
|
||||
RecordedData amplitudeRecorded;
|
||||
|
||||
// fixed-length decoding
|
||||
int historyIdFixed = 0;
|
||||
|
||||
std::vector<std::vector<uint16_t>> spectrumHistoryFixed;
|
||||
std::vector<uint8_t> detectedBins;
|
||||
std::vector<uint8_t> detectedTones;
|
||||
} m_rx;
|
||||
|
||||
struct Tx {
|
||||
bool hasData = false;
|
||||
|
||||
float sendVolume = 0.1f;
|
||||
|
||||
int dataLength = 0;
|
||||
int lastAmplitudeSize = 0;
|
||||
|
||||
std::vector<bool> dataBits;
|
||||
std::vector<double> phaseOffsets;
|
||||
|
||||
std::vector<Amplitude> bit1Amplitude;
|
||||
std::vector<Amplitude> bit0Amplitude;
|
||||
|
||||
TxRxData data;
|
||||
TxProtocol protocol;
|
||||
TxProtocols protocols;
|
||||
|
||||
Amplitude output;
|
||||
Amplitude outputResampled;
|
||||
TxRxData outputTmp;
|
||||
AmplitudeI16 outputI16;
|
||||
|
||||
Tones tones;
|
||||
} m_tx;
|
||||
|
||||
void * m_heap;
|
||||
int m_heapSize;
|
||||
|
||||
Resampler * m_resampler;
|
||||
};
|
||||
|
||||
870
src/ggwave.cpp
870
src/ggwave.cpp
File diff suppressed because it is too large
Load Diff
@@ -12,12 +12,6 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if !defined(ARDUINO) && !defined(PROGMEM)
|
||||
#define PROGMEM
|
||||
#else
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
|
||||
namespace RS {
|
||||
|
||||
namespace gf {
|
||||
|
||||
Reference in New Issue
Block a user