├── 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 | --------------------------------------------------------------------------------