Add Bluetooth examples

Co-authored-by: Peter Harper <77111776+peterharperuk@users.noreply.github.com>
This commit is contained in:
graham sanderson 2023-02-10 17:59:58 -06:00
parent 03f97a8999
commit 1c5d9aa567
127 changed files with 2296 additions and 63 deletions

View File

@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.12)
# Pull in SDK (must be before project)
include(pico_sdk_import.cmake)
include(pico_extras_import_optional.cmake)
project(pico_examples C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

View File

@ -117,15 +117,15 @@ These examples are for the Pico W, and are only available for `PICO_BOARD=pico_w
App|Description
---|---
[picow_access_point](pico_w/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_iperf_server](pico_w/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_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_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_tls_client](pico_w/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_udp_beacon](pico_w/udp_beacon)| A simple UDP transmitter.
[picow_access_point](pico_w/wifi/access_point)| Starts a WiFi access point, and fields DHCP requests.
[picow_blink](pico_w/wifi/blink)| Blinks the on-board LED (which is connected via the WiFi chip).
[picow_iperf_server](pico_w/wifi/iperf)| Runs an "iperf" server for WiFi speed testing.
[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/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/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/wifi/tls_client)| Demonstrates how to make a HTTPS request using TLS.
[picow_wifi_scan](pico_w/wifi/wifi_scan)| Scans for WiFi networks and prints the results.
[picow_udp_beacon](pico_w/wifi/udp_beacon)| A simple UDP transmitter.
#### FreeRTOS examples
@ -134,10 +134,79 @@ to point to the FreeRTOS Kernel.
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_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_ping_nosys](pico_w/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_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/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/wifi/freertos/ping)| Runs the lwip-contrib/apps/ping test app under FreeRTOS in NO_SYS=1 mode.
[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

View 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()

View File

@ -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_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")
add_subdirectory(wifi)
if (NOT TARGET pico_btstack_base)
message("Skipping Pico W Bluetooth examples as support is not available")
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()
add_subdirectory(bt)
endif()
endif()
endif()

398
pico_w/bt/CMakeLists.txt Normal file
View 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()

View 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)

View File

@ -0,0 +1 @@
picow_bt_example(a2dp_source_demo pico_btstack_hxcmod_player pico_btstack_sbc_encoder)

View File

@ -0,0 +1 @@
picow_bt_example(ancs_client_demo)

View File

@ -0,0 +1 @@
picow_bt_example(att_delayed_response)

View File

@ -0,0 +1 @@
picow_bt_example(avrcp_browsing_client)

View 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;
}

View 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 */

View 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

View File

@ -0,0 +1 @@
picow_bt_example(dut_mode_classic)

View File

@ -0,0 +1 @@
picow_bt_example(gap_dedicated_bonding)

View File

@ -0,0 +1 @@
picow_bt_example(gap_inquiry)

View File

@ -0,0 +1 @@
picow_bt_example(gap_le_advertisements)

View File

@ -0,0 +1 @@
picow_bt_example(gap_link_keys)

View File

@ -0,0 +1 @@
picow_bt_example(gatt_battery_query)

View File

@ -0,0 +1 @@
picow_bt_example(gatt_browser)

View File

@ -0,0 +1 @@
picow_bt_example(gatt_counter)

View 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)

View File

@ -0,0 +1 @@
picow_bt_example(gatt_device_information_query)

View File

@ -0,0 +1 @@
picow_bt_example(gatt_heart_rate_client)

View File

@ -0,0 +1 @@
picow_bt_example(gatt_streamer_server)

View 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)

View File

@ -0,0 +1 @@
picow_bt_example(hfp_ag_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder)

View File

@ -0,0 +1 @@
picow_bt_example(hfp_hf_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder)

View File

@ -0,0 +1 @@
picow_bt_example(hid_host_demo)

View File

@ -0,0 +1 @@
picow_bt_example(hid_keyboard_demo)

View File

@ -0,0 +1 @@
picow_bt_example(hid_mouse_demo)

View File

@ -0,0 +1 @@
picow_bt_example(hog_boot_host_demo)

View File

@ -0,0 +1 @@
picow_bt_example(hog_host_demo)

View File

@ -0,0 +1 @@
picow_bt_example(hog_keyboard_demo)

View File

@ -0,0 +1 @@
picow_bt_example(hog_mouse_demo)

View File

@ -0,0 +1 @@
picow_bt_example(hsp_ag_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder)

View File

@ -0,0 +1 @@
picow_bt_example(hsp_hs_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder)

View File

@ -0,0 +1 @@
picow_bt_example(le_credit_based_flow_control_mode_client)

View File

@ -0,0 +1 @@
picow_bt_example(le_credit_based_flow_control_mode_server)

View File

@ -0,0 +1 @@
picow_bt_example(le_mitm)

View File

@ -0,0 +1 @@
picow_bt_example(le_streamer_client)

View File

@ -0,0 +1 @@
picow_bt_example(led_counter)

View File

@ -0,0 +1 @@
picow_bt_example(mod_player pico_btstack_hxcmod_player)

View File

@ -0,0 +1 @@
picow_bt_example(nordic_spp_le_counter)

View File

@ -0,0 +1 @@
picow_bt_example(nordic_spp_le_streamer)

View 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)

View File

@ -0,0 +1 @@
picow_bt_example(pbap_client_demo)

View 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();
}

View 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
}

View 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);

View 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;
}

View 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();
}

View File

@ -0,0 +1 @@
picow_bt_example(sdp_bnep_query)

View File

@ -0,0 +1 @@
picow_bt_example(sdp_general_query)

View File

@ -0,0 +1 @@
picow_bt_example(sdp_rfcomm_query)

View File

@ -0,0 +1 @@
picow_bt_example(sine_player)

View File

@ -0,0 +1 @@
picow_bt_example(sm_pairing_central)

View File

@ -0,0 +1 @@
picow_bt_example(sm_pairing_peripheral)

View File

@ -0,0 +1 @@
picow_bt_example(spp_and_gatt_counter)

View File

@ -0,0 +1 @@
picow_bt_example(spp_and_gatt_streamer)

View File

@ -0,0 +1 @@
picow_bt_example(spp_counter)

View File

@ -0,0 +1 @@
picow_bt_example(spp_flowcontrol)

View File

@ -0,0 +1 @@
picow_bt_example(spp_streamer)

View File

@ -0,0 +1 @@
picow_bt_example(spp_streamer_client)

View 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)

View 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()

View 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

View 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(&notification_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(&notification_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;
}

View 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__ */

View 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;
}

View 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*)&current_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 *)&current_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);
}

View 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

View 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;
}

View 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,

View File

@ -0,0 +1 @@
picow_bt_example(ublox_spp_le_counter)

View 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()

View File

@ -311,11 +311,13 @@ int main() {
// you do not need it in your code
#if PICO_CYW43_ARCH_POLL
// 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();
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
// 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)
// work you might be doing.
sleep_ms(1000);

View File

@ -10,7 +10,7 @@
int main() {
stdio_init_all();
if (cyw43_arch_init()) {
printf("WiFi init failed");
printf("Wi-Fi init failed");
return -1;
}
while (true) {

View 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)

View File

@ -62,7 +62,7 @@ void main_task(__unused void *params) {
return;
}
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)) {
printf("failed to connect.\n");
exit(1);
@ -72,6 +72,7 @@ void main_task(__unused void *params) {
xTaskCreate(blink_task, "BlinkThread", configMINIMAL_STACK_SIZE, NULL, BLINK_TASK_PRIORITY, NULL);
cyw43_arch_lwip_begin();
#if CLIENT_TEST
printf("\nReady, running iperf client\n");
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)));
lwiperf_start_tcp_server_default(&iperf_report, NULL);
#endif
cyw43_arch_lwip_end();
while(true) {
// 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();

View 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

View File

@ -28,7 +28,7 @@ void main_task(__unused void *params) {
return;
}
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)) {
printf("failed to connect.\n");
exit(1);

View File

@ -14,7 +14,6 @@ target_link_libraries(picow_iperf_server_background
pico_stdlib
pico_lwip_iperf
)
pico_add_extra_outputs(picow_iperf_server_background)
add_executable(picow_iperf_server_poll

Some files were not shown because too many files have changed in this diff Show More