From 8ea8b8476721b929bf1575e3636dc83721eb75a3 Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Mon, 11 Dec 2023 17:05:18 -0700 Subject: [PATCH 1/9] Create base voice class Allows us to use a single base class in audio examples instead of a specific module Need to update name at some point as part of #9, it's not clear if UBX_CELL_VOICE or UBX_CELL_VOICE_BASE should be used based on the names alone --- src/SparkFun_u-blox_Cellular_Arduino_Library.h | 1 + src/sfe_ublox_cellular_voice.h | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/SparkFun_u-blox_Cellular_Arduino_Library.h b/src/SparkFun_u-blox_Cellular_Arduino_Library.h index a5b2243..96e8cd8 100644 --- a/src/SparkFun_u-blox_Cellular_Arduino_Library.h +++ b/src/SparkFun_u-blox_Cellular_Arduino_Library.h @@ -1,3 +1,4 @@ #include "sfe_ublox_cellular.h" +#include "sfe_ublox_cellular_voice.h" #include "sfe_sara_r5.h" #include "sfe_lara_r6.h" diff --git a/src/sfe_ublox_cellular_voice.h b/src/sfe_ublox_cellular_voice.h index 0e291dd..01b7627 100644 --- a/src/sfe_ublox_cellular_voice.h +++ b/src/sfe_ublox_cellular_voice.h @@ -127,4 +127,9 @@ class UBX_CELL_VOICE } }; +class UBX_CELL_VOICE_BASE : public UBX_CELL, public UBX_CELL_VOICE +{ + +}; + #endif \ No newline at end of file From 80ee412641359679ecc6a7a58f6a260c981887fe Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Mon, 11 Dec 2023 17:06:21 -0700 Subject: [PATCH 2/9] Create audio example 1 --- .../Audio_Example1_Play_Tone.ino | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 examples/Audio_Examples/Audio_Example1_Play_Tone/Audio_Example1_Play_Tone.ino diff --git a/examples/Audio_Examples/Audio_Example1_Play_Tone/Audio_Example1_Play_Tone.ino b/examples/Audio_Examples/Audio_Example1_Play_Tone/Audio_Example1_Play_Tone.ino new file mode 100644 index 0000000..df08d23 --- /dev/null +++ b/examples/Audio_Examples/Audio_Example1_Play_Tone/Audio_Example1_Play_Tone.ino @@ -0,0 +1,120 @@ +#include "SparkFun_u-blox_Cellular_Arduino_Library.h" + +// Uncomment the line below that you need for Serial on your platform +#define mySerial Serial1 +// SoftwareSerial mySerial(16, 17); + +// Uncomment the module you're using. If your module is not listed below, then +// it's not supported for this example +UBX_CELL_VOICE_BASE myModule; // This example works with all voice-enabled modules, so this base class can be used +// LARA_R6001 myModule; +// LARA_R6401 myModule; +// LARA_R6801_00B myModule; + +void setup() +{ + Serial.begin(115200); // Start the serial console + + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Audio Example 1 - Play Tone")); + Serial.println(F("Press any key to begin")); + + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); + + Serial.println(F("Beginning...")); + + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); + + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) + { + Serial.println(F("Module connected!")); + } + else + { + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) ; // Loop forever on fail + } + Serial.println(); +} + +void loop() +{ + String inputString; + char dtmfChar = 0; + uint16_t frequency = 0; + uint16_t duration = 0; + uint8_t volume = 0; + + while(true) + { + while(Serial.available() != 0){Serial.read();} + Serial.println(F("Enter a frequency in Hz (300-3400) or a DTMF character (0-9, *, #)")); + while(Serial.available() == 0){} + + inputString = Serial.readStringUntil('\n'); + + if(inputString.length() == 1) + { + dtmfChar = inputString.charAt(0); + if((dtmfChar >= '0' && dtmfChar <= '9') || dtmfChar == '*' || dtmfChar == '#') + { + break; + } + } + else + { + frequency = inputString.toInt(); + if(frequency >= 300 && frequency <= 3400) + { + dtmfChar == 0; + break; + } + } + } + + while(true) + { + while(Serial.available() != 0){Serial.read();} + Serial.println(F("Enter a duration in ms (50-1360)")); + while(Serial.available() == 0){} + + inputString = Serial.readStringUntil('\n'); + duration = inputString.toInt(); + if(duration >= 50 && duration <= 1360) + { + break; + } + } + + while(true) + { + while(Serial.available() != 0){Serial.read();} + Serial.println(F("Enter a volume (0-100)")); + while(Serial.available() == 0){} + + inputString = Serial.readStringUntil('\n'); + volume = inputString.toInt(); + if(volume <= 100) + { + break; + } + } + + if(dtmfChar == 0) + { + myModule.generateToneFreq(frequency, duration, volume); + } + else + { + myModule.generateToneDTMF(dtmfChar, duration, volume); + } +} \ No newline at end of file From 9b7a8bc05990b97a1fa6d3c33c37f24b8f45d5be Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Mon, 11 Dec 2023 17:13:53 -0700 Subject: [PATCH 3/9] Add note to audio example about needing a codec --- .../Audio_Example1_Play_Tone.ino | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/examples/Audio_Examples/Audio_Example1_Play_Tone/Audio_Example1_Play_Tone.ino b/examples/Audio_Examples/Audio_Example1_Play_Tone/Audio_Example1_Play_Tone.ino index df08d23..a6cc09c 100644 --- a/examples/Audio_Examples/Audio_Example1_Play_Tone/Audio_Example1_Play_Tone.ino +++ b/examples/Audio_Examples/Audio_Example1_Play_Tone/Audio_Example1_Play_Tone.ino @@ -17,6 +17,15 @@ void setup() // Wait for user to press key to begin Serial.println(F("u-blox Cellular Audio Example 1 - Play Tone")); + + Serial.println(); + Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(F("This example requires an audio codec attached to the I2S interface")); + Serial.println(F("of the cellular modem. Please add one and update this example as")); + Serial.println(F("needed to configure your audio codec!")); + Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(); + Serial.println(F("Press any key to begin")); while (!Serial.available()) // Wait for the user to press a key (send any serial character) From 1c0007ae7fda882a725008741f1a5ad9fff450c4 Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Tue, 12 Dec 2023 09:54:27 -0700 Subject: [PATCH 4/9] Rename audio example 1 to match conventions --- .../AudioExample1_PlayTone.ino} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/Audio_Examples/{Audio_Example1_Play_Tone/Audio_Example1_Play_Tone.ino => AudioExample1_PlayTone/AudioExample1_PlayTone.ino} (100%) diff --git a/examples/Audio_Examples/Audio_Example1_Play_Tone/Audio_Example1_Play_Tone.ino b/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino similarity index 100% rename from examples/Audio_Examples/Audio_Example1_Play_Tone/Audio_Example1_Play_Tone.ino rename to examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino From 38c935a659a8fc6c0656e643eff717d428980b96 Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Tue, 12 Dec 2023 10:04:22 -0700 Subject: [PATCH 5/9] Add audio resource enum Also default tone_id and nof_repeat to 0 in playAudioResource() --- src/sfe_ublox_cellular_voice.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sfe_ublox_cellular_voice.h b/src/sfe_ublox_cellular_voice.h index 01b7627..952e778 100644 --- a/src/sfe_ublox_cellular_voice.h +++ b/src/sfe_ublox_cellular_voice.h @@ -10,6 +10,13 @@ const char* const UBX_CELL_COMMAND_PLAY_AUDIO = "+UPAR"; // Play audio resour const char* const UBX_CELL_COMMAND_STOP_AUDIO = "+USAR"; // Stop audio resource const char* const UBX_CELL_COMMAND_GENERATE_TONE = "+UTGN"; // Tone generator +typedef enum +{ + UBX_CELL_AUDIO_RESOURCE_TONE = 0, + UBX_CELL_AUDIO_RESOURCE_MIDI = 1, + UBX_CELL_AUDIO_RESOURCE_LOOPBACK = 2 +} UBX_CELL_audio_resource_t; + // Base class for any modules supporting voice calls template class UBX_CELL_VOICE @@ -60,7 +67,7 @@ class UBX_CELL_VOICE nullptr, UBX_CELL_STANDARD_RESPONSE_TIMEOUT); } - UBX_CELL_error_t playAudioResource(uint8_t audio_resource, uint8_t tone_id, uint8_t nof_repeat) + UBX_CELL_error_t playAudioResource(uint8_t audio_resource, uint8_t tone_id = 0, uint8_t nof_repeat = 0) { UBX_CELL_error_t err; char *command; From e109e63b39f66d4a720f17e61821b558d1f897da Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Tue, 12 Dec 2023 10:04:34 -0700 Subject: [PATCH 6/9] Add audio example 2 (loopback) --- .../AudioExample2_Loopback.ino | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino diff --git a/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino b/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino new file mode 100644 index 0000000..f328587 --- /dev/null +++ b/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino @@ -0,0 +1,71 @@ +#include "SparkFun_u-blox_Cellular_Arduino_Library.h" + +// Uncomment the line below that you need for Serial on your platform +#define mySerial Serial1 +// SoftwareSerial mySerial(16, 17); + +// Uncomment the module you're using. If your module is not listed below, then +// it's not supported for this example +UBX_CELL_VOICE_BASE myModule; // This example works with all voice-enabled modules, so this base class can be used +// LARA_R6001 myModule; +// LARA_R6401 myModule; +// LARA_R6801_00B myModule; + +void setup() +{ + Serial.begin(115200); // Start the serial console + + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Audio Example 2 - Loopback")); + + Serial.println(); + Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(F("This example requires an audio codec attached to the I2S interface")); + Serial.println(F("of the cellular modem. Please add one and update this example as")); + Serial.println(F("needed to configure your audio codec!")); + Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(); + + Serial.println(F("Press any key to begin")); + + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); + + Serial.println(F("Beginning...")); + + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); + + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) + { + Serial.println(F("Module connected!")); + } + else + { + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) ; // Loop forever on fail + } + Serial.println(); +} + +void loop() +{ + while(Serial.available() != 0){Serial.read();} + Serial.println(F("Enter any key to begin loopback")); + while(Serial.available() == 0){} + + myModule.playAudioResource(UBX_CELL_AUDIO_RESOURCE_LOOPBACK); + + while(Serial.available() != 0){Serial.read();} + Serial.println(F("Enter any key to stop loopback")); + while(Serial.available() == 0){} + + myModule.stopAudioResource(UBX_CELL_AUDIO_RESOURCE_LOOPBACK); +} \ No newline at end of file From 7efffde75d7d2d9ed64a38e052e23d429c3e56fb Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Tue, 12 Dec 2023 17:45:59 -0700 Subject: [PATCH 7/9] Add RING URC handler Pending #16, this should work after that gets merged --- src/sfe_ublox_cellular_voice.h | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/sfe_ublox_cellular_voice.h b/src/sfe_ublox_cellular_voice.h index 952e778..9ceee64 100644 --- a/src/sfe_ublox_cellular_voice.h +++ b/src/sfe_ublox_cellular_voice.h @@ -10,6 +10,8 @@ const char* const UBX_CELL_COMMAND_PLAY_AUDIO = "+UPAR"; // Play audio resour const char* const UBX_CELL_COMMAND_STOP_AUDIO = "+USAR"; // Stop audio resource const char* const UBX_CELL_COMMAND_GENERATE_TONE = "+UTGN"; // Tone generator +const char* const UBX_CELL_RING_URC = "RING"; + typedef enum { UBX_CELL_AUDIO_RESOURCE_TONE = 0, @@ -22,6 +24,15 @@ template class UBX_CELL_VOICE { public: + UBX_CELL_VOICE(void) + { + // Set ring URC callback to nullptr + _ringCallback = nullptr; + + // Add handler for ring URC + static_cast(this)->addURCHandler(UBX_CELL_RING_URC, [this](const char* event){return this->urcCheckRing(event);}); + } + UBX_CELL_error_t dial(String number) { char *command; @@ -132,6 +143,31 @@ class UBX_CELL_VOICE free(command); return err; } + + void setRingCallback(void (*callback)(void)) + { + _ringCallback = callback; + } + +protected: + // Callback for incoming calls + void (*_ringCallback)(void); + + bool urcCheckRing(const char *event) + { + int socket, length; + char *searchPtr = strstr(event, UBX_CELL_RING_URC); + if (searchPtr != nullptr) + { + if(_ringCallback != nullptr) + { + _ringCallback(); + } + return true; + } + + return false; + } }; class UBX_CELL_VOICE_BASE : public UBX_CELL, public UBX_CELL_VOICE From 6c2da8c0511bd5c3e2bec6ea31a53817725fb134 Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Tue, 12 Dec 2023 17:46:23 -0700 Subject: [PATCH 8/9] Add audio example 3 (call control) --- .../AudioExample3_CallControl.ino | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino diff --git a/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino b/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino new file mode 100644 index 0000000..ae6ab47 --- /dev/null +++ b/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino @@ -0,0 +1,129 @@ +#include "SparkFun_u-blox_Cellular_Arduino_Library.h" + +// Uncomment the line below that you need for Serial on your platform +#define mySerial Serial1 +// SoftwareSerial mySerial(16, 17); + +// Uncomment the module you're using. If your module is not listed below, then +// it's not supported for this example +UBX_CELL_VOICE_BASE myModule; // This example works with all voice-enabled modules, so this base class can be used +// LARA_R6001 myModule; +// LARA_R6401 myModule; +// LARA_R6801_00B myModule; + +bool callInProgress = false; +bool incomingCall = false; + +void ringCallback() +{ + Serial.println(F("Incoming call! Enter \"A\" to answer, or anything else to reject")); + incomingCall = true; +} + +void setup() +{ + String currentOperator = ""; + + Serial.begin(115200); // Start the serial console + + // Wait for user to press key to begin + Serial.println(F("u-blox Cellular Audio Example 3 - Call Control")); + + Serial.println(); + Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(F("This example requires an audio codec attached to the I2S interface")); + Serial.println(F("of the cellular modem. Please add one and update this example as")); + Serial.println(F("needed to configure your audio codec!")); + Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(); + + Serial.println(F("Press any key to begin")); + + while (!Serial.available()) // Wait for the user to press a key (send any serial character) + ; + while (Serial.available()) // Empty the serial RX buffer + Serial.read(); + + Serial.println(F("Beginning...")); + + // myModule.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low + // Uncomment the next line if required + // myModule.invertPowerPin(true); + + // Initialize the module + if (myModule.begin(mySerial, UBX_CELL_DEFAULT_BAUD_RATE) ) + { + Serial.println(F("Module connected!")); + } + else + { + Serial.println(F("Unable to communicate with the module.")); + Serial.println(F("Manually power-on (hold the module's On button for 3 seconds) and try again.")); + while (1) ; // Loop forever on fail + } + Serial.println(); + + // First check to see if we're connected to an operator: + if (myModule.getOperator(¤tOperator) == UBX_CELL_SUCCESS) + { + Serial.print(F("Connected to: ")); + Serial.println(currentOperator); + } + else + { + Serial.print(F("The module is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); + while (1) + ; // Do nothing more + } + + // Set callback function for when a new call is received + myModule.setRingCallback(&ringCallback); + + Serial.println(F("Enter a number to dial")); + + // Clear any input + while(Serial.available()){Serial.read();} +} + +void loop() +{ + String inputString; + + myModule.bufferedPoll(); + + if(Serial.available()) + { + inputString = Serial.readStringUntil('\n'); + while(Serial.available()){Serial.read();} + + if(incomingCall) + { + if(inputString == "A" || inputString == "a") + { + Serial.println(F("Answering call, enter any key to hang up")); + myModule.answer(); + callInProgress = true; + } + else + { + Serial.println(F("Rejecting call")); + myModule.hangUp(); + } + incomingCall = false; + } + else if(callInProgress == false) + { + Serial.println("Dialing " + inputString + ", enter any key to hang up"); + myModule.dial(inputString); + callInProgress = true; + } + else + { + Serial.println(F("Hanging up, enter a new number to dial")); + myModule.hangUp(); + callInProgress = false; + } + } +} \ No newline at end of file From 83d58c8a4b93a695213c229e70576fa05cec9b78 Mon Sep 17 00:00:00 2001 From: Dryw Wade Date: Wed, 13 Dec 2023 10:52:52 -0700 Subject: [PATCH 9/9] Space out exclamation marks in audio examples Just for the rare chance that someone is using the ATMega2560 with the original bootloader, triple exclamation marks would cause bad things. Easy enough to avoid by spacing them out! --- .../AudioExample1_PlayTone/AudioExample1_PlayTone.ino | 4 ++-- .../AudioExample2_Loopback/AudioExample2_Loopback.ino | 4 ++-- .../AudioExample3_CallControl/AudioExample3_CallControl.ino | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino b/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino index a6cc09c..60f802d 100644 --- a/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino +++ b/examples/Audio_Examples/AudioExample1_PlayTone/AudioExample1_PlayTone.ino @@ -19,11 +19,11 @@ void setup() Serial.println(F("u-blox Cellular Audio Example 1 - Play Tone")); Serial.println(); - Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); Serial.println(F("This example requires an audio codec attached to the I2S interface")); Serial.println(F("of the cellular modem. Please add one and update this example as")); Serial.println(F("needed to configure your audio codec!")); - Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); Serial.println(); Serial.println(F("Press any key to begin")); diff --git a/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino b/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino index f328587..b07ce47 100644 --- a/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino +++ b/examples/Audio_Examples/AudioExample2_Loopback/AudioExample2_Loopback.ino @@ -19,11 +19,11 @@ void setup() Serial.println(F("u-blox Cellular Audio Example 2 - Loopback")); Serial.println(); - Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); Serial.println(F("This example requires an audio codec attached to the I2S interface")); Serial.println(F("of the cellular modem. Please add one and update this example as")); Serial.println(F("needed to configure your audio codec!")); - Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); Serial.println(); Serial.println(F("Press any key to begin")); diff --git a/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino b/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino index ae6ab47..47f407f 100644 --- a/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino +++ b/examples/Audio_Examples/AudioExample3_CallControl/AudioExample3_CallControl.ino @@ -30,11 +30,11 @@ void setup() Serial.println(F("u-blox Cellular Audio Example 3 - Call Control")); Serial.println(); - Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); Serial.println(F("This example requires an audio codec attached to the I2S interface")); Serial.println(F("of the cellular modem. Please add one and update this example as")); Serial.println(F("needed to configure your audio codec!")); - Serial.println(F("!!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!! ATTENTION !!!!!!!!")); + Serial.println(F("! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! ! ATTENTION ! ! ! ! !")); Serial.println(); Serial.println(F("Press any key to begin"));