From fac4d24ade988fc03dc731b659f8a54a7f45f7aa Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 23 Oct 2019 23:51:35 +0800 Subject: [PATCH] wavemeter: config, displacement calibration --- Cargo.lock | 7 +++ Cargo.toml | 1 + src/wavemeter.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++++- wavemeter.json | 17 ++++++++ 4 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 wavemeter.json diff --git a/Cargo.lock b/Cargo.lock index a353d53..e39e191 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,10 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "argparse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "autocfg" version = "0.1.6" @@ -14,6 +19,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "noptica-rs" version = "0.1.0" dependencies = [ + "argparse 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", @@ -90,6 +96,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] +"checksum argparse 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3f8ebf5827e4ac4fd5946560e6a99776ea73b596d80898f357007317a7141e47" "checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" diff --git a/Cargo.toml b/Cargo.toml index fef497b..072e2df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,4 @@ num-traits = "0.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" +argparse = "0.2.2" diff --git a/src/wavemeter.rs b/src/wavemeter.rs index ad379d6..f1382f1 100644 --- a/src/wavemeter.rs +++ b/src/wavemeter.rs @@ -1,3 +1,109 @@ -fn main() { - println!("hello world"); +extern crate argparse; +extern crate num_traits; +extern crate serde_derive; +extern crate serde_json; + +use argparse::{ArgumentParser, StoreTrue, Store}; + +use serde_derive::Deserialize; + +use std::error::Error; +use std::fs::File; +use std::io::BufReader; +use std::path::Path; + +mod noptica; + +#[derive(Deserialize, Debug)] +struct Config { + sample_command: String, // Shell command to start the logic analyzer. + sample_rate: f64, // Sample rate of the logic analyzer in Hz. + + // The logic analyzer command must produce a stream of 4-bit nibbles on its + // standard output, which are continuously sampled at the nominal sample rate. + // Each of the signals below are mapped to one bit within each nibble. + bit_ref: u8, // Bit# for REF signal of the reference laser head (HP 5501B). + bit_meas: u8, // Bit# for displacement measurement detector (HP 10780). + bit_input: u8, // Bit# for input laser interference detector. + + // The REF DPLL locks to the REF output of the reference laser and provides REF phase + // information at each sample of the logic analyzer. + // ref_min and ref_max are used to initialize the DPLL and clamp its NCO frequency. + ref_min: f64, // Minimum REF frequency in Hz. + ref_max: f64, // Maximum REF frequency in Hz. + refpll_ki: i64, // Integration constant of the DPLL loop filter. + refpll_kp: i64, // Proportionality constant of the DPLL loop filter. + + ref_wavelength: f64, // Wavelength of the reference laser in m. + scan_displacement: f64, // Optical path difference across one scan cycle in m (use -c). + scan_frequency: f64, // Frequency of the scan in Hz. + scan_blanking: f64, // Fraction of the scan period that is blanked at the beginning + // and end of each slope (4 times per scan period). +} + +fn read_config_from_file>(path: P) -> Result> { + let file = File::open(path)?; + let reader = BufReader::new(file); + let u = serde_json::from_reader(reader)?; + Ok(u) +} + +fn do_calibrate(config: &Config) { + let mut sample_count = 0; + let max_sample_count = (config.sample_rate/4.0) as u32; + let mut position_min = i64::max_value(); + let mut position_max = i64::min_value(); + + let mut refpll = noptica::Dpll::new( + noptica::Dpll::frequency_to_ftw(config.ref_min, config.sample_rate), + noptica::Dpll::frequency_to_ftw(config.ref_max, config.sample_rate), + config.refpll_ki, + config.refpll_kp); + let mut position_tracker = noptica::PositionTracker::new(); + + noptica::sample(&config.sample_command, |rising, _falling| { + refpll.tick(rising & (1 << config.bit_ref) != 0); + if rising & (1 << config.bit_meas) != 0 { + let position = position_tracker.edge(refpll.get_phase_unwrapped()); + if position > position_max { + position_max = position; + } + if position < position_min { + position_min = position; + } + } + + sample_count += 1; + if sample_count == max_sample_count { + println!("{}", ((position_max-position_min) as f64)/(noptica::Dpll::TURN as f64)*config.ref_wavelength); + sample_count = 0; + position_min = i64::max_value(); + position_max = i64::min_value(); + } + }) +} + +fn do_wavemeter(config: &Config) { + println!("TODO {}", config.sample_command); +} + +fn main() { + let mut calibrate = false; + let mut config_file = "wavemeter.json".to_string(); + { + let mut ap = ArgumentParser::new(); + ap.refer(&mut calibrate) + .add_option(&["-c", "--calibrate"], StoreTrue, + "Calibrate scan displacement"); + ap.refer(&mut config_file) + .add_option(&["--config"], Store, + "Configuration file"); + ap.parse_args_or_exit(); + } + let config = read_config_from_file(config_file).unwrap(); + if calibrate { + do_calibrate(&config); + } else { + do_wavemeter(&config); + } } diff --git a/wavemeter.json b/wavemeter.json new file mode 100644 index 0000000..fcd4eb3 --- /dev/null +++ b/wavemeter.json @@ -0,0 +1,17 @@ +{ + "sample_command": "glasgow run logic -V 3.3 --pins-d 0,1,2", + "sample_rate": 48e6, + "bit_ref": 0, + "bit_meas": 1, + "bit_input": 2, + + "ref_min": 1.9e6, + "ref_max": 2.1e6, + "refpll_ki": 4294967, + "refpll_kp": 85899345, + + "ref_wavelength": 632.991372e-9, + "scan_displacement": 40e-6, + "scan_frequency": 50.0, + "scan_blanking": 0.05 +}