Skip to content
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

Restructuring channel power state to an enum #183

Merged
merged 10 commits into from
Feb 3, 2022
44 changes: 31 additions & 13 deletions src/hardware/rf_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ mod sm {

statemachine! {
transitions: {
*Off + InterlockReset / start_powerup = Powerup(Instant<SystemTimer>),
*Off + InterlockReset [guard_powerup] / start_powerup = Powerup(Instant<SystemTimer>),
Off + Disable = Off,
Off + Fault(ChannelFault) / handle_fault = Blocked(ChannelFault),

Expand Down Expand Up @@ -662,6 +662,7 @@ impl sm::StateMachineContext for RfChannel {
*interlock
}


/// Begin the process of powering up the channel.
///
/// # Returns
Expand All @@ -688,6 +689,19 @@ impl sm::StateMachineContext for RfChannel {
self.start_powerup()
}

/// Guard against powering up the channel.
///
/// # Returns
/// Ok if the channel can power up. Err otherwise.
fn guard_powerup(&mut self) -> Result<(), ()> {
let settings = self.settings.settings();
if settings.state == ChannelState::Off {
Err(())
} else {
Ok(())
}
}

/// Check to see if it's currently acceptable to enable the RF output switch.
///
/// # Returns
Expand All @@ -710,7 +724,7 @@ impl sm::StateMachineContext for RfChannel {
}

// Do not enable output if it shouldn't be disabled due to settings.
if !matches!(settings.power_state, ChannelState::Enabled) {
if settings.state != ChannelState::Enabled {
return Err(());
}

Expand Down Expand Up @@ -846,17 +860,21 @@ impl sm::StateMachine<RfChannel> {
pub fn handle_settings(&mut self, settings: &ChannelSettings) -> Result<(), Error> {
self.context_mut().apply_settings(settings)?;

if matches!(settings.power_state, ChannelState::Off) {
// If settings has us disabled, it's always okay to blindly power down.
self.process_event(sm::Events::Disable).ok();
} else if matches!(settings.power_state, ChannelState::Off)
!= self.context().pins.enable_power.is_low().unwrap()
|| matches!(settings.power_state, ChannelState::Enabled)
!= self.context().pins.signal_on.is_high().unwrap()
{
// Our current power state has a mismatch with the settings. Reset ourselves into the
// updated state.
self.process_event(sm::Events::InterlockReset).ok();
match (self.state(), settings.state) {
// It's always acceptable to power off.
(_, ChannelState::Off) => {
self.process_event(sm::Events::Disable).ok();
}

// For cases when the channel needs to be powered, generate an interlock reset if the
// current power state doesn't match the desired state to kick the state machine into
// processing transitions.
(sm::States::Enabled | sm::States::Tripped(_), ChannelState::Powered)
ryan-summers marked this conversation as resolved.
Show resolved Hide resolved
| (sm::States::Off, ChannelState::Powered | ChannelState::Enabled) => {
self.process_event(sm::Events::InterlockReset).unwrap();
}

_ => {}
}

Ok(())
Expand Down
15 changes: 9 additions & 6 deletions src/settings/channel_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ const EXPECTED_VERSION: SemVersion = SemVersion {
patch: 1,
};

/// Indicates the enabled state of a channel.
/// Indicates the desired state of a channel.
#[derive(serde::Serialize, serde::Deserialize, Miniconf, Copy, Clone, PartialEq)]
pub enum ChannelState {
/// The channel should be turned off and power should be disconnected.
Off = 0,

/// The channel stages are powered and the RF switch is enabled.
// For compatibility reasons, Enabled is stored with the value equivalent to "true"
Enabled = 1,

// Stages are powered but RF switch is disabled. Used for bias current tuning.
/// Stages are powered but RF switch is disabled. Used for bias current tuning.
Powered = 2,
ryan-summers marked this conversation as resolved.
Show resolved Hide resolved
}

Expand All @@ -34,7 +37,7 @@ pub enum ChannelState {
pub struct ChannelSettings {
pub output_interlock_threshold: f32,
pub bias_voltage: f32,
pub power_state: ChannelState,
pub state: ChannelState,
pub input_power_transform: LinearTransformation,
pub output_power_transform: LinearTransformation,
pub reflected_power_transform: LinearTransformation,
Expand All @@ -46,7 +49,7 @@ impl Default for ChannelSettings {
Self {
output_interlock_threshold: 0.0,
bias_voltage: -3.2,
power_state: ChannelState::Off,
state: ChannelState::Off,

// When operating at 100MHz, the power detectors specify the following output
// characteristics for -10 dBm to 10 dBm (the equation uses slightly different coefficients
Expand Down Expand Up @@ -117,8 +120,8 @@ impl VersionedChannelData {
// We will never store `Powered` in EEPROM, since this is never desired. Cache the current
// power state while we serialize to ensure we only serialize Enabled and Off.
let mut versioned_copy = *self;
if matches!(versioned_copy.settings.power_state, ChannelState::Powered) {
versioned_copy.settings.power_state = ChannelState::Off;
if versioned_copy.settings.state == ChannelState::Powered {
versioned_copy.settings.state = ChannelState::Off;
}

let mut buffer: [u8; 64] = [0; 64];
Expand Down