Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Library|Description
[platypus](src/common/platypus)| Decoder for a custom image compression format suitable for dithered images (good for RGB555) and suitable for decoding on RP2040 at scanline speeds ... i.e you can easily decode a 320x240 image 60x per second to avoid storing the uncompressed image for scanout video. It gets about 50% compression (but is designed only for 4x4 fixed dithered RGB555 images, so is somewhat specific!). TODO add the encoder here :-)
[usb_device](src/rp2_common/usb_device), [usb_common](src/rp2_common/usb_common)| The custom and somewhat minimal USB device stack used in the bootrom. We now use TinyUSB in the Pico SDK but kept here for posterity
[usb_device_msc](src/rp2_common/usb_device_msc)| USB Mass Storage Class implementation using _usb_device_
[wifi_settings_connect](src/rp2_common/wifi_settings_connect)| Library to manage WiFi connections. It provides Flash storage for WiFi passwords and hotspot names, and a background async\_context service to automatically connect to them.

You can add Pico Extras to your project similarly to the SDK (copying [external/pico_extras_import.cmake](external/pico_extras_import.cmake) into your project)
having set the `PICO_EXTRAS_PATH` variable in your environment or via cmake variable.
Expand Down
3 changes: 2 additions & 1 deletion src/rp2_common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ pico_add_subdirectory(pico_sd_card)
pico_add_subdirectory(pico_scanvideo_dpi)
pico_add_subdirectory(usb_common)
pico_add_subdirectory(usb_device)
pico_add_subdirectory(usb_device_msc)
pico_add_subdirectory(usb_device_msc)
pico_add_subdirectory(wifi_settings_connect)
40 changes: 40 additions & 0 deletions src/rp2_common/wifi_settings_connect/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#
# Copyright (c) 2025 Jack Whitham
#
# SPDX-License-Identifier: BSD-3-Clause
#
# wifi_settings_connect
#
# Library to manage WiFi connections. It provides Flash storage
# for WiFi passwords and hotspot names, and a background async_context
# service to automatically connect to them.
#

if (NOT PICO_CYW43_SUPPORTED)
message("wifi_settings_connect: WiFi hardware is required: run cmake -DPICO_BOARD=pico_w or -DPICO_BOARD=pico2_w")
elseif (NOT TARGET pico_cyw43_arch)
message("wifi_settings_connect: WiFi driver pico_cyw43_arch is not present")
elseif (NOT TARGET pico_lwip_core)
message("wifi_settings_connect: IP layer pico_lwip_core is not present")
else()
message("wifi_settings_connect: library is available.")
add_library(wifi_settings_connect INTERFACE)

target_include_directories(wifi_settings_connect INTERFACE
${CMAKE_CURRENT_LIST_DIR}/include
)

target_sources(wifi_settings_connect INTERFACE
${CMAKE_CURRENT_LIST_DIR}/wifi_settings_connect.c
${CMAKE_CURRENT_LIST_DIR}/wifi_settings_flash_storage.c
${CMAKE_CURRENT_LIST_DIR}/wifi_settings_flash_range.c
${CMAKE_CURRENT_LIST_DIR}/wifi_settings_hostname.c
)

target_link_libraries(wifi_settings_connect INTERFACE
pico_async_context_base
pico_stdlib
pico_cyw43_arch
pico_lwip_core
)
endif()
22 changes: 22 additions & 0 deletions src/rp2_common/wifi_settings_connect/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# wifi\_settings\_connect

This is a library to manage WiFi connections. It provides Flash storage
for WiFi passwords and hotspot names, and a background async\_context
service to automatically connect to them. You can store details for
up to 16 hotspots and update them using `picotool` or a setup
application. This avoids any need to
specify build-time flags such as `WIFI_SSID` and `WIFI_PASSWORD`.

