├── README.md
├── xrfcon.c
├── refcon.c
├── dmrcon.c
└── ysfcon.c
/README.md:
--------------------------------------------------------------------------------
1 | # Reflector Connectors
2 | Software to connect DSTAR DPlus reflectors, YSF Reflectors, and DMR talkgroups from different servers. Example applications for these utilties are to connect a Dplus DSTAR reflector to an XLXD network via REF to REF using refcon, or connecting a Brandmeister/TGIF talkgroup to an XLXD network via dmrcon.
3 |
4 | # Build
5 | Each program is a single C file, and no makefile is required. To build, simply run gcc for each file:
6 | ```
7 | gcc -o dmrcon dmrcon.c
8 | gcc -o refcon refcon.c
9 | gcc -o ysfcon ysfcon.c
10 | ```
11 |
12 | # Usage
13 | Connect 2 DSTAR DPlus (REF) reflectors:
14 | ```
15 | ./refcon [CALLSIGN] [REFName:Module:REFHostname:Port] [REFName:Module:REFHostname:Port]
16 | ```
17 | Connect 2 YSF reflectors
18 | ```
19 | ./ysfcon [CALLSIGN] [YSFHost1IP:PORT] [YSFHost2IP:PORT]
20 | ```
21 | Connect 2 DMR talkgroups
22 | ```
23 | ./dmrcon [CALLSIGN] [DMRID] [DMRHost1IP:PORT:TG:PW] [DMRHost2IP:PORT:TG:PW]
24 | ```
25 |
26 |
--------------------------------------------------------------------------------
/xrfcon.c:
--------------------------------------------------------------------------------
1 | /*
2 | XrfCon - DExtra Reflector Connector
3 | Copyright (C) 2019 Doug McLain
4 | Copyright (C) 2022 Nuno Silva
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #define CLIENT_MOD 'A'
34 | //#define XRF1_DXRFD_COMPAT
35 | #define BUFSIZE 2048
36 | //#define DEBUG_SEND
37 | //#define DEBUG_RECV
38 |
39 | char *ref1;
40 | char *ref2;
41 | int udp1;
42 | int udp2;
43 | fd_set udpset;
44 | struct sockaddr_in host1;
45 | struct sockaddr_in host2;
46 | uint8_t buf[BUFSIZE];
47 | char callsign[8U];
48 | uint32_t host1_cnt;
49 | uint32_t host2_cnt;
50 | uint8_t host1_connect;
51 | uint8_t host2_connect;
52 |
53 | const uint16_t CCITT16_TABLE1[] = {
54 | 0x0000U, 0x1189U, 0x2312U, 0x329bU, 0x4624U, 0x57adU, 0x6536U, 0x74bfU,
55 | 0x8c48U, 0x9dc1U, 0xaf5aU, 0xbed3U, 0xca6cU, 0xdbe5U, 0xe97eU, 0xf8f7U,
56 | 0x1081U, 0x0108U, 0x3393U, 0x221aU, 0x56a5U, 0x472cU, 0x75b7U, 0x643eU,
57 | 0x9cc9U, 0x8d40U, 0xbfdbU, 0xae52U, 0xdaedU, 0xcb64U, 0xf9ffU, 0xe876U,
58 | 0x2102U, 0x308bU, 0x0210U, 0x1399U, 0x6726U, 0x76afU, 0x4434U, 0x55bdU,
59 | 0xad4aU, 0xbcc3U, 0x8e58U, 0x9fd1U, 0xeb6eU, 0xfae7U, 0xc87cU, 0xd9f5U,
60 | 0x3183U, 0x200aU, 0x1291U, 0x0318U, 0x77a7U, 0x662eU, 0x54b5U, 0x453cU,
61 | 0xbdcbU, 0xac42U, 0x9ed9U, 0x8f50U, 0xfbefU, 0xea66U, 0xd8fdU, 0xc974U,
62 | 0x4204U, 0x538dU, 0x6116U, 0x709fU, 0x0420U, 0x15a9U, 0x2732U, 0x36bbU,
63 | 0xce4cU, 0xdfc5U, 0xed5eU, 0xfcd7U, 0x8868U, 0x99e1U, 0xab7aU, 0xbaf3U,
64 | 0x5285U, 0x430cU, 0x7197U, 0x601eU, 0x14a1U, 0x0528U, 0x37b3U, 0x263aU,
65 | 0xdecdU, 0xcf44U, 0xfddfU, 0xec56U, 0x98e9U, 0x8960U, 0xbbfbU, 0xaa72U,
66 | 0x6306U, 0x728fU, 0x4014U, 0x519dU, 0x2522U, 0x34abU, 0x0630U, 0x17b9U,
67 | 0xef4eU, 0xfec7U, 0xcc5cU, 0xddd5U, 0xa96aU, 0xb8e3U, 0x8a78U, 0x9bf1U,
68 | 0x7387U, 0x620eU, 0x5095U, 0x411cU, 0x35a3U, 0x242aU, 0x16b1U, 0x0738U,
69 | 0xffcfU, 0xee46U, 0xdcddU, 0xcd54U, 0xb9ebU, 0xa862U, 0x9af9U, 0x8b70U,
70 | 0x8408U, 0x9581U, 0xa71aU, 0xb693U, 0xc22cU, 0xd3a5U, 0xe13eU, 0xf0b7U,
71 | 0x0840U, 0x19c9U, 0x2b52U, 0x3adbU, 0x4e64U, 0x5fedU, 0x6d76U, 0x7cffU,
72 | 0x9489U, 0x8500U, 0xb79bU, 0xa612U, 0xd2adU, 0xc324U, 0xf1bfU, 0xe036U,
73 | 0x18c1U, 0x0948U, 0x3bd3U, 0x2a5aU, 0x5ee5U, 0x4f6cU, 0x7df7U, 0x6c7eU,
74 | 0xa50aU, 0xb483U, 0x8618U, 0x9791U, 0xe32eU, 0xf2a7U, 0xc03cU, 0xd1b5U,
75 | 0x2942U, 0x38cbU, 0x0a50U, 0x1bd9U, 0x6f66U, 0x7eefU, 0x4c74U, 0x5dfdU,
76 | 0xb58bU, 0xa402U, 0x9699U, 0x8710U, 0xf3afU, 0xe226U, 0xd0bdU, 0xc134U,
77 | 0x39c3U, 0x284aU, 0x1ad1U, 0x0b58U, 0x7fe7U, 0x6e6eU, 0x5cf5U, 0x4d7cU,
78 | 0xc60cU, 0xd785U, 0xe51eU, 0xf497U, 0x8028U, 0x91a1U, 0xa33aU, 0xb2b3U,
79 | 0x4a44U, 0x5bcdU, 0x6956U, 0x78dfU, 0x0c60U, 0x1de9U, 0x2f72U, 0x3efbU,
80 | 0xd68dU, 0xc704U, 0xf59fU, 0xe416U, 0x90a9U, 0x8120U, 0xb3bbU, 0xa232U,
81 | 0x5ac5U, 0x4b4cU, 0x79d7U, 0x685eU, 0x1ce1U, 0x0d68U, 0x3ff3U, 0x2e7aU,
82 | 0xe70eU, 0xf687U, 0xc41cU, 0xd595U, 0xa12aU, 0xb0a3U, 0x8238U, 0x93b1U,
83 | 0x6b46U, 0x7acfU, 0x4854U, 0x59ddU, 0x2d62U, 0x3cebU, 0x0e70U, 0x1ff9U,
84 | 0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
85 | 0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U };
86 |
87 |
88 | int max(int x, int y)
89 | {
90 | if (x > y)
91 | return x;
92 | else
93 | return y;
94 | }
95 |
96 | void process_signal(int sig)
97 | {
98 | static uint32_t c1 = 0;
99 | static uint32_t c2 = 0;
100 | if(sig == SIGINT){
101 | fprintf(stderr, "\n\nShutting down link\n");
102 | memcpy(buf, callsign, 8);
103 | buf[8] = CLIENT_MOD;
104 | buf[9] = ' ';
105 | buf[10] = 0x00;
106 | sendto(udp1, buf, 11, 0, (const struct sockaddr *)&host1, sizeof(host1));
107 | sendto(udp2, buf, 11, 0, (const struct sockaddr *)&host2, sizeof(host2));
108 | #ifdef DEBUG_SEND
109 | fprintf(stderr, "SEND BOTH: ");
110 | for(int i = 0; i < 11; ++i){
111 | fprintf(stderr, "%02x ", buf[i]);
112 | }
113 | fprintf(stderr, "\n");
114 | fflush(stderr);
115 | #endif
116 | close(udp1);
117 | close(udp2);
118 | exit(EXIT_SUCCESS);
119 | }
120 | if(sig == SIGALRM){
121 | if(c1 != host1_cnt){
122 | c1 = host1_cnt;
123 | }
124 | else{
125 | c1 = host1_cnt = 0;
126 | host1_connect = 1;
127 | fprintf(stderr, "%s ping timeout\n", ref1);
128 | }
129 | if(c2 != host2_cnt){
130 | c2 = host2_cnt;
131 | }
132 | else{
133 | c2 = host2_cnt = 0;
134 | host2_connect = 1;
135 | fprintf(stderr, "%s ping timeout\n", ref2);
136 | }
137 | alarm(15);
138 | }
139 | }
140 |
141 | void addCCITT161(unsigned char *in, unsigned int length)
142 | {
143 |
144 | union C{
145 | uint16_t crc16;
146 | uint8_t crc8[2U];
147 | } c;
148 |
149 |
150 | c.crc16 = 0xFFFFU;
151 |
152 | for (unsigned int i = 0U; i < (length - 2U); i++)
153 | c.crc16 = (c.crc8[1U]) ^ CCITT16_TABLE1[c.crc8[0U] ^ in[i]];
154 |
155 | c.crc16 = ~(c.crc16);
156 |
157 | in[length - 2U] = c.crc8[0U];
158 | in[length - 1U] = c.crc8[1U];
159 | }
160 |
161 | int main(int argc, char **argv)
162 | {
163 | struct sockaddr_in rx;
164 | struct hostent *hp;
165 | char *mod1;
166 | char *mod2;
167 | char *host1_url;
168 | char *host2_url;
169 | int host1_port;
170 | int host2_port;
171 | socklen_t l = sizeof(host1);
172 | int rxlen;
173 | int r;
174 | int udprx,maxudp;
175 | uint16_t streamid = 0;
176 | const uint8_t header[4] = {0x44,0x53,0x56,0x54}; //packet header
177 |
178 | if(argc != 4){
179 | fprintf(stderr, "Usage: xrfcon [CALLSIGN] [XRFName1:MOD1:XRFHost1IP:PORT] [XRFName2:MOD2:XRFHost2IP:PORT]\n");
180 | return 0;
181 | }
182 | else{
183 | memset(callsign, ' ', 8);
184 | memcpy(callsign, argv[1], (strlen(argv[1])<8)?strlen(argv[1]):8);
185 |
186 | ref1 = strtok(argv[2], ":");
187 | mod1 = strtok(NULL, ":");
188 | host1_url = strtok(NULL, ":");
189 | host1_port = atoi(strtok(NULL, ":"));
190 |
191 | ref2= strtok(argv[3], ":");
192 | mod2 = strtok(NULL, ":");
193 | host2_url = strtok(NULL, ":");
194 | host2_port = atoi(strtok(NULL, ":"));
195 |
196 | printf("XRF1: %s%c %s:%d\n", ref1, mod1[0], host1_url, host1_port);
197 | printf("XRF2: %s%c %s:%d\n", ref2, mod2[0], host2_url, host2_port);
198 | }
199 |
200 | signal(SIGINT, process_signal); //Handle CTRL-C gracefully
201 | signal(SIGALRM, process_signal); //Watchdog
202 |
203 | if ((udp1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
204 | perror("cannot create socket\n");
205 | return 0;
206 | }
207 | if ((udp2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
208 | perror("cannot create socket\n");
209 | return 0;
210 | }
211 |
212 | maxudp = max(udp1, udp2) + 1;
213 |
214 | #ifdef XRF1_DXRFD_COMPAT
215 | memset((char *)&host1, 0, sizeof(host1));
216 | host1.sin_family = AF_INET;
217 | host1.sin_port = htons(30001);
218 | host1.sin_addr.s_addr = htonl(INADDR_ANY);
219 | if ( bind(udp1, (struct sockaddr *)&host1, sizeof(host1)) == -1 ) {
220 | fprintf(stderr, "error while binding the socket on port 30001\n");
221 | return 0;
222 | }
223 | #endif
224 |
225 | memset((char *)&host1, 0, sizeof(host1));
226 | host1.sin_family = AF_INET;
227 | host1.sin_port = htons(host1_port);
228 |
229 | memset((char *)&host2, 0, sizeof(host2));
230 | host2.sin_family = AF_INET;
231 | host2.sin_port = htons(host2_port);
232 |
233 | hp = gethostbyname(host1_url);
234 | if (!hp) {
235 | fprintf(stderr, "could not resolve %s\n", host1_url);
236 | return 0;
237 | }
238 | memcpy((void *)&host1.sin_addr, hp->h_addr_list[0], hp->h_length);
239 |
240 | hp = gethostbyname(host2_url);
241 | if (!hp) {
242 | fprintf(stderr, "could not resolve %s\n", host2_url);
243 | return 0;
244 | }
245 | memcpy((void *)&host2.sin_addr, hp->h_addr_list[0], hp->h_length);
246 | host1_cnt = 0;
247 | host2_cnt = 0;
248 | host1_connect = 1;
249 | host2_connect = 1;
250 | alarm(15);
251 |
252 | while (1) {
253 | if(host1_connect){
254 | host1_connect = 0;
255 | memcpy(buf, callsign, 8);
256 | buf[8] = CLIENT_MOD;
257 | buf[9] = mod1[0];
258 | buf[10] = 0x00;
259 | sendto(udp1, buf, 11, 0, (const struct sockaddr *)&host1, sizeof(host1));
260 | fprintf(stderr, "Connecting to %s...\n", ref1);
261 | #ifdef DEBUG_SEND
262 | fprintf(stderr, "SEND %s: ", ref1);
263 | for(int i = 0; i < 11; ++i){
264 | fprintf(stderr, "%02x ", buf[i]);
265 | }
266 | fprintf(stderr, "\n");
267 | fflush(stderr);
268 | #endif
269 | }
270 | if(host2_connect){
271 | host2_connect = 0;
272 | memcpy(buf, callsign, 8);
273 | buf[8] = CLIENT_MOD;
274 | buf[9] = mod2[0];
275 | buf[10] = 0x00;
276 | sendto(udp2, buf, 11, 0, (const struct sockaddr *)&host2, sizeof(host2));
277 | fprintf(stderr, "Connecting to %s...\n", ref2);
278 | #ifdef DEBUG_SEND
279 | fprintf(stderr, "SEND %s: ", ref2);
280 | for(int i = 0; i < 11; ++i){
281 | fprintf(stderr, "%02x ", buf[i]);
282 | }
283 | fprintf(stderr, "\n");
284 | fflush(stderr);
285 | #endif
286 | }
287 | FD_ZERO(&udpset);
288 | FD_SET(udp1, &udpset);
289 | FD_SET(udp2, &udpset);
290 | r = select(maxudp, &udpset, NULL, NULL, NULL);
291 | //fprintf(stderr, "Select returned r == %d\n", r);
292 | rxlen = 0;
293 | if(r > 0){
294 | if(FD_ISSET(udp1, &udpset)) {
295 | rxlen = recvfrom(udp1, buf, BUFSIZE, 0, (struct sockaddr *)&rx, &l);
296 | udprx = udp1;
297 | }
298 | else if(FD_ISSET(udp2, &udpset)) {
299 | rxlen = recvfrom(udp2, buf, BUFSIZE, 0, (struct sockaddr *)&rx, &l);
300 | udprx = udp2;
301 | }
302 | }
303 | #ifdef DEBUG_RECV
304 | if(rxlen){
305 | if(udprx == udp1){
306 | fprintf(stderr, "RECV %s: ", ref1);
307 | }
308 | else if(udprx == udp2){
309 | fprintf(stderr, "RECV %s: ", ref2);
310 | }
311 | for(int i = 0; i < rxlen; ++i){
312 | fprintf(stderr, "%02x ", buf[i]);
313 | }
314 | fprintf(stderr, "\n");
315 | fflush(stderr);
316 | }
317 | #endif
318 | if(rxlen == 9){ //keep-alive
319 | memcpy(buf, callsign, 8);
320 | buf[8] = 0x00;
321 | sendto(udprx, buf, 9, 0, (const struct sockaddr *)&rx, sizeof(rx));
322 |
323 | if( (udprx == udp1) && (rx.sin_addr.s_addr == host1.sin_addr.s_addr) ){
324 | ++host1_cnt;
325 | }
326 | else if( (udprx == udp2) && (rx.sin_addr.s_addr == host2.sin_addr.s_addr) ){
327 | ++host2_cnt;
328 | }
329 | #ifdef DEBUG_SEND
330 | if(udprx == udp1){
331 | fprintf(stderr, "SEND %s: ", ref1);
332 | }
333 | else if(udprx == udp2){
334 | fprintf(stderr, "SEND %s: ", ref2);
335 | }
336 | for(int i = 0; i < 9; ++i){
337 | fprintf(stderr, "%02x ", buf[i]);
338 | }
339 | fprintf(stderr, "\n");
340 | fflush(stderr);
341 | #endif
342 | }
343 | if((rxlen == 0x38) && (!memcmp(&buf[0], header, 4))) { //dv header
344 | for(int i = 0; i < 4; ++i){
345 | if((buf[0x32+i] > 0x20) && (buf[0x32+i] < 0x30)){
346 | buf[0x32+i] = 0x20;
347 | }
348 | else if((buf[0x32+i] > 0x39) && (buf[0x32+i] < 0x41)){
349 | buf[0x32+i] = 0x20;
350 | }
351 | else if((buf[0x32+i] > 0x5a) && (buf[0x32+i] < 0x61)){
352 | buf[0x32+i] = 0x20;
353 | }
354 | else if(buf[0x32+i] > 0x7a) {
355 | buf[0x32+i] = 0x20;
356 | }
357 | }
358 |
359 | if( (udprx == udp1) && (rx.sin_addr.s_addr == host1.sin_addr.s_addr) && !memcmp(&buf[18], ref1, 6) && (buf[25] == mod1[0]) ){
360 | memcpy(&buf[18], ref2, 6);
361 | buf[24] = ' ';
362 | buf[25] = mod2[0];
363 | streamid = (buf[12] << 8) | (buf[13] & 0xff);
364 | addCCITT161(&buf[15], 41);
365 | sendto(udp2, buf, 0x38, 0, (const struct sockaddr *)&host2, sizeof(host2));
366 | #ifdef DEBUG_SEND
367 | fprintf(stderr, "SEND %s: ", ref2);
368 | for(int i = 0; i < 0x38; ++i){
369 | fprintf(stderr, "%02x ", buf[i]);
370 | }
371 | fprintf(stderr, "\n");
372 | fflush(stderr);
373 | #endif
374 | }
375 | else if( (udprx == udp2) && (rx.sin_addr.s_addr == host2.sin_addr.s_addr) && !memcmp(&buf[18], ref2, 6) && (buf[25] == mod2[0]) ){
376 | memcpy(&buf[18], ref1, 6);
377 | buf[24] = ' ';
378 | buf[25] = mod1[0];
379 | streamid = (buf[12] << 8) | (buf[13] & 0xff);
380 | addCCITT161(&buf[15], 41);
381 | sendto(udp1, buf, 0x38, 0, (const struct sockaddr *)&host1, sizeof(host1));
382 | #ifdef DEBUG_SEND
383 | fprintf(stderr, "SEND %s: ", ref1);
384 | for(int i = 0; i < 0x38; ++i){
385 | fprintf(stderr, "%02x ", buf[i]);
386 | }
387 | fprintf(stderr, "\n");
388 | fflush(stderr);
389 | #endif
390 | }
391 | }
392 | if(rxlen == 0x1b){ //dv frame
393 | uint16_t s = (buf[12] << 8) | (buf[13] & 0xff);
394 | if(s == streamid){
395 | if( (udprx == udp1) && (rx.sin_addr.s_addr == host1.sin_addr.s_addr) ){
396 | sendto(udp2, buf, 0x1b, 0, (const struct sockaddr *)&host2, sizeof(host2));
397 | #ifdef DEBUG_SEND
398 | fprintf(stderr, "SEND %s: ", ref2);
399 | for(int i = 0; i < 0x1b; ++i){
400 | fprintf(stderr, "%02x ", buf[i]);
401 | }
402 | fprintf(stderr, "\n");
403 | fflush(stderr);
404 | #endif
405 | }
406 | else if( (udprx == udp2) && (rx.sin_addr.s_addr == host2.sin_addr.s_addr) ){
407 | sendto(udp1, buf, 0x1b, 0, (const struct sockaddr *)&host1, sizeof(host1));
408 | #ifdef DEBUG_SEND
409 | fprintf(stderr, "SEND %s: ", ref1);
410 | for(int i = 0; i < 0x1b; ++i){
411 | fprintf(stderr, "%02x ", buf[i]);
412 | }
413 | fprintf(stderr, "\n");
414 | fflush(stderr);
415 | #endif
416 | }
417 | }
418 | }
419 | }
420 | }
421 |
--------------------------------------------------------------------------------
/refcon.c:
--------------------------------------------------------------------------------
1 | /*
2 | RefCon - DPlus Reflector Connector
3 | Copyright (C) 2019 Doug McLain
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #define BUFSIZE 2048
34 | #define DEBUG_SEND
35 | #define DEBUG_RECV
36 |
37 | char *ref1;
38 | char *ref2;
39 | int udp1;
40 | int udp2;
41 | fd_set udpset;
42 | struct sockaddr_in host1;
43 | struct sockaddr_in host2;
44 | uint8_t buf[BUFSIZE];
45 | uint32_t host1_cnt;
46 | uint32_t host2_cnt;
47 | uint8_t host1_connect;
48 | uint8_t host2_connect;
49 |
50 | const uint16_t CCITT16_TABLE1[] = {
51 | 0x0000U, 0x1189U, 0x2312U, 0x329bU, 0x4624U, 0x57adU, 0x6536U, 0x74bfU,
52 | 0x8c48U, 0x9dc1U, 0xaf5aU, 0xbed3U, 0xca6cU, 0xdbe5U, 0xe97eU, 0xf8f7U,
53 | 0x1081U, 0x0108U, 0x3393U, 0x221aU, 0x56a5U, 0x472cU, 0x75b7U, 0x643eU,
54 | 0x9cc9U, 0x8d40U, 0xbfdbU, 0xae52U, 0xdaedU, 0xcb64U, 0xf9ffU, 0xe876U,
55 | 0x2102U, 0x308bU, 0x0210U, 0x1399U, 0x6726U, 0x76afU, 0x4434U, 0x55bdU,
56 | 0xad4aU, 0xbcc3U, 0x8e58U, 0x9fd1U, 0xeb6eU, 0xfae7U, 0xc87cU, 0xd9f5U,
57 | 0x3183U, 0x200aU, 0x1291U, 0x0318U, 0x77a7U, 0x662eU, 0x54b5U, 0x453cU,
58 | 0xbdcbU, 0xac42U, 0x9ed9U, 0x8f50U, 0xfbefU, 0xea66U, 0xd8fdU, 0xc974U,
59 | 0x4204U, 0x538dU, 0x6116U, 0x709fU, 0x0420U, 0x15a9U, 0x2732U, 0x36bbU,
60 | 0xce4cU, 0xdfc5U, 0xed5eU, 0xfcd7U, 0x8868U, 0x99e1U, 0xab7aU, 0xbaf3U,
61 | 0x5285U, 0x430cU, 0x7197U, 0x601eU, 0x14a1U, 0x0528U, 0x37b3U, 0x263aU,
62 | 0xdecdU, 0xcf44U, 0xfddfU, 0xec56U, 0x98e9U, 0x8960U, 0xbbfbU, 0xaa72U,
63 | 0x6306U, 0x728fU, 0x4014U, 0x519dU, 0x2522U, 0x34abU, 0x0630U, 0x17b9U,
64 | 0xef4eU, 0xfec7U, 0xcc5cU, 0xddd5U, 0xa96aU, 0xb8e3U, 0x8a78U, 0x9bf1U,
65 | 0x7387U, 0x620eU, 0x5095U, 0x411cU, 0x35a3U, 0x242aU, 0x16b1U, 0x0738U,
66 | 0xffcfU, 0xee46U, 0xdcddU, 0xcd54U, 0xb9ebU, 0xa862U, 0x9af9U, 0x8b70U,
67 | 0x8408U, 0x9581U, 0xa71aU, 0xb693U, 0xc22cU, 0xd3a5U, 0xe13eU, 0xf0b7U,
68 | 0x0840U, 0x19c9U, 0x2b52U, 0x3adbU, 0x4e64U, 0x5fedU, 0x6d76U, 0x7cffU,
69 | 0x9489U, 0x8500U, 0xb79bU, 0xa612U, 0xd2adU, 0xc324U, 0xf1bfU, 0xe036U,
70 | 0x18c1U, 0x0948U, 0x3bd3U, 0x2a5aU, 0x5ee5U, 0x4f6cU, 0x7df7U, 0x6c7eU,
71 | 0xa50aU, 0xb483U, 0x8618U, 0x9791U, 0xe32eU, 0xf2a7U, 0xc03cU, 0xd1b5U,
72 | 0x2942U, 0x38cbU, 0x0a50U, 0x1bd9U, 0x6f66U, 0x7eefU, 0x4c74U, 0x5dfdU,
73 | 0xb58bU, 0xa402U, 0x9699U, 0x8710U, 0xf3afU, 0xe226U, 0xd0bdU, 0xc134U,
74 | 0x39c3U, 0x284aU, 0x1ad1U, 0x0b58U, 0x7fe7U, 0x6e6eU, 0x5cf5U, 0x4d7cU,
75 | 0xc60cU, 0xd785U, 0xe51eU, 0xf497U, 0x8028U, 0x91a1U, 0xa33aU, 0xb2b3U,
76 | 0x4a44U, 0x5bcdU, 0x6956U, 0x78dfU, 0x0c60U, 0x1de9U, 0x2f72U, 0x3efbU,
77 | 0xd68dU, 0xc704U, 0xf59fU, 0xe416U, 0x90a9U, 0x8120U, 0xb3bbU, 0xa232U,
78 | 0x5ac5U, 0x4b4cU, 0x79d7U, 0x685eU, 0x1ce1U, 0x0d68U, 0x3ff3U, 0x2e7aU,
79 | 0xe70eU, 0xf687U, 0xc41cU, 0xd595U, 0xa12aU, 0xb0a3U, 0x8238U, 0x93b1U,
80 | 0x6b46U, 0x7acfU, 0x4854U, 0x59ddU, 0x2d62U, 0x3cebU, 0x0e70U, 0x1ff9U,
81 | 0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
82 | 0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U };
83 |
84 |
85 | int max(int x, int y)
86 | {
87 | if (x > y)
88 | return x;
89 | else
90 | return y;
91 | }
92 |
93 | void process_signal(int sig)
94 | {
95 | static uint32_t c1 = 0;
96 | static uint32_t c2 = 0;
97 | if(sig == SIGINT){
98 | fprintf(stderr, "\n\nShutting down link\n");
99 | buf[0] = 0x05;
100 | buf[1] = 0x00;
101 | buf[2] = 0x18;
102 | buf[3] = 0x00;
103 | buf[4] = 0x00;
104 | sendto(udp1, buf, 5, 0, (const struct sockaddr *)&host1, sizeof(host1));
105 | sendto(udp2, buf, 5, 0, (const struct sockaddr *)&host2, sizeof(host2));
106 | close(udp1);
107 | close(udp2);
108 | exit(EXIT_SUCCESS);
109 | }
110 | if(sig == SIGALRM){
111 | if(c1 != host1_cnt){
112 | c1 = host1_cnt;
113 | }
114 | else{
115 | c1 = host1_cnt = 0;
116 | host1_connect = 1;
117 | fprintf(stderr, "%s ping timeout\n", ref1);
118 | }
119 | if(c2 != host2_cnt){
120 | c2 = host2_cnt;
121 | }
122 | else{
123 | c2 = host2_cnt = 0;
124 | host2_connect = 1;
125 | fprintf(stderr, "%s ping timeout\n", ref2);
126 | }
127 | alarm(5);
128 | }
129 | }
130 |
131 | void addCCITT161(unsigned char *in, unsigned int length)
132 | {
133 |
134 | union C{
135 | uint16_t crc16;
136 | uint8_t crc8[2U];
137 | } c;
138 |
139 |
140 | c.crc16 = 0xFFFFU;
141 |
142 | for (unsigned int i = 0U; i < (length - 2U); i++)
143 | c.crc16 = (c.crc8[1U]) ^ CCITT16_TABLE1[c.crc8[0U] ^ in[i]];
144 |
145 | c.crc16 = ~(c.crc16);
146 |
147 | in[length - 2U] = c.crc8[0U];
148 | in[length - 1U] = c.crc8[1U];
149 | }
150 |
151 | int main(int argc, char **argv)
152 | {
153 | struct sockaddr_in rx;
154 | struct hostent *hp;
155 | char *mod1;
156 | char *mod2;
157 | char *host1_url;
158 | char *host2_url;
159 | int host1_port;
160 | int host2_port;
161 | char callsign[6U];
162 | socklen_t l = sizeof(host1);
163 | int rxlen;
164 | int r;
165 | int udprx,maxudp;
166 | uint16_t streamid = 0;
167 | const uint8_t header[5] = {0x80,0x44,0x53,0x56,0x54}; //DVSI packet header
168 |
169 | if(argc != 4){
170 | fprintf(stderr, "Usage: refcon [CALLSIGN] [REFName1:MOD1:REFHost1IP:PORT] [REFName2:MOD2:REFHost2IP:PORT]\n");
171 | return 0;
172 | }
173 | else{
174 | memset(callsign, ' ', 6);
175 | memcpy(callsign, argv[1], strlen(argv[1]));
176 |
177 | ref1 = strtok(argv[2], ":");
178 | mod1 = strtok(NULL, ":");
179 | host1_url = strtok(NULL, ":");
180 | host1_port = atoi(strtok(NULL, ":"));
181 |
182 | ref2= strtok(argv[3], ":");
183 | mod2 = strtok(NULL, ":");
184 | host2_url = strtok(NULL, ":");
185 | host2_port = atoi(strtok(NULL, ":"));
186 |
187 | printf("REF1: %s%c %s:%d\n", ref1, mod1[0], host1_url, host1_port);
188 | printf("REF2: %s%c %s:%d\n", ref2, mod2[0], host2_url, host2_port);
189 | }
190 |
191 | signal(SIGINT, process_signal); //Handle CTRL-C gracefully
192 | signal(SIGALRM, process_signal); //Watchdog
193 |
194 | if ((udp1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
195 | perror("cannot create socket\n");
196 | return 0;
197 | }
198 | if ((udp2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
199 | perror("cannot create socket\n");
200 | return 0;
201 | }
202 |
203 | maxudp = max(udp1, udp2) + 1;
204 |
205 | memset((char *)&host1, 0, sizeof(host1));
206 | host1.sin_family = AF_INET;
207 | host1.sin_port = htons(host1_port);
208 |
209 | memset((char *)&host2, 0, sizeof(host2));
210 | host2.sin_family = AF_INET;
211 | host2.sin_port = htons(host2_port);
212 |
213 | hp = gethostbyname(host1_url);
214 | if (!hp) {
215 | fprintf(stderr, "could not resolve %s\n", host1_url);
216 | return 0;
217 | }
218 | memcpy((void *)&host1.sin_addr, hp->h_addr_list[0], hp->h_length);
219 |
220 | hp = gethostbyname(host2_url);
221 | if (!hp) {
222 | fprintf(stderr, "could not resolve %s\n", host2_url);
223 | return 0;
224 | }
225 | memcpy((void *)&host2.sin_addr, hp->h_addr_list[0], hp->h_length);
226 | host1_cnt = 0;
227 | host2_cnt = 0;
228 | host1_connect = 1;
229 | host2_connect = 1;
230 | alarm(5);
231 |
232 | while (1) {
233 | if(host1_connect){
234 | host1_connect = 0;
235 | buf[0] = 0x05;
236 | buf[1] = 0x00;
237 | buf[2] = 0x18;
238 | buf[3] = 0x00;
239 | buf[4] = 0x01;
240 | sendto(udp1, buf, 5, 0, (const struct sockaddr *)&host1, sizeof(host1));
241 | fprintf(stderr, "Connecting to %s...\n", ref1);
242 | }
243 | if(host2_connect){
244 | host2_connect = 0;
245 | buf[0] = 0x05;
246 | buf[1] = 0x00;
247 | buf[2] = 0x18;
248 | buf[3] = 0x00;
249 | buf[4] = 0x01;
250 | sendto(udp2, buf, 5, 0, (const struct sockaddr *)&host2, sizeof(host2));
251 | fprintf(stderr, "Connecting to %s...\n", ref2);
252 | }
253 | FD_ZERO(&udpset);
254 | FD_SET(udp1, &udpset);
255 | FD_SET(udp2, &udpset);
256 | r = select(maxudp, &udpset, NULL, NULL, NULL);
257 | //fprintf(stderr, "Select returned r == %d\n", r);
258 | rxlen = 0;
259 | if(r > 0){
260 | if(FD_ISSET(udp1, &udpset)) {
261 | rxlen = recvfrom(udp1, buf, BUFSIZE, 0, (struct sockaddr *)&rx, &l);
262 | udprx = udp1;
263 | }
264 | else if(FD_ISSET(udp2, &udpset)) {
265 | rxlen = recvfrom(udp2, buf, BUFSIZE, 0, (struct sockaddr *)&rx, &l);
266 | udprx = udp2;
267 | }
268 | }
269 | #ifdef DEBUG_RECV
270 | if(rxlen){
271 | if(rx.sin_addr.s_addr == host1.sin_addr.s_addr){
272 | fprintf(stderr, "RECV %s: ", ref1);
273 | }
274 | else if(rx.sin_addr.s_addr == host2.sin_addr.s_addr){
275 | fprintf(stderr, "RECV %s: ", ref2);
276 | }
277 | for(int i = 0; i < rxlen; ++i){
278 | fprintf(stderr, "%02x ", buf[i]);
279 | }
280 | fprintf(stderr, "\n");
281 | fflush(stderr);
282 | }
283 | #endif
284 | if((rxlen == 5) && (buf[4] == 0x01)){
285 | srand(time(NULL));
286 | int x = (rand() % (999999 - 7245 + 1)) + 7245;
287 | char serial[9];
288 | sprintf(serial, "HS%06d", x);
289 | buf[0] = 0x1c;
290 | buf[1] = 0xc0;
291 | buf[2] = 0x04;
292 | buf[3] = 0x00;
293 | memcpy(&buf[4], callsign, 6);
294 | memset(&buf[10], 0, 10);
295 | memcpy(&buf[20], serial, 8);
296 | sendto(udprx, buf, 28, 0, (const struct sockaddr *)&rx, sizeof(rx));
297 | #ifdef DEBUG_SEND
298 | if(rx.sin_addr.s_addr == host1.sin_addr.s_addr){
299 | fprintf(stderr, "SEND %s: ", ref1);
300 | }
301 | else if(rx.sin_addr.s_addr == host2.sin_addr.s_addr){
302 | fprintf(stderr, "SEND %s: ", ref2);
303 | }
304 | for(int i = 0; i < 28; ++i){
305 | fprintf(stderr, "%02x ", buf[i]);
306 | }
307 | fprintf(stderr, "\n");
308 | fflush(stderr);
309 | #endif
310 | }
311 | if(rxlen == 3){
312 | sendto(udprx, buf, 3, 0, (const struct sockaddr *)&rx, sizeof(rx));
313 |
314 | if(rx.sin_addr.s_addr == host1.sin_addr.s_addr){
315 | #ifdef DEBUG_SEND
316 | fprintf(stderr, "SEND %s: ", ref1);
317 | for(int i = 0; i < 3; ++i){
318 | fprintf(stderr, "%02x ", buf[i]);
319 | }
320 | fprintf(stderr, "\n");
321 | fflush(stderr);
322 | #endif
323 | ++host1_cnt;
324 | }
325 | else if(rx.sin_addr.s_addr == host2.sin_addr.s_addr){
326 | #ifdef DEBUG_SEND
327 | fprintf(stderr, "SEND %s: ", ref2);
328 | for(int i = 0; i < 3; ++i){
329 | fprintf(stderr, "%02x ", buf[i]);
330 | }
331 | fprintf(stderr, "\n");
332 | fflush(stderr);
333 | #endif
334 | ++host2_cnt;
335 | }
336 | /*
337 | for(int i = 0; i < 3; ++i){
338 | fprintf(stderr, "%02x ", buf[i]);
339 | }
340 | fprintf(stderr, "\n");
341 | fflush(stderr);
342 | */
343 | }
344 | if((rxlen == 0x3a) && (!memcmp(&buf[1], header, 5))) {
345 | for(int i = 0; i < 4; ++i){
346 | if((buf[0x34+i] > 0x20) && (buf[0x34+i] < 0x30)){
347 | buf[0x34+i] = 0x20;
348 | }
349 | else if((buf[0x34+i] > 0x39) && (buf[0x34+i] < 0x41)){
350 | buf[0x34+i] = 0x20;
351 | }
352 | else if((buf[0x34+i] > 0x5a) && (buf[0x34+i] < 0x61)){
353 | buf[0x34+i] = 0x20;
354 | }
355 | else if(buf[0x34+i] > 0x7a) {
356 | buf[0x34+i] = 0x20;
357 | }
358 | }
359 |
360 | if( (udprx == udp1) && (rx.sin_addr.s_addr == host1.sin_addr.s_addr) && !memcmp(&buf[0x14], ref1, 6) && (buf[0x1b] == mod1[0]) ){
361 | memcpy(&buf[20], ref2, 6);
362 | buf[26] = ' ';
363 | buf[27] = mod2[0];
364 | memcpy(&buf[28], callsign, 6);
365 | buf[34] = ' ';
366 | buf[35] = 'G';
367 | streamid = (buf[14] << 8) | (buf[15] & 0xff);
368 | addCCITT161(&buf[17], 41);
369 | sendto(udp2, buf, 0x3a, 0, (const struct sockaddr *)&host2, sizeof(host2));
370 | #ifdef DEBUG_SEND
371 | fprintf(stderr, "SEND %s: ", ref2);
372 | for(int i = 0; i < 0x3a; ++i){
373 | fprintf(stderr, "%02x ", buf[i]);
374 | }
375 | fprintf(stderr, "\n");
376 | fflush(stderr);
377 | #endif
378 | }
379 | else if( (udprx == udp1) && (rx.sin_addr.s_addr == host1.sin_addr.s_addr) && !memcmp(&buf[0x1c], ref1, 6) && (buf[0x23] == mod1[0]) ){
380 | memcpy(&buf[20], ref2, 6);
381 | buf[26] = ' ';
382 | buf[27] = mod2[0];
383 | memcpy(&buf[28], callsign, 6);
384 | buf[34] = ' ';
385 | buf[35] = 'G';
386 | streamid = (buf[14] << 8) | (buf[15] & 0xff);
387 | addCCITT161(&buf[17], 41);
388 | sendto(udp2, buf, 0x3a, 0, (const struct sockaddr *)&host2, sizeof(host2));
389 | #ifdef DEBUG_SEND
390 | fprintf(stderr, "SEND %s: ", ref2);
391 | for(int i = 0; i < 0x3a; ++i){
392 | fprintf(stderr, "%02x ", buf[i]);
393 | }
394 | fprintf(stderr, "\n");
395 | fflush(stderr);
396 | #endif
397 | }
398 | else if( (udprx == udp2) && (rx.sin_addr.s_addr == host2.sin_addr.s_addr) && !memcmp(&buf[0x14], ref2, 6) && (buf[0x1b] == mod2[0]) ){
399 | memcpy(&buf[20], ref1, 6);
400 | buf[26] = ' ';
401 | buf[27] = mod1[0];
402 | memcpy(&buf[28], callsign, 6);
403 | buf[34] = ' ';
404 | buf[35] = 'G';
405 | streamid = (buf[14] << 8) | (buf[15] & 0xff);
406 | addCCITT161(&buf[17], 41);
407 | sendto(udp1, buf, 0x3a, 0, (const struct sockaddr *)&host1, sizeof(host1));
408 | #ifdef DEBUG_SEND
409 | fprintf(stderr, "SEND %s: ", ref1);
410 | for(int i = 0; i < 0x3a; ++i){
411 | fprintf(stderr, "%02x ", buf[i]);
412 | }
413 | fprintf(stderr, "\n");
414 | fflush(stderr);
415 | #endif
416 | }
417 | }
418 | if((rxlen == 0x1d) || (rxlen == 0x20)){
419 | uint16_t s = (buf[14] << 8) | (buf[15] & 0xff);
420 | if(s == streamid){
421 | if( (udprx == udp1) && (rx.sin_addr.s_addr == host1.sin_addr.s_addr) ){
422 | sendto(udp2, buf, rxlen, 0, (const struct sockaddr *)&host2, sizeof(host2));
423 | #ifdef DEBUG_SEND
424 | fprintf(stderr, "SEND %s: ", ref2);
425 | for(int i = 0; i < rxlen; ++i){
426 | fprintf(stderr, "%02x ", buf[i]);
427 | }
428 | fprintf(stderr, "\n");
429 | fflush(stderr);
430 | #endif
431 | }
432 | else if( (udprx == udp2) && (rx.sin_addr.s_addr == host2.sin_addr.s_addr) ){
433 | sendto(udp1, buf, rxlen, 0, (const struct sockaddr *)&host1, sizeof(host1));
434 | #ifdef DEBUG_SEND
435 | fprintf(stderr, "SEND %s: ", ref1);
436 | for(int i = 0; i < rxlen; ++i){
437 | fprintf(stderr, "%02x ", buf[i]);
438 | }
439 | fprintf(stderr, "\n");
440 | fflush(stderr);
441 | #endif
442 | }
443 | }
444 | }
445 | }
446 | }
447 |
--------------------------------------------------------------------------------
/dmrcon.c:
--------------------------------------------------------------------------------
1 | /*
2 | DMRCon - DMR Server/TG Connector
3 | Copyright (C) 2019 Doug McLain
4 |
5 | Based on code from https://github.com/juribeparada/MMDVM_CM
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | #define BUFSIZE 2048
37 | #define TIMEOUT 60
38 | //#define DEBUG
39 |
40 | #define SWAP(n) (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
41 |
42 | #define K(I) roundConstants[I]
43 | static const uint32_t roundConstants[64] = {
44 | 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
45 | 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
46 | 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
47 | 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
48 | 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
49 | 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
50 | 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
51 | 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
52 | 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
53 | 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
54 | 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
55 | 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
56 | 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
57 | 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
58 | 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
59 | 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL,
60 | };
61 |
62 | const unsigned char POLY[] = {64U, 56U, 14U, 1U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U};
63 |
64 | const unsigned char EXP_TABLE[] = {
65 | 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1DU, 0x3AU, 0x74U, 0xE8U, 0xCDU, 0x87U, 0x13U, 0x26U,
66 | 0x4CU, 0x98U, 0x2DU, 0x5AU, 0xB4U, 0x75U, 0xEAU, 0xC9U, 0x8FU, 0x03U, 0x06U, 0x0CU, 0x18U, 0x30U, 0x60U, 0xC0U,
67 | 0x9DU, 0x27U, 0x4EU, 0x9CU, 0x25U, 0x4AU, 0x94U, 0x35U, 0x6AU, 0xD4U, 0xB5U, 0x77U, 0xEEU, 0xC1U, 0x9FU, 0x23U,
68 | 0x46U, 0x8CU, 0x05U, 0x0AU, 0x14U, 0x28U, 0x50U, 0xA0U, 0x5DU, 0xBAU, 0x69U, 0xD2U, 0xB9U, 0x6FU, 0xDEU, 0xA1U,
69 | 0x5FU, 0xBEU, 0x61U, 0xC2U, 0x99U, 0x2FU, 0x5EU, 0xBCU, 0x65U, 0xCAU, 0x89U, 0x0FU, 0x1EU, 0x3CU, 0x78U, 0xF0U,
70 | 0xFDU, 0xE7U, 0xD3U, 0xBBU, 0x6BU, 0xD6U, 0xB1U, 0x7FU, 0xFEU, 0xE1U, 0xDFU, 0xA3U, 0x5BU, 0xB6U, 0x71U, 0xE2U,
71 | 0xD9U, 0xAFU, 0x43U, 0x86U, 0x11U, 0x22U, 0x44U, 0x88U, 0x0DU, 0x1AU, 0x34U, 0x68U, 0xD0U, 0xBDU, 0x67U, 0xCEU,
72 | 0x81U, 0x1FU, 0x3EU, 0x7CU, 0xF8U, 0xEDU, 0xC7U, 0x93U, 0x3BU, 0x76U, 0xECU, 0xC5U, 0x97U, 0x33U, 0x66U, 0xCCU,
73 | 0x85U, 0x17U, 0x2EU, 0x5CU, 0xB8U, 0x6DU, 0xDAU, 0xA9U, 0x4FU, 0x9EU, 0x21U, 0x42U, 0x84U, 0x15U, 0x2AU, 0x54U,
74 | 0xA8U, 0x4DU, 0x9AU, 0x29U, 0x52U, 0xA4U, 0x55U, 0xAAU, 0x49U, 0x92U, 0x39U, 0x72U, 0xE4U, 0xD5U, 0xB7U, 0x73U,
75 | 0xE6U, 0xD1U, 0xBFU, 0x63U, 0xC6U, 0x91U, 0x3FU, 0x7EU, 0xFCU, 0xE5U, 0xD7U, 0xB3U, 0x7BU, 0xF6U, 0xF1U, 0xFFU,
76 | 0xE3U, 0xDBU, 0xABU, 0x4BU, 0x96U, 0x31U, 0x62U, 0xC4U, 0x95U, 0x37U, 0x6EU, 0xDCU, 0xA5U, 0x57U, 0xAEU, 0x41U,
77 | 0x82U, 0x19U, 0x32U, 0x64U, 0xC8U, 0x8DU, 0x07U, 0x0EU, 0x1CU, 0x38U, 0x70U, 0xE0U, 0xDDU, 0xA7U, 0x53U, 0xA6U,
78 | 0x51U, 0xA2U, 0x59U, 0xB2U, 0x79U, 0xF2U, 0xF9U, 0xEFU, 0xC3U, 0x9BU, 0x2BU, 0x56U, 0xACU, 0x45U, 0x8AU, 0x09U,
79 | 0x12U, 0x24U, 0x48U, 0x90U, 0x3DU, 0x7AU, 0xF4U, 0xF5U, 0xF7U, 0xF3U, 0xFBU, 0xEBU, 0xCBU, 0x8BU, 0x0BU, 0x16U,
80 | 0x2CU, 0x58U, 0xB0U, 0x7DU, 0xFAU, 0xE9U, 0xCFU, 0x83U, 0x1BU, 0x36U, 0x6CU, 0xD8U, 0xADU, 0x47U, 0x8EU, 0x01U,
81 | 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1DU, 0x3AU, 0x74U, 0xE8U, 0xCDU, 0x87U, 0x13U, 0x26U, 0x4CU,
82 | 0x98U, 0x2DU, 0x5AU, 0xB4U, 0x75U, 0xEAU, 0xC9U, 0x8FU, 0x03U, 0x06U, 0x0CU, 0x18U, 0x30U, 0x60U, 0xC0U, 0x9DU,
83 | 0x27U, 0x4EU, 0x9CU, 0x25U, 0x4AU, 0x94U, 0x35U, 0x6AU, 0xD4U, 0xB5U, 0x77U, 0xEEU, 0xC1U, 0x9FU, 0x23U, 0x46U,
84 | 0x8CU, 0x05U, 0x0AU, 0x14U, 0x28U, 0x50U, 0xA0U, 0x5DU, 0xBAU, 0x69U, 0xD2U, 0xB9U, 0x6FU, 0xDEU, 0xA1U, 0x5FU,
85 | 0xBEU, 0x61U, 0xC2U, 0x99U, 0x2FU, 0x5EU, 0xBCU, 0x65U, 0xCAU, 0x89U, 0x0FU, 0x1EU, 0x3CU, 0x78U, 0xF0U, 0xFDU,
86 | 0xE7U, 0xD3U, 0xBBU, 0x6BU, 0xD6U, 0xB1U, 0x7FU, 0xFEU, 0xE1U, 0xDFU, 0xA3U, 0x5BU, 0xB6U, 0x71U, 0xE2U, 0xD9U,
87 | 0xAFU, 0x43U, 0x86U, 0x11U, 0x22U, 0x44U, 0x88U, 0x0DU, 0x1AU, 0x34U, 0x68U, 0xD0U, 0xBDU, 0x67U, 0xCEU, 0x81U,
88 | 0x1FU, 0x3EU, 0x7CU, 0xF8U, 0xEDU, 0xC7U, 0x93U, 0x3BU, 0x76U, 0xECU, 0xC5U, 0x97U, 0x33U, 0x66U, 0xCCU, 0x85U,
89 | 0x17U, 0x2EU, 0x5CU, 0xB8U, 0x6DU, 0xDAU, 0xA9U, 0x4FU, 0x9EU, 0x21U, 0x42U, 0x84U, 0x15U, 0x2AU, 0x54U, 0xA8U,
90 | 0x4DU, 0x9AU, 0x29U, 0x52U, 0xA4U, 0x55U, 0xAAU, 0x49U, 0x92U, 0x39U, 0x72U, 0xE4U, 0xD5U, 0xB7U, 0x73U, 0xE6U,
91 | 0xD1U, 0xBFU, 0x63U, 0xC6U, 0x91U, 0x3FU, 0x7EU, 0xFCU, 0xE5U, 0xD7U, 0xB3U, 0x7BU, 0xF6U, 0xF1U, 0xFFU, 0xE3U,
92 | 0xDBU, 0xABU, 0x4BU, 0x96U, 0x31U, 0x62U, 0xC4U, 0x95U, 0x37U, 0x6EU, 0xDCU, 0xA5U, 0x57U, 0xAEU, 0x41U, 0x82U,
93 | 0x19U, 0x32U, 0x64U, 0xC8U, 0x8DU, 0x07U, 0x0EU, 0x1CU, 0x38U, 0x70U, 0xE0U, 0xDDU, 0xA7U, 0x53U, 0xA6U, 0x51U,
94 | 0xA2U, 0x59U, 0xB2U, 0x79U, 0xF2U, 0xF9U, 0xEFU, 0xC3U, 0x9BU, 0x2BU, 0x56U, 0xACU, 0x45U, 0x8AU, 0x09U, 0x12U,
95 | 0x24U, 0x48U, 0x90U, 0x3DU, 0x7AU, 0xF4U, 0xF5U, 0xF7U, 0xF3U, 0xFBU, 0xEBU, 0xCBU, 0x8BU, 0x0BU, 0x16U, 0x2CU,
96 | 0x58U, 0xB0U, 0x7DU, 0xFAU, 0xE9U, 0xCFU, 0x83U, 0x1BU, 0x36U, 0x6CU, 0xD8U, 0xADU, 0x47U, 0x8EU, 0x01U, 0x00U
97 | };
98 |
99 | const unsigned char LOG_TABLE[] = {
100 | 0x00U, 0x00U, 0x01U, 0x19U, 0x02U, 0x32U, 0x1AU, 0xC6U, 0x03U, 0xDFU, 0x33U, 0xEEU, 0x1BU, 0x68U, 0xC7U, 0x4BU,
101 | 0x04U, 0x64U, 0xE0U, 0x0EU, 0x34U, 0x8DU, 0xEFU, 0x81U, 0x1CU, 0xC1U, 0x69U, 0xF8U, 0xC8U, 0x08U, 0x4CU, 0x71U,
102 | 0x05U, 0x8AU, 0x65U, 0x2FU, 0xE1U, 0x24U, 0x0FU, 0x21U, 0x35U, 0x93U, 0x8EU, 0xDAU, 0xF0U, 0x12U, 0x82U, 0x45U,
103 | 0x1DU, 0xB5U, 0xC2U, 0x7DU, 0x6AU, 0x27U, 0xF9U, 0xB9U, 0xC9U, 0x9AU, 0x09U, 0x78U, 0x4DU, 0xE4U, 0x72U, 0xA6U,
104 | 0x06U, 0xBFU, 0x8BU, 0x62U, 0x66U, 0xDDU, 0x30U, 0xFDU, 0xE2U, 0x98U, 0x25U, 0xB3U, 0x10U, 0x91U, 0x22U, 0x88U,
105 | 0x36U, 0xD0U, 0x94U, 0xCEU, 0x8FU, 0x96U, 0xDBU, 0xBDU, 0xF1U, 0xD2U, 0x13U, 0x5CU, 0x83U, 0x38U, 0x46U, 0x40U,
106 | 0x1EU, 0x42U, 0xB6U, 0xA3U, 0xC3U, 0x48U, 0x7EU, 0x6EU, 0x6BU, 0x3AU, 0x28U, 0x54U, 0xFAU, 0x85U, 0xBAU, 0x3DU,
107 | 0xCAU, 0x5EU, 0x9BU, 0x9FU, 0x0AU, 0x15U, 0x79U, 0x2BU, 0x4EU, 0xD4U, 0xE5U, 0xACU, 0x73U, 0xF3U, 0xA7U, 0x57U,
108 | 0x07U, 0x70U, 0xC0U, 0xF7U, 0x8CU, 0x80U, 0x63U, 0x0DU, 0x67U, 0x4AU, 0xDEU, 0xEDU, 0x31U, 0xC5U, 0xFEU, 0x18U,
109 | 0xE3U, 0xA5U, 0x99U, 0x77U, 0x26U, 0xB8U, 0xB4U, 0x7CU, 0x11U, 0x44U, 0x92U, 0xD9U, 0x23U, 0x20U, 0x89U, 0x2EU,
110 | 0x37U, 0x3FU, 0xD1U, 0x5BU, 0x95U, 0xBCU, 0xCFU, 0xCDU, 0x90U, 0x87U, 0x97U, 0xB2U, 0xDCU, 0xFCU, 0xBEU, 0x61U,
111 | 0xF2U, 0x56U, 0xD3U, 0xABU, 0x14U, 0x2AU, 0x5DU, 0x9EU, 0x84U, 0x3CU, 0x39U, 0x53U, 0x47U, 0x6DU, 0x41U, 0xA2U,
112 | 0x1FU, 0x2DU, 0x43U, 0xD8U, 0xB7U, 0x7BU, 0xA4U, 0x76U, 0xC4U, 0x17U, 0x49U, 0xECU, 0x7FU, 0x0CU, 0x6FU, 0xF6U,
113 | 0x6CU, 0xA1U, 0x3BU, 0x52U, 0x29U, 0x9DU, 0x55U, 0xAAU, 0xFBU, 0x60U, 0x86U, 0xB1U, 0xBBU, 0xCCU, 0x3EU, 0x5AU,
114 | 0xCBU, 0x59U, 0x5FU, 0xB0U, 0x9CU, 0xA9U, 0xA0U, 0x51U, 0x0BU, 0xF5U, 0x16U, 0xEBU, 0x7AU, 0x75U, 0x2CU, 0xD7U,
115 | 0x4FU, 0xAEU, 0xD5U, 0xE9U, 0xE6U, 0xE7U, 0xADU, 0xE8U, 0x74U, 0xD6U, 0xF4U, 0xEAU, 0xA8U, 0x50U, 0x58U, 0xAFU
116 | };
117 |
118 | const unsigned int ENCODING_TABLE_2087[] =
119 | {0x0000U, 0xB08EU, 0xE093U, 0x501DU, 0x70A9U, 0xC027U, 0x903AU, 0x20B4U, 0x60DCU, 0xD052U, 0x804FU, 0x30C1U,
120 | 0x1075U, 0xA0FBU, 0xF0E6U, 0x4068U, 0x7036U, 0xC0B8U, 0x90A5U, 0x202BU, 0x009FU, 0xB011U, 0xE00CU, 0x5082U,
121 | 0x10EAU, 0xA064U, 0xF079U, 0x40F7U, 0x6043U, 0xD0CDU, 0x80D0U, 0x305EU, 0xD06CU, 0x60E2U, 0x30FFU, 0x8071U,
122 | 0xA0C5U, 0x104BU, 0x4056U, 0xF0D8U, 0xB0B0U, 0x003EU, 0x5023U, 0xE0ADU, 0xC019U, 0x7097U, 0x208AU, 0x9004U,
123 | 0xA05AU, 0x10D4U, 0x40C9U, 0xF047U, 0xD0F3U, 0x607DU, 0x3060U, 0x80EEU, 0xC086U, 0x7008U, 0x2015U, 0x909BU,
124 | 0xB02FU, 0x00A1U, 0x50BCU, 0xE032U, 0x90D9U, 0x2057U, 0x704AU, 0xC0C4U, 0xE070U, 0x50FEU, 0x00E3U, 0xB06DU,
125 | 0xF005U, 0x408BU, 0x1096U, 0xA018U, 0x80ACU, 0x3022U, 0x603FU, 0xD0B1U, 0xE0EFU, 0x5061U, 0x007CU, 0xB0F2U,
126 | 0x9046U, 0x20C8U, 0x70D5U, 0xC05BU, 0x8033U, 0x30BDU, 0x60A0U, 0xD02EU, 0xF09AU, 0x4014U, 0x1009U, 0xA087U,
127 | 0x40B5U, 0xF03BU, 0xA026U, 0x10A8U, 0x301CU, 0x8092U, 0xD08FU, 0x6001U, 0x2069U, 0x90E7U, 0xC0FAU, 0x7074U,
128 | 0x50C0U, 0xE04EU, 0xB053U, 0x00DDU, 0x3083U, 0x800DU, 0xD010U, 0x609EU, 0x402AU, 0xF0A4U, 0xA0B9U, 0x1037U,
129 | 0x505FU, 0xE0D1U, 0xB0CCU, 0x0042U, 0x20F6U, 0x9078U, 0xC065U, 0x70EBU, 0xA03DU, 0x10B3U, 0x40AEU, 0xF020U,
130 | 0xD094U, 0x601AU, 0x3007U, 0x8089U, 0xC0E1U, 0x706FU, 0x2072U, 0x90FCU, 0xB048U, 0x00C6U, 0x50DBU, 0xE055U,
131 | 0xD00BU, 0x6085U, 0x3098U, 0x8016U, 0xA0A2U, 0x102CU, 0x4031U, 0xF0BFU, 0xB0D7U, 0x0059U, 0x5044U, 0xE0CAU,
132 | 0xC07EU, 0x70F0U, 0x20EDU, 0x9063U, 0x7051U, 0xC0DFU, 0x90C2U, 0x204CU, 0x00F8U, 0xB076U, 0xE06BU, 0x50E5U,
133 | 0x108DU, 0xA003U, 0xF01EU, 0x4090U, 0x6024U, 0xD0AAU, 0x80B7U, 0x3039U, 0x0067U, 0xB0E9U, 0xE0F4U, 0x507AU,
134 | 0x70CEU, 0xC040U, 0x905DU, 0x20D3U, 0x60BBU, 0xD035U, 0x8028U, 0x30A6U, 0x1012U, 0xA09CU, 0xF081U, 0x400FU,
135 | 0x30E4U, 0x806AU, 0xD077U, 0x60F9U, 0x404DU, 0xF0C3U, 0xA0DEU, 0x1050U, 0x5038U, 0xE0B6U, 0xB0ABU, 0x0025U,
136 | 0x2091U, 0x901FU, 0xC002U, 0x708CU, 0x40D2U, 0xF05CU, 0xA041U, 0x10CFU, 0x307BU, 0x80F5U, 0xD0E8U, 0x6066U,
137 | 0x200EU, 0x9080U, 0xC09DU, 0x7013U, 0x50A7U, 0xE029U, 0xB034U, 0x00BAU, 0xE088U, 0x5006U, 0x001BU, 0xB095U,
138 | 0x9021U, 0x20AFU, 0x70B2U, 0xC03CU, 0x8054U, 0x30DAU, 0x60C7U, 0xD049U, 0xF0FDU, 0x4073U, 0x106EU, 0xA0E0U,
139 | 0x90BEU, 0x2030U, 0x702DU, 0xC0A3U, 0xE017U, 0x5099U, 0x0084U, 0xB00AU, 0xF062U, 0x40ECU, 0x10F1U, 0xA07FU,
140 | 0x80CBU, 0x3045U, 0x6058U, 0xD0D6U
141 | };
142 |
143 | const uint32_t ENCODING_TABLE_1676[] =
144 | {0x0000U, 0x0273U, 0x04E5U, 0x0696U, 0x09C9U, 0x0BBAU, 0x0D2CU, 0x0F5FU, 0x11E2U, 0x1391U, 0x1507U, 0x1774U,
145 | 0x182BU, 0x1A58U, 0x1CCEU, 0x1EBDU, 0x21B7U, 0x23C4U, 0x2552U, 0x2721U, 0x287EU, 0x2A0DU, 0x2C9BU, 0x2EE8U,
146 | 0x3055U, 0x3226U, 0x34B0U, 0x36C3U, 0x399CU, 0x3BEFU, 0x3D79U, 0x3F0AU, 0x411EU, 0x436DU, 0x45FBU, 0x4788U,
147 | 0x48D7U, 0x4AA4U, 0x4C32U, 0x4E41U, 0x50FCU, 0x528FU, 0x5419U, 0x566AU, 0x5935U, 0x5B46U, 0x5DD0U, 0x5FA3U,
148 | 0x60A9U, 0x62DAU, 0x644CU, 0x663FU, 0x6960U, 0x6B13U, 0x6D85U, 0x6FF6U, 0x714BU, 0x7338U, 0x75AEU, 0x77DDU,
149 | 0x7882U, 0x7AF1U, 0x7C67U, 0x7E14U, 0x804FU, 0x823CU, 0x84AAU, 0x86D9U, 0x8986U, 0x8BF5U, 0x8D63U, 0x8F10U,
150 | 0x91ADU, 0x93DEU, 0x9548U, 0x973BU, 0x9864U, 0x9A17U, 0x9C81U, 0x9EF2U, 0xA1F8U, 0xA38BU, 0xA51DU, 0xA76EU,
151 | 0xA831U, 0xAA42U, 0xACD4U, 0xAEA7U, 0xB01AU, 0xB269U, 0xB4FFU, 0xB68CU, 0xB9D3U, 0xBBA0U, 0xBD36U, 0xBF45U,
152 | 0xC151U, 0xC322U, 0xC5B4U, 0xC7C7U, 0xC898U, 0xCAEBU, 0xCC7DU, 0xCE0EU, 0xD0B3U, 0xD2C0U, 0xD456U, 0xD625U,
153 | 0xD97AU, 0xDB09U, 0xDD9FU, 0xDFECU, 0xE0E6U, 0xE295U, 0xE403U, 0xE670U, 0xE92FU, 0xEB5CU, 0xEDCAU, 0xEFB9U,
154 | 0xF104U, 0xF377U, 0xF5E1U, 0xF792U, 0xF8CDU, 0xFABEU, 0xFC28U, 0xFE5BU
155 | };
156 |
157 | #define F2(A,B,C) ( ( A & B ) | ( C & ( A | B ) ) )
158 | #define F1(E,F,G) ( G ^ ( E & ( F ^ G ) ) )
159 |
160 | struct sockaddr_in host1;
161 | struct sockaddr_in host2;
162 | int udp1;
163 | int udp2;
164 | fd_set udpset;
165 | uint8_t buf[BUFSIZE];
166 | uint32_t host1_cnt;
167 | uint32_t host2_cnt;
168 | char callsign[10U];
169 | int dmrid;
170 | uint32_t sha256_state[8U];
171 | uint32_t sha256_total[2];
172 | uint32_t sha256_buffer[32U];
173 | uint32_t sha256_buflen;
174 | bool bptc_rawData[196];
175 | bool bptc_deInterData[196];
176 | bool emb_raw[128U];
177 | bool emb_data[72U];
178 | int rx_srcid;
179 | int tx_tgid;
180 | int host1_tg;
181 | int host2_tg;
182 | char *host1_pw;
183 | char *host2_pw;
184 |
185 |
186 | static const unsigned char fillbuf[64] = { 0x80, 0 };
187 |
188 | #define DISCONNECTED 0
189 | #define CONNECTING 1
190 | #define DMR_AUTH 2
191 | #define DMR_CONF 3
192 | #define DMR_OPTS 4
193 | #define CONNECTED_RW 5
194 | #define CONNECTED_RO 6
195 |
196 | void byteToBitsBE(unsigned char byte, bool* bits)
197 | {
198 | bits[0U] = (byte & 0x80U) == 0x80U;
199 | bits[1U] = (byte & 0x40U) == 0x40U;
200 | bits[2U] = (byte & 0x20U) == 0x20U;
201 | bits[3U] = (byte & 0x10U) == 0x10U;
202 | bits[4U] = (byte & 0x08U) == 0x08U;
203 | bits[5U] = (byte & 0x04U) == 0x04U;
204 | bits[6U] = (byte & 0x02U) == 0x02U;
205 | bits[7U] = (byte & 0x01U) == 0x01U;
206 | }
207 |
208 | void bitsToByteBE(bool* bits, unsigned char* byte)
209 | {
210 | *byte = bits[0U] ? 0x80U : 0x00U;
211 | *byte |= bits[1U] ? 0x40U : 0x00U;
212 | *byte |= bits[2U] ? 0x20U : 0x00U;
213 | *byte |= bits[3U] ? 0x10U : 0x00U;
214 | *byte |= bits[4U] ? 0x08U : 0x00U;
215 | *byte |= bits[5U] ? 0x04U : 0x00U;
216 | *byte |= bits[6U] ? 0x02U : 0x00U;
217 | *byte |= bits[7U] ? 0x01U : 0x00U;
218 | }
219 |
220 | int max(int x, int y)
221 | {
222 | if (x > y)
223 | return x;
224 | else
225 | return y;
226 | }
227 |
228 | static inline void set_uint32(unsigned char* cp, uint32_t v)
229 | {
230 | memcpy(cp, &v, sizeof v);
231 | }
232 |
233 | void process_signal(int sig)
234 | {
235 | static uint32_t c1 = 0;
236 | static uint32_t c2 = 0;
237 | static int cnt = 0;
238 | uint8_t b[20];
239 | uint8_t out[55];
240 | if(sig == SIGINT){
241 | fprintf(stderr, "\n\nShutting down link\n");
242 | b[0] = 'R';
243 | b[1] = 'P';
244 | b[2] = 'T';
245 | b[3] = 'C';
246 | b[4] = 'L';
247 | b[5] = (dmrid >> 24) & 0xff;
248 | b[6] = (dmrid >> 16) & 0xff;
249 | b[7] = (dmrid >> 8) & 0xff;
250 | b[8] = (dmrid >> 0) & 0xff;
251 | sendto(udp1, b, 9, 0, (const struct sockaddr *)&host1, sizeof(host1));
252 | sendto(udp2, b, 9, 0, (const struct sockaddr *)&host2, sizeof(host2));
253 | #ifdef DEBUG
254 | fprintf(stderr, "SEND BOTH: ");
255 | for(int i = 0; i < 14; ++i){
256 | fprintf(stderr, "%02x ", b[i]);
257 | }
258 | fprintf(stderr, "\n");
259 | fflush(stderr);
260 | #endif
261 | close(udp1);
262 | close(udp2);
263 | exit(EXIT_SUCCESS);
264 | }
265 | if(sig == SIGALRM){
266 | ++cnt;
267 | char tag[] = { 'R','P','T','P','I','N','G' };
268 | memcpy(b, tag, 7);
269 | b[7] = (dmrid >> 24) & 0xff;
270 | b[8] = (dmrid >> 16) & 0xff;
271 | b[9] = (dmrid >> 8) & 0xff;
272 | b[10] = (dmrid >> 0) & 0xff;
273 | sendto(udp1, b, 11, 0, (const struct sockaddr *)&host1, sizeof(host1));
274 | sendto(udp2, b, 11, 0, (const struct sockaddr *)&host2, sizeof(host2));
275 | #ifdef DEBUG
276 | fprintf(stderr, "SEND BOTH: ");
277 | for(int i = 0; i < 11; ++i){
278 | fprintf(stderr, "%02x ", b[i]);
279 | }
280 | fprintf(stderr, "\n");
281 | fflush(stderr);
282 | #endif
283 | alarm(5);
284 | }
285 | }
286 |
287 | void hamming_encode15113_2(bool* d)
288 | {
289 | d[11] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8];
290 | d[12] = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[9];
291 | d[13] = d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[7] ^ d[9] ^ d[10];
292 | d[14] = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[10];
293 | }
294 |
295 | void hamming_encode1393(bool* d)
296 | {
297 | d[9] = d[0] ^ d[1] ^ d[3] ^ d[5] ^ d[6];
298 | d[10] = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7];
299 | d[11] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8];
300 | d[12] = d[0] ^ d[2] ^ d[4] ^ d[5] ^ d[8];
301 | }
302 |
303 | void bptc_encode(const unsigned char* in, unsigned char* out)
304 | {
305 | //Extract
306 | bool bData[96U];
307 | byteToBitsBE(in[0U], bData + 0U);
308 | byteToBitsBE(in[1U], bData + 8U);
309 | byteToBitsBE(in[2U], bData + 16U);
310 | byteToBitsBE(in[3U], bData + 24U);
311 | byteToBitsBE(in[4U], bData + 32U);
312 | byteToBitsBE(in[5U], bData + 40U);
313 | byteToBitsBE(in[6U], bData + 48U);
314 | byteToBitsBE(in[7U], bData + 56U);
315 | byteToBitsBE(in[8U], bData + 64U);
316 | byteToBitsBE(in[9U], bData + 72U);
317 | byteToBitsBE(in[10U], bData + 80U);
318 | byteToBitsBE(in[11U], bData + 88U);
319 |
320 | for (unsigned int i = 0U; i < 196U; i++)
321 | bptc_deInterData[i] = false;
322 |
323 | unsigned int pos = 0U;
324 | for (unsigned int a = 4U; a <= 11U; a++, pos++)
325 | bptc_deInterData[a] = bData[pos];
326 |
327 | for (unsigned int a = 16U; a <= 26U; a++, pos++)
328 | bptc_deInterData[a] = bData[pos];
329 |
330 | for (unsigned int a = 31U; a <= 41U; a++, pos++)
331 | bptc_deInterData[a] = bData[pos];
332 |
333 | for (unsigned int a = 46U; a <= 56U; a++, pos++)
334 | bptc_deInterData[a] = bData[pos];
335 |
336 | for (unsigned int a = 61U; a <= 71U; a++, pos++)
337 | bptc_deInterData[a] = bData[pos];
338 |
339 | for (unsigned int a = 76U; a <= 86U; a++, pos++)
340 | bptc_deInterData[a] = bData[pos];
341 |
342 | for (unsigned int a = 91U; a <= 101U; a++, pos++)
343 | bptc_deInterData[a] = bData[pos];
344 |
345 | for (unsigned int a = 106U; a <= 116U; a++, pos++)
346 | bptc_deInterData[a] = bData[pos];
347 |
348 | for (unsigned int a = 121U; a <= 131U; a++, pos++)
349 | bptc_deInterData[a] = bData[pos];
350 |
351 | //Error check
352 | for (unsigned int r = 0U; r < 9U; r++) {
353 | unsigned int pos = (r * 15U) + 1U;
354 | hamming_encode15113_2(bptc_deInterData + pos);
355 | }
356 |
357 | bool col[13U];
358 | for (unsigned int c = 0U; c < 15U; c++) {
359 | unsigned int pos = c + 1U;
360 | for (unsigned int a = 0U; a < 13U; a++) {
361 | col[a] = bptc_deInterData[pos];
362 | pos = pos + 15U;
363 | }
364 |
365 | hamming_encode1393(col);
366 |
367 | pos = c + 1U;
368 | for (unsigned int a = 0U; a < 13U; a++) {
369 | bptc_deInterData[pos] = col[a];
370 | pos = pos + 15U;
371 | }
372 | }
373 | //Interleave
374 | for (unsigned int i = 0U; i < 196U; i++)
375 | bptc_rawData[i] = false;
376 |
377 | for (unsigned int a = 0U; a < 196U; a++) {
378 | unsigned int interleaveSequence = (a * 181U) % 196U;
379 | bptc_rawData[interleaveSequence] = bptc_deInterData[a];
380 | }
381 | //Extract
382 | bitsToByteBE(bptc_rawData + 0U, &out[0U]);
383 | bitsToByteBE(bptc_rawData + 8U, &out[1U]);
384 | bitsToByteBE(bptc_rawData + 16U, &out[2U]);
385 | bitsToByteBE(bptc_rawData + 24U, &out[3U]);
386 | bitsToByteBE(bptc_rawData + 32U, &out[4U]);
387 | bitsToByteBE(bptc_rawData + 40U, &out[5U]);
388 | bitsToByteBE(bptc_rawData + 48U, &out[6U]);
389 | bitsToByteBE(bptc_rawData + 56U, &out[7U]);
390 | bitsToByteBE(bptc_rawData + 64U, &out[8U]);
391 | bitsToByteBE(bptc_rawData + 72U, &out[9U]);
392 | bitsToByteBE(bptc_rawData + 80U, &out[10U]);
393 | bitsToByteBE(bptc_rawData + 88U, &out[11U]);
394 |
395 | unsigned char byte;
396 | bitsToByteBE(bptc_rawData + 96U, &byte);
397 | out[12U] = (out[12U] & 0x3FU) | ((byte >> 0) & 0xC0U);
398 | out[20U] = (out[20U] & 0xFCU) | ((byte >> 4) & 0x03U);
399 |
400 | bitsToByteBE(bptc_rawData + 100U, &out[21U]);
401 | bitsToByteBE(bptc_rawData + 108U, &out[22U]);
402 | bitsToByteBE(bptc_rawData + 116U, &out[23U]);
403 | bitsToByteBE(bptc_rawData + 124U, &out[24U]);
404 | bitsToByteBE(bptc_rawData + 132U, &out[25U]);
405 | bitsToByteBE(bptc_rawData + 140U, &out[26U]);
406 | bitsToByteBE(bptc_rawData + 148U, &out[27U]);
407 | bitsToByteBE(bptc_rawData + 156U, &out[28U]);
408 | bitsToByteBE(bptc_rawData + 164U, &out[29U]);
409 | bitsToByteBE(bptc_rawData + 172U, &out[30U]);
410 | bitsToByteBE(bptc_rawData + 180U, &out[31U]);
411 | bitsToByteBE(bptc_rawData + 188U, &out[32U]);
412 | }
413 |
414 | unsigned char rs129_gmult(unsigned char a, unsigned char b)
415 | {
416 | if (a == 0U || b == 0U)
417 | return 0U;
418 |
419 | unsigned int i = LOG_TABLE[a];
420 | unsigned int j = LOG_TABLE[b];
421 |
422 | return EXP_TABLE[i + j];
423 | }
424 |
425 | void generate_header()
426 | {
427 | uint8_t sync_ms_data[] = { 0x0D,0x5D,0x7F,0x77,0xFD,0x75,0x70 };
428 | uint8_t payload[33];
429 |
430 | memset(payload, 0, sizeof(payload));
431 |
432 | uint8_t lc[12];
433 | {
434 | memset(lc, 0, sizeof(lc));
435 | //DESTID/TGID
436 | lc[3] = buf[8];
437 | lc[4] = buf[9];
438 | lc[5] = buf[10];
439 | //SRCID
440 | lc[6] = buf[5];
441 | lc[7] = buf[6];
442 | lc[8] = buf[7];
443 |
444 | uint8_t parity[4];
445 |
446 | //RS129 Encode begin
447 | for (unsigned int i = 0U; i < 3U + 1U; i++)
448 | parity[i] = 0x00U;
449 |
450 | for (unsigned int i = 0U; i < 9; i++) {
451 | unsigned char dbyte = lc[i] ^ parity[3U - 1U];
452 |
453 | for (int j = 3U - 1; j > 0; j--)
454 | parity[j] = parity[j - 1] ^ rs129_gmult(POLY[j], dbyte);
455 |
456 | parity[0] = rs129_gmult(POLY[0], dbyte);
457 | }
458 | //RS129 Encode end
459 |
460 | lc[9] = parity[2] ^ 0x96;
461 | lc[10] = parity[1] ^ 0x96;
462 | lc[11] = parity[0] ^ 0x96;
463 | }
464 |
465 | memcpy(payload+13, sync_ms_data, sizeof(sync_ms_data));
466 | {
467 | uint8_t slottype[3];
468 | memset(slottype, 0, sizeof(slottype));
469 | slottype[0] = (1 << 4) & 0xF0;
470 | slottype[0] |= (1 << 0) & 0x0FU;
471 | //Golay2087 encoding
472 | slottype[1U] = ENCODING_TABLE_2087[slottype[0]] & 0xFFU;
473 | slottype[2U] = ENCODING_TABLE_2087[slottype[0]] >> 8;
474 | payload[12U] = (payload[12U] & 0xC0U) | ((slottype[0U] >> 2) & 0x3FU);
475 | payload[13U] = (payload[13U] & 0x0FU) | ((slottype[0U] << 6) & 0xC0U) | ((slottype[1U] >> 2) & 0x30U);
476 | payload[19U] = (payload[19U] & 0xF0U) | ((slottype[1U] >> 2) & 0x0FU);
477 | payload[20U] = (payload[20U] & 0x03U) | ((slottype[1U] << 6) & 0xC0U) | ((slottype[2U] >> 2) & 0x3CU);
478 |
479 | }
480 | bptc_encode(lc, payload);
481 | memcpy(buf + 20, payload, 33);
482 | }
483 |
484 | void sha256_process_block(const unsigned char* buffer, unsigned int len)
485 | {
486 | const uint32_t* words = (uint32_t*)buffer;
487 | unsigned int nwords = len / sizeof(uint32_t);
488 | const uint32_t* endp = words + nwords;
489 | uint32_t x[16];
490 | uint32_t a = sha256_state[0];
491 | uint32_t b = sha256_state[1];
492 | uint32_t c = sha256_state[2];
493 | uint32_t d = sha256_state[3];
494 | uint32_t e = sha256_state[4];
495 | uint32_t f = sha256_state[5];
496 | uint32_t g = sha256_state[6];
497 | uint32_t h = sha256_state[7];
498 |
499 | sha256_total[0] += len;
500 |
501 | if (sha256_total[0] < len)
502 | ++sha256_total[1];
503 |
504 | #define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
505 | #define S0(x) (rol(x,25)^rol(x,14)^(x>>3))
506 | #define S1(x) (rol(x,15)^rol(x,13)^(x>>10))
507 | #define SS0(x) (rol(x,30)^rol(x,19)^rol(x,10))
508 | #define SS1(x) (rol(x,26)^rol(x,21)^rol(x,7))
509 |
510 | #define M(I) (tm = S1(x[(I-2)&0x0f]) + x[(I-7)&0x0f] + S0(x[(I-15)&0x0f]) + x[I&0x0f], x[I&0x0f] = tm)
511 |
512 | #define R(A,B,C,D,E,F,G,H,K,M) do { t0 = SS0(A) + F2(A,B,C); \
513 | t1 = H + SS1(E) + F1(E,F,G) + K + M; \
514 | D += t1; H = t0 + t1; \
515 | } while(0)
516 |
517 | while (words < endp) {
518 | uint32_t tm;
519 | uint32_t t0, t1;
520 |
521 | for (unsigned int t = 0U; t < 16U; t++) {
522 | x[t] = SWAP(*words);
523 | words++;
524 | }
525 |
526 | R( a, b, c, d, e, f, g, h, K( 0), x[ 0] );
527 | R( h, a, b, c, d, e, f, g, K( 1), x[ 1] );
528 | R( g, h, a, b, c, d, e, f, K( 2), x[ 2] );
529 | R( f, g, h, a, b, c, d, e, K( 3), x[ 3] );
530 | R( e, f, g, h, a, b, c, d, K( 4), x[ 4] );
531 | R( d, e, f, g, h, a, b, c, K( 5), x[ 5] );
532 | R( c, d, e, f, g, h, a, b, K( 6), x[ 6] );
533 | R( b, c, d, e, f, g, h, a, K( 7), x[ 7] );
534 | R( a, b, c, d, e, f, g, h, K( 8), x[ 8] );
535 | R( h, a, b, c, d, e, f, g, K( 9), x[ 9] );
536 | R( g, h, a, b, c, d, e, f, K(10), x[10] );
537 | R( f, g, h, a, b, c, d, e, K(11), x[11] );
538 | R( e, f, g, h, a, b, c, d, K(12), x[12] );
539 | R( d, e, f, g, h, a, b, c, K(13), x[13] );
540 | R( c, d, e, f, g, h, a, b, K(14), x[14] );
541 | R( b, c, d, e, f, g, h, a, K(15), x[15] );
542 | R( a, b, c, d, e, f, g, h, K(16), M(16) );
543 | R( h, a, b, c, d, e, f, g, K(17), M(17) );
544 | R( g, h, a, b, c, d, e, f, K(18), M(18) );
545 | R( f, g, h, a, b, c, d, e, K(19), M(19) );
546 | R( e, f, g, h, a, b, c, d, K(20), M(20) );
547 | R( d, e, f, g, h, a, b, c, K(21), M(21) );
548 | R( c, d, e, f, g, h, a, b, K(22), M(22) );
549 | R( b, c, d, e, f, g, h, a, K(23), M(23) );
550 | R( a, b, c, d, e, f, g, h, K(24), M(24) );
551 | R( h, a, b, c, d, e, f, g, K(25), M(25) );
552 | R( g, h, a, b, c, d, e, f, K(26), M(26) );
553 | R( f, g, h, a, b, c, d, e, K(27), M(27) );
554 | R( e, f, g, h, a, b, c, d, K(28), M(28) );
555 | R( d, e, f, g, h, a, b, c, K(29), M(29) );
556 | R( c, d, e, f, g, h, a, b, K(30), M(30) );
557 | R( b, c, d, e, f, g, h, a, K(31), M(31) );
558 | R( a, b, c, d, e, f, g, h, K(32), M(32) );
559 | R( h, a, b, c, d, e, f, g, K(33), M(33) );
560 | R( g, h, a, b, c, d, e, f, K(34), M(34) );
561 | R( f, g, h, a, b, c, d, e, K(35), M(35) );
562 | R( e, f, g, h, a, b, c, d, K(36), M(36) );
563 | R( d, e, f, g, h, a, b, c, K(37), M(37) );
564 | R( c, d, e, f, g, h, a, b, K(38), M(38) );
565 | R( b, c, d, e, f, g, h, a, K(39), M(39) );
566 | R( a, b, c, d, e, f, g, h, K(40), M(40) );
567 | R( h, a, b, c, d, e, f, g, K(41), M(41) );
568 | R( g, h, a, b, c, d, e, f, K(42), M(42) );
569 | R( f, g, h, a, b, c, d, e, K(43), M(43) );
570 | R( e, f, g, h, a, b, c, d, K(44), M(44) );
571 | R( d, e, f, g, h, a, b, c, K(45), M(45) );
572 | R( c, d, e, f, g, h, a, b, K(46), M(46) );
573 | R( b, c, d, e, f, g, h, a, K(47), M(47) );
574 | R( a, b, c, d, e, f, g, h, K(48), M(48) );
575 | R( h, a, b, c, d, e, f, g, K(49), M(49) );
576 | R( g, h, a, b, c, d, e, f, K(50), M(50) );
577 | R( f, g, h, a, b, c, d, e, K(51), M(51) );
578 | R( e, f, g, h, a, b, c, d, K(52), M(52) );
579 | R( d, e, f, g, h, a, b, c, K(53), M(53) );
580 | R( c, d, e, f, g, h, a, b, K(54), M(54) );
581 | R( b, c, d, e, f, g, h, a, K(55), M(55) );
582 | R( a, b, c, d, e, f, g, h, K(56), M(56) );
583 | R( h, a, b, c, d, e, f, g, K(57), M(57) );
584 | R( g, h, a, b, c, d, e, f, K(58), M(58) );
585 | R( f, g, h, a, b, c, d, e, K(59), M(59) );
586 | R( e, f, g, h, a, b, c, d, K(60), M(60) );
587 | R( d, e, f, g, h, a, b, c, K(61), M(61) );
588 | R( c, d, e, f, g, h, a, b, K(62), M(62) );
589 | R( b, c, d, e, f, g, h, a, K(63), M(63) );
590 |
591 | a = sha256_state[0] += a;
592 | b = sha256_state[1] += b;
593 | c = sha256_state[2] += c;
594 | d = sha256_state[3] += d;
595 | e = sha256_state[4] += e;
596 | f = sha256_state[5] += f;
597 | g = sha256_state[6] += g;
598 | h = sha256_state[7] += h;
599 | }
600 | }
601 |
602 | void sha256_generate(char *in, int len, char *out)
603 | {
604 | unsigned int bytes, size;
605 |
606 | sha256_state[0] = 0x6a09e667UL;
607 | sha256_state[1] = 0xbb67ae85UL;
608 | sha256_state[2] = 0x3c6ef372UL;
609 | sha256_state[3] = 0xa54ff53aUL;
610 | sha256_state[4] = 0x510e527fUL;
611 | sha256_state[5] = 0x9b05688cUL;
612 | sha256_state[6] = 0x1f83d9abUL;
613 | sha256_state[7] = 0x5be0cd19UL;
614 |
615 | sha256_total[0] = sha256_total[1] = 0;
616 | sha256_buflen = 0;
617 |
618 | if (sha256_buflen != 0U) {
619 | unsigned int left_over = sha256_buflen;
620 | unsigned int add = 128U - left_over > len ? len : 128U - left_over;
621 |
622 | memcpy(&((char*)sha256_buffer)[left_over], in, add);
623 | sha256_buflen += add;
624 |
625 | if (sha256_buflen > 64U) {
626 | sha256_process_block((unsigned char*)sha256_buffer, sha256_buflen & ~63U);
627 |
628 | sha256_buflen &= 63U;
629 |
630 | memcpy(sha256_buffer, &((char*)sha256_buffer)[(left_over + add) & ~63U], sha256_buflen);
631 | }
632 |
633 | in += add;
634 | len -= add;
635 | }
636 |
637 | if (len >= 64U) {
638 | sha256_process_block(in, len & ~63U);
639 | in += (len & ~63U);
640 | len &= 63U;
641 | }
642 | if (len > 0U) {
643 | unsigned int left_over = sha256_buflen;
644 |
645 | memcpy(&((char*)sha256_buffer)[left_over], in, len);
646 | left_over += len;
647 |
648 | if (left_over >= 64U) {
649 | sha256_process_block((unsigned char*)sha256_buffer, 64U);
650 | left_over -= 64U;
651 | memcpy(sha256_buffer, &sha256_buffer[16], left_over);
652 | }
653 |
654 | sha256_buflen = left_over;
655 | }
656 |
657 | bytes = sha256_buflen;
658 | size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4;
659 |
660 | sha256_total[0] += bytes;
661 |
662 | if (sha256_total[0] < bytes)
663 | ++sha256_total[1];
664 |
665 | set_uint32((unsigned char*)&sha256_buffer[size - 2], SWAP((sha256_total[1] << 3) | (sha256_total[0] >> 29)));
666 | set_uint32((unsigned char*)&sha256_buffer[size - 1], SWAP(sha256_total[0] << 3));
667 |
668 | memcpy(&((char*)sha256_buffer)[bytes], fillbuf, (size - 2) * 4 - bytes);
669 |
670 | sha256_process_block((unsigned char*)sha256_buffer, size * 4);
671 |
672 | for (unsigned int i = 0U; i < 8U; i++)
673 | set_uint32(out + i * sizeof(sha256_state[0]), SWAP(sha256_state[i]));
674 | }
675 |
676 | void lc_get_data(uint8_t *bytes)
677 | {
678 | bool pf, r;
679 | uint8_t fid, options;
680 | pf = (bytes[0U] & 0x80U) == 0x80U;
681 | r = (bytes[0U] & 0x40U) == 0x40U;
682 | fid = bytes[1U];
683 | options = bytes[2U];
684 |
685 | bytes[0U] = 0;
686 |
687 | if (pf)
688 | bytes[0U] |= 0x80U;
689 |
690 | if (r)
691 | bytes[0U] |= 0x40U;
692 |
693 | bytes[1U] = fid;
694 | bytes[2U] = options;
695 | bytes[3U] = tx_tgid >> 16;
696 | bytes[4U] = tx_tgid >> 8;
697 | bytes[5U] = tx_tgid >> 0;
698 | bytes[6U] = rx_srcid >> 16;
699 | bytes[7U] = rx_srcid >> 8;
700 | bytes[8U] = rx_srcid >> 0;
701 | }
702 |
703 | void lc_get_data_bits(bool* bits)
704 | {
705 | uint8_t bytes[9U];
706 | memset(bytes, 0, 9);
707 | lc_get_data(bytes);
708 |
709 | byteToBitsBE(bytes[0U], bits + 0U);
710 | byteToBitsBE(bytes[1U], bits + 8U);
711 | byteToBitsBE(bytes[2U], bits + 16U);
712 | byteToBitsBE(bytes[3U], bits + 24U);
713 | byteToBitsBE(bytes[4U], bits + 32U);
714 | byteToBitsBE(bytes[5U], bits + 40U);
715 | byteToBitsBE(bytes[6U], bits + 48U);
716 | byteToBitsBE(bytes[7U], bits + 56U);
717 | byteToBitsBE(bytes[8U], bits + 64U);
718 | }
719 |
720 | void encode16114(bool* d)
721 | {
722 | d[11] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8];
723 | d[12] = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[9];
724 | d[13] = d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[7] ^ d[9] ^ d[10];
725 | d[14] = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[10];
726 | d[15] = d[0] ^ d[2] ^ d[5] ^ d[6] ^ d[8] ^ d[9] ^ d[10];
727 | }
728 |
729 | void encode_qr1676(uint8_t* data)
730 | {
731 | uint32_t value = (data[0U] >> 1) & 0x7FU;
732 | uint32_t cksum = ENCODING_TABLE_1676[value];
733 |
734 | data[0U] = cksum >> 8;
735 | data[1U] = cksum & 0xFFU;
736 | }
737 |
738 | void encode_embedded_data()
739 | {
740 | uint32_t crc;
741 | unsigned short total = 0U;
742 |
743 | lc_get_data_bits(emb_data);
744 |
745 | for (unsigned int i = 0U; i < 72U; i += 8U) {
746 | unsigned char c;
747 | bitsToByteBE(emb_data + i, &c);
748 | total += c;
749 | }
750 |
751 | total %= 31U;
752 | crc = total;
753 |
754 | bool data[128U];
755 | memset(data, 0x00U, 128U * sizeof(bool));
756 |
757 | data[106U] = (crc & 0x01U) == 0x01U;
758 | data[90U] = (crc & 0x02U) == 0x02U;
759 | data[74U] = (crc & 0x04U) == 0x04U;
760 | data[58U] = (crc & 0x08U) == 0x08U;
761 | data[42U] = (crc & 0x10U) == 0x10U;
762 |
763 | uint32_t b = 0U;
764 | for (uint32_t a = 0U; a < 11U; a++, b++)
765 | data[a] = emb_data[b];
766 |
767 | for (uint32_t a = 16U; a < 27U; a++, b++)
768 | data[a] = emb_data[b];
769 |
770 | for (uint32_t a = 32U; a < 42U; a++, b++)
771 | data[a] = emb_data[b];
772 |
773 | for (uint32_t a = 48U; a < 58U; a++, b++)
774 | data[a] = emb_data[b];
775 |
776 | for (uint32_t a = 64U; a < 74U; a++, b++)
777 | data[a] = emb_data[b];
778 |
779 | for (uint32_t a = 80U; a < 90U; a++, b++)
780 | data[a] = emb_data[b];
781 |
782 | for (uint32_t a = 96U; a < 106U; a++, b++)
783 | data[a] = emb_data[b];
784 |
785 | for (uint32_t a = 0U; a < 112U; a += 16U)
786 | encode16114(data + a);
787 |
788 | for (uint32_t a = 0U; a < 16U; a++)
789 | data[a + 112U] = data[a + 0U] ^ data[a + 16U] ^ data[a + 32U] ^ data[a + 48U] ^ data[a + 64U] ^ data[a + 80U] ^ data[a + 96U];
790 |
791 | b = 0U;
792 | for (uint32_t a = 0U; a < 128U; a++) {
793 | emb_raw[a] = data[b];
794 | b += 16U;
795 | if (b > 127U)
796 | b -= 127U;
797 | }
798 | }
799 |
800 | uint8_t get_embedded_data(uint8_t* data, uint8_t n)
801 | {
802 | if (n >= 1U && n < 5U) {
803 | n--;
804 |
805 | bool bits[40U];
806 | memset(bits, 0x00U, 40U * sizeof(bool));
807 | memcpy(bits + 4U, emb_raw + n * 32U, 32U * sizeof(bool));
808 |
809 | uint8_t bytes[5U];
810 | bitsToByteBE(bits + 0U, &bytes[0U]);
811 | bitsToByteBE(bits + 8U, &bytes[1U]);
812 | bitsToByteBE(bits + 16U, &bytes[2U]);
813 | bitsToByteBE(bits + 24U, &bytes[3U]);
814 | bitsToByteBE(bits + 32U, &bytes[4U]);
815 |
816 | data[14U] = (data[14U] & 0xF0U) | (bytes[0U] & 0x0FU);
817 | data[15U] = bytes[1U];
818 | data[16U] = bytes[2U];
819 | data[17U] = bytes[3U];
820 | data[18U] = (data[18U] & 0x0FU) | (bytes[4U] & 0xF0U);
821 |
822 | switch (n) {
823 | case 0U:
824 | return 1U;
825 | case 3U:
826 | return 2U;
827 | default:
828 | return 3U;
829 | }
830 | } else {
831 | data[14U] &= 0xF0U;
832 | data[15U] = 0x00U;
833 | data[16U] = 0x00U;
834 | data[17U] = 0x00U;
835 | data[18U] &= 0x0FU;
836 |
837 | return 0U;
838 | }
839 | }
840 |
841 | void get_emb_data(uint8_t* data, uint8_t lcss)
842 | {
843 | uint8_t DMREMB[2U];
844 | uint8_t m_colorcode = 1;
845 | DMREMB[0U] = (m_colorcode << 4) & 0xF0U;
846 | //DMREMB[0U] |= m_PI ? 0x08U : 0x00U;
847 | DMREMB[0U] |= (lcss << 1) & 0x06U;
848 | DMREMB[1U] = 0x00U;
849 |
850 | encode_qr1676(DMREMB);
851 |
852 | data[13U] = (data[13U] & 0xF0U) | ((DMREMB[0U] >> 4U) & 0x0FU);
853 | data[14U] = (data[14U] & 0x0FU) | ((DMREMB[0U] << 4U) & 0xF0U);
854 | data[18U] = (data[18U] & 0xF0U) | ((DMREMB[1U] >> 4U) & 0x0FU);
855 | data[19U] = (data[19U] & 0x0FU) | ((DMREMB[1U] << 4U) & 0xF0U);
856 | }
857 |
858 | int process_connect(int connect_status, char *buf, int h)
859 | {
860 | char in[100];
861 | char out[400];
862 | int len = 0;
863 | char latitude[20U], longitude[20U];
864 | memset(in, 0, 100);
865 | memset(out, 0, 400);
866 |
867 | switch(connect_status){
868 | case CONNECTING:
869 | connect_status = DMR_AUTH;
870 | memcpy(in, &buf[6], 4);
871 | memcpy(out, "RPTK", 4);
872 | out[4] = (dmrid >> 24) & 0xff;
873 | out[5] = (dmrid >> 16) & 0xff;
874 | out[6] = (dmrid >> 8) & 0xff;
875 | out[7] = (dmrid >> 0) & 0xff;
876 |
877 | if(h == 1){
878 | memcpy(&in[4], host1_pw, strlen(host1_pw));
879 | sha256_generate(in, strlen(host1_pw) + sizeof(uint32_t), &out[8]);
880 | }
881 | else if(h == 2){
882 | memcpy(&in[4], host2_pw, strlen(host2_pw));
883 | sha256_generate(in, strlen(host2_pw) + sizeof(uint32_t), &out[8]);
884 | }
885 | //memcpy(&in[4], "passw0rd", 8);
886 | //sha256_generate(in, 8 + sizeof(uint32_t), &out[8]);
887 |
888 | len = 40;
889 | fprintf(stderr, "Sending auth to DMR%d...\n", h);
890 | break;
891 | case DMR_AUTH:
892 | connect_status = DMR_CONF;
893 | memcpy(out, "RPTC", 4);
894 | out[4] = (dmrid >> 24) & 0xff;
895 | out[5] = (dmrid >> 16) & 0xff;
896 | out[6] = (dmrid >> 8) & 0xff;
897 | out[7] = (dmrid >> 0) & 0xff;
898 | sprintf(latitude, "%08f", 50.0f);
899 | sprintf(longitude, "%09f", 3.0f);
900 | sprintf(&out[8], "%-8.8s%09u%09u%02u%02u%8.8s%9.9s%03d%-20.20s%-19.19s%c%-124.124s%-40.40s%-40.40s", callsign,
901 | 438800000, 438800000, 1, 1, latitude, longitude, 0, "London","England", '4', "www.qrz.com", "20190131", "MMDVM"); // 302 bytes
902 | len = 302;
903 | fprintf(stderr, "Sending conf to DMR%d...\n", h);
904 | break;
905 | case DMR_CONF:
906 | connect_status = CONNECTED_RW;
907 | memcpy(buf, "DMRD", 4);
908 | buf[4] = 0x00;
909 | buf[5] = (((dmrid>99999999)?dmrid/100:dmrid) >> 16) & 0xff;
910 | buf[6] = (((dmrid>99999999)?dmrid/100:dmrid) >> 8) & 0xff;
911 | buf[7] = (((dmrid>99999999)?dmrid/100:dmrid) >> 0) & 0xff;
912 | buf[11] = (dmrid >> 24) & 0xff;
913 | buf[12] = (dmrid >> 16) & 0xff;
914 | buf[13] = (dmrid >> 8) & 0xff;
915 | buf[14] = (dmrid >> 0) & 0xff;
916 | buf[15] = 0xa1;
917 | buf[16] = 0xb6;
918 | buf[17] = 0x01;
919 | buf[18] = 0x00;
920 | buf[19] = 0x00;
921 |
922 | if(h == 1){
923 | buf[8] = (host1_tg >> 16) & 0xff;
924 | buf[9] = (host1_tg >> 8) & 0xff;
925 | buf[10] = (host1_tg >> 0) & 0xff;
926 | }
927 | else{
928 | buf[8] = (host2_tg >> 16) & 0xff;
929 | buf[9] = (host2_tg >> 8) & 0xff;
930 | buf[10] = (host2_tg >> 0) & 0xff;
931 | }
932 | generate_header();
933 | memcpy(out, buf, 55);
934 | len = 55;
935 | fprintf(stderr, "Connected to DMR%d\n", h);
936 | break;
937 | }
938 | if(h == 1){
939 | sendto(udp1, out, len, 0, (const struct sockaddr *)&host1, sizeof(host1));
940 | #ifdef DEBUG
941 | fprintf(stderr, "SEND DMR1: ");
942 | for(int i = 0; i < len; ++i){
943 | fprintf(stderr, "%02x ", (uint8_t)out[i]);
944 | }
945 | fprintf(stderr, "\n");
946 | fflush(stderr);
947 | #endif
948 | }
949 | else{
950 | sendto(udp2, out, len, 0, (const struct sockaddr *)&host2, sizeof(host2));
951 | #ifdef DEBUG
952 | fprintf(stderr, "SEND DMR2: ");
953 | for(int i = 0; i < len; ++i){
954 | fprintf(stderr, "%02x ", (uint8_t)out[i]);
955 | }
956 | fprintf(stderr, "\n");
957 | fflush(stderr);
958 | #endif
959 | }
960 | return connect_status;
961 | }
962 |
963 | int main(int argc, char **argv)
964 | {
965 | struct sockaddr_in rx;
966 | struct hostent *hp;
967 | char * host1_url;
968 | char * host2_url;
969 | int host1_port;
970 | int host2_port;
971 | int rxlen;
972 | int len = 0;
973 | int reuse = 1;
974 | int r;
975 | int udprx,maxudp;
976 | socklen_t l = sizeof(host1);
977 | static uint64_t ping_cnt1 = 0;
978 | static uint64_t ping_cnt2 = 0;
979 | uint16_t streamid = 0;
980 | time_t pong_time1;
981 | time_t pong_time2;
982 |
983 | if(argc != 5){
984 | fprintf(stderr, "Usage: dmrcon [CALLSIGN] [DMRID] [DMRHost1IP:PORT:TG:PW] [DMRHost2IP:PORT:TG:PW]\n");
985 | return 0;
986 | }
987 | else{
988 | memset(callsign, ' ', 10);
989 | memcpy(callsign, argv[1], strlen(argv[1]));
990 | //memset(host1_pw, 0, 100);
991 | //memset(host2_pw, 0, 100);
992 | dmrid = atoi(argv[2]);
993 | host1_url = strtok(argv[3], ":");
994 | host1_port = atoi(strtok(NULL, ":"));
995 | host1_tg = atoi(strtok(NULL, ":"));
996 | host1_pw = strtok(NULL, ":");
997 | host2_url = strtok(argv[4], ":");
998 | host2_port = atoi(strtok(NULL, ":"));
999 | host2_tg = atoi(strtok(NULL, ":"));
1000 | host2_pw = strtok(NULL, ":");
1001 | printf("DMR1: %s:%d\n", host1_url, host1_port);
1002 | printf("DMR2: %s:%d\n", host2_url, host2_port);
1003 | }
1004 |
1005 | signal(SIGINT, process_signal); //Handle CTRL-C gracefully
1006 | signal(SIGALRM, process_signal); //Ping timer
1007 |
1008 | if ((udp1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1009 | perror("cannot create socket");
1010 | return 0;
1011 | }
1012 |
1013 | if ((udp2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1014 | perror("cannot create socket");
1015 | return 0;
1016 | }
1017 |
1018 | maxudp = max(udp1, udp2) + 1;
1019 | memset((char *)&host1, 0, sizeof(host1));
1020 | host1.sin_family = AF_INET;
1021 | host1.sin_port = htons(host1_port);
1022 | memset((char *)&host2, 0, sizeof(host2));
1023 | host2.sin_family = AF_INET;
1024 | host2.sin_port = htons(host2_port);
1025 | hp = gethostbyname(host1_url);
1026 |
1027 | if (!hp) {
1028 | fprintf(stderr, "could not resolve %s\n", host1_url);
1029 | return 0;
1030 | }
1031 |
1032 | memcpy((void *)&host1.sin_addr, hp->h_addr_list[0], hp->h_length);
1033 | hp = gethostbyname(host2_url);
1034 |
1035 | if (!hp) {
1036 | fprintf(stderr, "could not resolve %s\n", host2_url);
1037 | return 0;
1038 | }
1039 |
1040 | memcpy((void *)&host2.sin_addr, hp->h_addr_list[0], hp->h_length);
1041 | host1_cnt = 0;
1042 | host2_cnt = 0;
1043 |
1044 | int host1_connect_status = DISCONNECTED;
1045 | int host2_connect_status = DISCONNECTED;
1046 |
1047 | alarm(5);
1048 |
1049 | while (1) {
1050 | if(host1_connect_status == DISCONNECTED){
1051 | host1_connect_status = CONNECTING;
1052 | pong_time1 = time(NULL);
1053 | buf[0] = 'R';
1054 | buf[1] = 'P';
1055 | buf[2] = 'T';
1056 | buf[3] = 'L';
1057 | buf[4] = (dmrid >> 24) & 0xff;
1058 | buf[5] = (dmrid >> 16) & 0xff;
1059 | buf[6] = (dmrid >> 8) & 0xff;
1060 | buf[7] = (dmrid >> 0) & 0xff;
1061 | sendto(udp1, buf, 8, 0, (const struct sockaddr *)&host1, sizeof(host1));
1062 | fprintf(stderr, "Connecting to %s...\n", host1_url);
1063 | #ifdef DEBUG
1064 | fprintf(stderr, "SEND DMR1: ");
1065 | for(int i = 0; i < 8; ++i){
1066 | fprintf(stderr, "%02x ", buf[i]);
1067 | }
1068 | fprintf(stderr, "\n");
1069 | fflush(stderr);
1070 | #endif
1071 | }
1072 | if(host2_connect_status == DISCONNECTED){
1073 | host2_connect_status = CONNECTING;
1074 | pong_time2 = time(NULL);
1075 | buf[0] = 'R';
1076 | buf[1] = 'P';
1077 | buf[2] = 'T';
1078 | buf[3] = 'L';
1079 | buf[4] = (dmrid >> 24) & 0xff;
1080 | buf[5] = (dmrid >> 16) & 0xff;
1081 | buf[6] = (dmrid >> 8) & 0xff;
1082 | buf[7] = (dmrid >> 0) & 0xff;
1083 | sendto(udp2, buf, 8, 0, (const struct sockaddr *)&host2, sizeof(host2));
1084 | fprintf(stderr, "Connecting to %s...\n", host2_url);
1085 | #ifdef DEBUG
1086 | fprintf(stderr, "SEND DMR2: ");
1087 | for(int i = 0; i < 8; ++i){
1088 | fprintf(stderr, "%02x ", buf[i]);
1089 | }
1090 | fprintf(stderr, "\n");
1091 | fflush(stderr);
1092 | #endif
1093 | }
1094 | FD_ZERO(&udpset);
1095 | FD_SET(udp1, &udpset);
1096 | FD_SET(udp2, &udpset);
1097 | r = select(maxudp, &udpset, NULL, NULL, NULL);
1098 | //fprintf(stderr, "Select returned r == %d\n", r);
1099 | rxlen = 0;
1100 | if(r > 0){
1101 | if(FD_ISSET(udp1, &udpset)) {
1102 | rxlen = recvfrom(udp1, buf, BUFSIZE, 0, (struct sockaddr *)&rx, &l);
1103 | udprx = udp1;
1104 | }
1105 | else if(FD_ISSET(udp2, &udpset)) {
1106 | rxlen = recvfrom(udp2, buf, BUFSIZE, 0, (struct sockaddr *)&rx, &l);
1107 | udprx = udp2;
1108 | }
1109 | }
1110 | #ifdef DEBUG
1111 | if(rxlen >= 11){
1112 | if(rx.sin_addr.s_addr == host1.sin_addr.s_addr){
1113 | //fprintf(stderr, "RECV DMR1 PING %d\n", ping_cnt1++);
1114 | fprintf(stderr, "RECV DMR1: ");
1115 | }
1116 | else if(rx.sin_addr.s_addr == host2.sin_addr.s_addr){
1117 | //fprintf(stderr, "RECV DMR2 PING %d\n", ping_cnt2++);
1118 | fprintf(stderr, "RECV DMR2: ");
1119 | }
1120 | for(int i = 0; i < rxlen; ++i){
1121 | fprintf(stderr, "%02x ", buf[i]);
1122 | }
1123 | fprintf(stderr, "\n");
1124 | fflush(stderr);
1125 | }
1126 | #endif
1127 | if( rxlen && (udprx == udp1) && (rx.sin_addr.s_addr == host1.sin_addr.s_addr) ){
1128 | if((host1_connect_status != CONNECTED_RW) && (memcmp(buf, "RPTACK", 6U) == 0)){
1129 | host1_connect_status = process_connect(host1_connect_status, buf, 1);
1130 | }
1131 | else if( (host1_connect_status == CONNECTED_RW) && (memcmp(buf, "MSTPONG", 7U) == 0) ){
1132 | pong_time1 = time(NULL);
1133 | }
1134 | else if( (host1_connect_status == CONNECTED_RW) && (rxlen == 55) ){
1135 | rx_srcid = ((buf[5] << 16) & 0xff0000) | ((buf[6] << 8) & 0xff00) | (buf[7] & 0xff);
1136 | if(rx_srcid == 0){
1137 | rx_srcid = ((dmrid>99999999)?dmrid/100:dmrid);
1138 | buf[5] = (rx_srcid >> 16) & 0xff;
1139 | buf[6] = (rx_srcid >> 8) & 0xff;
1140 | buf[7] = (rx_srcid >> 0) & 0xff;
1141 | }
1142 | tx_tgid = host2_tg;
1143 | buf[8] = (host2_tg >> 16) & 0xff;
1144 | buf[9] = (host2_tg >> 8) & 0xff;
1145 | buf[10] = (host2_tg >> 0) & 0xff;
1146 | buf[11] = (dmrid >> 24) & 0xff;
1147 | buf[12] = (dmrid >> 16) & 0xff;
1148 | buf[13] = (dmrid >> 8) & 0xff;
1149 | buf[14] = (dmrid >> 0) & 0xff;
1150 |
1151 | if ( *(uint32_t *)(&buf[16]) == 0 )
1152 | *(uint32_t *)(&buf[16]) = 100; //workaround, XLX doesn't like streamid 0
1153 |
1154 | if(buf[15] > 0x90){
1155 | generate_header();
1156 | }
1157 | else if(buf[15] == 0x90){
1158 | encode_embedded_data();
1159 | }
1160 | else if( (buf[15] > 0x80) && (buf[15] < 0x86) ){
1161 | uint8_t lcss = get_embedded_data(buf+20, buf[15] & 0x0f);
1162 | get_emb_data(buf+20, lcss);
1163 | }
1164 | if(rx_srcid > 0){
1165 | sendto(udp2, buf, rxlen, 0, (const struct sockaddr *)&host2, sizeof(host2));
1166 | #ifdef DEBUG
1167 | fprintf(stderr, "SEND DMR2: ");
1168 | for(int i = 0; i < rxlen; ++i){
1169 | fprintf(stderr, "%02x ", buf[i]);
1170 | }
1171 | fprintf(stderr, "\n");
1172 | fflush(stderr);
1173 | #endif
1174 | }
1175 | }
1176 | }
1177 | else if( rxlen && (udprx == udp2) && (rx.sin_addr.s_addr == host2.sin_addr.s_addr) ){
1178 | if((host2_connect_status != CONNECTED_RW) && (memcmp(buf, "RPTACK", 6U) == 0)){
1179 | host2_connect_status = process_connect(host2_connect_status, buf, 2);
1180 | }
1181 | else if( (host2_connect_status == CONNECTED_RW) && (memcmp(buf, "MSTPONG", 7U) == 0) ){
1182 | pong_time2 = time(NULL);
1183 | }
1184 | else if( (host2_connect_status == CONNECTED_RW) && (rxlen == 55) ){
1185 | rx_srcid = ((buf[5] << 16) & 0xff0000) | ((buf[6] << 8) & 0xff00) | (buf[7] & 0xff);
1186 | if(rx_srcid == 0){
1187 | rx_srcid = ((dmrid>99999999)?dmrid/100:dmrid);
1188 | buf[5] = (rx_srcid >> 16) & 0xff;
1189 | buf[6] = (rx_srcid >> 8) & 0xff;
1190 | buf[7] = (rx_srcid >> 0) & 0xff;
1191 | }
1192 | tx_tgid = host1_tg;
1193 | buf[8] = (host1_tg >> 16) & 0xff;
1194 | buf[9] = (host1_tg >> 8) & 0xff;
1195 | buf[10] = (host1_tg >> 0) & 0xff;
1196 | buf[11] = (dmrid >> 24) & 0xff;
1197 | buf[12] = (dmrid >> 16) & 0xff;
1198 | buf[13] = (dmrid >> 8) & 0xff;
1199 | buf[14] = (dmrid >> 0) & 0xff;
1200 |
1201 | if ( *(uint32_t *)(&buf[16]) == 0 )
1202 | *(uint32_t *)(&buf[16]) = 100; //workaround, XLX doesn't like streamid 0
1203 |
1204 | if(buf[15] > 0x90){
1205 | generate_header();
1206 | }
1207 | else if(buf[15] == 0x90){
1208 | encode_embedded_data();
1209 | }
1210 | else if( (buf[15] > 0x80) && (buf[15] < 0x86) ){
1211 | uint8_t lcss = get_embedded_data(buf+20, buf[15] & 0x0f);
1212 | get_emb_data(buf+20, lcss);
1213 | }
1214 | if(rx_srcid > 0){
1215 | sendto(udp1, buf, rxlen, 0, (const struct sockaddr *)&host1, sizeof(host1));
1216 | #ifdef DEBUG
1217 | fprintf(stderr, "SEND DMR1: ");
1218 | for(int i = 0; i < rxlen; ++i){
1219 | fprintf(stderr, "%02x ", buf[i]);
1220 | }
1221 | fprintf(stderr, "\n");
1222 | fflush(stderr);
1223 | #endif
1224 | }
1225 | }
1226 | }
1227 | if (time(NULL)-pong_time1 > TIMEOUT) {
1228 | host1_connect_status = DISCONNECTED;
1229 | fprintf(stderr, "DMR1 connection timed out, retrying connection...\n");
1230 | }
1231 | if (time(NULL)-pong_time2 > TIMEOUT) {
1232 | host2_connect_status = DISCONNECTED;
1233 | fprintf(stderr, "DMR2 connection timed out, retrying connection...\n");
1234 | }
1235 | }
1236 | }
1237 |
--------------------------------------------------------------------------------
/ysfcon.c:
--------------------------------------------------------------------------------
1 | /*
2 | YSFCon - YSF Reflector Connector with FICH codec
3 | Copyright (C) 2019 Doug McLain
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #define BUFSIZE 2048
34 | //#define DEBUG
35 |
36 | const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
37 |
38 | #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
39 | #define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
40 |
41 | const uint8_t BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 1U, 1U, 1U, 1U};
42 | const uint8_t BRANCH_TABLE2[] = {0U, 1U, 1U, 0U, 0U, 1U, 1U, 0U};
43 |
44 | const unsigned int NUM_OF_STATES_D2 = 8U;
45 | const unsigned int NUM_OF_STATES = 16U;
46 | const uint32_t M = 2U;
47 | const unsigned int K = 5U;
48 |
49 | int udp1;
50 | int udp2;
51 | fd_set udpset;
52 | struct sockaddr_in host1;
53 | struct sockaddr_in host2;
54 | uint8_t buf[BUFSIZE];
55 | char callsign[10U];
56 | uint32_t host1_cnt;
57 | uint32_t host2_cnt;
58 | uint8_t host1_connect;
59 | uint8_t host2_connect;
60 |
61 | uint16_t m_metrics1[16];
62 | uint16_t m_metrics2[16];;
63 | uint64_t m_decisions[180];
64 | uint16_t* m_oldMetrics;
65 | uint16_t* m_newMetrics;
66 | uint64_t* m_dp;
67 | unsigned char m_fich[6U];
68 |
69 | const unsigned int INTERLEAVE_TABLE[] = {
70 | 0U, 40U, 80U, 120U, 160U,
71 | 2U, 42U, 82U, 122U, 162U,
72 | 4U, 44U, 84U, 124U, 164U,
73 | 6U, 46U, 86U, 126U, 166U,
74 | 8U, 48U, 88U, 128U, 168U,
75 | 10U, 50U, 90U, 130U, 170U,
76 | 12U, 52U, 92U, 132U, 172U,
77 | 14U, 54U, 94U, 134U, 174U,
78 | 16U, 56U, 96U, 136U, 176U,
79 | 18U, 58U, 98U, 138U, 178U,
80 | 20U, 60U, 100U, 140U, 180U,
81 | 22U, 62U, 102U, 142U, 182U,
82 | 24U, 64U, 104U, 144U, 184U,
83 | 26U, 66U, 106U, 146U, 186U,
84 | 28U, 68U, 108U, 148U, 188U,
85 | 30U, 70U, 110U, 150U, 190U,
86 | 32U, 72U, 112U, 152U, 192U,
87 | 34U, 74U, 114U, 154U, 194U,
88 | 36U, 76U, 116U, 156U, 196U,
89 | 38U, 78U, 118U, 158U, 198U};
90 |
91 |
92 | const uint16_t CCITT16_TABLE2[] = {
93 | 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
94 | 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
95 | 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
96 | 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
97 | 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
98 | 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
99 | 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
100 | 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
101 | 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
102 | 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
103 | 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
104 | 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
105 | 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
106 | 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
107 | 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
108 | 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
109 | 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
110 | 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
111 | 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
112 | 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
113 | 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
114 | 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
115 | 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
116 | 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
117 | 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
118 | 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
119 | 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
120 | 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
121 | 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
122 | 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
123 | 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
124 | 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 };
125 |
126 | static const unsigned int ENCODING_TABLE_24128[] = {
127 | 0x000000U, 0x0018EBU, 0x00293EU, 0x0031D5U, 0x004A97U, 0x00527CU, 0x0063A9U, 0x007B42U, 0x008DC6U, 0x00952DU,
128 | 0x00A4F8U, 0x00BC13U, 0x00C751U, 0x00DFBAU, 0x00EE6FU, 0x00F684U, 0x010367U, 0x011B8CU, 0x012A59U, 0x0132B2U,
129 | 0x0149F0U, 0x01511BU, 0x0160CEU, 0x017825U, 0x018EA1U, 0x01964AU, 0x01A79FU, 0x01BF74U, 0x01C436U, 0x01DCDDU,
130 | 0x01ED08U, 0x01F5E3U, 0x0206CDU, 0x021E26U, 0x022FF3U, 0x023718U, 0x024C5AU, 0x0254B1U, 0x026564U, 0x027D8FU,
131 | 0x028B0BU, 0x0293E0U, 0x02A235U, 0x02BADEU, 0x02C19CU, 0x02D977U, 0x02E8A2U, 0x02F049U, 0x0305AAU, 0x031D41U,
132 | 0x032C94U, 0x03347FU, 0x034F3DU, 0x0357D6U, 0x036603U, 0x037EE8U, 0x03886CU, 0x039087U, 0x03A152U, 0x03B9B9U,
133 | 0x03C2FBU, 0x03DA10U, 0x03EBC5U, 0x03F32EU, 0x040D99U, 0x041572U, 0x0424A7U, 0x043C4CU, 0x04470EU, 0x045FE5U,
134 | 0x046E30U, 0x0476DBU, 0x04805FU, 0x0498B4U, 0x04A961U, 0x04B18AU, 0x04CAC8U, 0x04D223U, 0x04E3F6U, 0x04FB1DU,
135 | 0x050EFEU, 0x051615U, 0x0527C0U, 0x053F2BU, 0x054469U, 0x055C82U, 0x056D57U, 0x0575BCU, 0x058338U, 0x059BD3U,
136 | 0x05AA06U, 0x05B2EDU, 0x05C9AFU, 0x05D144U, 0x05E091U, 0x05F87AU, 0x060B54U, 0x0613BFU, 0x06226AU, 0x063A81U,
137 | 0x0641C3U, 0x065928U, 0x0668FDU, 0x067016U, 0x068692U, 0x069E79U, 0x06AFACU, 0x06B747U, 0x06CC05U, 0x06D4EEU,
138 | 0x06E53BU, 0x06FDD0U, 0x070833U, 0x0710D8U, 0x07210DU, 0x0739E6U, 0x0742A4U, 0x075A4FU, 0x076B9AU, 0x077371U,
139 | 0x0785F5U, 0x079D1EU, 0x07ACCBU, 0x07B420U, 0x07CF62U, 0x07D789U, 0x07E65CU, 0x07FEB7U, 0x0803DAU, 0x081B31U,
140 | 0x082AE4U, 0x08320FU, 0x08494DU, 0x0851A6U, 0x086073U, 0x087898U, 0x088E1CU, 0x0896F7U, 0x08A722U, 0x08BFC9U,
141 | 0x08C48BU, 0x08DC60U, 0x08EDB5U, 0x08F55EU, 0x0900BDU, 0x091856U, 0x092983U, 0x093168U, 0x094A2AU, 0x0952C1U,
142 | 0x096314U, 0x097BFFU, 0x098D7BU, 0x099590U, 0x09A445U, 0x09BCAEU, 0x09C7ECU, 0x09DF07U, 0x09EED2U, 0x09F639U,
143 | 0x0A0517U, 0x0A1DFCU, 0x0A2C29U, 0x0A34C2U, 0x0A4F80U, 0x0A576BU, 0x0A66BEU, 0x0A7E55U, 0x0A88D1U, 0x0A903AU,
144 | 0x0AA1EFU, 0x0AB904U, 0x0AC246U, 0x0ADAADU, 0x0AEB78U, 0x0AF393U, 0x0B0670U, 0x0B1E9BU, 0x0B2F4EU, 0x0B37A5U,
145 | 0x0B4CE7U, 0x0B540CU, 0x0B65D9U, 0x0B7D32U, 0x0B8BB6U, 0x0B935DU, 0x0BA288U, 0x0BBA63U, 0x0BC121U, 0x0BD9CAU,
146 | 0x0BE81FU, 0x0BF0F4U, 0x0C0E43U, 0x0C16A8U, 0x0C277DU, 0x0C3F96U, 0x0C44D4U, 0x0C5C3FU, 0x0C6DEAU, 0x0C7501U,
147 | 0x0C8385U, 0x0C9B6EU, 0x0CAABBU, 0x0CB250U, 0x0CC912U, 0x0CD1F9U, 0x0CE02CU, 0x0CF8C7U, 0x0D0D24U, 0x0D15CFU,
148 | 0x0D241AU, 0x0D3CF1U, 0x0D47B3U, 0x0D5F58U, 0x0D6E8DU, 0x0D7666U, 0x0D80E2U, 0x0D9809U, 0x0DA9DCU, 0x0DB137U,
149 | 0x0DCA75U, 0x0DD29EU, 0x0DE34BU, 0x0DFBA0U, 0x0E088EU, 0x0E1065U, 0x0E21B0U, 0x0E395BU, 0x0E4219U, 0x0E5AF2U,
150 | 0x0E6B27U, 0x0E73CCU, 0x0E8548U, 0x0E9DA3U, 0x0EAC76U, 0x0EB49DU, 0x0ECFDFU, 0x0ED734U, 0x0EE6E1U, 0x0EFE0AU,
151 | 0x0F0BE9U, 0x0F1302U, 0x0F22D7U, 0x0F3A3CU, 0x0F417EU, 0x0F5995U, 0x0F6840U, 0x0F70ABU, 0x0F862FU, 0x0F9EC4U,
152 | 0x0FAF11U, 0x0FB7FAU, 0x0FCCB8U, 0x0FD453U, 0x0FE586U, 0x0FFD6DU, 0x1007B4U, 0x101F5FU, 0x102E8AU, 0x103661U,
153 | 0x104D23U, 0x1055C8U, 0x10641DU, 0x107CF6U, 0x108A72U, 0x109299U, 0x10A34CU, 0x10BBA7U, 0x10C0E5U, 0x10D80EU,
154 | 0x10E9DBU, 0x10F130U, 0x1104D3U, 0x111C38U, 0x112DEDU, 0x113506U, 0x114E44U, 0x1156AFU, 0x11677AU, 0x117F91U,
155 | 0x118915U, 0x1191FEU, 0x11A02BU, 0x11B8C0U, 0x11C382U, 0x11DB69U, 0x11EABCU, 0x11F257U, 0x120179U, 0x121992U,
156 | 0x122847U, 0x1230ACU, 0x124BEEU, 0x125305U, 0x1262D0U, 0x127A3BU, 0x128CBFU, 0x129454U, 0x12A581U, 0x12BD6AU,
157 | 0x12C628U, 0x12DEC3U, 0x12EF16U, 0x12F7FDU, 0x13021EU, 0x131AF5U, 0x132B20U, 0x1333CBU, 0x134889U, 0x135062U,
158 | 0x1361B7U, 0x13795CU, 0x138FD8U, 0x139733U, 0x13A6E6U, 0x13BE0DU, 0x13C54FU, 0x13DDA4U, 0x13EC71U, 0x13F49AU,
159 | 0x140A2DU, 0x1412C6U, 0x142313U, 0x143BF8U, 0x1440BAU, 0x145851U, 0x146984U, 0x14716FU, 0x1487EBU, 0x149F00U,
160 | 0x14AED5U, 0x14B63EU, 0x14CD7CU, 0x14D597U, 0x14E442U, 0x14FCA9U, 0x15094AU, 0x1511A1U, 0x152074U, 0x15389FU,
161 | 0x1543DDU, 0x155B36U, 0x156AE3U, 0x157208U, 0x15848CU, 0x159C67U, 0x15ADB2U, 0x15B559U, 0x15CE1BU, 0x15D6F0U,
162 | 0x15E725U, 0x15FFCEU, 0x160CE0U, 0x16140BU, 0x1625DEU, 0x163D35U, 0x164677U, 0x165E9CU, 0x166F49U, 0x1677A2U,
163 | 0x168126U, 0x1699CDU, 0x16A818U, 0x16B0F3U, 0x16CBB1U, 0x16D35AU, 0x16E28FU, 0x16FA64U, 0x170F87U, 0x17176CU,
164 | 0x1726B9U, 0x173E52U, 0x174510U, 0x175DFBU, 0x176C2EU, 0x1774C5U, 0x178241U, 0x179AAAU, 0x17AB7FU, 0x17B394U,
165 | 0x17C8D6U, 0x17D03DU, 0x17E1E8U, 0x17F903U, 0x18046EU, 0x181C85U, 0x182D50U, 0x1835BBU, 0x184EF9U, 0x185612U,
166 | 0x1867C7U, 0x187F2CU, 0x1889A8U, 0x189143U, 0x18A096U, 0x18B87DU, 0x18C33FU, 0x18DBD4U, 0x18EA01U, 0x18F2EAU,
167 | 0x190709U, 0x191FE2U, 0x192E37U, 0x1936DCU, 0x194D9EU, 0x195575U, 0x1964A0U, 0x197C4BU, 0x198ACFU, 0x199224U,
168 | 0x19A3F1U, 0x19BB1AU, 0x19C058U, 0x19D8B3U, 0x19E966U, 0x19F18DU, 0x1A02A3U, 0x1A1A48U, 0x1A2B9DU, 0x1A3376U,
169 | 0x1A4834U, 0x1A50DFU, 0x1A610AU, 0x1A79E1U, 0x1A8F65U, 0x1A978EU, 0x1AA65BU, 0x1ABEB0U, 0x1AC5F2U, 0x1ADD19U,
170 | 0x1AECCCU, 0x1AF427U, 0x1B01C4U, 0x1B192FU, 0x1B28FAU, 0x1B3011U, 0x1B4B53U, 0x1B53B8U, 0x1B626DU, 0x1B7A86U,
171 | 0x1B8C02U, 0x1B94E9U, 0x1BA53CU, 0x1BBDD7U, 0x1BC695U, 0x1BDE7EU, 0x1BEFABU, 0x1BF740U, 0x1C09F7U, 0x1C111CU,
172 | 0x1C20C9U, 0x1C3822U, 0x1C4360U, 0x1C5B8BU, 0x1C6A5EU, 0x1C72B5U, 0x1C8431U, 0x1C9CDAU, 0x1CAD0FU, 0x1CB5E4U,
173 | 0x1CCEA6U, 0x1CD64DU, 0x1CE798U, 0x1CFF73U, 0x1D0A90U, 0x1D127BU, 0x1D23AEU, 0x1D3B45U, 0x1D4007U, 0x1D58ECU,
174 | 0x1D6939U, 0x1D71D2U, 0x1D8756U, 0x1D9FBDU, 0x1DAE68U, 0x1DB683U, 0x1DCDC1U, 0x1DD52AU, 0x1DE4FFU, 0x1DFC14U,
175 | 0x1E0F3AU, 0x1E17D1U, 0x1E2604U, 0x1E3EEFU, 0x1E45ADU, 0x1E5D46U, 0x1E6C93U, 0x1E7478U, 0x1E82FCU, 0x1E9A17U,
176 | 0x1EABC2U, 0x1EB329U, 0x1EC86BU, 0x1ED080U, 0x1EE155U, 0x1EF9BEU, 0x1F0C5DU, 0x1F14B6U, 0x1F2563U, 0x1F3D88U,
177 | 0x1F46CAU, 0x1F5E21U, 0x1F6FF4U, 0x1F771FU, 0x1F819BU, 0x1F9970U, 0x1FA8A5U, 0x1FB04EU, 0x1FCB0CU, 0x1FD3E7U,
178 | 0x1FE232U, 0x1FFAD9U, 0x200F68U, 0x201783U, 0x202656U, 0x203EBDU, 0x2045FFU, 0x205D14U, 0x206CC1U, 0x20742AU,
179 | 0x2082AEU, 0x209A45U, 0x20AB90U, 0x20B37BU, 0x20C839U, 0x20D0D2U, 0x20E107U, 0x20F9ECU, 0x210C0FU, 0x2114E4U,
180 | 0x212531U, 0x213DDAU, 0x214698U, 0x215E73U, 0x216FA6U, 0x21774DU, 0x2181C9U, 0x219922U, 0x21A8F7U, 0x21B01CU,
181 | 0x21CB5EU, 0x21D3B5U, 0x21E260U, 0x21FA8BU, 0x2209A5U, 0x22114EU, 0x22209BU, 0x223870U, 0x224332U, 0x225BD9U,
182 | 0x226A0CU, 0x2272E7U, 0x228463U, 0x229C88U, 0x22AD5DU, 0x22B5B6U, 0x22CEF4U, 0x22D61FU, 0x22E7CAU, 0x22FF21U,
183 | 0x230AC2U, 0x231229U, 0x2323FCU, 0x233B17U, 0x234055U, 0x2358BEU, 0x23696BU, 0x237180U, 0x238704U, 0x239FEFU,
184 | 0x23AE3AU, 0x23B6D1U, 0x23CD93U, 0x23D578U, 0x23E4ADU, 0x23FC46U, 0x2402F1U, 0x241A1AU, 0x242BCFU, 0x243324U,
185 | 0x244866U, 0x24508DU, 0x246158U, 0x2479B3U, 0x248F37U, 0x2497DCU, 0x24A609U, 0x24BEE2U, 0x24C5A0U, 0x24DD4BU,
186 | 0x24EC9EU, 0x24F475U, 0x250196U, 0x25197DU, 0x2528A8U, 0x253043U, 0x254B01U, 0x2553EAU, 0x25623FU, 0x257AD4U,
187 | 0x258C50U, 0x2594BBU, 0x25A56EU, 0x25BD85U, 0x25C6C7U, 0x25DE2CU, 0x25EFF9U, 0x25F712U, 0x26043CU, 0x261CD7U,
188 | 0x262D02U, 0x2635E9U, 0x264EABU, 0x265640U, 0x266795U, 0x267F7EU, 0x2689FAU, 0x269111U, 0x26A0C4U, 0x26B82FU,
189 | 0x26C36DU, 0x26DB86U, 0x26EA53U, 0x26F2B8U, 0x27075BU, 0x271FB0U, 0x272E65U, 0x27368EU, 0x274DCCU, 0x275527U,
190 | 0x2764F2U, 0x277C19U, 0x278A9DU, 0x279276U, 0x27A3A3U, 0x27BB48U, 0x27C00AU, 0x27D8E1U, 0x27E934U, 0x27F1DFU,
191 | 0x280CB2U, 0x281459U, 0x28258CU, 0x283D67U, 0x284625U, 0x285ECEU, 0x286F1BU, 0x2877F0U, 0x288174U, 0x28999FU,
192 | 0x28A84AU, 0x28B0A1U, 0x28CBE3U, 0x28D308U, 0x28E2DDU, 0x28FA36U, 0x290FD5U, 0x29173EU, 0x2926EBU, 0x293E00U,
193 | 0x294542U, 0x295DA9U, 0x296C7CU, 0x297497U, 0x298213U, 0x299AF8U, 0x29AB2DU, 0x29B3C6U, 0x29C884U, 0x29D06FU,
194 | 0x29E1BAU, 0x29F951U, 0x2A0A7FU, 0x2A1294U, 0x2A2341U, 0x2A3BAAU, 0x2A40E8U, 0x2A5803U, 0x2A69D6U, 0x2A713DU,
195 | 0x2A87B9U, 0x2A9F52U, 0x2AAE87U, 0x2AB66CU, 0x2ACD2EU, 0x2AD5C5U, 0x2AE410U, 0x2AFCFBU, 0x2B0918U, 0x2B11F3U,
196 | 0x2B2026U, 0x2B38CDU, 0x2B438FU, 0x2B5B64U, 0x2B6AB1U, 0x2B725AU, 0x2B84DEU, 0x2B9C35U, 0x2BADE0U, 0x2BB50BU,
197 | 0x2BCE49U, 0x2BD6A2U, 0x2BE777U, 0x2BFF9CU, 0x2C012BU, 0x2C19C0U, 0x2C2815U, 0x2C30FEU, 0x2C4BBCU, 0x2C5357U,
198 | 0x2C6282U, 0x2C7A69U, 0x2C8CEDU, 0x2C9406U, 0x2CA5D3U, 0x2CBD38U, 0x2CC67AU, 0x2CDE91U, 0x2CEF44U, 0x2CF7AFU,
199 | 0x2D024CU, 0x2D1AA7U, 0x2D2B72U, 0x2D3399U, 0x2D48DBU, 0x2D5030U, 0x2D61E5U, 0x2D790EU, 0x2D8F8AU, 0x2D9761U,
200 | 0x2DA6B4U, 0x2DBE5FU, 0x2DC51DU, 0x2DDDF6U, 0x2DEC23U, 0x2DF4C8U, 0x2E07E6U, 0x2E1F0DU, 0x2E2ED8U, 0x2E3633U,
201 | 0x2E4D71U, 0x2E559AU, 0x2E644FU, 0x2E7CA4U, 0x2E8A20U, 0x2E92CBU, 0x2EA31EU, 0x2EBBF5U, 0x2EC0B7U, 0x2ED85CU,
202 | 0x2EE989U, 0x2EF162U, 0x2F0481U, 0x2F1C6AU, 0x2F2DBFU, 0x2F3554U, 0x2F4E16U, 0x2F56FDU, 0x2F6728U, 0x2F7FC3U,
203 | 0x2F8947U, 0x2F91ACU, 0x2FA079U, 0x2FB892U, 0x2FC3D0U, 0x2FDB3BU, 0x2FEAEEU, 0x2FF205U, 0x3008DCU, 0x301037U,
204 | 0x3021E2U, 0x303909U, 0x30424BU, 0x305AA0U, 0x306B75U, 0x30739EU, 0x30851AU, 0x309DF1U, 0x30AC24U, 0x30B4CFU,
205 | 0x30CF8DU, 0x30D766U, 0x30E6B3U, 0x30FE58U, 0x310BBBU, 0x311350U, 0x312285U, 0x313A6EU, 0x31412CU, 0x3159C7U,
206 | 0x316812U, 0x3170F9U, 0x31867DU, 0x319E96U, 0x31AF43U, 0x31B7A8U, 0x31CCEAU, 0x31D401U, 0x31E5D4U, 0x31FD3FU,
207 | 0x320E11U, 0x3216FAU, 0x32272FU, 0x323FC4U, 0x324486U, 0x325C6DU, 0x326DB8U, 0x327553U, 0x3283D7U, 0x329B3CU,
208 | 0x32AAE9U, 0x32B202U, 0x32C940U, 0x32D1ABU, 0x32E07EU, 0x32F895U, 0x330D76U, 0x33159DU, 0x332448U, 0x333CA3U,
209 | 0x3347E1U, 0x335F0AU, 0x336EDFU, 0x337634U, 0x3380B0U, 0x33985BU, 0x33A98EU, 0x33B165U, 0x33CA27U, 0x33D2CCU,
210 | 0x33E319U, 0x33FBF2U, 0x340545U, 0x341DAEU, 0x342C7BU, 0x343490U, 0x344FD2U, 0x345739U, 0x3466ECU, 0x347E07U,
211 | 0x348883U, 0x349068U, 0x34A1BDU, 0x34B956U, 0x34C214U, 0x34DAFFU, 0x34EB2AU, 0x34F3C1U, 0x350622U, 0x351EC9U,
212 | 0x352F1CU, 0x3537F7U, 0x354CB5U, 0x35545EU, 0x35658BU, 0x357D60U, 0x358BE4U, 0x35930FU, 0x35A2DAU, 0x35BA31U,
213 | 0x35C173U, 0x35D998U, 0x35E84DU, 0x35F0A6U, 0x360388U, 0x361B63U, 0x362AB6U, 0x36325DU, 0x36491FU, 0x3651F4U,
214 | 0x366021U, 0x3678CAU, 0x368E4EU, 0x3696A5U, 0x36A770U, 0x36BF9BU, 0x36C4D9U, 0x36DC32U, 0x36EDE7U, 0x36F50CU,
215 | 0x3700EFU, 0x371804U, 0x3729D1U, 0x37313AU, 0x374A78U, 0x375293U, 0x376346U, 0x377BADU, 0x378D29U, 0x3795C2U,
216 | 0x37A417U, 0x37BCFCU, 0x37C7BEU, 0x37DF55U, 0x37EE80U, 0x37F66BU, 0x380B06U, 0x3813EDU, 0x382238U, 0x383AD3U,
217 | 0x384191U, 0x38597AU, 0x3868AFU, 0x387044U, 0x3886C0U, 0x389E2BU, 0x38AFFEU, 0x38B715U, 0x38CC57U, 0x38D4BCU,
218 | 0x38E569U, 0x38FD82U, 0x390861U, 0x39108AU, 0x39215FU, 0x3939B4U, 0x3942F6U, 0x395A1DU, 0x396BC8U, 0x397323U,
219 | 0x3985A7U, 0x399D4CU, 0x39AC99U, 0x39B472U, 0x39CF30U, 0x39D7DBU, 0x39E60EU, 0x39FEE5U, 0x3A0DCBU, 0x3A1520U,
220 | 0x3A24F5U, 0x3A3C1EU, 0x3A475CU, 0x3A5FB7U, 0x3A6E62U, 0x3A7689U, 0x3A800DU, 0x3A98E6U, 0x3AA933U, 0x3AB1D8U,
221 | 0x3ACA9AU, 0x3AD271U, 0x3AE3A4U, 0x3AFB4FU, 0x3B0EACU, 0x3B1647U, 0x3B2792U, 0x3B3F79U, 0x3B443BU, 0x3B5CD0U,
222 | 0x3B6D05U, 0x3B75EEU, 0x3B836AU, 0x3B9B81U, 0x3BAA54U, 0x3BB2BFU, 0x3BC9FDU, 0x3BD116U, 0x3BE0C3U, 0x3BF828U,
223 | 0x3C069FU, 0x3C1E74U, 0x3C2FA1U, 0x3C374AU, 0x3C4C08U, 0x3C54E3U, 0x3C6536U, 0x3C7DDDU, 0x3C8B59U, 0x3C93B2U,
224 | 0x3CA267U, 0x3CBA8CU, 0x3CC1CEU, 0x3CD925U, 0x3CE8F0U, 0x3CF01BU, 0x3D05F8U, 0x3D1D13U, 0x3D2CC6U, 0x3D342DU,
225 | 0x3D4F6FU, 0x3D5784U, 0x3D6651U, 0x3D7EBAU, 0x3D883EU, 0x3D90D5U, 0x3DA100U, 0x3DB9EBU, 0x3DC2A9U, 0x3DDA42U,
226 | 0x3DEB97U, 0x3DF37CU, 0x3E0052U, 0x3E18B9U, 0x3E296CU, 0x3E3187U, 0x3E4AC5U, 0x3E522EU, 0x3E63FBU, 0x3E7B10U,
227 | 0x3E8D94U, 0x3E957FU, 0x3EA4AAU, 0x3EBC41U, 0x3EC703U, 0x3EDFE8U, 0x3EEE3DU, 0x3EF6D6U, 0x3F0335U, 0x3F1BDEU,
228 | 0x3F2A0BU, 0x3F32E0U, 0x3F49A2U, 0x3F5149U, 0x3F609CU, 0x3F7877U, 0x3F8EF3U, 0x3F9618U, 0x3FA7CDU, 0x3FBF26U,
229 | 0x3FC464U, 0x3FDC8FU, 0x3FED5AU, 0x3FF5B1U, 0x40063BU, 0x401ED0U, 0x402F05U, 0x4037EEU, 0x404CACU, 0x405447U,
230 | 0x406592U, 0x407D79U, 0x408BFDU, 0x409316U, 0x40A2C3U, 0x40BA28U, 0x40C16AU, 0x40D981U, 0x40E854U, 0x40F0BFU,
231 | 0x41055CU, 0x411DB7U, 0x412C62U, 0x413489U, 0x414FCBU, 0x415720U, 0x4166F5U, 0x417E1EU, 0x41889AU, 0x419071U,
232 | 0x41A1A4U, 0x41B94FU, 0x41C20DU, 0x41DAE6U, 0x41EB33U, 0x41F3D8U, 0x4200F6U, 0x42181DU, 0x4229C8U, 0x423123U,
233 | 0x424A61U, 0x42528AU, 0x42635FU, 0x427BB4U, 0x428D30U, 0x4295DBU, 0x42A40EU, 0x42BCE5U, 0x42C7A7U, 0x42DF4CU,
234 | 0x42EE99U, 0x42F672U, 0x430391U, 0x431B7AU, 0x432AAFU, 0x433244U, 0x434906U, 0x4351EDU, 0x436038U, 0x4378D3U,
235 | 0x438E57U, 0x4396BCU, 0x43A769U, 0x43BF82U, 0x43C4C0U, 0x43DC2BU, 0x43EDFEU, 0x43F515U, 0x440BA2U, 0x441349U,
236 | 0x44229CU, 0x443A77U, 0x444135U, 0x4459DEU, 0x44680BU, 0x4470E0U, 0x448664U, 0x449E8FU, 0x44AF5AU, 0x44B7B1U,
237 | 0x44CCF3U, 0x44D418U, 0x44E5CDU, 0x44FD26U, 0x4508C5U, 0x45102EU, 0x4521FBU, 0x453910U, 0x454252U, 0x455AB9U,
238 | 0x456B6CU, 0x457387U, 0x458503U, 0x459DE8U, 0x45AC3DU, 0x45B4D6U, 0x45CF94U, 0x45D77FU, 0x45E6AAU, 0x45FE41U,
239 | 0x460D6FU, 0x461584U, 0x462451U, 0x463CBAU, 0x4647F8U, 0x465F13U, 0x466EC6U, 0x46762DU, 0x4680A9U, 0x469842U,
240 | 0x46A997U, 0x46B17CU, 0x46CA3EU, 0x46D2D5U, 0x46E300U, 0x46FBEBU, 0x470E08U, 0x4716E3U, 0x472736U, 0x473FDDU,
241 | 0x47449FU, 0x475C74U, 0x476DA1U, 0x47754AU, 0x4783CEU, 0x479B25U, 0x47AAF0U, 0x47B21BU, 0x47C959U, 0x47D1B2U,
242 | 0x47E067U, 0x47F88CU, 0x4805E1U, 0x481D0AU, 0x482CDFU, 0x483434U, 0x484F76U, 0x48579DU, 0x486648U, 0x487EA3U,
243 | 0x488827U, 0x4890CCU, 0x48A119U, 0x48B9F2U, 0x48C2B0U, 0x48DA5BU, 0x48EB8EU, 0x48F365U, 0x490686U, 0x491E6DU,
244 | 0x492FB8U, 0x493753U, 0x494C11U, 0x4954FAU, 0x49652FU, 0x497DC4U, 0x498B40U, 0x4993ABU, 0x49A27EU, 0x49BA95U,
245 | 0x49C1D7U, 0x49D93CU, 0x49E8E9U, 0x49F002U, 0x4A032CU, 0x4A1BC7U, 0x4A2A12U, 0x4A32F9U, 0x4A49BBU, 0x4A5150U,
246 | 0x4A6085U, 0x4A786EU, 0x4A8EEAU, 0x4A9601U, 0x4AA7D4U, 0x4ABF3FU, 0x4AC47DU, 0x4ADC96U, 0x4AED43U, 0x4AF5A8U,
247 | 0x4B004BU, 0x4B18A0U, 0x4B2975U, 0x4B319EU, 0x4B4ADCU, 0x4B5237U, 0x4B63E2U, 0x4B7B09U, 0x4B8D8DU, 0x4B9566U,
248 | 0x4BA4B3U, 0x4BBC58U, 0x4BC71AU, 0x4BDFF1U, 0x4BEE24U, 0x4BF6CFU, 0x4C0878U, 0x4C1093U, 0x4C2146U, 0x4C39ADU,
249 | 0x4C42EFU, 0x4C5A04U, 0x4C6BD1U, 0x4C733AU, 0x4C85BEU, 0x4C9D55U, 0x4CAC80U, 0x4CB46BU, 0x4CCF29U, 0x4CD7C2U,
250 | 0x4CE617U, 0x4CFEFCU, 0x4D0B1FU, 0x4D13F4U, 0x4D2221U, 0x4D3ACAU, 0x4D4188U, 0x4D5963U, 0x4D68B6U, 0x4D705DU,
251 | 0x4D86D9U, 0x4D9E32U, 0x4DAFE7U, 0x4DB70CU, 0x4DCC4EU, 0x4DD4A5U, 0x4DE570U, 0x4DFD9BU, 0x4E0EB5U, 0x4E165EU,
252 | 0x4E278BU, 0x4E3F60U, 0x4E4422U, 0x4E5CC9U, 0x4E6D1CU, 0x4E75F7U, 0x4E8373U, 0x4E9B98U, 0x4EAA4DU, 0x4EB2A6U,
253 | 0x4EC9E4U, 0x4ED10FU, 0x4EE0DAU, 0x4EF831U, 0x4F0DD2U, 0x4F1539U, 0x4F24ECU, 0x4F3C07U, 0x4F4745U, 0x4F5FAEU,
254 | 0x4F6E7BU, 0x4F7690U, 0x4F8014U, 0x4F98FFU, 0x4FA92AU, 0x4FB1C1U, 0x4FCA83U, 0x4FD268U, 0x4FE3BDU, 0x4FFB56U,
255 | 0x50018FU, 0x501964U, 0x5028B1U, 0x50305AU, 0x504B18U, 0x5053F3U, 0x506226U, 0x507ACDU, 0x508C49U, 0x5094A2U,
256 | 0x50A577U, 0x50BD9CU, 0x50C6DEU, 0x50DE35U, 0x50EFE0U, 0x50F70BU, 0x5102E8U, 0x511A03U, 0x512BD6U, 0x51333DU,
257 | 0x51487FU, 0x515094U, 0x516141U, 0x5179AAU, 0x518F2EU, 0x5197C5U, 0x51A610U, 0x51BEFBU, 0x51C5B9U, 0x51DD52U,
258 | 0x51EC87U, 0x51F46CU, 0x520742U, 0x521FA9U, 0x522E7CU, 0x523697U, 0x524DD5U, 0x52553EU, 0x5264EBU, 0x527C00U,
259 | 0x528A84U, 0x52926FU, 0x52A3BAU, 0x52BB51U, 0x52C013U, 0x52D8F8U, 0x52E92DU, 0x52F1C6U, 0x530425U, 0x531CCEU,
260 | 0x532D1BU, 0x5335F0U, 0x534EB2U, 0x535659U, 0x53678CU, 0x537F67U, 0x5389E3U, 0x539108U, 0x53A0DDU, 0x53B836U,
261 | 0x53C374U, 0x53DB9FU, 0x53EA4AU, 0x53F2A1U, 0x540C16U, 0x5414FDU, 0x542528U, 0x543DC3U, 0x544681U, 0x545E6AU,
262 | 0x546FBFU, 0x547754U, 0x5481D0U, 0x54993BU, 0x54A8EEU, 0x54B005U, 0x54CB47U, 0x54D3ACU, 0x54E279U, 0x54FA92U,
263 | 0x550F71U, 0x55179AU, 0x55264FU, 0x553EA4U, 0x5545E6U, 0x555D0DU, 0x556CD8U, 0x557433U, 0x5582B7U, 0x559A5CU,
264 | 0x55AB89U, 0x55B362U, 0x55C820U, 0x55D0CBU, 0x55E11EU, 0x55F9F5U, 0x560ADBU, 0x561230U, 0x5623E5U, 0x563B0EU,
265 | 0x56404CU, 0x5658A7U, 0x566972U, 0x567199U, 0x56871DU, 0x569FF6U, 0x56AE23U, 0x56B6C8U, 0x56CD8AU, 0x56D561U,
266 | 0x56E4B4U, 0x56FC5FU, 0x5709BCU, 0x571157U, 0x572082U, 0x573869U, 0x57432BU, 0x575BC0U, 0x576A15U, 0x5772FEU,
267 | 0x57847AU, 0x579C91U, 0x57AD44U, 0x57B5AFU, 0x57CEEDU, 0x57D606U, 0x57E7D3U, 0x57FF38U, 0x580255U, 0x581ABEU,
268 | 0x582B6BU, 0x583380U, 0x5848C2U, 0x585029U, 0x5861FCU, 0x587917U, 0x588F93U, 0x589778U, 0x58A6ADU, 0x58BE46U,
269 | 0x58C504U, 0x58DDEFU, 0x58EC3AU, 0x58F4D1U, 0x590132U, 0x5919D9U, 0x59280CU, 0x5930E7U, 0x594BA5U, 0x59534EU,
270 | 0x59629BU, 0x597A70U, 0x598CF4U, 0x59941FU, 0x59A5CAU, 0x59BD21U, 0x59C663U, 0x59DE88U, 0x59EF5DU, 0x59F7B6U,
271 | 0x5A0498U, 0x5A1C73U, 0x5A2DA6U, 0x5A354DU, 0x5A4E0FU, 0x5A56E4U, 0x5A6731U, 0x5A7FDAU, 0x5A895EU, 0x5A91B5U,
272 | 0x5AA060U, 0x5AB88BU, 0x5AC3C9U, 0x5ADB22U, 0x5AEAF7U, 0x5AF21CU, 0x5B07FFU, 0x5B1F14U, 0x5B2EC1U, 0x5B362AU,
273 | 0x5B4D68U, 0x5B5583U, 0x5B6456U, 0x5B7CBDU, 0x5B8A39U, 0x5B92D2U, 0x5BA307U, 0x5BBBECU, 0x5BC0AEU, 0x5BD845U,
274 | 0x5BE990U, 0x5BF17BU, 0x5C0FCCU, 0x5C1727U, 0x5C26F2U, 0x5C3E19U, 0x5C455BU, 0x5C5DB0U, 0x5C6C65U, 0x5C748EU,
275 | 0x5C820AU, 0x5C9AE1U, 0x5CAB34U, 0x5CB3DFU, 0x5CC89DU, 0x5CD076U, 0x5CE1A3U, 0x5CF948U, 0x5D0CABU, 0x5D1440U,
276 | 0x5D2595U, 0x5D3D7EU, 0x5D463CU, 0x5D5ED7U, 0x5D6F02U, 0x5D77E9U, 0x5D816DU, 0x5D9986U, 0x5DA853U, 0x5DB0B8U,
277 | 0x5DCBFAU, 0x5DD311U, 0x5DE2C4U, 0x5DFA2FU, 0x5E0901U, 0x5E11EAU, 0x5E203FU, 0x5E38D4U, 0x5E4396U, 0x5E5B7DU,
278 | 0x5E6AA8U, 0x5E7243U, 0x5E84C7U, 0x5E9C2CU, 0x5EADF9U, 0x5EB512U, 0x5ECE50U, 0x5ED6BBU, 0x5EE76EU, 0x5EFF85U,
279 | 0x5F0A66U, 0x5F128DU, 0x5F2358U, 0x5F3BB3U, 0x5F40F1U, 0x5F581AU, 0x5F69CFU, 0x5F7124U, 0x5F87A0U, 0x5F9F4BU,
280 | 0x5FAE9EU, 0x5FB675U, 0x5FCD37U, 0x5FD5DCU, 0x5FE409U, 0x5FFCE2U, 0x600953U, 0x6011B8U, 0x60206DU, 0x603886U,
281 | 0x6043C4U, 0x605B2FU, 0x606AFAU, 0x607211U, 0x608495U, 0x609C7EU, 0x60ADABU, 0x60B540U, 0x60CE02U, 0x60D6E9U,
282 | 0x60E73CU, 0x60FFD7U, 0x610A34U, 0x6112DFU, 0x61230AU, 0x613BE1U, 0x6140A3U, 0x615848U, 0x61699DU, 0x617176U,
283 | 0x6187F2U, 0x619F19U, 0x61AECCU, 0x61B627U, 0x61CD65U, 0x61D58EU, 0x61E45BU, 0x61FCB0U, 0x620F9EU, 0x621775U,
284 | 0x6226A0U, 0x623E4BU, 0x624509U, 0x625DE2U, 0x626C37U, 0x6274DCU, 0x628258U, 0x629AB3U, 0x62AB66U, 0x62B38DU,
285 | 0x62C8CFU, 0x62D024U, 0x62E1F1U, 0x62F91AU, 0x630CF9U, 0x631412U, 0x6325C7U, 0x633D2CU, 0x63466EU, 0x635E85U,
286 | 0x636F50U, 0x6377BBU, 0x63813FU, 0x6399D4U, 0x63A801U, 0x63B0EAU, 0x63CBA8U, 0x63D343U, 0x63E296U, 0x63FA7DU,
287 | 0x6404CAU, 0x641C21U, 0x642DF4U, 0x64351FU, 0x644E5DU, 0x6456B6U, 0x646763U, 0x647F88U, 0x64890CU, 0x6491E7U,
288 | 0x64A032U, 0x64B8D9U, 0x64C39BU, 0x64DB70U, 0x64EAA5U, 0x64F24EU, 0x6507ADU, 0x651F46U, 0x652E93U, 0x653678U,
289 | 0x654D3AU, 0x6555D1U, 0x656404U, 0x657CEFU, 0x658A6BU, 0x659280U, 0x65A355U, 0x65BBBEU, 0x65C0FCU, 0x65D817U,
290 | 0x65E9C2U, 0x65F129U, 0x660207U, 0x661AECU, 0x662B39U, 0x6633D2U, 0x664890U, 0x66507BU, 0x6661AEU, 0x667945U,
291 | 0x668FC1U, 0x66972AU, 0x66A6FFU, 0x66BE14U, 0x66C556U, 0x66DDBDU, 0x66EC68U, 0x66F483U, 0x670160U, 0x67198BU,
292 | 0x67285EU, 0x6730B5U, 0x674BF7U, 0x67531CU, 0x6762C9U, 0x677A22U, 0x678CA6U, 0x67944DU, 0x67A598U, 0x67BD73U,
293 | 0x67C631U, 0x67DEDAU, 0x67EF0FU, 0x67F7E4U, 0x680A89U, 0x681262U, 0x6823B7U, 0x683B5CU, 0x68401EU, 0x6858F5U,
294 | 0x686920U, 0x6871CBU, 0x68874FU, 0x689FA4U, 0x68AE71U, 0x68B69AU, 0x68CDD8U, 0x68D533U, 0x68E4E6U, 0x68FC0DU,
295 | 0x6909EEU, 0x691105U, 0x6920D0U, 0x69383BU, 0x694379U, 0x695B92U, 0x696A47U, 0x6972ACU, 0x698428U, 0x699CC3U,
296 | 0x69AD16U, 0x69B5FDU, 0x69CEBFU, 0x69D654U, 0x69E781U, 0x69FF6AU, 0x6A0C44U, 0x6A14AFU, 0x6A257AU, 0x6A3D91U,
297 | 0x6A46D3U, 0x6A5E38U, 0x6A6FEDU, 0x6A7706U, 0x6A8182U, 0x6A9969U, 0x6AA8BCU, 0x6AB057U, 0x6ACB15U, 0x6AD3FEU,
298 | 0x6AE22BU, 0x6AFAC0U, 0x6B0F23U, 0x6B17C8U, 0x6B261DU, 0x6B3EF6U, 0x6B45B4U, 0x6B5D5FU, 0x6B6C8AU, 0x6B7461U,
299 | 0x6B82E5U, 0x6B9A0EU, 0x6BABDBU, 0x6BB330U, 0x6BC872U, 0x6BD099U, 0x6BE14CU, 0x6BF9A7U, 0x6C0710U, 0x6C1FFBU,
300 | 0x6C2E2EU, 0x6C36C5U, 0x6C4D87U, 0x6C556CU, 0x6C64B9U, 0x6C7C52U, 0x6C8AD6U, 0x6C923DU, 0x6CA3E8U, 0x6CBB03U,
301 | 0x6CC041U, 0x6CD8AAU, 0x6CE97FU, 0x6CF194U, 0x6D0477U, 0x6D1C9CU, 0x6D2D49U, 0x6D35A2U, 0x6D4EE0U, 0x6D560BU,
302 | 0x6D67DEU, 0x6D7F35U, 0x6D89B1U, 0x6D915AU, 0x6DA08FU, 0x6DB864U, 0x6DC326U, 0x6DDBCDU, 0x6DEA18U, 0x6DF2F3U,
303 | 0x6E01DDU, 0x6E1936U, 0x6E28E3U, 0x6E3008U, 0x6E4B4AU, 0x6E53A1U, 0x6E6274U, 0x6E7A9FU, 0x6E8C1BU, 0x6E94F0U,
304 | 0x6EA525U, 0x6EBDCEU, 0x6EC68CU, 0x6EDE67U, 0x6EEFB2U, 0x6EF759U, 0x6F02BAU, 0x6F1A51U, 0x6F2B84U, 0x6F336FU,
305 | 0x6F482DU, 0x6F50C6U, 0x6F6113U, 0x6F79F8U, 0x6F8F7CU, 0x6F9797U, 0x6FA642U, 0x6FBEA9U, 0x6FC5EBU, 0x6FDD00U,
306 | 0x6FECD5U, 0x6FF43EU, 0x700EE7U, 0x70160CU, 0x7027D9U, 0x703F32U, 0x704470U, 0x705C9BU, 0x706D4EU, 0x7075A5U,
307 | 0x708321U, 0x709BCAU, 0x70AA1FU, 0x70B2F4U, 0x70C9B6U, 0x70D15DU, 0x70E088U, 0x70F863U, 0x710D80U, 0x71156BU,
308 | 0x7124BEU, 0x713C55U, 0x714717U, 0x715FFCU, 0x716E29U, 0x7176C2U, 0x718046U, 0x7198ADU, 0x71A978U, 0x71B193U,
309 | 0x71CAD1U, 0x71D23AU, 0x71E3EFU, 0x71FB04U, 0x72082AU, 0x7210C1U, 0x722114U, 0x7239FFU, 0x7242BDU, 0x725A56U,
310 | 0x726B83U, 0x727368U, 0x7285ECU, 0x729D07U, 0x72ACD2U, 0x72B439U, 0x72CF7BU, 0x72D790U, 0x72E645U, 0x72FEAEU,
311 | 0x730B4DU, 0x7313A6U, 0x732273U, 0x733A98U, 0x7341DAU, 0x735931U, 0x7368E4U, 0x73700FU, 0x73868BU, 0x739E60U,
312 | 0x73AFB5U, 0x73B75EU, 0x73CC1CU, 0x73D4F7U, 0x73E522U, 0x73FDC9U, 0x74037EU, 0x741B95U, 0x742A40U, 0x7432ABU,
313 | 0x7449E9U, 0x745102U, 0x7460D7U, 0x74783CU, 0x748EB8U, 0x749653U, 0x74A786U, 0x74BF6DU, 0x74C42FU, 0x74DCC4U,
314 | 0x74ED11U, 0x74F5FAU, 0x750019U, 0x7518F2U, 0x752927U, 0x7531CCU, 0x754A8EU, 0x755265U, 0x7563B0U, 0x757B5BU,
315 | 0x758DDFU, 0x759534U, 0x75A4E1U, 0x75BC0AU, 0x75C748U, 0x75DFA3U, 0x75EE76U, 0x75F69DU, 0x7605B3U, 0x761D58U,
316 | 0x762C8DU, 0x763466U, 0x764F24U, 0x7657CFU, 0x76661AU, 0x767EF1U, 0x768875U, 0x76909EU, 0x76A14BU, 0x76B9A0U,
317 | 0x76C2E2U, 0x76DA09U, 0x76EBDCU, 0x76F337U, 0x7706D4U, 0x771E3FU, 0x772FEAU, 0x773701U, 0x774C43U, 0x7754A8U,
318 | 0x77657DU, 0x777D96U, 0x778B12U, 0x7793F9U, 0x77A22CU, 0x77BAC7U, 0x77C185U, 0x77D96EU, 0x77E8BBU, 0x77F050U,
319 | 0x780D3DU, 0x7815D6U, 0x782403U, 0x783CE8U, 0x7847AAU, 0x785F41U, 0x786E94U, 0x78767FU, 0x7880FBU, 0x789810U,
320 | 0x78A9C5U, 0x78B12EU, 0x78CA6CU, 0x78D287U, 0x78E352U, 0x78FBB9U, 0x790E5AU, 0x7916B1U, 0x792764U, 0x793F8FU,
321 | 0x7944CDU, 0x795C26U, 0x796DF3U, 0x797518U, 0x79839CU, 0x799B77U, 0x79AAA2U, 0x79B249U, 0x79C90BU, 0x79D1E0U,
322 | 0x79E035U, 0x79F8DEU, 0x7A0BF0U, 0x7A131BU, 0x7A22CEU, 0x7A3A25U, 0x7A4167U, 0x7A598CU, 0x7A6859U, 0x7A70B2U,
323 | 0x7A8636U, 0x7A9EDDU, 0x7AAF08U, 0x7AB7E3U, 0x7ACCA1U, 0x7AD44AU, 0x7AE59FU, 0x7AFD74U, 0x7B0897U, 0x7B107CU,
324 | 0x7B21A9U, 0x7B3942U, 0x7B4200U, 0x7B5AEBU, 0x7B6B3EU, 0x7B73D5U, 0x7B8551U, 0x7B9DBAU, 0x7BAC6FU, 0x7BB484U,
325 | 0x7BCFC6U, 0x7BD72DU, 0x7BE6F8U, 0x7BFE13U, 0x7C00A4U, 0x7C184FU, 0x7C299AU, 0x7C3171U, 0x7C4A33U, 0x7C52D8U,
326 | 0x7C630DU, 0x7C7BE6U, 0x7C8D62U, 0x7C9589U, 0x7CA45CU, 0x7CBCB7U, 0x7CC7F5U, 0x7CDF1EU, 0x7CEECBU, 0x7CF620U,
327 | 0x7D03C3U, 0x7D1B28U, 0x7D2AFDU, 0x7D3216U, 0x7D4954U, 0x7D51BFU, 0x7D606AU, 0x7D7881U, 0x7D8E05U, 0x7D96EEU,
328 | 0x7DA73BU, 0x7DBFD0U, 0x7DC492U, 0x7DDC79U, 0x7DEDACU, 0x7DF547U, 0x7E0669U, 0x7E1E82U, 0x7E2F57U, 0x7E37BCU,
329 | 0x7E4CFEU, 0x7E5415U, 0x7E65C0U, 0x7E7D2BU, 0x7E8BAFU, 0x7E9344U, 0x7EA291U, 0x7EBA7AU, 0x7EC138U, 0x7ED9D3U,
330 | 0x7EE806U, 0x7EF0EDU, 0x7F050EU, 0x7F1DE5U, 0x7F2C30U, 0x7F34DBU, 0x7F4F99U, 0x7F5772U, 0x7F66A7U, 0x7F7E4CU,
331 | 0x7F88C8U, 0x7F9023U, 0x7FA1F6U, 0x7FB91DU, 0x7FC25FU, 0x7FDAB4U, 0x7FEB61U, 0x7FF38AU, 0x800C75U, 0x80149EU,
332 | 0x80254BU, 0x803DA0U, 0x8046E2U, 0x805E09U, 0x806FDCU, 0x807737U, 0x8081B3U, 0x809958U, 0x80A88DU, 0x80B066U,
333 | 0x80CB24U, 0x80D3CFU, 0x80E21AU, 0x80FAF1U, 0x810F12U, 0x8117F9U, 0x81262CU, 0x813EC7U, 0x814585U, 0x815D6EU,
334 | 0x816CBBU, 0x817450U, 0x8182D4U, 0x819A3FU, 0x81ABEAU, 0x81B301U, 0x81C843U, 0x81D0A8U, 0x81E17DU, 0x81F996U,
335 | 0x820AB8U, 0x821253U, 0x822386U, 0x823B6DU, 0x82402FU, 0x8258C4U, 0x826911U, 0x8271FAU, 0x82877EU, 0x829F95U,
336 | 0x82AE40U, 0x82B6ABU, 0x82CDE9U, 0x82D502U, 0x82E4D7U, 0x82FC3CU, 0x8309DFU, 0x831134U, 0x8320E1U, 0x83380AU,
337 | 0x834348U, 0x835BA3U, 0x836A76U, 0x83729DU, 0x838419U, 0x839CF2U, 0x83AD27U, 0x83B5CCU, 0x83CE8EU, 0x83D665U,
338 | 0x83E7B0U, 0x83FF5BU, 0x8401ECU, 0x841907U, 0x8428D2U, 0x843039U, 0x844B7BU, 0x845390U, 0x846245U, 0x847AAEU,
339 | 0x848C2AU, 0x8494C1U, 0x84A514U, 0x84BDFFU, 0x84C6BDU, 0x84DE56U, 0x84EF83U, 0x84F768U, 0x85028BU, 0x851A60U,
340 | 0x852BB5U, 0x85335EU, 0x85481CU, 0x8550F7U, 0x856122U, 0x8579C9U, 0x858F4DU, 0x8597A6U, 0x85A673U, 0x85BE98U,
341 | 0x85C5DAU, 0x85DD31U, 0x85ECE4U, 0x85F40FU, 0x860721U, 0x861FCAU, 0x862E1FU, 0x8636F4U, 0x864DB6U, 0x86555DU,
342 | 0x866488U, 0x867C63U, 0x868AE7U, 0x86920CU, 0x86A3D9U, 0x86BB32U, 0x86C070U, 0x86D89BU, 0x86E94EU, 0x86F1A5U,
343 | 0x870446U, 0x871CADU, 0x872D78U, 0x873593U, 0x874ED1U, 0x87563AU, 0x8767EFU, 0x877F04U, 0x878980U, 0x87916BU,
344 | 0x87A0BEU, 0x87B855U, 0x87C317U, 0x87DBFCU, 0x87EA29U, 0x87F2C2U, 0x880FAFU, 0x881744U, 0x882691U, 0x883E7AU,
345 | 0x884538U, 0x885DD3U, 0x886C06U, 0x8874EDU, 0x888269U, 0x889A82U, 0x88AB57U, 0x88B3BCU, 0x88C8FEU, 0x88D015U,
346 | 0x88E1C0U, 0x88F92BU, 0x890CC8U, 0x891423U, 0x8925F6U, 0x893D1DU, 0x89465FU, 0x895EB4U, 0x896F61U, 0x89778AU,
347 | 0x89810EU, 0x8999E5U, 0x89A830U, 0x89B0DBU, 0x89CB99U, 0x89D372U, 0x89E2A7U, 0x89FA4CU, 0x8A0962U, 0x8A1189U,
348 | 0x8A205CU, 0x8A38B7U, 0x8A43F5U, 0x8A5B1EU, 0x8A6ACBU, 0x8A7220U, 0x8A84A4U, 0x8A9C4FU, 0x8AAD9AU, 0x8AB571U,
349 | 0x8ACE33U, 0x8AD6D8U, 0x8AE70DU, 0x8AFFE6U, 0x8B0A05U, 0x8B12EEU, 0x8B233BU, 0x8B3BD0U, 0x8B4092U, 0x8B5879U,
350 | 0x8B69ACU, 0x8B7147U, 0x8B87C3U, 0x8B9F28U, 0x8BAEFDU, 0x8BB616U, 0x8BCD54U, 0x8BD5BFU, 0x8BE46AU, 0x8BFC81U,
351 | 0x8C0236U, 0x8C1ADDU, 0x8C2B08U, 0x8C33E3U, 0x8C48A1U, 0x8C504AU, 0x8C619FU, 0x8C7974U, 0x8C8FF0U, 0x8C971BU,
352 | 0x8CA6CEU, 0x8CBE25U, 0x8CC567U, 0x8CDD8CU, 0x8CEC59U, 0x8CF4B2U, 0x8D0151U, 0x8D19BAU, 0x8D286FU, 0x8D3084U,
353 | 0x8D4BC6U, 0x8D532DU, 0x8D62F8U, 0x8D7A13U, 0x8D8C97U, 0x8D947CU, 0x8DA5A9U, 0x8DBD42U, 0x8DC600U, 0x8DDEEBU,
354 | 0x8DEF3EU, 0x8DF7D5U, 0x8E04FBU, 0x8E1C10U, 0x8E2DC5U, 0x8E352EU, 0x8E4E6CU, 0x8E5687U, 0x8E6752U, 0x8E7FB9U,
355 | 0x8E893DU, 0x8E91D6U, 0x8EA003U, 0x8EB8E8U, 0x8EC3AAU, 0x8EDB41U, 0x8EEA94U, 0x8EF27FU, 0x8F079CU, 0x8F1F77U,
356 | 0x8F2EA2U, 0x8F3649U, 0x8F4D0BU, 0x8F55E0U, 0x8F6435U, 0x8F7CDEU, 0x8F8A5AU, 0x8F92B1U, 0x8FA364U, 0x8FBB8FU,
357 | 0x8FC0CDU, 0x8FD826U, 0x8FE9F3U, 0x8FF118U, 0x900BC1U, 0x90132AU, 0x9022FFU, 0x903A14U, 0x904156U, 0x9059BDU,
358 | 0x906868U, 0x907083U, 0x908607U, 0x909EECU, 0x90AF39U, 0x90B7D2U, 0x90CC90U, 0x90D47BU, 0x90E5AEU, 0x90FD45U,
359 | 0x9108A6U, 0x91104DU, 0x912198U, 0x913973U, 0x914231U, 0x915ADAU, 0x916B0FU, 0x9173E4U, 0x918560U, 0x919D8BU,
360 | 0x91AC5EU, 0x91B4B5U, 0x91CFF7U, 0x91D71CU, 0x91E6C9U, 0x91FE22U, 0x920D0CU, 0x9215E7U, 0x922432U, 0x923CD9U,
361 | 0x92479BU, 0x925F70U, 0x926EA5U, 0x92764EU, 0x9280CAU, 0x929821U, 0x92A9F4U, 0x92B11FU, 0x92CA5DU, 0x92D2B6U,
362 | 0x92E363U, 0x92FB88U, 0x930E6BU, 0x931680U, 0x932755U, 0x933FBEU, 0x9344FCU, 0x935C17U, 0x936DC2U, 0x937529U,
363 | 0x9383ADU, 0x939B46U, 0x93AA93U, 0x93B278U, 0x93C93AU, 0x93D1D1U, 0x93E004U, 0x93F8EFU, 0x940658U, 0x941EB3U,
364 | 0x942F66U, 0x94378DU, 0x944CCFU, 0x945424U, 0x9465F1U, 0x947D1AU, 0x948B9EU, 0x949375U, 0x94A2A0U, 0x94BA4BU,
365 | 0x94C109U, 0x94D9E2U, 0x94E837U, 0x94F0DCU, 0x95053FU, 0x951DD4U, 0x952C01U, 0x9534EAU, 0x954FA8U, 0x955743U,
366 | 0x956696U, 0x957E7DU, 0x9588F9U, 0x959012U, 0x95A1C7U, 0x95B92CU, 0x95C26EU, 0x95DA85U, 0x95EB50U, 0x95F3BBU,
367 | 0x960095U, 0x96187EU, 0x9629ABU, 0x963140U, 0x964A02U, 0x9652E9U, 0x96633CU, 0x967BD7U, 0x968D53U, 0x9695B8U,
368 | 0x96A46DU, 0x96BC86U, 0x96C7C4U, 0x96DF2FU, 0x96EEFAU, 0x96F611U, 0x9703F2U, 0x971B19U, 0x972ACCU, 0x973227U,
369 | 0x974965U, 0x97518EU, 0x97605BU, 0x9778B0U, 0x978E34U, 0x9796DFU, 0x97A70AU, 0x97BFE1U, 0x97C4A3U, 0x97DC48U,
370 | 0x97ED9DU, 0x97F576U, 0x98081BU, 0x9810F0U, 0x982125U, 0x9839CEU, 0x98428CU, 0x985A67U, 0x986BB2U, 0x987359U,
371 | 0x9885DDU, 0x989D36U, 0x98ACE3U, 0x98B408U, 0x98CF4AU, 0x98D7A1U, 0x98E674U, 0x98FE9FU, 0x990B7CU, 0x991397U,
372 | 0x992242U, 0x993AA9U, 0x9941EBU, 0x995900U, 0x9968D5U, 0x99703EU, 0x9986BAU, 0x999E51U, 0x99AF84U, 0x99B76FU,
373 | 0x99CC2DU, 0x99D4C6U, 0x99E513U, 0x99FDF8U, 0x9A0ED6U, 0x9A163DU, 0x9A27E8U, 0x9A3F03U, 0x9A4441U, 0x9A5CAAU,
374 | 0x9A6D7FU, 0x9A7594U, 0x9A8310U, 0x9A9BFBU, 0x9AAA2EU, 0x9AB2C5U, 0x9AC987U, 0x9AD16CU, 0x9AE0B9U, 0x9AF852U,
375 | 0x9B0DB1U, 0x9B155AU, 0x9B248FU, 0x9B3C64U, 0x9B4726U, 0x9B5FCDU, 0x9B6E18U, 0x9B76F3U, 0x9B8077U, 0x9B989CU,
376 | 0x9BA949U, 0x9BB1A2U, 0x9BCAE0U, 0x9BD20BU, 0x9BE3DEU, 0x9BFB35U, 0x9C0582U, 0x9C1D69U, 0x9C2CBCU, 0x9C3457U,
377 | 0x9C4F15U, 0x9C57FEU, 0x9C662BU, 0x9C7EC0U, 0x9C8844U, 0x9C90AFU, 0x9CA17AU, 0x9CB991U, 0x9CC2D3U, 0x9CDA38U,
378 | 0x9CEBEDU, 0x9CF306U, 0x9D06E5U, 0x9D1E0EU, 0x9D2FDBU, 0x9D3730U, 0x9D4C72U, 0x9D5499U, 0x9D654CU, 0x9D7DA7U,
379 | 0x9D8B23U, 0x9D93C8U, 0x9DA21DU, 0x9DBAF6U, 0x9DC1B4U, 0x9DD95FU, 0x9DE88AU, 0x9DF061U, 0x9E034FU, 0x9E1BA4U,
380 | 0x9E2A71U, 0x9E329AU, 0x9E49D8U, 0x9E5133U, 0x9E60E6U, 0x9E780DU, 0x9E8E89U, 0x9E9662U, 0x9EA7B7U, 0x9EBF5CU,
381 | 0x9EC41EU, 0x9EDCF5U, 0x9EED20U, 0x9EF5CBU, 0x9F0028U, 0x9F18C3U, 0x9F2916U, 0x9F31FDU, 0x9F4ABFU, 0x9F5254U,
382 | 0x9F6381U, 0x9F7B6AU, 0x9F8DEEU, 0x9F9505U, 0x9FA4D0U, 0x9FBC3BU, 0x9FC779U, 0x9FDF92U, 0x9FEE47U, 0x9FF6ACU,
383 | 0xA0031DU, 0xA01BF6U, 0xA02A23U, 0xA032C8U, 0xA0498AU, 0xA05161U, 0xA060B4U, 0xA0785FU, 0xA08EDBU, 0xA09630U,
384 | 0xA0A7E5U, 0xA0BF0EU, 0xA0C44CU, 0xA0DCA7U, 0xA0ED72U, 0xA0F599U, 0xA1007AU, 0xA11891U, 0xA12944U, 0xA131AFU,
385 | 0xA14AEDU, 0xA15206U, 0xA163D3U, 0xA17B38U, 0xA18DBCU, 0xA19557U, 0xA1A482U, 0xA1BC69U, 0xA1C72BU, 0xA1DFC0U,
386 | 0xA1EE15U, 0xA1F6FEU, 0xA205D0U, 0xA21D3BU, 0xA22CEEU, 0xA23405U, 0xA24F47U, 0xA257ACU, 0xA26679U, 0xA27E92U,
387 | 0xA28816U, 0xA290FDU, 0xA2A128U, 0xA2B9C3U, 0xA2C281U, 0xA2DA6AU, 0xA2EBBFU, 0xA2F354U, 0xA306B7U, 0xA31E5CU,
388 | 0xA32F89U, 0xA33762U, 0xA34C20U, 0xA354CBU, 0xA3651EU, 0xA37DF5U, 0xA38B71U, 0xA3939AU, 0xA3A24FU, 0xA3BAA4U,
389 | 0xA3C1E6U, 0xA3D90DU, 0xA3E8D8U, 0xA3F033U, 0xA40E84U, 0xA4166FU, 0xA427BAU, 0xA43F51U, 0xA44413U, 0xA45CF8U,
390 | 0xA46D2DU, 0xA475C6U, 0xA48342U, 0xA49BA9U, 0xA4AA7CU, 0xA4B297U, 0xA4C9D5U, 0xA4D13EU, 0xA4E0EBU, 0xA4F800U,
391 | 0xA50DE3U, 0xA51508U, 0xA524DDU, 0xA53C36U, 0xA54774U, 0xA55F9FU, 0xA56E4AU, 0xA576A1U, 0xA58025U, 0xA598CEU,
392 | 0xA5A91BU, 0xA5B1F0U, 0xA5CAB2U, 0xA5D259U, 0xA5E38CU, 0xA5FB67U, 0xA60849U, 0xA610A2U, 0xA62177U, 0xA6399CU,
393 | 0xA642DEU, 0xA65A35U, 0xA66BE0U, 0xA6730BU, 0xA6858FU, 0xA69D64U, 0xA6ACB1U, 0xA6B45AU, 0xA6CF18U, 0xA6D7F3U,
394 | 0xA6E626U, 0xA6FECDU, 0xA70B2EU, 0xA713C5U, 0xA72210U, 0xA73AFBU, 0xA741B9U, 0xA75952U, 0xA76887U, 0xA7706CU,
395 | 0xA786E8U, 0xA79E03U, 0xA7AFD6U, 0xA7B73DU, 0xA7CC7FU, 0xA7D494U, 0xA7E541U, 0xA7FDAAU, 0xA800C7U, 0xA8182CU,
396 | 0xA829F9U, 0xA83112U, 0xA84A50U, 0xA852BBU, 0xA8636EU, 0xA87B85U, 0xA88D01U, 0xA895EAU, 0xA8A43FU, 0xA8BCD4U,
397 | 0xA8C796U, 0xA8DF7DU, 0xA8EEA8U, 0xA8F643U, 0xA903A0U, 0xA91B4BU, 0xA92A9EU, 0xA93275U, 0xA94937U, 0xA951DCU,
398 | 0xA96009U, 0xA978E2U, 0xA98E66U, 0xA9968DU, 0xA9A758U, 0xA9BFB3U, 0xA9C4F1U, 0xA9DC1AU, 0xA9EDCFU, 0xA9F524U,
399 | 0xAA060AU, 0xAA1EE1U, 0xAA2F34U, 0xAA37DFU, 0xAA4C9DU, 0xAA5476U, 0xAA65A3U, 0xAA7D48U, 0xAA8BCCU, 0xAA9327U,
400 | 0xAAA2F2U, 0xAABA19U, 0xAAC15BU, 0xAAD9B0U, 0xAAE865U, 0xAAF08EU, 0xAB056DU, 0xAB1D86U, 0xAB2C53U, 0xAB34B8U,
401 | 0xAB4FFAU, 0xAB5711U, 0xAB66C4U, 0xAB7E2FU, 0xAB88ABU, 0xAB9040U, 0xABA195U, 0xABB97EU, 0xABC23CU, 0xABDAD7U,
402 | 0xABEB02U, 0xABF3E9U, 0xAC0D5EU, 0xAC15B5U, 0xAC2460U, 0xAC3C8BU, 0xAC47C9U, 0xAC5F22U, 0xAC6EF7U, 0xAC761CU,
403 | 0xAC8098U, 0xAC9873U, 0xACA9A6U, 0xACB14DU, 0xACCA0FU, 0xACD2E4U, 0xACE331U, 0xACFBDAU, 0xAD0E39U, 0xAD16D2U,
404 | 0xAD2707U, 0xAD3FECU, 0xAD44AEU, 0xAD5C45U, 0xAD6D90U, 0xAD757BU, 0xAD83FFU, 0xAD9B14U, 0xADAAC1U, 0xADB22AU,
405 | 0xADC968U, 0xADD183U, 0xADE056U, 0xADF8BDU, 0xAE0B93U, 0xAE1378U, 0xAE22ADU, 0xAE3A46U, 0xAE4104U, 0xAE59EFU,
406 | 0xAE683AU, 0xAE70D1U, 0xAE8655U, 0xAE9EBEU, 0xAEAF6BU, 0xAEB780U, 0xAECCC2U, 0xAED429U, 0xAEE5FCU, 0xAEFD17U,
407 | 0xAF08F4U, 0xAF101FU, 0xAF21CAU, 0xAF3921U, 0xAF4263U, 0xAF5A88U, 0xAF6B5DU, 0xAF73B6U, 0xAF8532U, 0xAF9DD9U,
408 | 0xAFAC0CU, 0xAFB4E7U, 0xAFCFA5U, 0xAFD74EU, 0xAFE69BU, 0xAFFE70U, 0xB004A9U, 0xB01C42U, 0xB02D97U, 0xB0357CU,
409 | 0xB04E3EU, 0xB056D5U, 0xB06700U, 0xB07FEBU, 0xB0896FU, 0xB09184U, 0xB0A051U, 0xB0B8BAU, 0xB0C3F8U, 0xB0DB13U,
410 | 0xB0EAC6U, 0xB0F22DU, 0xB107CEU, 0xB11F25U, 0xB12EF0U, 0xB1361BU, 0xB14D59U, 0xB155B2U, 0xB16467U, 0xB17C8CU,
411 | 0xB18A08U, 0xB192E3U, 0xB1A336U, 0xB1BBDDU, 0xB1C09FU, 0xB1D874U, 0xB1E9A1U, 0xB1F14AU, 0xB20264U, 0xB21A8FU,
412 | 0xB22B5AU, 0xB233B1U, 0xB248F3U, 0xB25018U, 0xB261CDU, 0xB27926U, 0xB28FA2U, 0xB29749U, 0xB2A69CU, 0xB2BE77U,
413 | 0xB2C535U, 0xB2DDDEU, 0xB2EC0BU, 0xB2F4E0U, 0xB30103U, 0xB319E8U, 0xB3283DU, 0xB330D6U, 0xB34B94U, 0xB3537FU,
414 | 0xB362AAU, 0xB37A41U, 0xB38CC5U, 0xB3942EU, 0xB3A5FBU, 0xB3BD10U, 0xB3C652U, 0xB3DEB9U, 0xB3EF6CU, 0xB3F787U,
415 | 0xB40930U, 0xB411DBU, 0xB4200EU, 0xB438E5U, 0xB443A7U, 0xB45B4CU, 0xB46A99U, 0xB47272U, 0xB484F6U, 0xB49C1DU,
416 | 0xB4ADC8U, 0xB4B523U, 0xB4CE61U, 0xB4D68AU, 0xB4E75FU, 0xB4FFB4U, 0xB50A57U, 0xB512BCU, 0xB52369U, 0xB53B82U,
417 | 0xB540C0U, 0xB5582BU, 0xB569FEU, 0xB57115U, 0xB58791U, 0xB59F7AU, 0xB5AEAFU, 0xB5B644U, 0xB5CD06U, 0xB5D5EDU,
418 | 0xB5E438U, 0xB5FCD3U, 0xB60FFDU, 0xB61716U, 0xB626C3U, 0xB63E28U, 0xB6456AU, 0xB65D81U, 0xB66C54U, 0xB674BFU,
419 | 0xB6823BU, 0xB69AD0U, 0xB6AB05U, 0xB6B3EEU, 0xB6C8ACU, 0xB6D047U, 0xB6E192U, 0xB6F979U, 0xB70C9AU, 0xB71471U,
420 | 0xB725A4U, 0xB73D4FU, 0xB7460DU, 0xB75EE6U, 0xB76F33U, 0xB777D8U, 0xB7815CU, 0xB799B7U, 0xB7A862U, 0xB7B089U,
421 | 0xB7CBCBU, 0xB7D320U, 0xB7E2F5U, 0xB7FA1EU, 0xB80773U, 0xB81F98U, 0xB82E4DU, 0xB836A6U, 0xB84DE4U, 0xB8550FU,
422 | 0xB864DAU, 0xB87C31U, 0xB88AB5U, 0xB8925EU, 0xB8A38BU, 0xB8BB60U, 0xB8C022U, 0xB8D8C9U, 0xB8E91CU, 0xB8F1F7U,
423 | 0xB90414U, 0xB91CFFU, 0xB92D2AU, 0xB935C1U, 0xB94E83U, 0xB95668U, 0xB967BDU, 0xB97F56U, 0xB989D2U, 0xB99139U,
424 | 0xB9A0ECU, 0xB9B807U, 0xB9C345U, 0xB9DBAEU, 0xB9EA7BU, 0xB9F290U, 0xBA01BEU, 0xBA1955U, 0xBA2880U, 0xBA306BU,
425 | 0xBA4B29U, 0xBA53C2U, 0xBA6217U, 0xBA7AFCU, 0xBA8C78U, 0xBA9493U, 0xBAA546U, 0xBABDADU, 0xBAC6EFU, 0xBADE04U,
426 | 0xBAEFD1U, 0xBAF73AU, 0xBB02D9U, 0xBB1A32U, 0xBB2BE7U, 0xBB330CU, 0xBB484EU, 0xBB50A5U, 0xBB6170U, 0xBB799BU,
427 | 0xBB8F1FU, 0xBB97F4U, 0xBBA621U, 0xBBBECAU, 0xBBC588U, 0xBBDD63U, 0xBBECB6U, 0xBBF45DU, 0xBC0AEAU, 0xBC1201U,
428 | 0xBC23D4U, 0xBC3B3FU, 0xBC407DU, 0xBC5896U, 0xBC6943U, 0xBC71A8U, 0xBC872CU, 0xBC9FC7U, 0xBCAE12U, 0xBCB6F9U,
429 | 0xBCCDBBU, 0xBCD550U, 0xBCE485U, 0xBCFC6EU, 0xBD098DU, 0xBD1166U, 0xBD20B3U, 0xBD3858U, 0xBD431AU, 0xBD5BF1U,
430 | 0xBD6A24U, 0xBD72CFU, 0xBD844BU, 0xBD9CA0U, 0xBDAD75U, 0xBDB59EU, 0xBDCEDCU, 0xBDD637U, 0xBDE7E2U, 0xBDFF09U,
431 | 0xBE0C27U, 0xBE14CCU, 0xBE2519U, 0xBE3DF2U, 0xBE46B0U, 0xBE5E5BU, 0xBE6F8EU, 0xBE7765U, 0xBE81E1U, 0xBE990AU,
432 | 0xBEA8DFU, 0xBEB034U, 0xBECB76U, 0xBED39DU, 0xBEE248U, 0xBEFAA3U, 0xBF0F40U, 0xBF17ABU, 0xBF267EU, 0xBF3E95U,
433 | 0xBF45D7U, 0xBF5D3CU, 0xBF6CE9U, 0xBF7402U, 0xBF8286U, 0xBF9A6DU, 0xBFABB8U, 0xBFB353U, 0xBFC811U, 0xBFD0FAU,
434 | 0xBFE12FU, 0xBFF9C4U, 0xC00A4EU, 0xC012A5U, 0xC02370U, 0xC03B9BU, 0xC040D9U, 0xC05832U, 0xC069E7U, 0xC0710CU,
435 | 0xC08788U, 0xC09F63U, 0xC0AEB6U, 0xC0B65DU, 0xC0CD1FU, 0xC0D5F4U, 0xC0E421U, 0xC0FCCAU, 0xC10929U, 0xC111C2U,
436 | 0xC12017U, 0xC138FCU, 0xC143BEU, 0xC15B55U, 0xC16A80U, 0xC1726BU, 0xC184EFU, 0xC19C04U, 0xC1ADD1U, 0xC1B53AU,
437 | 0xC1CE78U, 0xC1D693U, 0xC1E746U, 0xC1FFADU, 0xC20C83U, 0xC21468U, 0xC225BDU, 0xC23D56U, 0xC24614U, 0xC25EFFU,
438 | 0xC26F2AU, 0xC277C1U, 0xC28145U, 0xC299AEU, 0xC2A87BU, 0xC2B090U, 0xC2CBD2U, 0xC2D339U, 0xC2E2ECU, 0xC2FA07U,
439 | 0xC30FE4U, 0xC3170FU, 0xC326DAU, 0xC33E31U, 0xC34573U, 0xC35D98U, 0xC36C4DU, 0xC374A6U, 0xC38222U, 0xC39AC9U,
440 | 0xC3AB1CU, 0xC3B3F7U, 0xC3C8B5U, 0xC3D05EU, 0xC3E18BU, 0xC3F960U, 0xC407D7U, 0xC41F3CU, 0xC42EE9U, 0xC43602U,
441 | 0xC44D40U, 0xC455ABU, 0xC4647EU, 0xC47C95U, 0xC48A11U, 0xC492FAU, 0xC4A32FU, 0xC4BBC4U, 0xC4C086U, 0xC4D86DU,
442 | 0xC4E9B8U, 0xC4F153U, 0xC504B0U, 0xC51C5BU, 0xC52D8EU, 0xC53565U, 0xC54E27U, 0xC556CCU, 0xC56719U, 0xC57FF2U,
443 | 0xC58976U, 0xC5919DU, 0xC5A048U, 0xC5B8A3U, 0xC5C3E1U, 0xC5DB0AU, 0xC5EADFU, 0xC5F234U, 0xC6011AU, 0xC619F1U,
444 | 0xC62824U, 0xC630CFU, 0xC64B8DU, 0xC65366U, 0xC662B3U, 0xC67A58U, 0xC68CDCU, 0xC69437U, 0xC6A5E2U, 0xC6BD09U,
445 | 0xC6C64BU, 0xC6DEA0U, 0xC6EF75U, 0xC6F79EU, 0xC7027DU, 0xC71A96U, 0xC72B43U, 0xC733A8U, 0xC748EAU, 0xC75001U,
446 | 0xC761D4U, 0xC7793FU, 0xC78FBBU, 0xC79750U, 0xC7A685U, 0xC7BE6EU, 0xC7C52CU, 0xC7DDC7U, 0xC7EC12U, 0xC7F4F9U,
447 | 0xC80994U, 0xC8117FU, 0xC820AAU, 0xC83841U, 0xC84303U, 0xC85BE8U, 0xC86A3DU, 0xC872D6U, 0xC88452U, 0xC89CB9U,
448 | 0xC8AD6CU, 0xC8B587U, 0xC8CEC5U, 0xC8D62EU, 0xC8E7FBU, 0xC8FF10U, 0xC90AF3U, 0xC91218U, 0xC923CDU, 0xC93B26U,
449 | 0xC94064U, 0xC9588FU, 0xC9695AU, 0xC971B1U, 0xC98735U, 0xC99FDEU, 0xC9AE0BU, 0xC9B6E0U, 0xC9CDA2U, 0xC9D549U,
450 | 0xC9E49CU, 0xC9FC77U, 0xCA0F59U, 0xCA17B2U, 0xCA2667U, 0xCA3E8CU, 0xCA45CEU, 0xCA5D25U, 0xCA6CF0U, 0xCA741BU,
451 | 0xCA829FU, 0xCA9A74U, 0xCAABA1U, 0xCAB34AU, 0xCAC808U, 0xCAD0E3U, 0xCAE136U, 0xCAF9DDU, 0xCB0C3EU, 0xCB14D5U,
452 | 0xCB2500U, 0xCB3DEBU, 0xCB46A9U, 0xCB5E42U, 0xCB6F97U, 0xCB777CU, 0xCB81F8U, 0xCB9913U, 0xCBA8C6U, 0xCBB02DU,
453 | 0xCBCB6FU, 0xCBD384U, 0xCBE251U, 0xCBFABAU, 0xCC040DU, 0xCC1CE6U, 0xCC2D33U, 0xCC35D8U, 0xCC4E9AU, 0xCC5671U,
454 | 0xCC67A4U, 0xCC7F4FU, 0xCC89CBU, 0xCC9120U, 0xCCA0F5U, 0xCCB81EU, 0xCCC35CU, 0xCCDBB7U, 0xCCEA62U, 0xCCF289U,
455 | 0xCD076AU, 0xCD1F81U, 0xCD2E54U, 0xCD36BFU, 0xCD4DFDU, 0xCD5516U, 0xCD64C3U, 0xCD7C28U, 0xCD8AACU, 0xCD9247U,
456 | 0xCDA392U, 0xCDBB79U, 0xCDC03BU, 0xCDD8D0U, 0xCDE905U, 0xCDF1EEU, 0xCE02C0U, 0xCE1A2BU, 0xCE2BFEU, 0xCE3315U,
457 | 0xCE4857U, 0xCE50BCU, 0xCE6169U, 0xCE7982U, 0xCE8F06U, 0xCE97EDU, 0xCEA638U, 0xCEBED3U, 0xCEC591U, 0xCEDD7AU,
458 | 0xCEECAFU, 0xCEF444U, 0xCF01A7U, 0xCF194CU, 0xCF2899U, 0xCF3072U, 0xCF4B30U, 0xCF53DBU, 0xCF620EU, 0xCF7AE5U,
459 | 0xCF8C61U, 0xCF948AU, 0xCFA55FU, 0xCFBDB4U, 0xCFC6F6U, 0xCFDE1DU, 0xCFEFC8U, 0xCFF723U, 0xD00DFAU, 0xD01511U,
460 | 0xD024C4U, 0xD03C2FU, 0xD0476DU, 0xD05F86U, 0xD06E53U, 0xD076B8U, 0xD0803CU, 0xD098D7U, 0xD0A902U, 0xD0B1E9U,
461 | 0xD0CAABU, 0xD0D240U, 0xD0E395U, 0xD0FB7EU, 0xD10E9DU, 0xD11676U, 0xD127A3U, 0xD13F48U, 0xD1440AU, 0xD15CE1U,
462 | 0xD16D34U, 0xD175DFU, 0xD1835BU, 0xD19BB0U, 0xD1AA65U, 0xD1B28EU, 0xD1C9CCU, 0xD1D127U, 0xD1E0F2U, 0xD1F819U,
463 | 0xD20B37U, 0xD213DCU, 0xD22209U, 0xD23AE2U, 0xD241A0U, 0xD2594BU, 0xD2689EU, 0xD27075U, 0xD286F1U, 0xD29E1AU,
464 | 0xD2AFCFU, 0xD2B724U, 0xD2CC66U, 0xD2D48DU, 0xD2E558U, 0xD2FDB3U, 0xD30850U, 0xD310BBU, 0xD3216EU, 0xD33985U,
465 | 0xD342C7U, 0xD35A2CU, 0xD36BF9U, 0xD37312U, 0xD38596U, 0xD39D7DU, 0xD3ACA8U, 0xD3B443U, 0xD3CF01U, 0xD3D7EAU,
466 | 0xD3E63FU, 0xD3FED4U, 0xD40063U, 0xD41888U, 0xD4295DU, 0xD431B6U, 0xD44AF4U, 0xD4521FU, 0xD463CAU, 0xD47B21U,
467 | 0xD48DA5U, 0xD4954EU, 0xD4A49BU, 0xD4BC70U, 0xD4C732U, 0xD4DFD9U, 0xD4EE0CU, 0xD4F6E7U, 0xD50304U, 0xD51BEFU,
468 | 0xD52A3AU, 0xD532D1U, 0xD54993U, 0xD55178U, 0xD560ADU, 0xD57846U, 0xD58EC2U, 0xD59629U, 0xD5A7FCU, 0xD5BF17U,
469 | 0xD5C455U, 0xD5DCBEU, 0xD5ED6BU, 0xD5F580U, 0xD606AEU, 0xD61E45U, 0xD62F90U, 0xD6377BU, 0xD64C39U, 0xD654D2U,
470 | 0xD66507U, 0xD67DECU, 0xD68B68U, 0xD69383U, 0xD6A256U, 0xD6BABDU, 0xD6C1FFU, 0xD6D914U, 0xD6E8C1U, 0xD6F02AU,
471 | 0xD705C9U, 0xD71D22U, 0xD72CF7U, 0xD7341CU, 0xD74F5EU, 0xD757B5U, 0xD76660U, 0xD77E8BU, 0xD7880FU, 0xD790E4U,
472 | 0xD7A131U, 0xD7B9DAU, 0xD7C298U, 0xD7DA73U, 0xD7EBA6U, 0xD7F34DU, 0xD80E20U, 0xD816CBU, 0xD8271EU, 0xD83FF5U,
473 | 0xD844B7U, 0xD85C5CU, 0xD86D89U, 0xD87562U, 0xD883E6U, 0xD89B0DU, 0xD8AAD8U, 0xD8B233U, 0xD8C971U, 0xD8D19AU,
474 | 0xD8E04FU, 0xD8F8A4U, 0xD90D47U, 0xD915ACU, 0xD92479U, 0xD93C92U, 0xD947D0U, 0xD95F3BU, 0xD96EEEU, 0xD97605U,
475 | 0xD98081U, 0xD9986AU, 0xD9A9BFU, 0xD9B154U, 0xD9CA16U, 0xD9D2FDU, 0xD9E328U, 0xD9FBC3U, 0xDA08EDU, 0xDA1006U,
476 | 0xDA21D3U, 0xDA3938U, 0xDA427AU, 0xDA5A91U, 0xDA6B44U, 0xDA73AFU, 0xDA852BU, 0xDA9DC0U, 0xDAAC15U, 0xDAB4FEU,
477 | 0xDACFBCU, 0xDAD757U, 0xDAE682U, 0xDAFE69U, 0xDB0B8AU, 0xDB1361U, 0xDB22B4U, 0xDB3A5FU, 0xDB411DU, 0xDB59F6U,
478 | 0xDB6823U, 0xDB70C8U, 0xDB864CU, 0xDB9EA7U, 0xDBAF72U, 0xDBB799U, 0xDBCCDBU, 0xDBD430U, 0xDBE5E5U, 0xDBFD0EU,
479 | 0xDC03B9U, 0xDC1B52U, 0xDC2A87U, 0xDC326CU, 0xDC492EU, 0xDC51C5U, 0xDC6010U, 0xDC78FBU, 0xDC8E7FU, 0xDC9694U,
480 | 0xDCA741U, 0xDCBFAAU, 0xDCC4E8U, 0xDCDC03U, 0xDCEDD6U, 0xDCF53DU, 0xDD00DEU, 0xDD1835U, 0xDD29E0U, 0xDD310BU,
481 | 0xDD4A49U, 0xDD52A2U, 0xDD6377U, 0xDD7B9CU, 0xDD8D18U, 0xDD95F3U, 0xDDA426U, 0xDDBCCDU, 0xDDC78FU, 0xDDDF64U,
482 | 0xDDEEB1U, 0xDDF65AU, 0xDE0574U, 0xDE1D9FU, 0xDE2C4AU, 0xDE34A1U, 0xDE4FE3U, 0xDE5708U, 0xDE66DDU, 0xDE7E36U,
483 | 0xDE88B2U, 0xDE9059U, 0xDEA18CU, 0xDEB967U, 0xDEC225U, 0xDEDACEU, 0xDEEB1BU, 0xDEF3F0U, 0xDF0613U, 0xDF1EF8U,
484 | 0xDF2F2DU, 0xDF37C6U, 0xDF4C84U, 0xDF546FU, 0xDF65BAU, 0xDF7D51U, 0xDF8BD5U, 0xDF933EU, 0xDFA2EBU, 0xDFBA00U,
485 | 0xDFC142U, 0xDFD9A9U, 0xDFE87CU, 0xDFF097U, 0xE00526U, 0xE01DCDU, 0xE02C18U, 0xE034F3U, 0xE04FB1U, 0xE0575AU,
486 | 0xE0668FU, 0xE07E64U, 0xE088E0U, 0xE0900BU, 0xE0A1DEU, 0xE0B935U, 0xE0C277U, 0xE0DA9CU, 0xE0EB49U, 0xE0F3A2U,
487 | 0xE10641U, 0xE11EAAU, 0xE12F7FU, 0xE13794U, 0xE14CD6U, 0xE1543DU, 0xE165E8U, 0xE17D03U, 0xE18B87U, 0xE1936CU,
488 | 0xE1A2B9U, 0xE1BA52U, 0xE1C110U, 0xE1D9FBU, 0xE1E82EU, 0xE1F0C5U, 0xE203EBU, 0xE21B00U, 0xE22AD5U, 0xE2323EU,
489 | 0xE2497CU, 0xE25197U, 0xE26042U, 0xE278A9U, 0xE28E2DU, 0xE296C6U, 0xE2A713U, 0xE2BFF8U, 0xE2C4BAU, 0xE2DC51U,
490 | 0xE2ED84U, 0xE2F56FU, 0xE3008CU, 0xE31867U, 0xE329B2U, 0xE33159U, 0xE34A1BU, 0xE352F0U, 0xE36325U, 0xE37BCEU,
491 | 0xE38D4AU, 0xE395A1U, 0xE3A474U, 0xE3BC9FU, 0xE3C7DDU, 0xE3DF36U, 0xE3EEE3U, 0xE3F608U, 0xE408BFU, 0xE41054U,
492 | 0xE42181U, 0xE4396AU, 0xE44228U, 0xE45AC3U, 0xE46B16U, 0xE473FDU, 0xE48579U, 0xE49D92U, 0xE4AC47U, 0xE4B4ACU,
493 | 0xE4CFEEU, 0xE4D705U, 0xE4E6D0U, 0xE4FE3BU, 0xE50BD8U, 0xE51333U, 0xE522E6U, 0xE53A0DU, 0xE5414FU, 0xE559A4U,
494 | 0xE56871U, 0xE5709AU, 0xE5861EU, 0xE59EF5U, 0xE5AF20U, 0xE5B7CBU, 0xE5CC89U, 0xE5D462U, 0xE5E5B7U, 0xE5FD5CU,
495 | 0xE60E72U, 0xE61699U, 0xE6274CU, 0xE63FA7U, 0xE644E5U, 0xE65C0EU, 0xE66DDBU, 0xE67530U, 0xE683B4U, 0xE69B5FU,
496 | 0xE6AA8AU, 0xE6B261U, 0xE6C923U, 0xE6D1C8U, 0xE6E01DU, 0xE6F8F6U, 0xE70D15U, 0xE715FEU, 0xE7242BU, 0xE73CC0U,
497 | 0xE74782U, 0xE75F69U, 0xE76EBCU, 0xE77657U, 0xE780D3U, 0xE79838U, 0xE7A9EDU, 0xE7B106U, 0xE7CA44U, 0xE7D2AFU,
498 | 0xE7E37AU, 0xE7FB91U, 0xE806FCU, 0xE81E17U, 0xE82FC2U, 0xE83729U, 0xE84C6BU, 0xE85480U, 0xE86555U, 0xE87DBEU,
499 | 0xE88B3AU, 0xE893D1U, 0xE8A204U, 0xE8BAEFU, 0xE8C1ADU, 0xE8D946U, 0xE8E893U, 0xE8F078U, 0xE9059BU, 0xE91D70U,
500 | 0xE92CA5U, 0xE9344EU, 0xE94F0CU, 0xE957E7U, 0xE96632U, 0xE97ED9U, 0xE9885DU, 0xE990B6U, 0xE9A163U, 0xE9B988U,
501 | 0xE9C2CAU, 0xE9DA21U, 0xE9EBF4U, 0xE9F31FU, 0xEA0031U, 0xEA18DAU, 0xEA290FU, 0xEA31E4U, 0xEA4AA6U, 0xEA524DU,
502 | 0xEA6398U, 0xEA7B73U, 0xEA8DF7U, 0xEA951CU, 0xEAA4C9U, 0xEABC22U, 0xEAC760U, 0xEADF8BU, 0xEAEE5EU, 0xEAF6B5U,
503 | 0xEB0356U, 0xEB1BBDU, 0xEB2A68U, 0xEB3283U, 0xEB49C1U, 0xEB512AU, 0xEB60FFU, 0xEB7814U, 0xEB8E90U, 0xEB967BU,
504 | 0xEBA7AEU, 0xEBBF45U, 0xEBC407U, 0xEBDCECU, 0xEBED39U, 0xEBF5D2U, 0xEC0B65U, 0xEC138EU, 0xEC225BU, 0xEC3AB0U,
505 | 0xEC41F2U, 0xEC5919U, 0xEC68CCU, 0xEC7027U, 0xEC86A3U, 0xEC9E48U, 0xECAF9DU, 0xECB776U, 0xECCC34U, 0xECD4DFU,
506 | 0xECE50AU, 0xECFDE1U, 0xED0802U, 0xED10E9U, 0xED213CU, 0xED39D7U, 0xED4295U, 0xED5A7EU, 0xED6BABU, 0xED7340U,
507 | 0xED85C4U, 0xED9D2FU, 0xEDACFAU, 0xEDB411U, 0xEDCF53U, 0xEDD7B8U, 0xEDE66DU, 0xEDFE86U, 0xEE0DA8U, 0xEE1543U,
508 | 0xEE2496U, 0xEE3C7DU, 0xEE473FU, 0xEE5FD4U, 0xEE6E01U, 0xEE76EAU, 0xEE806EU, 0xEE9885U, 0xEEA950U, 0xEEB1BBU,
509 | 0xEECAF9U, 0xEED212U, 0xEEE3C7U, 0xEEFB2CU, 0xEF0ECFU, 0xEF1624U, 0xEF27F1U, 0xEF3F1AU, 0xEF4458U, 0xEF5CB3U,
510 | 0xEF6D66U, 0xEF758DU, 0xEF8309U, 0xEF9BE2U, 0xEFAA37U, 0xEFB2DCU, 0xEFC99EU, 0xEFD175U, 0xEFE0A0U, 0xEFF84BU,
511 | 0xF00292U, 0xF01A79U, 0xF02BACU, 0xF03347U, 0xF04805U, 0xF050EEU, 0xF0613BU, 0xF079D0U, 0xF08F54U, 0xF097BFU,
512 | 0xF0A66AU, 0xF0BE81U, 0xF0C5C3U, 0xF0DD28U, 0xF0ECFDU, 0xF0F416U, 0xF101F5U, 0xF1191EU, 0xF128CBU, 0xF13020U,
513 | 0xF14B62U, 0xF15389U, 0xF1625CU, 0xF17AB7U, 0xF18C33U, 0xF194D8U, 0xF1A50DU, 0xF1BDE6U, 0xF1C6A4U, 0xF1DE4FU,
514 | 0xF1EF9AU, 0xF1F771U, 0xF2045FU, 0xF21CB4U, 0xF22D61U, 0xF2358AU, 0xF24EC8U, 0xF25623U, 0xF267F6U, 0xF27F1DU,
515 | 0xF28999U, 0xF29172U, 0xF2A0A7U, 0xF2B84CU, 0xF2C30EU, 0xF2DBE5U, 0xF2EA30U, 0xF2F2DBU, 0xF30738U, 0xF31FD3U,
516 | 0xF32E06U, 0xF336EDU, 0xF34DAFU, 0xF35544U, 0xF36491U, 0xF37C7AU, 0xF38AFEU, 0xF39215U, 0xF3A3C0U, 0xF3BB2BU,
517 | 0xF3C069U, 0xF3D882U, 0xF3E957U, 0xF3F1BCU, 0xF40F0BU, 0xF417E0U, 0xF42635U, 0xF43EDEU, 0xF4459CU, 0xF45D77U,
518 | 0xF46CA2U, 0xF47449U, 0xF482CDU, 0xF49A26U, 0xF4ABF3U, 0xF4B318U, 0xF4C85AU, 0xF4D0B1U, 0xF4E164U, 0xF4F98FU,
519 | 0xF50C6CU, 0xF51487U, 0xF52552U, 0xF53DB9U, 0xF546FBU, 0xF55E10U, 0xF56FC5U, 0xF5772EU, 0xF581AAU, 0xF59941U,
520 | 0xF5A894U, 0xF5B07FU, 0xF5CB3DU, 0xF5D3D6U, 0xF5E203U, 0xF5FAE8U, 0xF609C6U, 0xF6112DU, 0xF620F8U, 0xF63813U,
521 | 0xF64351U, 0xF65BBAU, 0xF66A6FU, 0xF67284U, 0xF68400U, 0xF69CEBU, 0xF6AD3EU, 0xF6B5D5U, 0xF6CE97U, 0xF6D67CU,
522 | 0xF6E7A9U, 0xF6FF42U, 0xF70AA1U, 0xF7124AU, 0xF7239FU, 0xF73B74U, 0xF74036U, 0xF758DDU, 0xF76908U, 0xF771E3U,
523 | 0xF78767U, 0xF79F8CU, 0xF7AE59U, 0xF7B6B2U, 0xF7CDF0U, 0xF7D51BU, 0xF7E4CEU, 0xF7FC25U, 0xF80148U, 0xF819A3U,
524 | 0xF82876U, 0xF8309DU, 0xF84BDFU, 0xF85334U, 0xF862E1U, 0xF87A0AU, 0xF88C8EU, 0xF89465U, 0xF8A5B0U, 0xF8BD5BU,
525 | 0xF8C619U, 0xF8DEF2U, 0xF8EF27U, 0xF8F7CCU, 0xF9022FU, 0xF91AC4U, 0xF92B11U, 0xF933FAU, 0xF948B8U, 0xF95053U,
526 | 0xF96186U, 0xF9796DU, 0xF98FE9U, 0xF99702U, 0xF9A6D7U, 0xF9BE3CU, 0xF9C57EU, 0xF9DD95U, 0xF9EC40U, 0xF9F4ABU,
527 | 0xFA0785U, 0xFA1F6EU, 0xFA2EBBU, 0xFA3650U, 0xFA4D12U, 0xFA55F9U, 0xFA642CU, 0xFA7CC7U, 0xFA8A43U, 0xFA92A8U,
528 | 0xFAA37DU, 0xFABB96U, 0xFAC0D4U, 0xFAD83FU, 0xFAE9EAU, 0xFAF101U, 0xFB04E2U, 0xFB1C09U, 0xFB2DDCU, 0xFB3537U,
529 | 0xFB4E75U, 0xFB569EU, 0xFB674BU, 0xFB7FA0U, 0xFB8924U, 0xFB91CFU, 0xFBA01AU, 0xFBB8F1U, 0xFBC3B3U, 0xFBDB58U,
530 | 0xFBEA8DU, 0xFBF266U, 0xFC0CD1U, 0xFC143AU, 0xFC25EFU, 0xFC3D04U, 0xFC4646U, 0xFC5EADU, 0xFC6F78U, 0xFC7793U,
531 | 0xFC8117U, 0xFC99FCU, 0xFCA829U, 0xFCB0C2U, 0xFCCB80U, 0xFCD36BU, 0xFCE2BEU, 0xFCFA55U, 0xFD0FB6U, 0xFD175DU,
532 | 0xFD2688U, 0xFD3E63U, 0xFD4521U, 0xFD5DCAU, 0xFD6C1FU, 0xFD74F4U, 0xFD8270U, 0xFD9A9BU, 0xFDAB4EU, 0xFDB3A5U,
533 | 0xFDC8E7U, 0xFDD00CU, 0xFDE1D9U, 0xFDF932U, 0xFE0A1CU, 0xFE12F7U, 0xFE2322U, 0xFE3BC9U, 0xFE408BU, 0xFE5860U,
534 | 0xFE69B5U, 0xFE715EU, 0xFE87DAU, 0xFE9F31U, 0xFEAEE4U, 0xFEB60FU, 0xFECD4DU, 0xFED5A6U, 0xFEE473U, 0xFEFC98U,
535 | 0xFF097BU, 0xFF1190U, 0xFF2045U, 0xFF38AEU, 0xFF43ECU, 0xFF5B07U, 0xFF6AD2U, 0xFF7239U, 0xFF84BDU, 0xFF9C56U,
536 | 0xFFAD83U, 0xFFB568U, 0xFFCE2AU, 0xFFD6C1U, 0xFFE714U, 0xFFFFFFU};
537 |
538 |
539 | static const unsigned int DECODING_TABLE_23127[] = {
540 | 0x000000U, 0x000001U, 0x000002U, 0x000003U, 0x000004U, 0x000005U, 0x000006U, 0x000007U, 0x000008U, 0x000009U,
541 | 0x00000AU, 0x00000BU, 0x00000CU, 0x00000DU, 0x00000EU, 0x024020U, 0x000010U, 0x000011U, 0x000012U, 0x000013U,
542 | 0x000014U, 0x000015U, 0x000016U, 0x412000U, 0x000018U, 0x000019U, 0x00001AU, 0x180800U, 0x00001CU, 0x200300U,
543 | 0x048040U, 0x001480U, 0x000020U, 0x000021U, 0x000022U, 0x000023U, 0x000024U, 0x000025U, 0x000026U, 0x024008U,
544 | 0x000028U, 0x000029U, 0x00002AU, 0x024004U, 0x00002CU, 0x024002U, 0x024001U, 0x024000U, 0x000030U, 0x000031U,
545 | 0x000032U, 0x008180U, 0x000034U, 0x000C40U, 0x301000U, 0x0C0200U, 0x000038U, 0x043000U, 0x400600U, 0x210040U,
546 | 0x090080U, 0x508000U, 0x002900U, 0x024010U, 0x000040U, 0x000041U, 0x000042U, 0x000043U, 0x000044U, 0x000045U,
547 | 0x000046U, 0x280080U, 0x000048U, 0x000049U, 0x00004AU, 0x002500U, 0x00004CU, 0x111000U, 0x048010U, 0x400A00U,
548 | 0x000050U, 0x000051U, 0x000052U, 0x021200U, 0x000054U, 0x000C20U, 0x048008U, 0x104100U, 0x000058U, 0x404080U,
549 | 0x048004U, 0x210020U, 0x048002U, 0x0A2000U, 0x048000U, 0x048001U, 0x000060U, 0x000061U, 0x000062U, 0x540000U,
550 | 0x000064U, 0x000C10U, 0x010300U, 0x00B000U, 0x000068U, 0x088200U, 0x001880U, 0x210010U, 0x602000U, 0x040180U,
551 | 0x180400U, 0x024040U, 0x000070U, 0x000C04U, 0x086000U, 0x210008U, 0x000C01U, 0x000C00U, 0x420080U, 0x000C02U,
552 | 0x120100U, 0x210002U, 0x210001U, 0x210000U, 0x005200U, 0x000C08U, 0x048020U, 0x210004U, 0x000080U, 0x000081U,
553 | 0x000082U, 0x000083U, 0x000084U, 0x000085U, 0x000086U, 0x280040U, 0x000088U, 0x000089U, 0x00008AU, 0x050200U,
554 | 0x00008CU, 0x00A800U, 0x500100U, 0x001410U, 0x000090U, 0x000091U, 0x000092U, 0x008120U, 0x000094U, 0x160000U,
555 | 0x004A00U, 0x001408U, 0x000098U, 0x404040U, 0x222000U, 0x001404U, 0x090020U, 0x001402U, 0x001401U, 0x001400U,
556 | 0x0000A0U, 0x0000A1U, 0x0000A2U, 0x008110U, 0x0000A4U, 0x401200U, 0x042400U, 0x110800U, 0x0000A8U, 0x300400U,
557 | 0x001840U, 0x482000U, 0x090010U, 0x040140U, 0x208200U, 0x024080U, 0x0000B0U, 0x008102U, 0x008101U, 0x008100U,
558 | 0x090008U, 0x206000U, 0x420040U, 0x008104U, 0x090004U, 0x020A00U, 0x144000U, 0x008108U, 0x090000U, 0x090001U,
559 | 0x090002U, 0x001420U, 0x0000C0U, 0x0000C1U, 0x0000C2U, 0x280004U, 0x0000C4U, 0x280002U, 0x280001U, 0x280000U,
560 | 0x0000C8U, 0x404010U, 0x001820U, 0x128000U, 0x020600U, 0x040120U, 0x016000U, 0x280008U, 0x0000D0U, 0x404008U,
561 | 0x110400U, 0x042800U, 0x003100U, 0x018200U, 0x420020U, 0x280010U, 0x404001U, 0x404000U, 0x080300U, 0x404002U,
562 | 0x300800U, 0x404004U, 0x048080U, 0x001440U, 0x0000E0U, 0x032000U, 0x001808U, 0x004600U, 0x10C000U, 0x040108U,
563 | 0x420010U, 0x280020U, 0x001802U, 0x040104U, 0x001800U, 0x001801U, 0x040101U, 0x040100U, 0x001804U, 0x040102U,
564 | 0x240200U, 0x181000U, 0x420004U, 0x008140U, 0x420002U, 0x000C80U, 0x420000U, 0x420001U, 0x00A400U, 0x404020U,
565 | 0x001810U, 0x210080U, 0x090040U, 0x040110U, 0x420008U, 0x102200U, 0x000100U, 0x000101U, 0x000102U, 0x000103U,
566 | 0x000104U, 0x000105U, 0x000106U, 0x041800U, 0x000108U, 0x000109U, 0x00010AU, 0x002440U, 0x00010CU, 0x200210U,
567 | 0x500080U, 0x098000U, 0x000110U, 0x000111U, 0x000112U, 0x0080A0U, 0x000114U, 0x200208U, 0x0A0400U, 0x104040U,
568 | 0x000118U, 0x200204U, 0x015000U, 0x460000U, 0x200201U, 0x200200U, 0x002820U, 0x200202U, 0x000120U, 0x000121U,
569 | 0x000122U, 0x008090U, 0x000124U, 0x182000U, 0x010240U, 0x600400U, 0x000128U, 0x410800U, 0x2C0000U, 0x101200U,
570 | 0x009400U, 0x0400C0U, 0x002810U, 0x024100U, 0x000130U, 0x008082U, 0x008081U, 0x008080U, 0x444000U, 0x031000U,
571 | 0x002808U, 0x008084U, 0x120040U, 0x084400U, 0x002804U, 0x008088U, 0x002802U, 0x200220U, 0x002800U, 0x002801U,
572 | 0x000140U, 0x000141U, 0x000142U, 0x002408U, 0x000144U, 0x428000U, 0x010220U, 0x104010U, 0x000148U, 0x002402U,
573 | 0x002401U, 0x002400U, 0x084800U, 0x0400A0U, 0x221000U, 0x002404U, 0x000150U, 0x0D0000U, 0x600800U, 0x104004U,
574 | 0x003080U, 0x104002U, 0x104001U, 0x104000U, 0x120020U, 0x009800U, 0x080280U, 0x002410U, 0x410400U, 0x200240U,
575 | 0x048100U, 0x104008U, 0x000160U, 0x205000U, 0x010204U, 0x0A0800U, 0x010202U, 0x040088U, 0x010200U, 0x010201U,
576 | 0x120010U, 0x040084U, 0x40C000U, 0x002420U, 0x040081U, 0x040080U, 0x010208U, 0x040082U, 0x120008U, 0x402200U,
577 | 0x041400U, 0x0080C0U, 0x288000U, 0x000D00U, 0x010210U, 0x104020U, 0x120000U, 0x120001U, 0x120002U, 0x210100U,
578 | 0x120004U, 0x040090U, 0x002840U, 0x481000U, 0x000180U, 0x000181U, 0x000182U, 0x008030U, 0x000184U, 0x014400U,
579 | 0x500008U, 0x022200U, 0x000188U, 0x0A1000U, 0x500004U, 0x204800U, 0x500002U, 0x040060U, 0x500000U, 0x500001U,
580 | 0x000190U, 0x008022U, 0x008021U, 0x008020U, 0x003040U, 0x480800U, 0x250000U, 0x008024U, 0x040C00U, 0x112000U,
581 | 0x080240U, 0x008028U, 0x02C000U, 0x200280U, 0x500010U, 0x001500U, 0x0001A0U, 0x008012U, 0x008011U, 0x008010U,
582 | 0x220800U, 0x040048U, 0x085000U, 0x008014U, 0x006200U, 0x040044U, 0x030400U, 0x008018U, 0x040041U, 0x040040U,
583 | 0x500020U, 0x040042U, 0x008003U, 0x008002U, 0x008001U, 0x008000U, 0x100600U, 0x008006U, 0x008005U, 0x008004U,
584 | 0x601000U, 0x00800AU, 0x008009U, 0x008008U, 0x090100U, 0x040050U, 0x002880U, 0x00800CU, 0x0001C0U, 0x100A00U,
585 | 0x064000U, 0x411000U, 0x003010U, 0x040028U, 0x008C00U, 0x280100U, 0x218000U, 0x040024U, 0x080210U, 0x002480U,
586 | 0x040021U, 0x040020U, 0x500040U, 0x040022U, 0x003004U, 0x220400U, 0x080208U, 0x008060U, 0x003000U, 0x003001U,
587 | 0x003002U, 0x104080U, 0x080202U, 0x404100U, 0x080200U, 0x080201U, 0x003008U, 0x040030U, 0x080204U, 0x030800U,
588 | 0x480400U, 0x04000CU, 0x302000U, 0x008050U, 0x040009U, 0x040008U, 0x010280U, 0x04000AU, 0x040005U, 0x040004U,
589 | 0x001900U, 0x040006U, 0x040001U, 0x040000U, 0x040003U, 0x040002U, 0x014800U, 0x008042U, 0x008041U, 0x008040U,
590 | 0x003020U, 0x040018U, 0x420100U, 0x008044U, 0x120080U, 0x040014U, 0x080220U, 0x008048U, 0x040011U, 0x040010U,
591 | 0x204400U, 0x040012U, 0x000200U, 0x000201U, 0x000202U, 0x000203U, 0x000204U, 0x000205U, 0x000206U, 0x108400U,
592 | 0x000208U, 0x000209U, 0x00020AU, 0x050080U, 0x00020CU, 0x200110U, 0x083000U, 0x400840U, 0x000210U, 0x000211U,
593 | 0x000212U, 0x021040U, 0x000214U, 0x200108U, 0x004880U, 0x0C0020U, 0x000218U, 0x200104U, 0x400420U, 0x00E000U,
594 | 0x200101U, 0x200100U, 0x130000U, 0x200102U, 0x000220U, 0x000221U, 0x000222U, 0x202800U, 0x000224U, 0x401080U,
595 | 0x010140U, 0x0C0010U, 0x000228U, 0x088040U, 0x400410U, 0x101100U, 0x140800U, 0x012400U, 0x208080U, 0x024200U,
596 | 0x000230U, 0x114000U, 0x400408U, 0x0C0004U, 0x02A000U, 0x0C0002U, 0x0C0001U, 0x0C0000U, 0x400402U, 0x020880U,
597 | 0x400400U, 0x400401U, 0x005040U, 0x200120U, 0x400404U, 0x0C0008U, 0x000240U, 0x000241U, 0x000242U, 0x021010U,
598 | 0x000244U, 0x046000U, 0x010120U, 0x400808U, 0x000248U, 0x088020U, 0x304000U, 0x400804U, 0x020480U, 0x400802U,
599 | 0x400801U, 0x400800U, 0x000250U, 0x021002U, 0x021001U, 0x021000U, 0x580000U, 0x018080U, 0x202400U, 0x021004U,
600 | 0x012800U, 0x140400U, 0x080180U, 0x021008U, 0x005020U, 0x200140U, 0x048200U, 0x400810U, 0x000260U, 0x088008U,
601 | 0x010104U, 0x004480U, 0x010102U, 0x320000U, 0x010100U, 0x010101U, 0x088001U, 0x088000U, 0x062000U, 0x088002U,
602 | 0x005010U, 0x088004U, 0x010108U, 0x400820U, 0x240080U, 0x402100U, 0x108800U, 0x021020U, 0x005008U, 0x000E00U,
603 | 0x010110U, 0x0C0040U, 0x005004U, 0x088010U, 0x400440U, 0x210200U, 0x005000U, 0x005001U, 0x005002U, 0x102080U,
604 | 0x000280U, 0x000281U, 0x000282U, 0x050008U, 0x000284U, 0x401020U, 0x004810U, 0x022100U, 0x000288U, 0x050002U,
605 | 0x050001U, 0x050000U, 0x020440U, 0x184000U, 0x208020U, 0x050004U, 0x000290U, 0x082400U, 0x004804U, 0x700000U,
606 | 0x004802U, 0x018040U, 0x004800U, 0x004801U, 0x109000U, 0x020820U, 0x080140U, 0x050010U, 0x442000U, 0x200180U,
607 | 0x004808U, 0x001600U, 0x0002A0U, 0x401004U, 0x1A0000U, 0x004440U, 0x401001U, 0x401000U, 0x208008U, 0x401002U,
608 | 0x006100U, 0x020810U, 0x208004U, 0x050020U, 0x208002U, 0x401008U, 0x208000U, 0x208001U, 0x240040U, 0x020808U,
609 | 0x013000U, 0x008300U, 0x100500U, 0x401010U, 0x004820U, 0x0C0080U, 0x020801U, 0x020800U, 0x400480U, 0x020802U,
610 | 0x090200U, 0x020804U, 0x208010U, 0x102040U, 0x0002C0U, 0x100900U, 0x40A000U, 0x004420U, 0x020408U, 0x018010U,
611 | 0x141000U, 0x280200U, 0x020404U, 0x203000U, 0x080110U, 0x050040U, 0x020400U, 0x020401U, 0x020402U, 0x400880U,
612 | 0x240020U, 0x018004U, 0x080108U, 0x021080U, 0x018001U, 0x018000U, 0x004840U, 0x018002U, 0x080102U, 0x404200U,
613 | 0x080100U, 0x080101U, 0x020410U, 0x018008U, 0x080104U, 0x102020U, 0x240010U, 0x004402U, 0x004401U, 0x004400U,
614 | 0x082800U, 0x401040U, 0x010180U, 0x004404U, 0x510000U, 0x088080U, 0x001A00U, 0x004408U, 0x020420U, 0x040300U,
615 | 0x208040U, 0x102010U, 0x240000U, 0x240001U, 0x240002U, 0x004410U, 0x240004U, 0x018020U, 0x420200U, 0x102008U,
616 | 0x240008U, 0x020840U, 0x080120U, 0x102004U, 0x005080U, 0x102002U, 0x102001U, 0x102000U, 0x000300U, 0x000301U,
617 | 0x000302U, 0x484000U, 0x000304U, 0x200018U, 0x010060U, 0x022080U, 0x000308U, 0x200014U, 0x028800U, 0x101020U,
618 | 0x200011U, 0x200010U, 0x044400U, 0x200012U, 0x000310U, 0x20000CU, 0x142000U, 0x010C00U, 0x200009U, 0x200008U,
619 | 0x409000U, 0x20000AU, 0x200005U, 0x200004U, 0x0800C0U, 0x200006U, 0x200001U, 0x200000U, 0x200003U, 0x200002U,
620 | 0x000320U, 0x060400U, 0x010044U, 0x101008U, 0x010042U, 0x00C800U, 0x010040U, 0x010041U, 0x006080U, 0x101002U,
621 | 0x101001U, 0x101000U, 0x4A0000U, 0x200030U, 0x010048U, 0x101004U, 0x081800U, 0x402040U, 0x224000U, 0x008280U,
622 | 0x100480U, 0x200028U, 0x010050U, 0x0C0100U, 0x058000U, 0x200024U, 0x400500U, 0x101010U, 0x200021U, 0x200020U,
623 | 0x002A00U, 0x200022U, 0x000340U, 0x100880U, 0x010024U, 0x248000U, 0x010022U, 0x081400U, 0x010020U, 0x010021U,
624 | 0x441000U, 0x034000U, 0x080090U, 0x002600U, 0x10A000U, 0x200050U, 0x010028U, 0x400900U, 0x00C400U, 0x402020U,
625 | 0x080088U, 0x021100U, 0x060800U, 0x200048U, 0x010030U, 0x104200U, 0x080082U, 0x200044U, 0x080080U, 0x080081U,
626 | 0x200041U, 0x200040U, 0x080084U, 0x200042U, 0x010006U, 0x402010U, 0x010004U, 0x010005U, 0x010002U, 0x010003U,
627 | 0x010000U, 0x010001U, 0x200C00U, 0x088100U, 0x01000CU, 0x101040U, 0x01000AU, 0x040280U, 0x010008U, 0x010009U,
628 | 0x402001U, 0x402000U, 0x010014U, 0x402002U, 0x010012U, 0x402004U, 0x010010U, 0x010011U, 0x120200U, 0x402008U,
629 | 0x0800A0U, 0x044800U, 0x005100U, 0x200060U, 0x010018U, 0x028400U, 0x000380U, 0x100840U, 0x201400U, 0x022004U,
630 | 0x0C8000U, 0x022002U, 0x022001U, 0x022000U, 0x006020U, 0x408400U, 0x080050U, 0x050100U, 0x011800U, 0x200090U,
631 | 0x500200U, 0x022008U, 0x430000U, 0x045000U, 0x080048U, 0x008220U, 0x100420U, 0x200088U, 0x004900U, 0x022010U,
632 | 0x080042U, 0x200084U, 0x080040U, 0x080041U, 0x200081U, 0x200080U, 0x080044U, 0x200082U, 0x006008U, 0x290000U,
633 | 0x440800U, 0x008210U, 0x100410U, 0x401100U, 0x0100C0U, 0x022020U, 0x006000U, 0x006001U, 0x006002U, 0x101080U,
634 | 0x006004U, 0x040240U, 0x208100U, 0x080C00U, 0x100404U, 0x008202U, 0x008201U, 0x008200U, 0x100400U, 0x100401U,
635 | 0x100402U, 0x008204U, 0x006010U, 0x020900U, 0x080060U, 0x008208U, 0x100408U, 0x2000A0U, 0x061000U, 0x414000U,
636 | 0x100801U, 0x100800U, 0x080018U, 0x100802U, 0x604000U, 0x100804U, 0x0100A0U, 0x022040U, 0x080012U, 0x100808U,
637 | 0x080010U, 0x080011U, 0x020500U, 0x040220U, 0x080014U, 0x00D000U, 0x08000AU, 0x100810U, 0x080008U, 0x080009U,
638 | 0x003200U, 0x018100U, 0x08000CU, 0x440400U, 0x080002U, 0x080003U, 0x080000U, 0x080001U, 0x080006U, 0x2000C0U,
639 | 0x080004U, 0x080005U, 0x029000U, 0x100820U, 0x010084U, 0x004500U, 0x010082U, 0x040208U, 0x010080U, 0x010081U,
640 | 0x006040U, 0x040204U, 0x080030U, 0x620000U, 0x040201U, 0x040200U, 0x010088U, 0x040202U, 0x240100U, 0x402080U,
641 | 0x080028U, 0x008240U, 0x100440U, 0x0A4000U, 0x010090U, 0x201800U, 0x080022U, 0x011400U, 0x080020U, 0x080021U,
642 | 0x408800U, 0x040210U, 0x080024U, 0x102100U, 0x000400U, 0x000401U, 0x000402U, 0x000403U, 0x000404U, 0x000405U,
643 | 0x000406U, 0x108200U, 0x000408U, 0x000409U, 0x00040AU, 0x002140U, 0x00040CU, 0x4C0000U, 0x210800U, 0x001090U,
644 | 0x000410U, 0x000411U, 0x000412U, 0x244000U, 0x000414U, 0x000860U, 0x0A0100U, 0x001088U, 0x000418U, 0x038000U,
645 | 0x400220U, 0x001084U, 0x106000U, 0x001082U, 0x001081U, 0x001080U, 0x000420U, 0x000421U, 0x000422U, 0x091000U,
646 | 0x000424U, 0x000850U, 0x042080U, 0x600100U, 0x000428U, 0x300080U, 0x400210U, 0x048800U, 0x009100U, 0x012200U,
647 | 0x180040U, 0x024400U, 0x000430U, 0x000844U, 0x400208U, 0x122000U, 0x000841U, 0x000840U, 0x01C000U, 0x000842U,
648 | 0x400202U, 0x084100U, 0x400200U, 0x400201U, 0x260000U, 0x000848U, 0x400204U, 0x0010A0U, 0x000440U, 0x000441U,
649 | 0x000442U, 0x002108U, 0x000444U, 0x000830U, 0x405000U, 0x070000U, 0x000448U, 0x002102U, 0x002101U, 0x002100U,
650 | 0x020280U, 0x20C000U, 0x180020U, 0x002104U, 0x000450U, 0x000824U, 0x110080U, 0x488000U, 0x000821U, 0x000820U,
651 | 0x202200U, 0x000822U, 0x281000U, 0x140200U, 0x024800U, 0x002110U, 0x410100U, 0x000828U, 0x048400U, 0x0010C0U,
652 | 0x000460U, 0x000814U, 0x228000U, 0x004280U, 0x000811U, 0x000810U, 0x180008U, 0x000812U, 0x054000U, 0x421000U,
653 | 0x180004U, 0x002120U, 0x180002U, 0x000818U, 0x180000U, 0x180001U, 0x000805U, 0x000804U, 0x041100U, 0x000806U,
654 | 0x000801U, 0x000800U, 0x000803U, 0x000802U, 0x00A080U, 0x00080CU, 0x400240U, 0x210400U, 0x000809U, 0x000808U,
655 | 0x180010U, 0x00080AU, 0x000480U, 0x000481U, 0x000482U, 0x420800U, 0x000484U, 0x014100U, 0x042020U, 0x001018U,
656 | 0x000488U, 0x300020U, 0x08C000U, 0x001014U, 0x020240U, 0x001012U, 0x001011U, 0x001010U, 0x000490U, 0x082200U,
657 | 0x110040U, 0x00100CU, 0x608000U, 0x00100AU, 0x001009U, 0x001008U, 0x040900U, 0x001006U, 0x001005U, 0x001004U,
658 | 0x001003U, 0x001002U, 0x001001U, 0x001000U, 0x0004A0U, 0x300008U, 0x042004U, 0x004240U, 0x042002U, 0x0A8000U,
659 | 0x042000U, 0x042001U, 0x300001U, 0x300000U, 0x030100U, 0x300002U, 0x404800U, 0x300004U, 0x042008U, 0x001030U,
660 | 0x025000U, 0x450000U, 0x280800U, 0x008500U, 0x100300U, 0x0008C0U, 0x042010U, 0x001028U, 0x00A040U, 0x300010U,
661 | 0x400280U, 0x001024U, 0x090400U, 0x001022U, 0x001021U, 0x001020U, 0x0004C0U, 0x049000U, 0x110010U, 0x004220U,
662 | 0x020208U, 0x502000U, 0x008900U, 0x280400U, 0x020204U, 0x090800U, 0x640000U, 0x002180U, 0x020200U, 0x020201U,
663 | 0x020202U, 0x001050U, 0x110002U, 0x220100U, 0x110000U, 0x110001U, 0x0C4000U, 0x0008A0U, 0x110004U, 0x001048U,
664 | 0x00A020U, 0x404400U, 0x110008U, 0x001044U, 0x020210U, 0x001042U, 0x001041U, 0x001040U, 0x480100U, 0x004202U,
665 | 0x004201U, 0x004200U, 0x211000U, 0x000890U, 0x042040U, 0x004204U, 0x00A010U, 0x300040U, 0x001C00U, 0x004208U,
666 | 0x020220U, 0x040500U, 0x180080U, 0x418000U, 0x00A008U, 0x000884U, 0x110020U, 0x004210U, 0x000881U, 0x000880U,
667 | 0x420400U, 0x000882U, 0x00A000U, 0x00A001U, 0x00A002U, 0x0E0000U, 0x00A004U, 0x000888U, 0x204100U, 0x001060U,
668 | 0x000500U, 0x000501U, 0x000502U, 0x002048U, 0x000504U, 0x014080U, 0x0A0010U, 0x600020U, 0x000508U, 0x002042U,
669 | 0x002041U, 0x002040U, 0x009020U, 0x120800U, 0x044200U, 0x002044U, 0x000510U, 0x501000U, 0x0A0004U, 0x010A00U,
670 | 0x0A0002U, 0x04A000U, 0x0A0000U, 0x0A0001U, 0x040880U, 0x084020U, 0x308000U, 0x002050U, 0x410040U, 0x200600U,
671 | 0x0A0008U, 0x001180U, 0x000520U, 0x060200U, 0x104800U, 0x600004U, 0x009008U, 0x600002U, 0x600001U, 0x600000U,
672 | 0x009004U, 0x084010U, 0x030080U, 0x002060U, 0x009000U, 0x009001U, 0x009002U, 0x600008U, 0x212000U, 0x084008U,
673 | 0x041040U, 0x008480U, 0x100280U, 0x000940U, 0x0A0020U, 0x600010U, 0x084001U, 0x084000U, 0x400300U, 0x084002U,
674 | 0x009010U, 0x084004U, 0x002C00U, 0x150000U, 0x000540U, 0x00200AU, 0x002009U, 0x002008U, 0x340000U, 0x081200U,
675 | 0x008880U, 0x00200CU, 0x002003U, 0x002002U, 0x002001U, 0x002000U, 0x410010U, 0x002006U, 0x002005U, 0x002004U,
676 | 0x00C200U, 0x220080U, 0x041020U, 0x002018U, 0x410008U, 0x000920U, 0x0A0040U, 0x104400U, 0x410004U, 0x002012U,
677 | 0x002011U, 0x002010U, 0x410000U, 0x410001U, 0x410002U, 0x002014U, 0x480080U, 0x118000U, 0x041010U, 0x002028U,
678 | 0x026000U, 0x000910U, 0x010600U, 0x600040U, 0x200A00U, 0x002022U, 0x002021U, 0x002020U, 0x009040U, 0x040480U,
679 | 0x180100U, 0x002024U, 0x041002U, 0x000904U, 0x041000U, 0x041001U, 0x000901U, 0x000900U, 0x041004U, 0x000902U,
680 | 0x120400U, 0x084040U, 0x041008U, 0x002030U, 0x410020U, 0x000908U, 0x204080U, 0x028200U, 0x000580U, 0x014004U,
681 | 0x201200U, 0x1C0000U, 0x014001U, 0x014000U, 0x008840U, 0x014002U, 0x040810U, 0x408200U, 0x030020U, 0x0020C0U,
682 | 0x282000U, 0x014008U, 0x500400U, 0x001110U, 0x040808U, 0x220040U, 0x406000U, 0x008420U, 0x100220U, 0x014010U,
683 | 0x0A0080U, 0x001108U, 0x040800U, 0x040801U, 0x040802U, 0x001104U, 0x040804U, 0x001102U, 0x001101U, 0x001100U,
684 | 0x480040U, 0x003800U, 0x030008U, 0x008410U, 0x100210U, 0x014020U, 0x042100U, 0x600080U, 0x030002U, 0x300100U,
685 | 0x030000U, 0x030001U, 0x009080U, 0x040440U, 0x030004U, 0x080A00U, 0x100204U, 0x008402U, 0x008401U, 0x008400U,
686 | 0x100200U, 0x100201U, 0x100202U, 0x008404U, 0x040820U, 0x084080U, 0x030010U, 0x008408U, 0x100208U, 0x422000U,
687 | 0x204040U, 0x001120U, 0x480020U, 0x220010U, 0x008804U, 0x002088U, 0x008802U, 0x014040U, 0x008800U, 0x008801U,
688 | 0x105000U, 0x002082U, 0x002081U, 0x002080U, 0x020300U, 0x040420U, 0x008808U, 0x002084U, 0x220001U, 0x220000U,
689 | 0x110100U, 0x220002U, 0x003400U, 0x220004U, 0x008810U, 0x440200U, 0x040840U, 0x220008U, 0x080600U, 0x002090U,
690 | 0x410080U, 0x188000U, 0x204020U, 0x001140U, 0x480000U, 0x480001U, 0x480002U, 0x004300U, 0x480004U, 0x040408U,
691 | 0x008820U, 0x121000U, 0x480008U, 0x040404U, 0x030040U, 0x0020A0U, 0x040401U, 0x040400U, 0x204010U, 0x040402U,
692 | 0x480010U, 0x220020U, 0x041080U, 0x008440U, 0x100240U, 0x000980U, 0x204008U, 0x092000U, 0x00A100U, 0x011200U,
693 | 0x204004U, 0x500800U, 0x204002U, 0x040410U, 0x204000U, 0x204001U, 0x000600U, 0x000601U, 0x000602U, 0x108004U,
694 | 0x000604U, 0x108002U, 0x108001U, 0x108000U, 0x000608U, 0x005800U, 0x400030U, 0x2A0000U, 0x0200C0U, 0x012020U,
695 | 0x044100U, 0x108008U, 0x000610U, 0x082080U, 0x400028U, 0x010900U, 0x051000U, 0x424000U, 0x202040U, 0x108010U,
696 | 0x400022U, 0x140040U, 0x400020U, 0x400021U, 0x088800U, 0x200500U, 0x400024U, 0x001280U, 0x000620U, 0x060100U,
697 | 0x400018U, 0x0040C0U, 0x284000U, 0x012008U, 0x021800U, 0x108020U, 0x400012U, 0x012004U, 0x400010U, 0x400011U,
698 | 0x012001U, 0x012000U, 0x400014U, 0x012002U, 0x40000AU, 0x209000U, 0x400008U, 0x400009U, 0x100180U, 0x000A40U,
699 | 0x40000CU, 0x0C0400U, 0x400002U, 0x400003U, 0x400000U, 0x400001U, 0x400006U, 0x012010U, 0x400004U, 0x400005U,
700 | 0x000640U, 0x610000U, 0x0C0800U, 0x0040A0U, 0x020088U, 0x081100U, 0x202010U, 0x108040U, 0x020084U, 0x140010U,
701 | 0x019000U, 0x002300U, 0x020080U, 0x020081U, 0x020082U, 0x400C00U, 0x00C100U, 0x140008U, 0x202004U, 0x021400U,
702 | 0x202002U, 0x000A20U, 0x202000U, 0x202001U, 0x140001U, 0x140000U, 0x400060U, 0x140002U, 0x020090U, 0x140004U,
703 | 0x202008U, 0x094000U, 0x103000U, 0x004082U, 0x004081U, 0x004080U, 0x448000U, 0x000A10U, 0x010500U, 0x004084U,
704 | 0x200900U, 0x088400U, 0x400050U, 0x004088U, 0x0200A0U, 0x012040U, 0x180200U, 0x241000U, 0x0B0000U, 0x000A04U,
705 | 0x400048U, 0x004090U, 0x000A01U, 0x000A00U, 0x202020U, 0x000A02U, 0x400042U, 0x140020U, 0x400040U, 0x400041U,
706 | 0x005400U, 0x000A08U, 0x400044U, 0x028100U, 0x000680U, 0x082010U, 0x201100U, 0x004060U, 0x020048U, 0x240800U,
707 | 0x490000U, 0x108080U, 0x020044U, 0x408100U, 0x102800U, 0x050400U, 0x020040U, 0x020041U, 0x020042U, 0x001210U,
708 | 0x082001U, 0x082000U, 0x068000U, 0x082002U, 0x100120U, 0x082004U, 0x004C00U, 0x001208U, 0x214000U, 0x082008U,
709 | 0x4000A0U, 0x001204U, 0x020050U, 0x001202U, 0x001201U, 0x001200U, 0x018800U, 0x004042U, 0x004041U, 0x004040U,
710 | 0x100110U, 0x401400U, 0x042200U, 0x004044U, 0x0C1000U, 0x300200U, 0x400090U, 0x004048U, 0x020060U, 0x012080U,
711 | 0x208400U, 0x080900U, 0x100104U, 0x082020U, 0x400088U, 0x004050U, 0x100100U, 0x100101U, 0x100102U, 0x230000U,
712 | 0x400082U, 0x020C00U, 0x400080U, 0x400081U, 0x100108U, 0x04C000U, 0x400084U, 0x001220U, 0x02000CU, 0x004022U,
713 | 0x004021U, 0x004020U, 0x020008U, 0x020009U, 0x02000AU, 0x004024U, 0x020004U, 0x020005U, 0x020006U, 0x004028U,
714 | 0x020000U, 0x020001U, 0x020002U, 0x020003U, 0x401800U, 0x082040U, 0x110200U, 0x004030U, 0x020018U, 0x018400U,
715 | 0x202080U, 0x440100U, 0x020014U, 0x140080U, 0x080500U, 0x208800U, 0x020010U, 0x020011U, 0x020012U, 0x001240U,
716 | 0x004003U, 0x004002U, 0x004001U, 0x004000U, 0x020028U, 0x004006U, 0x004005U, 0x004004U, 0x020024U, 0x00400AU,
717 | 0x004009U, 0x004008U, 0x020020U, 0x020021U, 0x020022U, 0x00400CU, 0x240400U, 0x004012U, 0x004011U, 0x004010U,
718 | 0x100140U, 0x000A80U, 0x089000U, 0x004014U, 0x00A200U, 0x011100U, 0x4000C0U, 0x004018U, 0x020030U, 0x680000U,
719 | 0x050800U, 0x102400U, 0x000700U, 0x060020U, 0x201080U, 0x010810U, 0x402800U, 0x081040U, 0x044008U, 0x108100U,
720 | 0x190000U, 0x408080U, 0x044004U, 0x002240U, 0x044002U, 0x200410U, 0x044000U, 0x044001U, 0x00C040U, 0x010802U,
721 | 0x010801U, 0x010800U, 0x1000A0U, 0x200408U, 0x0A0200U, 0x010804U, 0x023000U, 0x200404U, 0x400120U, 0x010808U,
722 | 0x200401U, 0x200400U, 0x044010U, 0x200402U, 0x060001U, 0x060000U, 0x08A000U, 0x060002U, 0x100090U, 0x060004U,
723 | 0x010440U, 0x600200U, 0x200840U, 0x060008U, 0x400110U, 0x101400U, 0x009200U, 0x012100U, 0x044020U, 0x080880U,
724 | 0x100084U, 0x060010U, 0x400108U, 0x010820U, 0x100080U, 0x100081U, 0x100082U, 0x007000U, 0x400102U, 0x084200U,
725 | 0x400100U, 0x400101U, 0x100088U, 0x200420U, 0x400104U, 0x028040U, 0x00C010U, 0x081004U, 0x520000U, 0x002208U,
726 | 0x081001U, 0x081000U, 0x010420U, 0x081002U, 0x200820U, 0x002202U, 0x002201U, 0x002200U, 0x020180U, 0x081008U,
727 | 0x044040U, 0x002204U, 0x00C000U, 0x00C001U, 0x00C002U, 0x010840U, 0x00C004U, 0x081010U, 0x202100U, 0x440080U,
728 | 0x00C008U, 0x140100U, 0x080480U, 0x002210U, 0x410200U, 0x200440U, 0x101800U, 0x028020U, 0x200808U, 0x060040U,
729 | 0x010404U, 0x004180U, 0x010402U, 0x081020U, 0x010400U, 0x010401U, 0x200800U, 0x200801U, 0x200802U, 0x002220U,
730 | 0x200804U, 0x504000U, 0x010408U, 0x028010U, 0x00C020U, 0x402400U, 0x041200U, 0x380000U, 0x1000C0U, 0x000B00U,
731 | 0x010410U, 0x028008U, 0x200810U, 0x011080U, 0x400140U, 0x028004U, 0x0C2000U, 0x028002U, 0x028001U, 0x028000U,
732 | 0x201002U, 0x408008U, 0x201000U, 0x201001U, 0x100030U, 0x014200U, 0x201004U, 0x022400U, 0x408001U, 0x408000U,
733 | 0x201008U, 0x408002U, 0x020140U, 0x408004U, 0x044080U, 0x080820U, 0x100024U, 0x082100U, 0x201010U, 0x010880U,
734 | 0x100020U, 0x100021U, 0x100022U, 0x440040U, 0x040A00U, 0x408010U, 0x080440U, 0x124000U, 0x100028U, 0x200480U,
735 | 0x01A000U, 0x001300U, 0x100014U, 0x060080U, 0x201020U, 0x004140U, 0x100010U, 0x100011U, 0x100012U, 0x080808U,
736 | 0x006400U, 0x408020U, 0x030200U, 0x080804U, 0x100018U, 0x080802U, 0x080801U, 0x080800U, 0x100004U, 0x100005U,
737 | 0x100006U, 0x008600U, 0x100000U, 0x100001U, 0x100002U, 0x100003U, 0x10000CU, 0x011040U, 0x400180U, 0x242000U,
738 | 0x100008U, 0x100009U, 0x10000AU, 0x080810U, 0x052000U, 0x100C00U, 0x201040U, 0x004120U, 0x020108U, 0x081080U,
739 | 0x008A00U, 0x440010U, 0x020104U, 0x408040U, 0x080410U, 0x002280U, 0x020100U, 0x020101U, 0x020102U, 0x310000U,
740 | 0x00C080U, 0x220200U, 0x080408U, 0x440004U, 0x100060U, 0x440002U, 0x440001U, 0x440000U, 0x080402U, 0x011020U,
741 | 0x080400U, 0x080401U, 0x020110U, 0x006800U, 0x080404U, 0x440008U, 0x480200U, 0x004102U, 0x004101U, 0x004100U,
742 | 0x100050U, 0x20A000U, 0x010480U, 0x004104U, 0x200880U, 0x011010U, 0x148000U, 0x004108U, 0x020120U, 0x040600U,
743 | 0x403000U, 0x080840U, 0x100044U, 0x011008U, 0x022800U, 0x004110U, 0x100040U, 0x100041U, 0x100042U, 0x440020U,
744 | 0x011001U, 0x011000U, 0x080420U, 0x011002U, 0x100048U, 0x011004U, 0x204200U, 0x028080U};
745 |
746 | #define X22 0x00400000 /* vector representation of X^{22} */
747 | #define X11 0x00000800 /* vector representation of X^{11} */
748 | #define MASK12 0xfffff800 /* auxiliary vector for testing */
749 | #define GENPOL 0x00000c75 /* generator polinomial, g(x) */
750 |
751 | int max(int x, int y)
752 | {
753 | if (x > y)
754 | return x;
755 | else
756 | return y;
757 | }
758 |
759 | void process_signal(int sig)
760 | {
761 | static uint32_t c1 = 0;
762 | static uint32_t c2 = 0;
763 | if(sig == SIGINT){
764 | fprintf(stderr, "\n\nShutting down link\n");
765 | buf[0] = 'Y';
766 | buf[1] = 'S';
767 | buf[2] = 'F';
768 | buf[3] = 'U';
769 | memcpy(&buf[4], callsign, 10);
770 | sendto(udp1, buf, 14, 0, (const struct sockaddr *)&host1, sizeof(host1));
771 | sendto(udp2, buf, 14, 0, (const struct sockaddr *)&host2, sizeof(host2));
772 | close(udp1);
773 | close(udp2);
774 | exit(EXIT_SUCCESS);
775 | }
776 | if(sig == SIGALRM){
777 | buf[0] = 'Y';
778 | buf[1] = 'S';
779 | buf[2] = 'F';
780 | buf[3] = 'P';
781 | memcpy(&buf[4], callsign, 10);
782 | sendto(udp1, buf, 14, 0, (const struct sockaddr *)&host1, sizeof(host1));
783 | sendto(udp2, buf, 14, 0, (const struct sockaddr *)&host2, sizeof(host2));
784 | alarm(5);
785 | }
786 | #ifdef DEBUG
787 | fprintf(stderr, "SEND BOTH: ");
788 | for(int i = 0; i < 14; ++i){
789 | fprintf(stderr, "%02x ", buf[i]);
790 | }
791 | fprintf(stderr, "\n");
792 | fflush(stderr);
793 | #endif
794 | }
795 |
796 | void addCCITT162(unsigned char *in, unsigned int length)
797 | {
798 | union crc {
799 | uint16_t crc16;
800 | uint8_t crc8[2U];
801 | };
802 | union crc c;
803 |
804 | c.crc16 = 0U;
805 |
806 | for (unsigned i = 0U; i < (length - 2U); i++)
807 | c.crc16 = (uint16_t)((c.crc8[0U]) << 8) ^ CCITT16_TABLE2[c.crc8[1U] ^ in[i]];
808 |
809 | c.crc16 = ~c.crc16;
810 |
811 | in[length - 1U] = c.crc8[0U];
812 | in[length - 2U] = c.crc8[1U];
813 | }
814 |
815 | unsigned int get_syndrome_23127(unsigned int pattern)
816 | {
817 | unsigned int aux = X22;
818 |
819 | if (pattern >= X11) {
820 | while (pattern & MASK12) {
821 | while (!(aux & pattern))
822 | aux = aux >> 1;
823 |
824 | pattern ^= (aux / X11) * GENPOL;
825 | }
826 | }
827 |
828 | return pattern;
829 | }
830 |
831 | unsigned int encode24128(unsigned int data)
832 | {
833 | return ENCODING_TABLE_24128[data];
834 | }
835 |
836 | unsigned int decode23127(unsigned int code)
837 | {
838 | unsigned int syndrome = get_syndrome_23127(code);
839 | unsigned int error_pattern = DECODING_TABLE_23127[syndrome];
840 |
841 | code ^= error_pattern;
842 |
843 | return code >> 11;
844 | }
845 |
846 |
847 | unsigned int decode24128(unsigned char* bytes)
848 | {
849 | unsigned int code = bytes[0U];
850 | code <<= 8;
851 | code |= bytes[1U];
852 | code <<= 8;
853 | code |= bytes[2U];
854 |
855 | return decode23127(code >> 1);
856 | }
857 |
858 | void convolution_decode(uint8_t s0, uint8_t s1)
859 | {
860 | *m_dp = 0U;
861 |
862 | for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) {
863 | uint8_t j = i * 2U;
864 |
865 | uint16_t metric = (BRANCH_TABLE1[i] ^ s0) + (BRANCH_TABLE2[i] ^ s1);
866 |
867 | uint16_t m0 = m_oldMetrics[i] + metric;
868 | uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric);
869 | uint8_t decision0 = (m0 >= m1) ? 1U : 0U;
870 | m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0;
871 |
872 | m0 = m_oldMetrics[i] + (M - metric);
873 | m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + metric;
874 | uint8_t decision1 = (m0 >= m1) ? 1U : 0U;
875 | m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0;
876 |
877 | *m_dp |= (uint64_t)((decision1) << (j + 1U)) | (uint64_t)((decision0) << (j + 0U));
878 | }
879 |
880 | ++m_dp;
881 |
882 | uint16_t* tmp = m_oldMetrics;
883 | m_oldMetrics = m_newMetrics;
884 | m_newMetrics = tmp;
885 | }
886 |
887 | void convolution_chainback(unsigned char* out, unsigned int nBits)
888 | {
889 | uint32_t state = 0U;
890 |
891 | while (nBits-- > 0) {
892 | --m_dp;
893 |
894 | uint32_t i = state >> (9 - K);
895 | uint8_t bit = (uint8_t)(*m_dp >> i) & 1;
896 | state = (bit << 7) | (state >> 1);
897 |
898 | WRITE_BIT1(out, nBits, bit != 0U);
899 | }
900 | }
901 |
902 | void convolution_encode(const unsigned char* in, unsigned char* out, unsigned int nBits)
903 | {
904 | uint8_t d1 = 0U, d2 = 0U, d3 = 0U, d4 = 0U;
905 | uint32_t k = 0U;
906 | for (unsigned int i = 0U; i < nBits; i++) {
907 | uint8_t d = READ_BIT1(in, i) ? 1U : 0U;
908 |
909 | uint8_t g1 = (d + d3 + d4) & 1;
910 | uint8_t g2 = (d + d1 + d2 + d4) & 1;
911 |
912 | d4 = d3;
913 | d3 = d2;
914 | d2 = d1;
915 | d1 = d;
916 |
917 | WRITE_BIT1(out, k, g1 != 0U);
918 | k++;
919 |
920 | WRITE_BIT1(out, k, g2 != 0U);
921 | k++;
922 | }
923 | }
924 |
925 |
926 | void fich_decode(const unsigned char* bytes)
927 | {
928 | memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
929 | memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
930 |
931 | m_oldMetrics = m_metrics1;
932 | m_newMetrics = m_metrics2;
933 | m_dp = m_decisions;
934 |
935 | // Deinterleave the FICH and send bits to the Viterbi decoder
936 | for (unsigned int i = 0U; i < 100U; i++) {
937 | unsigned int n = INTERLEAVE_TABLE[i];
938 | uint8_t s0 = READ_BIT1(bytes, n) ? 1U : 0U;
939 |
940 | n++;
941 | uint8_t s1 = READ_BIT1(bytes, n) ? 1U : 0U;
942 |
943 | convolution_decode(s0, s1);
944 | }
945 |
946 | unsigned char output[13U];
947 | convolution_chainback(output, 96U);
948 |
949 | unsigned int b0 = decode24128(output + 0U);
950 | unsigned int b1 = decode24128(output + 3U);
951 | unsigned int b2 = decode24128(output + 6U);
952 | unsigned int b3 = decode24128(output + 9U);
953 |
954 | m_fich[0U] = (b0 >> 4) & 0xFFU;
955 | m_fich[1U] = ((b0 << 4) & 0xF0U) | ((b1 >> 8) & 0x0FU);
956 | m_fich[2U] = (b1 >> 0) & 0xFFU;
957 | m_fich[3U] = (b2 >> 4) & 0xFFU;
958 | m_fich[4U] = ((b2 << 4) & 0xF0U) | ((b3 >> 8) & 0x0FU);
959 | m_fich[5U] = (b3 >> 0) & 0xFFU;
960 |
961 | return;//CCRC::checkCCITT162(m_fich, 6U);
962 | }
963 |
964 | void fich_encode(unsigned char* bytes)
965 | {
966 | addCCITT162(m_fich, 6U);
967 |
968 | unsigned int b0 = ((m_fich[0U] << 4) & 0xFF0U) | ((m_fich[1U] >> 4) & 0x00FU);
969 | unsigned int b1 = ((m_fich[1U] << 8) & 0xF00U) | ((m_fich[2U] >> 0) & 0x0FFU);
970 | unsigned int b2 = ((m_fich[3U] << 4) & 0xFF0U) | ((m_fich[4U] >> 4) & 0x00FU);
971 | unsigned int b3 = ((m_fich[4U] << 8) & 0xF00U) | ((m_fich[5U] >> 0) & 0x0FFU);
972 |
973 | unsigned int c0 = encode24128(b0);
974 | unsigned int c1 = encode24128(b1);
975 | unsigned int c2 = encode24128(b2);
976 | unsigned int c3 = encode24128(b3);
977 |
978 | unsigned char conv[13U];
979 | conv[0U] = (c0 >> 16) & 0xFFU;
980 | conv[1U] = (c0 >> 8) & 0xFFU;
981 | conv[2U] = (c0 >> 0) & 0xFFU;
982 | conv[3U] = (c1 >> 16) & 0xFFU;
983 | conv[4U] = (c1 >> 8) & 0xFFU;
984 | conv[5U] = (c1 >> 0) & 0xFFU;
985 | conv[6U] = (c2 >> 16) & 0xFFU;
986 | conv[7U] = (c2 >> 8) & 0xFFU;
987 | conv[8U] = (c2 >> 0) & 0xFFU;
988 | conv[9U] = (c3 >> 16) & 0xFFU;
989 | conv[10U] = (c3 >> 8) & 0xFFU;
990 | conv[11U] = (c3 >> 0) & 0xFFU;
991 | conv[12U] = 0x00U;
992 |
993 | //CYSFConvolution convolution;
994 | unsigned char convolved[25U];
995 | convolution_encode(conv, convolved, 100U);
996 |
997 | unsigned int j = 0U;
998 | for (unsigned int i = 0U; i < 100U; i++) {
999 | unsigned int n = INTERLEAVE_TABLE[i];
1000 |
1001 | bool s0 = READ_BIT1(convolved, j) != 0U;
1002 | j++;
1003 |
1004 | bool s1 = READ_BIT1(convolved, j) != 0U;
1005 | j++;
1006 |
1007 | WRITE_BIT1(bytes, n, s0);
1008 |
1009 | n++;
1010 | WRITE_BIT1(bytes, n, s1);
1011 | }
1012 | }
1013 |
1014 | void fich_set_fi(unsigned char fi)
1015 | {
1016 | m_fich[0U] &= 0x3FU;
1017 | m_fich[0U] |= (fi << 6) & 0xC0U;
1018 | }
1019 |
1020 | void fich_set_cs(unsigned char cs)
1021 | {
1022 | m_fich[0U] &= 0xCFU;
1023 | m_fich[0U] |= (cs << 4) & 0x30U;
1024 | }
1025 |
1026 | void fich_set_cm(unsigned char cm)
1027 | {
1028 | m_fich[0U] &= 0xF3U;
1029 | m_fich[0U] |= (cm << 2) & 0x0CU;
1030 | }
1031 |
1032 | void fich_set_fn(unsigned char fn)
1033 | {
1034 | m_fich[1U] &= 0xC7U;
1035 | m_fich[1U] |= (fn << 3) & 0x38U;
1036 | }
1037 |
1038 | void fich_set_ft(unsigned char ft)
1039 | {
1040 | m_fich[1U] &= 0xF8U;
1041 | m_fich[1U] |= ft & 0x07U;
1042 | }
1043 |
1044 | void fich_set_mr(unsigned char mr)
1045 | {
1046 | m_fich[2U] &= 0xC7U;
1047 | m_fich[2U] |= (mr << 3) & 0x38U;
1048 | }
1049 |
1050 | void fich_set_voip(bool on)
1051 | {
1052 | if (on)
1053 | m_fich[2U] |= 0x04U;
1054 | else
1055 | m_fich[2U] &= 0xFBU;
1056 | }
1057 |
1058 | int main(int argc, char **argv)
1059 | {
1060 | struct sockaddr_in rx;
1061 | struct hostent *hp;
1062 | char * host1_url;
1063 | char * host2_url;
1064 | int host1_port;
1065 | int host2_port;
1066 | socklen_t l = sizeof(host1);
1067 | int rxlen;
1068 | int len = 0;
1069 | int reuse = 1;
1070 | int r;
1071 | int udprx,maxudp;
1072 |
1073 | static uint64_t ping_cnt = 0;
1074 | uint16_t streamid = 0;
1075 |
1076 | uint8_t connect_status;
1077 |
1078 | if(argc != 4){
1079 | fprintf(stderr, "Usage: ysfcon [CALLSIGN] [YSFHost1IP:PORT] [YSFHost2IP:PORT]\n");
1080 | return 0;
1081 | }
1082 | else{
1083 | memset(callsign, ' ', 10);
1084 | memcpy(callsign, argv[1], strlen(argv[1]));
1085 | host1_url = strtok(argv[2], ":");
1086 | host1_port = atoi(strtok(NULL, ":"));
1087 | host2_url = strtok(argv[3], ":");
1088 | host2_port = atoi(strtok(NULL, ":"));
1089 | printf("YSF1: %s:%d\n", host1_url, host1_port);
1090 | printf("YSF2: %s:%d\n", host2_url, host2_port);
1091 | }
1092 |
1093 |
1094 | signal(SIGINT, process_signal); //Handle CTRL-C gracefully
1095 | signal(SIGALRM, process_signal); //Watchdog
1096 |
1097 | if ((udp1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1098 | perror("cannot create socket\n");
1099 | return 0;
1100 | }
1101 | if ((udp2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1102 | perror("cannot create socket\n");
1103 | return 0;
1104 | }
1105 |
1106 | maxudp = max(udp1, udp2) + 1;
1107 |
1108 | memset((char *)&host1, 0, sizeof(host1));
1109 | host1.sin_family = AF_INET;
1110 | host1.sin_port = htons(host1_port);
1111 |
1112 | memset((char *)&host2, 0, sizeof(host2));
1113 | host2.sin_family = AF_INET;
1114 | host2.sin_port = htons(host2_port);
1115 |
1116 | hp = gethostbyname(host1_url);
1117 | if (!hp) {
1118 | fprintf(stderr, "could not resolve %s\n", host1_url);
1119 | return 0;
1120 | }
1121 | memcpy((void *)&host1.sin_addr, hp->h_addr_list[0], hp->h_length);
1122 |
1123 | hp = gethostbyname(host2_url);
1124 | if (!hp) {
1125 | fprintf(stderr, "could not resolve %s\n", host2_url);
1126 | return 0;
1127 | }
1128 | memcpy((void *)&host2.sin_addr, hp->h_addr_list[0], hp->h_length);
1129 | host1_cnt = 0;
1130 | host2_cnt = 0;
1131 | host1_connect = 1;
1132 | host2_connect = 1;
1133 | alarm(5);
1134 |
1135 | while (1) {
1136 | if(host1_connect){
1137 | host1_connect = 0;
1138 | buf[0] = 'Y';
1139 | buf[1] = 'S';
1140 | buf[2] = 'F';
1141 | buf[3] = 'P';
1142 | memcpy(&buf[4], callsign, 10);
1143 | sendto(udp1, buf, 14, 0, (const struct sockaddr *)&host1, sizeof(host1));
1144 | fprintf(stderr, "Connecting to YSF1...\n");
1145 | }
1146 | if(host2_connect){
1147 | host2_connect = 0;
1148 | buf[0] = 'Y';
1149 | buf[1] = 'S';
1150 | buf[2] = 'F';
1151 | buf[3] = 'P';
1152 | memcpy(&buf[4], callsign, 10);
1153 | sendto(udp2, buf, 14, 0, (const struct sockaddr *)&host2, sizeof(host2));
1154 | fprintf(stderr, "Connecting to YSF2...\n");
1155 | }
1156 | FD_ZERO(&udpset);
1157 | FD_SET(udp1, &udpset);
1158 | FD_SET(udp2, &udpset);
1159 | r = select(maxudp, &udpset, NULL, NULL, NULL);
1160 | //fprintf(stderr, "Select returned r == %d\n", r);
1161 | rxlen = 0;
1162 | if(r > 0){
1163 | if(FD_ISSET(udp1, &udpset)) {
1164 | rxlen = recvfrom(udp1, buf, BUFSIZE, 0, (struct sockaddr *)&rx, &l);
1165 | udprx = udp1;
1166 | }
1167 | else if(FD_ISSET(udp2, &udpset)) {
1168 | rxlen = recvfrom(udp2, buf, BUFSIZE, 0, (struct sockaddr *)&rx, &l);
1169 | udprx = udp2;
1170 | }
1171 | }
1172 | #ifdef DEBUG
1173 | if(rxlen){
1174 | if(rx.sin_addr.s_addr == host1.sin_addr.s_addr){
1175 | fprintf(stderr, "RECV YSF1: ");
1176 | }
1177 | else if(rx.sin_addr.s_addr == host2.sin_addr.s_addr){
1178 | fprintf(stderr, "RECV YSF2: ");
1179 | }
1180 | for(int i = 0; i < rxlen; ++i){
1181 | fprintf(stderr, "%02x ", buf[i]);
1182 | }
1183 | fprintf(stderr, "\n");
1184 | fflush(stderr);
1185 | }
1186 | #endif
1187 | if(rxlen == 155){
1188 | fich_decode(&buf[40]);
1189 | fich_set_voip(false);
1190 | fich_encode(&buf[40]);
1191 | if( (udprx == udp1) && (rx.sin_addr.s_addr == host1.sin_addr.s_addr) ){
1192 | sendto(udp2, buf, rxlen, 0, (const struct sockaddr *)&host2, sizeof(host2));
1193 | #ifdef DEBUG
1194 | fprintf(stderr, "SEND YSF2: ");
1195 | for(int i = 0; i < rxlen; ++i){
1196 | fprintf(stderr, "%02x ", buf[i]);
1197 | }
1198 | fprintf(stderr, "\n");
1199 | fflush(stderr);
1200 | #endif
1201 | }
1202 | else if( (udprx == udp2) && (rx.sin_addr.s_addr == host2.sin_addr.s_addr) ){
1203 | sendto(udp1, buf, rxlen, 0, (const struct sockaddr *)&host1, sizeof(host1));
1204 | #ifdef DEBUG
1205 | fprintf(stderr, "SEND YSF1: ");
1206 | for(int i = 0; i < rxlen; ++i){
1207 | fprintf(stderr, "%02x ", buf[i]);
1208 | }
1209 | fprintf(stderr, "\n");
1210 | fflush(stderr);
1211 | #endif
1212 | }
1213 | }
1214 | }
1215 | }
1216 |
--------------------------------------------------------------------------------