use core::sync::atomic::{AtomicU32, Ordering};
pub static TONE_AMPLITUDES: AtomicU32 = AtomicU32::new(0);
pub static CANDIDATES: AtomicU32 = AtomicU32::new(0);
pub static MINSYNC1_PASS: AtomicU32 = AtomicU32::new(0);
pub static MINSYNC2_REJECTED: AtomicU32 = AtomicU32::new(0);
pub static FANO_ATTEMPTS: AtomicU32 = AtomicU32::new(0);
pub static FANO_OK: AtomicU32 = AtomicU32::new(0);
pub static OSD_ATTEMPTS: AtomicU32 = AtomicU32::new(0);
pub static OSD_OK: AtomicU32 = AtomicU32::new(0);
pub static FANO_US: AtomicU32 = AtomicU32::new(0);
pub static BIT_METRICS_US: AtomicU32 = AtomicU32::new(0);
pub static OSD_US: AtomicU32 = AtomicU32::new(0);
pub static COARSE_SPECTRO_US: AtomicU32 = AtomicU32::new(0);
pub static COARSE_REFINE_US: AtomicU32 = AtomicU32::new(0);
#[inline]
pub fn add_us(counter: &AtomicU32, us: u32) {
counter.fetch_add(us, Ordering::Relaxed);
}
pub static LADDER_BUDGET_ABORTED: AtomicU32 = AtomicU32::new(0);
const ALL: &[&AtomicU32] = &[
&TONE_AMPLITUDES,
&CANDIDATES,
&MINSYNC1_PASS,
&MINSYNC2_REJECTED,
&FANO_ATTEMPTS,
&FANO_OK,
&OSD_ATTEMPTS,
&OSD_OK,
&LADDER_BUDGET_ABORTED,
];
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Counts {
pub coarse_spectro_us: u32,
pub coarse_refine_us: u32,
pub fano_us: u32,
pub bit_metrics_us: u32,
pub osd_us: u32,
pub tone_amplitudes: u32,
pub candidates: u32,
pub minsync1_pass: u32,
pub minsync2_rejected: u32,
pub fano_attempts: u32,
pub fano_ok: u32,
pub osd_attempts: u32,
pub osd_ok: u32,
pub ladder_budget_aborted: u32,
}
impl Counts {
#[must_use]
pub fn since(self, earlier: Counts) -> Counts {
Counts {
coarse_spectro_us: self
.coarse_spectro_us
.saturating_sub(earlier.coarse_spectro_us),
coarse_refine_us: self
.coarse_refine_us
.saturating_sub(earlier.coarse_refine_us),
fano_us: self.fano_us.saturating_sub(earlier.fano_us),
bit_metrics_us: self.bit_metrics_us.saturating_sub(earlier.bit_metrics_us),
osd_us: self.osd_us.saturating_sub(earlier.osd_us),
tone_amplitudes: self.tone_amplitudes.saturating_sub(earlier.tone_amplitudes),
candidates: self.candidates.saturating_sub(earlier.candidates),
minsync1_pass: self.minsync1_pass.saturating_sub(earlier.minsync1_pass),
minsync2_rejected: self
.minsync2_rejected
.saturating_sub(earlier.minsync2_rejected),
fano_attempts: self.fano_attempts.saturating_sub(earlier.fano_attempts),
fano_ok: self.fano_ok.saturating_sub(earlier.fano_ok),
osd_attempts: self.osd_attempts.saturating_sub(earlier.osd_attempts),
osd_ok: self.osd_ok.saturating_sub(earlier.osd_ok),
ladder_budget_aborted: self
.ladder_budget_aborted
.saturating_sub(earlier.ladder_budget_aborted),
}
}
#[must_use]
pub fn baseband_bytes_read(self) -> u64 {
const PER_CALL: u64 =
(super::demod::N_SYMBOLS * super::demod::NSPS_BASEBAND * 2 * 4) as u64;
u64::from(self.tone_amplitudes) * PER_CALL
}
}
#[must_use]
pub fn snapshot() -> Counts {
Counts {
coarse_spectro_us: COARSE_SPECTRO_US.load(Ordering::Relaxed),
coarse_refine_us: COARSE_REFINE_US.load(Ordering::Relaxed),
fano_us: FANO_US.load(Ordering::Relaxed),
bit_metrics_us: BIT_METRICS_US.load(Ordering::Relaxed),
osd_us: OSD_US.load(Ordering::Relaxed),
tone_amplitudes: TONE_AMPLITUDES.load(Ordering::Relaxed),
candidates: CANDIDATES.load(Ordering::Relaxed),
minsync1_pass: MINSYNC1_PASS.load(Ordering::Relaxed),
minsync2_rejected: MINSYNC2_REJECTED.load(Ordering::Relaxed),
fano_attempts: FANO_ATTEMPTS.load(Ordering::Relaxed),
fano_ok: FANO_OK.load(Ordering::Relaxed),
osd_attempts: OSD_ATTEMPTS.load(Ordering::Relaxed),
osd_ok: OSD_OK.load(Ordering::Relaxed),
ladder_budget_aborted: LADDER_BUDGET_ABORTED.load(Ordering::Relaxed),
}
}
pub fn reset() {
for c in ALL {
c.store(0, Ordering::Relaxed);
}
COARSE_SPECTRO_US.store(0, Ordering::Relaxed);
COARSE_REFINE_US.store(0, Ordering::Relaxed);
FANO_US.store(0, Ordering::Relaxed);
BIT_METRICS_US.store(0, Ordering::Relaxed);
OSD_US.store(0, Ordering::Relaxed);
}
#[inline]
pub(crate) fn bump(c: &AtomicU32) {
c.fetch_add(1, Ordering::Relaxed);
}