The Flash storage location for hotspot details is specified in
`include/wifi_settings/wifi_settings_configuration.h`. It is at
`0x101ff000` (for Pico W) and `0x103fe000` (for Pico 2 W). To add your
WiFi details at this location, please [see these
instructions](https://github.com/jwhitham/pico-wifi-settings/blob/master/doc/SETTINGS_FILE.md).
You can edit the settings as a text file and transfer it with `picotool`,
or install a [setup application](https://github.com/jwhitham/pico-wifi-settings/blob/master/doc/SETUP_APP.md)
to add or update WiFi details.

This wifi\_settings\_connect library is a subset of a larger
library, [wifi\_settings](https://github.com/jwhitham/pico-wifi-settings/),
which adds remote update functions for both the WiFi settings
and (optionally) your Pico application too.
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Copyright (c) 2025 Jack Whitham
*
* SPDX-License-Identifier: BSD-3-Clause
*
* This header file contains default values for timeouts,
* addresses and limits within the pico-wifi-settings library.
*/

#ifndef WIFI_SETTINGS_CONFIGURATION_H
#define WIFI_SETTINGS_CONFIGURATION_H


#if defined(FLASH_ADDRESS_OF_WIFI_SETTINGS_FILE)
// Flash address of wifi-settings file already defined
#elif PICO_RP2040
// Flash address of wifi-settings file on Pico 1 W
#define FLASH_ADDRESS_OF_WIFI_SETTINGS_FILE 0x001ff000
// Note: Flash addresses have 0 = start of Flash.
// Note: The CPU's address for the wifi-settings file is 0x101ff000 on Pico 1.

#elif PICO_RP2350
// Flash address of wifi-settings file on Pico 2 W
#define FLASH_ADDRESS_OF_WIFI_SETTINGS_FILE 0x003fe000
// Note: Flash addresses have 0 = start of Flash.
// Note: avoid final sector due to RP2350-E10 bug
// Note: The CPU's address for the wifi-settings file is 0x103fe000 on Pico 2
// assuming that there is no translation (e.g. partitioning).

#else
#error "Unknown Pico model - please set FLASH_ADDRESS_OF_WIFI_SETTINGS_FILE appropriately"
#endif

// Size of wifi-settings file (bytes, must be a whole number of Flash sectors)
#ifndef WIFI_SETTINGS_FILE_SIZE
#define WIFI_SETTINGS_FILE_SIZE 0x1000
#endif

// Minimum time between initialisation and the first scan (milliseconds).
#ifndef INITIAL_SETUP_TIME_MS
#define INITIAL_SETUP_TIME_MS 1000
#endif

// Maximum time allowed between calling cyw43_wifi_join and getting an IP address (milliseconds).
// If this timeout expires, wifi_settings will try a different hotspot or rescan. The attempt to
// join a hotspot can fail sooner than this, e.g. if the password is incorrect or the hotspot vanishes.
#ifndef CONNECT_TIMEOUT_TIME_MS
#define CONNECT_TIMEOUT_TIME_MS 30000
#endif

// Minimum time between scans (milliseconds). If a scan fails to find any known hotspot,
// wifi_settings will always wait at least this long before retry.
#ifndef REPEAT_SCAN_TIME_MS
#define REPEAT_SCAN_TIME_MS 3000
#endif

// Minimum time between calls to the periodic function, wifi_settings_periodic_callback,
// which will initiate scans and connections if necessary (milliseconds).
#ifndef PERIODIC_TIME_MS
#define PERIODIC_TIME_MS 1000
#endif

// Maximum number of SSIDs that can be supported.
#ifndef NUM_SSIDS
#define NUM_SSIDS 16
#endif

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* Copyright (c) 2025 Jack Whitham
*
* SPDX-License-Identifier: BSD-3-Clause
*
* This header file declares functions used to initialise and connect to WiFi
* with pico-wifi-settings.
*
*/

#ifndef _WIFI_SETTINGS_CONNECT_H_
#define _WIFI_SETTINGS_CONNECT_H_

#include <stdbool.h>

// These settings are fixed by WPA-PSK standards
#define WIFI_SSID_SIZE 33 // including '\0' character
#define WIFI_BSSID_SIZE 6 // size of a MAC address
#define WIFI_PASSWORD_SIZE 65 // including '\0' character

/// @brief Initialise wifi_settings module
/// @return 0 on success, or an error code from cyw43_arch_init
int wifi_settings_init();

/// @brief Deinitialise wifi_settings module
void wifi_settings_deinit();

/// @brief Connect to WiFi if possible, using the settings in Flash.
/// The actual connection may take some time to be established, and
/// may not be possible. Call wifi_settings_is_connected() to see if
/// the connection is ready.
void wifi_settings_connect();

/// @brief Disconnect from WiFi immediately.
void wifi_settings_disconnect();

/// @brief Determine if connection is ready.
/// @return true if ready
bool wifi_settings_is_connected();

/// @brief Determine if the WiFi settings are empty - if the
/// file is empty, wifi_settings will be unable to connect. See README.md
/// for instructions on how to provide settings.
/// @return true if empty (no known SSIDs or BSSIDs)
bool wifi_settings_has_no_wifi_details();

/// @brief Get a report on the current connection status
/// @param[inout] text Text buffer for the report
/// @param[in] text_size Available space in the buffer (bytes)
/// @return Return code from snprintf when formatting
int wifi_settings_get_connect_status_text(char* text, int text_size);

/// @brief Get a report on the network hardware (cyw43) status (e.g. signal strength)
/// @param[inout] text Text buffer for the report
/// @param[in] text_size Available space in the buffer (bytes)
/// @return Return code from snprintf when formatting
int wifi_settings_get_hw_status_text(char* text, int text_size);

/// @brief Get a report on the IP stack status (e.g. IP address)
/// @param[inout] text Text buffer for the report
/// @param[in] text_size Available space in the buffer (bytes)
/// @return Return code from snprintf when formatting
int wifi_settings_get_ip_status_text(char* text, int text_size);

/// @brief Get the status of a connection attempt to
/// an SSID as a static string, e.g. SUCCESS, NOT_FOUND. "" is returned
/// if the SSID index is not known.
/// @param[in] ssid_index Index matching the ssid number.
/// @return Static string containing the SSID status.
const char* wifi_settings_get_ssid_status(int ssid_index);


#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Copyright (c) 2025 Jack Whitham
*
* SPDX-License-Identifier: BSD-3-Clause
*
* This header file is intended to be internal and should not be included directly by applications.
*
*/

#ifndef WIFI_SETTINGS_CONNECT_INTERNAL_H
#define WIFI_SETTINGS_CONNECT_INTERNAL_H

#ifndef WIFI_SETTINGS_CONNECT_C
#error "This is an internal header intended only for use by wifi_settings_connect.c and its unit tests"
#else

#include "wifi_settings_configuration.h"

#include "pico/async_context.h"
#include "pico/stdlib.h"
#include "pico/time.h"
#include "pico/cyw43_arch.h"

enum wifi_connect_state_t {
UNINITIALISED = 0, // cyw43 hardware was not started
INITIALISATION_ERROR, // initialisation failed (see hw_error_code)
STORAGE_EMPTY_ERROR, // no WiFi details are known
DISCONNECTED, // call wifi_settings_connect() to connect
TRY_TO_CONNECT, // connection process begun
SCANNING, // scan running
CONNECTING, // connection running
CONNECTED_IP, // connection is ready for use
};

enum ssid_scan_info_t {
NOT_FOUND = 0, // this SSID was not found
FOUND, // this SSID was found by the most recent scan
ATTEMPT, // we attempted to connect to this SSID
FAILED, // ... but it failed with an error
TIMEOUT, // ... but it failed with a timeout
BADAUTH, // ... but the password is wrong
SUCCESS, // ... and it worked
LOST, // we connected to this SSID but the connection dropped
};

#define IPV4_ADDRESS_SIZE 16 // "xxx.xxx.xxx.xxx\0"
#define KEY_SIZE 10 // e.g. "bssid0"

struct wifi_state_t {
enum wifi_connect_state_t cstate;
enum ssid_scan_info_t ssid_scan_info[NUM_SSIDS + 1];
struct netif* netif;
cyw43_t* cyw43;
uint selected_ssid_index;
int hw_error_code;
absolute_time_t connect_timeout_time;
absolute_time_t scan_holdoff_time;
async_context_t* context;
async_at_time_worker_t periodic_worker;
};

#endif
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* Copyright (c) 2025 Jack Whitham
*
* SPDX-License-Identifier: BSD-3-Clause
*
* This header file declares functions used to check and translate address ranges.
*
*/

#ifndef _WIFI_SETTINGS_FLASH_RANGE_H_
#define _WIFI_SETTINGS_FLASH_RANGE_H_

#include "hardware/flash.h"

#include <stdbool.h>
#include <stdint.h>

/// @brief Represents a range of Flash memory addresses
typedef struct wifi_settings_flash_range_t {
uint32_t start_address;
uint32_t size;
} wifi_settings_flash_range_t;

/// @brief Represents a range of logical memory addresses
typedef struct wifi_settings_logical_range_t {
void* start_address;
uint32_t size;
} wifi_settings_logical_range_t;

/// @brief Detect if a Flash memory range entirely fits within another
/// @param[in] inner Inner Flash memory range
/// @param[in] outer Outer Flash memory range
/// @return true if inner is entirely within outer
bool wifi_settings_range_is_contained(
const wifi_settings_flash_range_t* inner,
const wifi_settings_flash_range_t* outer);

/// @brief Detect if a Flash memory range intersects with another
/// @param[in] fr1 First range
/// @param[in] fr2 Second range
/// @return true if fr1 and fr2 overlap by one or more bytes
bool wifi_settings_range_has_overlap(
const wifi_settings_flash_range_t* fr1,
const wifi_settings_flash_range_t* fr2);

/// @brief Determine the range of addresses that are in Flash
/// @param[out] r Flash memory range
void wifi_settings_range_get_all(
wifi_settings_flash_range_t* r);

/// @brief Determine the range of addresses that are reusable
/// (Reusable -> not occupied by the current program, not
/// occupied by the wifi-settings file, and within the current partition, if any.)
/// @param[out] r Flash memory range
void wifi_settings_range_get_reusable(
wifi_settings_flash_range_t* r);

/// @brief Determine the range of addresses used by the wifi-settings file
/// @param[out] r Flash memory range
void wifi_settings_range_get_wifi_settings_file(
wifi_settings_flash_range_t* r);

/// @brief Determine the range of addresses used by the current program
/// @param[out] r Flash memory range
void wifi_settings_range_get_program(
wifi_settings_flash_range_t* r);

/// @brief Determine the range of addresses used by the current partition
/// @param[out] r Flash memory range
void wifi_settings_range_get_partition(
wifi_settings_flash_range_t* r);

/// @brief Translate Flash range to logical range
/// @param[in] fr Flash memory range
/// @param[out] lr Logical memory range
void wifi_settings_range_translate_to_logical(
const wifi_settings_flash_range_t* fr,
wifi_settings_logical_range_t* lr);

/// @brief Align Flash range to sector boundary and size:
/// no effect if they are already aligned
/// @param[inout] fr Flash memory range (possibly unaligned)
void wifi_settings_range_align_to_sector(
wifi_settings_flash_range_t* fr);

/// @brief Translate logical range to Flash range if possible.
/// Not possible if the logical range is outside of an accessible area of Flash:
/// (1) ROM/RAM/other non-Flash addresses, (2) outside of the current partition,
/// (3) outside of both XIP_BASE and XIP_NOCACHE_NOALLOC_NOTRANSLATE_BASE regions.
/// @param[in] lr Logical memory range
/// @param[out] fr Flash memory range
/// @return true if translation was possible
bool wifi_settings_range_translate_to_flash(
const wifi_settings_logical_range_t* lr,
wifi_settings_flash_range_t* fr);

#endif
Loading