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

Initial interlock configuration and RF channel management structure #27

Merged
merged 28 commits into from
Jul 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e97f382
Adding work-in-progress shared-bus implementation
ryan-summers Jul 3, 2020
9c5df1d
Adding WIP
ryan-summers Jul 6, 2020
6bcd876
Adding AD5627 driver
ryan-summers Jul 6, 2020
e82379c
Merge branch 'develop' into feature/interlock-config
ryan-summers Jul 6, 2020
c6d6e8b
Adding finalized I2C mux
ryan-summers Jul 6, 2020
a7441f1
Formatting AD5627
ryan-summers Jul 6, 2020
f2b86fc
Adding configuration of interlock thresholds
ryan-summers Jul 6, 2020
9f0f807
Merge branch 'feature/interlock-drivers' into feature/interlock-config
ryan-summers Jul 6, 2020
64871a8
Fixing driver structure
ryan-summers Jul 6, 2020
f54facc
Removing redundant drivers
ryan-summers Jul 6, 2020
1f0db7a
Cleaning up code
ryan-summers Jul 6, 2020
08be914
Merge branch 'develop' into feature/interlock-config
ryan-summers Jul 8, 2020
0d7dc23
Adding copyright notice
ryan-summers Jul 8, 2020
875fecd
Adding WIP support for RF channels
ryan-summers Jul 8, 2020
c9fd21f
Adding channel GPIO and device configuration
ryan-summers Jul 8, 2020
b86ed2f
Merge branch 'develop' into feature/interlock-config
ryan-summers Jul 8, 2020
ba0a277
Adding work-in-progress channel control
ryan-summers Jul 8, 2020
a6f1b7f
Adding initial configuration of interlock thresholds
ryan-summers Jul 8, 2020
2fa0a4b
Merge branch 'feature/rtic-integration' into feature/interlock-config
ryan-summers Jul 8, 2020
20a85f7
Merge branch 'develop' into feature/interlock-config
ryan-summers Jul 8, 2020
8c61d65
Correcting changes to toml
ryan-summers Jul 8, 2020
631c365
Fixing lint
ryan-summers Jul 8, 2020
e096d07
Adding logging, fixing code after review
ryan-summers Jul 9, 2020
184833f
Formatting
ryan-summers Jul 9, 2020
9231890
Adding analog power measurement pins to channel structures
ryan-summers Jul 9, 2020
b9b4005
Adding docs for macro
ryan-summers Jul 9, 2020
69cc32f
Renaming control pins to channel pins
ryan-summers Jul 9, 2020
30799fe
Fixing power measurement equations, updating comments
ryan-summers Jul 9, 2020
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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ cortex-m-rt = "0.6.10"
panic-halt = "0.2.0"
cortex-m-rtic = "0.5.3"
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"
Expand Down
1 change: 1 addition & 0 deletions ads7924/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub enum Channel {
}

/// Indicates errors that the ADC may encounter.
#[derive(Debug)]
pub enum Error {
Interface,
Size,
Expand Down
1 change: 1 addition & 0 deletions dac7571/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ where
}

/// Represents errors that can be generated by the DAC driver.
#[derive(Debug)]
pub enum Error {
Bounds,
Interface,
Expand Down
133 changes: 133 additions & 0 deletions src/booster_channels.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
//! Booster NGFW channel management control interface definitions.
//!
//! # Copyright
//! Copyright (C) 2020 QUARTIQ GmbH - All Rights Reserved
//! Unauthorized usage, editing, or copying is strictly prohibited.
//! Proprietary and confidential.

use enum_iterator::IntoEnumIterator;
use tca9548::{self, Tca9548};

use super::{BusManager, BusProxy, I2C};
use crate::error::Error;
use crate::rf_channel::{ChannelPins as RfChannelPins, RfChannel};

/// Represents a control structure for interfacing to booster RF channels.
pub struct BoosterChannels {
channels: [Option<RfChannel>; 8],
mux: Tca9548<BusProxy<I2C>>,
}

/// Indicates a booster RF channel.
#[derive(IntoEnumIterator, Copy, Clone, Debug)]
pub enum Channel {
Zero = 0,
One = 1,
Two = 2,
Three = 3,
Four = 4,
Five = 5,
Six = 6,
Seven = 7,
}

impl Into<tca9548::Bus> for Channel {
fn into(self) -> tca9548::Bus {
match self {
Channel::Zero => tca9548::Bus::Zero,
Channel::One => tca9548::Bus::One,
Channel::Two => tca9548::Bus::Two,
Channel::Three => tca9548::Bus::Three,
Channel::Four => tca9548::Bus::Four,
Channel::Five => tca9548::Bus::Five,
Channel::Six => tca9548::Bus::Six,
Channel::Seven => tca9548::Bus::Seven,
}
}
}

impl BoosterChannels {
/// Construct booster RF channels.
///
/// # Note
/// This function will scan channels to check if they are present.
///
/// # Args
/// * `mux` - The I2C mux used for switching between channel communications.
/// * `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 pins: [Option<RfChannelPins>; 8],
) -> Self {
let mut rf_channels: [Option<RfChannel>; 8] =
[None, None, None, None, None, None, None, None];

for channel in Channel::into_enum_iter() {
// Selecting an I2C bus should never fail.
mux.select_bus(Some(channel.into()))
.expect("Failed to select channel");

let control_pins = pins[channel as usize]
.take()
.expect("Channel pins not available");
jordens marked this conversation as resolved.
Show resolved Hide resolved

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.
rf_channel.set_interlock_thresholds(0.0, 0.0).unwrap();
rf_channels[channel as usize].replace(rf_channel);
}
None => {
info!("Channel {} did not enumerate", channel as usize);
}
}
}

