diff --git a/README.md b/README.md index 459b5f9..cfd3285 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ App|Description [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_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. #### FreeRTOS examples diff --git a/pico_w/CMakeLists.txt b/pico_w/CMakeLists.txt index 1b50c42..e939dcb 100644 --- a/pico_w/CMakeLists.txt +++ b/pico_w/CMakeLists.txt @@ -32,6 +32,7 @@ if (PICO_CYW43_SUPPORTED) # set by PICO_BOARD=pico_w add_subdirectory(tcp_client) add_subdirectory(tcp_server) add_subdirectory(freertos) + add_subdirectory(udp_beacon) endif() endif() endif() diff --git a/pico_w/udp_beacon/CMakeLists.txt b/pico_w/udp_beacon/CMakeLists.txt new file mode 100644 index 0000000..59300ee --- /dev/null +++ b/pico_w/udp_beacon/CMakeLists.txt @@ -0,0 +1,34 @@ +add_executable(picow_udp_beacon_background + picow_udp_beacon.c + ) +target_compile_definitions(picow_udp_beacon_background PRIVATE + WIFI_SSID=\"${WIFI_SSID}\" + WIFI_PASSWORD=\"${WIFI_PASSWORD}\" + ) +target_include_directories(picow_udp_beacon_background PRIVATE + ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts + ) +target_link_libraries(picow_udp_beacon_background + pico_cyw43_arch_lwip_threadsafe_background + pico_stdlib + ) + +pico_add_extra_outputs(picow_udp_beacon_background) + +add_executable(picow_udp_beacon_poll + picow_udp_beacon.c + ) +target_compile_definitions(picow_udp_beacon_poll PRIVATE + WIFI_SSID=\"${WIFI_SSID}\" + WIFI_PASSWORD=\"${WIFI_PASSWORD}\" + ) +target_include_directories(picow_udp_beacon_poll PRIVATE + ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts + ) +target_link_libraries(picow_udp_beacon_poll + pico_cyw43_arch_lwip_poll + pico_stdlib + ) +pico_add_extra_outputs(picow_udp_beacon_poll) diff --git a/pico_w/udp_beacon/lwipopts.h b/pico_w/udp_beacon/lwipopts.h new file mode 100644 index 0000000..8571ed5 --- /dev/null +++ b/pico_w/udp_beacon/lwipopts.h @@ -0,0 +1,10 @@ +#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" + +#endif diff --git a/pico_w/udp_beacon/picow_udp_beacon.c b/pico_w/udp_beacon/picow_udp_beacon.c new file mode 100644 index 0000000..e6c2ddf --- /dev/null +++ b/pico_w/udp_beacon/picow_udp_beacon.c @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2022 Andrew McDonnell + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "pico/stdlib.h" +#include "pico/cyw43_arch.h" + +#include "lwip/pbuf.h" +#include "lwip/udp.h" + +#define UDP_PORT 4444 +#define BEACON_MSG_LEN_MAX 127 +#define BEACON_TARGET "255.255.255.255" +#define BEACON_INTERVAL_MS 1000 + +void run_udp_beacon() { + struct udp_pcb* pcb = udp_new(); + + ip_addr_t addr; + ipaddr_aton(BEACON_TARGET, &addr); + + int counter = 0; + while (true) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, BEACON_MSG_LEN_MAX+1, PBUF_RAM); + char *req = (char *)p->payload; + memset(req, 0, BEACON_MSG_LEN_MAX+1); + snprintf(req, BEACON_MSG_LEN_MAX, "%d\n", counter); + err_t er = udp_sendto(pcb, p, &addr, UDP_PORT); + pbuf_free(p); + if (er != ERR_OK) { + printf("Failed to send UDP packet! error=%d", er); + } else { + printf("Sent packet %d\n", counter); + counter++; + } + + // Note in practice for this simple UDP transmitter, + // the end result for both background and poll is the same + +#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. + cyw43_arch_poll(); + sleep_ms(BEACON_INTERVAL_MS); +#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) + // work you might be doing. + sleep_ms(BEACON_INTERVAL_MS); +#endif + } +} + +int main() { + stdio_init_all(); + + if (cyw43_arch_init()) { + printf("failed to initialise\n"); + return 1; + } + + cyw43_arch_enable_sta_mode(); + + printf("Connecting to WiFi...\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"); + } + run_udp_beacon(); + cyw43_arch_deinit(); + return 0; +} \ No newline at end of file