initial commit
This commit is contained in:
commit
da1c2a94c9
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
**/*.rs.bk
|
|
@ -0,0 +1,101 @@
|
|||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "noptica-rs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"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)",
|
||||
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"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"
|
||||
"checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802"
|
||||
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
|
||||
"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
|
||||
"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425"
|
||||
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
|
||||
"checksum syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "158521e6f544e7e3dcfc370ac180794aa38cb34a1b1e07609376d4adcf429b93"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "noptica-rs"
|
||||
version = "0.1.0"
|
||||
authors = ["Sebastien Bourdeauducq <sb@m-labs.hk>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
num-traits = "0.2"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"sample_command": "sudo sigrok-cli -O binary -d fx2lafw --config samplerate=8000000 --continuous",
|
||||
"sample_rate": 8e6,
|
||||
"freq_min": 1.9e6,
|
||||
"freq_max": 2.1e6,
|
||||
"bit_ref": 0,
|
||||
|
||||
"refpll_ki": 4294967,
|
||||
"refpll_kl": 85899345
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import sys, os
|
||||
|
||||
sample_rate = 24e6
|
||||
ref_frequency = 2.0e6
|
||||
|
||||
|
||||
ref_phase = 0
|
||||
ref_ftw = int(ref_frequency*2**32/sample_rate)
|
||||
|
||||
fp = os.fdopen(sys.stdout.fileno(), "wb")
|
||||
|
||||
while True:
|
||||
ref_phase = (ref_phase + ref_ftw) & 0xffffffff
|
||||
|
||||
sample = 0
|
||||
if ref_phase >= 0x80000000:
|
||||
sample |= 0x01
|
||||
fp.write(bytes([sample]))
|
|
@ -0,0 +1,43 @@
|
|||
extern crate num_traits;
|
||||
extern crate serde_derive;
|
||||
extern crate serde_json;
|
||||
|
||||
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,
|
||||
sample_rate: f64,
|
||||
freq_min: f64,
|
||||
freq_max: f64,
|
||||
bit_ref: u8,
|
||||
refpll_ki: i64,
|
||||
refpll_kl: i64
|
||||
}
|
||||
|
||||
fn read_config_from_file<P: AsRef<Path>>(path: P) -> Result<Config, Box<Error>> {
|
||||
let file = File::open(path)?;
|
||||
let reader = BufReader::new(file);
|
||||
let u = serde_json::from_reader(reader)?;
|
||||
Ok(u)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let config = read_config_from_file("config.json").unwrap();
|
||||
let mut refpll = noptica::Dpll::new(
|
||||
noptica::Dpll::frequency_to_ftw(config.freq_min, config.sample_rate),
|
||||
noptica::Dpll::frequency_to_ftw(config.freq_max, config.sample_rate),
|
||||
config.refpll_ki,
|
||||
config.refpll_kl);
|
||||
noptica::sample(&config.sample_command, |rising, _falling| {
|
||||
refpll.tick(rising & (1 << config.bit_ref) != 0);
|
||||
// println!("{}", refpll.get_phase_unwrapped());
|
||||
})
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
use std::io::{BufReader, Read};
|
||||
use num_traits::clamp;
|
||||
|
||||
pub struct Dpll {
|
||||
ftw_min: i64,
|
||||
ftw_max: i64,
|
||||
ki: i64,
|
||||
kp: i64,
|
||||
|
||||
ftw: i64,
|
||||
integrator: i64,
|
||||
|
||||
phase: i64,
|
||||
phase_unwrapped: i64,
|
||||
}
|
||||
|
||||
impl Dpll {
|
||||
pub fn new(ftw_min: i64, ftw_max: i64, ki: i64, kp: i64) -> Dpll {
|
||||
assert!(ftw_min < 0x80000000);
|
||||
assert!(ftw_max < 0x80000000);
|
||||
let init_ftw = (ftw_min + ftw_max)/2;
|
||||
Dpll {
|
||||
ftw_min: ftw_min,
|
||||
ftw_max: ftw_max,
|
||||
ki: ki,
|
||||
kp: kp,
|
||||
ftw: init_ftw,
|
||||
integrator: init_ftw,
|
||||
phase: 0,
|
||||
phase_unwrapped: 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn frequency_to_ftw(frequency: f64, sample_rate: f64) -> i64 {
|
||||
(frequency*(u32::max_value() as f64)/sample_rate) as i64
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, edge: bool) {
|
||||
self.phase = (self.phase + self.ftw) & 0xffffffff;
|
||||
self.phase_unwrapped = self.phase_unwrapped.wrapping_add(self.ftw);
|
||||
if edge {
|
||||
let pe = 0x80000000 - self.phase;
|
||||
self.integrator = clamp(self.integrator + (pe*self.ki >> 32),
|
||||
self.ftw_min, self.ftw_max);
|
||||
self.ftw = clamp(self.integrator + (pe*self.kp >> 32),
|
||||
self.ftw_min, self.ftw_max);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_phase_unwrapped(&self) -> i64 {
|
||||
self.phase_unwrapped
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn sample(command: &str, mut callback: impl FnMut(u8, u8)) {
|
||||
let child = std::process::Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(command)
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let mut reader = BufReader::new(child.stdout.unwrap());
|
||||
let mut br_sample = [0; 1];
|
||||
let mut last_sample = 0;
|
||||
loop {
|
||||
reader.read_exact(&mut br_sample).unwrap();
|
||||
let sample = br_sample[0];
|
||||
let rising = sample & !last_sample;
|
||||
let falling = !sample & last_sample;
|
||||
callback(rising, falling);
|
||||
last_sample = sample;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue