Skip to content

Set "disabled" PM at reset, provide PM constants and better documentation #6976

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
59 changes: 54 additions & 5 deletions ports/raspberrypi/bindings/cyw43/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@
#include "shared-bindings/microcontroller/Pin.h"
#include "bindings/cyw43/__init__.h"


static int power_management_value = PM_DISABLED;

void bindings_cyw43_wifi_enforce_pm() {
cyw43_wifi_pm(&cyw43_state, power_management_value);
}

//| class CywPin:
//| """A class that represents a GPIO pin attached to the wifi chip.
//|
Expand All @@ -49,23 +56,60 @@ const mp_obj_type_t cyw43_pin_type = {
)
};

//| PM_STANDARD: int
//| """The standard power management mode"""
//| PM_AGGRESSIVE: int
//| """Aggressive power management mode for optimal power usage at the cost of performance"""
//| PM_PERFORMANCE: int
//| """Performance power management mode where more power is used to increase performance"""
//| PM_DISABLED: int
//| """Disable power management and always use highest power mode. CircuitPython sets this value at reset time, because it provides the best connectivity reliability."""
//|
//| def set_power_management(value: int) -> None:
//| """Set the power management register
//|
//| According to Raspberry Pi documentation, the value 0xa11140
//| increases responsiveness at the cost of higher power usage.
//| For transmitter power, see ``wifi.Radio.txpower``.
//| This controls software power saving features inside the cyw43 chip.
//| it does not control transmitter power.
//|
//| The value is interpreted as a 24-bit hexadecimal number of the form
//| ``0x00adbrrm``.
//|
//| The low 4 bits, ``m``, are the power management mode:
//| * 0: disabled
//| * 1: aggressive power saving which reduces wifi throughput
//| * 2: Power saving with high througput
//|
//| Besides this value, there appears to be no other public documentation
//| of the values that can be used.
//| The next 8 bits, ``r``, specify "the maximum time to wait before going back to sleep" for power management mode 2. The units of ``r`` are 10ms.
//|
//| The next 4 bits, ``b``, are the "wake period is measured in beacon periods".
//|
//| The next 4 bits, ``d``, specify the "wake interval measured in DTIMs. If this is set to 0, the wake interval is measured in beacon periods".
//|
//| The top 4 bits, ``a``, specifies the "wake interval sent to the access point"
//|
//| Several ``PM_`` constants gathered from various sources are included
//| in this module. According to Raspberry Pi documentation, the value 0xa11140
//| (called `cyw43.PM_DISABLED` here) increases responsiveness at the cost of higher power
//| usage.
//| """
//|
STATIC mp_obj_t cyw43_set_power_management(const mp_obj_t value_in) {
mp_int_t value = mp_obj_get_int(value_in);
cyw43_wifi_pm(&cyw43_state, value);
power_management_value = value;
bindings_cyw43_wifi_enforce_pm();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(cyw43_set_power_management_obj, cyw43_set_power_management);

//| def get_power_management() -> int:
//| """Retrieve the power management register"""
//|
STATIC mp_obj_t cyw43_get_power_management() {
return mp_obj_new_int(power_management_value);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(cyw43_get_power_management_obj, cyw43_get_power_management);

const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj) {
if (!mp_obj_is_type(obj, &mcu_pin_type) && !mp_obj_is_type(obj, &cyw43_pin_type)) {
mp_raise_TypeError_varg(translate("Expected a %q or %q"), mcu_pin_type.name, cyw43_pin_type.name);
Expand All @@ -83,6 +127,11 @@ STATIC const mp_rom_map_elem_t cyw43_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cyw43) },
{ MP_ROM_QSTR(MP_QSTR_CywPin), MP_ROM_QSTR(MP_QSTR_CywPin) },
{ MP_ROM_QSTR(MP_QSTR_set_power_management), &cyw43_set_power_management_obj },
{ MP_ROM_QSTR(MP_QSTR_get_power_management), &cyw43_get_power_management_obj },
{ MP_ROM_QSTR(MP_QSTR_PM_STANDARD), MP_ROM_INT(PM_STANDARD) },
{ MP_ROM_QSTR(MP_QSTR_PM_AGGRESSIVE), MP_ROM_INT(PM_AGGRESSIVE) },
{ MP_ROM_QSTR(MP_QSTR_PM_PERFORMANCE), MP_ROM_INT(PM_PERFORMANCE) },
{ MP_ROM_QSTR(MP_QSTR_PM_DISABLED), MP_ROM_INT(PM_DISABLED) },
};

