use crate::error::{Error, Result};
use crate::utility::bits::{bdotprod, msb_index};
const MIN_MSEQUENCE_M: u32 = 2;
const MAX_MSEQUENCE_M: u32 = 31;
const MSEQUENCE_GENPOLY_M2: u32 = 0x00000003; const MSEQUENCE_GENPOLY_M3: u32 = 0x00000006; const MSEQUENCE_GENPOLY_M4: u32 = 0x0000000c; const MSEQUENCE_GENPOLY_M5: u32 = 0x00000014; const MSEQUENCE_GENPOLY_M6: u32 = 0x00000030; const MSEQUENCE_GENPOLY_M7: u32 = 0x00000060; const MSEQUENCE_GENPOLY_M8: u32 = 0x000000b8; const MSEQUENCE_GENPOLY_M9: u32 = 0x00000110; const MSEQUENCE_GENPOLY_M10: u32 = 0x00000240; const MSEQUENCE_GENPOLY_M11: u32 = 0x00000500; const MSEQUENCE_GENPOLY_M12: u32 = 0x00000e08; const MSEQUENCE_GENPOLY_M13: u32 = 0x00001c80; const MSEQUENCE_GENPOLY_M14: u32 = 0x00003802; const MSEQUENCE_GENPOLY_M15: u32 = 0x00006000; const MSEQUENCE_GENPOLY_M16: u32 = 0x0000d008; const MSEQUENCE_GENPOLY_M17: u32 = 0x00012000; const MSEQUENCE_GENPOLY_M18: u32 = 0x00020400; const MSEQUENCE_GENPOLY_M19: u32 = 0x00072000; const MSEQUENCE_GENPOLY_M20: u32 = 0x00090000; const MSEQUENCE_GENPOLY_M21: u32 = 0x00140000; const MSEQUENCE_GENPOLY_M22: u32 = 0x00300000; const MSEQUENCE_GENPOLY_M23: u32 = 0x00420000; const MSEQUENCE_GENPOLY_M24: u32 = 0x00e10000; const MSEQUENCE_GENPOLY_M25: u32 = 0x01000004; const MSEQUENCE_GENPOLY_M26: u32 = 0x02000023; const MSEQUENCE_GENPOLY_M27: u32 = 0x04000013; const MSEQUENCE_GENPOLY_M28: u32 = 0x08000004; const MSEQUENCE_GENPOLY_M29: u32 = 0x10000002; const MSEQUENCE_GENPOLY_M30: u32 = 0x20000029; const MSEQUENCE_GENPOLY_M31: u32 = 0x40000004;
#[derive(Debug, Clone, Copy)]
pub struct MSequence {
m: u32, g: u32, a: u32, n: u32, state: u32, }
impl MSequence {
pub fn new(m: u32, g: u32, a: u32) -> Result<Self> {
if m > MAX_MSEQUENCE_M || m < MIN_MSEQUENCE_M {
return Err(Error::Config(format!("m ({}) not in range", m)));
}
Ok(Self {
m,
g,
a,
n: (1 << m) - 1,
state: a,
})
}
pub fn create_genpoly(g: u32) -> Result<Self> {
let t = msb_index(g);
if t < 2 {
return Err(Error::Config(format!("invalid generator polynomial: 0x{:x}", g)));
}
let m = t;
let a = 1;
Self::new(m, g, a)
}
pub fn create_default(m: u32) -> Result<Self> {
let g = match m {
2 => MSEQUENCE_GENPOLY_M2,
3 => MSEQUENCE_GENPOLY_M3,
4 => MSEQUENCE_GENPOLY_M4,
5 => MSEQUENCE_GENPOLY_M5,
6 => MSEQUENCE_GENPOLY_M6,
7 => MSEQUENCE_GENPOLY_M7,
8 => MSEQUENCE_GENPOLY_M8,
9 => MSEQUENCE_GENPOLY_M9,
10 => MSEQUENCE_GENPOLY_M10,
11 => MSEQUENCE_GENPOLY_M11,
12 => MSEQUENCE_GENPOLY_M12,
13 => MSEQUENCE_GENPOLY_M13,
14 => MSEQUENCE_GENPOLY_M14,
15 => MSEQUENCE_GENPOLY_M15,
16 => MSEQUENCE_GENPOLY_M16,
17 => MSEQUENCE_GENPOLY_M17,
18 => MSEQUENCE_GENPOLY_M18,
19 => MSEQUENCE_GENPOLY_M19,
20 => MSEQUENCE_GENPOLY_M20,
21 => MSEQUENCE_GENPOLY_M21,
22 => MSEQUENCE_GENPOLY_M22,
23 => MSEQUENCE_GENPOLY_M23,
24 => MSEQUENCE_GENPOLY_M24,
25 => MSEQUENCE_GENPOLY_M25,
26 => MSEQUENCE_GENPOLY_M26,
27 => MSEQUENCE_GENPOLY_M27,
28 => MSEQUENCE_GENPOLY_M28,
29 => MSEQUENCE_GENPOLY_M29,
30 => MSEQUENCE_GENPOLY_M30,
31 => MSEQUENCE_GENPOLY_M31,
_ => return Err(Error::Config(format!("m ({}) not in range", m))),
};
Self::create_genpoly(g)
}
pub fn advance(&mut self) -> u32 {
let b = bdotprod(self.state, self.g);
self.state <<= 1;
self.state |= b;
self.state &= self.n;
b
}
pub fn generate_symbol(&mut self, bps: u32) -> u32 {
let mut s = 0;
for _ in 0..bps {
s <<= 1;
s |= self.advance();
}
s
}
pub fn reset(&mut self) {
self.state = self.a;
}
pub fn get_genpoly_length(&self) -> u32 { self.m }
pub fn get_length(&self) -> u32 { self.n }
pub fn get_genpoly(&self) -> u32 { self.g }
pub fn get_state(&self) -> u32 { self.state }
pub fn set_state(&mut self, a: u32) {
self.state = a;
}
pub fn measure_period(&mut self) -> u32 {
let s = self.get_state();
let mut period = 0;
for _ in 0..=self.n {
self.advance();
period += 1;
if self.get_state() == s {
break;
}
}
period
}
pub fn genpoly_period(g: u32) -> Result<u32> {
let mut q = MSequence::create_genpoly(g)?;
Ok(q.measure_period())
}
}
#[cfg(test)]
mod tests{
use super::*;
use test_macro::autotest_annotate;
use crate::sequence::bsequence::BSequence;
fn msequence_test_autocorrelation(m: u32) {
let mut ms = MSequence::create_default(m).unwrap();
let n = ms.get_length();
let bs1 = BSequence::from_msequence(&mut ms).unwrap();
let mut bs2 = BSequence::from_msequence(&mut ms).unwrap();
assert_eq!(bs1.get_length(), n as usize);
assert_eq!(bs2.get_length(), n as usize);
let mut rxy = bs1.correlate(&bs2).unwrap();
assert_eq!(rxy, n as i32);
for _ in 0..n-1 {
bs2.push(ms.advance());
rxy = 2 * bs1.correlate(&bs2).unwrap() - n as i32;
assert_eq!(rxy, -1);
}
}
#[test]
#[autotest_annotate(autotest_msequence_xcorr_m2)]
fn test_msequence_xcorr_m2() { msequence_test_autocorrelation(2); }
#[test]
#[autotest_annotate(autotest_msequence_xcorr_m3)]
fn test_msequence_xcorr_m3() { msequence_test_autocorrelation(3); }
#[test]
#[autotest_annotate(autotest_msequence_xcorr_m4)]
fn test_msequence_xcorr_m4() { msequence_test_autocorrelation(4); }
#[test]
#[autotest_annotate(autotest_msequence_xcorr_m5)]
fn test_msequence_xcorr_m5() { msequence_test_autocorrelation(5); }
#[test]
#[autotest_annotate(autotest_msequence_xcorr_m6)]
fn test_msequence_xcorr_m6() { msequence_test_autocorrelation(6); }
#[test]
#[autotest_annotate(autotest_msequence_xcorr_m7)]
fn test_msequence_xcorr_m7() { msequence_test_autocorrelation(7); }
#[test]
#[autotest_annotate(autotest_msequence_xcorr_m8)]
fn test_msequence_xcorr_m8() { msequence_test_autocorrelation(8); }
#[test]
#[autotest_annotate(autotest_msequence_xcorr_m9)]
fn test_msequence_xcorr_m9() { msequence_test_autocorrelation(9); }
#[test]
#[autotest_annotate(autotest_msequence_xcorr_m10)]
fn test_msequence_xcorr_m10() { msequence_test_autocorrelation(10); }
#[test]
#[autotest_annotate(autotest_msequence_xcorr_m11)]
fn test_msequence_xcorr_m11() { msequence_test_autocorrelation(11); }
#[test]
#[autotest_annotate(autotest_msequence_xcorr_m12)]
fn test_msequence_xcorr_m12() { msequence_test_autocorrelation(12); }
fn msequence_test_period(m: u32) {
let mut q = MSequence::create_default(m).unwrap();
let n = (1u32 << m) - 1;
let p = q.measure_period();
assert_eq!(p, n);
}
#[test]
#[autotest_annotate(autotest_msequence_period_m2)]
fn test_msequence_period_m2() { msequence_test_period(2); }
#[test]
#[autotest_annotate(autotest_msequence_period_m3)]
fn test_msequence_period_m3() { msequence_test_period(3); }
#[test]
#[autotest_annotate(autotest_msequence_period_m4)]
fn test_msequence_period_m4() { msequence_test_period(4); }
#[test]
#[autotest_annotate(autotest_msequence_period_m5)]
fn test_msequence_period_m5() { msequence_test_period(5); }
#[test]
#[autotest_annotate(autotest_msequence_period_m6)]
fn test_msequence_period_m6() { msequence_test_period(6); }
#[test]
#[autotest_annotate(autotest_msequence_period_m7)]
fn test_msequence_period_m7() { msequence_test_period(7); }
#[test]
#[autotest_annotate(autotest_msequence_period_m8)]
fn test_msequence_period_m8() { msequence_test_period(8); }
#[test]
#[autotest_annotate(autotest_msequence_period_m9)]
fn test_msequence_period_m9() { msequence_test_period(9); }
#[test]
#[autotest_annotate(autotest_msequence_period_m10)]
fn test_msequence_period_m10() { msequence_test_period(10); }
#[test]
#[autotest_annotate(autotest_msequence_period_m11)]
fn test_msequence_period_m11() { msequence_test_period(11); }
#[test]
#[autotest_annotate(autotest_msequence_period_m12)]
fn test_msequence_period_m12() { msequence_test_period(12); }
#[test]
#[autotest_annotate(autotest_msequence_period_m13)]
fn test_msequence_period_m13() { msequence_test_period(13); }
#[test]
#[autotest_annotate(autotest_msequence_period_m14)]
fn test_msequence_period_m14() { msequence_test_period(14); }
#[test]
#[autotest_annotate(autotest_msequence_period_m15)]
fn test_msequence_period_m15() { msequence_test_period(15); }
#[test]
#[autotest_annotate(autotest_msequence_period_m16)]
fn test_msequence_period_m16() { msequence_test_period(16); }
#[test]
#[autotest_annotate(autotest_msequence_period_m17)]
fn test_msequence_period_m17() { msequence_test_period(17); }
#[test]
#[autotest_annotate(autotest_msequence_period_m18)]
fn test_msequence_period_m18() { msequence_test_period(18); }
#[test]
#[autotest_annotate(autotest_msequence_period_m19)]
fn test_msequence_period_m19() { msequence_test_period(19); }
#[test]
#[autotest_annotate(autotest_msequence_period_m20)]
fn test_msequence_period_m20() { msequence_test_period(20); }
#[test]
#[autotest_annotate(autotest_msequence_period_m21)]
fn test_msequence_period_m21() { msequence_test_period(21); }
#[test]
#[autotest_annotate(autotest_msequence_period_m22)]
fn test_msequence_period_m22() { msequence_test_period(22); }
#[test]
#[autotest_annotate(autotest_msequence_period_m23)]
fn test_msequence_period_m23() { msequence_test_period(23); }
#[test]
#[autotest_annotate(autotest_msequence_period_m24)]
fn test_msequence_period_m24() { msequence_test_period(24); }
#[test]
#[autotest_annotate(autotest_msequence_period_m25)]
fn test_msequence_period_m25() { msequence_test_period(25); }
#[test]
#[autotest_annotate(autotest_msequence_period_m26)]
fn test_msequence_period_m26() { msequence_test_period(26); }
#[test]
#[autotest_annotate(autotest_msequence_period_m27)]
fn test_msequence_period_m27() { msequence_test_period(27); }
#[test]
#[autotest_annotate(autotest_msequence_period_m28)]
fn test_msequence_period_m28() { msequence_test_period(28); }
#[test]
#[autotest_annotate(autotest_msequence_period_m29)]
fn test_msequence_period_m29() { msequence_test_period(29); }
#[test]
#[autotest_annotate(autotest_msequence_period_m30)]
fn test_msequence_period_m30() { msequence_test_period(30); }
#[test]
#[autotest_annotate(autotest_msequence_period_m31)]
fn test_msequence_period_m31() { msequence_test_period(31); }
#[test]
#[autotest_annotate(autotest_msequence_config)]
fn test_msequence_config() {
assert!(MSequence::new(100, 0, 0).is_err());
assert!(MSequence::create_default(32).is_err()); assert!(MSequence::create_genpoly(0).is_err());
let mut q = MSequence::create_genpoly(MSEQUENCE_GENPOLY_M11).unwrap();
assert_eq!(q.get_state(), 1);
q.set_state(0x8a);
assert_eq!(q.get_state(), 0x8a);
}
}