use stm32f4xx_hal::{ adc::Adc, hal::{blocking::spi::Transfer, digital::v2::{InputPin, OutputPin}}, gpio::{ AF5, Alternate, Analog, gpioa::*, gpiob::*, gpioc::*, gpioe::*, gpiof::*, gpiog::*, GpioExt, Output, PushPull, Speed::VeryHigh, }, rcc::Clocks, pwm::{self, PwmChannels}, spi::{Spi, NoMiso}, stm32::{ADC1, ADC2, ADC3, GPIOA, GPIOB, GPIOC, GPIOE, GPIOF, GPIOG, SPI2, SPI4, SPI5, TIM1, TIM3}, time::U32Ext, }; use crate::channel::{Channel0, Channel1}; use crate::softspi::SoftSpi; pub struct DummyInputPin; impl InputPin for DummyInputPin { type Error = (); // `Void` fn is_high(&self) -> Result { Ok(false) } fn is_low(&self) -> Result { Ok(true) } } pub trait ChannelPins { type DacSpi: Transfer; type DacSync: OutputPin; type Shdn: OutputPin; type Adc; type VRefPin; type ItecPin; type DacFeedbackPin; type TecUMeasPin; } impl ChannelPins for Channel0 { type DacSpi = Dac0Spi; type DacSync = PE4>; type Shdn = PE10>; type Adc = Adc; type VRefPin = PA0; type ItecPin = PA6; type DacFeedbackPin = PA4; type TecUMeasPin = PC2; } impl ChannelPins for Channel1 { type DacSpi = Dac1Spi; type DacSync = PF6>; type Shdn = PE15>; type Adc = Adc; type VRefPin = PA3; type ItecPin = PB0; type DacFeedbackPin = PA5; type TecUMeasPin = PC3; } /// SPI peripheral used for communication with the ADC pub type AdcSpi = Spi>, PB14>, PB15>)>; pub type AdcNss = PB12>; type Dac0Spi = SoftSpi>, PE6>, DummyInputPin>; type Dac1Spi = SoftSpi>, PF9>, DummyInputPin>; pub type TecUMeasAdc = Adc; pub struct ChannelPinSet { pub dac_spi: C::DacSpi, pub dac_sync: C::DacSync, pub shdn: C::Shdn, pub adc: C::Adc, pub vref_pin: C::VRefPin, pub itec_pin: C::ItecPin, pub dac_feedback_pin: C::DacFeedbackPin, pub tec_u_meas_pin: C::TecUMeasPin, } pub struct Pins { pub adc_spi: AdcSpi, pub adc_nss: AdcNss, pub tec_u_meas_adc: TecUMeasAdc, pub pwm: PwmPins, pub channel0: ChannelPinSet, pub channel1: ChannelPinSet, } impl Pins { /// Setup GPIO pins and configure MCU peripherals pub fn setup( clocks: Clocks, tim1: TIM1, tim3: TIM3, gpioa: GPIOA, gpiob: GPIOB, gpioc: GPIOC, gpioe: GPIOE, gpiof: GPIOF, gpiog: GPIOG, spi2: SPI2, spi4: SPI4, spi5: SPI5, adc1: ADC1, adc2: ADC2, adc3: ADC3, ) -> Self { let gpioa = gpioa.split(); let gpiob = gpiob.split(); let gpioc = gpioc.split(); let gpioe = gpioe.split(); let gpiof = gpiof.split(); let gpiog = gpiog.split(); Self::setup_ethernet( gpioa.pa1, gpioa.pa2, gpioc.pc1, gpioa.pa7, gpioc.pc4, gpioc.pc5, gpiob.pb11, gpiog.pg13, gpiob.pb13 ); let adc_spi = Self::setup_spi_adc(clocks, spi2, gpiob.pb10, gpiob.pb14, gpiob.pb15); let adc_nss = gpiob.pb12.into_push_pull_output(); let tec_u_meas_adc = Adc::adc3(adc3, true, Default::default()); let pwm = PwmPins::setup( clocks, tim1, tim3, gpioc.pc6, gpioc.pc7, gpioe.pe9, gpioe.pe11, gpioe.pe13, gpioe.pe14 ); let (dac0_spi, dac0_sync) = Self::setup_dac0( clocks, spi4, gpioe.pe2, gpioe.pe4, gpioe.pe6 ); let mut shdn0 = gpioe.pe10.into_push_pull_output(); let _ = shdn0.set_low(); let mut adc0 = Adc::adc1(adc1, true, Default::default()); adc0.enable(); let vref0_pin = gpioa.pa0.into_analog(); let itec0_pin = gpioa.pa6.into_analog(); let dac_feedback0_pin = gpioa.pa4.into_analog(); let tec_u_meas0_pin = gpioc.pc2.into_analog(); let channel0 = ChannelPinSet { dac_spi: dac0_spi, dac_sync: dac0_sync, shdn: shdn0, adc: adc0, vref_pin: vref0_pin, itec_pin: itec0_pin, dac_feedback_pin: dac_feedback0_pin, tec_u_meas_pin: tec_u_meas0_pin, }; let (dac1_spi, dac1_sync) = Self::setup_dac1( clocks, spi5, gpiof.pf7, gpiof.pf6, gpiof.pf9 ); let mut shdn1 = gpioe.pe15.into_push_pull_output(); let _ = shdn1.set_low(); let mut adc1 = Adc::adc2(adc2, true, Default::default()); adc1.enable(); let vref1_pin = gpioa.pa3.into_analog(); let itec1_pin = gpiob.pb0.into_analog(); let dac_feedback1_pin = gpioa.pa5.into_analog(); let tec_u_meas1_pin = gpioc.pc3.into_analog(); let channel1 = ChannelPinSet { dac_spi: dac1_spi, dac_sync: dac1_sync, shdn: shdn1, adc: adc1, vref_pin: vref1_pin, itec_pin: itec1_pin, dac_feedback_pin: dac_feedback1_pin, tec_u_meas_pin: tec_u_meas1_pin, }; Pins { adc_spi, adc_nss, tec_u_meas_adc, pwm, channel0, channel1, } } /// Configure the GPIO pins for SPI operation, and initialize SPI fn setup_spi_adc( clocks: Clocks, spi2: SPI2, sck: PB10, miso: PB14, mosi: PB15, ) -> AdcSpi { let sck = sck.into_alternate_af5(); let miso = miso.into_alternate_af5(); let mosi = mosi.into_alternate_af5(); Spi::spi2( spi2, (sck, miso, mosi), crate::ad7172::SPI_MODE, crate::ad7172::SPI_CLOCK.into(), clocks ) } fn setup_dac0( clocks: Clocks, spi4: SPI4, sclk: PE2, sync: PE4, sdin: PE6 ) -> (Dac0Spi, PE4>) { let sclk = sclk.into_push_pull_output(); let sdin = sdin.into_push_pull_output(); let spi = SoftSpi::new( sclk, sdin, DummyInputPin, ); let sync = sync.into_push_pull_output(); (spi, sync) } fn setup_dac1( clocks: Clocks, spi5: SPI5, sclk: PF7, sync: PF6, sdin: PF9 ) -> (Dac1Spi, PF6>) { let sclk = sclk.into_push_pull_output(); let sdin = sdin.into_push_pull_output(); let spi = SoftSpi::new( sclk, sdin, DummyInputPin, ); let sync = sync.into_push_pull_output(); (spi, sync) } /// Configure the GPIO pins for Ethernet operation fn setup_ethernet( pa1: PA1, pa2: PA2, pc1: PC1, pa7: PA7, pc4: PC4, pc5: PC5, pb11: PB11, pg13: PG13, pb13: PB13 ) { // PA1 RMII Reference Clock - SB13 ON pa1.into_alternate_af11().set_speed(VeryHigh); // PA2 RMII MDIO - SB160 ON pa2.into_alternate_af11().set_speed(VeryHigh); // PC1 RMII MDC - SB164 ON pc1.into_alternate_af11().set_speed(VeryHigh); // PA7 RMII RX Data Valid D11 JP6 ON pa7.into_alternate_af11().set_speed(VeryHigh); // PC4 RMII RXD0 - SB178 ON pc4.into_alternate_af11().set_speed(VeryHigh); // PC5 RMII RXD1 - SB181 ON pc5.into_alternate_af11().set_speed(VeryHigh); // PB11 RMII TX Enable - SB183 ON pb11.into_alternate_af11().set_speed(VeryHigh); // PG13 RXII TXD0 - SB182 ON pg13.into_alternate_af11().set_speed(VeryHigh); // PB13 RMII TXD1 I2S_A_CK JP7 ON pb13.into_alternate_af11().set_speed(VeryHigh); } } pub struct PwmPins { pub max_v0: PwmChannels, pub max_v1: PwmChannels, pub max_i_pos0: PwmChannels, pub max_i_pos1: PwmChannels, pub max_i_neg0: PwmChannels, pub max_i_neg1: PwmChannels, } impl PwmPins { fn setup( clocks: Clocks, tim1: TIM1, tim3: TIM3, max_v0: PC6, max_v1: PC7, max_i_pos0: PE9, max_i_pos1: PE11, max_i_neg0: PE13, max_i_neg1: PE14, ) -> PwmPins { let freq = 20u32.khz(); let channels = ( max_v0.into_alternate_af2(), max_v1.into_alternate_af2(), ); let (max_v0, max_v1) = pwm::tim3(tim3, channels, clocks, freq); let channels = ( max_i_pos0.into_alternate_af1(), max_i_pos1.into_alternate_af1(), max_i_neg0.into_alternate_af1(), max_i_neg1.into_alternate_af1(), ); let (max_i_pos0, max_i_pos1, max_i_neg0, max_i_neg1) = pwm::tim1(tim1, channels, clocks, freq); PwmPins { max_v0, max_v1, max_i_pos0, max_i_pos1, max_i_neg0, max_i_neg1, } } }