Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ jobs:
- name: Galactic Unicorn
board: galactic
cmake-args: '-DDISPLAY_PATH=display/galactic/galactic_unicorn.cmake'
- name: Headless Unicorn
board: none
cmake-args: '-DHEADLESS=1'

runs-on: ubuntu-20.04

Expand Down
21 changes: 18 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()

include(bluetooth/bluetooth.cmake)

if(HEADLESS)
set(DISPLAY_NAME "Headless Unicorn")
else()
include(effect/rainbow_fft.cmake)
include(effect/classic_fft.cmake)

Expand All @@ -21,6 +25,8 @@ else()
message(WARNING "Using default display (display/galactic/galactic_unicorn.cmake)...")
include(display/galactic/galactic_unicorn.cmake)
endif()
endif()


add_executable(${NAME}
${CMAKE_CURRENT_LIST_DIR}/src/main.cpp
Expand All @@ -37,9 +43,6 @@ target_link_libraries(${NAME}
picow_bt_example_common
pico_audio_i2s
pico_multicore
display
rainbow_fft
classic_fft
)

message(WARNING "Display: ${DISPLAY_NAME}")
Expand All @@ -50,6 +53,18 @@ target_compile_definitions(${NAME} PRIVATE
BLUETOOTH_DEVICE_NAME="${DISPLAY_NAME}"
)

if(HEADLESS)
target_compile_definitions(${NAME} PRIVATE
HEADLESS=1
)
else()
target_link_libraries(${NAME}
display
rainbow_fft
classic_fft
)
endif()

pico_enable_stdio_usb(${NAME} 1)
pico_add_extra_outputs(${NAME})

Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,12 @@ For Cosmic Unicorn:
mkdir build.cosmic
cd build.cosmic
cmake .. -DPICO_SDK_PATH=../../pico-sdk -DPICO_EXTRAS_PATH=../../pico-extras -DPICO_BOARD=pico_w -DDISPLAY_PATH=display/cosmic/cosmic_unicorn.cmake -DCMAKE_BUILD_TYPE=Release
```

For Pico Audio, ie. without a display:

```bash
mkdir build.headless
cd build.headless
cmake .. -DPICO_SDK_PATH=../../pico-sdk -DPICO_EXTRAS_PATH=../../pico-extras -DPICO_BOARD=none -DHEADLESS=1 -DCMAKE_BUILD_TYPE=Release
```
2 changes: 1 addition & 1 deletion src/a2dp_sink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,7 @@ static void stdin_process(char cmd){

switch (cmd){
case 'b':
status = a2dp_sink_establish_stream(device_addr, stream_endpoint->a2dp_local_seid, &a2dp_connection->a2dp_cid);
status = a2dp_sink_establish_stream(device_addr, /*stream_endpoint->a2dp_local_seid, */&a2dp_connection->a2dp_cid);
printf(" - Create AVDTP connection to addr %s, and local seid %d, cid 0x%02x.\n",
bd_addr_to_str(device_addr), a2dp_connection->a2dp_local_seid, a2dp_connection->a2dp_cid);
break;
Expand Down
47 changes: 34 additions & 13 deletions src/btstack_audio_pico.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "pico/multicore.h"
#include "pico/sync.h"

#ifndef HEADLESS
#include "display.hpp"
#include "effect.hpp"
#include "lib/fixed_fft.hpp"
Expand All @@ -78,10 +79,28 @@ uint32_t core1_stack[512];
int16_t effect_buf[SAMPLE_COUNT] = {0};
#endif

#ifdef EFFECTS_ON_CORE1
auto_init_mutex(core1_effect_update);

void core1_entry() {
while(1) {
mutex_enter_blocking(&core1_effect_update);
effects[0]->update(effect_buf, SAMPLE_COUNT);
mutex_exit(&core1_effect_update);
}
}
#endif

#else
// If display is disabled, we'll set the sample count to the same as fixed_fft.hpp does anyway.
constexpr unsigned int SAMPLE_COUNT = 1024u;
#define DRIVER_POLL_INTERVAL_MS 5

#endif

static constexpr unsigned int BUFFERS_PER_FFT_SAMPLE = 2;
static constexpr unsigned int SAMPLES_PER_AUDIO_BUFFER = SAMPLE_COUNT / BUFFERS_PER_FFT_SAMPLE;


// client
static void (*playback_callback)(int16_t * buffer, uint16_t num_samples);

Expand All @@ -99,18 +118,6 @@ static uint8_t btstack_audio_pico_channel_count;
static uint8_t btstack_volume;
static uint8_t btstack_last_sample_idx;

auto_init_mutex(core1_effect_update);

#ifdef EFFECTS_ON_CORE1
void core1_entry() {
while(1) {
mutex_enter_blocking(&core1_effect_update);
effects[0]->update(effect_buf, SAMPLE_COUNT);
mutex_exit(&core1_effect_update);
}
}
#endif

static audio_buffer_pool_t *init_audio(uint32_t sample_frequency, uint8_t channel_count) {

// num channels requested by application
Expand Down Expand Up @@ -147,6 +154,7 @@ static audio_buffer_pool_t *init_audio(uint32_t sample_frequency, uint8_t channe
assert(ok);
(void)ok;

#ifndef HEADLESS
effects.push_back(&rainbow_fft);
effects.push_back(&classic_fft);

Expand All @@ -159,6 +167,8 @@ static audio_buffer_pool_t *init_audio(uint32_t sample_frequency, uint8_t channe

#ifdef EFFECTS_ON_CORE1
multicore_launch_core1_with_stack(core1_entry, core1_stack, core1_stack_len);
#endif

#endif

return producer_pool;
Expand All @@ -171,32 +181,41 @@ static void btstack_audio_pico_sink_fill_buffers(void){
break;
}

#ifndef HEADLESS
if (!gpio_get(Display::SWITCH_A)) {
current_effect = 0;
}

if (!gpio_get(Display::SWITCH_B)) {
current_effect = 1;
}
#endif

int16_t * buffer16 = (int16_t *) audio_buffer->buffer->bytes;
(*playback_callback)(buffer16, audio_buffer->max_sample_count);

#ifndef HEADLESS
#ifndef EFFECTS_ON_CORE1
effects[current_effect]->update(buffer16, SAMPLE_COUNT);
#endif

#ifdef EFFECTS_ON_CORE1
mutex_enter_blocking(&core1_effect_update);
#endif
#endif

for (auto i = 0u; i < SAMPLE_COUNT; i++) {
#ifndef HEADLESS
#ifdef EFFECTS_ON_CORE1
effect_buf[i] = buffer16[i];
#endif
#endif
buffer16[i] = (int32_t(buffer16[i]) * int32_t(btstack_volume)) >> 8;
}
#ifndef HEADLESS
#ifdef EFFECTS_ON_CORE1
mutex_exit(&core1_effect_update);
#endif
#endif

// duplicate samples for mono
Expand Down Expand Up @@ -267,7 +286,9 @@ static void btstack_audio_pico_sink_stop_stream(void){
// state
btstack_audio_pico_sink_active = false;

#ifndef HEADLESS
display.clear();
#endif
}

static void btstack_audio_pico_sink_close(void){
Expand Down