ldpc_toolbox/cli/
dvbs2.rs

1//! DVB-S2 CLI subcommand
2//!
3//! This subcommand can be used to generate the LDPC codes used in the DVB-S2
4//! standard. It will print the alist of the parity check matrix to `stdout`
5//! and optionally compute and print the girth of the Tanner graph. See
6//! [`crate::codes::dvbs2`] for more information about the DVB-S2 LDPC codes.
7//!
8//! # Examples
9//! The r=1/2, n=64800 parity check matrix for the normal FECFRAMEs can
10//! be generated with
11//! ```shell
12//! $ ldpc-toolbox dvbs2 --rate 1/2
13//! ```
14//! Its girth is computed with
15//! ```shell
16//! $ ldpc-toolbox dvbs2 --rate 1/2 --girth
17//! Code girth = 6
18//! ```
19//!
20//! The n=16200 code for the short FECFRAMEs is generated with
21//! ```shell
22//! $ ldpc-toolbox dvbs2 --rate 1/2 --short
23//! ```
24
25use crate::cli::*;
26use crate::codes::dvbs2::Code;
27use clap::Parser;
28
29type Error = String;
30type Result<T> = std::result::Result<T, Error>;
31
32/// DVB-S2 CLI arguments.
33#[derive(Debug, Parser)]
34#[command(about = "Generates the alist of DVB-S2 LDPCs")]
35pub struct Args {
36    /// Coding rate
37    #[arg(short, long)]
38    pub rate: String,
39    /// Enables short FECFRAME
40    #[arg(long)]
41    pub short: bool,
42    /// Performs girth calculation
43    #[arg(long)]
44    pub girth: bool,
45}
46
47impl Args {
48    fn code(&self) -> Result<Code> {
49        match (&*self.rate, self.short) {
50            ("1/4", false) => Ok(Code::R1_4),
51            ("1/3", false) => Ok(Code::R1_3),
52            ("2/5", false) => Ok(Code::R2_5),
53            ("1/2", false) => Ok(Code::R1_2),
54            ("3/5", false) => Ok(Code::R3_5),
55            ("2/3", false) => Ok(Code::R2_3),
56            ("3/4", false) => Ok(Code::R3_4),
57            ("4/5", false) => Ok(Code::R4_5),
58            ("5/6", false) => Ok(Code::R5_6),
59            ("8/9", false) => Ok(Code::R8_9),
60            ("9/10", false) => Ok(Code::R9_10),
61            ("1/4", true) => Ok(Code::R1_4short),
62            ("1/3", true) => Ok(Code::R1_3short),
63            ("2/5", true) => Ok(Code::R2_5short),
64            ("1/2", true) => Ok(Code::R1_2short),
65            ("3/5", true) => Ok(Code::R3_5short),
66            ("2/3", true) => Ok(Code::R2_3short),
67            ("3/4", true) => Ok(Code::R3_4short),
68            ("4/5", true) => Ok(Code::R4_5short),
69            ("5/6", true) => Ok(Code::R5_6short),
70            ("8/9", true) => Ok(Code::R8_9short),
71            _ => Err(self.code_error()),
72        }
73    }
74
75    fn code_error(&self) -> String {
76        let fecframe = if self.short { "short" } else { "normal" };
77        format!("Invalid rate {} for {} FECFRAME", self.rate, fecframe)
78    }
79}
80
81impl Run for Args {
82    fn run(&self) -> std::result::Result<(), Box<dyn std::error::Error>> {
83        let h = self.code()?.h();
84        if self.girth {
85            if let Some(g) = h.girth() {
86                println!("Code girth = {}", g);
87            } else {
88                println!("Code girth is infinite");
89            }
90        } else {
91            print!("{}", h.alist());
92        }
93        Ok(())
94    }
95}