Skip to main content

webarkitlib_rs/
bch.rs

1use crate::types::ARMatrixCodeType;
2
3pub fn decode_parity65(code_raw: u64) -> Result<u64, &'static str> {
4    const PARITY65_DECODER_TABLE: [i8; 64] = [
5        0, -1, -1, 3, -1, 5, 6, -1, -1, 9, 10, -1, 12, -1, -1, 15, -1, 17, 18, -1, 20, -1, -1, 23, 24,
6        -1, -1, 27, -1, 29, 30, -1, -1, 1, 2, -1, 4, -1, -1, 7, 8, -1, -1, 11, -1, 13, 14, -1, 16, -1,
7        -1, 19, -1, 21, 22, -1, -1, 25, 26, -1, 28, -1, -1, 31,
8    ];
9    if code_raw >= 64 {
10        return Err("EDC fail");
11    }
12    let val = PARITY65_DECODER_TABLE[code_raw as usize];
13    if val < 0 {
14        Err("EDC fail")
15    } else {
16        Ok(val as u64)
17    }
18}
19
20pub fn decode_hamming63(code_raw: u64) -> Result<(u64, i32), &'static str> {
21    const HAMMING63_DECODER_TABLE: [i8; 64] = [
22        0, 0, 0, 1, 0, 1, 1, 1, 0, 2, 4, -1, -1, 5, 3, 1, 0, 2, -1, 6, 7, -1, 3, 1, 2, 2, 3, 2, 3, 2,
23        3, 3, 0, -1, 4, 6, 7, 5, -1, 1, 4, 5, 4, 4, 5, 5, 4, 5, 7, 6, 6, 6, 7, 7, 7, 6, -1, 2, 4, 6, 7,
24        5, 3, -1,
25    ];
26    const ERROR_CORRECTED: [bool; 64] = [
27        false, true, true, true, true, true, true, false, true, true, true, false, false, true, true,
28        true, true, true, false, true, true, false, true, true, true, false, true, true, true, true,
29        false, true, true, false, true, true, true, true, false, true, true, true, false, true, true,
30        false, true, true, true, true, true, false, false, true, true, true, false, true, true, true,
31        true, true, true, false,
32    ];
33    if code_raw >= 64 {
34        return Err("EDC fail");
35    }
36    let val = HAMMING63_DECODER_TABLE[code_raw as usize];
37    if val < 0 {
38        Err("EDC fail")
39    } else {
40        let corrected = if ERROR_CORRECTED[code_raw as usize] {
41            1
42        } else {
43            0
44        };
45        Ok((val as u64, corrected))
46    }
47}
48
49pub fn decode_bch(
50    matrix_code_type: ARMatrixCodeType,
51    in_val: u64,
52) -> Result<(u64, i32), &'static str> {
53    let t: usize;
54    let k: usize;
55    let n: usize;
56    let length: usize;
57    let alpha_to: &[i32];
58    let index_of: &[i32];
59
60    const BCH_15_ALPHA_TO: [i32; 15] = [1, 2, 4, 8, 3, 6, 12, 11, 5, 10, 7, 14, 15, 13, 9];
61    const BCH_15_INDEX_OF: [i32; 16] = [-1, 0, 1, 4, 2, 8, 5, 10, 3, 14, 9, 7, 6, 13, 11, 12];
62    const BCH_31_ALPHA_TO: [i32; 31] = [
63        1, 2, 4, 8, 16, 5, 10, 20, 13, 26, 17, 7, 14, 28, 29, 31, 27, 19, 3, 6, 12, 24, 21, 15, 30,
64        25, 23, 11, 22, 9, 18,
65    ];
66    const BCH_31_INDEX_OF: [i32; 32] = [
67        -1, 0, 1, 18, 2, 5, 19, 11, 3, 29, 6, 27, 20, 8, 12, 23, 4, 10, 30, 17, 7, 22, 28, 26, 21, 25,
68        9, 16, 13, 14, 24, 15,
69    ];
70
71    let mut recd = [0u8; 127];
72
73    match matrix_code_type {
74        ARMatrixCodeType::Code4x4BCH1393 | ARMatrixCodeType::Code4x4BCH1355 => {
75            if matrix_code_type == ARMatrixCodeType::Code4x4BCH1393 {
76                t = 1;
77                k = 9;
78            } else {
79                t = 2;
80                k = 5;
81            }
82            n = 15;
83            length = 13;
84            alpha_to = &BCH_15_ALPHA_TO;
85            index_of = &BCH_15_INDEX_OF;
86        }
87        ARMatrixCodeType::Code5x5BCH22125 | ARMatrixCodeType::Code5x5BCH2277 => {
88            if matrix_code_type == ARMatrixCodeType::Code5x5BCH22125 {
89                t = 2;
90                k = 12;
91            } else {
92                t = 3;
93                k = 7;
94            }
95            n = 31;
96            length = 22;
97            alpha_to = &BCH_31_ALPHA_TO;
98            index_of = &BCH_31_INDEX_OF;
99        }
100        _ => return Err("Unsupported BCH code type"),
101    }
102
103    let mut in_bitwise = in_val;
104    for i in 0..length {
105        recd[i] = (in_bitwise & 1) as u8;
106        in_bitwise >>= 1;
107    }
108
109    let mut syn_error = false;
110    let t2 = 2 * t;
111    let mut s = vec![0; t2 + 1];
112
113    for i in 1..=t2 {
114        s[i] = 0;
115        for j in 0..length {
116            if recd[j] != 0 {
117                s[i] ^= alpha_to[(i * j) % n];
118            }
119        }
120        if s[i] != 0 {
121            syn_error = true;
122        }
123        s[i] = index_of[s[i] as usize];
124    }
125
126    let mut l_arr = vec![0usize; t2 + 2];
127    if syn_error {
128        let mut elp = vec![vec![0; 18]; 20];
129        let mut d = vec![0; 20];
130        let mut u_lu = vec![0i32; 20];
131        let mut loc = vec![0usize; 127];
132        let mut reg = vec![0; 10];
133
134        d[0] = 0;
135        d[1] = s[1];
136        elp[0][0] = 0;
137        elp[1][0] = 1;
138        for i in 1..t2 {
139            elp[0][i] = -1;
140            elp[1][i] = 0;
141        }
142        l_arr[0] = 0;
143        l_arr[1] = 0;
144        u_lu[0] = -1;
145        u_lu[1] = 0;
146        let mut u = 0;
147
148        loop {
149            u += 1;
150            if d[u] == -1 {
151                l_arr[u + 1] = l_arr[u];
152                for i in 0..=l_arr[u] {
153                    elp[u + 1][i] = elp[u][i];
154                    if elp[u][i] >= 0 {
155                        elp[u][i] = index_of[elp[u][i] as usize];
156                    }
157                }
158            } else {
159                let mut q = u as i32 - 1;
160                while d[q as usize] == -1 && q > 0 {
161                    q -= 1;
162                }
163                if q > 0 {
164                    let mut j = q;
165                    loop {
166                        j -= 1;
167                        if d[j as usize] != -1 && u_lu[q as usize] < u_lu[j as usize] {
168                            q = j;
169                        }
170                        if j <= 0 {
171                            break;
172                        }
173                    }
174                }
175
176                let q = q as usize;
177                if l_arr[u] > l_arr[q] + u - q {
178                    l_arr[u + 1] = l_arr[u];
179                } else {
180                    l_arr[u + 1] = l_arr[q] + u - q;
181                }
182
183                for i in 0..t2 {
184                    elp[u + 1][i] = 0;
185                }
186                for i in 0..=l_arr[q] {
187                    if elp[q][i] != -1 {
188                        elp[u + 1][i + u - q] = alpha_to[((d[u] + (n as i32) - d[q] + elp[q][i]) % (n as i32)) as usize];
189                    }
190                }
191                for i in 0..=l_arr[u] {
192                    elp[u + 1][i] ^= elp[u][i];
193                    if elp[u][i] >= 0 {
194                        elp[u][i] = index_of[elp[u][i] as usize];
195                    }
196                }
197            }
198            u_lu[u + 1] = u as i32 - l_arr[u + 1] as i32;
199
200            if u < t2 {
201                if s[u + 1] != -1 {
202                    d[u + 1] = alpha_to[s[u + 1] as usize];
203                } else {
204                    d[u + 1] = 0;
205                }
206                for i in 1..=l_arr[u + 1] {
207                    if s[u + 1 - i] != -1 && elp[u + 1][i] != 0 {
208                        d[u + 1] ^= alpha_to[((s[u + 1 - i] + index_of[elp[u + 1][i] as usize]) % (n as i32)) as usize];
209                    }
210                }
211                if d[u + 1] >= 0 {
212                    d[u + 1] = index_of[d[u + 1] as usize];
213                }
214            }
215
216            if u >= t2 || l_arr[u + 1] > t {
217                break;
218            }
219        }
220
221        u += 1;
222        if l_arr[u] <= t {
223            for i in 0..=l_arr[u] {
224                if elp[u][i] >= 0 {
225                    elp[u][i] = index_of[elp[u][i] as usize];
226                }
227            }
228
229            for i in 1..=l_arr[u] {
230                reg[i] = elp[u][i];
231            }
232            let mut count = 0;
233            for i in 1..=n {
234                let mut q_err = 1;
235                for j in 1..=l_arr[u] {
236                    if reg[j] != -1 {
237                        reg[j] = (reg[j] + j as i32) % (n as i32);
238                        q_err ^= alpha_to[reg[j] as usize];
239                    }
240                }
241                if q_err == 0 {
242                    loc[count] = n - i;
243                    count += 1;
244                }
245            }
246
247            if count == l_arr[u] {
248                for i in 0..l_arr[u] {
249                    recd[loc[i]] ^= 1;
250                }
251            } else {
252                return Err("BCH correction failed (count != l)");
253            }
254        } else {
255            return Err("BCH correction failed (l > t)");
256        }
257    }
258
259    let mut out_p = 0u64;
260    let mut out_bit = 1u64;
261    for i in (length - k)..length {
262        if recd[i] != 0 {
263            out_p += out_bit;
264        }
265        out_bit <<= 1;
266    }
267
268    let corrected = if syn_error { l_arr[s.len() - 1] as i32 } else { 0 };
269    Ok((out_p, corrected))
270}