BoosterChannels {
channels: rf_channels,
mux: mux,
}
}

/// Set the interlock thresholds for the channel.
///
/// # Args
/// * `channel` - The RF channel to set thresholds for.
/// * `forward_threshold` - The dBm interlock threshold for forward power.
/// * `reflected_threshold` - The dBm interlock threshold for reflected power.
pub fn set_interlock_thresholds(
&mut self,
channel: Channel,
forward_threshold: f32,
reflected_threshold: f32,
) -> Result<(), Error> {
if self.channels[channel as usize].is_none() {
return Err(Error::NotPresent);
}

// Selecting an I2C bus should never fail.
self.mux
.select_bus(Some(channel.into()))
.expect("Failed to select channel");

match &mut self.channels[channel as usize] {
Some(rf_channel) => {
match rf_channel.set_interlock_thresholds(forward_threshold, reflected_threshold) {
// Configuring a present channel should never have an interface failure
// (although the requested value may be out of range).
Err(Error::Interface) => {
panic!("Failed to configure thresholds on CH{}", channel as usize);
}
x => x,
}
}
None => Err(Error::NotPresent),
}
}
}
15 changes: 15 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//! Error type definitions for Booster NGFW
//!
//! # Copyright
//! Copyright (C) 2020 QUARTIQ GmbH - All Rights Reserved
//! Unauthorized usage, editing, or copying is strictly prohibited.
//! Proprietary and confidential.

/// An enumeration of possible errors with the device.
#[derive(Debug, Copy, Clone)]
pub enum Error {
Invalid,
NotPresent,
Interface,
Bounds,
}
131 changes: 121 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ use shared_bus_rtic::{self, BusProxy};
use stm32f4xx_hal as hal;

use hal::prelude::*;
use tca9548::Tca9548;

mod booster_channels;
mod error;
mod rf_channel;
use booster_channels::BoosterChannels;
use rf_channel::{AdcPins, ChannelPins as RfChannelPins};

// Convenience type definition for the I2C bus used for booster RF channels.
type I2C = hal::i2c::I2c<
Expand All @@ -27,10 +32,65 @@ 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
/// * `gpio` - The GPIO port used to instantiate analog pins.
/// * `tx_power` - The name of the pin to instantiate for the TX power measurement.
/// * `reflected_power` - The name of the pin to instantiate for the reflected power measurement.
///
/// # Returns
/// An AdcPin enumeration describing the ADC pins.
macro_rules! adc_pins {
($gpio:ident, $tx_power:ident, $reflected_power:ident) => {{
let tx_power = $gpio.$tx_power.into_analog().downgrade();
let reflected_power = $gpio.$reflected_power.into_analog().downgrade();

AdcPins::$gpio(tx_power, reflected_power)
}};
}

/// Macro for genering an RfChannelPins structure.
///
/// # Args
/// * `gpiod` - The GPIOD Parts structure to extract pins from.
/// * `gpioe` - The GPIOE Parts structure to extract pins from.
/// * `gpiog` - The GPIOG Parts structure to extract pins from.
/// * `enable` - The pin ID of the enable pin in GPIOD.
/// * `alert` - The pin ID of the alert pin in GPIOD.
/// * `input_overdrive` - The pin ID of the input overdrive pin in GPIOE.
/// * `output_overdrive` - The pin ID of the output overdrive pin in GPIOE.
/// * `signal_on` - The pin ID of the signal on pin in GPIOG.
///
/// # Returns
/// An option containing the RfChannelPins structure.
macro_rules! channel_pins {
($gpiod:ident, $gpioe:ident, $gpiog:ident, $enable:ident, $alert:ident, $input_overdrive:ident,
$output_overdrive:ident, $signal_on:ident, $analog_pins:ident) => {{
let enable_power = $gpiod.$enable.into_push_pull_output().downgrade();
let alert = $gpiod.$alert.into_floating_input().downgrade();
let input_overdrive = $gpioe.$input_overdrive.into_floating_input().downgrade();
let output_overdrive = $gpioe.$output_overdrive.into_pull_down_input().downgrade();
let signal_on = $gpiog.$signal_on.into_push_pull_output().downgrade();

Some(RfChannelPins::new(
jordens marked this conversation as resolved.
Show resolved Hide resolved
enable_power,
alert,
input_overdrive,
output_overdrive,
signal_on,
$analog_pins,
))
}};
}

