adf4351 0.1.0

Analog Devices ADF4351 HAL driver
Documentation
#![deny(unsafe_code)]
#![no_main]
#![no_std]

extern crate panic_halt; // panic handler

use cortex_m;
use cortex_m_rt::entry;
use stm32f4xx_hal as hal;

use cortex_m_semihosting::hprintln;

use crate::hal::{
    prelude::*,
    stm32,
    spi::Spi,
};

use embedded_hal::spi::MODE_0;

use adf4351::{ device::*, register::*, config::*, constants::*, };

/// Example board config / test frequency generator.
/// Example boards:
/// [STM32F407VET6](https://www.amazon.com/HiLetgo-STM32F407VET6-Cortex-M4-Development-NRF2410/dp/B071KBZR58/ref=sxts_sxwds-bia-wc-drs-ajax1_0?cv_ct_cx=stm32f4&dchild=1&keywords=stm32f4&pd_rd_i=B071KBZR58&pd_rd_r=55e7d3f3-cdc8-4579-86db-7ca754be35b7&pd_rd_w=A8TgI&pd_rd_wg=J3B78&pf_rd_p=037ca9fd-790e-4a16-836b-14da89aed20e&pf_rd_r=1R23WCQBWJCYQN1MXC0G&psc=1&qid=1601162000&sr=1-1-25b07e09-600a-4f0d-816e-b06387f8bcf1)
/// [ADF4351](https://www.amazon.com/35M-4-4GHz-Frequency-Synthesizer-Development-Generator/dp/B078NRD8V6/ref=sr_1_3?dchild=1&keywords=adf4351&qid=1601162186&sr=8-3)
#[entry]
fn main() -> ! {
    let dp = stm32::Peripherals::take().unwrap();
    let cp = cortex_m::peripheral::Peripherals::take().unwrap();

    let rcc = dp.RCC.constrain();
    let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(168.mhz()).pclk1(42.mhz()).pclk2(84.mhz()).freeze();

    let gpioa = dp.GPIOA.split();
    let mut led1 = gpioa.pa6.into_push_pull_output();

    let mut delay = hal::delay::Delay::new(cp.SYST, clocks);

    let gpiob = dp.GPIOB.split();
    let pin_ce = gpiob.pb10.into_push_pull_output();
    let pin_le = gpiob.pb11.into_push_pull_output();

    let sck = gpiob.pb13.into_alternate_af5();
    let mosi = gpiob.pb15.into_alternate_af5();

    let spi = Spi::spi2(
        dp.SPI2,
        (sck, hal::spi::NoMiso , mosi),
        MODE_0,
        stm32f4xx_hal::time::KiloHertz(100).into(),
        clocks,
    );

    let mut sg = Adf4351::new(spi, pin_ce, pin_le);
    sg.enable().unwrap();
    let xtal = 25_000_000;

    let rs = RegisterSet::default()
        // Double buffer register writes
        .set(DoubleBuffer::Enabled)

        // FRAC-N modulus
        .set(Mod(4000))

        // Board config
        .set(ChargePumpCurrent(0b111))
        .set(PhaseDetectorPolarity::Positive)

        // Keep xtal input, clean up duty cycle
        .set(R(1))
        .set(RefDoubler::Enabled)
        .set(Rdiv2::Enabled)

        // Pin config
        .set(LockDetectPin::DigitalLockDetect)

        // RF out
        .set(BandSelectClockDiv(200))
        .set(AuxOutputEnable::Enabled)
        .set(AuxOutputPower(2))
        .set(RfOutputEnable::Enabled)
        .set(OutputPower(2))
        ;

    let f_out = 63_000_000;
    let rs = FracN::init(rs); // init FracN mode, one time settings
    let fracn = FracN(Fpfd::new(xtal, &rs).unwrap()); // init with cuffent PFD config
    let rs = fracn.set_f_out(f_out, rs).unwrap(); // set output frequency

    sg.write_register_set(&mut delay, &rs).unwrap();

    let rs_words = rs.to_words();
    for (i,w) in rs_words.iter().enumerate() {
        hprintln!("RS[{}] {:#010x} {:#034b}", i, w, w).unwrap();
    };

    let int : Int = rs.get();
    let frac : Frac = rs.get();
    let modulus : Mod = rs.get();
    let rfdiv : RfDividerSelect = rs.get();
    hprintln!("{:?} {:?} {:?} {:?}", int, frac, modulus, rfdiv).unwrap();
    hprintln!("{:?} => f set {:?} <-> f actual {:?}", fracn.0, f_out, FracN::f_out_hz(xtal, &rs)).unwrap();

    delay.delay_ms(10000_u32);

    // Try different frequencies
    let mut step = OUT_FREQ_MAX - OUT_FREQ_MIN;
    while step > 0 {
        step = step/2;

        for f_out in (OUT_FREQ_MIN .. OUT_FREQ_MAX+1).step_by(step as usize) {
            let rs = fracn.set_f_out(f_out, rs).unwrap(); // set output frequency
            sg.write_register_set(&mut delay, &rs).unwrap();
            hprintln!("[{:012}] {:?} => f set {:012} <-> f actual {:012}", step, fracn.0, f_out, FracN::f_out_hz(xtal, &rs).unwrap()).unwrap();
            delay.delay_ms(1000_u32);
        }
    }

    loop {
        led1.set_high().unwrap();
        delay.delay_ms(1000_u32);
        led1.set_low().unwrap();
        delay.delay_ms(1000_u32);
    }
}