diff --git a/examples/arduino-rx/arduino-rx.ino b/examples/arduino-rx/arduino-rx.ino index 2557a2f..ebb76e7 100644 --- a/examples/arduino-rx/arduino-rx.ino +++ b/examples/arduino-rx/arduino-rx.ino @@ -2,6 +2,7 @@ #include +const int kPinButton0 = 5; const int kPinSpeaker = 10; using TSample = int16_t; @@ -29,6 +30,30 @@ volatile int err = 0; // global GGwave instance GGWave ggwave; +// uncoment this to enable SSD1306 display output +#define DISPLAY_OUTPUT 1 + +#ifdef DISPLAY_OUTPUT + +#include +#include +#include +#include + +#define SCREEN_WIDTH 128 // OLED display width, in pixels +#define SCREEN_HEIGHT 32 // OLED display height, in pixels + +// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) +// The pins for I2C are defined by the Wire-library. +// On an arduino UNO: A4(SDA), A5(SCL) +// On an arduino MEGA 2560: 20(SDA), 21(SCL) +// On an arduino LEONARDO: 2(SDA), 3(SCL), ... +#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) +#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 +Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); + +#endif + // 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) { Serial.print(F("Sending text: ")); @@ -55,68 +80,104 @@ void setup() { while (!Serial); pinMode(kPinSpeaker, OUTPUT); + pinMode(kPinButton0, INPUT_PULLUP); + +#ifdef DISPLAY_OUTPUT + { + // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally + if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { + Serial.println(F("SSD1306 allocation failed")); + for(;;); // Don't proceed, loop forever + } + + // Show initial display buffer contents on the screen -- + // the library initializes this with an Adafruit splash screen. + //display.display(); + //delay(2000); // Pause for 2 seconds + + // Clear the buffer + display.clearDisplay(); + + display.setTextSize(2); + display.setTextColor(SSD1306_WHITE); // Draw white text + display.setCursor(0, 0); // Start at top-left corner + display.println(F("GGWave!")); + display.setTextSize(1); + display.println(F("")); + display.println(F("Listening...")); + + display.display(); + } +#endif Serial.println(F("Trying to create ggwave instance")); ggwave.setLogFile(nullptr); - auto p = GGWave::getDefaultParameters(); + { + 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_I16; - p.operatingMode = GGWAVE_OPERATING_MODE_RX | GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_USE_DSS | GGWAVE_OPERATING_MODE_TX_ONLY_TONES; + 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_I16; + p.operatingMode = GGWAVE_OPERATING_MODE_RX | GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_USE_DSS | GGWAVE_OPERATING_MODE_TX_ONLY_TONES; - GGWave::Protocols::tx().disableAll(); - GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_DT_NORMAL, true); - GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_DT_FAST, true); - GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_DT_FASTEST, true); - 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); + GGWave::Protocols::tx().disableAll(); + GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_DT_NORMAL, true); + GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_DT_FAST, true); + GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_DT_FASTEST, true); + 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); - GGWave::Protocols::rx().disableAll(); - GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_NORMAL, true); - GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FAST, true); - GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FASTEST, true); - GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_NORMAL, true); - GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FAST, true); - GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FASTEST, true); + GGWave::Protocols::rx().disableAll(); + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_NORMAL, true); + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FAST, true); + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FASTEST, true); + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_NORMAL, true); + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FAST, true); + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FASTEST, true); - ggwave.prepare(p); - Serial.println(ggwave.heapSize()); + ggwave.prepare(p); + Serial.println(ggwave.heapSize()); + } delay(1000); Serial.println(F("Instance initialized")); - // Configure the data receive callback - PDM.onReceive(onPDMdata); + { + // Configure the data receive callback + PDM.onReceive(onPDMdata); - // Optionally set the gain - // Defaults to 20 on the BLE Sense and -10 on the Portenta Vision Shields - //PDM.setGain(30); + // Optionally set the gain + // Defaults to 20 on the BLE Sense and -10 on the Portenta Vision Shields + //PDM.setGain(30); - // Initialize PDM with: - // - one channel (mono mode) - // - 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, sampleRate)) { - Serial.println(F("Failed to start PDM!")); - while (1); + // Initialize PDM with: + // - one channel (mono mode) + // - 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, sampleRate)) { + Serial.println(F("Failed to start PDM!")); + while (1); + } } } void loop() { int nr = 0; int niter = 0; + int but0Prev = HIGH; GGWave::TxRxData result; + char resultLast[17]; + while (true) { while (qsize >= samplesPerFrame) { auto tStart = millis(); @@ -148,19 +209,19 @@ void loop() { Serial.println((char *) result.data()); - if (strcmp((char *)result.data(), "test") == 0) { - // pause microphone capture while transmitting - PDM.end(); - delay(500); +#ifdef DISPLAY_OUTPUT + { + display.clearDisplay(); - send_text(ggwave, kPinSpeaker, "hello", GGWAVE_PROTOCOL_MT_FASTEST); + display.setTextSize(2); + display.setTextColor(SSD1306_WHITE); + display.setCursor(0, 0); + display.println((char *) result.data()); - // resume microphone capture - if (!PDM.begin(channels, sampleRate)) { - Serial.println(F("Failed to start PDM!")); - while (1); - } + display.display(); } +#endif + strcpy(resultLast, (char *) result.data()); } } @@ -169,6 +230,31 @@ void loop() { Serial.println(err); err = 0; } + + int but0 = digitalRead(kPinButton0); + if (but0 == LOW && but0Prev == HIGH) { + Serial.println(F("Button 0 pressed - transmitting ..")); + + { + // pause microphone capture while transmitting + PDM.end(); + delay(500); + + send_text(ggwave, kPinSpeaker, resultLast, GGWAVE_PROTOCOL_MT_FASTEST); + + // resume microphone capture + if (!PDM.begin(channels, sampleRate)) { + Serial.println(F("Failed to start PDM!")); + while (1); + } + } + + Serial.println(F("Done")); + + but0Prev = LOW; + } else if (but0 == HIGH && but0Prev == LOW) { + but0Prev = HIGH; + } } } diff --git a/examples/esp32-rx/esp32-rx.ino b/examples/esp32-rx/esp32-rx.ino index 5c8b6a0..ab5fe3d 100644 --- a/examples/esp32-rx/esp32-rx.ino +++ b/examples/esp32-rx/esp32-rx.ino @@ -1,5 +1,6 @@ #include "ggwave/ggwave.h" +#include #include // global GGwave instance @@ -8,8 +9,12 @@ GGWave ggwave; using TSample = int16_t; const size_t kSampleSize_bytes = sizeof(TSample); -const int sampleRate = 12000; -const int samplesPerFrame = 256; +const int sampleRate = 24000; +const int samplesPerFrame = 512; + +// switch to the following settings if only using MT protocols +//const int sampleRate = 12000; +//const int samplesPerFrame = 256; TSample sampleBuffer[samplesPerFrame]; @@ -32,11 +37,63 @@ const i2s_config_t adc_i2s_config = { .fixed_mclk = 0 }; +// uncoment this to enable SSD1306 display output +#define DISPLAY_OUTPUT 1 + +#ifdef DISPLAY_OUTPUT + +#include +#include +#include +#include + +#define SCREEN_WIDTH 128 // OLED display width, in pixels +#define SCREEN_HEIGHT 32 // OLED display height, in pixels + +// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) +// The pins for I2C are defined by the Wire-library. +// On an arduino UNO: A4(SDA), A5(SCL) +// On an arduino MEGA 2560: 20(SDA), 21(SCL) +// On an arduino LEONARDO: 2(SDA), 3(SCL), ... +#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) +#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 +Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); + +#endif + void setup() { Serial.begin(115200); while (!Serial); Serial.println(F("GGWave test for ESP32")); +#ifdef DISPLAY_OUTPUT + { + // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally + if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { + Serial.println(F("SSD1306 allocation failed")); + for(;;); // Don't proceed, loop forever + } + + // Show initial display buffer contents on the screen -- + // the library initializes this with an Adafruit splash screen. + //display.display(); + //delay(2000); // Pause for 2 seconds + + // Clear the buffer + display.clearDisplay(); + + display.setTextSize(2); + display.setTextColor(SSD1306_WHITE); // Draw white text + display.setCursor(0, 0); // Start at top-left corner + display.println(F("GGWave!")); + display.setTextSize(1); + display.println(F("")); + display.println(F("Listening...")); + + display.display(); + } +#endif + { Serial.println(F("Trying to create ggwave instance")); @@ -54,19 +111,16 @@ void setup() { p.operatingMode = GGWAVE_OPERATING_MODE_RX | GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_USE_DSS | GGWAVE_OPERATING_MODE_TX_ONLY_TONES; GGWave::Protocols::tx().disableAll(); - //GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_DT_NORMAL, true); - //GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_DT_FAST, true); - //GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_DT_FASTEST, true); - 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_NORMAL, true); + //GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_MT_FAST, true); GGWave::Protocols::tx().toggle(GGWAVE_PROTOCOL_MT_FASTEST, true); GGWave::Protocols::rx().disableAll(); //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_NORMAL, true); //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FAST, true); - //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FASTEST, true); - GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_NORMAL, true); - GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FAST, true); + GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_DT_FASTEST, true); + //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_NORMAL, true); + //GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FAST, true); GGWave::Protocols::rx().toggle(GGWAVE_PROTOCOL_MT_FASTEST, true); ggwave.prepare(p); @@ -122,6 +176,11 @@ void loop() { s1 = s0 ^ s1; s0 = s0 ^ s1; } + + // use with serial plotter to observe real-time audio signal + //for (int i = 0; i < samples_read; i++) { + // Serial.println(sampleBuffer[i]); + //} } auto tStart = millis(); @@ -148,9 +207,18 @@ void loop() { Serial.println(F(" bytes:")); Serial.println((char *) result.data()); - } - //for (int i = 0; i < samples_read; i++) { - // Serial.println(samples[i]); - //} +#ifdef DISPLAY_OUTPUT + { + display.clearDisplay(); + + display.setTextSize(2); + display.setTextColor(SSD1306_WHITE); + display.setCursor(0, 0); + display.println((char *) result.data()); + + display.display(); + } +#endif + } } diff --git a/include/ggwave/ggwave.h b/include/ggwave/ggwave.h index 37747a4..14949fd 100644 --- a/include/ggwave/ggwave.h +++ b/include/ggwave/ggwave.h @@ -390,7 +390,7 @@ public: #include #ifdef ARDUINO -#ifdef ARDUINO_ARCH_AVR +#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARDUINO_NANO33BLE) || defined(ARDUINO_ARCH_MBED_RP2040) || defined(ARDUINO_ARCH_RP2040) #include #else #include