initial commit
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