From 29abca72cdcba437971d8a03e95258b6cd30e11d Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 24 Aug 2020 17:03:44 +0800 Subject: [PATCH] cpld: auto invoke io update --- src/lib.rs | 70 +++++++++++++++++++----- src/main.rs | 135 +++++++++++++++++++++++++++++++++++++++-------- src/spi_slave.rs | 49 +++++++++-------- 3 files changed, 195 insertions(+), 59 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 981ab51..01d9ae3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,20 +30,22 @@ pub enum Error { CSError, GetRefMutDataError, AttenuatorError, + IOUpdateError, } /* * Basic structure for CPLD signal multiplexing */ #[derive(Debug)] -pub struct CPLDData { +pub struct CPLDData { pub(crate) spi: SPI, pub(crate) chip_select: (CS0, CS1, CS2), + pub(crate) io_update: GPIO, } #[derive(Debug)] -pub struct CPLD { - pub(crate) data: cell::RefCell>, +pub struct CPLD { + pub(crate) data: cell::RefCell>, } pub trait SelectChip { @@ -51,12 +53,13 @@ pub trait SelectChip { fn select_chip(&mut self, chip: u8) -> Result<(), Self::Error>; } -impl SelectChip for CPLDData +impl SelectChip for CPLDData where SPI: Transfer, CS0: OutputPin, CS1: OutputPin, CS2: OutputPin, + GPIO: OutputPin, { type Error = Error; fn select_chip(&mut self, chip: u8) -> Result<(), Self::Error> { @@ -77,17 +80,38 @@ where } } -pub trait DoOnGetRefMutData { +trait IssueIOUpdate { + type Error; + fn issue_io_update(&mut self) -> Result<(), Self::Error>; +} + +impl IssueIOUpdate for CPLDData +where + SPI: Transfer, + CS0: OutputPin, + CS1: OutputPin, + CS2: OutputPin, + GPIO: OutputPin, +{ + type Error = Error; + + fn issue_io_update(&mut self) -> Result<(), Self::Error> { + self.io_update.set_high().map_err(|_| Error::IOUpdateError)?; + self.io_update.set_low().map_err(|_| Error::IOUpdateError) + } +} + +pub trait DoOnGetRefMutData { fn do_on_get_ref_mut_data( &self, - f: impl FnOnce(cell::RefMut>) -> Result>, + f: impl FnOnce(cell::RefMut>) -> Result>, ) -> Result>; } -impl DoOnGetRefMutData for CPLD { +impl DoOnGetRefMutData for CPLD { fn do_on_get_ref_mut_data( &self, - f: impl FnOnce(cell::RefMut>) -> Result>, + f: impl FnOnce(cell::RefMut>) -> Result>, ) -> Result> { let dev = self .data @@ -97,12 +121,13 @@ impl DoOnGetRefMutData for CPLD Transfer for CPLD +impl Transfer for CPLD where SPI: Transfer, CS0: OutputPin, CS1: OutputPin, CS2: OutputPin, + GPIO: OutputPin, { type Error = Error; @@ -111,19 +136,21 @@ where } } -impl CPLD where +impl CPLD where SPI: Transfer, CS0: OutputPin, CS1: OutputPin, CS2: OutputPin, + GPIO: OutputPin { // Constructor for CPLD - pub fn new(spi: SPI, chip_select: (CS0, CS1, CS2)) -> Self { + pub fn new(spi: SPI, chip_select: (CS0, CS1, CS2), io_update: GPIO) -> Self { // Init data let data = CPLDData { spi, chip_select, + io_update, }; // Init CPLD @@ -133,13 +160,13 @@ impl CPLD where } // Destroy the wrapper, return the CPLD data - pub fn destroy(self) -> (SPI, (CS0, CS1, CS2)) { + pub fn destroy(self) -> (SPI, (CS0, CS1, CS2), GPIO) { let cpld = self.data.into_inner(); - (cpld.spi, cpld.chip_select) + (cpld.spi, cpld.chip_select, cpld.io_update) } // Split SPI into chips, wrapped by Parts struct - pub fn split<'a>(&'a self) -> Parts<'a, CPLD, SPI, CS0, CS1, CS2> { + pub fn split<'a>(&'a self) -> Parts<'a, CPLD, SPI, CS0, CS1, CS2, GPIO> { Parts::new(&self) } @@ -148,3 +175,18 @@ impl CPLD where self.do_on_get_ref_mut_data(|mut dev| dev.select_chip(channel)) } } + +impl CPLD +where + SPI: Transfer, + CS0: OutputPin, + CS1: OutputPin, + CS2: OutputPin, + GPIO: OutputPin +{ + // Issue I/O Update + pub fn issue_io_update(&mut self) -> Result<(), Error> { + self.do_on_get_ref_mut_data(|mut dev| dev.issue_io_update()) + } +} + diff --git a/src/main.rs b/src/main.rs index 394eae1..3bde150 100644 --- a/src/main.rs +++ b/src/main.rs @@ -75,7 +75,7 @@ fn main() -> ! { let miso = gpioa.pa6.into_alternate_af5(); - let (mut cs0, mut cs1, mut cs2) = ( + let (cs0, cs1, cs2) = ( gpiob.pb12.into_push_pull_output(), gpioa.pa15.into_push_pull_output(), gpioc.pc7.into_push_pull_output(), @@ -84,37 +84,83 @@ fn main() -> ! { /* * I/O_Update -> PB13 */ + // TODO: Incoporate io_update into DDS let mut io_update = gpiob.pb15.into_push_pull_output(); - let mut spi = dp.SPI1.spi( + let spi = dp.SPI1.spi( (sclk, miso, mosi), spi::MODE_0, 3.mhz(), ccdr.peripheral.SPI1, &ccdr.clocks, ); - - // debug led - let mut yellow = gpioe.pe1.into_push_pull_output(); - yellow.set_high().unwrap(); -/* - let mut switch = CPLD::new(spi, (cs0, cs1, cs2)); + let mut switch = CPLD::new(spi, (cs0, cs1, cs2), io_update); let parts = switch.split(); let mut config = ConfigRegister::new(parts.spi1); let mut att = Attenuator::new(parts.spi2); let mut dds0 = DDS::new(parts.spi4); - loop { - let mut counter = config.get_status(StatusMask::RF_SW).unwrap(); - hprintln!("{}", counter); - config.set_configurations(&mut [ - (CFGMask::RF_SW, ((counter + 1)%16) as u32) - ]).unwrap(); - } -*/ + // Reset all DDS, set CLK_SEL to 0 + config.set_configurations(&mut [ + (CFGMask::RST, 1), + (CFGMask::IO_RST, 1), + (CFGMask::IO_UPDATE, 0) + ]).unwrap(); + config.set_configurations(&mut [ + (CFGMask::IO_RST, 0), + (CFGMask::RST, 0), + (CFGMask::RF_SW, 1) + ]).unwrap(); + + dds0.write_register(0x00, &mut[ + 0x00, 0x00, 0x00, 0x02 + ]).unwrap(); + +// io_update.set_high().unwrap(); +// io_update.set_low().unwrap(); +// switch.issue_io_update(); + + dds0.write_register(0x02, &mut[ + 0x01F, 0x3F, 0xC0, 0x00 + ]).unwrap(); + +// io_update.set_high().unwrap(); +// io_update.set_low().unwrap(); +// switch.issue_io_update(); + + hprintln!("{:#X?}", dds0.read_register(0x00, &mut[ + 0x00, 0x00, 0x00, 0x00 + ]).unwrap()).unwrap(); + + // Calculate FTW + let f_out = 10_000_000; + let f_sclk = 100_000_000; + let resolution :u64 = 1 << 32; + let ftw = (resolution * f_out / f_sclk) as u32; + + hprintln!("{}", ftw); + + // Read single-tone profile 0 + let mut profile :[u8; 8] = [0; 8]; + dds0.read_register(0x0E, &mut profile).unwrap(); + + // Overwrite FTW on profile + profile[4] = ((ftw >> 24) & 0xFF) as u8; + profile[5] = ((ftw >> 16) & 0xFF) as u8; + profile[6] = ((ftw >> 8 ) & 0xFF) as u8; + profile[7] = ((ftw >> 0 ) & 0xFF) as u8; + + dds0.write_register(0x0E, &mut profile).unwrap(); +// io_update.set_high().unwrap(); +// io_update.set_low().unwrap(); +// switch.issue_io_update(); + + hprintln!("{:#X?}", dds0.read_register(0x0E, &mut profile).unwrap()).unwrap(); + +/* cs0.set_low().unwrap(); cs1.set_low().unwrap(); cs2.set_low().unwrap(); @@ -139,29 +185,72 @@ fn main() -> ! { cs0.set_low().unwrap(); // Release reset, control I/O Update through EEM + // Relay clock signal from internal OSC (CLK_SEL = 0) + // Enable Switch 0 cs0.set_high().unwrap(); spi.transfer(&mut [ - 0x00, 0x00, 0x0A + 0x00, 0x00, 0x01 ]).unwrap(); cs0.set_low().unwrap(); cs0.set_low().unwrap(); cs1.set_low().unwrap(); cs2.set_high().unwrap(); - - hprintln!("{:?}", spi.transfer(&mut [ + + // Configure SDIO to be input only, enable 3-wires communication + spi.transfer(&mut [ 0x00, 0x00, 0x00, 0x00, 0x02 - ]).unwrap()).unwrap(); + ]).unwrap(); + + // IO Update after every SPI transfer + io_update.set_high().unwrap(); + delay.delay_ms(1_u16); + io_update.set_low().unwrap(); + + // Bypass PLL, bypass divisor + spi.transfer(&mut [ + 0x02, 0x1F, 0x3F, 0xC0, 0x00 + ]).unwrap(); io_update.set_high().unwrap(); delay.delay_ms(1_u16); io_update.set_low().unwrap(); - hprintln!("{:?}", spi.transfer(&mut [ - 0x80, 0x00, 0x00, 0x00, 0x00 + hprintln!("{:#X?}", spi.transfer(&mut [ + 0x82, 0x00, 0x00, 0x00, 0x00 ]).unwrap()).unwrap(); - + let f_out = 10_000_000.0; + let f_sclk = 100_000_000.0; + let resolution :u64 = 1 << 32; + let ftw = ((resolution as f32) * f_out / f_sclk) as u32; + hprintln!("{:#X}", ftw); + + // Read profile 0 + let mut profile_arr_0 :[u8; 9] = [0; 9]; + profile_arr_0[0] = 0x8E; + hprintln!("{:#X?}", spi.transfer(&mut profile_arr_0).unwrap()).unwrap(); + + // Write FTW to profile 0 + profile_arr_0[0] = 0x0E; + profile_arr_0[5] = ((ftw >> 24) & 0xFF) as u8; + profile_arr_0[6] = ((ftw >> 16) & 0xFF) as u8; + profile_arr_0[7] = ((ftw >> 8 ) & 0xFF) as u8; + profile_arr_0[8] = ((ftw >> 0 ) & 0xFF) as u8; + + hprintln!("{:#X?}", profile_arr_0).unwrap(); + spi.transfer(&mut profile_arr_0).unwrap(); + + // Update after write + io_update.set_high().unwrap(); + delay.delay_ms(1_u16); + io_update.set_low().unwrap(); + + // Read profile again, new value should be present + profile_arr_0[0] = 0x8E; + hprintln!("{:#X?}", spi.transfer(&mut profile_arr_0).unwrap()).unwrap(); +*/ + loop {} } diff --git a/src/spi_slave.rs b/src/spi_slave.rs index 159e460..ded1c3c 100644 --- a/src/spi_slave.rs +++ b/src/spi_slave.rs @@ -4,45 +4,47 @@ use embedded_hal::{ }; use core::marker::PhantomData; -use crate::{DoOnGetRefMutData, Error, SelectChip}; +use crate::{DoOnGetRefMutData, Error, SelectChip, IssueIOUpdate}; -pub struct SPISlave<'a, DEV: 'a, SPI, CS0, CS1, CS2> ( +pub struct SPISlave<'a, DEV: 'a, SPI, CS0, CS1, CS2, GPIO> ( &'a DEV, - u8, - PhantomData<(SPI, CS0, CS1, CS2)>, + u8, // Channel of SPI slave + bool, // Need I/O Update + PhantomData<(SPI, CS0, CS1, CS2, GPIO)>, ); -pub struct Parts<'a, DEV: 'a, SPI, CS0, CS1, CS2> { - pub spi1: SPISlave<'a, DEV, SPI, CS0, CS1, CS2>, - pub spi2: SPISlave<'a, DEV, SPI, CS0, CS1, CS2>, - pub spi3: SPISlave<'a, DEV, SPI, CS0, CS1, CS2>, - pub spi4: SPISlave<'a, DEV, SPI, CS0, CS1, CS2>, - pub spi5: SPISlave<'a, DEV, SPI, CS0, CS1, CS2>, - pub spi6: SPISlave<'a, DEV, SPI, CS0, CS1, CS2>, - pub spi7: SPISlave<'a, DEV, SPI, CS0, CS1, CS2>, +pub struct Parts<'a, DEV: 'a, SPI, CS0, CS1, CS2, GPIO> { + pub spi1: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>, + pub spi2: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>, + pub spi3: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>, + pub spi4: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>, + pub spi5: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>, + pub spi6: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>, + pub spi7: SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO>, } -impl<'a, DEV, SPI, CS0, CS1, CS2> Parts<'a, DEV, SPI, CS0, CS1, CS2> { +impl<'a, DEV, SPI, CS0, CS1, CS2, GPIO> Parts<'a, DEV, SPI, CS0, CS1, CS2, GPIO> { pub(crate) fn new(cpld: &'a DEV) -> Self { Parts { - spi1: SPISlave(&cpld, 1, PhantomData), - spi2: SPISlave(&cpld, 2, PhantomData), - spi3: SPISlave(&cpld, 3, PhantomData), - spi4: SPISlave(&cpld, 4, PhantomData), - spi5: SPISlave(&cpld, 5, PhantomData), - spi6: SPISlave(&cpld, 6, PhantomData), - spi7: SPISlave(&cpld, 7, PhantomData), + spi1: SPISlave(&cpld, 1, false, PhantomData), + spi2: SPISlave(&cpld, 2, false, PhantomData), + spi3: SPISlave(&cpld, 3, true, PhantomData), + spi4: SPISlave(&cpld, 4, true, PhantomData), + spi5: SPISlave(&cpld, 5, true, PhantomData), + spi6: SPISlave(&cpld, 6, true, PhantomData), + spi7: SPISlave(&cpld, 7, true, PhantomData), } } } -impl<'a, DEV, SPI, CS0, CS1, CS2, E> Transfer for SPISlave<'a, DEV, SPI, CS0, CS1, CS2> +impl<'a, DEV, SPI, CS0, CS1, CS2, GPIO, E> Transfer for SPISlave<'a, DEV, SPI, CS0, CS1, CS2, GPIO> where CS2: OutputPin, CS1: OutputPin, CS0: OutputPin, - DEV: DoOnGetRefMutData, + DEV: DoOnGetRefMutData, SPI: Transfer, + GPIO: OutputPin, { type Error = Error; @@ -51,6 +53,9 @@ where dev.select_chip(self.1); let result = dev.spi.transfer(words).map_err(Error::SPI); dev.select_chip(0); + if self.2 { + dev.issue_io_update(); + } result }) }