forked from M-Labs/thermostat
main: refactor into Channel/Channels
This commit is contained in:
parent
6dd6bb2e1e
commit
9466961bd7
34
src/channel.rs
Normal file
34
src/channel.rs
Normal 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
30
src/channels.rs
Normal 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 }
|
||||||
|
}
|
||||||
|
}
|
81
src/main.rs
81
src/main.rs
@ -45,6 +45,9 @@ use command_parser::{Command, ShowCommand, PwmPin};
|
|||||||
mod timer;
|
mod timer;
|
||||||
mod pid;
|
mod pid;
|
||||||
mod steinhart_hart;
|
mod steinhart_hart;
|
||||||
|
mod channels;
|
||||||
|
use channels::Channels;
|
||||||
|
mod channel;
|
||||||
mod channel_state;
|
mod channel_state;
|
||||||
use channel_state::ChannelState;
|
use channel_state::ChannelState;
|
||||||
|
|
||||||
@ -92,24 +95,10 @@ fn main() -> ! {
|
|||||||
dp.SPI2, dp.SPI4, dp.SPI5,
|
dp.SPI2, dp.SPI4, dp.SPI5,
|
||||||
dp.ADC1, dp.ADC2,
|
dp.ADC1, dp.ADC2,
|
||||||
);
|
);
|
||||||
|
let mut channels = Channels::new(pins);
|
||||||
let mut adc = ad7172::Adc::new(pins.adc_spi, pins.adc_nss).unwrap();
|
let mut channel_states: [ChannelState; CHANNELS] = [
|
||||||
// Feature not used
|
ChannelState::default(), ChannelState::default()
|
||||||
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;
|
|
||||||
|
|
||||||
timer::setup(cp.SYST, clocks);
|
timer::setup(cp.SYST, clocks);
|
||||||
|
|
||||||
#[cfg(not(feature = "generate-hwaddr"))]
|
#[cfg(not(feature = "generate-hwaddr"))]
|
||||||
@ -121,17 +110,13 @@ fn main() -> ! {
|
|||||||
};
|
};
|
||||||
info!("Net hwaddr: {}", hwaddr);
|
info!("Net hwaddr: {}", hwaddr);
|
||||||
|
|
||||||
let mut channel_states: [ChannelState; CHANNELS] = [
|
|
||||||
ChannelState::default(), ChannelState::default()
|
|
||||||
];
|
|
||||||
|
|
||||||
net::run(dp.ETHERNET_MAC, dp.ETHERNET_DMA, hwaddr, |iface| {
|
net::run(dp.ETHERNET_MAC, dp.ETHERNET_DMA, hwaddr, |iface| {
|
||||||
Server::<Session>::run(iface, |server| {
|
Server::<Session>::run(iface, |server| {
|
||||||
loop {
|
loop {
|
||||||
let instant = Instant::from_millis(i64::from(timer::now()));
|
let instant = Instant::from_millis(i64::from(timer::now()));
|
||||||
// ADC input
|
// ADC input
|
||||||
adc.data_ready().unwrap().map(|channel| {
|
channels.adc.data_ready().unwrap().map(|channel| {
|
||||||
let data = adc.read_data().unwrap();
|
let data = channels.adc.read_data().unwrap();
|
||||||
|
|
||||||
let state = &mut channel_states[usize::from(channel)];
|
let state = &mut channel_states[usize::from(channel)];
|
||||||
state.update_adc(instant, data);
|
state.update_adc(instant, data);
|
||||||
@ -140,12 +125,12 @@ fn main() -> ! {
|
|||||||
// Forward PID output to i_set DAC
|
// Forward PID output to i_set DAC
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
dac0.set(state.dac_value).unwrap();
|
channels.channel0.dac.set(state.dac_value).unwrap();
|
||||||
shdn0.set_high().unwrap();
|
channels.channel0.shdn.set_high().unwrap();
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
dac1.set(state.dac_value).unwrap();
|
channels.channel1.dac.set(state.dac_value).unwrap();
|
||||||
shdn1.set_high().unwrap();
|
channels.channel1.shdn.set_high().unwrap();
|
||||||
}
|
}
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!(),
|
unreachable!(),
|
||||||
@ -189,8 +174,8 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ref0 = pins.ref0_adc.convert(
|
let ref0 = channels.channel0.ref_adc.convert(
|
||||||
&pins.ref0_pin, stm32f4xx_hal::adc::config::SampleTime::Cycles_480
|
&channels.channel0.ref_pin, stm32f4xx_hal::adc::config::SampleTime::Cycles_480
|
||||||
);
|
);
|
||||||
let _ = writeln!(socket, "ref0={}", ref0);
|
let _ = writeln!(socket, "ref0={}", ref0);
|
||||||
}
|
}
|
||||||
@ -241,14 +226,14 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
show_pwm_channel(socket.deref_mut(), "max_v", &pwm.max_v0);
|
show_pwm_channel(socket.deref_mut(), "max_v", &channels.pwm.max_v0);
|
||||||
show_pwm_channel(socket.deref_mut(), "max_i_pos", &pwm.max_i_pos0);
|
show_pwm_channel(socket.deref_mut(), "max_i_pos", &channels.pwm.max_i_pos0);
|
||||||
show_pwm_channel(socket.deref_mut(), "max_i_neg", &pwm.max_i_neg0);
|
show_pwm_channel(socket.deref_mut(), "max_i_neg", &channels.pwm.max_i_neg0);
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
show_pwm_channel(socket.deref_mut(), "max_v", &pwm.max_v1);
|
show_pwm_channel(socket.deref_mut(), "max_v", &channels.pwm.max_v1);
|
||||||
show_pwm_channel(socket.deref_mut(), "max_i_pos", &pwm.max_i_pos1);
|
show_pwm_channel(socket.deref_mut(), "max_i_pos", &channels.pwm.max_i_pos1);
|
||||||
show_pwm_channel(socket.deref_mut(), "max_i_neg", &pwm.max_i_neg1);
|
show_pwm_channel(socket.deref_mut(), "max_i_neg", &channels.pwm.max_i_neg1);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
@ -269,7 +254,7 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
Command::Show(ShowCommand::PostFilter) => {
|
Command::Show(ShowCommand::PostFilter) => {
|
||||||
for (channel, _) in channel_states.iter().enumerate() {
|
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) => {
|
Some(filter) => {
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
socket, "channel {}: postfilter={:.2} SPS",
|
socket, "channel {}: postfilter={:.2} SPS",
|
||||||
@ -294,12 +279,12 @@ fn main() -> ! {
|
|||||||
channel_states[channel].pid_enabled = false;
|
channel_states[channel].pid_enabled = false;
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
dac0.set(duty).unwrap();
|
channels.channel0.dac.set(duty).unwrap();
|
||||||
shdn0.set_high().unwrap();
|
channels.channel0.shdn.set_high().unwrap();
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
dac1.set(duty).unwrap();
|
channels.channel1.dac.set(duty).unwrap();
|
||||||
shdn1.set_high().unwrap();
|
channels.channel1.shdn.set_high().unwrap();
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
@ -327,17 +312,17 @@ fn main() -> ! {
|
|||||||
// Handled above
|
// Handled above
|
||||||
unreachable!(),
|
unreachable!(),
|
||||||
(0, PwmPin::MaxIPos) =>
|
(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) =>
|
(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) =>
|
(0, PwmPin::MaxV) =>
|
||||||
set_pwm_channel(&mut pwm.max_v0, duty),
|
set_pwm_channel(&mut channels.pwm.max_v0, duty),
|
||||||
(1, PwmPin::MaxIPos) =>
|
(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) =>
|
(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) =>
|
(1, PwmPin::MaxV) =>
|
||||||
set_pwm_channel(&mut pwm.max_v1, duty),
|
set_pwm_channel(&mut channels.pwm.max_v1, duty),
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!(),
|
unreachable!(),
|
||||||
};
|
};
|
||||||
@ -389,7 +374,7 @@ fn main() -> ! {
|
|||||||
let filter = ad7172::PostFilter::closest(rate);
|
let filter = ad7172::PostFilter::closest(rate);
|
||||||
match filter {
|
match filter {
|
||||||
Some(filter) => {
|
Some(filter) => {
|
||||||
adc.set_postfilter(channel as u8, Some(filter)).unwrap();
|
channels.adc.set_postfilter(channel as u8, Some(filter)).unwrap();
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
socket, "channel {}: postfilter set to {:.2} SPS",
|
socket, "channel {}: postfilter set to {:.2} SPS",
|
||||||
channel, filter.output_rate().unwrap()
|
channel, filter.output_rate().unwrap()
|
||||||
|
72
src/pins.rs
72
src/pins.rs
@ -1,6 +1,6 @@
|
|||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
adc::Adc,
|
adc::Adc,
|
||||||
hal::digital::v2::OutputPin,
|
hal::{blocking::spi::Transfer, digital::v2::OutputPin},
|
||||||
gpio::{
|
gpio::{
|
||||||
AF5, Alternate, Analog,
|
AF5, Alternate, Analog,
|
||||||
gpioa::*,
|
gpioa::*,
|
||||||
@ -22,25 +22,51 @@ use stm32f4xx_hal::{
|
|||||||
use crate::channel::{Channel0, Channel1};
|
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
|
/// 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 Dac0Spi = Spi<SPI4, (PE2<Alternate<AF5>>, NoMiso, PE6<Alternate<AF5>>)>;
|
||||||
type Dac1Spi = Spi<SPI5, (PF7<Alternate<AF5>>, NoMiso, PF9<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 struct Pins {
|
||||||
pub adc_spi: AdcSpi,
|
pub adc_spi: AdcSpi,
|
||||||
pub adc_nss: PB12<Output<PushPull>>,
|
pub adc_nss: AdcNss,
|
||||||
pub pwm: PwmPins,
|
pub pwm: PwmPins,
|
||||||
pub dac0_spi: Dac0Spi,
|
pub channel0: ChannelPinSet<Channel0>,
|
||||||
pub dac0_sync: PE4<Output<PushPull>>,
|
pub channel1: ChannelPinSet<Channel1>,
|
||||||
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>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pins {
|
impl Pins {
|
||||||
@ -83,6 +109,13 @@ impl Pins {
|
|||||||
let mut ref0_adc = Adc::adc1(adc1, true, Default::default());
|
let mut ref0_adc = Adc::adc1(adc1, true, Default::default());
|
||||||
ref0_adc.enable();
|
ref0_adc.enable();
|
||||||
let ref0_pin = gpioa.pa0.into_analog();
|
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(
|
let (dac1_spi, dac1_sync) = Self::setup_dac1(
|
||||||
clocks, spi5,
|
clocks, spi5,
|
||||||
@ -91,14 +124,21 @@ impl Pins {
|
|||||||
let mut shdn1 = gpioe.pe15.into_push_pull_output();
|
let mut shdn1 = gpioe.pe15.into_push_pull_output();
|
||||||
let _ = shdn1.set_low();
|
let _ = shdn1.set_low();
|
||||||
let mut ref1_adc = Adc::adc2(adc2, true, Default::default());
|
let mut ref1_adc = Adc::adc2(adc2, true, Default::default());
|
||||||
let ref1_pin = gpioa.pa3.into_analog();
|
|
||||||
ref1_adc.enable();
|
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 {
|
Pins {
|
||||||
adc_spi, adc_nss,
|
adc_spi, adc_nss,
|
||||||
pwm,
|
pwm,
|
||||||
dac0_spi, dac0_sync, shdn0, ref0_adc, ref0_pin,
|
channel0,
|
||||||
dac1_spi, dac1_sync, shdn1, ref1_adc, ref1_pin,
|
channel1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user