humpback-dds/src/main.rs

200 lines
4.4 KiB
Rust

#![no_main]
#![no_std]
use panic_semihosting as _;
use stm32h7xx_hal::hal::digital::v2::{
InputPin,
OutputPin,
};
use stm32h7xx_hal::{pac, prelude::*, spi};
use cortex_m;
use cortex_m::asm::nop;
use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;
use core::ptr;
use nb::block;
use firmware;
use firmware::{
CPLD,
attenuator::Attenuator,
config_register::{
ConfigRegister,
CFGMask,
StatusMask,
},
dds::{
DDS,
DDSCFRMask,
},
};
#[entry]
fn main() -> ! {
let cp = cortex_m::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
let pwr = dp.PWR.constrain();
let vos = pwr.freeze();
let rcc = dp.RCC.constrain();
let ccdr = rcc
.sys_ck(400.mhz())
.pll1_q_ck(48.mhz())
.freeze(vos, &dp.SYSCFG);
let mut delay = cp.SYST.delay(ccdr.clocks);
let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA);
let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);
let gpioc = dp.GPIOC.split(ccdr.peripheral.GPIOC);
let gpiod = dp.GPIOD.split(ccdr.peripheral.GPIOD);
let gpioe = dp.GPIOE.split(ccdr.peripheral.GPIOE);
let gpiof = dp.GPIOF.split(ccdr.peripheral.GPIOF);
// Setup CDONE for checking
let fpga_cdone = gpiod.pd15.into_pull_up_input();
match fpga_cdone.is_high() {
Ok(true) => hprintln!("FPGA is ready."),
Ok(_) => hprintln!("FPGA is in reset state."),
Err(_) => hprintln!("Error: Cannot read C_DONE"),
}.unwrap();
/*
* Using SPI1, AF5
* SCLK -> PA5
* MOSI -> PB5
* MISO -> PA6
* CS -> 0: PB12, 1: PA15, 2: PC7
*/
let sclk = gpioa.pa5.into_alternate_af5();
let mosi = gpiob.pb5.into_alternate_af5();
let miso = gpioa.pa6.into_alternate_af5();
let (cs0, cs1, cs2) = (
gpiob.pb12.into_push_pull_output(),
gpioa.pa15.into_push_pull_output(),
gpioc.pc7.into_push_pull_output(),
);
/*
* I/O_Update -> PB13
*/
let io_update = gpiob.pb15.into_push_pull_output();
let spi = dp.SPI1.spi(
(sclk, miso, mosi),
spi::MODE_0,
3.mhz(),
ccdr.peripheral.SPI1,
&ccdr.clocks,
);
let 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);
// 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, 13),
(CFGMask::DIV, 2)
]).unwrap();
// dds0.write_register(0x00, &mut[
// 0x00, 0x00, 0x00, 0x02
// ]).unwrap();
// dds0.write_register(0x01, &mut[
// 0x01, 0x01, 0x00, 0x20
// ]).unwrap();
// dds0.write_register(0x02, &mut[
// 0x05, 0x38, 0xC5, 0x28
// ]).unwrap();
dds0.init().unwrap();
dds0.set_configurations(&mut [
(DDSCFRMask::PDCLK_ENABLE, 0),
(DDSCFRMask::READ_EFFECTIVE_FTW, 1),
(DDSCFRMask::DIGITAL_RAMP_ENABLE, 0),
(DDSCFRMask::EN_AMP_SCALE_SINGLE_TONE_PRO, 1),
(DDSCFRMask::N, 0x14),
(DDSCFRMask::PLL_ENABLE, 1),
(DDSCFRMask::PFD_RESET, 1),
(DDSCFRMask::REFCLK_IN_DIV_BYPASS, 1),
(DDSCFRMask::I_CP, 7),
(DDSCFRMask::VCO_SEL, 5),
(DDSCFRMask::DRV0, 0),
]).unwrap();
hprintln!("{:#X?}", dds0.read_register(0x02, &mut[
0x00, 0x00, 0x00, 0x00
]).unwrap()).unwrap();
dds0.set_configurations(&mut [
(DDSCFRMask::PFD_RESET, 0),
]).unwrap();
hprintln!("{:#X?}", dds0.read_register(0x02, &mut[
0x00, 0x00, 0x00, 0x00
]).unwrap()).unwrap();
// Calculate FTW
let f_out = 8_008_135;
let f_sclk = 100_000_000 / 2 * 20;
let resolution :u64 = 1 << 32;
let ftw = (resolution * f_out / f_sclk) as u32;
// Read single-tone profile 0
let mut profile :[u8; 8] = [0; 8];
dds0.read_register(0x0E, &mut profile).unwrap();
// Overwrite FTW on profile 0
profile[0] = 0x1F;
profile[1] = 0xFF;
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();
// Attenuator
att.set_attenuation([
0.0, 31.5, 24.0, 0.0
]).unwrap();
hprintln!("{:#X?}", dds0.get_configurations(&mut
[
(DDSCFRMask::SDIO_IN_ONLY, 0),
(DDSCFRMask::LSB_FIRST, 0),
(DDSCFRMask::PROFILE_CTRL, 0),
(DDSCFRMask::EN_AMP_SCALE_SINGLE_TONE_PRO, 0),
(DDSCFRMask::DRV0, 0),
(DDSCFRMask::VCO_SEL, 0)
]
).unwrap()).unwrap();
loop {}
}