1
0
mirror of https://github.com/danog/libdvb.git synced 2024-11-30 04:19:00 +01:00
This commit is contained in:
Andrey Dyldin 2021-01-29 15:03:36 +02:00
parent f09139fd9a
commit 8a72f3411f
3 changed files with 97 additions and 81 deletions

View File

@ -231,21 +231,22 @@ impl FeDevice {
for p in cmdseq {
match p.cmd {
DTV_FREQUENCY => {
let v = p.get_data();
let v = unsafe { p.u.data };
ensure!(
self.frequency_range.contains(&v),
FeError::InvalidFrequency
);
}
DTV_SYMBOL_RATE => {
let v = p.get_data();
let v = unsafe { p.u.data };
ensure!(
self.symbolrate_range.contains(&v),
FeError::InvalidSymbolrate
);
}
DTV_INVERSION => {
if p.get_data() == INVERSION_AUTO {
let v = unsafe { p.u.data };
if v == INVERSION_AUTO {
ensure!(
self.caps & FE_CAN_INVERSION_AUTO != 0,
FeError::NoAutoInversion
@ -253,7 +254,8 @@ impl FeDevice {
}
}
DTV_TRANSMISSION_MODE => {
if p.get_data() == TRANSMISSION_MODE_AUTO {
let v = unsafe { p.u.data };
if v == TRANSMISSION_MODE_AUTO {
ensure!(
self.caps & FE_CAN_TRANSMISSION_MODE_AUTO != 0,
FeError::NoAutoTransmitMode
@ -261,7 +263,8 @@ impl FeDevice {
}
}
DTV_GUARD_INTERVAL => {
if p.get_data() == GUARD_INTERVAL_AUTO {
let v = unsafe { p.u.data };
if v == GUARD_INTERVAL_AUTO {
ensure!(
self.caps & FE_CAN_GUARD_INTERVAL_AUTO != 0,
FeError::NoAutoGuardInterval
@ -269,7 +272,8 @@ impl FeDevice {
}
}
DTV_HIERARCHY => {
if p.get_data() == HIERARCHY_AUTO {
let v = unsafe { p.u.data };
if v == HIERARCHY_AUTO {
ensure!(
self.caps & FE_CAN_HIERARCHY_AUTO != 0,
FeError::NoAutoHierarchy

View File

@ -21,22 +21,32 @@ use {
/// Frontend status
#[derive(Default, Debug, Copy, Clone)]
#[derive(Debug)]
pub struct FeStatus {
/// `sys::frontend::fe_status`
status: u32,
/// signal level in dBm
signal: Option<f64>,
/// properties
props: [DtvProperty; 4],
}
/// signal-to-noise ratio in dB
snr: Option<f64>,
/// number of bit errors before the forward error correction coding
ber: Option<u64>,
/// number of block errors after the outer forward error correction coding
unc: Option<u64>,
impl Default for FeStatus {
fn default() -> FeStatus {
FeStatus {
status: 0,
props: [
// 0: signal level
DtvProperty::new(DTV_STAT_SIGNAL_STRENGTH, 0),
// 1: signal-to-noise ratio
DtvProperty::new(DTV_STAT_CNR, 0),
// 2: ber - number of bit errors
DtvProperty::new(DTV_STAT_PRE_ERROR_BIT_COUNT, 0),
// 3: unc - number of block errors
DtvProperty::new(DTV_STAT_ERROR_BLOCK_COUNT, 0),
],
}
}
}
@ -67,12 +77,8 @@ impl<'a> FeStatusDisplay<'a> {
}
write!(f, " S:")?;
if let Some(signal) = self.inner.signal {
// TODO: config for lo/hi
let lo: f64 = -85.0;
let hi: f64 = -6.0;
let relative = 100.0 - (signal - hi) * 100.0 / (lo - hi);
write!(f, "{:.02}dBm ({:.0}%)", signal, relative)?;
if let Some((decibel, relative)) = self.inner.get_signal_level() {
write!(f, "{:.02}dBm ({:.0}%)", decibel, relative)?;
} else {
write!(f, "-")?;
}
@ -82,9 +88,8 @@ impl<'a> FeStatusDisplay<'a> {
}
write!(f, " Q:")?;
if let Some(snr) = self.inner.snr {
let relative = 5 * snr as u32;
write!(f, "{:.02}dB ({}%)", snr, relative)?;
if let Some((decibel, relative)) = self.inner.get_signal_noise_ratio() {
write!(f, "{:.02}dB ({}%)", decibel, relative)?;
} else {
write!(f, "-")?;
}
@ -94,14 +99,14 @@ impl<'a> FeStatusDisplay<'a> {
}
write!(f, " BER:")?;
if let Some(ber) = self.inner.ber {
if let Some(ber) = self.inner.props[2].get_stats_counter() {
write!(f, "{}", ber & 0xFFFF)?;
} else {
write!(f, "-")?;
}
write!(f, " UNC:")?;
if let Some(unc) = self.inner.unc {
if let Some(unc) = self.inner.props[3].get_stats_counter() {
write!(f, "{}", unc & 0xFFFF)
} else {
write!(f, "-")
@ -130,12 +135,8 @@ impl<'a> FeStatusDisplay<'a> {
}
write!(f, "\nSignal: ")?;
if let Some(signal) = self.inner.signal {
// TODO: config for lo/hi
let lo: f64 = -85.0;
let hi: f64 = -6.0;
let relative = 100.0 - (signal - hi) * 100.0 / (lo - hi);
write!(f, "{:.02}dBm ({:.0}%)", signal, relative)?;
if let Some((decibel, relative)) = self.inner.get_signal_level() {
write!(f, "{:.02}dBm ({:.0}%)", decibel, relative)?;
} else {
write!(f, "-")?;
}
@ -145,9 +146,8 @@ impl<'a> FeStatusDisplay<'a> {
}
write!(f, "\nSNR: ")?;
if let Some(snr) = self.inner.snr {
let relative = 5 * snr as u32;
write!(f, "{:.02}dB ({}%)", snr, relative)?;
if let Some((decibel, relative)) = self.inner.get_signal_noise_ratio() {
write!(f, "{:.02}dB ({}%)", decibel, relative)?;
} else {
write!(f, "-")?;
}
@ -157,14 +157,14 @@ impl<'a> FeStatusDisplay<'a> {
}
write!(f, "\nBER: ")?;
if let Some(ber) = self.inner.ber {
if let Some(ber) = self.inner.props[2].get_stats_counter() {
write!(f, "{}", ber & 0xFFFF)?;
} else {
write!(f, "-")?;
}
write!(f, "\nUNC: ")?;
if let Some(unc) = self.inner.unc {
if let Some(unc) = self.inner.props[3].get_stats_counter() {
write!(f, "{}", unc & 0xFFFF)
} else {
write!(f, "-")
@ -206,6 +206,19 @@ impl FeStatus {
}
}
fn get_signal_level(&self) -> Option<(f64, u64)> {
// TODO: config for lo/hi
// let lo: f64 = -85.0;
// let hi: f64 = -6.0;
// let relative = 100.0 - (decibel - hi) * 100.0 / (lo - hi);
None
}
fn get_signal_noise_ratio(&self) -> Option<(f64, u64)> {
// let relative = 5 * decibel as u32;
None
}
/// Reads frontend status
pub fn read(&mut self, fe: &FeDevice) -> Result<()> {
self.status = FE_NONE;
@ -220,18 +233,7 @@ impl FeStatus {
return Ok(());
}
let mut cmdseq = [
DtvProperty::new(DTV_STAT_SIGNAL_STRENGTH, 0),
DtvProperty::new(DTV_STAT_CNR, 0),
DtvProperty::new(DTV_STAT_PRE_ERROR_BIT_COUNT, 0),
DtvProperty::new(DTV_STAT_ERROR_BLOCK_COUNT, 0),
];
fe.get_properties(&mut cmdseq)?;
self.signal = (unsafe { cmdseq[0].u.st }).get_decibel();
self.snr = (unsafe { cmdseq[1].u.st }).get_decibel();
self.ber = (unsafe { cmdseq[2].u.st }).get_counter();
self.unc = (unsafe { cmdseq[3].u.st }).get_counter();
fe.get_properties(&mut self.props)?;
Ok(())
}

View File

@ -454,7 +454,7 @@ impl fmt::Debug for DtvStats {
}
FE_SCALE_RELATIVE => {
s.field(FIELD_SCALE, &"FE_SCALE_RELATIVE");
s.field(FIELD_VALUE, &{self.value as u64});
s.field(FIELD_VALUE, &{(self.value as u64) * 100 / 65535});
}
FE_SCALE_COUNTER => {
s.field(FIELD_SCALE, &"FE_SCALE_COUNTER");
@ -484,33 +484,8 @@ pub struct DtvFrontendStats {
impl fmt::Debug for DtvFrontendStats {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let stats = &self.stat[0 .. self.len as usize];
f.debug_list().entries(stats.iter()).finish()
}
}
impl DtvFrontendStats {
pub fn get_counter(&self) -> Option<u64> {
for i in 0 .. ::std::cmp::min(self.len as usize, self.stat.len()) {
let s = &self.stat[i];
if s.scale == FE_SCALE_COUNTER {
return Some(s.value as u64);
}
}
None
}
pub fn get_decibel(&self) -> Option<f64> {
for i in 0 .. ::std::cmp::min(self.len as usize, self.stat.len()) {
let s = &self.stat[i];
if s.scale == FE_SCALE_DECIBEL {
return Some((s.value as f64) / 1000.0);
}
}
None
let len = ::std::cmp::min(self.len as usize, self.stat.len());
f.debug_list().entries(self.stat[0 .. len].iter()).finish()
}
}
@ -708,14 +683,31 @@ impl fmt::Debug for DtvProperty {
s.field(FIELD_CMD, &"DTV_STAT_CNR");
s.field(FIELD_STATS, unsafe { &self.u.st });
}
DTV_STAT_PRE_ERROR_BIT_COUNT => {
s.field(FIELD_CMD, &"DTV_STAT_PRE_ERROR_BIT_COUNT");
s.field(FIELD_STATS, unsafe { &self.u.st });
}
DTV_STAT_PRE_TOTAL_BIT_COUNT => {
s.field(FIELD_CMD, &"DTV_STAT_PRE_TOTAL_BIT_COUNT");
s.field(FIELD_STATS, unsafe { &self.u.st });
}
DTV_STAT_POST_ERROR_BIT_COUNT => {
s.field(FIELD_CMD, &"DTV_STAT_POST_ERROR_BIT_COUNT");
s.field(FIELD_STATS, unsafe { &self.u.st });
}
DTV_STAT_POST_TOTAL_BIT_COUNT => {
s.field(FIELD_CMD, &"DTV_STAT_POST_TOTAL_BIT_COUNT");
s.field(FIELD_STATS, unsafe { &self.u.st });
}
DTV_STAT_ERROR_BLOCK_COUNT => {
s.field(FIELD_CMD, &"DTV_STAT_ERROR_BLOCK_COUNT");
s.field(FIELD_STATS, unsafe { &self.u.st });
}
DTV_STAT_TOTAL_BLOCK_COUNT => {
s.field(FIELD_CMD, &"DTV_STAT_TOTAL_BLOCK_COUNT");
s.field(FIELD_STATS, unsafe { &self.u.st });
}
// TODO: more values
_ => {}
@ -738,9 +730,27 @@ impl DtvProperty {
}
}
#[inline]
pub fn get_data(&self) -> u32 {
unsafe { self.u.data }
pub fn get_stats_counter(&self) -> Option<u64> {
match self.cmd {
DTV_STAT_PRE_ERROR_BIT_COUNT |
DTV_STAT_PRE_TOTAL_BIT_COUNT |
DTV_STAT_POST_ERROR_BIT_COUNT |
DTV_STAT_POST_TOTAL_BIT_COUNT |
DTV_STAT_ERROR_BLOCK_COUNT |
DTV_STAT_TOTAL_BLOCK_COUNT => {
let stats = unsafe { &self.u.st };
if stats.len > 0 {
let s = &stats.stat[0];
if s.scale == FE_SCALE_COUNTER {
return Some(s.value as u64);
}
}
}
_ => {}
}
None
}
}