Skip to content

Commit 9749ce1

Browse files
authored
Merge pull request #11308 from mikeysklar/esp32c5-wifi-5ghz
wifi: scan 5GHz channels on dual-band radios
2 parents de15916 + 117fa80 commit 9749ce1

3 files changed

Lines changed: 42 additions & 21 deletions

File tree

ports/espressif/common-hal/wifi/Radio.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "components/esp_netif/include/esp_netif_net_stack.h"
2727
#include "components/esp_wifi/include/esp_wifi.h"
28+
#include "soc/soc_caps.h"
2829
#include "components/lwip/include/apps/ping/ping_sock.h"
2930
#include "lwip/sockets.h"
3031

@@ -94,6 +95,11 @@ void common_hal_wifi_radio_set_enabled(wifi_radio_obj_t *self, bool enabled) {
9495
}
9596
if (!self->started && enabled) {
9697
ESP_ERROR_CHECK(esp_wifi_start());
98+
#if defined(SOC_WIFI_SUPPORT_5G) && SOC_WIFI_SUPPORT_5G
99+
// Dual-band radios default to 2.4 GHz only. Enable both bands so that
100+
// 5 GHz networks are visible to scans and can be connected to.
101+
ESP_ERROR_CHECK(esp_wifi_set_band_mode(WIFI_BAND_MODE_AUTO));
102+
#endif
97103
self->started = true;
98104
common_hal_wifi_radio_set_tx_power(self, CIRCUITPY_WIFI_DEFAULT_TX_POWER);
99105
return;

ports/espressif/common-hal/wifi/ScannedNetworks.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "shared-bindings/wifi/ScannedNetworks.h"
1919

2020
#include "components/esp_wifi/include/esp_wifi.h"
21+
#include "soc/soc_caps.h"
2122

2223
static void wifi_scannednetworks_done(wifi_scannednetworks_obj_t *self) {
2324
self->done = true;
@@ -111,29 +112,38 @@ mp_obj_t common_hal_wifi_scannednetworks_next(wifi_scannednetworks_obj_t *self)
111112
}
112113

113114
// We don't do a linear scan so that we look at a variety of spectrum up front.
115+
#if defined(SOC_WIFI_SUPPORT_5G) && SOC_WIFI_SUPPORT_5G
116+
// 2.4 GHz first, then the 5 GHz U-NII bands. DFS channels are omitted:
117+
// they require radar detection before transmitting.
118+
static uint8_t scan_pattern[] = {6, 1, 11, 3, 9, 13, 2, 4, 8, 12, 5, 7, 10, 14,
119+
36, 40, 44, 48, 149, 153, 157, 161, 165, 0};
120+
#else
114121
static uint8_t scan_pattern[] = {6, 1, 11, 3, 9, 13, 2, 4, 8, 12, 5, 7, 10, 14, 0};
122+
#endif
115123

116124
void wifi_scannednetworks_scan_next_channel(wifi_scannednetworks_obj_t *self) {
117-
// There is no channel 0, so use that as a flag to indicate we've run out of channels to scan.
118-
uint8_t next_channel = 0;
119-
while (self->current_channel_index < sizeof(scan_pattern)) {
120-
next_channel = scan_pattern[self->current_channel_index];
121-
self->current_channel_index++;
122-
// Scan only channels that are in the specified range.
123-
if (self->start_channel <= next_channel && next_channel <= self->end_channel) {
124-
break;
125+
while (true) {
126+
// There is no channel 0, so use that as a flag to indicate we've run out of channels to scan.
127+
uint8_t next_channel = 0;
128+
while (self->current_channel_index < sizeof(scan_pattern)) {
129+
next_channel = scan_pattern[self->current_channel_index];
130+
self->current_channel_index++;
131+
// Scan only channels that are in the specified range.
132+
if (self->start_channel <= next_channel && next_channel <= self->end_channel) {
133+
break;
134+
}
125135
}
126-
}
127-
wifi_scan_config_t config = { 0 };
128-
config.channel = next_channel;
129-
if (next_channel == 0) {
130-
wifi_scannednetworks_done(self);
131-
} else {
132-
esp_err_t result = esp_wifi_scan_start(&config, false);
133-
if (result != ESP_OK) {
136+
if (next_channel == 0) {
134137
wifi_scannednetworks_done(self);
135-
} else {
138+
return;
139+
}
140+
wifi_scan_config_t config = { 0 };
141+
config.channel = next_channel;
142+
// The radio rejects channels outside the band it is set to. Skip those
143+
// rather than ending the scan, so the rest of the pattern still runs.
144+
if (esp_wifi_scan_start(&config, false) == ESP_OK) {
136145
self->channel_scan_in_progress = true;
146+
return;
137147
}
138148
}
139149
}

shared-bindings/wifi/Radio.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,13 @@ MP_PROPERTY_GETTER(wifi_radio_mac_address_ap_obj,
254254
#endif
255255

256256
//| def start_scanning_networks(
257-
//| self, *, start_channel: int = 1, stop_channel: int = 11
257+
//| self, *, start_channel: int = 1, stop_channel: int = 165
258258
//| ) -> Iterable[Network]:
259259
//| """Scans for available wifi networks over the given channel range. Make sure the channels are allowed in your country.
260260
//|
261+
//| On dual-band radios, 5 GHz channels (36 and above) may also be given.
262+
//| Channel numbers that the radio does not support are skipped.
263+
//|
261264
//| .. note::
262265
//|
263266
//| In the raspberrypi port (RP2040 CYW43), ``start_channel`` and ``stop_channel`` are ignored.
@@ -268,17 +271,19 @@ static mp_obj_t wifi_radio_start_scanning_networks(size_t n_args, const mp_obj_t
268271
enum { ARG_start_channel, ARG_stop_channel };
269272
static const mp_arg_t allowed_args[] = {
270273
{ MP_QSTR_start_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
271-
{ MP_QSTR_stop_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 11} },
274+
{ MP_QSTR_stop_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 165} },
272275
};
273276

274277
wifi_radio_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
275278
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
276279
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
277280

281+
// 165 is the highest channel in the scan pattern. Channels the radio
282+
// doesn't support are skipped while scanning rather than rejected here.
278283
uint8_t start_channel =
279-
(uint8_t)mp_arg_validate_int_range(args[ARG_start_channel].u_int, 1, 14, MP_QSTR_start_channel);
284+
(uint8_t)mp_arg_validate_int_range(args[ARG_start_channel].u_int, 1, 165, MP_QSTR_start_channel);
280285
uint8_t stop_channel =
281-
(uint8_t)mp_arg_validate_int_range(args[ARG_stop_channel].u_int, 1, 14, MP_QSTR_stop_channel);
286+
(uint8_t)mp_arg_validate_int_range(args[ARG_stop_channel].u_int, 1, 165, MP_QSTR_stop_channel);
282287
// Swap if in reverse order, without complaining.
283288
if (start_channel > stop_channel) {
284289
uint8_t temp = stop_channel;

0 commit comments

Comments
 (0)