Skip to content

Commit

Permalink
booster_channels: map() channel api
Browse files Browse the repository at this point in the history
  • Loading branch information
jordens committed Oct 10, 2020
1 parent d0a48af commit 6f1c8f1
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 174 deletions.
128 changes: 3 additions & 125 deletions src/booster_channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ use tca9548::{self, Tca9548};

use super::{I2cBusManager, I2cProxy};
use crate::error::Error;
use crate::rf_channel::{
ChannelPins as RfChannelPins, ChannelState, Property as RfChannelProperty, PropertyId,
RfChannel, ChannelStatus,
};
use crate::rf_channel::{ChannelPins as RfChannelPins, RfChannel};
use embedded_hal::blocking::delay::DelayUs;

/// Represents a control structure for interfacing to booster RF channels.
Expand Down Expand Up @@ -108,7 +105,7 @@ impl BoosterChannels {
/// # Args
/// * `channel` - The channel to perform the action on.
/// * `func` - A function called with the channel selected and with the channel and the ADC3 peripheral passed as arguments.
pub fn map_channel<F, R>(&mut self, channel: Channel, f: F) -> Result<R, Error>
pub fn map<F, R>(&mut self, channel: Channel, func: F) -> Result<R, Error>
where
F: FnOnce(&mut RfChannel, &mut hal::adc::Adc<hal::stm32::ADC3>) -> Result<R, Error>,
{
Expand All @@ -117,126 +114,7 @@ impl BoosterChannels {
let ch = &mut self.channels[channel as usize];
ch.as_mut().ok_or(Error::NotPresent).and_then(|ch| {
mux.select_bus(Some(channel.into())).unwrap();
f(ch, adc)
func(ch, adc)
})
}

/// Enable an RF channel.
///
/// # Args
/// * `channel` - The channel to enable.
pub fn enable_channel(&mut self, channel: Channel) -> Result<(), Error> {
self.map_channel(channel, |ch, _| ch.start_powerup(true))
}

/// Power up an RF channel without enabling output.
///
/// # Args
/// * `channel` - The channel to power-up.
pub fn power_channel(&mut self, channel: Channel) -> Result<(), Error> {
self.map_channel(channel, |ch, _| ch.start_powerup(false))
}

/// Disable an RF channel.
///
/// # Args
/// * `channel` - The channel to disable.
pub fn disable_channel(&mut self, channel: Channel) -> Result<(), Error> {
self.map_channel(channel, |ch, _| Ok(ch.start_disable()))
}

/// Get the temperature of a channel.
///
/// # Args
/// * `channel` - The channel to get the temperature of.
///
/// # Returns
/// The temperature of the channel in degrees celsius.
pub fn get_temperature(&mut self, channel: Channel) -> Result<f32, Error> {
self.map_channel(channel, |ch, _| Ok(ch.get_temperature()))
}

/// Set the bias voltage of a channel.
///
/// # Args
/// * `channel` - The channel to set the bias voltage of.
/// * `bias_voltage` - The desired bias voltage to apply to the RF amplification transistor.
pub fn set_bias(
&mut self,
channel: Channel,
bias_voltage: f32,
delay: &mut impl DelayUs<u16>,
) -> Result<(f32, f32), Error> {
self.map_channel(channel, |ch, _| {
ch.set_bias(bias_voltage)?;

// Settle the bias current and wait for an up-to-date measurement.
delay.delay_us(11000);
Ok((ch.get_bias_voltage(), ch.get_p28v_current()))
})
}

/// Get the state of a channel.
///
/// # Args
/// * `channel` - The channel to get the state of.
///
/// # Returns
/// The channel state of the requested channel.
pub fn get_channel_state(&mut self, channel: Channel) -> Result<ChannelState, Error> {
self.map_channel(channel, |ch, _| Ok(ch.get_state()))
}

/// Get the current status of the channel.
///
/// # Args
/// * `channel` - The channel to get the status of.
///
/// Returns
/// A structure indicating all measurements on the channel.
pub fn get_status(&mut self, channel: Channel) -> Result<ChannelStatus, Error> {
self.map_channel(channel, |ch, adc| Ok(ch.get_status(adc)))
}

/// Save the current channel configuration in channel EEPROM.
pub fn save_configuration(&mut self, channel: Channel) -> Result<(), Error> {
self.map_channel(channel, |ch, _| Ok(ch.save_configuration()))
}

/// Update the states of RF channels as necessary.
pub fn update(&mut self) {
for channel in Channel::into_enum_iter() {
self.map_channel(channel, |ch, _| Ok(ch.update().unwrap()))
.ok();
}
}

/// Read a property from an RF channel.
///
/// # Args
/// * `channel` - The channel to read the property of.
/// * `property` - The identifier of the property to read.
///
/// # Returns
/// The requested property of the desired channel.
pub fn read_property(
&mut self,
channel: Channel,
property: PropertyId,
) -> Result<RfChannelProperty, Error> {
self.map_channel(channel, |ch, _| Ok(ch.get_property(property)))
}

/// Write a property into an RF channel.
///
/// # Args
/// * `channel` - The channel to update the property of.
/// * `property` - The property to set.
pub fn write_property(
&mut self,
channel: Channel,
property: RfChannelProperty,
) -> Result<(), Error> {
self.map_channel(channel, |ch, _| ch.set_property(property))
}
}
31 changes: 16 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,12 +501,12 @@ const APP: () = {
// Check in with the watchdog.
c.resources.watchdog.check_in(WatchdogClient::MonitorTask);

// Potentially update the state of any channels.
c.resources.main_bus.channels.update();

// Check all of the timer channels.
for channel in Channel::into_enum_iter() {
let state = match c.resources.main_bus.channels.get_channel_state(channel) {
let state = match c.resources.main_bus.channels.map(channel, |ch, _| {
ch.update()?;
Ok(ch.get_state())
}) {
Err(Error::NotPresent) => {
// Clear all LEDs for this channel.
c.resources.leds.set_led(Color::Red, channel, false);
Expand Down Expand Up @@ -569,11 +569,11 @@ const APP: () = {
let mut temperatures: [f32; 8] = [0.0; 8];

for channel in Channel::into_enum_iter() {
temperatures[channel as usize] = match c
.resources
.main_bus
.lock(|main_bus| main_bus.channels.get_temperature(channel))
{
temperatures[channel as usize] = match c.resources.main_bus.lock(|main_bus| {
main_bus
.channels
.map(channel, |ch, _| Ok(ch.get_temperature()))
}) {
Ok(temp) => temp,
Err(Error::NotPresent) => 0.0,
err => err.unwrap(),
Expand Down Expand Up @@ -603,10 +603,11 @@ const APP: () = {

// Gather telemetry for all of the channels.
for channel in Channel::into_enum_iter() {
let measurements = c
.resources
.main_bus
.lock(|main_bus| main_bus.channels.get_status(channel));
let measurements = c.resources.main_bus.lock(|main_bus| {
main_bus
.channels
.map(channel, |ch, adc| Ok(ch.get_status(adc)))
});

if let Ok(measurements) = measurements {
// Broadcast the measured data over the telemetry interface.
Expand Down Expand Up @@ -647,7 +648,7 @@ const APP: () = {
ButtonEvent::InterlockReset => {
for chan in Channel::into_enum_iter() {
c.resources.main_bus.lock(|main_bus| {
match main_bus.channels.enable_channel(chan) {
match main_bus.channels.map(chan, |ch, _| ch.start_powerup(true)) {
Ok(_) | Err(Error::NotPresent) => {}

// It is possible to attempt to re-enable the channel before it was
Expand All @@ -664,7 +665,7 @@ const APP: () = {
ButtonEvent::Standby => {
for chan in Channel::into_enum_iter() {
c.resources.main_bus.lock(|main_bus| {
match main_bus.channels.disable_channel(chan) {
match main_bus.channels.map(chan, |ch, _| Ok(ch.start_disable())) {
Ok(_) | Err(Error::NotPresent) => {}
Err(e) => panic!("Standby failed on {:?}: {:?}", chan, e),
}
Expand Down
75 changes: 41 additions & 34 deletions src/mqtt_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,18 +244,18 @@ impl ControlState {
if !self.subscribed {
resources.mqtt_client.lock(|client| {
if client.is_connected().unwrap() {
client
.subscribe(&self.generate_topic_string("channel/state"), &[])
.unwrap();
client
.subscribe(&self.generate_topic_string("channel/bias"), &[])
.unwrap();
client
.subscribe(&self.generate_topic_string("channel/read"), &[])
.unwrap();
client
.subscribe(&self.generate_topic_string("channel/write"), &[])
.unwrap();
for topic in [
"channel/state",
"channel/bias",
"channel/read",
"channel/write",
]
.iter()
{
client
.subscribe(&self.generate_topic_string(topic), &[])
.unwrap();
}
self.subscribed = true;
}
});
Expand Down Expand Up @@ -334,25 +334,26 @@ fn handle_channel_update(message: &[u8], channels: &mut BoosterChannels) -> Stri
Ok(data) => data,
Err(_) => return Response::error_msg("Failed to decode data"),
};

match request.action {
ChannelAction::Enable => channels.enable_channel(request.channel).map_or_else(
|e| Response::error(e),
|_| Response::okay("Channel enabled"),
),
ChannelAction::Disable => channels.disable_channel(request.channel).map_or_else(
|e| Response::error(e),
|_| Response::okay("Channel disabled"),
),
ChannelAction::Powerup => channels.power_channel(request.channel).map_or_else(
|e| Response::error(e),
|_| Response::okay("Channel powered"),
),
ChannelAction::Save => channels.save_configuration(request.channel).map_or_else(
|e| Response::error(e),
|_| Response::okay("Configuration saved"),
),
}
channels
.map(request.channel, |ch, _| match request.action {
ChannelAction::Powerup => {
ch.start_powerup(false)?;
Ok("Channel powered")
}
ChannelAction::Enable => {
ch.start_powerup(true)?;
Ok("Channel enabled")
}
ChannelAction::Disable => {
ch.start_disable();
Ok("Channel disabled")
}
ChannelAction::Save => {
ch.save_configuration();
Ok("Channel saved")
}
})
.map_or_else(|e| Response::error(e), |m| Response::okay(m))
}

/// Handle a request to read a property of an RF channel.
Expand All @@ -372,7 +373,7 @@ fn handle_channel_property_read(
Err(_) => return Response::error_msg("Failed to decode read request"),
};

match channels.read_property(request.channel, request.prop) {
match channels.map(request.channel, |ch, _| Ok(ch.get_property(request.prop))) {
Ok(prop) => PropertyReadResponse::okay(prop),
Err(error) => Response::error(error),
}
Expand Down Expand Up @@ -400,7 +401,7 @@ fn handle_channel_property_write(
Err(_) => return Response::error_msg("Failed to decode property"),
};

match channels.write_property(request.channel, property) {
match channels.map(request.channel, |ch, _| ch.set_property(property)) {
Ok(_) => Response::okay("Property update successful"),
Err(error) => Response::error(error),
}
Expand All @@ -425,7 +426,13 @@ fn handle_channel_bias(
Err(_) => return Response::error_msg("Failed to decode data"),
};

match channels.set_bias(request.channel, request.voltage, delay) {
match channels.map(request.channel, |ch, _| {
ch.set_bias(request.voltage)?;

// Settle the bias current and wait for an up-to-date measurement.
delay.delay_us(11000);
Ok((ch.get_bias_voltage(), ch.get_p28v_current()))
}) {
Ok((vgs, ids)) => ChannelBiasResponse::okay(vgs, ids),
Err(error) => Response::error(error),
}
Expand Down

0 comments on commit 6f1c8f1

Please sign in to comment.