Skip to content

Commit 01e9dc9

Browse files
Add A2DP sink (speaker) support (#2177)
Provide direct connection from BT audio to I2S and PWM audio outputs. Example included showing play/pause operation.
1 parent ec5e62e commit 01e9dc9

14 files changed

+1561
-68
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// A2DPSink example - Released to the public domain in 2024 by Earle F. Philhower, III
2+
3+
// Hook up a phono plug to GP0 and GP1 (and GND of course...the 1st 3 pins on the PCB)
4+
// Connect wired earbuds up and connect over BT from your phone and play some music.
5+
6+
#include <BluetoothAudio.h>
7+
#include <PWMAudio.h>
8+
9+
PWMAudio pwm;
10+
A2DPSink a2dp;
11+
12+
volatile A2DPSink::PlaybackStatus status = A2DPSink::STOPPED;
13+
14+
void volumeCB(void *param, int pct) {
15+
(void) param;
16+
Serial.printf("Speaker volume changed to %d%%\n", pct);
17+
}
18+
19+
void connectCB(void *param, bool connected) {
20+
(void) param;
21+
if (connected) {
22+
Serial.printf("A2DP connection started to %s\n", bd_addr_to_str(a2dp.getSourceAddress()));
23+
} else {
24+
Serial.printf("A2DP connection stopped\n");
25+
}
26+
}
27+
28+
void playbackCB(void *param, A2DPSink::PlaybackStatus state) {
29+
(void) param;
30+
status = state;
31+
}
32+
33+
void setup() {
34+
Serial.begin(115200);
35+
delay(3000);
36+
Serial.printf("Starting, connect to the PicoW and start playing music\n");
37+
Serial.printf("Use BOOTSEL to pause/resume playback\n");
38+
a2dp.setName("PicoW Boom 00:00:00:00:00:00");
39+
a2dp.setConsumer(new BluetoothAudioConsumerPWM(pwm));
40+
a2dp.onVolume(volumeCB);
41+
a2dp.onConnect(connectCB);
42+
a2dp.onPlaybackStatus(playbackCB);
43+
a2dp.begin();
44+
}
45+
46+
void loop() {
47+
if (BOOTSEL) {
48+
__lockBluetooth();
49+
if (status == A2DPSink::PAUSED) {
50+
a2dp.play();
51+
Serial.printf("Resuming\n");
52+
} else if (status == A2DPSink::PLAYING) {
53+
a2dp.pause();
54+
Serial.printf("Pausing\n");
55+
}
56+
__unlockBluetooth();
57+
while (BOOTSEL);
58+
}
59+
}

libraries/BluetoothAudio/examples/A2DPSource/A2DPSource.ino

+12-10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <BluetoothAudio.h>
55
#include "raw.h"
66

7+
A2DPSource a2dp;
8+
79
int16_t pcm[64 * 2];
810
uint32_t phase = 0;
911
volatile uint32_t fr = 32;
@@ -39,7 +41,7 @@ void volumeCB(void *param, int pct) {
3941
void connectCB(void *param, bool connected) {
4042
(void) param;
4143
if (connected) {
42-
Serial.printf("A2DP connection started to %s\n", bd_addr_to_str(A2DPSource.getSinkAddress()));
44+
Serial.printf("A2DP connection started to %s\n", bd_addr_to_str(a2dp.getSinkAddress()));
4345
} else {
4446
Serial.printf("A2DP connection stopped\n");
4547
}
@@ -67,29 +69,29 @@ void fillPCM() {
6769

6870
void setup() {
6971
delay(2000);
70-
A2DPSource.onAVRCP(avrcpCB);
71-
A2DPSource.onVolume(volumeCB);
72-
A2DPSource.onConnect(connectCB);
73-
A2DPSource.begin();
72+
a2dp.onAVRCP(avrcpCB);
73+
a2dp.onVolume(volumeCB);
74+
a2dp.onConnect(connectCB);
75+
a2dp.begin();
7476
Serial.printf("Starting, press BOOTSEL to pair to first found speaker\n");
7577
Serial.printf("Use the forward button on speaker to change tones\n");
7678
Serial.printf("Use the reverse button on speaker to alternate between tones and Au Claire De La Lune\n");
7779
Serial.printf("Use the play button on speaker to pause/unpause the tone\n");
7880
}
7981

8082
void loop() {
81-
while ((size_t)A2DPSource.availableForWrite() > sizeof(pcm)) {
83+
while ((size_t)a2dp.availableForWrite() > sizeof(pcm)) {
8284
fillPCM();
83-
A2DPSource.write((const uint8_t *)pcm, sizeof(pcm));
85+
a2dp.write((const uint8_t *)pcm, sizeof(pcm));
8486
}
8587
if (BOOTSEL) {
8688
while (BOOTSEL) {
8789
delay(1);
8890
}
89-
A2DPSource.disconnect();
90-
A2DPSource.clearPairing();
91+
a2dp.disconnect();
92+
a2dp.clearPairing();
9193
Serial.printf("Connecting...");
92-
if (A2DPSource.connect()) {
94+
if (a2dp.connect()) {
9395
Serial.printf("Connected!\n");
9496
} else {
9597
Serial.printf("Failed! :(\n");

libraries/BluetoothAudio/keywords.txt

+22-2
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,22 @@
66
# Datatypes (KEYWORD1)
77
#######################################
88

9+
BluetoothAudio KEYWORD1
10+
BluetoothHCI KEYWORD1
911
A2DPSource KEYWORD1
1012
BTDeviceInfo KEYWORD1
13+
BluetoothAudioConsumer KEYWORD1
14+
BluetoothAudioConsumerI2S KEYWORD1
15+
BluetoothAudioConsumerPWM KEYWORD1
16+
A2DPSink KEYWORD1
1117

1218
#######################################
1319
# Methods and Functions (KEYWORD2)
1420
#######################################
1521
begin KEYWORD2
1622
end KEYWORD2
1723

24+
setConsumer KEYWORD2
1825
setFrequency KEYWORD2
1926
setName KEYWORD2
2027
setsetBufferSize KEYWORD2
@@ -26,14 +33,24 @@ connected KEYWORD2
2633
disconnect KEYWORD2
2734
clearPairing KEYWORD2
2835
connect KEYWORD2
29-
connect KEYWORD2
30-
connect KEYWORD2
36+
37+
play KEYWORD2
38+
stop KEYWORD2
39+
pause KEYWORD2
40+
fastForward KEYWORD2
41+
rewind KEYWORD2
42+
forward KEYWORD2
43+
backward KEYWORD2
44+
volumeUp KEYWORD2
45+
volumeDown KEYWORD2
46+
mute KEYWORD2
3147

3248
onTransmit KEYWORD2
3349
onAVRCP KEYWORD2
3450
onBattery KEYWORD2
3551
onVolume KEYWORD2
3652
onConnect KEYWORD2
53+
onPlaybackStatus KEYWORD2
3754

3855
# BTDeviceInfo
3956
deviceClass KEYWORD2
@@ -45,3 +62,6 @@ name KEYWORD2
4562
#######################################
4663
# Constants (LITERAL1)
4764
#######################################
65+
STOPPED LITERAL
66+
PLAYING LITERAL
67+
PAUSED LITERAL

0 commit comments

Comments
 (0)