main: refactor into Channel/Channels

softspi
Astro 2020-05-12 23:16:57 +02:00
parent 6dd6bb2e1e
commit 9466961bd7
4 changed files with 153 additions and 64 deletions

34
src/channel.rs Normal file
View File

@ -0,0 +1,34 @@
use crate::pins::{ChannelPins, ChannelPinSet};
use crate::channel_state::ChannelState;
use crate::ad5680;
/// Marker type for the first channel
pub struct Channel0;
/// Marker type for the second channel
pub struct Channel1;
pub struct Channel<C: ChannelPins> {
pub state: ChannelState,
pub dac: ad5680::Dac<C::DacSpi, C::DacSync>,
pub shdn: C::Shdn,
pub ref_adc: C::RefAdc,
pub ref_pin: C::RefPin,
}
impl<C: ChannelPins> Channel<C> {
pub fn new(pins: ChannelPinSet<C>) -> Self {
let state = ChannelState::default();
let mut dac = ad5680::Dac::new(pins.dac_spi, pins.dac_sync);
let _ = dac.set(0);
Channel {
state,
dac,
shdn: pins.shdn,
ref_adc: pins.ref_adc,
ref_pin: pins.ref_pin,
}
}
}

30
src/channels.rs Normal file
View File

@ -0,0 +1,30 @@
use crate::{
ad7172,
channel::{Channel, Channel0, Channel1},
pins,
};
pub struct Channels {
pub channel0: Channel<Channel0>,
pub channel1: Channel<Channel1>,
pub adc: ad7172::Adc<pins::AdcSpi, pins::AdcNss>,
pub pwm: pins::PwmPins,
}
impl Channels {
pub fn new(pins: pins::Pins) -> Self {
let channel0 = Channel::new(pins.channel0);
let channel1 = Channel::new(pins.channel1);
let pwm = pins.pwm;
let mut adc = ad7172::Adc::new(pins.adc_spi, pins.adc_nss).unwrap();
// Feature not used
adc.set_sync_enable(false).unwrap();
// Setup channels
adc.setup_channel(0, ad7172::Input::Ain0, ad7172::Input::Ain1).unwrap();
adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap();
adc.calibrate_offset().unwrap();
Channels { channel0, channel1, adc, pwm }
}
}

View File

