1
0
mirror of https://github.com/danog/libdvb.git synced 2024-11-26 20:04:39 +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 { for p in cmdseq {
match p.cmd { match p.cmd {
DTV_FREQUENCY => { DTV_FREQUENCY => {
let v = p.get_data(); let v = unsafe { p.u.data };
ensure!( ensure!(
self.frequency_range.contains(&v), self.frequency_range.contains(&v),
FeError::InvalidFrequency FeError::InvalidFrequency
); );
} }
DTV_SYMBOL_RATE => { DTV_SYMBOL_RATE => {
let v = p.get_data(); let v = unsafe { p.u.data };
ensure!( ensure!(
self.symbolrate_range.contains(&v), self.symbolrate_range.contains(&v),
FeError::InvalidSymbolrate FeError::InvalidSymbolrate
); );
} }
DTV_INVERSION => { DTV_INVERSION => {
if p.get_data() == INVERSION_AUTO { let v = unsafe { p.u.data };
if v == INVERSION_AUTO {
ensure!( ensure!(
self.caps & FE_CAN_INVERSION_AUTO != 0, self.caps & FE_CAN_INVERSION_AUTO != 0,
FeError::NoAutoInversion FeError::NoAutoInversion
@ -253,7 +254,8 @@ impl FeDevice {
} }
} }
DTV_TRANSMISSION_MODE => { DTV_TRANSMISSION_MODE => {
if p.get_data() == TRANSMISSION_MODE_AUTO { let v = unsafe { p.u.data };
if v == TRANSMISSION_MODE_AUTO {
ensure!( ensure!(
self.caps & FE_CAN_TRANSMISSION_MODE_AUTO != 0, self.caps & FE_CAN_TRANSMISSION_MODE_AUTO != 0,
FeError::NoAutoTransmitMode FeError::NoAutoTransmitMode
@ -261,7 +263,8 @@ impl FeDevice {
} }
} }
DTV_GUARD_INTERVAL => { DTV_GUARD_INTERVAL => {
if p.get_data() == GUARD_INTERVAL_AUTO { let v = unsafe { p.u.data };
if v == GUARD_INTERVAL_AUTO {
ensure!( ensure!(
self.caps & FE_CAN_GUARD_INTERVAL_AUTO != 0, self.caps & FE_CAN_GUARD_INTERVAL_AUTO != 0,
FeError::NoAutoGuardInterval FeError::NoAutoGuardInterval
@ -269,7 +272,8 @@ impl FeDevice {
} }
} }
DTV_HIERARCHY => { DTV_HIERARCHY => {
if p.get_data() == HIERARCHY_AUTO { let v = unsafe { p.u.data };
if v == HIERARCHY_AUTO {
ensure!( ensure!(
self.caps & FE_CAN_HIERARCHY_AUTO != 0, self.caps & FE_CAN_HIERARCHY_AUTO != 0,
FeError::NoAutoHierarchy FeError::NoAutoHierarchy

View File

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

View File

@ -454,7 +454,7 @@ impl fmt::Debug for DtvStats {
} }
FE_SCALE_RELATIVE => { FE_SCALE_RELATIVE => {
s.field(FIELD_SCALE, &"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 => { FE_SCALE_COUNTER => {
s.field(FIELD_SCALE, &"FE_SCALE_COUNTER"); s.field(FIELD_SCALE, &"FE_SCALE_COUNTER");
@ -484,33 +484,8 @@ pub struct DtvFrontendStats {
impl fmt::Debug for DtvFrontendStats { impl fmt::Debug for DtvFrontendStats {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let stats = &self.stat[0 .. self.len as usize]; let len = ::std::cmp::min(self.len as usize, self.stat.len());
f.debug_list().entries(stats.iter()).finish() f.debug_list().entries(self.stat[0 .. len].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
} }
} }
@ -708,14 +683,31 @@ impl fmt::Debug for DtvProperty {
s.field(FIELD_CMD, &"DTV_STAT_CNR"); s.field(FIELD_CMD, &"DTV_STAT_CNR");
s.field(FIELD_STATS, unsafe { &self.u.st }); s.field(FIELD_STATS, unsafe { &self.u.st });
} }
DTV_STAT_PRE_ERROR_BIT_COUNT => { DTV_STAT_PRE_ERROR_BIT_COUNT => {
s.field(FIELD_CMD, &"DTV_STAT_PRE_ERROR_BIT_COUNT"); s.field(FIELD_CMD, &"DTV_STAT_PRE_ERROR_BIT_COUNT");
s.field(FIELD_STATS, unsafe { &self.u.st }); 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 => { DTV_STAT_ERROR_BLOCK_COUNT => {
s.field(FIELD_CMD, &"DTV_STAT_ERROR_BLOCK_COUNT"); s.field(FIELD_CMD, &"DTV_STAT_ERROR_BLOCK_COUNT");
s.field(FIELD_STATS, unsafe { &self.u.st }); 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 // TODO: more values
_ => {} _ => {}
@ -738,9 +730,27 @@ impl DtvProperty {
} }
} }
#[inline] pub fn get_stats_counter(&self) -> Option<u64> {
pub fn get_data(&self) -> u32 { match self.cmd {
unsafe { self.u.data } 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
} }
} }