#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true)]
const APP: () = {
struct Resources {
mux: Tca9548<BusProxy<I2C>>,
channels: BoosterChannels,
}

#[init]
Expand All @@ -49,10 +109,16 @@ const APP: () = {
.require_pll48clk()
.freeze();

let gpiob = c.device.GPIOB.split();

let mut delay = hal::delay::Delay::new(cp.SYST, clocks);

let gpioa = c.device.GPIOA.split();
let gpiob = c.device.GPIOB.split();
let gpioc = c.device.GPIOC.split();
let gpiod = c.device.GPIOD.split();
let gpioe = c.device.GPIOE.split();
let gpiof = c.device.GPIOF.split();
let gpiog = c.device.GPIOG.split();

let i2c_bus_manager = {
let i2c = {
let scl = gpiob.pb6.into_alternate_af4_open_drain();
Expand All @@ -63,18 +129,63 @@ const APP: () = {
shared_bus_rtic::new!(i2c, I2C)
};

let mux = {
let mut i2c_mux_reset = gpiob.pb14.into_push_pull_output();
tca9548::Tca9548::default(i2c_bus_manager.acquire(), &mut i2c_mux_reset, &mut delay)
.unwrap()
// Instantiate the I2C interface to the I2C mux. Use a shared-bus so we can share the I2C
// bus with all of the Booster peripheral devices.
let channels = {
let channel_pins = {
let ch1_pins = {
let analog_pins = adc_pins!(gpioa, pa0, pa1);
channel_pins!(gpiod, gpioe, gpiog, pd0, pd8, pe8, pe0, pg8, analog_pins)
};
let ch2_pins = {
let analog_pins = adc_pins!(gpioa, pa2, pa3);
channel_pins!(gpiod, gpioe, gpiog, pd1, pd9, pe9, pe1, pg9, analog_pins)
};
let ch3_pins = {
let analog_pins = adc_pins!(gpiof, pf6, pf7);
channel_pins!(gpiod, gpioe, gpiog, pd2, pd10, pe10, pe2, pg10, analog_pins)
};
let ch4_pins = {
let analog_pins = adc_pins!(gpiof, pf8, pf9);
channel_pins!(gpiod, gpioe, gpiog, pd3, pd11, pe11, pe3, pg11, analog_pins)
};
let ch5_pins = {
let analog_pins = adc_pins!(gpiof, pf10, pf3);
channel_pins!(gpiod, gpioe, gpiog, pd4, pd12, pe12, pe4, pg12, analog_pins)
};
let ch6_pins = {
let analog_pins = adc_pins!(gpioc, pc0, pc1);
channel_pins!(gpiod, gpioe, gpiog, pd5, pd13, pe13, pe5, pg13, analog_pins)
};
let ch7_pins = {
let analog_pins = adc_pins!(gpioc, pc2, pc3);
channel_pins!(gpiod, gpioe, gpiog, pd6, pd14, pe14, pe6, pg14, analog_pins)
};
let ch8_pins = {
let analog_pins = adc_pins!(gpiof, pf4, pf5);
channel_pins!(gpiod, gpioe, gpiog, pd7, pd15, pe15, pe7, pg15, analog_pins)
};

[
ch1_pins, ch2_pins, ch3_pins, ch4_pins, ch5_pins, ch6_pins, ch7_pins, ch8_pins,
]
};

let mux = {
let mut i2c_mux_reset = gpiob.pb14.into_push_pull_output();
tca9548::Tca9548::default(i2c_bus_manager.acquire(), &mut i2c_mux_reset, &mut delay)
.unwrap()
};

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

info!("Startup complete");

init::LateResources { mux }
init::LateResources { channels: channels }
}

#[idle(resources=[mux])]
#[idle(resources=[channels])]
fn idle(_: idle::Context) -> ! {
loop {
asm::nop();
Expand Down
Loading