Add Bluetooth examples
Co-authored-by: Peter Harper <77111776+peterharperuk@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.12)
|
|||||||
# Pull in SDK (must be before project)
|
# Pull in SDK (must be before project)
|
||||||
include(pico_sdk_import.cmake)
|
include(pico_sdk_import.cmake)
|
||||||
|
|
||||||
|
include(pico_extras_import_optional.cmake)
|
||||||
|
|
||||||
project(pico_examples C CXX ASM)
|
project(pico_examples C CXX ASM)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|||||||
95
README.md
95
README.md
@@ -117,15 +117,15 @@ These examples are for the Pico W, and are only available for `PICO_BOARD=pico_w
|
|||||||
|
|
||||||
App|Description
|
App|Description
|
||||||
---|---
|
---|---
|
||||||
[picow_access_point](pico_w/access_point)| Starts a WiFi access point, and fields DHCP requests.
|
[picow_access_point](pico_w/wifi/access_point)| Starts a WiFi access point, and fields DHCP requests.
|
||||||
[picow_blink](pico_w/blink)| Blinks the on-board LED (which is connected via the WiFi chip).
|
[picow_blink](pico_w/wifi/blink)| Blinks the on-board LED (which is connected via the WiFi chip).
|
||||||
[picow_iperf_server](pico_w/iperf)| Runs an "iperf" server for WiFi speed testing.
|
[picow_iperf_server](pico_w/wifi/iperf)| Runs an "iperf" server for WiFi speed testing.
|
||||||
[picow_ntp_client](pico_w/ntp_client)| Connects to an NTP server to fetch and display the current time.
|
[picow_ntp_client](pico_w/wifi/ntp_client)| Connects to an NTP server to fetch and display the current time.
|
||||||
[picow_tcp_client](pico_w/tcp_client)| A simple TCP client. You can run [python_test_tcp_server.py](pico_w/python_test_tcp/python_test_tcp_server.py) for it to connect to.
|
[picow_tcp_client](pico_w/wifi/tcp_client)| A simple TCP client. You can run [python_test_tcp_server.py](pico_w/wifi/python_test_tcp/python_test_tcp_server.py) for it to connect to.
|
||||||
[picow_tcp_server](pico_w/tcp_server)| A simple TCP server. You can use [python_test_tcp_client.py](pico_w/python_test_tcp/python_test_tcp_client.py) to connect to it.
|
[picow_tcp_server](pico_w/wifi/tcp_server)| A simple TCP server. You can use [python_test_tcp_client.py](pico_w//wifi/python_test_tcp/python_test_tcp_client.py) to connect to it.
|
||||||
[picow_tls_client](pico_w/tls_client)| Demonstrates how to make a HTTPS request using TLS.
|
[picow_tls_client](pico_w/wifi/tls_client)| Demonstrates how to make a HTTPS request using TLS.
|
||||||
[picow_wifi_scan](pico_w/wifi_scan)| Scans for WiFi networks and prints the results.
|
[picow_wifi_scan](pico_w/wifi/wifi_scan)| Scans for WiFi networks and prints the results.
|
||||||
[picow_udp_beacon](pico_w/udp_beacon)| A simple UDP transmitter.
|
[picow_udp_beacon](pico_w/wifi/udp_beacon)| A simple UDP transmitter.
|
||||||
|
|
||||||
#### FreeRTOS examples
|
#### FreeRTOS examples
|
||||||
|
|
||||||
@@ -134,10 +134,79 @@ to point to the FreeRTOS Kernel.
|
|||||||
|
|
||||||
App|Description
|
App|Description
|
||||||
---|---
|
---|---
|
||||||
[picow_freertos_iperf_server_nosys](pico_w/freertos/iperf)| Runs an "iperf" server for WiFi speed testing under FreeRTOS in NO_SYS=1 mode. The LED is blinked in another task
|
[picow_freertos_iperf_server_nosys](pico_w/wifi/freertos/iperf)| Runs an "iperf" server for WiFi speed testing under FreeRTOS in NO_SYS=1 mode. The LED is blinked in another task
|
||||||
[picow_freertos_iperf_server_sys](pico_w/freertos/iperf)| Runs an "iperf" server for WiFi speed testing under FreeRTOS in NO_SYS=0 (i.e. full FreeRTOS integration) mode. The LED is blinked in another task
|
[picow_freertos_iperf_server_sys](pico_w/wifi/freertos/iperf)| Runs an "iperf" server for WiFi speed testing under FreeRTOS in NO_SYS=0 (i.e. full FreeRTOS integration) mode. The LED is blinked in another task
|
||||||
[picow_freertos_ping_nosys](pico_w/freertos/ping)| Runs the lwip-contrib/apps/ping test app under FreeRTOS in NO_SYS=1 mode.
|
[picow_freertos_ping_nosys](pico_w/wifi/freertos/ping)| Runs the lwip-contrib/apps/ping test app under FreeRTOS in NO_SYS=1 mode.
|
||||||
[picow_freertos_ping_sys](pico_w/freertos/ping)| Runs the lwip-contrib/apps/ping test app under FreeRTOS in NO_SYS=0 (i.e. full FreeRTOS integration) mode. The test app uses the lwIP _socket_ API in this case.
|
[picow_freertos_ping_sys](pico_w/wifi/freertos/ping)| Runs the lwip-contrib/apps/ping test app under FreeRTOS in NO_SYS=0 (i.e. full FreeRTOS integration) mode. The test app uses the lwIP _socket_ API in this case.
|
||||||
|
|
||||||
|
### Pico W Bluetooth
|
||||||
|
|
||||||
|
These examples are for the Pico W, and are only available for `PICO_BOARD=pico_w`.
|
||||||
|
They are examples from the Blue Kitchen Bluetooth stack, see [here](https://bluekitchen-gmbh.com/btstack/#examples/examples/index.html) for a full description.
|
||||||
|
|
||||||
|
By default, the Bluetooth examples are only built in one "mode" only (*background*, *poll*, or *freertos*), with the
|
||||||
|
default being *background*. This can be changed by passing `-DBTSTACK_EXAMPLE_TYPE=poll` etc. to `CMake`, or all
|
||||||
|
examples can be built (which may be slow) by passing `-DBTSTACK_EXAMPLE_TYPE=all`
|
||||||
|
Freertos versions can only be built if `FREERTOS_KERNEL_PATH` is defined.
|
||||||
|
|
||||||
|
App|Description
|
||||||
|
---|---
|
||||||
|
[picow_bt_example_a2dp_sink_demo](https://github.com/bluekitchen/btstack/tree/master/example/a2dp_sink_demo.c)|A2DP Sink - Receive Audio Stream and Control Playback.
|
||||||
|
[picow_bt_example_a2dp_source_demo](https://github.com/bluekitchen/btstack/tree/master/example/a2dp_source_demo.c)|A2DP Source - Stream Audio and Control Volume.
|
||||||
|
[picow_bt_example_ancs_client_demo](https://github.com/bluekitchen/btstack/tree/master/example/ancs_client_demo.c)|LE ANCS Client - Apple Notification Service.
|
||||||
|
[picow_bt_example_att_delayed_response](https://github.com/bluekitchen/btstack/tree/master/example/att_delayed_response.c)|LE Peripheral - Delayed Response.
|
||||||
|
[picow_bt_example_audio_duplex](https://github.com/bluekitchen/btstack/tree/master/example/audio_duplex.c)|Audio Driver - Forward Audio from Source to Sink.
|
||||||
|
[picow_bt_example_avrcp_browsing_client](https://github.com/bluekitchen/btstack/tree/master/example/avrcp_browsing_client.c)|AVRCP Browsing - Browse Media Players and Media Information.
|
||||||
|
[picow_bt_example_dut_mode_classic](https://github.com/bluekitchen/btstack/tree/master/example/dut_mode_classic.c)|Testing - Enable Device Under Test (DUT.c) Mode for Classic.
|
||||||
|
[picow_bt_example_gap_dedicated_bonding](https://github.com/bluekitchen/btstack/tree/master/example/gap_dedicated_bonding.c)|GAP bonding
|
||||||
|
[picow_bt_example_gap_inquiry](https://github.com/bluekitchen/btstack/tree/master/example/gap_inquiry.c)|GAP Classic Inquiry.
|
||||||
|
[picow_bt_example_gap_le_advertisements](https://github.com/bluekitchen/btstack/tree/master/example/gap_le_advertisements.c)|GAP LE Advertisements Scanner.
|
||||||
|
[picow_bt_example_gap_link_keys](https://github.com/bluekitchen/btstack/tree/master/example/gap_link_keys.c)|GAP Link Key Management (Classic.c).
|
||||||
|
[picow_bt_example_gatt_battery_query](https://github.com/bluekitchen/btstack/tree/master/example/gatt_battery_query.c)|GATT Battery Service Client.
|
||||||
|
[picow_bt_example_gatt_browser](https://github.com/bluekitchen/btstack/tree/master/example/gatt_browser.c)|GATT Client - Discover Primary Services.
|
||||||
|
[picow_bt_example_gatt_counter](https://github.com/bluekitchen/btstack/tree/master/example/gatt_counter.c)|GATT Server - Heartbeat Counter over GATT.
|
||||||
|
[picow_bt_example_gatt_device_information_query](https://github.com/bluekitchen/btstack/tree/master/example/gatt_device_information_query.c)|GATT Device Information Service Client.
|
||||||
|
[picow_bt_example_gatt_heart_rate_client](https://github.com/bluekitchen/btstack/tree/master/example/gatt_heart_rate_client.c)|GATT Heart Rate Sensor Client.
|
||||||
|
[picow_bt_example_gatt_streamer_server](https://github.com/bluekitchen/btstack/tree/master/example/gatt_streamer_server.c)|Performance - Stream Data over GATT (Server.c).
|
||||||
|
[picow_bt_example_hfp_ag_demo](https://github.com/bluekitchen/btstack/tree/master/example/hfp_ag_demo.c)|HFP AG - Audio Gateway.
|
||||||
|
[picow_bt_example_hfp_hf_demo](https://github.com/bluekitchen/btstack/tree/master/example/hfp_hf_demo.c)|HFP HF - Hands-Free.
|
||||||
|
[picow_bt_example_hid_host_demo](https://github.com/bluekitchen/btstack/tree/master/example/hid_host_demo.c)|HID Host Classic.
|
||||||
|
[picow_bt_example_hid_keyboard_demo](https://github.com/bluekitchen/btstack/tree/master/example/hid_keyboard_demo.c)|HID Keyboard Classic.
|
||||||
|
[picow_bt_example_hid_mouse_demo](https://github.com/bluekitchen/btstack/tree/master/example/hid_mouse_demo.c)|HID Mouse Classic.
|
||||||
|
[picow_bt_example_hog_boot_host_demo](https://github.com/bluekitchen/btstack/tree/master/example/hog_boot_host_demo.c)|HID Boot Host LE.
|
||||||
|
[picow_bt_example_hog_host_demo](https://github.com/bluekitchen/btstack/tree/master/example/hog_host_demo.c)|HID Host LE.
|
||||||
|
[picow_bt_example_hog_keyboard_demo](https://github.com/bluekitchen/btstack/tree/master/example/hog_keyboard_demo.c)|HID Keyboard LE.
|
||||||
|
[picow_bt_example_hog_mouse_demo](https://github.com/bluekitchen/btstack/tree/master/example/hog_mouse_demo.c)|HID Mouse LE.
|
||||||
|
[picow_bt_example_hsp_ag_demo](https://github.com/bluekitchen/btstack/tree/master/example/hsp_ag_demo.c)|HSP AG - Audio Gateway.
|
||||||
|
[picow_bt_example_hsp_hs_demo](https://github.com/bluekitchen/btstack/tree/master/example/hsp_hs_demo.c)|HSP HS - Headset.
|
||||||
|
[picow_bt_example_le_credit_based_flow_control_mode_client](https://github.com/bluekitchen/btstack/tree/master/example/le_credit_based_flow_control_mode_client.c)|LE Credit-Based Flow-Control Mode Client - Send Data over L2CAP.
|
||||||
|
[picow_bt_example_le_credit_based_flow_control_mode_server](https://github.com/bluekitchen/btstack/tree/master/example/le_credit_based_flow_control_mode_server.c)|LE Credit-Based Flow-Control Mode Server - Receive data over L2CAP.
|
||||||
|
[picow_bt_example_led_counter](https://github.com/bluekitchen/btstack/tree/master/example/led_counter.c)|Hello World - Blinking a LED without Bluetooth.
|
||||||
|
[picow_bt_example_le_mitm](https://github.com/bluekitchen/btstack/tree/master/example/le_mitm.c)|LE Man-in-the-Middle Tool.
|
||||||
|
[picow_bt_example_le_streamer_client](https://github.com/bluekitchen/btstack/tree/master/example/le_streamer_client.c)|Performance - Stream Data over GATT (Client.c).
|
||||||
|
[picow_bt_example_mod_player](https://github.com/bluekitchen/btstack/tree/master/example/mod_player.c)|Audio Driver - Play 80's MOD Song.
|
||||||
|
[picow_bt_example_nordic_spp_le_counter](https://github.com/bluekitchen/btstack/tree/master/example/nordic_spp_le_counter.c)|LE Nordic SPP-like Heartbeat Server.
|
||||||
|
[picow_bt_example_nordic_spp_le_streamer](https://github.com/bluekitchen/btstack/tree/master/example/nordic_spp_le_streamer.c)|LE Nordic SPP-like Streamer Server.
|
||||||
|
[picow_bt_example_sdp_general_query](https://github.com/bluekitchen/btstack/tree/master/example/sdp_general_query.c)|SDP Client - Query Remote SDP Records.
|
||||||
|
[picow_bt_example_sdp_rfcomm_query](https://github.com/bluekitchen/btstack/tree/master/example/sdp_rfcomm_query.c)|SDP Client - Query RFCOMM SDP record.
|
||||||
|
[picow_bt_example_sine_player](https://github.com/bluekitchen/btstack/tree/master/example/sine_player.c)|Audio Driver - Play Sine.
|
||||||
|
[picow_bt_example_sm_pairing_central](https://github.com/bluekitchen/btstack/tree/master/example/sm_pairing_central.c)|LE Central - Test Pairing Methods.
|
||||||
|
[picow_bt_example_sm_pairing_peripheral](https://github.com/bluekitchen/btstack/tree/master/example/sm_pairing_peripheral.c)|LE Peripheral - Test Pairing Methods.
|
||||||
|
[picow_bt_example_spp_and_gatt_counter](https://github.com/bluekitchen/btstack/tree/master/example/spp_and_gatt_counter.c)|Dual Mode - SPP and LE Counter.
|
||||||
|
[picow_bt_example_spp_and_gatt_streamer](https://github.com/bluekitchen/btstack/tree/master/example/spp_and_gatt_streamer.c)|Dual Mode - SPP and LE streamer.
|
||||||
|
[picow_bt_example_spp_counter](https://github.com/bluekitchen/btstack/tree/master/example/spp_counter.c)|SPP Server - Heartbeat Counter over RFCOMM.
|
||||||
|
[picow_bt_example_spp_flowcontrol](https://github.com/bluekitchen/btstack/tree/master/example/spp_flowcontrol.c)|SPP Server - RFCOMM Flow Control.
|
||||||
|
[picow_bt_example_spp_streamer_client](https://github.com/bluekitchen/btstack/tree/master/example/spp_streamer_client.c)|Performance - Stream Data over SPP (Client.c).
|
||||||
|
[picow_bt_example_spp_streamer](https://github.com/bluekitchen/btstack/tree/master/example/spp_streamer.c)|Performance - Stream Data over SPP (Server.c).
|
||||||
|
[picow_bt_example_ublox_spp_le_counter](pico_w/bt/ublox_spp_le_counter.c)|LE u-blox SPP-like Heartbeat Server.
|
||||||
|
|
||||||
|
Some Standalone Bluetooth examples (without all the common example build infrastructure) are also available:
|
||||||
|
|
||||||
|
App|Description
|
||||||
|
---|---
|
||||||
|
[picow_ble_temp_sensor](pico_w/bt/standalone)|Reads from the on board temperature sensor and sends notifications via BLE
|
||||||
|
[picow_ble_temp_sensor_with_wifi](pico_w/bt/standalone)|Same as above but also connects to Wi-Fi and starts an "iperf" server
|
||||||
|
[picow_ble_temp_reader](pico_w/bt/standalone)|Connects to on of the above "sensors" and reads the temperature
|
||||||
|
|
||||||
### PIO
|
### PIO
|
||||||
|
|
||||||
|
|||||||
59
pico_extras_import_optional.cmake
Normal file
59
pico_extras_import_optional.cmake
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# This is a copy of <PICO_EXTRAS_PATH>/external/pico_extras_import.cmake
|
||||||
|
|
||||||
|
# This can be dropped into an external project to help locate pico-extras
|
||||||
|
# It should be include()ed prior to project()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_EXTRAS_PATH} AND (NOT PICO_EXTRAS_PATH))
|
||||||
|
set(PICO_EXTRAS_PATH $ENV{PICO_EXTRAS_PATH})
|
||||||
|
message("Using PICO_EXTRAS_PATH from environment ('${PICO_EXTRAS_PATH}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_EXTRAS_FETCH_FROM_GIT} AND (NOT PICO_EXTRAS_FETCH_FROM_GIT))
|
||||||
|
set(PICO_EXTRAS_FETCH_FROM_GIT $ENV{PICO_EXTRAS_FETCH_FROM_GIT})
|
||||||
|
message("Using PICO_EXTRAS_FETCH_FROM_GIT from environment ('${PICO_EXTRAS_FETCH_FROM_GIT}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_EXTRAS_FETCH_FROM_GIT_PATH} AND (NOT PICO_EXTRAS_FETCH_FROM_GIT_PATH))
|
||||||
|
set(PICO_EXTRAS_FETCH_FROM_GIT_PATH $ENV{PICO_EXTRAS_FETCH_FROM_GIT_PATH})
|
||||||
|
message("Using PICO_EXTRAS_FETCH_FROM_GIT_PATH from environment ('${PICO_EXTRAS_FETCH_FROM_GIT_PATH}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (NOT PICO_EXTRAS_PATH)
|
||||||
|
if (PICO_EXTRAS_FETCH_FROM_GIT)
|
||||||
|
include(FetchContent)
|
||||||
|
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||||
|
if (PICO_EXTRAS_FETCH_FROM_GIT_PATH)
|
||||||
|
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||||
|
endif ()
|
||||||
|
FetchContent_Declare(
|
||||||
|
pico_extras
|
||||||
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-extras
|
||||||
|
GIT_TAG master
|
||||||
|
)
|
||||||
|
if (NOT pico_extras)
|
||||||
|
message("Downloading Raspberry Pi Pico Extras")
|
||||||
|
FetchContent_Populate(pico_extras)
|
||||||
|
set(PICO_EXTRAS_PATH ${pico_extras_SOURCE_DIR})
|
||||||
|
endif ()
|
||||||
|
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||||
|
else ()
|
||||||
|
if (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../pico-extras")
|
||||||
|
set(PICO_EXTRAS_PATH ${PICO_SDK_PATH}/../pico-extras)
|
||||||
|
message("Defaulting PICO_EXTRAS_PATH as sibling of PICO_SDK_PATH: ${PICO_EXTRAS_PATH}")
|
||||||
|
endif()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (PICO_EXTRAS_PATH)
|
||||||
|
set(PICO_EXTRAS_PATH "${PICO_EXTRAS_PATH}" CACHE PATH "Path to the PICO EXTRAS")
|
||||||
|
set(PICO_EXTRAS_FETCH_FROM_GIT "${PICO_EXTRAS_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of PICO EXTRAS from git if not otherwise locatable")
|
||||||
|
set(PICO_EXTRAS_FETCH_FROM_GIT_PATH "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download EXTRAS")
|
||||||
|
|
||||||
|
get_filename_component(PICO_EXTRAS_PATH "${PICO_EXTRAS_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||||
|
if (NOT EXISTS ${PICO_EXTRAS_PATH})
|
||||||
|
message(FATAL_ERROR "Directory '${PICO_EXTRAS_PATH}' not found")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_EXTRAS_PATH ${PICO_EXTRAS_PATH} CACHE PATH "Path to the PICO EXTRAS" FORCE)
|
||||||
|
add_subdirectory(${PICO_EXTRAS_PATH} pico_extras)
|
||||||
|
endif()
|
||||||
@@ -18,27 +18,11 @@ if (PICO_CYW43_SUPPORTED) # set by PICO_BOARD=pico_w
|
|||||||
set(WIFI_SSID "${WIFI_SSID}" CACHE INTERNAL "WiFi SSID for examples")
|
set(WIFI_SSID "${WIFI_SSID}" CACHE INTERNAL "WiFi SSID for examples")
|
||||||
set(WIFI_PASSWORD "${WIFI_PASSWORD}" CACHE INTERNAL "WiFi password for examples")
|
set(WIFI_PASSWORD "${WIFI_PASSWORD}" CACHE INTERNAL "WiFi password for examples")
|
||||||
|
|
||||||
add_subdirectory(blink)
|
add_subdirectory(wifi)
|
||||||
add_subdirectory(wifi_scan)
|
if (NOT TARGET pico_btstack_base)
|
||||||
add_subdirectory(access_point)
|
message("Skipping Pico W Bluetooth examples as support is not available")
|
||||||
|
|
||||||
if ("${WIFI_SSID}" STREQUAL "")
|
|
||||||
message("Skipping some Pico W examples as WIFI_SSID is not defined")
|
|
||||||
elseif ("${WIFI_PASSWORD}" STREQUAL "")
|
|
||||||
message("Skipping some Pico W examples as WIFI_PASSWORD is not defined")
|
|
||||||
else()
|
else()
|
||||||
add_subdirectory(iperf)
|
add_subdirectory(bt)
|
||||||
add_subdirectory(ntp_client)
|
|
||||||
add_subdirectory(tcp_client)
|
|
||||||
add_subdirectory(tcp_server)
|
|
||||||
add_subdirectory(freertos)
|
|
||||||
add_subdirectory(udp_beacon)
|
|
||||||
|
|
||||||
if (NOT PICO_MBEDTLS_PATH)
|
|
||||||
message("Skipping tls examples as PICO_MBEDTLS_PATH is not defined")
|
|
||||||
else()
|
|
||||||
add_subdirectory(tls_client)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
398
pico_w/bt/CMakeLists.txt
Normal file
398
pico_w/bt/CMakeLists.txt
Normal file
@@ -0,0 +1,398 @@
|
|||||||
|
add_subdirectory(standalone)
|
||||||
|
|
||||||
|
set(BTSTACK_ROOT ${PICO_SDK_PATH}/lib/btstack)
|
||||||
|
set(BTSTACK_EXAMPLE_PATH ${BTSTACK_ROOT}/example)
|
||||||
|
set(BTSTACK_3RD_PARTY_PATH ${BTSTACK_ROOT}/3rd-party)
|
||||||
|
set(BT_EXAMPLE_COMMON_DIR "${CMAKE_CURRENT_LIST_DIR}")
|
||||||
|
|
||||||
|
if (NOT PICO_EXTRAS_PATH)
|
||||||
|
message("Skipping some Pico W BTstack examples that require pico-extras")
|
||||||
|
else()
|
||||||
|
add_library(pico_btstack_audio_example INTERFACE)
|
||||||
|
target_sources(pico_btstack_audio_example INTERFACE
|
||||||
|
${PICO_BTSTACK_PATH}/src/btstack_audio.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/btstack_audio_pico.c
|
||||||
|
)
|
||||||
|
target_link_libraries(pico_btstack_audio_example INTERFACE
|
||||||
|
pico_audio_i2s
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# mod player used by a2dp_source_demo and mod_player and demo song
|
||||||
|
add_library(pico_btstack_hxcmod_player INTERFACE)
|
||||||
|
target_sources(pico_btstack_hxcmod_player INTERFACE
|
||||||
|
${BTSTACK_3RD_PARTY_PATH}/hxcmod-player/hxcmod.c
|
||||||
|
${BTSTACK_3RD_PARTY_PATH}/hxcmod-player/mods/nao-deceased_by_disease.c
|
||||||
|
)
|
||||||
|
target_include_directories(pico_btstack_hxcmod_player INTERFACE
|
||||||
|
${BTSTACK_3RD_PARTY_PATH}/hxcmod-player
|
||||||
|
${BTSTACK_3RD_PARTY_PATH}/hxcmod-player/mods
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(pico_btstack_sco_demo_util INTERFACE)
|
||||||
|
target_sources(pico_btstack_sco_demo_util INTERFACE
|
||||||
|
# sco demo utils
|
||||||
|
${BTSTACK_EXAMPLE_PATH}/sco_demo_util.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Adds common stuff for all the examples
|
||||||
|
add_library(picow_bt_example_common INTERFACE)
|
||||||
|
target_sources(picow_bt_example_common INTERFACE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/picow_bt_example_common.c
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_bt_example_common INTERFACE
|
||||||
|
pico_stdlib
|
||||||
|
pico_btstack_ble
|
||||||
|
pico_btstack_classic
|
||||||
|
pico_btstack_cyw43
|
||||||
|
)
|
||||||
|
target_include_directories(picow_bt_example_common INTERFACE
|
||||||
|
${BT_EXAMPLE_COMMON_DIR}/config # Use our own config
|
||||||
|
${BTSTACK_EXAMPLE_PATH}/
|
||||||
|
)
|
||||||
|
target_compile_definitions(picow_bt_example_common INTERFACE
|
||||||
|
PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS=3000
|
||||||
|
#WANT_HCI_DUMP=1 # This enables btstack debug
|
||||||
|
#ENABLE_SEGGER_RTT=1
|
||||||
|
)
|
||||||
|
if (TARGET pico_btstack_audio_example)
|
||||||
|
target_link_libraries(picow_bt_example_common INTERFACE
|
||||||
|
pico_btstack_audio_example
|
||||||
|
)
|
||||||
|
target_compile_definitions(picow_bt_example_common INTERFACE
|
||||||
|
TEST_AUDIO=1
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Adds stuff needed for cyw43 lwip
|
||||||
|
add_library(picow_bt_example_cyw43_lwip INTERFACE)
|
||||||
|
target_link_libraries(picow_bt_example_cyw43_lwip INTERFACE
|
||||||
|
picow_bt_example_common
|
||||||
|
)
|
||||||
|
target_compile_definitions(picow_bt_example_cyw43_lwip INTERFACE
|
||||||
|
WIFI_SSID=\"${WIFI_SSID}\"
|
||||||
|
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
|
||||||
|
CYW43_LWIP=1
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_bt_example_cyw43_lwip INTERFACE
|
||||||
|
pico_lwip_iperf
|
||||||
|
)
|
||||||
|
target_include_directories(picow_bt_example_cyw43_lwip INTERFACE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/../wifi # for our common lwipopts
|
||||||
|
)
|
||||||
|
|
||||||
|
# disables cyw43 lwip
|
||||||
|
add_library(picow_bt_example_no_cyw43_lwip INTERFACE)
|
||||||
|
target_link_libraries(picow_bt_example_no_cyw43_lwip INTERFACE
|
||||||
|
picow_bt_example_common
|
||||||
|
)
|
||||||
|
target_compile_definitions(picow_bt_example_no_cyw43_lwip INTERFACE
|
||||||
|
CYW43_LWIP=0
|
||||||
|
)
|
||||||
|
|
||||||
|
# variant: no cyw43 lwip | poll
|
||||||
|
add_library(picow_bt_example_no_cyw43_lwip_poll INTERFACE)
|
||||||
|
target_sources(picow_bt_example_no_cyw43_lwip_poll INTERFACE
|
||||||
|
${BT_EXAMPLE_COMMON_DIR}/picow_bt_example_poll.c
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_bt_example_no_cyw43_lwip_poll INTERFACE
|
||||||
|
picow_bt_example_no_cyw43_lwip
|
||||||
|
pico_cyw43_arch_poll
|
||||||
|
)
|
||||||
|
|
||||||
|
# variant: cyw43 lwip | poll
|
||||||
|
add_library(picow_bt_example_cyw43_lwip_poll INTERFACE)
|
||||||
|
target_sources(picow_bt_example_cyw43_lwip_poll INTERFACE
|
||||||
|
${BT_EXAMPLE_COMMON_DIR}/picow_bt_example_poll.c
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_bt_example_cyw43_lwip_poll INTERFACE
|
||||||
|
picow_bt_example_cyw43_lwip
|
||||||
|
pico_cyw43_arch_lwip_poll
|
||||||
|
)
|
||||||
|
|
||||||
|
# variant: btstack lwip | poll
|
||||||
|
add_library(picow_bt_example_btstack_lwip_poll INTERFACE)
|
||||||
|
target_sources(picow_bt_example_btstack_lwip_poll INTERFACE
|
||||||
|
${BT_EXAMPLE_COMMON_DIR}/picow_bt_example_poll.c
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_bt_example_btstack_lwip_poll INTERFACE
|
||||||
|
picow_bt_example_no_cyw43_lwip
|
||||||
|
pico_cyw43_arch_poll
|
||||||
|
pico_lwip_nosys
|
||||||
|
pico_btstack_bnep_lwip
|
||||||
|
)
|
||||||
|
target_include_directories(picow_bt_example_btstack_lwip_poll INTERFACE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/../wifi # for our common lwipopts
|
||||||
|
)
|
||||||
|
|
||||||
|
# variant: no cyw43 lwip | background
|
||||||
|
add_library(picow_bt_example_no_cyw43_lwip_background INTERFACE)
|
||||||
|
target_sources(picow_bt_example_no_cyw43_lwip_background INTERFACE
|
||||||
|
${BT_EXAMPLE_COMMON_DIR}/picow_bt_example_background.c
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_bt_example_no_cyw43_lwip_background INTERFACE
|
||||||
|
picow_bt_example_no_cyw43_lwip
|
||||||
|
pico_cyw43_arch_threadsafe_background
|
||||||
|
)
|
||||||
|
|
||||||
|
# variant: cyw43 lwip | background
|
||||||
|
add_library(picow_bt_example_cyw43_lwip_background INTERFACE)
|
||||||
|
target_sources(picow_bt_example_cyw43_lwip_background INTERFACE
|
||||||
|
${BT_EXAMPLE_COMMON_DIR}/picow_bt_example_background.c
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_bt_example_cyw43_lwip_background INTERFACE
|
||||||
|
picow_bt_example_cyw43_lwip
|
||||||
|
pico_cyw43_arch_lwip_threadsafe_background
|
||||||
|
)
|
||||||
|
|
||||||
|
# variant: btstack lwip | background
|
||||||
|
add_library(picow_bt_example_btstack_lwip_background INTERFACE)
|
||||||
|
target_sources(picow_bt_example_btstack_lwip_background INTERFACE
|
||||||
|
${BT_EXAMPLE_COMMON_DIR}/picow_bt_example_background.c
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_bt_example_btstack_lwip_background INTERFACE
|
||||||
|
picow_bt_example_no_cyw43_lwip
|
||||||
|
pico_cyw43_arch_threadsafe_background
|
||||||
|
pico_lwip_nosys
|
||||||
|
pico_btstack_bnep_lwip
|
||||||
|
)
|
||||||
|
target_include_directories(picow_bt_example_btstack_lwip_background INTERFACE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/../wifi # for our common lwipopts
|
||||||
|
)
|
||||||
|
|
||||||
|
if (FREERTOS_KERNEL_PATH OR DEFINED ENV{FREERTOS_KERNEL_PATH})
|
||||||
|
include(FreeRTOS_Kernel_import.cmake)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (TARGET FreeRTOS-Kernel)
|
||||||
|
# common freertos stuff
|
||||||
|
add_library(picow_bt_example_common_freertos INTERFACE)
|
||||||
|
target_sources(picow_bt_example_common_freertos INTERFACE
|
||||||
|
${BT_EXAMPLE_COMMON_DIR}/picow_bt_example_freertos.c
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_bt_example_common_freertos INTERFACE
|
||||||
|
picow_bt_example_common
|
||||||
|
FreeRTOS-Kernel-Heap4 # FreeRTOS kernel and dynamic heap
|
||||||
|
)
|
||||||
|
target_compile_definitions(picow_bt_example_common_freertos INTERFACE
|
||||||
|
CYW43_TASK_STACK_SIZE=1024
|
||||||
|
NO_SYS=0
|
||||||
|
)
|
||||||
|
target_include_directories(picow_bt_example_common_freertos INTERFACE
|
||||||
|
${FREERTOS_KERNEL_PATH}/include
|
||||||
|
${FREERTOS_KERNEL_PATH}/portable/ThirdParty/GCC/RP2040/include
|
||||||
|
)
|
||||||
|
|
||||||
|
# variant: no cyw43 lwip | freertos
|
||||||
|
add_library(picow_bt_example_no_cyw43_lwip_freertos INTERFACE)
|
||||||
|
target_link_libraries(picow_bt_example_no_cyw43_lwip_freertos INTERFACE
|
||||||
|
picow_bt_example_common_freertos
|
||||||
|
picow_bt_example_no_cyw43_lwip
|
||||||
|
pico_cyw43_arch_sys_freertos
|
||||||
|
)
|
||||||
|
|
||||||
|
# variant: cyw43 lwip | freertos
|
||||||
|
add_library(picow_bt_example_cyw43_lwip_freertos INTERFACE)
|
||||||
|
target_link_libraries(picow_bt_example_cyw43_lwip_freertos INTERFACE
|
||||||
|
picow_bt_example_common_freertos
|
||||||
|
picow_bt_example_cyw43_lwip
|
||||||
|
pico_cyw43_arch_lwip_sys_freertos
|
||||||
|
)
|
||||||
|
target_compile_definitions(picow_bt_example_cyw43_lwip_freertos INTERFACE
|
||||||
|
HAVE_LWIP=1 # stops btstack calling lwip_init
|
||||||
|
)
|
||||||
|
|
||||||
|
# variant: btstack lwip | freertos
|
||||||
|
add_library(picow_bt_example_btstack_lwip_freertos INTERFACE)
|
||||||
|
target_link_libraries(picow_bt_example_btstack_lwip_freertos INTERFACE
|
||||||
|
picow_bt_example_common_freertos
|
||||||
|
picow_bt_example_no_cyw43_lwip
|
||||||
|
pico_cyw43_arch_sys_freertos
|
||||||
|
pico_btstack_bnep_lwip_sys_freertos
|
||||||
|
pico_lwip_freertos
|
||||||
|
)
|
||||||
|
target_include_directories(picow_bt_example_btstack_lwip_freertos INTERFACE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/../wifi # for our common lwipopts
|
||||||
|
)
|
||||||
|
target_compile_definitions(picow_bt_example_btstack_lwip_freertos INTERFACE
|
||||||
|
HAVE_LWIP=1 # stops btstack calling lwip_init
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Common stuff for all examples. Pass the example name
|
||||||
|
function(picow_bt_example_common NAME)
|
||||||
|
if (NOT TARGET picow_bt_example_common_${NAME})
|
||||||
|
add_library(picow_bt_example_common_${NAME} INTERFACE)
|
||||||
|
target_sources(picow_bt_example_common_${NAME} INTERFACE
|
||||||
|
# actual example
|
||||||
|
${BTSTACK_EXAMPLE_PATH}/${NAME}.c
|
||||||
|
)
|
||||||
|
if (EXISTS "${BTSTACK_EXAMPLE_PATH}/${NAME}.gatt")
|
||||||
|
pico_btstack_make_gatt_header(picow_bt_example_common_${NAME} INTERFACE ${BTSTACK_EXAMPLE_PATH}/${NAME}.gatt)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# The type of example to build
|
||||||
|
if(NOT DEFINED BTSTACK_EXAMPLE_TYPE)
|
||||||
|
set(BTSTACK_EXAMPLE_TYPE "background")
|
||||||
|
endif()
|
||||||
|
if ((NOT BTSTACK_EXAMPLE_TYPE STREQUAL "poll") AND
|
||||||
|
(NOT BTSTACK_EXAMPLE_TYPE STREQUAL "background") AND
|
||||||
|
(NOT BTSTACK_EXAMPLE_TYPE STREQUAL "freertos") AND
|
||||||
|
(NOT BTSTACK_EXAMPLE_TYPE STREQUAL "all"))
|
||||||
|
message(FATAL_ERROR "Unknown BTSTACK_EXAMPLE_TYPE '${BTSTACK_EXAMPLE_TYPE}'; valid options are 'poll', 'background', 'freertos' or 'all'")
|
||||||
|
endif()
|
||||||
|
set(BTSTACK_EXAMPLE_TYPE "${BTSTACK_EXAMPLE_TYPE}" CACHE INTERNAL "BT stack example type (poll|background|freertos|all)")
|
||||||
|
|
||||||
|
# Add an poll example, pass btstack example name, target name, variant lib and extra libs
|
||||||
|
function(picow_bt_example_poll NAME TARGET_NAME VARIANT_LIB)
|
||||||
|
if ("${BTSTACK_EXAMPLE_TYPE}" STREQUAL "poll" OR "${BTSTACK_EXAMPLE_TYPE}" STREQUAL "all")
|
||||||
|
picow_bt_example_common(${NAME})
|
||||||
|
add_executable(${TARGET_NAME}_poll)
|
||||||
|
target_link_libraries(${TARGET_NAME}_poll PRIVATE
|
||||||
|
picow_bt_example_common_${NAME}
|
||||||
|
${VARIANT_LIB}
|
||||||
|
${ARGN} # extra libs
|
||||||
|
)
|
||||||
|
pico_add_extra_outputs(${TARGET_NAME}_poll)
|
||||||
|
example_auto_set_url(${TARGET_NAME}_poll)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Add an background example, pass btstack example name, target name, variant lib and extra libs
|
||||||
|
function(picow_bt_example_background NAME TARGET_NAME VARIANT_LIB)
|
||||||
|
if ("${BTSTACK_EXAMPLE_TYPE}" STREQUAL "background" OR "${BTSTACK_EXAMPLE_TYPE}" STREQUAL "all")
|
||||||
|
picow_bt_example_common(${NAME})
|
||||||
|
add_executable(${TARGET_NAME}_background)
|
||||||
|
target_link_libraries(${TARGET_NAME}_background PRIVATE
|
||||||
|
picow_bt_example_common_${NAME}
|
||||||
|
${VARIANT_LIB}
|
||||||
|
${ARGN} # extra libs
|
||||||
|
)
|
||||||
|
pico_add_extra_outputs(${TARGET_NAME}_background)
|
||||||
|
example_auto_set_url(${TARGET_NAME}_background)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Add a freertos example, pass btstack example name, target name, variant lib and extra libs
|
||||||
|
function(picow_bt_example_freertos NAME TARGET_NAME VARIANT_LIB)
|
||||||
|
if ("${BTSTACK_EXAMPLE_TYPE}" STREQUAL "freertos" OR "${BTSTACK_EXAMPLE_TYPE}" STREQUAL "all")
|
||||||
|
if (TARGET FreeRTOS-Kernel)
|
||||||
|
picow_bt_example_common(${NAME})
|
||||||
|
add_executable(${TARGET_NAME}_freertos)
|
||||||
|
target_link_libraries(${TARGET_NAME}_freertos PRIVATE
|
||||||
|
picow_bt_example_common_${NAME}
|
||||||
|
${VARIANT_LIB}
|
||||||
|
${ARGN} # extra libs
|
||||||
|
)
|
||||||
|
pico_add_extra_outputs(${TARGET_NAME}_freertos)
|
||||||
|
example_auto_set_url(${TARGET_NAME}_freertos)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# The default name of the bt example target
|
||||||
|
function(picow_bt_example_target_name NAME RET)
|
||||||
|
SET(${RET} "picow_bt_example_${NAME}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Make a btstack example, NAME should match source file in lib/btstack/example
|
||||||
|
# Extra parameters indicate extra libraries to link to
|
||||||
|
function(picow_bt_example NAME)
|
||||||
|
picow_bt_example_target_name(${NAME} TARGET_NAME)
|
||||||
|
picow_bt_example_poll(${NAME} ${TARGET_NAME} picow_bt_example_no_cyw43_lwip_poll ${ARGN})
|
||||||
|
picow_bt_example_background(${NAME} ${TARGET_NAME} picow_bt_example_no_cyw43_lwip_background ${ARGN})
|
||||||
|
picow_bt_example_freertos(${NAME} ${TARGET_NAME} picow_bt_example_no_cyw43_lwip_freertos ${ARGN})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# List of examples from btstack
|
||||||
|
include(${BTSTACK_ROOT}/example/CMakeLists.txt)
|
||||||
|
|
||||||
|
# Full list of bluetooth examples
|
||||||
|
set(BTSTACK_EXAMPLES
|
||||||
|
${EXAMPLES_GENERAL}
|
||||||
|
${EXAMPLES_CLASSIC_ONLY}
|
||||||
|
${EXAMPLES_LE_ONLY}
|
||||||
|
${EXAMPLES_DUAL_MODE}
|
||||||
|
pan_lwip_http_server
|
||||||
|
)
|
||||||
|
|
||||||
|
# These examples run wifi and bt at the same time
|
||||||
|
if (WIFI_SSID AND WIFI_PASSWORD)
|
||||||
|
list(APPEND BTSTACK_EXAMPLES
|
||||||
|
gatt_counter_with_wifi
|
||||||
|
gatt_streamer_server_with_wifi
|
||||||
|
#spp_streamer_with_wifi
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Extra examples that are not that interesting or a bit tricky to run
|
||||||
|
# They are not built unless BTSTACK_EXAMPLES_ALL=1
|
||||||
|
set(BTSTACK_EXAMPLES_ADDITIONAL
|
||||||
|
ancs_client_demo
|
||||||
|
att_delayed_response
|
||||||
|
avrcp_browsing_client
|
||||||
|
dut_mode_classic
|
||||||
|
gap_dedicated_bonding
|
||||||
|
gap_link_keys
|
||||||
|
le_credit_based_flow_control_mode_client
|
||||||
|
le_credit_based_flow_control_mode_server
|
||||||
|
le_mitm
|
||||||
|
led_counter
|
||||||
|
sdp_bnep_query
|
||||||
|
sdp_general_query
|
||||||
|
spp_flowcontrol
|
||||||
|
sdp_rfcomm_query
|
||||||
|
spp_and_gatt_counter
|
||||||
|
spp_and_gatt_streamer
|
||||||
|
hfp_ag_demo
|
||||||
|
hsp_ag_demo
|
||||||
|
hfp_hf_demo
|
||||||
|
hsp_hs_demo
|
||||||
|
mod_player
|
||||||
|
sine_player
|
||||||
|
ublox_spp_le_counter
|
||||||
|
nordic_spp_le_streamer
|
||||||
|
nordic_spp_le_counter
|
||||||
|
hog_boot_host_demo
|
||||||
|
gatt_battery_query
|
||||||
|
gatt_browser
|
||||||
|
gatt_device_information_query
|
||||||
|
le_streamer_client
|
||||||
|
)
|
||||||
|
|
||||||
|
# These examples will only be built if pico-extras exists
|
||||||
|
set(BTSTACK_EXAMPLES_NEED_EXTRAS
|
||||||
|
a2dp_sink_demo
|
||||||
|
hfp_hf_demo
|
||||||
|
hfp_ag_demo
|
||||||
|
hsp_ag_demo
|
||||||
|
hsp_hs_demo
|
||||||
|
mod_player
|
||||||
|
sine_player
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add examples
|
||||||
|
set(BTSTACK_EXAMPLE_COUNT 0)
|
||||||
|
list(REMOVE_DUPLICATES BTSTACK_EXAMPLES)
|
||||||
|
foreach(NAME ${BTSTACK_EXAMPLES})
|
||||||
|
# Ignore if sub folder not found
|
||||||
|
if (NOT IS_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/${NAME})
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
|
# Ignore example if it needs pico-extras and pico-extras could not be found
|
||||||
|
if (NOT PICO_EXTRAS_PATH AND ${NAME} IN_LIST BTSTACK_EXAMPLES_NEED_EXTRAS)
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
|
# Ignore less interesting examples if BTSTACK_EXAMPLES_ALL=1 is not set
|
||||||
|
if (NOT BTSTACK_EXAMPLES_ALL AND ${NAME} IN_LIST BTSTACK_EXAMPLES_ADDITIONAL)
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
|
# add example
|
||||||
|
add_subdirectory(${NAME})
|
||||||
|
MATH(EXPR BTSTACK_EXAMPLE_COUNT "${BTSTACK_EXAMPLE_COUNT}+1")
|
||||||
|
endforeach()
|
||||||
|
message("Adding ${BTSTACK_EXAMPLE_COUNT} BTstack examples of type '${BTSTACK_EXAMPLE_TYPE}'")
|
||||||
|
|
||||||
|
suppress_btstack_warnings()
|
||||||
7
pico_w/bt/a2dp_sink_demo/CMakeLists.txt
Normal file
7
pico_w/bt/a2dp_sink_demo/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
add_library(a2dp_sink_demo_pins INTERFACE)
|
||||||
|
target_compile_definitions(a2dp_sink_demo_pins INTERFACE
|
||||||
|
PICO_AUDIO_I2S_DATA_PIN=9
|
||||||
|
PICO_AUDIO_I2S_CLOCK_PIN_BASE=10
|
||||||
|
)
|
||||||
|
|
||||||
|
picow_bt_example(a2dp_sink_demo pico_btstack_sbc_decoder a2dp_sink_demo_pins)
|
||||||
1
pico_w/bt/a2dp_source_demo/CMakeLists.txt
Normal file
1
pico_w/bt/a2dp_source_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(a2dp_source_demo pico_btstack_hxcmod_player pico_btstack_sbc_encoder)
|
||||||
1
pico_w/bt/ancs_client_demo/CMakeLists.txt
Normal file
1
pico_w/bt/ancs_client_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(ancs_client_demo)
|
||||||
1
pico_w/bt/att_delayed_response/CMakeLists.txt
Normal file
1
pico_w/bt/att_delayed_response/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(att_delayed_response)
|
||||||
1
pico_w/bt/avrcp_browsing_client/CMakeLists.txt
Normal file
1
pico_w/bt/avrcp_browsing_client/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(avrcp_browsing_client)
|
||||||
208
pico_w/bt/btstack_audio_pico.c
Normal file
208
pico_w/bt/btstack_audio_pico.c
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 BlueKitchen GmbH
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the names of
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
* 4. Any redistribution, use, or modification is done solely for
|
||||||
|
* personal benefit and not for any commercial purpose or for
|
||||||
|
* monetary gain.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
|
||||||
|
* GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Please inquire about commercial licensing options at
|
||||||
|
* contact@bluekitchen-gmbh.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BTSTACK_FILE__ "btstack_audio_pico.c"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* btstack_audio_pico.c
|
||||||
|
*
|
||||||
|
* Implementation of btstack_audio.h using pico_i2s
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btstack_config.h"
|
||||||
|
|
||||||
|
#include "btstack_debug.h"
|
||||||
|
#include "btstack_audio.h"
|
||||||
|
#include "btstack_run_loop.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <hardware/dma.h>
|
||||||
|
|
||||||
|
#include "pico/audio_i2s.h"
|
||||||
|
|
||||||
|
#define DRIVER_POLL_INTERVAL_MS 5
|
||||||
|
#define SAMPLES_PER_BUFFER 512
|
||||||
|
|
||||||
|
// client
|
||||||
|
static void (*playback_callback)(int16_t * buffer, uint16_t num_samples);
|
||||||
|
|
||||||
|
// timer to fill output ring buffer
|
||||||
|
static btstack_timer_source_t driver_timer_sink;
|
||||||
|
|
||||||
|
|
||||||
|
static bool btstack_audio_pico_sink_active;
|
||||||
|
|
||||||
|
// from pico-playground/audio/sine_wave/sine_wave.c
|
||||||
|
|
||||||
|
static audio_format_t btstack_audio_pico_audio_format;
|
||||||
|
static audio_buffer_format_t btstack_audio_pico_producer_format;
|
||||||
|
static audio_buffer_pool_t * btstack_audio_pico_audio_buffer_pool;
|
||||||
|
static uint8_t btstack_audio_pico_channel_count;
|
||||||
|
|
||||||
|
static audio_buffer_pool_t *init_audio(uint32_t sample_frequency, uint8_t channel_count) {
|
||||||
|
|
||||||
|
// num channels requested by application
|
||||||
|
btstack_audio_pico_channel_count = channel_count;
|
||||||
|
|
||||||
|
// always use stereo
|
||||||
|
btstack_audio_pico_audio_format.format = AUDIO_BUFFER_FORMAT_PCM_S16;
|
||||||
|
btstack_audio_pico_audio_format.sample_freq = sample_frequency;
|
||||||
|
btstack_audio_pico_audio_format.channel_count = 2;
|
||||||
|
|
||||||
|
btstack_audio_pico_producer_format.format = &btstack_audio_pico_audio_format;
|
||||||
|
btstack_audio_pico_producer_format.sample_stride = 2 * 2;
|
||||||
|
|
||||||
|
audio_buffer_pool_t * producer_pool = audio_new_producer_pool(&btstack_audio_pico_producer_format, 3, SAMPLES_PER_BUFFER); // todo correct size
|
||||||
|
|
||||||
|
audio_i2s_config_t config;
|
||||||
|
config.data_pin = PICO_AUDIO_I2S_DATA_PIN;
|
||||||
|
config.clock_pin_base = PICO_AUDIO_I2S_CLOCK_PIN_BASE;
|
||||||
|
config.dma_channel = (int8_t) dma_claim_unused_channel(true);
|
||||||
|
config.pio_sm = 0;
|
||||||
|
|
||||||
|
// audio_i2s_setup claims the channel again https://github.com/raspberrypi/pico-extras/issues/48
|
||||||
|
dma_channel_unclaim(config.dma_channel);
|
||||||
|
const audio_format_t * output_format = audio_i2s_setup(&btstack_audio_pico_audio_format, &config);
|
||||||
|
if (!output_format) {
|
||||||
|
panic("PicoAudio: Unable to open audio device.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ok = audio_i2s_connect(producer_pool);
|
||||||
|
assert(ok);
|
||||||
|
(void)ok;
|
||||||
|
|
||||||
|
return producer_pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btstack_audio_pico_sink_fill_buffers(void){
|
||||||
|
while (true){
|
||||||
|
audio_buffer_t * audio_buffer = take_audio_buffer(btstack_audio_pico_audio_buffer_pool, false);
|
||||||
|
if (audio_buffer == NULL){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t * buffer16 = (int16_t *) audio_buffer->buffer->bytes;
|
||||||
|
(*playback_callback)(buffer16, audio_buffer->max_sample_count);
|
||||||
|
|
||||||
|
// duplicate samples for mono
|
||||||
|
if (btstack_audio_pico_channel_count == 1){
|
||||||
|
int16_t i;
|
||||||
|
for (i = SAMPLES_PER_BUFFER - 1 ; i >= 0; i--){
|
||||||
|
buffer16[2*i ] = buffer16[i];
|
||||||
|
buffer16[2*i+1] = buffer16[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_buffer->sample_count = audio_buffer->max_sample_count;
|
||||||
|
give_audio_buffer(btstack_audio_pico_audio_buffer_pool, audio_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void driver_timer_handler_sink(btstack_timer_source_t * ts){
|
||||||
|
|
||||||
|
// refill
|
||||||
|
btstack_audio_pico_sink_fill_buffers();
|
||||||
|
|
||||||
|
// re-set timer
|
||||||
|
btstack_run_loop_set_timer(ts, DRIVER_POLL_INTERVAL_MS);
|
||||||
|
btstack_run_loop_add_timer(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int btstack_audio_pico_sink_init(
|
||||||
|
uint8_t channels,
|
||||||
|
uint32_t samplerate,
|
||||||
|
void (*playback)(int16_t * buffer, uint16_t num_samples)
|
||||||
|
){
|
||||||
|
btstack_assert(playback != NULL);
|
||||||
|
btstack_assert(channels != 0);
|
||||||
|
|
||||||
|
playback_callback = playback;
|
||||||
|
|
||||||
|
btstack_audio_pico_audio_buffer_pool = init_audio(samplerate, channels);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btstack_audio_pico_sink_set_volume(uint8_t volume){
|
||||||
|
UNUSED(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btstack_audio_pico_sink_start_stream(void){
|
||||||
|
|
||||||
|
// pre-fill HAL buffers
|
||||||
|
btstack_audio_pico_sink_fill_buffers();
|
||||||
|
|
||||||
|
// start timer
|
||||||
|
btstack_run_loop_set_timer_handler(&driver_timer_sink, &driver_timer_handler_sink);
|
||||||
|
btstack_run_loop_set_timer(&driver_timer_sink, DRIVER_POLL_INTERVAL_MS);
|
||||||
|
btstack_run_loop_add_timer(&driver_timer_sink);
|
||||||
|
|
||||||
|
// state
|
||||||
|
btstack_audio_pico_sink_active = true;
|
||||||
|
|
||||||
|
audio_i2s_set_enabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btstack_audio_pico_sink_stop_stream(void){
|
||||||
|
|
||||||
|
audio_i2s_set_enabled(false);
|
||||||
|
|
||||||
|
// stop timer
|
||||||
|
btstack_run_loop_remove_timer(&driver_timer_sink);
|
||||||
|
// state
|
||||||
|
btstack_audio_pico_sink_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btstack_audio_pico_sink_close(void){
|
||||||
|
// stop stream if needed
|
||||||
|
if (btstack_audio_pico_sink_active){
|
||||||
|
btstack_audio_pico_sink_stop_stream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const btstack_audio_sink_t btstack_audio_pico_sink = {
|
||||||
|
.init = &btstack_audio_pico_sink_init,
|
||||||
|
.set_volume = &btstack_audio_pico_sink_set_volume,
|
||||||
|
.start_stream = &btstack_audio_pico_sink_start_stream,
|
||||||
|
.stop_stream = &btstack_audio_pico_sink_stop_stream,
|
||||||
|
.close = &btstack_audio_pico_sink_close,
|
||||||
|
};
|
||||||
|
|
||||||
|
const btstack_audio_sink_t * btstack_audio_pico_sink_get_instance(void){
|
||||||
|
return &btstack_audio_pico_sink;
|
||||||
|
}
|
||||||
143
pico_w/bt/config/FreeRTOSConfig.h
Normal file
143
pico_w/bt/config/FreeRTOSConfig.h
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS V202111.00
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* http://www.FreeRTOS.org
|
||||||
|
* http://aws.amazon.com/freertos
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FREERTOS_CONFIG_H
|
||||||
|
#define FREERTOS_CONFIG_H
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Application specific definitions.
|
||||||
|
*
|
||||||
|
* These definitions should be adjusted for your particular hardware and
|
||||||
|
* application requirements.
|
||||||
|
*
|
||||||
|
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
|
||||||
|
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
|
||||||
|
*
|
||||||
|
* See http://www.freertos.org/a00110.html
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler Related */
|
||||||
|
#define configUSE_PREEMPTION 1
|
||||||
|
#define configUSE_TICKLESS_IDLE 0
|
||||||
|
#define configUSE_IDLE_HOOK 0
|
||||||
|
#define configUSE_TICK_HOOK 0
|
||||||
|
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
|
||||||
|
#define configMAX_PRIORITIES 32
|
||||||
|
#define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 1024
|
||||||
|
#define configUSE_16_BIT_TICKS 0
|
||||||
|
|
||||||
|
#define configIDLE_SHOULD_YIELD 1
|
||||||
|
|
||||||
|
/* Synchronization Related */
|
||||||
|
#define configUSE_MUTEXES 1
|
||||||
|
#define configUSE_RECURSIVE_MUTEXES 1
|
||||||
|
#define configUSE_APPLICATION_TASK_TAG 0
|
||||||
|
#define configUSE_COUNTING_SEMAPHORES 1
|
||||||
|
#define configQUEUE_REGISTRY_SIZE 8
|
||||||
|
#define configUSE_QUEUE_SETS 1
|
||||||
|
#define configUSE_TIME_SLICING 1
|
||||||
|
#define configUSE_NEWLIB_REENTRANT 0
|
||||||
|
// todo need this for lwip FreeRTOS sys_arch to compile
|
||||||
|
#define configENABLE_BACKWARD_COMPATIBILITY 1
|
||||||
|
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
|
||||||
|
|
||||||
|
/* System */
|
||||||
|
#define configSTACK_DEPTH_TYPE uint32_t
|
||||||
|
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
|
||||||
|
|
||||||
|
/* Memory allocation related definitions. */
|
||||||
|
#define configSUPPORT_STATIC_ALLOCATION 0
|
||||||
|
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||||
|
#define configTOTAL_HEAP_SIZE (128*1024)
|
||||||
|
#define configAPPLICATION_ALLOCATED_HEAP 0
|
||||||
|
|
||||||
|
/* Hook function related definitions. */
|
||||||
|
#define configCHECK_FOR_STACK_OVERFLOW 0
|
||||||
|
#define configUSE_MALLOC_FAILED_HOOK 0
|
||||||
|
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
|
||||||
|
|
||||||
|
/* Run time and task stats gathering related definitions. */
|
||||||
|
#define configGENERATE_RUN_TIME_STATS 0
|
||||||
|
#define configUSE_TRACE_FACILITY 1
|
||||||
|
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
|
||||||
|
|
||||||
|
/* Co-routine related definitions. */
|
||||||
|
#define configUSE_CO_ROUTINES 0
|
||||||
|
#define configMAX_CO_ROUTINE_PRIORITIES 1
|
||||||
|
|
||||||
|
/* Software timer related definitions. */
|
||||||
|
#define configUSE_TIMERS 1
|
||||||
|
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
|
||||||
|
#define configTIMER_QUEUE_LENGTH 10
|
||||||
|
#define configTIMER_TASK_STACK_DEPTH 1024
|
||||||
|
|
||||||
|
/* Interrupt nesting behaviour configuration. */
|
||||||
|
/*
|
||||||
|
#define configKERNEL_INTERRUPT_PRIORITY [dependent of processor]
|
||||||
|
#define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application]
|
||||||
|
#define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application]
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if FREE_RTOS_KERNEL_SMP // set by the RP2040 SMP port of FreeRTOS
|
||||||
|
/* SMP port only */
|
||||||
|
#define configNUM_CORES 2
|
||||||
|
#define configTICK_CORE 0
|
||||||
|
#define configRUN_MULTIPLE_PRIORITIES 1
|
||||||
|
#define configUSE_CORE_AFFINITY 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* RP2040 specific */
|
||||||
|
#define configSUPPORT_PICO_SYNC_INTEROP 1
|
||||||
|
#define configSUPPORT_PICO_TIME_INTEROP 1
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
/* Define to trap errors during development. */
|
||||||
|
#define configASSERT(x) assert(x)
|
||||||
|
|
||||||
|
/* Set the following definitions to 1 to include the API function, or zero
|
||||||
|
to exclude the API function. */
|
||||||
|
#define INCLUDE_vTaskPrioritySet 1
|
||||||
|
#define INCLUDE_uxTaskPriorityGet 1
|
||||||
|
#define INCLUDE_vTaskDelete 1
|
||||||
|
#define INCLUDE_vTaskSuspend 1
|
||||||
|
#define INCLUDE_vTaskDelayUntil 1
|
||||||
|
#define INCLUDE_vTaskDelay 1
|
||||||
|
#define INCLUDE_xTaskGetSchedulerState 1
|
||||||
|
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||||
|
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||||
|
#define INCLUDE_xTaskGetIdleTaskHandle 1
|
||||||
|
#define INCLUDE_eTaskGetState 1
|
||||||
|
#define INCLUDE_xTimerPendFunctionCall 1
|
||||||
|
#define INCLUDE_xTaskAbortDelay 1
|
||||||
|
#define INCLUDE_xTaskGetHandle 1
|
||||||
|
#define INCLUDE_xTaskResumeFromISR 1
|
||||||
|
#define INCLUDE_xQueueGetMutexHolder 1
|
||||||
|
|
||||||
|
/* A header file that defines trace macro can be included here. */
|
||||||
|
|
||||||
|
#endif /* FREERTOS_CONFIG_H */
|
||||||
|
|
||||||
77
pico_w/bt/config/btstack_config.h
Normal file
77
pico_w/bt/config/btstack_config.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#ifndef _PICO_BTSTACK_BTSTACK_CONFIG_H
|
||||||
|
#define _PICO_BTSTACK_BTSTACK_CONFIG_H
|
||||||
|
|
||||||
|
// BTstack features that can be enabled
|
||||||
|
#define ENABLE_LE_PERIPHERAL
|
||||||
|
#define ENABLE_LE_CENTRAL
|
||||||
|
#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
|
||||||
|
#define ENABLE_LOG_INFO
|
||||||
|
#define ENABLE_LOG_ERROR
|
||||||
|
#define ENABLE_PRINTF_HEXDUMP
|
||||||
|
#define ENABLE_SCO_OVER_HCI
|
||||||
|
|
||||||
|
// BTstack configuration. buffers, sizes, ...
|
||||||
|
#define HCI_OUTGOING_PRE_BUFFER_SIZE 4
|
||||||
|
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
|
||||||
|
#define HCI_ACL_CHUNK_SIZE_ALIGNMENT 4
|
||||||
|
#define MAX_NR_AVDTP_CONNECTIONS 1
|
||||||
|
#define MAX_NR_AVDTP_STREAM_ENDPOINTS 1
|
||||||
|
#define MAX_NR_AVRCP_CONNECTIONS 2
|
||||||
|
#define MAX_NR_BNEP_CHANNELS 1
|
||||||
|
#define MAX_NR_BNEP_SERVICES 1
|
||||||
|
#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2
|
||||||
|
#define MAX_NR_GATT_CLIENTS 1
|
||||||
|
#define MAX_NR_HCI_CONNECTIONS 2
|
||||||
|
#define MAX_NR_HID_HOST_CONNECTIONS 1
|
||||||
|
#define MAX_NR_HIDS_CLIENTS 1
|
||||||
|
#define MAX_NR_HFP_CONNECTIONS 1
|
||||||
|
#define MAX_NR_L2CAP_CHANNELS 4
|
||||||
|
#define MAX_NR_L2CAP_SERVICES 3
|
||||||
|
#define MAX_NR_RFCOMM_CHANNELS 1
|
||||||
|
#define MAX_NR_RFCOMM_MULTIPLEXERS 1
|
||||||
|
#define MAX_NR_RFCOMM_SERVICES 1
|
||||||
|
#define MAX_NR_SERVICE_RECORD_ITEMS 4
|
||||||
|
#define MAX_NR_SM_LOOKUP_ENTRIES 3
|
||||||
|
#define MAX_NR_WHITELIST_ENTRIES 16
|
||||||
|
#define MAX_NR_LE_DEVICE_DB_ENTRIES 16
|
||||||
|
|
||||||
|
// Limit number of ACL/SCO Buffer to use by stack to avoid cyw43 shared bus overrun
|
||||||
|
#define MAX_NR_CONTROLLER_ACL_BUFFERS 3
|
||||||
|
#define MAX_NR_CONTROLLER_SCO_PACKETS 3
|
||||||
|
|
||||||
|
// Enable and configure HCI Controller to Host Flow Control to avoid cyw43 shared bus overrun
|
||||||
|
#define ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
|
||||||
|
#define HCI_HOST_ACL_PACKET_LEN 1024
|
||||||
|
#define HCI_HOST_ACL_PACKET_NUM 3
|
||||||
|
#define HCI_HOST_SCO_PACKET_LEN 120
|
||||||
|
#define HCI_HOST_SCO_PACKET_NUM 3
|
||||||
|
|
||||||
|
// Link Key DB and LE Device DB using TLV on top of Flash Sector interface
|
||||||
|
#define NVM_NUM_DEVICE_DB_ENTRIES 16
|
||||||
|
#define NVM_NUM_LINK_KEYS 16
|
||||||
|
|
||||||
|
// We don't give btstack a malloc, so use a fixed-size ATT DB.
|
||||||
|
#define MAX_ATT_DB_SIZE 512
|
||||||
|
|
||||||
|
// BTstack HAL configuration
|
||||||
|
#define HAVE_EMBEDDED_TIME_MS
|
||||||
|
|
||||||
|
// map btstack_assert onto Pico SDK assert()
|
||||||
|
#define HAVE_ASSERT
|
||||||
|
|
||||||
|
// Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A).
|
||||||
|
#define HCI_RESET_RESEND_TIMEOUT_MS 1000
|
||||||
|
|
||||||
|
#define ENABLE_SOFTWARE_AES128
|
||||||
|
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
|
||||||
|
|
||||||
|
#define HAVE_BTSTACK_STDIN
|
||||||
|
|
||||||
|
// To get the audio demos working even with HCI dump at 115200, this truncates long ACL packetws
|
||||||
|
//#define HCI_DUMP_STDOUT_MAX_SIZE_ACL 100
|
||||||
|
|
||||||
|
#ifdef ENABLE_CLASSIC
|
||||||
|
#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_H
|
||||||
1
pico_w/bt/dut_mode_classic/CMakeLists.txt
Normal file
1
pico_w/bt/dut_mode_classic/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(dut_mode_classic)
|
||||||
1
pico_w/bt/gap_dedicated_bonding/CMakeLists.txt
Normal file
1
pico_w/bt/gap_dedicated_bonding/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(gap_dedicated_bonding)
|
||||||
1
pico_w/bt/gap_inquiry/CMakeLists.txt
Normal file
1
pico_w/bt/gap_inquiry/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(gap_inquiry)
|
||||||
1
pico_w/bt/gap_le_advertisements/CMakeLists.txt
Normal file
1
pico_w/bt/gap_le_advertisements/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(gap_le_advertisements)
|
||||||
1
pico_w/bt/gap_link_keys/CMakeLists.txt
Normal file
1
pico_w/bt/gap_link_keys/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(gap_link_keys)
|
||||||
1
pico_w/bt/gatt_battery_query/CMakeLists.txt
Normal file
1
pico_w/bt/gatt_battery_query/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(gatt_battery_query)
|
||||||
1
pico_w/bt/gatt_browser/CMakeLists.txt
Normal file
1
pico_w/bt/gatt_browser/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(gatt_browser)
|
||||||
1
pico_w/bt/gatt_counter/CMakeLists.txt
Normal file
1
pico_w/bt/gatt_counter/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(gatt_counter)
|
||||||
6
pico_w/bt/gatt_counter_with_wifi/CMakeLists.txt
Normal file
6
pico_w/bt/gatt_counter_with_wifi/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
set(NAME gatt_counter)
|
||||||
|
picow_bt_example_target_name(${NAME}_with_wifi TARGET_NAME)
|
||||||
|
|
||||||
|
picow_bt_example_poll(${NAME} ${TARGET_NAME} picow_bt_example_cyw43_lwip_poll)
|
||||||
|
picow_bt_example_background(${NAME} ${TARGET_NAME} picow_bt_example_cyw43_lwip_background)
|
||||||
|
picow_bt_example_freertos(${NAME} ${TARGET_NAME} picow_bt_example_cyw43_lwip_freertos)
|
||||||
1
pico_w/bt/gatt_device_information_query/CMakeLists.txt
Normal file
1
pico_w/bt/gatt_device_information_query/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(gatt_device_information_query)
|
||||||
1
pico_w/bt/gatt_heart_rate_client/CMakeLists.txt
Normal file
1
pico_w/bt/gatt_heart_rate_client/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(gatt_heart_rate_client)
|
||||||
1
pico_w/bt/gatt_streamer_server/CMakeLists.txt
Normal file
1
pico_w/bt/gatt_streamer_server/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(gatt_streamer_server)
|
||||||
6
pico_w/bt/gatt_streamer_server_with_wifi/CMakeLists.txt
Normal file
6
pico_w/bt/gatt_streamer_server_with_wifi/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
set(NAME gatt_streamer_server)
|
||||||
|
picow_bt_example_target_name(${NAME}_with_wifi TARGET_NAME)
|
||||||
|
|
||||||
|
picow_bt_example_poll(${NAME} ${TARGET_NAME} picow_bt_example_cyw43_lwip_poll)
|
||||||
|
picow_bt_example_background(${NAME} ${TARGET_NAME} picow_bt_example_cyw43_lwip_background)
|
||||||
|
picow_bt_example_freertos(${NAME} ${TARGET_NAME} picow_bt_example_cyw43_lwip_freertos)
|
||||||
1
pico_w/bt/hfp_ag_demo/CMakeLists.txt
Normal file
1
pico_w/bt/hfp_ag_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(hfp_ag_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder)
|
||||||
1
pico_w/bt/hfp_hf_demo/CMakeLists.txt
Normal file
1
pico_w/bt/hfp_hf_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(hfp_hf_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder)
|
||||||
1
pico_w/bt/hid_host_demo/CMakeLists.txt
Normal file
1
pico_w/bt/hid_host_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(hid_host_demo)
|
||||||
1
pico_w/bt/hid_keyboard_demo/CMakeLists.txt
Normal file
1
pico_w/bt/hid_keyboard_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(hid_keyboard_demo)
|
||||||
1
pico_w/bt/hid_mouse_demo/CMakeLists.txt
Normal file
1
pico_w/bt/hid_mouse_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(hid_mouse_demo)
|
||||||
1
pico_w/bt/hog_boot_host_demo/CMakeLists.txt
Normal file
1
pico_w/bt/hog_boot_host_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(hog_boot_host_demo)
|
||||||
1
pico_w/bt/hog_host_demo/CMakeLists.txt
Normal file
1
pico_w/bt/hog_host_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(hog_host_demo)
|
||||||
1
pico_w/bt/hog_keyboard_demo/CMakeLists.txt
Normal file
1
pico_w/bt/hog_keyboard_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(hog_keyboard_demo)
|
||||||
1
pico_w/bt/hog_mouse_demo/CMakeLists.txt
Normal file
1
pico_w/bt/hog_mouse_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(hog_mouse_demo)
|
||||||
1
pico_w/bt/hsp_ag_demo/CMakeLists.txt
Normal file
1
pico_w/bt/hsp_ag_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(hsp_ag_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder)
|
||||||
1
pico_w/bt/hsp_hs_demo/CMakeLists.txt
Normal file
1
pico_w/bt/hsp_hs_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(hsp_hs_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(le_credit_based_flow_control_mode_client)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(le_credit_based_flow_control_mode_server)
|
||||||
1
pico_w/bt/le_mitm/CMakeLists.txt
Normal file
1
pico_w/bt/le_mitm/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(le_mitm)
|
||||||
1
pico_w/bt/le_streamer_client/CMakeLists.txt
Normal file
1
pico_w/bt/le_streamer_client/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(le_streamer_client)
|
||||||
1
pico_w/bt/led_counter/CMakeLists.txt
Normal file
1
pico_w/bt/led_counter/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(led_counter)
|
||||||
1
pico_w/bt/mod_player/CMakeLists.txt
Normal file
1
pico_w/bt/mod_player/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(mod_player pico_btstack_hxcmod_player)
|
||||||
1
pico_w/bt/nordic_spp_le_counter/CMakeLists.txt
Normal file
1
pico_w/bt/nordic_spp_le_counter/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(nordic_spp_le_counter)
|
||||||
1
pico_w/bt/nordic_spp_le_streamer/CMakeLists.txt
Normal file
1
pico_w/bt/nordic_spp_le_streamer/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(nordic_spp_le_streamer)
|
||||||
13
pico_w/bt/pan_lwip_http_server/CMakeLists.txt
Normal file
13
pico_w/bt/pan_lwip_http_server/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
add_library(pan_lwip_dhserver INTERFACE)
|
||||||
|
target_sources(pan_lwip_dhserver INTERFACE
|
||||||
|
${BTSTACK_3RD_PARTY_PATH}/lwip/dhcp-server/dhserver.c
|
||||||
|
)
|
||||||
|
target_include_directories(pan_lwip_dhserver INTERFACE
|
||||||
|
${BTSTACK_3RD_PARTY_PATH}/lwip/dhcp-server
|
||||||
|
)
|
||||||
|
|
||||||
|
picow_bt_example_target_name(pan_lwip_http_server TARGET_NAME)
|
||||||
|
|
||||||
|
picow_bt_example_poll(pan_lwip_http_server ${TARGET_NAME} picow_bt_example_btstack_lwip_poll pan_lwip_dhserver pico_lwip_http)
|
||||||
|
picow_bt_example_background(pan_lwip_http_server ${TARGET_NAME} picow_bt_example_btstack_lwip_background pan_lwip_dhserver pico_lwip_http)
|
||||||
|
picow_bt_example_freertos(pan_lwip_http_server ${TARGET_NAME} picow_bt_example_btstack_lwip_freertos pan_lwip_dhserver pico_lwip_http)
|
||||||
1
pico_w/bt/pbap_client_demo/CMakeLists.txt
Normal file
1
pico_w/bt/pbap_client_demo/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(pbap_client_demo)
|
||||||
21
pico_w/bt/picow_bt_example_background.c
Normal file
21
pico_w/bt/picow_bt_example_background.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btstack_run_loop.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "picow_bt_example_common.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
int res = picow_bt_example_init();
|
||||||
|
if (res){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
picow_bt_example_main();
|
||||||
|
btstack_run_loop_execute();
|
||||||
|
}
|
||||||
101
pico_w/bt/picow_bt_example_common.c
Normal file
101
pico_w/bt/picow_bt_example_common.c
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btstack_audio.h"
|
||||||
|
#include "btstack_event.h"
|
||||||
|
#include "hal_led.h"
|
||||||
|
#include "pico/cyw43_arch.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
|
#if defined(WIFI_SSID) && defined(WIFI_PASSWORD)
|
||||||
|
#define TEST_BTWIFI 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TEST_BTWIFI
|
||||||
|
#include "lwip/ip4_addr.h"
|
||||||
|
#include "lwip/apps/lwiperf.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Start the btstack example
|
||||||
|
int btstack_main(int argc, const char * argv[]);
|
||||||
|
|
||||||
|
#if TEST_AUDIO
|
||||||
|
const btstack_audio_sink_t * btstack_audio_pico_sink_get_instance(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||||
|
|
||||||
|
static int led_state = 0;
|
||||||
|
|
||||||
|
void hal_led_toggle(void){
|
||||||
|
led_state = 1 - led_state;
|
||||||
|
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||||
|
UNUSED(size);
|
||||||
|
UNUSED(channel);
|
||||||
|
bd_addr_t local_addr;
|
||||||
|
if (packet_type != HCI_EVENT_PACKET) return;
|
||||||
|
switch(hci_event_packet_get_type(packet)){
|
||||||
|
case BTSTACK_EVENT_STATE:
|
||||||
|
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
|
||||||
|
gap_local_bd_addr(local_addr);
|
||||||
|
printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TEST_BTWIFI
|
||||||
|
static void iperf_report(void *arg, enum lwiperf_report_type report_type,
|
||||||
|
const ip_addr_t *local_addr, u16_t local_port, const ip_addr_t *remote_addr, u16_t remote_port,
|
||||||
|
u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec) {
|
||||||
|
static uint32_t total_iperf_megabytes = 0;
|
||||||
|
uint32_t mbytes = bytes_transferred / 1024 / 1024;
|
||||||
|
float mbits = bandwidth_kbitpsec / 1000.0;
|
||||||
|
total_iperf_megabytes += mbytes;
|
||||||
|
printf("Completed iperf transfer of %d MBytes @ %.1f Mbits/sec\n", mbytes, mbits);
|
||||||
|
printf("Total iperf megabytes since start %d Mbytes\n", total_iperf_megabytes);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int picow_bt_example_init(void) {
|
||||||
|
// initialize CYW43 driver architecture (will enable BT if/because CYW43_ENABLE_BLUETOOTH == 1)
|
||||||
|
if (cyw43_arch_init()) {
|
||||||
|
printf("failed to initialise cyw43_arch\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// inform about BTstack state
|
||||||
|
hci_event_callback_registration.callback = &packet_handler;
|
||||||
|
hci_add_event_handler(&hci_event_callback_registration);
|
||||||
|
|
||||||
|
// setup i2s audio for sink
|
||||||
|
#if TEST_AUDIO
|
||||||
|
btstack_audio_sink_set_instance(btstack_audio_pico_sink_get_instance());
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void picow_bt_example_main(void) {
|
||||||
|
|
||||||
|
btstack_main(0, NULL);
|
||||||
|
|
||||||
|
#if TEST_BTWIFI
|
||||||
|
uint32_t start_ms = to_ms_since_boot(get_absolute_time());
|
||||||
|
cyw43_arch_enable_sta_mode();
|
||||||
|
printf("Connecting to WiFi \"%s\"...\n", WIFI_SSID);
|
||||||
|
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
|
||||||
|
panic("failed to connect");
|
||||||
|
} else {
|
||||||
|
printf("Connected in %lus.\n", (to_ms_since_boot(get_absolute_time()) - start_ms) / 1000);
|
||||||
|
}
|
||||||
|
printf("\nReady, running iperf server at %s\n", ip4addr_ntoa(netif_ip4_addr(netif_list)));
|
||||||
|
lwiperf_start_tcp_server_default(&iperf_report, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
18
pico_w/bt/picow_bt_example_common.h
Normal file
18
pico_w/bt/picow_bt_example_common.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief Initialise BTstack example with cyw43
|
||||||
|
*
|
||||||
|
* \return 0 if ok
|
||||||
|
*/
|
||||||
|
int picow_bt_example_init(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief Run the BTstack example
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void picow_bt_example_main(void);
|
||||||
112
pico_w/bt/picow_bt_example_freertos.c
Normal file
112
pico_w/bt/picow_bt_example_freertos.c
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "pico/btstack_init.h"
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#include "picow_bt_example_common.h"
|
||||||
|
|
||||||
|
#if HAVE_LWIP
|
||||||
|
#include "pico/lwip_freertos.h"
|
||||||
|
#include "pico/cyw43_arch.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RUN_FREERTOS_ON_CORE
|
||||||
|
#define RUN_FREERTOS_ON_CORE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TEST_TASK_PRIORITY ( tskIDLE_PRIORITY + 2UL )
|
||||||
|
#define BLINK_TASK_PRIORITY ( tskIDLE_PRIORITY + 1UL )
|
||||||
|
|
||||||
|
#ifdef TEST_BLINK_TASK
|
||||||
|
void blink_task(__unused void *params) {
|
||||||
|
printf("blink_task starts\n");
|
||||||
|
while (true) {
|
||||||
|
#if 0 && configNUM_CORES > 1
|
||||||
|
static int last_core_id;
|
||||||
|
if (portGET_CORE_ID() != last_core_id) {
|
||||||
|
last_core_id = portGET_CORE_ID();
|
||||||
|
printf("blinking now from core %d\n", last_core_id);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
hal_led_toggle();
|
||||||
|
vTaskDelay(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main_task(__unused void *params) {
|
||||||
|
|
||||||
|
int res = picow_bt_example_init();
|
||||||
|
if (res){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're using lwip but not via cyw43 (e.g. pan) we have to call this
|
||||||
|
#if HAVE_LWIP && !CYW43_LWIP
|
||||||
|
lwip_freertos_init(cyw43_arch_async_context());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
picow_bt_example_main();
|
||||||
|
|
||||||
|
#ifdef TEST_BLINK_TASK
|
||||||
|
xTaskCreate(blink_task, "BlinkThread", configMINIMAL_STACK_SIZE, NULL, BLINK_TASK_PRIORITY, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
vTaskDelay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
pico_btstack_deinit();
|
||||||
|
|
||||||
|
#if HAVE_LWIP && !CYW43_LWIP
|
||||||
|
lwip_freertos_deinit(cyw43_arch_async_context());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void vLaunch( void) {
|
||||||
|
TaskHandle_t task;
|
||||||
|
xTaskCreate(main_task, "TestMainThread", 1024, NULL, TEST_TASK_PRIORITY, &task);
|
||||||
|
|
||||||
|
#if NO_SYS && configUSE_CORE_AFFINITY && configNUM_CORES > 1
|
||||||
|
// we must bind the main task to one core (well at least while the init is called)
|
||||||
|
// (note we only do this in NO_SYS mode, because cyw43_arch_freertos
|
||||||
|
// takes care of it otherwise)
|
||||||
|
vTaskCoreAffinitySet(task, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Start the tasks and timer running. */
|
||||||
|
vTaskStartScheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
/* Configure the hardware ready to run the demo. */
|
||||||
|
const char *rtos_name;
|
||||||
|
#if ( portSUPPORT_SMP == 1 )
|
||||||
|
rtos_name = "FreeRTOS SMP";
|
||||||
|
#else
|
||||||
|
rtos_name = "FreeRTOS";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( portSUPPORT_SMP == 1 ) && ( configNUM_CORES == 2 )
|
||||||
|
printf("Starting %s on both cores:\n", rtos_name);
|
||||||
|
vLaunch();
|
||||||
|
#elif ( RUN_FREE_RTOS_ON_CORE == 1 )
|
||||||
|
printf("Starting %s on core 1:\n", rtos_name);
|
||||||
|
multicore_launch_core1(vLaunch);
|
||||||
|
while (true);
|
||||||
|
#else
|
||||||
|
printf("Starting %s on core 0:\n", rtos_name);
|
||||||
|
vLaunch();
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
21
pico_w/bt/picow_bt_example_poll.c
Normal file
21
pico_w/bt/picow_bt_example_poll.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btstack_run_loop.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "picow_bt_example_common.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
int res = picow_bt_example_init();
|
||||||
|
if (res){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
picow_bt_example_main();
|
||||||
|
btstack_run_loop_execute();
|
||||||
|
}
|
||||||
1
pico_w/bt/sdp_bnep_query/CMakeLists.txt
Normal file
1
pico_w/bt/sdp_bnep_query/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(sdp_bnep_query)
|
||||||
1
pico_w/bt/sdp_general_query/CMakeLists.txt
Normal file
1
pico_w/bt/sdp_general_query/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(sdp_general_query)
|
||||||
1
pico_w/bt/sdp_rfcomm_query/CMakeLists.txt
Normal file
1
pico_w/bt/sdp_rfcomm_query/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(sdp_rfcomm_query)
|
||||||
1
pico_w/bt/sine_player/CMakeLists.txt
Normal file
1
pico_w/bt/sine_player/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(sine_player)
|
||||||
1
pico_w/bt/sm_pairing_central/CMakeLists.txt
Normal file
1
pico_w/bt/sm_pairing_central/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(sm_pairing_central)
|
||||||
1
pico_w/bt/sm_pairing_peripheral/CMakeLists.txt
Normal file
1
pico_w/bt/sm_pairing_peripheral/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(sm_pairing_peripheral)
|
||||||
1
pico_w/bt/spp_and_gatt_counter/CMakeLists.txt
Normal file
1
pico_w/bt/spp_and_gatt_counter/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(spp_and_gatt_counter)
|
||||||
1
pico_w/bt/spp_and_gatt_streamer/CMakeLists.txt
Normal file
1
pico_w/bt/spp_and_gatt_streamer/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(spp_and_gatt_streamer)
|
||||||
1
pico_w/bt/spp_counter/CMakeLists.txt
Normal file
1
pico_w/bt/spp_counter/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(spp_counter)
|
||||||
1
pico_w/bt/spp_flowcontrol/CMakeLists.txt
Normal file
1
pico_w/bt/spp_flowcontrol/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(spp_flowcontrol)
|
||||||
1
pico_w/bt/spp_streamer/CMakeLists.txt
Normal file
1
pico_w/bt/spp_streamer/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(spp_streamer)
|
||||||
1
pico_w/bt/spp_streamer_client/CMakeLists.txt
Normal file
1
pico_w/bt/spp_streamer_client/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(spp_streamer_client)
|
||||||
6
pico_w/bt/spp_streamer_with_wifi/CMakeLists.txt
Normal file
6
pico_w/bt/spp_streamer_with_wifi/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
set(NAME spp_streamer)
|
||||||
|
picow_bt_example_target_name(${NAME}_with_wifi TARGET_NAME)
|
||||||
|
|
||||||
|
picow_bt_example_poll(${NAME} ${TARGET_NAME} picow_bt_example_cyw43_lwip_poll)
|
||||||
|
picow_bt_example_background(${NAME} ${TARGET_NAME} picow_bt_example_cyw43_lwip_background)
|
||||||
|
picow_bt_example_freertos(${NAME} ${TARGET_NAME} picow_bt_example_cyw43_lwip_freertos)
|
||||||
68
pico_w/bt/standalone/CMakeLists.txt
Normal file
68
pico_w/bt/standalone/CMakeLists.txt
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Standalone example that reads from the on board temperature sensor and sends notifications via BLE
|
||||||
|
# Flashes slowly each second to show it's running
|
||||||
|
add_executable(picow_ble_temp_sensor
|
||||||
|
server.c server_common.c
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_ble_temp_sensor
|
||||||
|
pico_stdlib
|
||||||
|
pico_btstack_ble
|
||||||
|
pico_btstack_cyw43
|
||||||
|
pico_cyw43_arch_none
|
||||||
|
hardware_adc
|
||||||
|
)
|
||||||
|
target_include_directories(picow_ble_temp_sensor PRIVATE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR} # For btstack config
|
||||||
|
)
|
||||||
|
pico_btstack_make_gatt_header(picow_ble_temp_sensor PRIVATE "${CMAKE_CURRENT_LIST_DIR}/temp_sensor.gatt")
|
||||||
|
|
||||||
|
pico_add_extra_outputs(picow_ble_temp_sensor)
|
||||||
|
example_auto_set_url(picow_ble_temp_sensor)
|
||||||
|
|
||||||
|
# Standalone example that connects to picow_ble_temp_sensor and reads the temperature
|
||||||
|
# Flahes once quickly each second when it's running but not connected to another device
|
||||||
|
# Flashes twice quickly each second when connected to another device and reading it's temperature
|
||||||
|
add_executable(picow_ble_temp_reader
|
||||||
|
client.c
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_ble_temp_reader
|
||||||
|
pico_stdlib
|
||||||
|
pico_btstack_ble
|
||||||
|
pico_btstack_cyw43
|
||||||
|
pico_cyw43_arch_none
|
||||||
|
hardware_adc
|
||||||
|
)
|
||||||
|
target_include_directories(picow_ble_temp_reader PRIVATE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR} # For btstack config
|
||||||
|
)
|
||||||
|
target_compile_definitions(picow_ble_temp_reader PRIVATE
|
||||||
|
RUNNING_AS_CLIENT=1
|
||||||
|
)
|
||||||
|
|
||||||
|
pico_add_extra_outputs(picow_ble_temp_reader)
|
||||||
|
example_auto_set_url(picow_ble_temp_reader)
|
||||||
|
|
||||||
|
if (WIFI_SSID AND WIFI_PASSWORD)
|
||||||
|
# Another version of the sensor example, but this time also runs iperf over wifi
|
||||||
|
add_executable(picow_ble_temp_sensor_with_wifi
|
||||||
|
server_with_wifi.c server_common.c
|
||||||
|
)
|
||||||
|
target_link_libraries(picow_ble_temp_sensor_with_wifi
|
||||||
|
pico_stdlib
|
||||||
|
pico_btstack_ble
|
||||||
|
pico_btstack_cyw43
|
||||||
|
pico_cyw43_arch_lwip_threadsafe_background
|
||||||
|
pico_lwip_iperf
|
||||||
|
hardware_adc
|
||||||
|
)
|
||||||
|
target_include_directories(picow_ble_temp_sensor_with_wifi PRIVATE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR} # For btstack config
|
||||||
|
)
|
||||||
|
target_compile_definitions(picow_ble_temp_sensor_with_wifi PRIVATE
|
||||||
|
WIFI_SSID=\"${WIFI_SSID}\"
|
||||||
|
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
|
||||||
|
)
|
||||||
|
pico_btstack_make_gatt_header(picow_ble_temp_sensor_with_wifi PRIVATE "${CMAKE_CURRENT_LIST_DIR}/temp_sensor.gatt")
|
||||||
|
|
||||||
|
pico_add_extra_outputs(picow_ble_temp_sensor_with_wifi)
|
||||||
|
example_auto_set_url(picow_ble_temp_sensor_with_wifi)
|
||||||
|
endif()
|
||||||
58
pico_w/bt/standalone/btstack_config.h
Normal file
58
pico_w/bt/standalone/btstack_config.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#ifndef _PICO_BTSTACK_BTSTACK_CONFIG_H
|
||||||
|
#define _PICO_BTSTACK_BTSTACK_CONFIG_H
|
||||||
|
|
||||||
|
#ifndef ENABLE_BLE
|
||||||
|
#error Please link to pico_btstack_ble
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// BTstack features that can be enabled
|
||||||
|
#define ENABLE_LE_PERIPHERAL
|
||||||
|
#define ENABLE_LOG_INFO
|
||||||
|
#define ENABLE_LOG_ERROR
|
||||||
|
#define ENABLE_PRINTF_HEXDUMP
|
||||||
|
|
||||||
|
// for the client
|
||||||
|
#if RUNNING_AS_CLIENT
|
||||||
|
#define ENABLE_LE_CENTRAL
|
||||||
|
#define MAX_NR_GATT_CLIENTS 1
|
||||||
|
#else
|
||||||
|
#define MAX_NR_GATT_CLIENTS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// BTstack configuration. buffers, sizes, ...
|
||||||
|
#define HCI_OUTGOING_PRE_BUFFER_SIZE 4
|
||||||
|
#define HCI_ACL_PAYLOAD_SIZE (255 + 4)
|
||||||
|
#define HCI_ACL_CHUNK_SIZE_ALIGNMENT 4
|
||||||
|
#define MAX_NR_HCI_CONNECTIONS 1
|
||||||
|
#define MAX_NR_SM_LOOKUP_ENTRIES 3
|
||||||
|
#define MAX_NR_WHITELIST_ENTRIES 16
|
||||||
|
#define MAX_NR_LE_DEVICE_DB_ENTRIES 16
|
||||||
|
|
||||||
|
// Limit number of ACL/SCO Buffer to use by stack to avoid cyw43 shared bus overrun
|
||||||
|
#define MAX_NR_CONTROLLER_ACL_BUFFERS 3
|
||||||
|
#define MAX_NR_CONTROLLER_SCO_PACKETS 3
|
||||||
|
|
||||||
|
// Enable and configure HCI Controller to Host Flow Control to avoid cyw43 shared bus overrun
|
||||||
|
#define ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
|
||||||
|
#define HCI_HOST_ACL_PACKET_LEN (255+4)
|
||||||
|
#define HCI_HOST_ACL_PACKET_NUM 3
|
||||||
|
#define HCI_HOST_SCO_PACKET_LEN 120
|
||||||
|
#define HCI_HOST_SCO_PACKET_NUM 3
|
||||||
|
|
||||||
|
// Link Key DB and LE Device DB using TLV on top of Flash Sector interface
|
||||||
|
#define NVM_NUM_DEVICE_DB_ENTRIES 16
|
||||||
|
#define NVM_NUM_LINK_KEYS 16
|
||||||
|
|
||||||
|
// We don't give btstack a malloc, so use a fixed-size ATT DB.
|
||||||
|
#define MAX_ATT_DB_SIZE 512
|
||||||
|
|
||||||
|
// BTstack HAL configuration
|
||||||
|
#define HAVE_EMBEDDED_TIME_MS
|
||||||
|
// map btstack_assert onto Pico SDK assert()
|
||||||
|
#define HAVE_ASSERT
|
||||||
|
// Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A).
|
||||||
|
#define HCI_RESET_RESEND_TIMEOUT_MS 1000
|
||||||
|
#define ENABLE_SOFTWARE_AES128
|
||||||
|
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_H
|
||||||
273
pico_w/bt/standalone/client.c
Normal file
273
pico_w/bt/standalone/client.c
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "btstack.h"
|
||||||
|
#include "pico/cyw43_arch.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define DEBUG_LOG(...) printf(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DEBUG_LOG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LED_QUICK_FLASH_DELAY_MS 100
|
||||||
|
#define LED_SLOW_FLASH_DELAY_MS 1000
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TC_OFF,
|
||||||
|
TC_IDLE,
|
||||||
|
TC_W4_SCAN_RESULT,
|
||||||
|
TC_W4_CONNECT,
|
||||||
|
TC_W4_SERVICE_RESULT,
|
||||||
|
TC_W4_CHARACTERISTIC_RESULT,
|
||||||
|
TC_W4_ENABLE_NOTIFICATIONS_COMPLETE,
|
||||||
|
TC_W4_READY
|
||||||
|
} gc_state_t;
|
||||||
|
|
||||||
|
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||||
|
static gc_state_t state = TC_OFF;
|
||||||
|
static bd_addr_t server_addr;
|
||||||
|
static bd_addr_type_t server_addr_type;
|
||||||
|
static hci_con_handle_t connection_handle;
|
||||||
|
static gatt_client_service_t server_service;
|
||||||
|
static gatt_client_characteristic_t server_characteristic;
|
||||||
|
static bool listener_registered;
|
||||||
|
static gatt_client_notification_t notification_listener;
|
||||||
|
static btstack_timer_source_t heartbeat;
|
||||||
|
|
||||||
|
static void client_start(void){
|
||||||
|
DEBUG_LOG("Start scanning!\n");
|
||||||
|
state = TC_W4_SCAN_RESULT;
|
||||||
|
gap_set_scan_parameters(0,0x0030, 0x0030);
|
||||||
|
gap_start_scan();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool advertisement_report_contains_service(uint16_t service, uint8_t *advertisement_report){
|
||||||
|
// get advertisement from report event
|
||||||
|
const uint8_t * adv_data = gap_event_advertising_report_get_data(advertisement_report);
|
||||||
|
uint8_t adv_len = gap_event_advertising_report_get_data_length(advertisement_report);
|
||||||
|
|
||||||
|
// iterate over advertisement data
|
||||||
|
ad_context_t context;
|
||||||
|
for (ad_iterator_init(&context, adv_len, adv_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){
|
||||||
|
uint8_t data_type = ad_iterator_get_data_type(&context);
|
||||||
|
uint8_t data_size = ad_iterator_get_data_len(&context);
|
||||||
|
const uint8_t * data = ad_iterator_get_data(&context);
|
||||||
|
switch (data_type){
|
||||||
|
case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
|
||||||
|
for (int i = 0; i < data_size; i += 2) {
|
||||||
|
uint16_t type = little_endian_read_16(data, i);
|
||||||
|
if (type == service) return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
|
||||||
|
UNUSED(packet_type);
|
||||||
|
UNUSED(channel);
|
||||||
|
UNUSED(size);
|
||||||
|
|
||||||
|
uint8_t att_status;
|
||||||
|
switch(state){
|
||||||
|
case TC_W4_SERVICE_RESULT:
|
||||||
|
switch(hci_event_packet_get_type(packet)) {
|
||||||
|
case GATT_EVENT_SERVICE_QUERY_RESULT:
|
||||||
|
// store service (we expect only one)
|
||||||
|
DEBUG_LOG("Storing service\n");
|
||||||
|
gatt_event_service_query_result_get_service(packet, &server_service);
|
||||||
|
break;
|
||||||
|
case GATT_EVENT_QUERY_COMPLETE:
|
||||||
|
att_status = gatt_event_query_complete_get_att_status(packet);
|
||||||
|
if (att_status != ATT_ERROR_SUCCESS){
|
||||||
|
printf("SERVICE_QUERY_RESULT, ATT Error 0x%02x.\n", att_status);
|
||||||
|
gap_disconnect(connection_handle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// service query complete, look for characteristic
|
||||||
|
state = TC_W4_CHARACTERISTIC_RESULT;
|
||||||
|
DEBUG_LOG("Search for env sensing characteristic.\n");
|
||||||
|
gatt_client_discover_characteristics_for_service_by_uuid16(handle_gatt_client_event, connection_handle, &server_service, ORG_BLUETOOTH_CHARACTERISTIC_TEMPERATURE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TC_W4_CHARACTERISTIC_RESULT:
|
||||||
|
switch(hci_event_packet_get_type(packet)) {
|
||||||
|
case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
|
||||||
|
DEBUG_LOG("Storing characteristic\n");
|
||||||
|
gatt_event_characteristic_query_result_get_characteristic(packet, &server_characteristic);
|
||||||
|
break;
|
||||||
|
case GATT_EVENT_QUERY_COMPLETE:
|
||||||
|
att_status = gatt_event_query_complete_get_att_status(packet);
|
||||||
|
if (att_status != ATT_ERROR_SUCCESS){
|
||||||
|
printf("CHARACTERISTIC_QUERY_RESULT, ATT Error 0x%02x.\n", att_status);
|
||||||
|
gap_disconnect(connection_handle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// register handler for notifications
|
||||||
|
listener_registered = true;
|
||||||
|
gatt_client_listen_for_characteristic_value_updates(¬ification_listener, handle_gatt_client_event, connection_handle, &server_characteristic);
|
||||||
|
// enable notifications
|
||||||
|
DEBUG_LOG("Enable notify on characteristic.\n");
|
||||||
|
state = TC_W4_ENABLE_NOTIFICATIONS_COMPLETE;
|
||||||
|
gatt_client_write_client_characteristic_configuration(handle_gatt_client_event, connection_handle,
|
||||||
|
&server_characteristic, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TC_W4_ENABLE_NOTIFICATIONS_COMPLETE:
|
||||||
|
switch(hci_event_packet_get_type(packet)) {
|
||||||
|
case GATT_EVENT_QUERY_COMPLETE:
|
||||||
|
DEBUG_LOG("Notifications enabled, ATT status 0x%02x\n", gatt_event_query_complete_get_att_status(packet));
|
||||||
|
if (gatt_event_query_complete_get_att_status(packet) != ATT_ERROR_SUCCESS) break;
|
||||||
|
state = TC_W4_READY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TC_W4_READY:
|
||||||
|
switch(hci_event_packet_get_type(packet)) {
|
||||||
|
case GATT_EVENT_NOTIFICATION: {
|
||||||
|
uint16_t value_length = gatt_event_notification_get_value_length(packet);
|
||||||
|
const uint8_t *value = gatt_event_notification_get_value(packet);
|
||||||
|
DEBUG_LOG("Indication value len %d\n", value_length);
|
||||||
|
if (value_length == 2) {
|
||||||
|
float temp = little_endian_read_16(value, 0);
|
||||||
|
printf("read temp %.2f degc\n", temp / 100);
|
||||||
|
} else {
|
||||||
|
printf("Unexpected length %d\n", value_length);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
printf("Unknown packet type 0x%02x\n", hci_event_packet_get_type(packet));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("error\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
|
||||||
|
UNUSED(size);
|
||||||
|
UNUSED(channel);
|
||||||
|
bd_addr_t local_addr;
|
||||||
|
if (packet_type != HCI_EVENT_PACKET) return;
|
||||||
|
|
||||||
|
uint8_t event_type = hci_event_packet_get_type(packet);
|
||||||
|
switch(event_type){
|
||||||
|
case BTSTACK_EVENT_STATE:
|
||||||
|
if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING) {
|
||||||
|
gap_local_bd_addr(local_addr);
|
||||||
|
printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr));
|
||||||
|
client_start();
|
||||||
|
} else {
|
||||||
|
state = TC_OFF;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GAP_EVENT_ADVERTISING_REPORT:
|
||||||
|
if (state != TC_W4_SCAN_RESULT) return;
|
||||||
|
// check name in advertisement
|
||||||
|
if (!advertisement_report_contains_service(ORG_BLUETOOTH_SERVICE_ENVIRONMENTAL_SENSING, packet)) return;
|
||||||
|
// store address and type
|
||||||
|
gap_event_advertising_report_get_address(packet, server_addr);
|
||||||
|
server_addr_type = gap_event_advertising_report_get_address_type(packet);
|
||||||
|
// stop scanning, and connect to the device
|
||||||
|
state = TC_W4_CONNECT;
|
||||||
|
gap_stop_scan();
|
||||||
|
printf("Connecting to device with addr %s.\n", bd_addr_to_str(server_addr));
|
||||||
|
gap_connect(server_addr, server_addr_type);
|
||||||
|
break;
|
||||||
|
case HCI_EVENT_LE_META:
|
||||||
|
// wait for connection complete
|
||||||
|
switch (hci_event_le_meta_get_subevent_code(packet)) {
|
||||||
|
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
|
||||||
|
if (state != TC_W4_CONNECT) return;
|
||||||
|
connection_handle = hci_subevent_le_connection_complete_get_connection_handle(packet);
|
||||||
|
// initialize gatt client context with handle, and add it to the list of active clients
|
||||||
|
// query primary services
|
||||||
|
DEBUG_LOG("Search for env sensing service.\n");
|
||||||
|
state = TC_W4_SERVICE_RESULT;
|
||||||
|
gatt_client_discover_primary_services_by_uuid16(handle_gatt_client_event, connection_handle, ORG_BLUETOOTH_SERVICE_ENVIRONMENTAL_SENSING);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||||
|
// unregister listener
|
||||||
|
connection_handle = HCI_CON_HANDLE_INVALID;
|
||||||
|
if (listener_registered){
|
||||||
|
listener_registered = false;
|
||||||
|
gatt_client_stop_listening_for_characteristic_value_updates(¬ification_listener);
|
||||||
|
}
|
||||||
|
printf("Disconnected %s\n", bd_addr_to_str(server_addr));
|
||||||
|
if (state == TC_OFF) break;
|
||||||
|
client_start();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void heartbeat_handler(struct btstack_timer_source *ts) {
|
||||||
|
// Invert the led
|
||||||
|
static bool quick_flash;
|
||||||
|
static bool led_on = true;
|
||||||
|
|
||||||
|
led_on = !led_on;
|
||||||
|
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led_on);
|
||||||
|
if (listener_registered && led_on) {
|
||||||
|
quick_flash = !quick_flash;
|
||||||
|
} else if (!listener_registered) {
|
||||||
|
quick_flash = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restart timer
|
||||||
|
btstack_run_loop_set_timer(ts, (led_on || quick_flash) ? LED_QUICK_FLASH_DELAY_MS : LED_SLOW_FLASH_DELAY_MS);
|
||||||
|
btstack_run_loop_add_timer(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
// initialize CYW43 driver architecture (will enable BT if/because CYW43_ENABLE_BLUETOOTH == 1)
|
||||||
|
if (cyw43_arch_init()) {
|
||||||
|
printf("failed to initialise cyw43_arch\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
l2cap_init();
|
||||||
|
sm_init();
|
||||||
|
sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);
|
||||||
|
gatt_client_init();
|
||||||
|
|
||||||
|
hci_event_callback_registration.callback = &hci_event_handler;
|
||||||
|
hci_add_event_handler(&hci_event_callback_registration);
|
||||||
|
|
||||||
|
// set one-shot btstack timer
|
||||||
|
heartbeat.process = &heartbeat_handler;
|
||||||
|
btstack_run_loop_set_timer(&heartbeat, LED_SLOW_FLASH_DELAY_MS);
|
||||||
|
btstack_run_loop_add_timer(&heartbeat);
|
||||||
|
|
||||||
|
// turn on!
|
||||||
|
hci_power_control(HCI_POWER_ON);
|
||||||
|
|
||||||
|
btstack_run_loop_execute();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
76
pico_w/bt/standalone/lwipopts.h
Normal file
76
pico_w/bt/standalone/lwipopts.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#ifndef _LWIPOPTS_H
|
||||||
|
#define _LWIPOPTS_H
|
||||||
|
|
||||||
|
// see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details
|
||||||
|
|
||||||
|
#define NO_SYS 1
|
||||||
|
#define LWIP_SOCKET 0
|
||||||
|
#define MEM_LIBC_MALLOC 0
|
||||||
|
#define MEM_ALIGNMENT 4
|
||||||
|
#define MEM_SIZE 4000
|
||||||
|
#define MEMP_NUM_TCP_SEG 32
|
||||||
|
#define MEMP_NUM_ARP_QUEUE 10
|
||||||
|
#define PBUF_POOL_SIZE 24
|
||||||
|
#define LWIP_ARP 1
|
||||||
|
#define LWIP_ETHERNET 1
|
||||||
|
#define LWIP_ICMP 1
|
||||||
|
#define LWIP_RAW 1
|
||||||
|
#define TCP_WND (8 * TCP_MSS)
|
||||||
|
#define TCP_MSS 1460
|
||||||
|
#define TCP_SND_BUF (8 * TCP_MSS)
|
||||||
|
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
|
||||||
|
#define LWIP_NETIF_STATUS_CALLBACK 1
|
||||||
|
#define LWIP_NETIF_LINK_CALLBACK 1
|
||||||
|
#define LWIP_NETIF_HOSTNAME 1
|
||||||
|
#define LWIP_NETCONN 0
|
||||||
|
#define MEM_STATS 0
|
||||||
|
#define SYS_STATS 0
|
||||||
|
#define MEMP_STATS 0
|
||||||
|
#define LINK_STATS 0
|
||||||
|
#define LWIP_CHKSUM_ALGORITHM 3
|
||||||
|
#define LWIP_DHCP 1
|
||||||
|
#define LWIP_IPV4 1
|
||||||
|
#define LWIP_TCP 1
|
||||||
|
#define LWIP_UDP 1
|
||||||
|
#define LWIP_DNS 1
|
||||||
|
#define LWIP_TCP_KEEPALIVE 1
|
||||||
|
#define LWIP_NETIF_TX_SINGLE_PBUF 1
|
||||||
|
#define DHCP_DOES_ARP_CHECK 0
|
||||||
|
#define LWIP_DHCP_DOES_ACD_CHECK 0
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define LWIP_DEBUG 1
|
||||||
|
#define LWIP_STATS 1
|
||||||
|
#define LWIP_STATS_DISPLAY 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ETHARP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define NETIF_DEBUG LWIP_DBG_OFF
|
||||||
|
#define PBUF_DEBUG LWIP_DBG_OFF
|
||||||
|
#define API_LIB_DEBUG LWIP_DBG_OFF
|
||||||
|
#define API_MSG_DEBUG LWIP_DBG_OFF
|
||||||
|
#define SOCKETS_DEBUG LWIP_DBG_OFF
|
||||||
|
#define ICMP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define INET_DEBUG LWIP_DBG_OFF
|
||||||
|
#define IP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define IP_REASS_DEBUG LWIP_DBG_OFF
|
||||||
|
#define RAW_DEBUG LWIP_DBG_OFF
|
||||||
|
#define MEM_DEBUG LWIP_DBG_OFF
|
||||||
|
#define MEMP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define SYS_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_RTO_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_CWND_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_WND_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_FR_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCP_RST_DEBUG LWIP_DBG_OFF
|
||||||
|
#define UDP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define PPP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define SLIP_DEBUG LWIP_DBG_OFF
|
||||||
|
#define DHCP_DEBUG LWIP_DBG_OFF
|
||||||
|
|
||||||
|
#endif /* __LWIPOPTS_H__ */
|
||||||
79
pico_w/bt/standalone/server.c
Normal file
79
pico_w/bt/standalone/server.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "btstack.h"
|
||||||
|
#include "pico/cyw43_arch.h"
|
||||||
|
#include "pico/btstack_cyw43.h"
|
||||||
|
#include "hardware/adc.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
|
#include "server_common.h"
|
||||||
|
|
||||||
|
#define HEARTBEAT_PERIOD_MS 1000
|
||||||
|
|
||||||
|
static btstack_timer_source_t heartbeat;
|
||||||
|
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||||
|
|
||||||
|
static void heartbeat_handler(struct btstack_timer_source *ts) {
|
||||||
|
static uint32_t counter = 0;
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
// Update the temp every 10s
|
||||||
|
if (counter % 10 == 0) {
|
||||||
|
poll_temp();
|
||||||
|
if (le_notification_enabled) {
|
||||||
|
att_server_request_can_send_now_event(con_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert the led
|
||||||
|
static int led_on = true;
|
||||||
|
led_on = !led_on;
|
||||||
|
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led_on);
|
||||||
|
|
||||||
|
// Restart timer
|
||||||
|
btstack_run_loop_set_timer(ts, HEARTBEAT_PERIOD_MS);
|
||||||
|
btstack_run_loop_add_timer(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
// initialize CYW43 driver architecture (will enable BT if/because CYW43_ENABLE_BLUETOOTH == 1)
|
||||||
|
if (cyw43_arch_init()) {
|
||||||
|
printf("failed to initialise cyw43_arch\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise adc for the temp sensor
|
||||||
|
adc_init();
|
||||||
|
adc_select_input(ADC_CHANNEL_TEMPSENSOR);
|
||||||
|
adc_set_temp_sensor_enabled(true);
|
||||||
|
|
||||||
|
l2cap_init();
|
||||||
|
sm_init();
|
||||||
|
|
||||||
|
att_server_init(profile_data, att_read_callback, att_write_callback);
|
||||||
|
|
||||||
|
// inform about BTstack state
|
||||||
|
hci_event_callback_registration.callback = &packet_handler;
|
||||||
|
hci_add_event_handler(&hci_event_callback_registration);
|
||||||
|
|
||||||
|
// register for ATT event
|
||||||
|
att_server_register_packet_handler(packet_handler);
|
||||||
|
|
||||||
|
// set one-shot btstack timer
|
||||||
|
heartbeat.process = &heartbeat_handler;
|
||||||
|
btstack_run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS);
|
||||||
|
btstack_run_loop_add_timer(&heartbeat);
|
||||||
|
|
||||||
|
// turn on bluetooth!
|
||||||
|
hci_power_control(HCI_POWER_ON);
|
||||||
|
|
||||||
|
btstack_run_loop_execute();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
106
pico_w/bt/standalone/server_common.c
Normal file
106
pico_w/bt/standalone/server_common.c
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "btstack.h"
|
||||||
|
#include "hardware/adc.h"
|
||||||
|
|
||||||
|
#include "temp_sensor.h"
|
||||||
|
#include "server_common.h"
|
||||||
|
|
||||||
|
#define APP_AD_FLAGS 0x06
|
||||||
|
static uint8_t adv_data[] = {
|
||||||
|
// Flags general discoverable
|
||||||
|
0x02, BLUETOOTH_DATA_TYPE_FLAGS, APP_AD_FLAGS,
|
||||||
|
// Name
|
||||||
|
0x17, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'P', 'i', 'c', 'o', ' ', '0', '0', ':', '0', '0', ':', '0', '0', ':', '0', '0', ':', '0', '0', ':', '0', '0',
|
||||||
|
0x03, BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS, 0x1a, 0x18,
|
||||||
|
};
|
||||||
|
static const uint8_t adv_data_len = sizeof(adv_data);
|
||||||
|
|
||||||
|
int le_notification_enabled;
|
||||||
|
hci_con_handle_t con_handle;
|
||||||
|
uint16_t current_temp;
|
||||||
|
|
||||||
|
void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
|
||||||
|
UNUSED(size);
|
||||||
|
UNUSED(channel);
|
||||||
|
bd_addr_t local_addr;
|
||||||
|
if (packet_type != HCI_EVENT_PACKET) return;
|
||||||
|
|
||||||
|
uint8_t event_type = hci_event_packet_get_type(packet);
|
||||||
|
switch(event_type){
|
||||||
|
case BTSTACK_EVENT_STATE:
|
||||||
|
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
|
||||||
|
gap_local_bd_addr(local_addr);
|
||||||
|
printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr));
|
||||||
|
|
||||||
|
// setup advertisements
|
||||||
|
uint16_t adv_int_min = 800;
|
||||||
|
uint16_t adv_int_max = 800;
|
||||||
|
uint8_t adv_type = 0;
|
||||||
|
bd_addr_t null_addr;
|
||||||
|
memset(null_addr, 0, 6);
|
||||||
|
gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00);
|
||||||
|
assert(adv_data_len <= 31); // ble limitation
|
||||||
|
gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data);
|
||||||
|
gap_advertisements_enable(1);
|
||||||
|
|
||||||
|
poll_temp();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||||
|
le_notification_enabled = 0;
|
||||||
|
break;
|
||||||
|
case ATT_EVENT_CAN_SEND_NOW:
|
||||||
|
att_server_notify(con_handle, ATT_CHARACTERISTIC_ORG_BLUETOOTH_CHARACTERISTIC_TEMPERATURE_01_VALUE_HANDLE, (uint8_t*)¤t_temp, sizeof(current_temp));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size) {
|
||||||
|
UNUSED(connection_handle);
|
||||||
|
|
||||||
|
if (att_handle == ATT_CHARACTERISTIC_ORG_BLUETOOTH_CHARACTERISTIC_TEMPERATURE_01_VALUE_HANDLE){
|
||||||
|
return att_read_callback_handle_blob((const uint8_t *)¤t_temp, sizeof(current_temp), offset, buffer, buffer_size);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) {
|
||||||
|
UNUSED(transaction_mode);
|
||||||
|
UNUSED(offset);
|
||||||
|
UNUSED(buffer_size);
|
||||||
|
|
||||||
|
if (att_handle != ATT_CHARACTERISTIC_ORG_BLUETOOTH_CHARACTERISTIC_TEMPERATURE_01_CLIENT_CONFIGURATION_HANDLE) return 0;
|
||||||
|
le_notification_enabled = little_endian_read_16(buffer, 0) == GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION;
|
||||||
|
con_handle = connection_handle;
|
||||||
|
if (le_notification_enabled) {
|
||||||
|
att_server_request_can_send_now_event(con_handle);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void poll_temp(void) {
|
||||||
|
adc_select_input(ADC_CHANNEL_TEMPSENSOR);
|
||||||
|
uint32_t raw32 = adc_read();
|
||||||
|
const uint32_t bits = 12;
|
||||||
|
|
||||||
|
// Scale raw reading to 16 bit value using a Taylor expansion (for 8 <= bits <= 16)
|
||||||
|
uint16_t raw16 = raw32 << (16 - bits) | raw32 >> (2 * bits - 16);
|
||||||
|
|
||||||
|
// ref https://github.com/raspberrypi/pico-micropython-examples/blob/master/adc/temperature.py
|
||||||
|
const float conversion_factor = 3.3 / (65535);
|
||||||
|
float reading = raw16 * conversion_factor;
|
||||||
|
|
||||||
|
// The temperature sensor measures the Vbe voltage of a biased bipolar diode, connected to the fifth ADC channel
|
||||||
|
// Typically, Vbe = 0.706V at 27 degrees C, with a slope of -1.721mV (0.001721) per degree.
|
||||||
|
float deg_c = 27 - (reading - 0.706) / 0.001721;
|
||||||
|
current_temp = deg_c * 100;
|
||||||
|
printf("Write temp %.2f degc\n", deg_c);
|
||||||
|
}
|
||||||
22
pico_w/bt/standalone/server_common.h
Normal file
22
pico_w/bt/standalone/server_common.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERVER_COMMON_H_
|
||||||
|
#define SERVER_COMMON_H_
|
||||||
|
|
||||||
|
#define ADC_CHANNEL_TEMPSENSOR 4
|
||||||
|
|
||||||
|
extern int le_notification_enabled;
|
||||||
|
extern hci_con_handle_t con_handle;
|
||||||
|
extern uint16_t current_temp;
|
||||||
|
extern uint8_t const profile_data[];
|
||||||
|
|
||||||
|
void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||||
|
uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size);
|
||||||
|
int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size);
|
||||||
|
void poll_temp(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
117
pico_w/bt/standalone/server_with_wifi.c
Normal file
117
pico_w/bt/standalone/server_with_wifi.c
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "btstack.h"
|
||||||
|
#include "pico/cyw43_arch.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "hardware/adc.h"
|
||||||
|
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/ip4_addr.h"
|
||||||
|
#include "lwip/apps/lwiperf.h"
|
||||||
|
|
||||||
|
#include "server_common.h"
|
||||||
|
|
||||||
|
#define HEARTBEAT_PERIOD_MS 1000
|
||||||
|
|
||||||
|
static void heartbeat_handler(async_context_t *context, async_at_time_worker_t *worker);
|
||||||
|
|
||||||
|
static async_at_time_worker_t heartbeat_worker = { .do_work = heartbeat_handler };
|
||||||
|
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||||
|
|
||||||
|
static void heartbeat_handler(async_context_t *context, async_at_time_worker_t *worker) {
|
||||||
|
static uint32_t counter = 0;
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
// Update the temp every 10s
|
||||||
|
if (counter % 10 == 0) {
|
||||||
|
poll_temp();
|
||||||
|
if (le_notification_enabled) {
|
||||||
|
att_server_request_can_send_now_event(con_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert the led
|
||||||
|
static int led_on = true;
|
||||||
|
led_on = !led_on;
|
||||||
|
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led_on);
|
||||||
|
|
||||||
|
// Restart timer
|
||||||
|
async_context_add_at_time_worker_in_ms(context, &heartbeat_worker, HEARTBEAT_PERIOD_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report IP results and exit
|
||||||
|
static void iperf_report(void *arg, enum lwiperf_report_type report_type,
|
||||||
|
const ip_addr_t *local_addr, u16_t local_port, const ip_addr_t *remote_addr, u16_t remote_port,
|
||||||
|
u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec) {
|
||||||
|
static uint32_t total_iperf_megabytes = 0;
|
||||||
|
uint32_t mbytes = bytes_transferred / 1024 / 1024;
|
||||||
|
float mbits = bandwidth_kbitpsec / 1000.0;
|
||||||
|
|
||||||
|
total_iperf_megabytes += mbytes;
|
||||||
|
|
||||||
|
printf("Completed iperf transfer of %d MBytes @ %.1f Mbits/sec\n", mbytes, mbits);
|
||||||
|
printf("Total iperf megabytes since start %d Mbytes\n", total_iperf_megabytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
// initialize CYW43 architecture
|
||||||
|
// - will enable BT if CYW43_ENABLE_BLUETOOTH == 1
|
||||||
|
// - will enable lwIP if CYW43_LWIP == 1
|
||||||
|
if (cyw43_arch_init()) {
|
||||||
|
printf("failed to initialise cyw43_arch\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise adc for the temp sensor
|
||||||
|
adc_init();
|
||||||
|
adc_select_input(ADC_CHANNEL_TEMPSENSOR);
|
||||||
|
adc_set_temp_sensor_enabled(true);
|
||||||
|
|
||||||
|
l2cap_init();
|
||||||
|
sm_init();
|
||||||
|
att_server_init(profile_data, att_read_callback, att_write_callback);
|
||||||
|
|
||||||
|
// inform about BTstack state
|
||||||
|
hci_event_callback_registration.callback = &packet_handler;
|
||||||
|
hci_add_event_handler(&hci_event_callback_registration);
|
||||||
|
|
||||||
|
// register for ATT event
|
||||||
|
att_server_register_packet_handler(packet_handler);
|
||||||
|
|
||||||
|
// set one-shot btstack timer
|
||||||
|
async_context_add_at_time_worker_in_ms(cyw43_arch_async_context(), &heartbeat_worker, HEARTBEAT_PERIOD_MS);
|
||||||
|
|
||||||
|
// Connect to Wi-Fi
|
||||||
|
cyw43_arch_enable_sta_mode();
|
||||||
|
printf("Connecting to Wi-Fi...\n");
|
||||||
|
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
|
||||||
|
printf("failed to connect.\n");
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
printf("Connected.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup iperf
|
||||||
|
cyw43_arch_lwip_begin();
|
||||||
|
printf("\nReady, running iperf server at %s\n", ip4addr_ntoa(netif_ip4_addr(netif_list)));
|
||||||
|
lwiperf_start_tcp_server_default(&iperf_report, NULL);
|
||||||
|
cyw43_arch_lwip_end();
|
||||||
|
|
||||||
|
// turn on bluetooth!
|
||||||
|
hci_power_control(HCI_POWER_ON);
|
||||||
|
|
||||||
|
// For threadsafe background we can just enter a loop
|
||||||
|
while(true) {
|
||||||
|
sleep_ms(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
cyw43_arch_deinit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
8
pico_w/bt/standalone/temp_sensor.gatt
Normal file
8
pico_w/bt/standalone/temp_sensor.gatt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
PRIMARY_SERVICE, GAP_SERVICE
|
||||||
|
CHARACTERISTIC, GAP_DEVICE_NAME, READ, "picow_temp"
|
||||||
|
|
||||||
|
PRIMARY_SERVICE, GATT_SERVICE
|
||||||
|
CHARACTERISTIC, GATT_DATABASE_HASH, READ,
|
||||||
|
|
||||||
|
PRIMARY_SERVICE, ORG_BLUETOOTH_SERVICE_ENVIRONMENTAL_SENSING
|
||||||
|
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_TEMPERATURE, READ | NOTIFY | INDICATE | DYNAMIC,
|
||||||
1
pico_w/bt/ublox_spp_le_counter/CMakeLists.txt
Normal file
1
pico_w/bt/ublox_spp_le_counter/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picow_bt_example(ublox_spp_le_counter)
|
||||||
25
pico_w/wifi/CMakeLists.txt
Normal file
25
pico_w/wifi/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
set(WIFI_SSID "${WIFI_SSID}" CACHE INTERNAL "WiFi SSID for examples")
|
||||||
|
set(WIFI_PASSWORD "${WIFI_PASSWORD}" CACHE INTERNAL "WiFi password for examples")
|
||||||
|
|
||||||
|
add_subdirectory(blink)
|
||||||
|
add_subdirectory(wifi_scan)
|
||||||
|
add_subdirectory(access_point)
|
||||||
|
|
||||||
|
if ("${WIFI_SSID}" STREQUAL "")
|
||||||
|
message("Skipping some Pico W examples as WIFI_SSID is not defined")
|
||||||
|
elseif ("${WIFI_PASSWORD}" STREQUAL "")
|
||||||
|
message("Skipping some Pico W examples as WIFI_PASSWORD is not defined")
|
||||||
|
else()
|
||||||
|
add_subdirectory(iperf)
|
||||||
|
add_subdirectory(ntp_client)
|
||||||
|
add_subdirectory(tcp_client)
|
||||||
|
add_subdirectory(tcp_server)
|
||||||
|
add_subdirectory(freertos)
|
||||||
|
add_subdirectory(udp_beacon)
|
||||||
|
|
||||||
|
if (NOT PICO_MBEDTLS_PATH)
|
||||||
|
message("Skipping tls examples as PICO_MBEDTLS_PATH is not defined")
|
||||||
|
else()
|
||||||
|
add_subdirectory(tls_client)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
@@ -311,11 +311,13 @@ int main() {
|
|||||||
// you do not need it in your code
|
// you do not need it in your code
|
||||||
#if PICO_CYW43_ARCH_POLL
|
#if PICO_CYW43_ARCH_POLL
|
||||||
// if you are using pico_cyw43_arch_poll, then you must poll periodically from your
|
// if you are using pico_cyw43_arch_poll, then you must poll periodically from your
|
||||||
// main loop (not from a timer) to check for WiFi driver or lwIP work that needs to be done.
|
// main loop (not from a timer interrupt) to check for Wi-Fi driver or lwIP work that needs to be done.
|
||||||
cyw43_arch_poll();
|
cyw43_arch_poll();
|
||||||
sleep_ms(1);
|
// you can poll as often as you like, however if you have nothing else to do you can
|
||||||
|
// choose to sleep until either a specified time, or cyw43_arch_poll() has work to do:
|
||||||
|
cyw43_arch_wait_for_work_until(make_timeout_time_ms(1000));
|
||||||
#else
|
#else
|
||||||
// if you are not using pico_cyw43_arch_poll, then WiFI driver and lwIP work
|
// if you are not using pico_cyw43_arch_poll, then Wi-FI driver and lwIP work
|
||||||
// is done via interrupt in the background. This sleep is just an example of some (blocking)
|
// is done via interrupt in the background. This sleep is just an example of some (blocking)
|
||||||
// work you might be doing.
|
// work you might be doing.
|
||||||
sleep_ms(1000);
|
sleep_ms(1000);
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
int main() {
|
int main() {
|
||||||
stdio_init_all();
|
stdio_init_all();
|
||||||
if (cyw43_arch_init()) {
|
if (cyw43_arch_init()) {
|
||||||
printf("WiFi init failed");
|
printf("Wi-Fi init failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
62
pico_w/wifi/freertos/FreeRTOS_Kernel_import.cmake
Normal file
62
pico_w/wifi/freertos/FreeRTOS_Kernel_import.cmake
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# This is a copy of <FREERTOS_KERNEL_PATH>/portable/ThirdParty/GCC/RP2040/FREERTOS_KERNEL_import.cmake
|
||||||
|
|
||||||
|
# This can be dropped into an external project to help locate the FreeRTOS kernel
|
||||||
|
# It should be include()ed prior to project(). Alternatively this file may
|
||||||
|
# or the CMakeLists.txt in this directory may be included or added via add_subdirectory
|
||||||
|
# respectively.
|
||||||
|
|
||||||
|
if (DEFINED ENV{FREERTOS_KERNEL_PATH} AND (NOT FREERTOS_KERNEL_PATH))
|
||||||
|
set(FREERTOS_KERNEL_PATH $ENV{FREERTOS_KERNEL_PATH})
|
||||||
|
message("Using FREERTOS_KERNEL_PATH from environment ('${FREERTOS_KERNEL_PATH}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/GCC/RP2040")
|
||||||
|
# undo the above
|
||||||
|
set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../..")
|
||||||
|
|
||||||
|
if (NOT FREERTOS_KERNEL_PATH)
|
||||||
|
# check if we are inside the FreeRTOS kernel tree (i.e. this file has been included directly)
|
||||||
|
get_filename_component(_ACTUAL_PATH ${CMAKE_CURRENT_LIST_DIR} REALPATH)
|
||||||
|
get_filename_component(_POSSIBLE_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} REALPATH)
|
||||||
|
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
|
||||||
|
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
|
||||||
|
endif()
|
||||||
|
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
|
||||||
|
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
|
||||||
|
message("Setting FREERTOS_KERNEL_PATH to ${FREERTOS_KERNEL_PATH} based on location of FreeRTOS-Kernel-import.cmake")
|
||||||
|
elseif (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../FreeRTOS-Kernel")
|
||||||
|
set(FREERTOS_KERNEL_PATH ${PICO_SDK_PATH}/../FreeRTOS-Kernel)
|
||||||
|
message("Defaulting FREERTOS_KERNEL_PATH as sibling of PICO_SDK_PATH: ${FREERTOS_KERNEL_PATH}")
|
||||||
|
endif()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (NOT FREERTOS_KERNEL_PATH)
|
||||||
|
foreach(POSSIBLE_SUFFIX Source FreeRTOS-Kernel FreeRTOS/Source)
|
||||||
|
# check if FreeRTOS-Kernel exists under directory that included us
|
||||||
|
set(SEARCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}})
|
||||||
|
set(SEARCH_ROOT ../../../..)
|
||||||
|
get_filename_component(_POSSIBLE_PATH ${SEARCH_ROOT}/${POSSIBLE_SUFFIX} REALPATH)
|
||||||
|
if (EXISTS ${_POSSIBLE_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
|
||||||
|
get_filename_component(FREERTOS_KERNEL_PATH ${_POSSIBLE_PATH} REALPATH)
|
||||||
|
message("Setting FREERTOS_KERNEL_PATH to '${FREERTOS_KERNEL_PATH}' found relative to enclosing project")
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT FREERTOS_KERNEL_PATH)
|
||||||
|
message(FATAL_ERROR "FreeRTOS location was not specified. Please set FREERTOS_KERNEL_PATH.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" CACHE PATH "Path to the FreeRTOS Kernel")
|
||||||
|
|
||||||
|
get_filename_component(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||||
|
if (NOT EXISTS ${FREERTOS_KERNEL_PATH})
|
||||||
|
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' not found")
|
||||||
|
endif()
|
||||||
|
if (NOT EXISTS ${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
|
||||||
|
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' does not contain an RP2040 port here: ${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}")
|
||||||
|
endif()
|
||||||
|
set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} CACHE PATH "Path to the FreeRTOS_KERNEL" FORCE)
|
||||||
|
|
||||||
|
add_subdirectory(${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} FREERTOS_KERNEL)
|
||||||
@@ -62,7 +62,7 @@ void main_task(__unused void *params) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cyw43_arch_enable_sta_mode();
|
cyw43_arch_enable_sta_mode();
|
||||||
printf("Connecting to WiFi...\n");
|
printf("Connecting to Wi-Fi...\n");
|
||||||
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
|
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
|
||||||
printf("failed to connect.\n");
|
printf("failed to connect.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -72,6 +72,7 @@ void main_task(__unused void *params) {
|
|||||||
|
|
||||||
xTaskCreate(blink_task, "BlinkThread", configMINIMAL_STACK_SIZE, NULL, BLINK_TASK_PRIORITY, NULL);
|
xTaskCreate(blink_task, "BlinkThread", configMINIMAL_STACK_SIZE, NULL, BLINK_TASK_PRIORITY, NULL);
|
||||||
|
|
||||||
|
cyw43_arch_lwip_begin();
|
||||||
#if CLIENT_TEST
|
#if CLIENT_TEST
|
||||||
printf("\nReady, running iperf client\n");
|
printf("\nReady, running iperf client\n");
|
||||||
ip_addr_t clientaddr;
|
ip_addr_t clientaddr;
|
||||||
@@ -81,10 +82,11 @@ void main_task(__unused void *params) {
|
|||||||
printf("\nReady, running iperf server at %s\n", ip4addr_ntoa(netif_ip4_addr(netif_list)));
|
printf("\nReady, running iperf server at %s\n", ip4addr_ntoa(netif_ip4_addr(netif_list)));
|
||||||
lwiperf_start_tcp_server_default(&iperf_report, NULL);
|
lwiperf_start_tcp_server_default(&iperf_report, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
cyw43_arch_lwip_end();
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
// not much to do as LED is in another task, and we're using RAW (callback) lwIP API
|
// not much to do as LED is in another task, and we're using RAW (callback) lwIP API
|
||||||
vTaskDelay(100);
|
vTaskDelay(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
cyw43_arch_deinit();
|
cyw43_arch_deinit();
|
||||||
21
pico_w/wifi/freertos/ping/lwipopts.h
Normal file
21
pico_w/wifi/freertos/ping/lwipopts.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef _LWIPOPTS_H
|
||||||
|
#define _LWIPOPTS_H
|
||||||
|
|
||||||
|
// Generally you would define your own explicit list of lwIP options
|
||||||
|
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html)
|
||||||
|
//
|
||||||
|
// This example uses a common include to avoid repetition
|
||||||
|
#include "lwipopts_examples_common.h"
|
||||||
|
|
||||||
|
#if !NO_SYS
|
||||||
|
#define TCPIP_THREAD_STACKSIZE 1024
|
||||||
|
#define DEFAULT_THREAD_STACKSIZE 1024
|
||||||
|
#define DEFAULT_RAW_RECVMBOX_SIZE 8
|
||||||
|
#define TCPIP_MBOX_SIZE 8
|
||||||
|
#define LWIP_TIMEVAL_PRIVATE 0
|
||||||
|
|
||||||
|
// not necessary, can be done either way
|
||||||
|
#define LWIP_TCPIP_CORE_LOCKING_INPUT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -28,7 +28,7 @@ void main_task(__unused void *params) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cyw43_arch_enable_sta_mode();
|
cyw43_arch_enable_sta_mode();
|
||||||
printf("Connecting to WiFi...\n");
|
printf("Connecting to Wi-Fi...\n");
|
||||||
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
|
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
|
||||||
printf("failed to connect.\n");
|
printf("failed to connect.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -14,7 +14,6 @@ target_link_libraries(picow_iperf_server_background
|
|||||||
pico_stdlib
|
pico_stdlib
|
||||||
pico_lwip_iperf
|
pico_lwip_iperf
|
||||||
)
|
)
|
||||||
|
|
||||||
pico_add_extra_outputs(picow_iperf_server_background)
|
pico_add_extra_outputs(picow_iperf_server_background)
|
||||||
|
|
||||||
add_executable(picow_iperf_server_poll
|
add_executable(picow_iperf_server_poll
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user