@ -45,6 +45,9 @@ use command_parser::{Command, ShowCommand, PwmPin};
mod timer;
mod pid;
mod steinhart_hart;
mod channels;
use channels::Channels;
mod channel;
mod channel_state;
use channel_state::ChannelState;
@ -92,24 +95,10 @@ fn main() -> ! {
dp.SPI2, dp.SPI4, dp.SPI5,
dp.ADC1, dp.ADC2,
);
let mut adc = ad7172::Adc::new(pins.adc_spi, pins.adc_nss).unwrap();
// Feature not used
adc.set_sync_enable(false).unwrap();
// Setup channels
adc.setup_channel(0, ad7172::Input::Ain0, ad7172::Input::Ain1).unwrap();
adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap();
adc.calibrate_offset().unwrap();
let mut dac0 = ad5680::Dac::new(pins.dac0_spi, pins.dac0_sync);
dac0.set(0).unwrap();
let mut dac1 = ad5680::Dac::new(pins.dac1_spi, pins.dac1_sync);
dac1.set(0).unwrap();
let mut pwm = pins.pwm;
let mut shdn0 = pins.shdn0;
let mut shdn1 = pins.shdn1;
let mut channels = Channels::new(pins);
let mut channel_states: [ChannelState; CHANNELS] = [
ChannelState::default(), ChannelState::default()
];
timer::setup(cp.SYST, clocks);
#[cfg(not(feature = "generate-hwaddr"))]
@ -121,17 +110,13 @@ fn main() -> ! {
};
info!("Net hwaddr: {}", hwaddr);
let mut channel_states: [ChannelState; CHANNELS] = [
ChannelState::default(), ChannelState::default()
];
net::run(dp.ETHERNET_MAC, dp.ETHERNET_DMA, hwaddr, |iface| {
Server::<Session>::run(iface, |server| {
loop {
let instant = Instant::from_millis(i64::from(timer::now()));
// ADC input
adc.data_ready().unwrap().map(|channel| {
let data = adc.read_data().unwrap();
channels.adc.data_ready().unwrap().map(|channel| {
let data = channels.adc.read_data().unwrap();
let state = &mut channel_states[usize::from(channel)];
state.update_adc(instant, data);
@ -140,12 +125,12 @@ fn main() -> ! {
// Forward PID output to i_set DAC
match channel {
0 => {
dac0.set(state.dac_value).unwrap();
shdn0.set_high().unwrap();
channels.channel0.dac.set(state.dac_value).unwrap();
channels.channel0.shdn.set_high().unwrap();
}
1 => {
dac1.set(state.dac_value).unwrap();
shdn1.set_high().unwrap();
channels.channel1.dac.set(state.dac_value).unwrap();
channels.channel1.shdn.set_high().unwrap();
}
_ =>
unreachable!(),
@ -189,8 +174,8 @@ fn main() -> ! {
}
}
let ref0 = pins.ref0_adc.convert(
&pins.ref0_pin, stm32f4xx_hal::adc::config::SampleTime::Cycles_480
let ref0 = channels.channel0.ref_adc.convert(
&channels.channel0.ref_pin, stm32f4xx_hal::adc::config::SampleTime::Cycles_480
);
let _ = writeln!(socket, "ref0={}", ref0);
}
@ -241,14 +226,14 @@ fn main() -> ! {
}
match channel {
0 => {
show_pwm_channel(socket.deref_mut(), "max_v", &pwm.max_v0);
show_pwm_channel(socket.deref_mut(), "max_i_pos", &pwm.max_i_pos0);
show_pwm_channel(socket.deref_mut(), "max_i_neg", &pwm.max_i_neg0);
show_pwm_channel(socket.deref_mut(), "max_v", &channels.pwm.max_v0);
show_pwm_channel(socket.deref_mut(), "max_i_pos", &channels.pwm.max_i_pos0);
show_pwm_channel(socket.deref_mut(), "max_i_neg", &channels.pwm.max_i_neg0);
}
1 => {
show_pwm_channel(socket.deref_mut(), "max_v", &pwm.max_v1);
show_pwm_channel(socket.deref_mut(), "max_i_pos", &pwm.max_i_pos1);
show_pwm_channel(socket.deref_mut(), "max_i_neg", &pwm.max_i_neg1);
show_pwm_channel(socket.deref_mut(), "max_v", &channels.pwm.max_v1);
show_pwm_channel(socket.deref_mut(), "max_i_pos", &channels.pwm.max_i_pos1);
show_pwm_channel(socket.deref_mut(), "max_i_neg", &channels.pwm.max_i_neg1);
}
_ => unreachable!(),
}
@ -269,7 +254,7 @@ fn main() -> ! {
}
Command::Show(ShowCommand::PostFilter) => {
for (channel, _) in channel_states.iter().enumerate() {
match adc.get_postfilter(channel as u8).unwrap() {
match channels.adc.get_postfilter(channel as u8).unwrap() {
Some(filter) => {
let _ = writeln!(
socket, "channel {}: postfilter={:.2} SPS",
@ -294,12 +279,12 @@ fn main() -> ! {
channel_states[channel].pid_enabled = false;
match channel {
0 => {
dac0.set(duty).unwrap();
shdn0.set_high().unwrap();
channels.channel0.dac.set(duty).unwrap();
channels.channel0.shdn.set_high().unwrap();
}
1 => {
dac1.set(duty).unwrap();
shdn1.set_high().unwrap();
channels.channel1.dac.set(duty).unwrap();
channels.channel1.shdn.set_high().unwrap();
}
_ => unreachable!(),
}
@ -327,17 +312,17 @@ fn main() -> ! {
// Handled above
unreachable!(),
(0, PwmPin::MaxIPos) =>
set_pwm_channel(&mut pwm.max_i_pos0, duty),
set_pwm_channel(&mut channels.pwm.max_i_pos0, duty),
(0, PwmPin::MaxINeg) =>
set_pwm_channel(&mut pwm.max_i_neg0, duty),
set_pwm_channel(&mut channels.pwm.max_i_neg0, duty),
(0, PwmPin::MaxV) =>
set_pwm_channel(&mut pwm.max_v0, duty),
set_pwm_channel(&mut channels.pwm.max_v0, duty),
(1, PwmPin::MaxIPos) =>
set_pwm_channel(&mut pwm.max_i_pos1, duty),
set_pwm_channel(&mut channels.pwm.max_i_pos1, duty),
(1, PwmPin::MaxINeg) =>
set_pwm_channel(&mut pwm.max_i_neg1, duty),
set_pwm_channel(&mut channels.pwm.max_i_neg1, duty),
(1, PwmPin::MaxV) =>
set_pwm_channel(&mut pwm.max_v1, duty),
set_pwm_channel(&mut channels.pwm.max_v1, duty),
_ =>
unreachable!(),
};
@ -389,7 +374,7 @@ fn main() -> ! {
let filter = ad7172::PostFilter::closest(rate);
match filter {
Some(filter) => {
adc.set_postfilter(channel as u8, Some(filter)).unwrap();
channels.adc.set_postfilter(channel as u8, Some(filter)).unwrap();
let _ = writeln!(
socket, "channel {}: postfilter set to {:.2} SPS",
channel, filter.output_rate().unwrap()

View File

@ -1,6 +1,6 @@
use stm32f4xx_hal::{
adc::Adc,
hal::digital::v2::OutputPin,
hal::{blocking::spi::Transfer, digital::v2::OutputPin},
gpio::{
AF5, Alternate, Analog,
gpioa::*,
@ -22,25 +22,51 @@ use stm32f4xx_hal::{
use crate::channel::{Channel0, Channel1};
pub trait ChannelPins {
type DacSpi: Transfer<u8>;
type DacSync: OutputPin;
type Shdn: OutputPin;
type RefAdc;
type RefPin;
}
impl ChannelPins for Channel0 {
type DacSpi = Dac0Spi;
type DacSync = PE4<Output<PushPull>>;
type Shdn = PE10<Output<PushPull>>;
type RefAdc = Adc<ADC1>;
type RefPin = PA0<Analog>;
}
impl ChannelPins for Channel1 {
type DacSpi = Dac1Spi;
type DacSync = PF6<Output<PushPull>>;
type Shdn = PE15<Output<PushPull>>;
type RefAdc = Adc<ADC2>;
type RefPin = PA3<Analog>;
}
/// SPI peripheral used for communication with the ADC
type AdcSpi = Spi<SPI2, (PB10<Alternate<AF5>>, PB14<Alternate<AF5>>, PB15<Alternate<AF5>>)>;
pub type AdcSpi = Spi<SPI2, (PB10<Alternate<AF5>>, PB14<Alternate<AF5>>, PB15<Alternate<AF5>>)>;
pub type AdcNss = PB12<Output<PushPull>>;
type Dac0Spi = Spi<SPI4, (PE2<Alternate<AF5>>, NoMiso, PE6<Alternate<AF5>>)>;
type Dac1Spi = Spi<SPI5, (PF7<Alternate<AF5>>, NoMiso, PF9<Alternate<AF5>>)>;
pub struct ChannelPinSet<C: ChannelPins> {
pub dac_spi: C::DacSpi,
pub dac_sync: C::DacSync,
pub shdn: C::Shdn,
pub ref_adc: C::RefAdc,
pub ref_pin: C::RefPin,
}
pub struct Pins {
pub adc_spi: AdcSpi,
pub adc_nss: PB12<Output<PushPull>>,
pub adc_nss: AdcNss,
pub pwm: PwmPins,
pub dac0_spi: Dac0Spi,
pub dac0_sync: PE4<Output<PushPull>>,
pub shdn0: PE10<Output<PushPull>>,
pub ref0_adc: Adc<ADC1>,
pub ref0_pin: PA0<Analog>,
pub dac1_spi: Dac1Spi,
pub dac1_sync: PF6<Output<PushPull>>,
pub shdn1: PE15<Output<PushPull>>,
pub ref1_adc: Adc<ADC2>,
pub ref1_pin: PA3<Analog>,
pub channel0: ChannelPinSet<Channel0>,
pub channel1: ChannelPinSet<Channel1>,
}
impl Pins {
@ -83,6 +109,13 @@ impl Pins {
let mut ref0_adc = Adc::adc1(adc1, true, Default::default());
ref0_adc.enable();
let ref0_pin = gpioa.pa0.into_analog();
let channel0 = ChannelPinSet {
dac_spi: dac0_spi,
dac_sync: dac0_sync,
shdn: shdn0,
ref_adc: ref0_adc,
ref_pin: ref0_pin,
};
let (dac1_spi, dac1_sync) = Self::setup_dac1(
clocks, spi5,
@ -91,14 +124,21 @@ impl Pins {
let mut shdn1 = gpioe.pe15.into_push_pull_output();
let _ = shdn1.set_low();
let mut ref1_adc = Adc::adc2(adc2, true, Default::default());
let ref1_pin = gpioa.pa3.into_analog();
ref1_adc.enable();
let ref1_pin = gpioa.pa3.into_analog();
let channel1 = ChannelPinSet {
dac_spi: dac1_spi,
dac_sync: dac1_sync,
shdn: shdn1,
ref_adc: ref1_adc,
ref_pin: ref1_pin,
};
Pins {
adc_spi, adc_nss,
pwm,
dac0_spi, dac0_sync, shdn0, ref0_adc, ref0_pin,
dac1_spi, dac1_sync, shdn1, ref1_adc, ref1_pin,
channel0,
channel1,
}
}