From 001610f0d0b94859b8c8800dcdfa255343f2ea05 Mon Sep 17 00:00:00 2001 From: Lukas Krejci Date: Wed, 30 Nov 2022 15:57:52 +0100 Subject: [PATCH] Be able to specify the power management mode at init time. --- examples/rpi-pico-w/src/main.rs | 2 +- src/lib.rs | 106 +++++++++++++++++++++++++++++--- 2 files changed, 100 insertions(+), 8 deletions(-) diff --git a/examples/rpi-pico-w/src/main.rs b/examples/rpi-pico-w/src/main.rs index fd58e46d..73cfdf42 100644 --- a/examples/rpi-pico-w/src/main.rs +++ b/examples/rpi-pico-w/src/main.rs @@ -70,7 +70,7 @@ async fn main(spawner: Spawner) { spawner.spawn(wifi_task(runner)).unwrap(); - control.init(clm).await; + control.init(clm, cyw43::PowerManagementMode::PowerSave).await; //control.join_open(env!("WIFI_NETWORK")).await; control.join_wpa2(env!("WIFI_NETWORK"), env!("WIFI_PASSWORD")).await; diff --git a/src/lib.rs b/src/lib.rs index 94032271..884cb082 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -143,8 +143,92 @@ pub struct Control<'a> { ioctl_state: &'a Cell, } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum PowerManagementMode { + /// Custom, officially unsupported mode. Use at your own risk. + /// All power-saving features set to their max at only a marginal decrease in power consumption + /// as oppposed to `Aggressive`. + SuperSave, + + /// Aggressive power saving mode. + Aggressive, + + /// The default mode. + PowerSave, + + /// Performance is prefered over power consumption but still some power is conserved as opposed to + /// `None`. + Performance, + + /// Unlike all the other PM modes, this lowers the power consumption at all times at the cost of + /// a much lower throughput. + ThroughputThrottling, + + /// No power management is configured. This consumes the most power. + None, +} + +impl Default for PowerManagementMode { + fn default() -> Self { + Self::PowerSave + } +} + +impl PowerManagementMode { + fn sleep_ret_ms(&self) -> u16 { + match self { + PowerManagementMode::SuperSave => 2000, + PowerManagementMode::Aggressive => 2000, + PowerManagementMode::PowerSave => 200, + PowerManagementMode::Performance => 20, + PowerManagementMode::ThroughputThrottling => 0, // value doesn't matter + PowerManagementMode::None => 0, // value doesn't matter + } + } + + fn beacon_period(&self) -> u8 { + match self { + PowerManagementMode::SuperSave => 255, + PowerManagementMode::Aggressive => 1, + PowerManagementMode::PowerSave => 1, + PowerManagementMode::Performance => 1, + PowerManagementMode::ThroughputThrottling => 0, // value doesn't matter + PowerManagementMode::None => 0, // value doesn't matter + } + } + + fn dtim_period(&self) -> u8 { + match self { + PowerManagementMode::SuperSave => 255, + PowerManagementMode::Aggressive => 1, + PowerManagementMode::PowerSave => 1, + PowerManagementMode::Performance => 1, + PowerManagementMode::ThroughputThrottling => 0, // value doesn't matter + PowerManagementMode::None => 0, // value doesn't matter + } + } + + fn assoc(&self) -> u8 { + match self { + PowerManagementMode::SuperSave => 255, + PowerManagementMode::Aggressive => 10, + PowerManagementMode::PowerSave => 10, + PowerManagementMode::Performance => 1, + PowerManagementMode::ThroughputThrottling => 0, // value doesn't matter + PowerManagementMode::None => 0, // value doesn't matter + } + } + + fn mode(&self) -> u32 { + match self { + PowerManagementMode::ThroughputThrottling => 1, + _ => 2, + } + } +} + impl<'a> Control<'a> { - pub async fn init(&mut self, clm: &[u8]) { + pub async fn init(&mut self, clm: &[u8], power_save_mode: PowerManagementMode) { const CHUNK_SIZE: usize = 1024; info!("Downloading CLM..."); @@ -239,12 +323,20 @@ impl<'a> Control<'a> { Timer::after(Duration::from_millis(100)).await; - // power save mode 2 - self.set_iovar_u32("pm2_sleep_ret", 0xc8).await; - self.set_iovar_u32("bcn_li_bcn", 1).await; - self.set_iovar_u32("bcn_li_dtim", 1).await; - self.set_iovar_u32("assoc_listen", 10).await; - self.ioctl_set_u32(0x86, 0, 2).await; + // power save mode + if power_save_mode != PowerManagementMode::None { + let mode = power_save_mode.mode(); + if mode == 2 { + self.set_iovar_u32("pm2_sleep_ret", power_save_mode.sleep_ret_ms() as u32) + .await; + self.set_iovar_u32("bcn_li_bcn", power_save_mode.beacon_period() as u32) + .await; + self.set_iovar_u32("bcn_li_dtim", power_save_mode.dtim_period() as u32) + .await; + self.set_iovar_u32("assoc_listen", power_save_mode.assoc() as u32).await; + } + self.ioctl_set_u32(86, 0, mode).await; + } self.ioctl_set_u32(110, 0, 1).await; // SET_GMODE = auto self.ioctl_set_u32(142, 0, 0).await; // SET_BAND = any