From 1c5d9aa567598e6e3eadf6d7f2d8a9342b44dab4 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Fri, 10 Feb 2023 17:59:58 -0600 Subject: [PATCH] Add Bluetooth examples Co-authored-by: Peter Harper <77111776+peterharperuk@users.noreply.github.com> --- CMakeLists.txt | 2 + README.md | 95 ++++- pico_extras_import_optional.cmake | 59 +++ pico_w/CMakeLists.txt | 24 +- pico_w/bt/CMakeLists.txt | 398 ++++++++++++++++++ .../FreeRTOS_Kernel_import.cmake | 0 pico_w/bt/a2dp_sink_demo/CMakeLists.txt | 7 + pico_w/bt/a2dp_source_demo/CMakeLists.txt | 1 + pico_w/bt/ancs_client_demo/CMakeLists.txt | 1 + pico_w/bt/att_delayed_response/CMakeLists.txt | 1 + .../bt/avrcp_browsing_client/CMakeLists.txt | 1 + pico_w/bt/btstack_audio_pico.c | 208 +++++++++ pico_w/bt/config/FreeRTOSConfig.h | 143 +++++++ pico_w/bt/config/btstack_config.h | 77 ++++ .../{freertos/iperf => bt/config}/lwipopts.h | 0 pico_w/bt/dut_mode_classic/CMakeLists.txt | 1 + .../bt/gap_dedicated_bonding/CMakeLists.txt | 1 + pico_w/bt/gap_inquiry/CMakeLists.txt | 1 + .../bt/gap_le_advertisements/CMakeLists.txt | 1 + pico_w/bt/gap_link_keys/CMakeLists.txt | 1 + pico_w/bt/gatt_battery_query/CMakeLists.txt | 1 + pico_w/bt/gatt_browser/CMakeLists.txt | 1 + pico_w/bt/gatt_counter/CMakeLists.txt | 1 + .../bt/gatt_counter_with_wifi/CMakeLists.txt | 6 + .../CMakeLists.txt | 1 + .../bt/gatt_heart_rate_client/CMakeLists.txt | 1 + pico_w/bt/gatt_streamer_server/CMakeLists.txt | 1 + .../CMakeLists.txt | 6 + pico_w/bt/hfp_ag_demo/CMakeLists.txt | 1 + pico_w/bt/hfp_hf_demo/CMakeLists.txt | 1 + pico_w/bt/hid_host_demo/CMakeLists.txt | 1 + pico_w/bt/hid_keyboard_demo/CMakeLists.txt | 1 + pico_w/bt/hid_mouse_demo/CMakeLists.txt | 1 + pico_w/bt/hog_boot_host_demo/CMakeLists.txt | 1 + pico_w/bt/hog_host_demo/CMakeLists.txt | 1 + pico_w/bt/hog_keyboard_demo/CMakeLists.txt | 1 + pico_w/bt/hog_mouse_demo/CMakeLists.txt | 1 + pico_w/bt/hsp_ag_demo/CMakeLists.txt | 1 + pico_w/bt/hsp_hs_demo/CMakeLists.txt | 1 + .../CMakeLists.txt | 1 + .../CMakeLists.txt | 1 + pico_w/bt/le_mitm/CMakeLists.txt | 1 + pico_w/bt/le_streamer_client/CMakeLists.txt | 1 + pico_w/bt/led_counter/CMakeLists.txt | 1 + pico_w/bt/mod_player/CMakeLists.txt | 1 + .../bt/nordic_spp_le_counter/CMakeLists.txt | 1 + .../bt/nordic_spp_le_streamer/CMakeLists.txt | 1 + pico_w/bt/pan_lwip_http_server/CMakeLists.txt | 13 + pico_w/bt/pbap_client_demo/CMakeLists.txt | 1 + pico_w/bt/picow_bt_example_background.c | 21 + pico_w/bt/picow_bt_example_common.c | 101 +++++ pico_w/bt/picow_bt_example_common.h | 18 + pico_w/bt/picow_bt_example_freertos.c | 112 +++++ pico_w/bt/picow_bt_example_poll.c | 21 + pico_w/bt/sdp_bnep_query/CMakeLists.txt | 1 + pico_w/bt/sdp_general_query/CMakeLists.txt | 1 + pico_w/bt/sdp_rfcomm_query/CMakeLists.txt | 1 + pico_w/bt/sine_player/CMakeLists.txt | 1 + pico_w/bt/sm_pairing_central/CMakeLists.txt | 1 + .../bt/sm_pairing_peripheral/CMakeLists.txt | 1 + pico_w/bt/spp_and_gatt_counter/CMakeLists.txt | 1 + .../bt/spp_and_gatt_streamer/CMakeLists.txt | 1 + pico_w/bt/spp_counter/CMakeLists.txt | 1 + pico_w/bt/spp_flowcontrol/CMakeLists.txt | 1 + pico_w/bt/spp_streamer/CMakeLists.txt | 1 + pico_w/bt/spp_streamer_client/CMakeLists.txt | 1 + .../bt/spp_streamer_with_wifi/CMakeLists.txt | 6 + pico_w/bt/standalone/CMakeLists.txt | 68 +++ pico_w/bt/standalone/btstack_config.h | 58 +++ pico_w/bt/standalone/client.c | 273 ++++++++++++ pico_w/bt/standalone/lwipopts.h | 76 ++++ pico_w/bt/standalone/server.c | 79 ++++ pico_w/bt/standalone/server_common.c | 106 +++++ pico_w/bt/standalone/server_common.h | 22 + pico_w/bt/standalone/server_with_wifi.c | 117 +++++ pico_w/bt/standalone/temp_sensor.gatt | 8 + pico_w/bt/ublox_spp_le_counter/CMakeLists.txt | 1 + pico_w/wifi/CMakeLists.txt | 25 ++ pico_w/{ => wifi}/access_point/CMakeLists.txt | 0 .../access_point/dhcpserver/LICENSE | 0 .../access_point/dhcpserver/dhcpserver.c | 0 .../access_point/dhcpserver/dhcpserver.h | 0 .../access_point/dnsserver/dnsserver.c | 0 .../access_point/dnsserver/dnsserver.h | 0 pico_w/{ => wifi}/access_point/lwipopts.h | 0 .../access_point/picow_access_point.c | 8 +- pico_w/{ => wifi}/blink/CMakeLists.txt | 0 pico_w/{ => wifi}/blink/picow_blink.c | 2 +- pico_w/{ => wifi}/freertos/CMakeLists.txt | 0 .../freertos/FreeRTOS_Kernel_import.cmake | 62 +++ .../{ => wifi}/freertos/iperf/CMakeLists.txt | 0 .../freertos/iperf/FreeRTOSConfig.h | 0 .../ping => wifi/freertos/iperf}/lwipopts.h | 0 .../freertos/iperf/picow_freertos_iperf.c | 6 +- .../{ => wifi}/freertos/ping/CMakeLists.txt | 0 .../{ => wifi}/freertos/ping/FreeRTOSConfig.h | 0 pico_w/wifi/freertos/ping/lwipopts.h | 21 + .../freertos/ping/picow_freertos_ping.c | 2 +- pico_w/{ => wifi}/iperf/CMakeLists.txt | 1 - pico_w/{ => wifi}/iperf/lwipopts.h | 0 pico_w/{ => wifi}/iperf/picow_iperf.c | 10 +- pico_w/{ => wifi}/lwipopts_examples_common.h | 0 pico_w/{ => wifi}/ntp_client/CMakeLists.txt | 0 pico_w/{ => wifi}/ntp_client/lwipopts.h | 0 .../{ => wifi}/ntp_client/picow_ntp_client.c | 7 +- .../micropython_test_tcp_client.py | 0 .../micropython_test_tcp_server.py | 0 .../python_test_tcp/python_test_tcp_client.py | 0 .../python_test_tcp/python_test_tcp_server.py | 0 pico_w/{ => wifi}/tcp_client/CMakeLists.txt | 0 pico_w/{ => wifi}/tcp_client/lwipopts.h | 0 .../{ => wifi}/tcp_client/picow_tcp_client.c | 8 +- pico_w/{ => wifi}/tcp_server/CMakeLists.txt | 0 pico_w/{ => wifi}/tcp_server/lwipopts.h | 0 .../{ => wifi}/tcp_server/picow_tcp_server.c | 8 +- pico_w/{ => wifi}/tls_client/CMakeLists.txt | 0 pico_w/{ => wifi}/tls_client/lwipopts.h | 0 pico_w/{ => wifi}/tls_client/mbedtls_config.h | 0 .../{ => wifi}/tls_client/picow_tls_client.c | 6 +- pico_w/{ => wifi}/udp_beacon/CMakeLists.txt | 0 pico_w/{ => wifi}/udp_beacon/lwipopts.h | 0 .../{ => wifi}/udp_beacon/picow_udp_beacon.c | 4 +- pico_w/{ => wifi}/wifi_scan/CMakeLists.txt | 0 pico_w/{ => wifi}/wifi_scan/lwipopts.h | 0 pico_w/{ => wifi}/wifi_scan/picow_wifi_scan.c | 14 +- pio/squarewave/CMakeLists.txt | 1 + pio/ws2812/CMakeLists.txt | 2 + 127 files changed, 2296 insertions(+), 63 deletions(-) create mode 100644 pico_extras_import_optional.cmake create mode 100644 pico_w/bt/CMakeLists.txt rename pico_w/{freertos => bt}/FreeRTOS_Kernel_import.cmake (100%) create mode 100644 pico_w/bt/a2dp_sink_demo/CMakeLists.txt create mode 100644 pico_w/bt/a2dp_source_demo/CMakeLists.txt create mode 100644 pico_w/bt/ancs_client_demo/CMakeLists.txt create mode 100644 pico_w/bt/att_delayed_response/CMakeLists.txt create mode 100644 pico_w/bt/avrcp_browsing_client/CMakeLists.txt create mode 100644 pico_w/bt/btstack_audio_pico.c create mode 100644 pico_w/bt/config/FreeRTOSConfig.h create mode 100644 pico_w/bt/config/btstack_config.h rename pico_w/{freertos/iperf => bt/config}/lwipopts.h (100%) create mode 100644 pico_w/bt/dut_mode_classic/CMakeLists.txt create mode 100644 pico_w/bt/gap_dedicated_bonding/CMakeLists.txt create mode 100644 pico_w/bt/gap_inquiry/CMakeLists.txt create mode 100644 pico_w/bt/gap_le_advertisements/CMakeLists.txt create mode 100644 pico_w/bt/gap_link_keys/CMakeLists.txt create mode 100644 pico_w/bt/gatt_battery_query/CMakeLists.txt create mode 100644 pico_w/bt/gatt_browser/CMakeLists.txt create mode 100644 pico_w/bt/gatt_counter/CMakeLists.txt create mode 100644 pico_w/bt/gatt_counter_with_wifi/CMakeLists.txt create mode 100644 pico_w/bt/gatt_device_information_query/CMakeLists.txt create mode 100644 pico_w/bt/gatt_heart_rate_client/CMakeLists.txt create mode 100644 pico_w/bt/gatt_streamer_server/CMakeLists.txt create mode 100644 pico_w/bt/gatt_streamer_server_with_wifi/CMakeLists.txt create mode 100644 pico_w/bt/hfp_ag_demo/CMakeLists.txt create mode 100644 pico_w/bt/hfp_hf_demo/CMakeLists.txt create mode 100644 pico_w/bt/hid_host_demo/CMakeLists.txt create mode 100644 pico_w/bt/hid_keyboard_demo/CMakeLists.txt create mode 100644 pico_w/bt/hid_mouse_demo/CMakeLists.txt create mode 100644 pico_w/bt/hog_boot_host_demo/CMakeLists.txt create mode 100644 pico_w/bt/hog_host_demo/CMakeLists.txt create mode 100644 pico_w/bt/hog_keyboard_demo/CMakeLists.txt create mode 100644 pico_w/bt/hog_mouse_demo/CMakeLists.txt create mode 100644 pico_w/bt/hsp_ag_demo/CMakeLists.txt create mode 100644 pico_w/bt/hsp_hs_demo/CMakeLists.txt create mode 100644 pico_w/bt/le_credit_based_flow_control_mode_client/CMakeLists.txt create mode 100644 pico_w/bt/le_credit_based_flow_control_mode_server/CMakeLists.txt create mode 100644 pico_w/bt/le_mitm/CMakeLists.txt create mode 100644 pico_w/bt/le_streamer_client/CMakeLists.txt create mode 100644 pico_w/bt/led_counter/CMakeLists.txt create mode 100644 pico_w/bt/mod_player/CMakeLists.txt create mode 100644 pico_w/bt/nordic_spp_le_counter/CMakeLists.txt create mode 100644 pico_w/bt/nordic_spp_le_streamer/CMakeLists.txt create mode 100644 pico_w/bt/pan_lwip_http_server/CMakeLists.txt create mode 100644 pico_w/bt/pbap_client_demo/CMakeLists.txt create mode 100644 pico_w/bt/picow_bt_example_background.c create mode 100644 pico_w/bt/picow_bt_example_common.c create mode 100644 pico_w/bt/picow_bt_example_common.h create mode 100644 pico_w/bt/picow_bt_example_freertos.c create mode 100644 pico_w/bt/picow_bt_example_poll.c create mode 100644 pico_w/bt/sdp_bnep_query/CMakeLists.txt create mode 100644 pico_w/bt/sdp_general_query/CMakeLists.txt create mode 100644 pico_w/bt/sdp_rfcomm_query/CMakeLists.txt create mode 100644 pico_w/bt/sine_player/CMakeLists.txt create mode 100644 pico_w/bt/sm_pairing_central/CMakeLists.txt create mode 100644 pico_w/bt/sm_pairing_peripheral/CMakeLists.txt create mode 100644 pico_w/bt/spp_and_gatt_counter/CMakeLists.txt create mode 100644 pico_w/bt/spp_and_gatt_streamer/CMakeLists.txt create mode 100644 pico_w/bt/spp_counter/CMakeLists.txt create mode 100644 pico_w/bt/spp_flowcontrol/CMakeLists.txt create mode 100644 pico_w/bt/spp_streamer/CMakeLists.txt create mode 100644 pico_w/bt/spp_streamer_client/CMakeLists.txt create mode 100644 pico_w/bt/spp_streamer_with_wifi/CMakeLists.txt create mode 100644 pico_w/bt/standalone/CMakeLists.txt create mode 100644 pico_w/bt/standalone/btstack_config.h create mode 100644 pico_w/bt/standalone/client.c create mode 100644 pico_w/bt/standalone/lwipopts.h create mode 100644 pico_w/bt/standalone/server.c create mode 100644 pico_w/bt/standalone/server_common.c create mode 100644 pico_w/bt/standalone/server_common.h create mode 100644 pico_w/bt/standalone/server_with_wifi.c create mode 100644 pico_w/bt/standalone/temp_sensor.gatt create mode 100644 pico_w/bt/ublox_spp_le_counter/CMakeLists.txt create mode 100644 pico_w/wifi/CMakeLists.txt rename pico_w/{ => wifi}/access_point/CMakeLists.txt (100%) rename pico_w/{ => wifi}/access_point/dhcpserver/LICENSE (100%) rename pico_w/{ => wifi}/access_point/dhcpserver/dhcpserver.c (100%) rename pico_w/{ => wifi}/access_point/dhcpserver/dhcpserver.h (100%) rename pico_w/{ => wifi}/access_point/dnsserver/dnsserver.c (100%) rename pico_w/{ => wifi}/access_point/dnsserver/dnsserver.h (100%) rename pico_w/{ => wifi}/access_point/lwipopts.h (100%) rename pico_w/{ => wifi}/access_point/picow_access_point.c (95%) rename pico_w/{ => wifi}/blink/CMakeLists.txt (100%) rename pico_w/{ => wifi}/blink/picow_blink.c (92%) rename pico_w/{ => wifi}/freertos/CMakeLists.txt (100%) create mode 100644 pico_w/wifi/freertos/FreeRTOS_Kernel_import.cmake rename pico_w/{ => wifi}/freertos/iperf/CMakeLists.txt (100%) rename pico_w/{ => wifi}/freertos/iperf/FreeRTOSConfig.h (100%) rename pico_w/{freertos/ping => wifi/freertos/iperf}/lwipopts.h (100%) rename pico_w/{ => wifi}/freertos/iperf/picow_freertos_iperf.c (96%) rename pico_w/{ => wifi}/freertos/ping/CMakeLists.txt (100%) rename pico_w/{ => wifi}/freertos/ping/FreeRTOSConfig.h (100%) create mode 100644 pico_w/wifi/freertos/ping/lwipopts.h rename pico_w/{ => wifi}/freertos/ping/picow_freertos_ping.c (98%) rename pico_w/{ => wifi}/iperf/CMakeLists.txt (99%) rename pico_w/{ => wifi}/iperf/lwipopts.h (100%) rename pico_w/{ => wifi}/iperf/picow_iperf.c (87%) rename pico_w/{ => wifi}/lwipopts_examples_common.h (100%) rename pico_w/{ => wifi}/ntp_client/CMakeLists.txt (100%) rename pico_w/{ => wifi}/ntp_client/lwipopts.h (100%) rename pico_w/{ => wifi}/ntp_client/picow_ntp_client.c (93%) rename pico_w/{ => wifi}/python_test_tcp/micropython_test_tcp_client.py (100%) rename pico_w/{ => wifi}/python_test_tcp/micropython_test_tcp_server.py (100%) rename pico_w/{ => wifi}/python_test_tcp/python_test_tcp_client.py (100%) rename pico_w/{ => wifi}/python_test_tcp/python_test_tcp_server.py (100%) rename pico_w/{ => wifi}/tcp_client/CMakeLists.txt (100%) rename pico_w/{ => wifi}/tcp_client/lwipopts.h (100%) rename pico_w/{ => wifi}/tcp_client/picow_tcp_client.c (94%) rename pico_w/{ => wifi}/tcp_server/CMakeLists.txt (100%) rename pico_w/{ => wifi}/tcp_server/lwipopts.h (100%) rename pico_w/{ => wifi}/tcp_server/picow_tcp_server.c (95%) rename pico_w/{ => wifi}/tls_client/CMakeLists.txt (100%) rename pico_w/{ => wifi}/tls_client/lwipopts.h (100%) rename pico_w/{ => wifi}/tls_client/mbedtls_config.h (100%) rename pico_w/{ => wifi}/tls_client/picow_tls_client.c (95%) rename pico_w/{ => wifi}/udp_beacon/CMakeLists.txt (100%) rename pico_w/{ => wifi}/udp_beacon/lwipopts.h (100%) rename pico_w/{ => wifi}/udp_beacon/picow_udp_beacon.c (93%) rename pico_w/{ => wifi}/wifi_scan/CMakeLists.txt (100%) rename pico_w/{ => wifi}/wifi_scan/lwipopts.h (100%) rename pico_w/{ => wifi}/wifi_scan/picow_wifi_scan.c (77%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e69739..fc91638 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/README.md b/README.md index 3f69f38..abf8344 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/pico_extras_import_optional.cmake b/pico_extras_import_optional.cmake new file mode 100644 index 0000000..692e14a --- /dev/null +++ b/pico_extras_import_optional.cmake @@ -0,0 +1,59 @@ +# This is a copy of /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() \ No newline at end of file diff --git a/pico_w/CMakeLists.txt b/pico_w/CMakeLists.txt index 4de3936..f66c02e 100644 --- a/pico_w/CMakeLists.txt +++ b/pico_w/CMakeLists.txt @@ -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() diff --git a/pico_w/bt/CMakeLists.txt b/pico_w/bt/CMakeLists.txt new file mode 100644 index 0000000..3ea5f33 --- /dev/null +++ b/pico_w/bt/CMakeLists.txt @@ -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() diff --git a/pico_w/freertos/FreeRTOS_Kernel_import.cmake b/pico_w/bt/FreeRTOS_Kernel_import.cmake similarity index 100% rename from pico_w/freertos/FreeRTOS_Kernel_import.cmake rename to pico_w/bt/FreeRTOS_Kernel_import.cmake diff --git a/pico_w/bt/a2dp_sink_demo/CMakeLists.txt b/pico_w/bt/a2dp_sink_demo/CMakeLists.txt new file mode 100644 index 0000000..d92d715 --- /dev/null +++ b/pico_w/bt/a2dp_sink_demo/CMakeLists.txt @@ -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) diff --git a/pico_w/bt/a2dp_source_demo/CMakeLists.txt b/pico_w/bt/a2dp_source_demo/CMakeLists.txt new file mode 100644 index 0000000..f3ff454 --- /dev/null +++ b/pico_w/bt/a2dp_source_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(a2dp_source_demo pico_btstack_hxcmod_player pico_btstack_sbc_encoder) \ No newline at end of file diff --git a/pico_w/bt/ancs_client_demo/CMakeLists.txt b/pico_w/bt/ancs_client_demo/CMakeLists.txt new file mode 100644 index 0000000..3a0c52f --- /dev/null +++ b/pico_w/bt/ancs_client_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(ancs_client_demo) diff --git a/pico_w/bt/att_delayed_response/CMakeLists.txt b/pico_w/bt/att_delayed_response/CMakeLists.txt new file mode 100644 index 0000000..441475a --- /dev/null +++ b/pico_w/bt/att_delayed_response/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(att_delayed_response) diff --git a/pico_w/bt/avrcp_browsing_client/CMakeLists.txt b/pico_w/bt/avrcp_browsing_client/CMakeLists.txt new file mode 100644 index 0000000..f78762e --- /dev/null +++ b/pico_w/bt/avrcp_browsing_client/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(avrcp_browsing_client) diff --git a/pico_w/bt/btstack_audio_pico.c b/pico_w/bt/btstack_audio_pico.c new file mode 100644 index 0000000..f98fc1e --- /dev/null +++ b/pico_w/bt/btstack_audio_pico.c @@ -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 +#include + +#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; +} diff --git a/pico_w/bt/config/FreeRTOSConfig.h b/pico_w/bt/config/FreeRTOSConfig.h new file mode 100644 index 0000000..f39428d --- /dev/null +++ b/pico_w/bt/config/FreeRTOSConfig.h @@ -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 +/* 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 */ + diff --git a/pico_w/bt/config/btstack_config.h b/pico_w/bt/config/btstack_config.h new file mode 100644 index 0000000..dfc89f8 --- /dev/null +++ b/pico_w/bt/config/btstack_config.h @@ -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 diff --git a/pico_w/freertos/iperf/lwipopts.h b/pico_w/bt/config/lwipopts.h similarity index 100% rename from pico_w/freertos/iperf/lwipopts.h rename to pico_w/bt/config/lwipopts.h diff --git a/pico_w/bt/dut_mode_classic/CMakeLists.txt b/pico_w/bt/dut_mode_classic/CMakeLists.txt new file mode 100644 index 0000000..44bc17f --- /dev/null +++ b/pico_w/bt/dut_mode_classic/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(dut_mode_classic) diff --git a/pico_w/bt/gap_dedicated_bonding/CMakeLists.txt b/pico_w/bt/gap_dedicated_bonding/CMakeLists.txt new file mode 100644 index 0000000..72daea2 --- /dev/null +++ b/pico_w/bt/gap_dedicated_bonding/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(gap_dedicated_bonding) diff --git a/pico_w/bt/gap_inquiry/CMakeLists.txt b/pico_w/bt/gap_inquiry/CMakeLists.txt new file mode 100644 index 0000000..383582e --- /dev/null +++ b/pico_w/bt/gap_inquiry/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(gap_inquiry) diff --git a/pico_w/bt/gap_le_advertisements/CMakeLists.txt b/pico_w/bt/gap_le_advertisements/CMakeLists.txt new file mode 100644 index 0000000..07f6093 --- /dev/null +++ b/pico_w/bt/gap_le_advertisements/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(gap_le_advertisements) diff --git a/pico_w/bt/gap_link_keys/CMakeLists.txt b/pico_w/bt/gap_link_keys/CMakeLists.txt new file mode 100644 index 0000000..b20dfc6 --- /dev/null +++ b/pico_w/bt/gap_link_keys/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(gap_link_keys) diff --git a/pico_w/bt/gatt_battery_query/CMakeLists.txt b/pico_w/bt/gatt_battery_query/CMakeLists.txt new file mode 100644 index 0000000..f4669eb --- /dev/null +++ b/pico_w/bt/gatt_battery_query/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(gatt_battery_query) diff --git a/pico_w/bt/gatt_browser/CMakeLists.txt b/pico_w/bt/gatt_browser/CMakeLists.txt new file mode 100644 index 0000000..42971bc --- /dev/null +++ b/pico_w/bt/gatt_browser/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(gatt_browser) diff --git a/pico_w/bt/gatt_counter/CMakeLists.txt b/pico_w/bt/gatt_counter/CMakeLists.txt new file mode 100644 index 0000000..287e542 --- /dev/null +++ b/pico_w/bt/gatt_counter/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(gatt_counter) diff --git a/pico_w/bt/gatt_counter_with_wifi/CMakeLists.txt b/pico_w/bt/gatt_counter_with_wifi/CMakeLists.txt new file mode 100644 index 0000000..500deca --- /dev/null +++ b/pico_w/bt/gatt_counter_with_wifi/CMakeLists.txt @@ -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) diff --git a/pico_w/bt/gatt_device_information_query/CMakeLists.txt b/pico_w/bt/gatt_device_information_query/CMakeLists.txt new file mode 100644 index 0000000..227acc3 --- /dev/null +++ b/pico_w/bt/gatt_device_information_query/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(gatt_device_information_query) diff --git a/pico_w/bt/gatt_heart_rate_client/CMakeLists.txt b/pico_w/bt/gatt_heart_rate_client/CMakeLists.txt new file mode 100644 index 0000000..5766c54 --- /dev/null +++ b/pico_w/bt/gatt_heart_rate_client/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(gatt_heart_rate_client) diff --git a/pico_w/bt/gatt_streamer_server/CMakeLists.txt b/pico_w/bt/gatt_streamer_server/CMakeLists.txt new file mode 100644 index 0000000..1e5ea1d --- /dev/null +++ b/pico_w/bt/gatt_streamer_server/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(gatt_streamer_server) diff --git a/pico_w/bt/gatt_streamer_server_with_wifi/CMakeLists.txt b/pico_w/bt/gatt_streamer_server_with_wifi/CMakeLists.txt new file mode 100644 index 0000000..d705b54 --- /dev/null +++ b/pico_w/bt/gatt_streamer_server_with_wifi/CMakeLists.txt @@ -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) diff --git a/pico_w/bt/hfp_ag_demo/CMakeLists.txt b/pico_w/bt/hfp_ag_demo/CMakeLists.txt new file mode 100644 index 0000000..5a5b604 --- /dev/null +++ b/pico_w/bt/hfp_ag_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(hfp_ag_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder) diff --git a/pico_w/bt/hfp_hf_demo/CMakeLists.txt b/pico_w/bt/hfp_hf_demo/CMakeLists.txt new file mode 100644 index 0000000..cf8d89c --- /dev/null +++ b/pico_w/bt/hfp_hf_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(hfp_hf_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder) diff --git a/pico_w/bt/hid_host_demo/CMakeLists.txt b/pico_w/bt/hid_host_demo/CMakeLists.txt new file mode 100644 index 0000000..3febdba --- /dev/null +++ b/pico_w/bt/hid_host_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(hid_host_demo) diff --git a/pico_w/bt/hid_keyboard_demo/CMakeLists.txt b/pico_w/bt/hid_keyboard_demo/CMakeLists.txt new file mode 100644 index 0000000..29a8ac7 --- /dev/null +++ b/pico_w/bt/hid_keyboard_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(hid_keyboard_demo) diff --git a/pico_w/bt/hid_mouse_demo/CMakeLists.txt b/pico_w/bt/hid_mouse_demo/CMakeLists.txt new file mode 100644 index 0000000..aebb18a --- /dev/null +++ b/pico_w/bt/hid_mouse_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(hid_mouse_demo) diff --git a/pico_w/bt/hog_boot_host_demo/CMakeLists.txt b/pico_w/bt/hog_boot_host_demo/CMakeLists.txt new file mode 100644 index 0000000..536649d --- /dev/null +++ b/pico_w/bt/hog_boot_host_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(hog_boot_host_demo) diff --git a/pico_w/bt/hog_host_demo/CMakeLists.txt b/pico_w/bt/hog_host_demo/CMakeLists.txt new file mode 100644 index 0000000..c7ce663 --- /dev/null +++ b/pico_w/bt/hog_host_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(hog_host_demo) diff --git a/pico_w/bt/hog_keyboard_demo/CMakeLists.txt b/pico_w/bt/hog_keyboard_demo/CMakeLists.txt new file mode 100644 index 0000000..6cae1e2 --- /dev/null +++ b/pico_w/bt/hog_keyboard_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(hog_keyboard_demo) diff --git a/pico_w/bt/hog_mouse_demo/CMakeLists.txt b/pico_w/bt/hog_mouse_demo/CMakeLists.txt new file mode 100644 index 0000000..2e176ef --- /dev/null +++ b/pico_w/bt/hog_mouse_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(hog_mouse_demo) diff --git a/pico_w/bt/hsp_ag_demo/CMakeLists.txt b/pico_w/bt/hsp_ag_demo/CMakeLists.txt new file mode 100644 index 0000000..1cdcfe0 --- /dev/null +++ b/pico_w/bt/hsp_ag_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(hsp_ag_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder) diff --git a/pico_w/bt/hsp_hs_demo/CMakeLists.txt b/pico_w/bt/hsp_hs_demo/CMakeLists.txt new file mode 100644 index 0000000..24221c6 --- /dev/null +++ b/pico_w/bt/hsp_hs_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(hsp_hs_demo pico_btstack_sco_demo_util pico_btstack_sbc_encoder) diff --git a/pico_w/bt/le_credit_based_flow_control_mode_client/CMakeLists.txt b/pico_w/bt/le_credit_based_flow_control_mode_client/CMakeLists.txt new file mode 100644 index 0000000..addcbe0 --- /dev/null +++ b/pico_w/bt/le_credit_based_flow_control_mode_client/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(le_credit_based_flow_control_mode_client) diff --git a/pico_w/bt/le_credit_based_flow_control_mode_server/CMakeLists.txt b/pico_w/bt/le_credit_based_flow_control_mode_server/CMakeLists.txt new file mode 100644 index 0000000..60529c9 --- /dev/null +++ b/pico_w/bt/le_credit_based_flow_control_mode_server/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(le_credit_based_flow_control_mode_server) diff --git a/pico_w/bt/le_mitm/CMakeLists.txt b/pico_w/bt/le_mitm/CMakeLists.txt new file mode 100644 index 0000000..0fc965f --- /dev/null +++ b/pico_w/bt/le_mitm/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(le_mitm) diff --git a/pico_w/bt/le_streamer_client/CMakeLists.txt b/pico_w/bt/le_streamer_client/CMakeLists.txt new file mode 100644 index 0000000..256f1df --- /dev/null +++ b/pico_w/bt/le_streamer_client/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(le_streamer_client) diff --git a/pico_w/bt/led_counter/CMakeLists.txt b/pico_w/bt/led_counter/CMakeLists.txt new file mode 100644 index 0000000..9351f10 --- /dev/null +++ b/pico_w/bt/led_counter/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(led_counter) diff --git a/pico_w/bt/mod_player/CMakeLists.txt b/pico_w/bt/mod_player/CMakeLists.txt new file mode 100644 index 0000000..1069015 --- /dev/null +++ b/pico_w/bt/mod_player/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(mod_player pico_btstack_hxcmod_player) diff --git a/pico_w/bt/nordic_spp_le_counter/CMakeLists.txt b/pico_w/bt/nordic_spp_le_counter/CMakeLists.txt new file mode 100644 index 0000000..9bb804f --- /dev/null +++ b/pico_w/bt/nordic_spp_le_counter/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(nordic_spp_le_counter) diff --git a/pico_w/bt/nordic_spp_le_streamer/CMakeLists.txt b/pico_w/bt/nordic_spp_le_streamer/CMakeLists.txt new file mode 100644 index 0000000..0d3b48c --- /dev/null +++ b/pico_w/bt/nordic_spp_le_streamer/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(nordic_spp_le_streamer) diff --git a/pico_w/bt/pan_lwip_http_server/CMakeLists.txt b/pico_w/bt/pan_lwip_http_server/CMakeLists.txt new file mode 100644 index 0000000..8904080 --- /dev/null +++ b/pico_w/bt/pan_lwip_http_server/CMakeLists.txt @@ -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) diff --git a/pico_w/bt/pbap_client_demo/CMakeLists.txt b/pico_w/bt/pbap_client_demo/CMakeLists.txt new file mode 100644 index 0000000..503c52b --- /dev/null +++ b/pico_w/bt/pbap_client_demo/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(pbap_client_demo) diff --git a/pico_w/bt/picow_bt_example_background.c b/pico_w/bt/picow_bt_example_background.c new file mode 100644 index 0000000..24794d2 --- /dev/null +++ b/pico_w/bt/picow_bt_example_background.c @@ -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(); +} diff --git a/pico_w/bt/picow_bt_example_common.c b/pico_w/bt/picow_bt_example_common.c new file mode 100644 index 0000000..3c80213 --- /dev/null +++ b/pico_w/bt/picow_bt_example_common.c @@ -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 +} diff --git a/pico_w/bt/picow_bt_example_common.h b/pico_w/bt/picow_bt_example_common.h new file mode 100644 index 0000000..7253227 --- /dev/null +++ b/pico_w/bt/picow_bt_example_common.h @@ -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); diff --git a/pico_w/bt/picow_bt_example_freertos.c b/pico_w/bt/picow_bt_example_freertos.c new file mode 100644 index 0000000..fa38614 --- /dev/null +++ b/pico_w/bt/picow_bt_example_freertos.c @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2022 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#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; +} diff --git a/pico_w/bt/picow_bt_example_poll.c b/pico_w/bt/picow_bt_example_poll.c new file mode 100644 index 0000000..24794d2 --- /dev/null +++ b/pico_w/bt/picow_bt_example_poll.c @@ -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(); +} diff --git a/pico_w/bt/sdp_bnep_query/CMakeLists.txt b/pico_w/bt/sdp_bnep_query/CMakeLists.txt new file mode 100644 index 0000000..17cb14f --- /dev/null +++ b/pico_w/bt/sdp_bnep_query/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(sdp_bnep_query) diff --git a/pico_w/bt/sdp_general_query/CMakeLists.txt b/pico_w/bt/sdp_general_query/CMakeLists.txt new file mode 100644 index 0000000..e095cde --- /dev/null +++ b/pico_w/bt/sdp_general_query/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(sdp_general_query) diff --git a/pico_w/bt/sdp_rfcomm_query/CMakeLists.txt b/pico_w/bt/sdp_rfcomm_query/CMakeLists.txt new file mode 100644 index 0000000..f558231 --- /dev/null +++ b/pico_w/bt/sdp_rfcomm_query/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(sdp_rfcomm_query) diff --git a/pico_w/bt/sine_player/CMakeLists.txt b/pico_w/bt/sine_player/CMakeLists.txt new file mode 100644 index 0000000..97edf79 --- /dev/null +++ b/pico_w/bt/sine_player/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(sine_player) diff --git a/pico_w/bt/sm_pairing_central/CMakeLists.txt b/pico_w/bt/sm_pairing_central/CMakeLists.txt new file mode 100644 index 0000000..456096d --- /dev/null +++ b/pico_w/bt/sm_pairing_central/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(sm_pairing_central) diff --git a/pico_w/bt/sm_pairing_peripheral/CMakeLists.txt b/pico_w/bt/sm_pairing_peripheral/CMakeLists.txt new file mode 100644 index 0000000..66e5a27 --- /dev/null +++ b/pico_w/bt/sm_pairing_peripheral/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(sm_pairing_peripheral) diff --git a/pico_w/bt/spp_and_gatt_counter/CMakeLists.txt b/pico_w/bt/spp_and_gatt_counter/CMakeLists.txt new file mode 100644 index 0000000..7ed8e4a --- /dev/null +++ b/pico_w/bt/spp_and_gatt_counter/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(spp_and_gatt_counter) diff --git a/pico_w/bt/spp_and_gatt_streamer/CMakeLists.txt b/pico_w/bt/spp_and_gatt_streamer/CMakeLists.txt new file mode 100644 index 0000000..47afd6a --- /dev/null +++ b/pico_w/bt/spp_and_gatt_streamer/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(spp_and_gatt_streamer) diff --git a/pico_w/bt/spp_counter/CMakeLists.txt b/pico_w/bt/spp_counter/CMakeLists.txt new file mode 100644 index 0000000..9465d5c --- /dev/null +++ b/pico_w/bt/spp_counter/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(spp_counter) diff --git a/pico_w/bt/spp_flowcontrol/CMakeLists.txt b/pico_w/bt/spp_flowcontrol/CMakeLists.txt new file mode 100644 index 0000000..75c4b83 --- /dev/null +++ b/pico_w/bt/spp_flowcontrol/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(spp_flowcontrol) diff --git a/pico_w/bt/spp_streamer/CMakeLists.txt b/pico_w/bt/spp_streamer/CMakeLists.txt new file mode 100644 index 0000000..f35d401 --- /dev/null +++ b/pico_w/bt/spp_streamer/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(spp_streamer) diff --git a/pico_w/bt/spp_streamer_client/CMakeLists.txt b/pico_w/bt/spp_streamer_client/CMakeLists.txt new file mode 100644 index 0000000..b858388 --- /dev/null +++ b/pico_w/bt/spp_streamer_client/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(spp_streamer_client) diff --git a/pico_w/bt/spp_streamer_with_wifi/CMakeLists.txt b/pico_w/bt/spp_streamer_with_wifi/CMakeLists.txt new file mode 100644 index 0000000..02ed945 --- /dev/null +++ b/pico_w/bt/spp_streamer_with_wifi/CMakeLists.txt @@ -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) diff --git a/pico_w/bt/standalone/CMakeLists.txt b/pico_w/bt/standalone/CMakeLists.txt new file mode 100644 index 0000000..28d20b6 --- /dev/null +++ b/pico_w/bt/standalone/CMakeLists.txt @@ -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() diff --git a/pico_w/bt/standalone/btstack_config.h b/pico_w/bt/standalone/btstack_config.h new file mode 100644 index 0000000..c392dff --- /dev/null +++ b/pico_w/bt/standalone/btstack_config.h @@ -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 diff --git a/pico_w/bt/standalone/client.c b/pico_w/bt/standalone/client.c new file mode 100644 index 0000000..19e599c --- /dev/null +++ b/pico_w/bt/standalone/client.c @@ -0,0 +1,273 @@ +/** + * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#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; +} diff --git a/pico_w/bt/standalone/lwipopts.h b/pico_w/bt/standalone/lwipopts.h new file mode 100644 index 0000000..32bb24c --- /dev/null +++ b/pico_w/bt/standalone/lwipopts.h @@ -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__ */ diff --git a/pico_w/bt/standalone/server.c b/pico_w/bt/standalone/server.c new file mode 100644 index 0000000..0ac0e6b --- /dev/null +++ b/pico_w/bt/standalone/server.c @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#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; +} diff --git a/pico_w/bt/standalone/server_common.c b/pico_w/bt/standalone/server_common.c new file mode 100644 index 0000000..fd42919 --- /dev/null +++ b/pico_w/bt/standalone/server_common.c @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#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); + } \ No newline at end of file diff --git a/pico_w/bt/standalone/server_common.h b/pico_w/bt/standalone/server_common.h new file mode 100644 index 0000000..80b9c59 --- /dev/null +++ b/pico_w/bt/standalone/server_common.h @@ -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 diff --git a/pico_w/bt/standalone/server_with_wifi.c b/pico_w/bt/standalone/server_with_wifi.c new file mode 100644 index 0000000..f8fce4d --- /dev/null +++ b/pico_w/bt/standalone/server_with_wifi.c @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#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; +} diff --git a/pico_w/bt/standalone/temp_sensor.gatt b/pico_w/bt/standalone/temp_sensor.gatt new file mode 100644 index 0000000..5df3084 --- /dev/null +++ b/pico_w/bt/standalone/temp_sensor.gatt @@ -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, diff --git a/pico_w/bt/ublox_spp_le_counter/CMakeLists.txt b/pico_w/bt/ublox_spp_le_counter/CMakeLists.txt new file mode 100644 index 0000000..92ef01c --- /dev/null +++ b/pico_w/bt/ublox_spp_le_counter/CMakeLists.txt @@ -0,0 +1 @@ +picow_bt_example(ublox_spp_le_counter) diff --git a/pico_w/wifi/CMakeLists.txt b/pico_w/wifi/CMakeLists.txt new file mode 100644 index 0000000..8288eb7 --- /dev/null +++ b/pico_w/wifi/CMakeLists.txt @@ -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() diff --git a/pico_w/access_point/CMakeLists.txt b/pico_w/wifi/access_point/CMakeLists.txt similarity index 100% rename from pico_w/access_point/CMakeLists.txt rename to pico_w/wifi/access_point/CMakeLists.txt diff --git a/pico_w/access_point/dhcpserver/LICENSE b/pico_w/wifi/access_point/dhcpserver/LICENSE similarity index 100% rename from pico_w/access_point/dhcpserver/LICENSE rename to pico_w/wifi/access_point/dhcpserver/LICENSE diff --git a/pico_w/access_point/dhcpserver/dhcpserver.c b/pico_w/wifi/access_point/dhcpserver/dhcpserver.c similarity index 100% rename from pico_w/access_point/dhcpserver/dhcpserver.c rename to pico_w/wifi/access_point/dhcpserver/dhcpserver.c diff --git a/pico_w/access_point/dhcpserver/dhcpserver.h b/pico_w/wifi/access_point/dhcpserver/dhcpserver.h similarity index 100% rename from pico_w/access_point/dhcpserver/dhcpserver.h rename to pico_w/wifi/access_point/dhcpserver/dhcpserver.h diff --git a/pico_w/access_point/dnsserver/dnsserver.c b/pico_w/wifi/access_point/dnsserver/dnsserver.c similarity index 100% rename from pico_w/access_point/dnsserver/dnsserver.c rename to pico_w/wifi/access_point/dnsserver/dnsserver.c diff --git a/pico_w/access_point/dnsserver/dnsserver.h b/pico_w/wifi/access_point/dnsserver/dnsserver.h similarity index 100% rename from pico_w/access_point/dnsserver/dnsserver.h rename to pico_w/wifi/access_point/dnsserver/dnsserver.h diff --git a/pico_w/access_point/lwipopts.h b/pico_w/wifi/access_point/lwipopts.h similarity index 100% rename from pico_w/access_point/lwipopts.h rename to pico_w/wifi/access_point/lwipopts.h diff --git a/pico_w/access_point/picow_access_point.c b/pico_w/wifi/access_point/picow_access_point.c similarity index 95% rename from pico_w/access_point/picow_access_point.c rename to pico_w/wifi/access_point/picow_access_point.c index 899e61f..20b586d 100644 --- a/pico_w/access_point/picow_access_point.c +++ b/pico_w/wifi/access_point/picow_access_point.c @@ -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); diff --git a/pico_w/blink/CMakeLists.txt b/pico_w/wifi/blink/CMakeLists.txt similarity index 100% rename from pico_w/blink/CMakeLists.txt rename to pico_w/wifi/blink/CMakeLists.txt diff --git a/pico_w/blink/picow_blink.c b/pico_w/wifi/blink/picow_blink.c similarity index 92% rename from pico_w/blink/picow_blink.c rename to pico_w/wifi/blink/picow_blink.c index d5d7ac4..149b477 100644 --- a/pico_w/blink/picow_blink.c +++ b/pico_w/wifi/blink/picow_blink.c @@ -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) { diff --git a/pico_w/freertos/CMakeLists.txt b/pico_w/wifi/freertos/CMakeLists.txt similarity index 100% rename from pico_w/freertos/CMakeLists.txt rename to pico_w/wifi/freertos/CMakeLists.txt diff --git a/pico_w/wifi/freertos/FreeRTOS_Kernel_import.cmake b/pico_w/wifi/freertos/FreeRTOS_Kernel_import.cmake new file mode 100644 index 0000000..dc68ed0 --- /dev/null +++ b/pico_w/wifi/freertos/FreeRTOS_Kernel_import.cmake @@ -0,0 +1,62 @@ +# This is a copy of /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) \ No newline at end of file diff --git a/pico_w/freertos/iperf/CMakeLists.txt b/pico_w/wifi/freertos/iperf/CMakeLists.txt similarity index 100% rename from pico_w/freertos/iperf/CMakeLists.txt rename to pico_w/wifi/freertos/iperf/CMakeLists.txt diff --git a/pico_w/freertos/iperf/FreeRTOSConfig.h b/pico_w/wifi/freertos/iperf/FreeRTOSConfig.h similarity index 100% rename from pico_w/freertos/iperf/FreeRTOSConfig.h rename to pico_w/wifi/freertos/iperf/FreeRTOSConfig.h diff --git a/pico_w/freertos/ping/lwipopts.h b/pico_w/wifi/freertos/iperf/lwipopts.h similarity index 100% rename from pico_w/freertos/ping/lwipopts.h rename to pico_w/wifi/freertos/iperf/lwipopts.h diff --git a/pico_w/freertos/iperf/picow_freertos_iperf.c b/pico_w/wifi/freertos/iperf/picow_freertos_iperf.c similarity index 96% rename from pico_w/freertos/iperf/picow_freertos_iperf.c rename to pico_w/wifi/freertos/iperf/picow_freertos_iperf.c index d409514..73b0f19 100644 --- a/pico_w/freertos/iperf/picow_freertos_iperf.c +++ b/pico_w/wifi/freertos/iperf/picow_freertos_iperf.c @@ -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(); diff --git a/pico_w/freertos/ping/CMakeLists.txt b/pico_w/wifi/freertos/ping/CMakeLists.txt similarity index 100% rename from pico_w/freertos/ping/CMakeLists.txt rename to pico_w/wifi/freertos/ping/CMakeLists.txt diff --git a/pico_w/freertos/ping/FreeRTOSConfig.h b/pico_w/wifi/freertos/ping/FreeRTOSConfig.h similarity index 100% rename from pico_w/freertos/ping/FreeRTOSConfig.h rename to pico_w/wifi/freertos/ping/FreeRTOSConfig.h diff --git a/pico_w/wifi/freertos/ping/lwipopts.h b/pico_w/wifi/freertos/ping/lwipopts.h new file mode 100644 index 0000000..b8983d7 --- /dev/null +++ b/pico_w/wifi/freertos/ping/lwipopts.h @@ -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 diff --git a/pico_w/freertos/ping/picow_freertos_ping.c b/pico_w/wifi/freertos/ping/picow_freertos_ping.c similarity index 98% rename from pico_w/freertos/ping/picow_freertos_ping.c rename to pico_w/wifi/freertos/ping/picow_freertos_ping.c index 48499a3..a20c1d7 100644 --- a/pico_w/freertos/ping/picow_freertos_ping.c +++ b/pico_w/wifi/freertos/ping/picow_freertos_ping.c @@ -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); diff --git a/pico_w/iperf/CMakeLists.txt b/pico_w/wifi/iperf/CMakeLists.txt similarity index 99% rename from pico_w/iperf/CMakeLists.txt rename to pico_w/wifi/iperf/CMakeLists.txt index d9c43fe..56a6a1b 100644 --- a/pico_w/iperf/CMakeLists.txt +++ b/pico_w/wifi/iperf/CMakeLists.txt @@ -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 diff --git a/pico_w/iperf/lwipopts.h b/pico_w/wifi/iperf/lwipopts.h similarity index 100% rename from pico_w/iperf/lwipopts.h rename to pico_w/wifi/iperf/lwipopts.h diff --git a/pico_w/iperf/picow_iperf.c b/pico_w/wifi/iperf/picow_iperf.c similarity index 87% rename from pico_w/iperf/picow_iperf.c rename to pico_w/wifi/iperf/picow_iperf.c index cd479cc..6e90d5d 100644 --- a/pico_w/iperf/picow_iperf.c +++ b/pico_w/wifi/iperf/picow_iperf.c @@ -44,7 +44,7 @@ int main() { return 1; } 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"); return 1; @@ -52,6 +52,7 @@ int main() { printf("Connected.\n"); } + cyw43_arch_lwip_begin(); #if CLIENT_TEST printf("\nReady, running iperf client\n"); ip_addr_t clientaddr; @@ -61,6 +62,7 @@ int main() { 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) { #if USE_LED @@ -83,9 +85,11 @@ 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(led_time); #else // if you are not using pico_cyw43_arch_poll, then WiFI driver and lwIP work // is done via interrupt in the background. This sleep is just an example of some (blocking) diff --git a/pico_w/lwipopts_examples_common.h b/pico_w/wifi/lwipopts_examples_common.h similarity index 100% rename from pico_w/lwipopts_examples_common.h rename to pico_w/wifi/lwipopts_examples_common.h diff --git a/pico_w/ntp_client/CMakeLists.txt b/pico_w/wifi/ntp_client/CMakeLists.txt similarity index 100% rename from pico_w/ntp_client/CMakeLists.txt rename to pico_w/wifi/ntp_client/CMakeLists.txt diff --git a/pico_w/ntp_client/lwipopts.h b/pico_w/wifi/ntp_client/lwipopts.h similarity index 100% rename from pico_w/ntp_client/lwipopts.h rename to pico_w/wifi/ntp_client/lwipopts.h diff --git a/pico_w/ntp_client/picow_ntp_client.c b/pico_w/wifi/ntp_client/picow_ntp_client.c similarity index 93% rename from pico_w/ntp_client/picow_ntp_client.c rename to pico_w/wifi/ntp_client/picow_ntp_client.c index e39d178..fb76304 100644 --- a/pico_w/ntp_client/picow_ntp_client.c +++ b/pico_w/wifi/ntp_client/picow_ntp_client.c @@ -130,7 +130,6 @@ void run_ntp_test(void) { return; while(true) { if (absolute_time_diff_us(get_absolute_time(), state->ntp_test_time) < 0 && !state->dns_request_sent) { - // Set alarm in case udp requests are lost state->ntp_resend_alarm = add_alarm_in_ms(NTP_RESEND_TIME, ntp_failed_handler, state, true); @@ -152,9 +151,11 @@ void run_ntp_test(void) { } #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(state->dns_request_sent ? at_the_end_of_time : state->ntp_test_time); #else // if you are not using pico_cyw43_arch_poll, then WiFI driver and lwIP work // is done via interrupt in the background. This sleep is just an example of some (blocking) diff --git a/pico_w/python_test_tcp/micropython_test_tcp_client.py b/pico_w/wifi/python_test_tcp/micropython_test_tcp_client.py similarity index 100% rename from pico_w/python_test_tcp/micropython_test_tcp_client.py rename to pico_w/wifi/python_test_tcp/micropython_test_tcp_client.py diff --git a/pico_w/python_test_tcp/micropython_test_tcp_server.py b/pico_w/wifi/python_test_tcp/micropython_test_tcp_server.py similarity index 100% rename from pico_w/python_test_tcp/micropython_test_tcp_server.py rename to pico_w/wifi/python_test_tcp/micropython_test_tcp_server.py diff --git a/pico_w/python_test_tcp/python_test_tcp_client.py b/pico_w/wifi/python_test_tcp/python_test_tcp_client.py similarity index 100% rename from pico_w/python_test_tcp/python_test_tcp_client.py rename to pico_w/wifi/python_test_tcp/python_test_tcp_client.py diff --git a/pico_w/python_test_tcp/python_test_tcp_server.py b/pico_w/wifi/python_test_tcp/python_test_tcp_server.py similarity index 100% rename from pico_w/python_test_tcp/python_test_tcp_server.py rename to pico_w/wifi/python_test_tcp/python_test_tcp_server.py diff --git a/pico_w/tcp_client/CMakeLists.txt b/pico_w/wifi/tcp_client/CMakeLists.txt similarity index 100% rename from pico_w/tcp_client/CMakeLists.txt rename to pico_w/wifi/tcp_client/CMakeLists.txt diff --git a/pico_w/tcp_client/lwipopts.h b/pico_w/wifi/tcp_client/lwipopts.h similarity index 100% rename from pico_w/tcp_client/lwipopts.h rename to pico_w/wifi/tcp_client/lwipopts.h diff --git a/pico_w/tcp_client/picow_tcp_client.c b/pico_w/wifi/tcp_client/picow_tcp_client.c similarity index 94% rename from pico_w/tcp_client/picow_tcp_client.c rename to pico_w/wifi/tcp_client/picow_tcp_client.c index 9d7ba3f..397937c 100644 --- a/pico_w/tcp_client/picow_tcp_client.c +++ b/pico_w/wifi/tcp_client/picow_tcp_client.c @@ -219,9 +219,11 @@ void run_tcp_client_test(void) { // 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) 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 // is done via interrupt in the background. This sleep is just an example of some (blocking) @@ -241,7 +243,7 @@ int main() { } 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"); return 1; diff --git a/pico_w/tcp_server/CMakeLists.txt b/pico_w/wifi/tcp_server/CMakeLists.txt similarity index 100% rename from pico_w/tcp_server/CMakeLists.txt rename to pico_w/wifi/tcp_server/CMakeLists.txt diff --git a/pico_w/tcp_server/lwipopts.h b/pico_w/wifi/tcp_server/lwipopts.h similarity index 100% rename from pico_w/tcp_server/lwipopts.h rename to pico_w/wifi/tcp_server/lwipopts.h diff --git a/pico_w/tcp_server/picow_tcp_server.c b/pico_w/wifi/tcp_server/picow_tcp_server.c similarity index 95% rename from pico_w/tcp_server/picow_tcp_server.c rename to pico_w/wifi/tcp_server/picow_tcp_server.c index 871f819..f9b500e 100644 --- a/pico_w/tcp_server/picow_tcp_server.c +++ b/pico_w/wifi/tcp_server/picow_tcp_server.c @@ -230,9 +230,11 @@ void run_tcp_server_test(void) { // 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) 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 // is done via interrupt in the background. This sleep is just an example of some (blocking) @@ -253,7 +255,7 @@ int main() { 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"); return 1; diff --git a/pico_w/tls_client/CMakeLists.txt b/pico_w/wifi/tls_client/CMakeLists.txt similarity index 100% rename from pico_w/tls_client/CMakeLists.txt rename to pico_w/wifi/tls_client/CMakeLists.txt diff --git a/pico_w/tls_client/lwipopts.h b/pico_w/wifi/tls_client/lwipopts.h similarity index 100% rename from pico_w/tls_client/lwipopts.h rename to pico_w/wifi/tls_client/lwipopts.h diff --git a/pico_w/tls_client/mbedtls_config.h b/pico_w/wifi/tls_client/mbedtls_config.h similarity index 100% rename from pico_w/tls_client/mbedtls_config.h rename to pico_w/wifi/tls_client/mbedtls_config.h diff --git a/pico_w/tls_client/picow_tls_client.c b/pico_w/wifi/tls_client/picow_tls_client.c similarity index 95% rename from pico_w/tls_client/picow_tls_client.c rename to pico_w/wifi/tls_client/picow_tls_client.c index 4094f73..d1576e6 100644 --- a/pico_w/tls_client/picow_tls_client.c +++ b/pico_w/wifi/tls_client/picow_tls_client.c @@ -204,9 +204,11 @@ void run_tls_client_test(void) { // 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) 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 // is done via interrupt in the background. This sleep is just an example of some (blocking) diff --git a/pico_w/udp_beacon/CMakeLists.txt b/pico_w/wifi/udp_beacon/CMakeLists.txt similarity index 100% rename from pico_w/udp_beacon/CMakeLists.txt rename to pico_w/wifi/udp_beacon/CMakeLists.txt diff --git a/pico_w/udp_beacon/lwipopts.h b/pico_w/wifi/udp_beacon/lwipopts.h similarity index 100% rename from pico_w/udp_beacon/lwipopts.h rename to pico_w/wifi/udp_beacon/lwipopts.h diff --git a/pico_w/udp_beacon/picow_udp_beacon.c b/pico_w/wifi/udp_beacon/picow_udp_beacon.c similarity index 93% rename from pico_w/udp_beacon/picow_udp_beacon.c rename to pico_w/wifi/udp_beacon/picow_udp_beacon.c index e6c2ddf..8333f11 100644 --- a/pico_w/udp_beacon/picow_udp_beacon.c +++ b/pico_w/wifi/udp_beacon/picow_udp_beacon.c @@ -44,7 +44,7 @@ void run_udp_beacon() { #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) to check for Wi-Fi driver or lwIP work that needs to be done. cyw43_arch_poll(); sleep_ms(BEACON_INTERVAL_MS); #else @@ -66,7 +66,7 @@ int main() { 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"); return 1; diff --git a/pico_w/wifi_scan/CMakeLists.txt b/pico_w/wifi/wifi_scan/CMakeLists.txt similarity index 100% rename from pico_w/wifi_scan/CMakeLists.txt rename to pico_w/wifi/wifi_scan/CMakeLists.txt diff --git a/pico_w/wifi_scan/lwipopts.h b/pico_w/wifi/wifi_scan/lwipopts.h similarity index 100% rename from pico_w/wifi_scan/lwipopts.h rename to pico_w/wifi/wifi_scan/lwipopts.h diff --git a/pico_w/wifi_scan/picow_wifi_scan.c b/pico_w/wifi/wifi_scan/picow_wifi_scan.c similarity index 77% rename from pico_w/wifi_scan/picow_wifi_scan.c rename to pico_w/wifi/wifi_scan/picow_wifi_scan.c index 082b23e..1e500f8 100644 --- a/pico_w/wifi_scan/picow_wifi_scan.c +++ b/pico_w/wifi/wifi_scan/picow_wifi_scan.c @@ -32,10 +32,10 @@ int main() { cyw43_arch_enable_sta_mode(); - absolute_time_t scan_test = nil_time; + absolute_time_t scan_time = nil_time; bool scan_in_progress = false; while(true) { - if (absolute_time_diff_us(get_absolute_time(), scan_test) < 0) { + if (absolute_time_diff_us(get_absolute_time(), scan_time) < 0) { if (!scan_in_progress) { cyw43_wifi_scan_options_t scan_options = {0}; int err = cyw43_wifi_scan(&cyw43_state, &scan_options, NULL, scan_result); @@ -44,10 +44,10 @@ int main() { scan_in_progress = true; } else { printf("Failed to start scan: %d\n", err); - scan_test = make_timeout_time_ms(10000); // wait 10s and scan again + scan_time = make_timeout_time_ms(10000); // wait 10s and scan again } } else if (!cyw43_wifi_scan_active(&cyw43_state)) { - scan_test = make_timeout_time_ms(10000); // wait 10s and scan again + scan_time = make_timeout_time_ms(10000); // wait 10s and scan again scan_in_progress = false; } } @@ -55,9 +55,11 @@ 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) 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(scan_time); #else // if you are not using pico_cyw43_arch_poll, then WiFI driver and lwIP work // is done via interrupt in the background. This sleep is just an example of some (blocking) diff --git a/pio/squarewave/CMakeLists.txt b/pio/squarewave/CMakeLists.txt index c2564d5..07f724b 100644 --- a/pio/squarewave/CMakeLists.txt +++ b/pio/squarewave/CMakeLists.txt @@ -12,6 +12,7 @@ pico_add_extra_outputs(pio_squarewave) # add url via pico_set_program_url example_auto_set_url(pio_squarewave) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/generated) # generate .hex file and .pio.h file for the RP2040 datasheet (to make sure # the datasheet always shows the output of the latest pioasm version) add_custom_target(pio_squarewave_datasheet DEPENDS diff --git a/pio/ws2812/CMakeLists.txt b/pio/ws2812/CMakeLists.txt index b0e14d4..eecb2d3 100644 --- a/pio/ws2812/CMakeLists.txt +++ b/pio/ws2812/CMakeLists.txt @@ -1,5 +1,7 @@ add_executable(pio_ws2812) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/generated) + # generate the header file into the source tree as it is included in the RP2040 datasheet pico_generate_pio_header(pio_ws2812 ${CMAKE_CURRENT_LIST_DIR}/ws2812.pio OUTPUT_DIR ${CMAKE_CURRENT_LIST_DIR}/generated)