diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 28edcc8..6c6e3b9 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -92,6 +92,7 @@ else() add_subdirectory(arduino-tx) add_subdirectory(arduino-tx-obsolete) add_subdirectory(esp32-rx) + add_subdirectory(rp2040-rx) endif() if (GGWAVE_SUPPORT_SDL2) diff --git a/examples/arduino-rx/arduino-rx.ino b/examples/arduino-rx/arduino-rx.ino index 8ac41de..f56516f 100644 --- a/examples/arduino-rx/arduino-rx.ino +++ b/examples/arduino-rx/arduino-rx.ino @@ -50,7 +50,7 @@ // Uncoment this line to enable long-range transmission // The used protocols are slower and use more memory to decode, but are much more robust -//#define EXAMPLE_LONG_RANGE 1 +//#define LONG_RANGE 1 #include @@ -129,7 +129,7 @@ void send_text(GGWave & ggwave, uint8_t pin, const char * text, GGWave::TxProtoc void setup() { Serial.begin(57600); - //while (!Serial); + while (!Serial); pinMode(kPinLED0, OUTPUT); pinMode(kPinSpeaker, OUTPUT); @@ -139,6 +139,8 @@ void setup() { #ifdef DISPLAY_OUTPUT { + Serial.println(F("Initializing display...")); + // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); @@ -175,12 +177,15 @@ void setup() { // Adjust the "ggwave" parameters to your needs. // Make sure that the "payloadLength" parameter matches the one used on the transmitting side. -#ifdef EXAMPLE_LONG_RANGE +#ifdef LONG_RANGE // The "FAST" protocols require 2x more memory, so we reduce the payload length to compensate: p.payloadLength = 8; #else p.payloadLength = 16; #endif + Serial.print(F("Using payload length: ")); + Serial.println(p.payloadLength); + p.sampleRateInp = sampleRate; p.sampleRateOut = sampleRate; p.sampleRate = sampleRate; @@ -204,12 +209,12 @@ void setup() { // Remove the ones that you don't need to reduce memory usage GGWave::Protocols::rx().disableAll(); //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_NORMAL, true); -#ifdef EXAMPLE_LONG_RANGE +#ifdef LONG_RANGE GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FAST, true); #endif GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FASTEST, true); //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_NORMAL, true); -#ifdef EXAMPLE_LONG_RANGE +#ifdef LONG_RANGE GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FAST, true); #endif GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FASTEST, true); @@ -249,7 +254,6 @@ void loop() { int but0Prev = HIGH; GGWave::TxRxData result; - GGWave::Spectrum rxSpectrum; char resultLast[17]; int tLastReceive = -10000; @@ -295,6 +299,7 @@ void loop() { #ifdef DISPLAY_OUTPUT const auto t = millis(); + static GGWave::Spectrum rxSpectrum; if (ggwave.rxTakeSpectrum(rxSpectrum) && t > 2000) { const bool isNew = t - tLastReceive < 2000; diff --git a/examples/esp32-rx/esp32-rx.ino b/examples/esp32-rx/esp32-rx.ino index e645e8a..99dd0f4 100644 --- a/examples/esp32-rx/esp32-rx.ino +++ b/examples/esp32-rx/esp32-rx.ino @@ -14,7 +14,7 @@ // Tested I2S microphones: // - Adafruit I2S SPH0645 // -// The ESP32 microcontroller has a built-int 12-bit ADC which is used to digitalize the analog signal +// The ESP32 microcontroller has a built-in 12-bit ADC which is used to digitalize the analog signal // from the external analog microphone. When I2S microphone is used, the ADC is not used. // // The sketch optionally supports displaying the received "ggwave" data on an OLED display. @@ -75,7 +75,7 @@ // Uncoment this line to enable long-range transmission // These protocols are slower and use more memory to decode, but are much more robust -//#define EXAMPLE_LONG_RANGE 1 +//#define LONG_RANGE 1 #include @@ -89,12 +89,13 @@ const int kPinLED0 = 2; GGWave ggwave; // Audio capture configuration -using TSample = int16_t; +using TSample = int16_t; #if defined(MIC_ANALOG) -using TSampleInput = int16_t; +using TSampleInput = int16_t; #elif defined(MIC_I2S) || defined(MIC_I2S_SPH0645) -using TSampleInput = int32_t; +using TSampleInput = int32_t; #endif + const size_t kSampleSize_bytes = sizeof(TSample); // High sample rate - better quality, but more CPU/Memory usage @@ -193,6 +194,8 @@ void setup() { #ifdef DISPLAY_OUTPUT { + Serial.println(F("Initializing display...")); + // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); @@ -229,12 +232,15 @@ void setup() { // Adjust the "ggwave" parameters to your needs. // Make sure that the "payloadLength" parameter matches the one used on the transmitting side. -#ifdef EXAMPLE_LONG_RANGE +#ifdef LONG_RANGE // The "FAST" protocols require 2x more memory, so we reduce the payload length to compensate: p.payloadLength = 8; #else p.payloadLength = 16; #endif + Serial.print(F("Using payload length: ")); + Serial.println(p.payloadLength); + p.sampleRateInp = sampleRate; p.sampleRateOut = sampleRate; p.sampleRate = sampleRate; @@ -254,12 +260,12 @@ void setup() { // Remove the ones that you don't need to reduce memory usage GGWave::Protocols::rx().disableAll(); //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_NORMAL, true); -#ifdef EXAMPLE_LONG_RANGE +#ifdef LONG_RANGE GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FAST, true); #endif GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FASTEST, true); //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_NORMAL, true); -#ifdef EXAMPLE_LONG_RANGE +#ifdef LONG_RANGE GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FAST, true); #endif GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FASTEST, true); @@ -315,7 +321,6 @@ int niter = 0; int tLastReceive = -10000; GGWave::TxRxData result; -GGWave::Spectrum rxSpectrum; void loop() { // Read from i2s @@ -391,6 +396,7 @@ void loop() { #ifdef DISPLAY_OUTPUT const auto t = millis(); + static GGWave::Spectrum rxSpectrum; if (ggwave.rxTakeSpectrum(rxSpectrum) && t > 2000) { const bool isNew = t - tLastReceive < 2000; diff --git a/examples/rp2040-rx/CMakeLists.txt b/examples/rp2040-rx/CMakeLists.txt new file mode 100644 index 0000000..60b5800 --- /dev/null +++ b/examples/rp2040-rx/CMakeLists.txt @@ -0,0 +1,2 @@ +# +# rp2040-rx diff --git a/examples/rp2040-rx/README.md b/examples/rp2040-rx/README.md index 8f0cde0..37aeccc 100644 --- a/examples/rp2040-rx/README.md +++ b/examples/rp2040-rx/README.md @@ -1,5 +1,28 @@ # rp2040-rx -WIP in progress +This is a sample project for receiving audio data using [RP2040](https://www.espressif.com/en/products/socs/esp32) microcontroller. +The chip has a built-in 12-bit ADC which is used to process the analog audio from the external microphone module in real-time. + +## Setup + +- Raspberry Pi Pico (or other RP2040 board) +- Microphone, tested with the following, but others could be also supported: + - Analog: + - MAX9814 + - KY-037 + - KY-038 + - WS Sound sensor + +## Pinout + +### Analog Microphone + +| MCU | Mic | +| ------- | --------- | +| GND | GND | +| 3.3V | VCC / VDD | +| GPIO 26 | Out | + +![Sketch-Breadboard](fritzing-sketch_bb.png) ![1658510571716150](https://user-images.githubusercontent.com/1991296/180506853-01954beb-ccd4-4b71-ac20-232899d99abf.jpg) diff --git a/examples/rp2040-rx/mic-analog.cpp b/examples/rp2040-rx/mic-analog.cpp new file mode 100644 index 0000000..9c5c331 --- /dev/null +++ b/examples/rp2040-rx/mic-analog.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2021 Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include "mic-analog.h" + +#include "hardware/adc.h" +#include "hardware/clocks.h" +#include "hardware/dma.h" +#include "hardware/irq.h" + +#include +#include + +#define ANALOG_RAW_BUFFER_COUNT 2 + +static struct { + int dma_channel; + uint16_t* raw_buffer[ANALOG_RAW_BUFFER_COUNT]; + uint32_t buffer_size; + int16_t bias; + uint32_t dma_irq; + + volatile int raw_buffer_write_index; + volatile int raw_buffer_read_index; + + analog_microphone_config config; + analog_samples_ready_handler_t samples_ready_handler; +} analog_mic; + +static void analog_dma_handler(); + +int analog_microphone_init(const struct analog_microphone_config* config) { + memset(&analog_mic, 0x00, sizeof(analog_mic)); + memcpy(&analog_mic.config, config, sizeof(analog_mic.config)); + + if (config->gpio < 26 || config->gpio > 29) { + return -1; + } + + size_t raw_buffer_size = config->sample_buffer_size * sizeof(analog_mic.raw_buffer[0][0]); + + analog_mic.buffer_size = config->sample_buffer_size; + analog_mic.bias = ((int16_t)((config->bias_voltage * 4095) / 3.3)); + + for (int i = 0; i < ANALOG_RAW_BUFFER_COUNT; i++) { + analog_mic.raw_buffer[i] = (uint16_t* )malloc(raw_buffer_size); + if (analog_mic.raw_buffer[i] == NULL) { + analog_microphone_deinit(); + + return -1; + } + } + + analog_mic.dma_channel = dma_claim_unused_channel(true); + if (analog_mic.dma_channel < 0) { + analog_microphone_deinit(); + + return -1; + } + + float clk_div = (clock_get_hz(clk_adc) / (1.0 * config->sample_rate)) - 1; + + dma_channel_config dma_channel_cfg = dma_channel_get_default_config(analog_mic.dma_channel); + + channel_config_set_transfer_data_size(&dma_channel_cfg, DMA_SIZE_16); + channel_config_set_read_increment(&dma_channel_cfg, false); + channel_config_set_write_increment(&dma_channel_cfg, true); + channel_config_set_dreq(&dma_channel_cfg, DREQ_ADC); + + analog_mic.dma_irq = DMA_IRQ_0; + + dma_channel_configure( + analog_mic.dma_channel, + &dma_channel_cfg, + analog_mic.raw_buffer[0], + &adc_hw->fifo, + analog_mic.buffer_size, + false + ); + + adc_gpio_init(config->gpio); + + adc_init(); + adc_select_input(config->gpio - 26); + adc_fifo_setup( + true, // Write each completed conversion to the sample FIFO + true, // Enable DMA data request (DREQ) + 1, // DREQ (and IRQ) asserted when at least 1 sample present + false, // We won't see the ERR bit because of 8 bit reads; disable. + false // Don't shift each sample to 8 bits when pushing to FIFO + ); + + adc_set_clkdiv(clk_div); + + return 0; +} + +void analog_microphone_deinit() { + for (int i = 0; i < ANALOG_RAW_BUFFER_COUNT; i++) { + if (analog_mic.raw_buffer[i]) { + free(analog_mic.raw_buffer[i]); + + analog_mic.raw_buffer[i] = NULL; + } + } + + if (analog_mic.dma_channel > -1) { + dma_channel_unclaim(analog_mic.dma_channel); + + analog_mic.dma_channel = -1; + } +} + +int analog_microphone_start() { + irq_set_enabled(analog_mic.dma_irq, true); + irq_set_exclusive_handler(analog_mic.dma_irq, analog_dma_handler); + + if (analog_mic.dma_irq == DMA_IRQ_0) { + dma_channel_set_irq0_enabled(analog_mic.dma_channel, true); + } else if (analog_mic.dma_irq == DMA_IRQ_1) { + dma_channel_set_irq1_enabled(analog_mic.dma_channel, true); + } else { + return -1; + } + + analog_mic.raw_buffer_write_index = 0; + analog_mic.raw_buffer_read_index = 0; + + dma_channel_transfer_to_buffer_now( + analog_mic.dma_channel, + analog_mic.raw_buffer[0], + analog_mic.buffer_size + ); + + adc_run(true); // start running the adc + // + return 0; +} + +void analog_microphone_stop() { + adc_run(false); // stop running the adc + + dma_channel_abort(analog_mic.dma_channel); + + if (analog_mic.dma_irq == DMA_IRQ_0) { + dma_channel_set_irq0_enabled(analog_mic.dma_channel, false); + } else if (analog_mic.dma_irq == DMA_IRQ_1) { + dma_channel_set_irq1_enabled(analog_mic.dma_channel, false); + } + + irq_set_enabled(analog_mic.dma_irq, false); +} + +static void analog_dma_handler() { + // clear IRQ + if (analog_mic.dma_irq == DMA_IRQ_0) { + dma_hw->ints0 = (1u << analog_mic.dma_channel); + } else if (analog_mic.dma_irq == DMA_IRQ_1) { + dma_hw->ints1 = (1u << analog_mic.dma_channel); + } + + // get the current buffer index + analog_mic.raw_buffer_read_index = analog_mic.raw_buffer_write_index; + + // get the next capture index to send the dma to start + analog_mic.raw_buffer_write_index = (analog_mic.raw_buffer_write_index + 1) % ANALOG_RAW_BUFFER_COUNT; + + // give the channel a new buffer to write to and re-trigger it + dma_channel_transfer_to_buffer_now( + analog_mic.dma_channel, + analog_mic.raw_buffer[analog_mic.raw_buffer_write_index], + analog_mic.buffer_size + ); + + if (analog_mic.samples_ready_handler) { + analog_mic.samples_ready_handler(); + } +} + +void analog_microphone_set_samples_ready_handler(analog_samples_ready_handler_t handler) { + analog_mic.samples_ready_handler = handler; +} + +int analog_microphone_read(int16_t* buffer, size_t samples) { + if (samples > analog_mic.config.sample_buffer_size) { + samples = analog_mic.config.sample_buffer_size; + } + + if (analog_mic.raw_buffer_write_index == analog_mic.raw_buffer_read_index) { + return 0; + } + + uint16_t* in = analog_mic.raw_buffer[analog_mic.raw_buffer_read_index]; + int16_t* out = buffer; + int16_t bias = analog_mic.bias; + + analog_mic.raw_buffer_read_index++; + + for (int i = 0; i < samples; i++) { + *out++ = *in++ - bias; + } + + return samples; +} diff --git a/examples/rp2040-rx/mic-analog.h b/examples/rp2040-rx/mic-analog.h new file mode 100644 index 0000000..93f3461 --- /dev/null +++ b/examples/rp2040-rx/mic-analog.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#ifndef _PICO_ANALOG_MICROPHONE_H_ +#define _PICO_ANALOG_MICROPHONE_H_ + +#include +#include + +typedef void (*analog_samples_ready_handler_t)(void); + +struct analog_microphone_config { + uint32_t gpio; + float bias_voltage; + uint32_t sample_rate; + uint32_t sample_buffer_size; +}; + +int analog_microphone_init(const struct analog_microphone_config* config); +void analog_microphone_deinit(); + +int analog_microphone_start(); +void analog_microphone_stop(); + +void analog_microphone_set_samples_ready_handler(analog_samples_ready_handler_t handler); + +int analog_microphone_read(int16_t* buffer, size_t samples); + +#endif diff --git a/examples/rp2040-rx/rp2040-rx.ino b/examples/rp2040-rx/rp2040-rx.ino new file mode 100644 index 0000000..d8aa1fe --- /dev/null +++ b/examples/rp2040-rx/rp2040-rx.ino @@ -0,0 +1,242 @@ +// rp2040-rx +// +// Sample sketch for receiving sound data using "ggwave" +// +// Tested MCU boards: +// - Raspberry Pi Pico +// - Arduino Nano RP2040 Connect +// +// Tested analog microphones: +// - MAX9814 +// - KY-037 +// - KY-038 +// - WS Sound sensor +// +// The RP2040 microcontroller has a built-in 12-bit ADC which is used to digitalize the analog signal +// from the external analog microphone. The MCU supports sampling rates up to 500kHz which makes it +// capable of even recording audio in the ultrasound range, given that your microphone's sensitivity +// supports it. +// +// If you want to perform a quick test, you can use the free "Waver" application: +// - Web: https://waver.ggerganov.com +// - Android: https://play.google.com/store/apps/details?id=com.ggerganov.Waver +// - iOS: https://apps.apple.com/us/app/waver-data-over-sound/id1543607865 +// +// Make sure to enable the "Fixed-length" option in "Waver"'s settings and set the number of +// bytes to be equal to "payloadLength" used in the sketch. Also, select a protocol that is +// listed as Rx in the current sketch. +// +// Sketch: https://github.com/ggerganov/ggwave/tree/master/examples/rp2040-rx +// +// ## Pinout +// +// ### Analog Microphone +// +// | MCU | Mic | +// | ------- | --------- | +// | GND | GND | +// | 3.3V | VCC / VDD | +// | GPIO 26 | Out | +// + +// Uncomment the line coresponding to your microhpone +#define MIC_ANALOG + +// Uncoment this line to enable long-range transmission +// The used protocols are slower and use more memory to decode, but are much more robust +//#define LONG_RANGE 1 + +#include + +// Audio capture configuration +using TSample = int16_t; + +const size_t kSampleSize_bytes = sizeof(TSample); + +// High sample rate - better quality, but more CPU/Memory usage +const int sampleRate = 48000; +const int samplesPerFrame = 1024; + +// Low sample rate +//const int sampleRate = 24000; +//const int samplesPerFrame = 512; + +TSample sampleBuffer[samplesPerFrame]; + +#if defined(MIC_ANALOG) + +#include "mic-analog.h" + +volatile int samplesRead = 0; + +const struct analog_microphone_config config = { + // GPIO to use for input, must be ADC compatible (GPIO 26 - 28) + .gpio = 26, + + // bias voltage of microphone in volts + .bias_voltage = 1.25, + + // sample rate in Hz + .sample_rate = sampleRate, + + // number of samples to buffer + .sample_buffer_size = samplesPerFrame, +}; + +void on_analog_samples_ready() +{ + // callback from library when all the samples in the library + // internal sample buffer are ready for reading + samplesRead = analog_microphone_read(sampleBuffer, samplesPerFrame); +} + +#endif + +// Global GGwave instance +GGWave ggwave; + +void setup() { + Serial.begin(115200); + while (!Serial); + + // Initialize "ggwave" + { + Serial.println(F("Trying to initialize the ggwave instance")); + + ggwave.setLogFile(nullptr); + + auto p = GGWave::getDefaultParameters(); + + // Adjust the "ggwave" parameters to your needs. + // Make sure that the "payloadLength" parameter matches the one used on the transmitting side. +#ifdef LONG_RANGE + // The "FAST" protocols require 2x more memory, so we reduce the payload length to compensate: + p.payloadLength = 8; +#else + p.payloadLength = 16; +#endif + Serial.print(F("Using payload length: ")); + Serial.println(p.payloadLength); + + 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_OPERATING_MODE_RX | GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_USE_DSS | GGWAVE_OPERATING_MODE_TX_ONLY_TONES; + + // Protocols to use for TX + // Remove the ones that you don't need to reduce memory usage + GGWave::Protocols::tx().disableAll(); + //GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_MT_NORMAL, true); + //GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_MT_FAST, true); + GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_MT_FASTEST, true); + + // Protocols to use for RX + // Remove the ones that you don't need to reduce memory and CPU usage + GGWave::Protocols::rx().disableAll(); + + //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_AUDIBLE_NORMAL, true); + //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_NORMAL, true); + //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_NORMAL, true); + + //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_AUDIBLE_NORMAL, true); + //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_NORMAL, true); + //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_NORMAL, true); + + //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_ULTRASOUND_NORMAL, true); + //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_ULTRASOUND_FAST, true); + //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_ULTRASOUND_FASTEST, true); + +#ifdef LONG_RANGE + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_AUDIBLE_FAST, true); + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FAST, true); + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FAST, true); +#endif + + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_AUDIBLE_FASTEST, true); + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FASTEST, true); + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FASTEST, true); + + // Print the memory required for the "ggwave" instance: + ggwave.prepare(p, false); + + Serial.print(F("Required memory by the ggwave instance: ")); + Serial.print(ggwave.heapSize()); + Serial.println(F(" bytes")); + + // Initialize the "ggwave" instance: + ggwave.prepare(p, true); + Serial.print(F("Instance initialized successfully! Memory used: ")); + } + + // initialize the analog microphone + if (analog_microphone_init(&config) < 0) { + Serial.println(F("analog microphone initialization failed!")); + while (1) { tight_loop_contents(); } + } + + // set callback that is called when all the samples in the library + // internal sample buffer are ready for reading + analog_microphone_set_samples_ready_handler(on_analog_samples_ready); + + // start capturing data from the analog microphone + if (analog_microphone_start() < 0) { + Serial.println(F("Analog microphone start failed!")); + while (1) { tight_loop_contents(); } + } + + Serial.println(F("setup() done")); +} + +int niter = 0; +int tLastReceive = -10000; + +GGWave::TxRxData result; + +void loop() { + // wait for new samples + while (samplesRead == 0) { tight_loop_contents(); } + + // store and clear the samples read from the callback + int nSamples = samplesRead; + samplesRead = 0; + + //// loop through any new collected samples + //for (int i = 0; i < nSamples; i++) { + // Serial.printf("%d\n", sampleBuffer[i]); + //} + + // Try to decode any "ggwave" data: + auto tStart = millis(); + + if (ggwave.decode(sampleBuffer, samplesPerFrame*kSampleSize_bytes) == false) { + Serial.println("Failed to decode"); + } + + auto tEnd = millis(); + + if (++niter % 10 == 0) { + // print the time it took the last decode() call to complete + // should be smaller than samplesPerFrame/sampleRate seconds + // for example: samplesPerFrame = 128, sampleRate = 6000 => not more than 20 ms + Serial.println(tEnd - tStart); + if (tEnd - tStart > 1000*(float(samplesPerFrame)/sampleRate)) { + Serial.println(F("Warning: decode() took too long to execute!")); + } + } + + // Check if we have successfully decoded any data: + int nr = ggwave.rxTakeData(result); + if (nr > 0) { + Serial.println(tEnd - tStart); + Serial.print(F("Received data with length ")); + Serial.print(nr); // should be equal to p.payloadLength + Serial.println(F(" bytes:")); + + Serial.println((char *) result.data()); + + tLastReceive = tEnd; + } +} diff --git a/include/ggwave/ggwave.h b/include/ggwave/ggwave.h index 95a4acb..e87d57f 100644 --- a/include/ggwave/ggwave.h +++ b/include/ggwave/ggwave.h @@ -15,7 +15,7 @@ # define GGWAVE_API #endif -#if defined(ARDUINO) +#if defined(ARDUINO_UNO) #define GGWAVE_CONFIG_FEW_PROTOCOLS #endif