1
+ /*
2
+ This example is only for ESP devices.
3
+
4
+ This example demonstrates usage of callback functions and duplex operation.
5
+ Callback functions allow you to perform audio events pseudo parallel to your main loop.
6
+ This way you no longer need to poll for reading or writing data from/to I2S module.
7
+
8
+ Unlike Arduino, ESP allows you to operate input and output simultaneously on separate pins.
9
+
10
+ Hardware:
11
+ 1. ESP board with at least 4 GPIOs available
12
+ 2. I2S mirophone (for example this one https://www.adafruit.com/product/3421)
13
+ 3. I2S decoder (for example this one https://www.adafruit.com/product/3678)
14
+ 4. Headphones, or speaker(s) to be connected into the decoder
15
+ 5. Some connecting wires, USB cable and optionally a breadboard
16
+
17
+ Wiring:
18
+ Note: If you need to use other than default pins you can change the default definition below this comment block
19
+ 1. Connect pins of both the microphone and decoder to common SCK and FS pins on ESP
20
+ 1.a SCK (Source Clock, or Bit Clock) connects by default to pin 5
21
+ 1.b FS (Frame Select, or Left-Right Select) connects by default to pin 25
22
+ 2. Connect data pin of your microphone to pin 35
23
+ 3. Connect data pin of your decoder to pin 26
24
+ 4. Connect power pins and other remaining pins of your modules according to their specific instructions
25
+ 5. Connect headphones/speaker(s) to decoder
26
+ 6. Connect ESP board to your computer via USB cable
27
+
28
+ Steps to run:
29
+ 1. Select target board:
30
+ Tools -> Board -> ESP32 Arduino -> your board
31
+ 2. Upload sketch
32
+ Press upload button (arrow in top left corner)
33
+ When you see in console line like this: "Connecting........_____.....__"
34
+ If loading doesn't start automatically, you may need to press and hold Boot
35
+ button and press EN button shortly. Now you can release both buttons.
36
+ You should see lines like this: "Writing at 0x00010000... (12 %)" with rising percentage on each line.
37
+ If this fails, try the board buttons right after pressing upload button, or reconnect the USB cable.
38
+ 3. Open plotter
39
+ Tools -> Serial Plotter
40
+ 4. Enjoy
41
+ Listen to generated square wave signal, while observing the wave signal recorded by your microphone
42
+ both at the same time thanks to ESP duplex ability.
43
+
44
+ Tip:
45
+ Install ArduinoSound library and discover extended functionality of I2S
46
+ you can try ESP WiFi telephone, Record on SD card and Play back from it...
47
+
48
+ Created by Tomas Pilny
49
+ on 23rd June 2021
50
+ */
51
+
52
+
53
+ #include < I2S.h>
54
+ const int sampleRate = 16000 ; // sample rate in Hz
55
+ const int bitsPerSample = 16 ;
56
+
57
+ // code from SimpleTone example
58
+ const int frequency = 1250 ; // frequency of square wave in Hz
59
+ const int amplitude = 32767 ; // amplitude of square wave
60
+
61
+ const int halfWavelength = (sampleRate / frequency); // half wavelength of square wave
62
+
63
+ short sample = amplitude; // current sample value
64
+ int count = 0 ;
65
+
66
+ void outputCallback (){
67
+ if (count % halfWavelength == 0 ) {
68
+ // invert the sample every half wavelength count multiple to generate square wave
69
+ sample = -1 * sample;
70
+ }
71
+
72
+ // write the same sample twice, once for left and once for the right channel
73
+ I2S.write (sample);
74
+ I2S.write (sample);
75
+
76
+ // increment the counter for the next sample
77
+ count++;
78
+ }
79
+
80
+ // code from InputSerialPlotter example
81
+ void inputCallback (){
82
+ // read a sample
83
+ int sample = I2S.read ();
84
+
85
+ if (sample) {
86
+ // if it's non-zero print value to serial
87
+ Serial.println (sample);
88
+ }
89
+ }
90
+
91
+ void setup () {
92
+ // Open serial communications and wait for port to open:
93
+ // A baud rate of 115200 is used instead of 9600 for a faster data rate
94
+ // on non-native USB ports
95
+ Serial.begin (115200 );
96
+ while (!Serial) {
97
+ ; // wait for serial port to connect. Needed for native USB port only
98
+ }
99
+
100
+ // start I2S at 8 kHz with 32-bits per sample
101
+ if (!I2S.begin (I2S_PHILIPS_MODE, sampleRate, bitsPerSample)) {
102
+ Serial.println (" Failed to initialize I2S!" );
103
+ while (1 ); // do nothing
104
+ }
105
+ I2S.setHalfDuplex (); // Use two data pins (default pins are input=35, output=26)
106
+
107
+ // Register our callback functions
108
+ I2S.onTransmit (outputCallback); // Function outputCallback will be called each time I2S finishes transmit operation (audio output)
109
+ I2S.onReceive (inputCallback); // Function inputCallback will be called each time I2S finishes receive operation (audio input)
110
+ Serial.println (" Callbacks example setup done." );
111
+ }
112
+
113
+ void loop () {
114
+ // loop task remains free for other work
115
+ delay (100 ); // Let the FreeRTOS reset the watchDogTimer
116
+ }
0 commit comments