Compare commits
1 Commits
2f57ccf617
...
ec506fd0ce
Author | SHA1 | Date |
---|---|---|
morgan | ec506fd0ce |
|
@ -289,6 +289,7 @@ pub fn main_setup(timer: &mut GlobalTimer) -> Result<(), &'static str> {
|
||||||
pub mod wrpll {
|
pub mod wrpll {
|
||||||
|
|
||||||
use libboard_zynq::gic;
|
use libboard_zynq::gic;
|
||||||
|
use libcortex_a9::mutex::Mutex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -299,9 +300,9 @@ pub mod wrpll {
|
||||||
|
|
||||||
const ADPLL_MAX: i32 = (950.0 / 0.0001164) as i32;
|
const ADPLL_MAX: i32 = (950.0 / 0.0001164) as i32;
|
||||||
|
|
||||||
static mut BASE_ADPLL: i32 = 0;
|
static BASE_ADPLL: Mutex<i32> = Mutex::new(0);
|
||||||
static mut H_INTEGRATOR: i32 = 0;
|
static H_INTEGRATOR: Mutex<i32> = Mutex::new(0);
|
||||||
static mut M_INTEGRATOR: i32 = 0;
|
static M_INTEGRATOR: Mutex<i32> = Mutex::new(0);
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum IRQ {
|
pub enum IRQ {
|
||||||
|
@ -310,86 +311,79 @@ pub mod wrpll {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod tag_collector {
|
mod tag_collector {
|
||||||
use super::IRQ;
|
use super::*;
|
||||||
use crate::pl::csr;
|
|
||||||
|
|
||||||
const BEATING_PERIOD: i32 = 0x4000;
|
const BEATING_PERIOD: i32 = 0x4000;
|
||||||
const BEATING_HALFPERIOD: i32 = 0x2000;
|
const BEATING_HALFPERIOD: i32 = 0x2000;
|
||||||
|
|
||||||
// for helper PLL
|
// for helper PLL
|
||||||
static mut LAST_GTX_TAG: u32 = 0;
|
static LAST_GTX_TAG: Mutex<u32> = Mutex::new(0);
|
||||||
static mut FIRST_GTX_INTERRUPT: bool = true;
|
static FIRST_GTX_INTERRUPT: Mutex<bool> = Mutex::new(false);
|
||||||
static mut PERIOD_DET_READY: bool = false;
|
static PERIOD_DET_READY: Mutex<bool> = Mutex::new(false);
|
||||||
|
|
||||||
// for main PLL
|
// for main PLL
|
||||||
static mut GTX_TAG: u32 = 0;
|
static GTX_TAG: Mutex<u32> = Mutex::new(0);
|
||||||
static mut GTX_TAG_READY: bool = false;
|
static GTX_TAG_READY: Mutex<bool> = Mutex::new(false);
|
||||||
static mut MAIN_TAG: u32 = 0;
|
static MAIN_TAG: Mutex<u32> = Mutex::new(0);
|
||||||
static mut MAIN_TAG_READY: bool = false;
|
static MAIN_TAG_READY: Mutex<bool> = Mutex::new(false);
|
||||||
|
|
||||||
pub fn reset() {
|
pub fn reset() {
|
||||||
clear_period_det_ready();
|
clear_period_det_ready();
|
||||||
clear_phase_det_ready();
|
clear_phase_det_ready();
|
||||||
unsafe {
|
*LAST_GTX_TAG.lock() = 0;
|
||||||
LAST_GTX_TAG = 0;
|
*FIRST_GTX_INTERRUPT.lock() = true;
|
||||||
FIRST_GTX_INTERRUPT = true;
|
*GTX_TAG.lock() = 0;
|
||||||
GTX_TAG = 0;
|
*MAIN_TAG.lock() = 0;
|
||||||
MAIN_TAG = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_period_det_ready() {
|
pub fn clear_period_det_ready() {
|
||||||
unsafe {
|
*PERIOD_DET_READY.lock() = false;
|
||||||
PERIOD_DET_READY = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_phase_det_ready() {
|
pub fn clear_phase_det_ready() {
|
||||||
unsafe {
|
*GTX_TAG_READY.lock() = false;
|
||||||
GTX_TAG_READY = false;
|
*MAIN_TAG_READY.lock() = false;
|
||||||
MAIN_TAG_READY = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn collect_tags(interrupt: IRQ) {
|
pub fn collect_tags(interrupt: IRQ) {
|
||||||
match interrupt {
|
match interrupt {
|
||||||
IRQ::GTXTag => unsafe {
|
IRQ::GTXTag => {
|
||||||
if !FIRST_GTX_INTERRUPT {
|
let mut gtx_tag_lock = GTX_TAG.lock();
|
||||||
LAST_GTX_TAG = GTX_TAG;
|
|
||||||
PERIOD_DET_READY = true;
|
if !(*FIRST_GTX_INTERRUPT.lock()) {
|
||||||
|
*LAST_GTX_TAG.lock() = *gtx_tag_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
GTX_TAG = csr::wrpll::gtx_tag_read();
|
*gtx_tag_lock = unsafe { csr::wrpll::gtx_tag_read() };
|
||||||
FIRST_GTX_INTERRUPT = false;
|
*FIRST_GTX_INTERRUPT.lock() = false;
|
||||||
GTX_TAG_READY = true;
|
*GTX_TAG_READY.lock() = true;
|
||||||
},
|
}
|
||||||
IRQ::MainTag => unsafe {
|
IRQ::MainTag => {
|
||||||
MAIN_TAG = csr::wrpll::main_tag_read();
|
*MAIN_TAG.lock() = unsafe { csr::wrpll::main_tag_read() };
|
||||||
MAIN_TAG_READY = true;
|
*MAIN_TAG_READY.lock() = true;
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn period_det_ready() -> bool {
|
pub fn period_det_ready() -> bool {
|
||||||
unsafe { PERIOD_DET_READY }
|
*PERIOD_DET_READY.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn phase_det_ready() -> bool {
|
pub fn phase_det_ready() -> bool {
|
||||||
unsafe { GTX_TAG_READY && MAIN_TAG_READY }
|
*GTX_TAG_READY.lock() && *MAIN_TAG_READY.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_period_error() -> i32 {
|
pub fn get_period_error() -> i32 {
|
||||||
// when gtx tag roll over, overflowing_sub prevent the difference to overflow and still get the correct period
|
// overflowing_sub can calculate the correct beating period when GTX_TAG roll over
|
||||||
unsafe { BEATING_PERIOD - (GTX_TAG.overflowing_sub(LAST_GTX_TAG).0) as i32 }
|
BEATING_PERIOD - ((*GTX_TAG.lock()).overflowing_sub(*LAST_GTX_TAG.lock()).0) as i32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_phase_error() -> i32 {
|
pub fn get_phase_error() -> i32 {
|
||||||
let mut phase_error: i32;
|
// unwrap tag difference
|
||||||
|
let mut phase_error = (*MAIN_TAG.lock())
|
||||||
unsafe {
|
.overflowing_sub(*GTX_TAG.lock())
|
||||||
// unwrap tag difference
|
.0
|
||||||
phase_error = MAIN_TAG.overflowing_sub(GTX_TAG).0.rem_euclid(BEATING_PERIOD as u32) as i32;
|
.rem_euclid(BEATING_PERIOD as u32) as i32;
|
||||||
}
|
|
||||||
|
|
||||||
// mapping tags from [0, 2π] -> [-π, π]
|
// mapping tags from [0, 2π] -> [-π, π]
|
||||||
if phase_error > BEATING_HALFPERIOD {
|
if phase_error > BEATING_HALFPERIOD {
|
||||||
|
@ -493,11 +487,10 @@ pub mod wrpll {
|
||||||
|error: i32| (((error) as f64 * 1e6) / (0.0001164 * (1 << (TIMER_WIDTH - COUNTER_DIV)) as f64)) as i32;
|
|error: i32| (((error) as f64 * 1e6) / (0.0001164 * (1 << (TIMER_WIDTH - COUNTER_DIV)) as f64)) as i32;
|
||||||
|
|
||||||
let (gtx_count, main_count, _helper_count) = get_freq_counts(timer);
|
let (gtx_count, main_count, _helper_count) = get_freq_counts(timer);
|
||||||
unsafe {
|
let mut base_adpll_lock = BASE_ADPLL.lock();
|
||||||
BASE_ADPLL = count2adpll(gtx_count as i32 - main_count as i32);
|
*base_adpll_lock = count2adpll(gtx_count as i32 - main_count as i32);
|
||||||
set_adpll(i2c::DCXO::Main, BASE_ADPLL)?;
|
set_adpll(i2c::DCXO::Main, *base_adpll_lock)?;
|
||||||
set_adpll(i2c::DCXO::Helper, BASE_ADPLL)?;
|
set_adpll(i2c::DCXO::Helper, *base_adpll_lock)?;
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -516,10 +509,8 @@ pub mod wrpll {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_plls() -> Result<(), &'static str> {
|
fn reset_plls() -> Result<(), &'static str> {
|
||||||
unsafe {
|
*H_INTEGRATOR.lock() = 0;
|
||||||
H_INTEGRATOR = 0;
|
*M_INTEGRATOR.lock() = 0;
|
||||||
M_INTEGRATOR = 0;
|
|
||||||
}
|
|
||||||
set_adpll(i2c::DCXO::Main, 0)?;
|
set_adpll(i2c::DCXO::Main, 0)?;
|
||||||
set_adpll(i2c::DCXO::Helper, 0)?;
|
set_adpll(i2c::DCXO::Helper, 0)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -549,16 +540,14 @@ pub mod wrpll {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn helper_pll() -> Result<(), &'static str> {
|
pub fn helper_pll() -> Result<(), &'static str> {
|
||||||
let period_err = tag_collector::get_period_error();
|
|
||||||
|
|
||||||
const H_KP: i32 = 2;
|
const H_KP: i32 = 2;
|
||||||
const H_KI: f32 = 0.5;
|
const H_KI: f32 = 0.5;
|
||||||
|
|
||||||
let mut h_adpll: i32;
|
let period_err = tag_collector::get_period_error();
|
||||||
unsafe {
|
let mut integrator_lock = H_INTEGRATOR.lock();
|
||||||
H_INTEGRATOR += (period_err as f32 * H_KI) as i32;
|
|
||||||
h_adpll = BASE_ADPLL + period_err * H_KP + H_INTEGRATOR;
|
*integrator_lock += (period_err as f32 * H_KI) as i32;
|
||||||
}
|
let mut h_adpll = *BASE_ADPLL.lock() + period_err * H_KP + *integrator_lock;
|
||||||
|
|
||||||
h_adpll = h_adpll.clamp(-ADPLL_MAX, ADPLL_MAX);
|
h_adpll = h_adpll.clamp(-ADPLL_MAX, ADPLL_MAX);
|
||||||
set_adpll(i2c::DCXO::Helper, h_adpll)?;
|
set_adpll(i2c::DCXO::Helper, h_adpll)?;
|
||||||
|
@ -567,16 +556,14 @@ pub mod wrpll {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_pll() -> Result<(), &'static str> {
|
pub fn main_pll() -> Result<(), &'static str> {
|
||||||
let phase_err = tag_collector::get_phase_error();
|
|
||||||
|
|
||||||
const M_KP: i32 = 12;
|
const M_KP: i32 = 12;
|
||||||
const M_KI: i32 = 2;
|
const M_KI: i32 = 2;
|
||||||
|
|
||||||
let mut m_adpll: i32;
|
let phase_err = tag_collector::get_phase_error();
|
||||||
unsafe {
|
let mut integrator_lock = M_INTEGRATOR.lock();
|
||||||
M_INTEGRATOR += phase_err * M_KI;
|
|
||||||
m_adpll = BASE_ADPLL + phase_err * M_KP + M_INTEGRATOR;
|
*integrator_lock += phase_err * M_KI;
|
||||||
}
|
let mut m_adpll = *BASE_ADPLL.lock() + phase_err * M_KP + *integrator_lock;
|
||||||
|
|
||||||
m_adpll = m_adpll.clamp(-ADPLL_MAX, ADPLL_MAX);
|
m_adpll = m_adpll.clamp(-ADPLL_MAX, ADPLL_MAX);
|
||||||
set_adpll(i2c::DCXO::Main, m_adpll)?;
|
set_adpll(i2c::DCXO::Main, m_adpll)?;
|
||||||
|
|
Loading…
Reference in New Issue