Skip to main content

rds_rs/
radiotext.rs

1use crate::text::BLANK_CHAR;
2use crate::text_prob::TextProb;
3use modular_bitfield_msb::prelude::*;
4
5pub const MAX_RADIOTEXT_LEN: usize = 64;
6pub const END_OF_MESSAGE_CHAR: u8 = 0x0d;
7
8/// Radiotext (RT) decoding state for one variant (A or B)
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct Radiotext {
11    /// Final decoded text.
12    pub display: [u8; MAX_RADIOTEXT_LEN],
13    pvt: TextProb<MAX_RADIOTEXT_LEN>,
14}
15
16impl Default for Radiotext {
17    fn default() -> Self {
18        Self {
19            display: [BLANK_CHAR; MAX_RADIOTEXT_LEN],
20            pvt: TextProb::default(),
21        }
22    }
23}
24
25/// Which RT variant is currently being decoded.
26#[derive(BitfieldSpecifier, Debug, Default, Clone, Copy, PartialEq, Eq)]
27#[bits = 1]
28pub enum RtVariant {
29    #[default]
30    A,
31    B,
32}
33
34#[derive(Debug, Default, Clone, PartialEq, Eq)]
35pub struct RtData {
36    pub a: Radiotext,         // RT A text.
37    pub b: Radiotext,         // RT B text.
38    pub decode_rt: RtVariant, // Which RT text currently being decoded.
39}
40
41impl Radiotext {
42    pub fn reset(&mut self) {
43        self.display.fill(BLANK_CHAR);
44    }
45
46    // Write (up to) a pair of two character tuples (up to four characters) into this
47    // instance starting at character index `addr`. One or both of the two-character
48    // pairs may be missing, and if so do nothing.
49    pub fn update_rt_simple(&mut self, addr: usize, char_pairs: &[Option<[u8; 2]>]) {
50        let mut idx = addr;
51
52        // Write two characters if provided.
53        // Return true if the end of message character (0xD) is received.
54        let mut add_pair = |pair: &Option<[u8; 2]>| -> bool {
55            if pair.is_none() {
56                return false;
57            }
58            for ch in pair.unwrap() {
59                if ch == END_OF_MESSAGE_CHAR {
60                    self.display[idx..].fill(BLANK_CHAR);
61                    return true;
62                }
63                self.display[idx] = ch;
64                idx += 1;
65            }
66            false
67        };
68
69        let eom = add_pair(&char_pairs[0]);
70        if !eom && char_pairs.len() > 1 {
71            add_pair(&char_pairs[1]);
72        }
73    }
74
75    pub fn update_rt_advance(&mut self, addr: usize, char_pairs: &[Option<[u8; 2]>]) {
76        let mut idx = addr;
77
78        let mut add_pair = |pair: &Option<[u8; 2]>| {
79            if pair.is_none() {
80                return;
81            }
82            for ch in pair.unwrap() {
83                self.pvt.update(idx, ch);
84                idx += 1;
85            }
86        };
87
88        add_pair(&char_pairs[0]);
89        if char_pairs.len() > 1 {
90            add_pair(&char_pairs[1]);
91        }
92        if !self.pvt.is_complete() {
93            return;
94        }
95        self.display.copy_from_slice(&self.pvt.hi_prob);
96    }
97
98    pub fn bump_rt_validation_count(&mut self) {
99        self.pvt.bump_rt_validation_count();
100    }
101}