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}