1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use collect_slice::CollectSlice;
use bits::{Dibit, Hexbit, HexbitBytes};
use buffer::{Buffer, VoiceLCTermWordStorage, VoiceExtraStorage};
use coding::{reed_solomon, golay};
use consts::LINK_CONTROL_BYTES;
use error::Result;
use stats::{Stats, HasStats};
use voice::control::LinkControlFields;
use error::P25Error::*;
pub struct VoiceLCTerminatorReceiver {
outer: Buffer<VoiceLCTermWordStorage>,
inner: Buffer<VoiceExtraStorage>,
stats: Stats,
}
impl VoiceLCTerminatorReceiver {
pub fn new() -> VoiceLCTerminatorReceiver {
VoiceLCTerminatorReceiver {
outer: Buffer::new(VoiceLCTermWordStorage::new()),
inner: Buffer::new(VoiceExtraStorage::new()),
stats: Stats::default(),
}
}
pub fn feed(&mut self, dibit: Dibit) -> Option<Result<LinkControlFields>> {
let buf = match self.outer.feed(dibit) {
Some(buf) => buf,
None => return None,
};
let data = match golay::extended::decode(*buf as u32) {
Some((data, err)) => {
self.stats.record_golay_ext(err);
data
},
None => 0,
};
assert!(self.inner.feed(Hexbit::new((data >> 6) as u8)).is_none());
let hexbits = match self.inner.feed(Hexbit::new((data & 0x3F) as u8)) {
Some(buf) => buf,
None => return None,
};
let data = match reed_solomon::short::decode(hexbits) {
Some((data, err)) => {
self.stats.record_rs_short(err);
data
},
None => return Some(Err(RsShortUnrecoverable)),
};
let mut bytes = [0; LINK_CONTROL_BYTES];
HexbitBytes::new(data.iter().cloned())
.collect_slice_checked(&mut bytes[..]);
Some(Ok(LinkControlFields::new(bytes)))
}
}
impl HasStats for VoiceLCTerminatorReceiver {
fn stats(&mut self) -> &mut Stats { &mut self.stats }
}