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

Expose channel monitoring and telemetry as RTIC tasks #32

Merged
merged 16 commits into from
Aug 24, 2020
Merged
Show file tree
Hide file tree
Changes from 8 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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ embedded-hal = "0.2.4"
enum-iterator = "0.6.0"
cortex-m-log = { version = "0.6.1", features = ["log-integration"] }
log = "0.4.8"
shared-bus-rtic = "0.1.2"
shared-bus-rtic = "0.2.1"


[dependencies.stm32f4xx-hal]
Expand Down
25 changes: 14 additions & 11 deletions src/booster_channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use tca9548::{self, Tca9548};
use crate::error::Error;
use crate::rf_channel::{ChannelPins as RfChannelPins, RfChannel};

use super::{BusManager, BusProxy, I2C};
use super::I2C;
use shared_bus_rtic::{CommonBus, SharedBus};

/// A EUI-48 identifier for a given channel.
pub struct ChannelIdentifier {
Expand All @@ -27,6 +28,7 @@ impl ChannelIdentifier {
}

/// Contains channel status information in SI base units.
#[derive(Debug)]
pub struct ChannelStatus {
pub input_overdrive: bool,
pub output_overdrive: bool,
Expand All @@ -47,7 +49,8 @@ pub struct ChannelStatus {
/// Represents a control structure for interfacing to booster RF channels.
pub struct BoosterChannels {
channels: [Option<RfChannel>; 8],
mux: Tca9548<BusProxy<I2C>>,
adc: core::cell::RefCell<hal::adc::Adc<hal::stm32::ADC3>>,
mux: Tca9548<SharedBus<I2C>>,
}

/// Indicates a booster RF channel.
Expand Down Expand Up @@ -86,14 +89,16 @@ impl BoosterChannels {
///
/// # Args
/// * `mux` - The I2C mux used for switching between channel communications.
/// * `adc` - The ADC used to measure analog channels.
/// * `manager` - The I2C bus manager used for the shared I2C bus.
/// * `pins` - An array of all RfChannel control/status pins.
///
/// # Returns
/// A `BoosterChannels` object that can be used to manage all available RF channels.
pub fn new(
mut mux: Tca9548<BusProxy<I2C>>,
manager: &'static BusManager,
mut mux: Tca9548<SharedBus<I2C>>,
adc: hal::adc::Adc<hal::stm32::ADC3>,
manager: &'static CommonBus<I2C>,
mut pins: [Option<RfChannelPins>; 8],
) -> Self {
let mut rf_channels: [Option<RfChannel>; 8] =
Expand All @@ -108,7 +113,7 @@ impl BoosterChannels {
.take()
.expect("Channel pins not available");

match RfChannel::new(manager, control_pins) {
match RfChannel::new(&manager, control_pins) {
Some(mut rf_channel) => {
// Setting interlock thresholds should not fail here as we have verified the
// device is on the bus.
Expand All @@ -124,6 +129,7 @@ impl BoosterChannels {
BoosterChannels {
channels: rf_channels,
mux: mux,
adc: core::cell::RefCell::new(adc),
}
}

Expand Down Expand Up @@ -291,21 +297,18 @@ impl BoosterChannels {
///
/// # Args
/// * `channel` - The channel to get the status of.
/// * `adc` - The ADC to use for measuring channel power measurements.
///
/// Returns
/// A structure indicating all measurements on the channel.
pub fn get_status(
&mut self,
channel: Channel,
mut adc: hal::adc::Adc<hal::stm32::ADC3>,
) -> Result<ChannelStatus, Error> {
pub fn get_status(&mut self, channel: Channel) -> Result<ChannelStatus, Error> {
self.mux.select_bus(Some(channel.into())).unwrap();

match &mut self.channels[channel as usize] {
Some(rf_channel) => {
let power_measurements = rf_channel.get_supply_measurements();

let mut adc = self.adc.borrow_mut();

let status = ChannelStatus {
input_overdrive: rf_channel.pins.input_overdrive.is_high().unwrap(),
output_overdrive: rf_channel.pins.output_overdrive.is_high().unwrap(),
Expand Down
76 changes: 68 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@
extern crate log;

use cortex_m::asm;
use enum_iterator::IntoEnumIterator;
use panic_halt as _;
use shared_bus_rtic::{self, BusProxy};
use stm32f4xx_hal as hal;

use hal::prelude::*;
use hal::{prelude::*, timer::Event};

mod booster_channels;
mod error;
mod linear_transformation;
mod rf_channel;
use booster_channels::BoosterChannels;
use booster_channels::{BoosterChannels, Channel};
use error::Error;
use rf_channel::{AdcPin, AnalogPins as AdcPins, ChannelPins as RfChannelPins};

// Convenience type definition for the I2C bus used for booster RF channels.
Expand All @@ -33,9 +34,6 @@ type I2C = hal::i2c::I2c<
),
>;

// Convenience type definition for the shared bus BusManager type.
type BusManager = shared_bus_rtic::shared_bus::BusManager<shared_bus_rtic::Mutex<I2C>, I2C>;

/// Construct ADC pins associated with an RF channel.
///
/// # Args
Expand Down Expand Up @@ -90,6 +88,8 @@ macro_rules! channel_pins {
#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true)]
const APP: () = {
struct Resources {
monitor_timer: hal::timer::Timer<hal::stm32::TIM2>,
telemetry_timer: hal::timer::Timer<hal::stm32::TIM3>,
channels: BoosterChannels,
}

Expand Down Expand Up @@ -177,12 +177,72 @@ const APP: () = {
.unwrap()
};

BoosterChannels::new(mux, &i2c_bus_manager, channel_pins)
let adc =
hal::adc::Adc::adc3(c.device.ADC3, true, hal::adc::config::AdcConfig::default());

BoosterChannels::new(mux, adc, i2c_bus_manager, channel_pins)
};

info!("Startup complete");

init::LateResources { channels: channels }
// Configure a timer to periodically monitor the output channels.
let mut monitor_timer = hal::timer::Timer::tim2(c.device.TIM2, 50.hz(), clocks);
monitor_timer.listen(Event::TimeOut);

// Configure a timer to periodically gather telemetry.
let mut telemetry_timer = hal::timer::Timer::tim3(c.device.TIM3, 2.hz(), clocks);
telemetry_timer.listen(Event::TimeOut);

init::LateResources {
monitor_timer: monitor_timer,
telemetry_timer: telemetry_timer,
channels: channels,
}
}

#[task(binds=TIM2, priority=2, resources=[monitor_timer, channels])]
fn channel_monitor(c: channel_monitor::Context) {
c.resources.monitor_timer.clear_interrupt(Event::TimeOut);

// Check all of the timer channels.
for channel in Channel::into_enum_iter() {
let _error_detected = match c.resources.channels.error_detected(channel) {
Err(Error::NotPresent) => {
// TODO: Clear all LEDs for this channel.
continue;
}
Ok(detected) => detected,
Err(error) => panic!("Encountered error: {:?}", error),
};

let _warning_detected = match c.resources.channels.warning_detected(channel) {
Ok(detected) => detected,
Err(error) => panic!("Encountered error: {:?}", error),
};

let _enabled = match c.resources.channels.is_enabled(channel) {
Ok(detected) => detected,
Err(error) => panic!("Encountered error: {:?}", error),
};

// TODO: Echo the measured values to the LEDs on the user interface for this channel.
}
}

#[task(binds=TIM3, priority=1, resources=[telemetry_timer, channels])]
fn telemetry(mut c: telemetry::Context) {
c.resources.telemetry_timer.clear_interrupt(Event::TimeOut);

// Gather telemetry for all of the channels.
for channel in Channel::into_enum_iter() {
let measurements = c
.resources
.channels
.lock(|booster_channels| booster_channels.get_status(channel));

// TODO: Broadcast the measured data over the telemetry interface.
info!("{:?}", measurements);
}
}

#[idle(resources=[channels])]
Expand Down
9 changes: 5 additions & 4 deletions src/rf_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ use max6642::Max6642;
use mcp3221::Mcp3221;
use microchip_24aa02e48::Microchip24AA02E48;

use super::{BusManager, BusProxy, I2C};
use super::I2C;
use crate::error::Error;
use shared_bus_rtic::SharedBus;
use stm32f4xx_hal::{
self as hal,
adc::config::SampleTime,
Expand All @@ -22,7 +23,7 @@ use stm32f4xx_hal::{
};

// Convenience type definition for all I2C devices on the bus.
type I2cDevice = BusProxy<I2C>;
type I2cDevice = SharedBus<I2C>;

/// A structure representing power supply measurements of a channel.
pub struct SupplyMeasurements {
Expand Down Expand Up @@ -142,7 +143,7 @@ impl Devices {
/// # Returns
/// An option containing the devices if they were discovered on the bus. If any device did not
/// properly enumerate, the option will be empty.
fn new(manager: &'static BusManager) -> Option<Self> {
fn new(manager: SharedBus<I2C>) -> Option<Self> {
// The ADS7924 and DAC7571 are present on the booster mainboard, so instantiation
// and communication should never fail.
let mut dac7571 = Dac7571::default(manager.acquire());
Expand Down Expand Up @@ -267,7 +268,7 @@ impl RfChannel {
///
/// # Returns
/// An option containing an RfChannel if a channel was discovered on the bus. None otherwise.
pub fn new(manager: &'static BusManager, control_pins: ChannelPins) -> Option<Self> {
pub fn new(manager: &SharedBus<I2C>, control_pins: ChannelPins) -> Option<Self> {
// Attempt to instantiate the I2C devices on the channel.
match Devices::new(manager) {
Some(devices) => {
Expand Down