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 22 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
134 changes: 134 additions & 0 deletions src/booster_channels.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
//! 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 embedded_hal::blocking::delay::DelayMs;
use enum_iterator::IntoEnumIterator;
use tca9548::{self, Tca9548};

use super::{BusManager, BusProxy, I2C};
use crate::error::Error;
use crate::rf_channel::{ControlPins 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 and enable 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.
/// * `delay` - A delay function to delay while waiting for channels to power up.
///
/// # Returns
/// A `BoosterChannels` object that can be used to manage all available RF channels.
pub fn new<DELAY>(
mut mux: Tca9548<BusProxy<I2C>>,
manager: &'static BusManager,
mut pins: [Option<RfChannelPins>; 8],
delay: &mut DELAY,
) -> Self
where
DELAY: DelayMs<u8>,
{
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())).unwrap();

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, delay) {
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(-30.0, -30.0).unwrap();
ryan-summers marked this conversation as resolved.
Show resolved Hide resolved
rf_channels[channel as usize].replace(rf_channel);
}
None => {}
}
}

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())).unwrap();

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,
}
87 changes: 75 additions & 12 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::ControlPins as RfChannelPins;

// Convenience type definition for the I2C bus used for booster RF channels.
type I2C = hal::i2c::I2c<
Expand All @@ -27,10 +32,46 @@ 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>;

/// 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) => {{
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,
))
}};
}

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

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

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

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

let gpiob = c.device.GPIOB.split();
let gpiod = c.device.GPIOD.split();
let gpioe = c.device.GPIOE.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 +107,37 @@ 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 = channel_pins!(gpiod, gpioe, gpiog, pd0, pd8, pe8, pe0, pg8);
let ch2_pins = channel_pins!(gpiod, gpioe, gpiog, pd1, pd9, pe9, pe1, pg9);
let ch3_pins = channel_pins!(gpiod, gpioe, gpiog, pd2, pd10, pe10, pe2, pg10);
let ch4_pins = channel_pins!(gpiod, gpioe, gpiog, pd3, pd11, pe11, pe3, pg11);
let ch5_pins = channel_pins!(gpiod, gpioe, gpiog, pd4, pd12, pe12, pe4, pg12);
let ch6_pins = channel_pins!(gpiod, gpioe, gpiog, pd5, pd13, pe13, pe5, pg13);
let ch7_pins = channel_pins!(gpiod, gpioe, gpiog, pd6, pd14, pe14, pe6, pg14);
let ch8_pins = channel_pins!(gpiod, gpioe, gpiog, pd7, pd15, pe15, pe7, pg15);

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

info!("Startup complete");
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, &mut delay)
};

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

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