STATIC MP_DEFINE_CONST_DICT(cyw43_module_globals, cyw43_module_globals_table);
Expand Down
19 changes: 19 additions & 0 deletions ports/raspberrypi/bindings/cyw43/__init__.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,26 @@
#pragma once

#include "py/obj.h"
#include "common-hal/microcontroller/Pin.h"

extern const mp_obj_type_t cyw43_pin_type;
const mcu_pin_obj_t *validate_obj_is_free_pin_including_cyw43(mp_obj_t obj);
const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj);

#define CONSTANT_CYW43_PM_VALUE(pm_mode, pm2_sleep_ret_ms, li_beacon_period, li_dtim_period, li_assoc) \
(li_assoc << 20 | /* listen interval sent to ap */ \
li_dtim_period << 16 | \
li_beacon_period << 12 | \
(pm2_sleep_ret_ms / 10) << 4 | /* cyw43_ll_wifi_pm multiplies this by 10 */ \
pm_mode /* CYW43_PM2_POWERSAVE_MODE etc */)

// CYW43_DEFAULT_PM (except a compile-time constant)
#define PM_STANDARD CONSTANT_CYW43_PM_VALUE(CYW43_PM2_POWERSAVE_MODE, 200, 1, 1, 10)
// CYW43_AGGRESSIVE_PM (except a compile-time constant)
#define PM_AGGRESSIVE CONSTANT_CYW43_PM_VALUE(CYW43_PM2_POWERSAVE_MODE, 2000, 1, 1, 10)
// CYW43_PERFORMANCE_PM (except a compile-time constant)
#define PM_PERFORMANCE CONSTANT_CYW43_PM_VALUE(CYW43_PM2_POWERSAVE_MODE, 20, 1, 1, 1)
// The 0xa11140 magic value
#define PM_DISABLED CONSTANT_CYW43_PM_VALUE(CYW43_NO_POWERSAVE_MODE, 200, 1, 1, 10)

extern void bindings_cyw43_wifi_enforce_pm(void);
4 changes: 4 additions & 0 deletions ports/raspberrypi/common-hal/wifi/Radio.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "shared/runtime/interrupt_char.h"
#include "py/gc.h"
#include "py/runtime.h"
#include "bindings/cyw43/__init__.h"
#include "shared-bindings/ipaddress/IPv4Address.h"
#include "shared-bindings/wifi/ScannedNetworks.h"
#include "shared-bindings/wifi/AuthMode.h"
Expand Down Expand Up @@ -152,13 +153,15 @@ void common_hal_wifi_radio_stop_scanning_networks(wifi_radio_obj_t *self) {

void common_hal_wifi_radio_start_station(wifi_radio_obj_t *self) {
cyw43_arch_enable_sta_mode();
bindings_cyw43_wifi_enforce_pm();
}

void common_hal_wifi_radio_stop_station(wifi_radio_obj_t *self) {
}

void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, uint8_t authmode, uint8_t max_connections) {
mp_raise_NotImplementedError(NULL);
bindings_cyw43_wifi_enforce_pm();
}

void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) {
Expand All @@ -173,6 +176,7 @@ wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t
// TODO use connect_async so we can service bg tasks & check for ctrl-c during
// connect
int result = cyw43_arch_wifi_connect_timeout_ms((const char *)ssid, (const char *)password, CYW43_AUTH_WPA2_AES_PSK, timeout_ms);
bindings_cyw43_wifi_enforce_pm();
switch (result) {
case 0:
return WIFI_RADIO_ERROR_NONE;
Expand Down