├── .gitignore ├── LICENSE.md ├── handy_utils.c ├── handy_utils.h ├── main_melproc.c ├── mel_common.c ├── mel_common.h ├── mel_metrix.c ├── mel_metrix.h ├── mel_metrix_table.h ├── mel_wcd.c ├── mel_wcd.h ├── mel_wcd_fxcpu_fx3.c ├── mel_wcd_fxcpu_fx3.h ├── mel_wpa.c ├── mel_wpa.h ├── mel_wpa_fxcpu_fx3.c ├── mel_wpa_fxcpu_fx3.h ├── mel_wpg.c ├── mel_wpg.h ├── mel_wpg_device.c ├── mel_wpg_device.h ├── mel_wpg_fxcpu_fx3.c ├── mel_wpg_fxcpu_fx3.h ├── mel_wpg_fxcpu_regs.c ├── mel_wpg_fxcpu_regs.h ├── mel_wpg_instr.c ├── mel_wpg_instr.h ├── mel_wpg_item.c ├── mel_wpg_item.h ├── mel_wpg_tables.h ├── protocmn.c └── protocmn.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | 4 | # Libraries 5 | *.lib 6 | *.a 7 | 8 | # Shared objects (inc. Windows DLLs) 9 | *.dll 10 | *.so 11 | *.so.* 12 | *.dylib 13 | 14 | # Executables 15 | *.exe 16 | *.out 17 | *.app 18 | -------------------------------------------------------------------------------- /handy_utils.c: -------------------------------------------------------------------------------- 1 | #include "handy_utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int compare_buffers(void* buf1,int buf1_size,void* buf2,int buf2_size) 8 | { 9 | int n_diffs = 1; 10 | unsigned char* b1 = buf1; 11 | unsigned char* b2 = buf2; 12 | 13 | if (buf1_size == buf2_size) 14 | { 15 | if (memcmp(b1,b2,buf1_size)) 16 | { 17 | #if 1 18 | int j; 19 | 20 | for (j = 0 ; j < buf1_size; j++) 21 | { 22 | if(!(j%16)) 23 | { 24 | printf("\n%04X\t",j); 25 | } 26 | 27 | if (b1[j]!=b2[j]) 28 | { 29 | n_diffs++; 30 | 31 | printf(" [%02X->%02X] ",b1[j],b2[j]); 32 | } 33 | else 34 | { 35 | printf("%02X ",b1[j]); 36 | } 37 | } 38 | 39 | printf("\n"); 40 | #endif 41 | } 42 | else 43 | { 44 | //printf("SUCCESS\n"); 45 | n_diffs = 0; 46 | } 47 | } 48 | else 49 | { 50 | printf("DIFFERENT ENC/DEC SIZES!!!: %d != %d\n", buf1_size,buf2_size); 51 | } 52 | 53 | return(n_diffs); 54 | } 55 | -------------------------------------------------------------------------------- /handy_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef __handy_utils_h__ 2 | #define __handy_utils_h__ 3 | 4 | int compare_buffers(void* buf1,int buf1_size,void* buf2,int buf2_size); 5 | 6 | #endif /* __handy_utils_h__ */ 7 | -------------------------------------------------------------------------------- /main_melproc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "handy_utils.h" 6 | #include "mel_wpa.h" 7 | #include "mel_wcd.h" 8 | #include "mel_wpg.h" 9 | #include "mel_wpg_fxcpu_fx3.h" 10 | 11 | #include "mel_wpg_instr.h" 12 | 13 | #include "mel_metrix.h" 14 | 15 | #pragma warning (disable : 4996) 16 | 17 | #define WCD_NAME_SIZEOF 40 18 | 19 | int process_wcd(int argc,char** argv); 20 | int process_wpg(int argc,char** argv); 21 | int process_wpa(int argc,char** argv); 22 | int process_til(int argc,char** argv); 23 | 24 | int main(int argc,char** argv) 25 | { 26 | char *ext; 27 | size_t fname_len; 28 | 29 | #if 0 30 | mel_metrix_stats(); 31 | //mel_wpg_printf_opcodes_FXCPU(); 32 | //mel_wpg_generate_metrix_FXCPU(); 33 | mel_wpg_printf_metrix_FXCPU(); 34 | 35 | //mel_metrix_generate(); 36 | //mel_metrix_printf(); 37 | //mel_opnames_printf(); 38 | return(0); 39 | #endif 40 | 41 | if (argc < 2) 42 | { 43 | printf("usage: *.exe file_in"); 44 | // 0 1 1 45 | return(1); 46 | } 47 | 48 | fname_len = strlen(argv[1]); 49 | 50 | ext = argv[1] + fname_len - 3; 51 | 52 | printf("EXTENSION IS: %s\n\n\n",ext); 53 | 54 | if (!strcmp(ext,"wcd")) 55 | { 56 | return process_wcd(argc,argv); 57 | } 58 | 59 | if (!strcmp(ext,"wpg")) 60 | { 61 | return process_wpg(argc,argv); 62 | } 63 | 64 | if (!strcmp(ext,"til")) 65 | { 66 | return process_til(argc,argv); 67 | } 68 | 69 | if (!strcmp(ext,"wpa")) 70 | { 71 | return process_wpa(argc,argv); 72 | } 73 | 74 | return 1; 75 | } 76 | 77 | int process_wpg(int argc,char** argv) 78 | { 79 | char *file_name; 80 | FILE *fp_i = 0; 81 | 82 | file_name = argv[1]; 83 | 84 | fp_i = fopen(file_name,"rb"); 85 | if (fp_i) 86 | { 87 | unsigned char* data = 0; 88 | int file_size; 89 | 90 | fseek(fp_i,0,SEEK_END); 91 | file_size = ftell(fp_i); 92 | 93 | fseek(fp_i,0,SEEK_SET); 94 | 95 | data = (unsigned char*)malloc(file_size); 96 | if (data) 97 | { 98 | void* wpg; 99 | MELTools tools; 100 | int cpuSeries; 101 | int cpuType; 102 | int prgMode; 103 | 104 | fread(data,1,file_size,fp_i); 105 | 106 | wpg = mel_wpg_dec(data,file_size,&cpuSeries,&cpuType,&prgMode,&tools); 107 | if (wpg) 108 | { 109 | unsigned char* buf2; 110 | int buf2_size; 111 | int enc_size; 112 | //int min_size; 113 | int maxsteps = 16000;//= wpa->page1.mem_capacity_in_steps 114 | 115 | { 116 | WPG_FXCPU_FX3U* wpg_fx = wpg; 117 | 118 | printf("\tDEC WPG STEPS: %d\tNOPs: %d (%.2f %%)\tUSED: %d steps (%.2f %%)\n", 119 | wpg_fx->steps,wpg_fx->nop_steps, 120 | 100.0*(double)wpg_fx->nop_steps/(double)wpg_fx->steps, 121 | wpg_fx->steps - wpg_fx->nop_steps, 122 | 100.0*(double)(wpg_fx->steps-wpg_fx->nop_steps)/(double)wpg_fx->steps 123 | ); 124 | } 125 | 126 | ////////////////////////////////////////////////////////////////////////// 127 | //CHECK WPG DECODING/ENCODING 128 | ////////////////////////////////////////////////////////////////////////// 129 | //buf2_size = file_size; 130 | buf2_size = 64*1024; 131 | buf2 = malloc(buf2_size); 132 | memset(buf2,0xDD,buf2_size); 133 | 134 | enc_size = mel_wpg_enc(cpuSeries,cpuType,wpg,buf2,prgMode,&tools,maxsteps); 135 | { 136 | FILE* fp_o; 137 | 138 | fp_o = fopen("out.wpg","wb+"); 139 | fwrite(buf2,1,enc_size,fp_o); 140 | fclose(fp_o); 141 | fflush(fp_o); 142 | } 143 | { 144 | WPG_FXCPU_FX3U* wpg_fx = wpg; 145 | 146 | printf("\tENC WPG STEPS: %d\tNOPs: %d (%.2f %%)\tUSED: %d steps (%.2f %%)\n", 147 | wpg_fx->steps,wpg_fx->nop_steps, 148 | 100.0*(double)wpg_fx->nop_steps/(double)wpg_fx->steps, 149 | wpg_fx->steps - wpg_fx->nop_steps, 150 | 100.0*(double)(wpg_fx->steps-wpg_fx->nop_steps)/(double)wpg_fx->steps 151 | ); 152 | } 153 | 154 | printf("\n\n\n"); 155 | 156 | //min_size = (enc_size < file_size)? enc_size:file_size; 157 | if (compare_buffers(data,file_size,buf2,enc_size)==0) 158 | //if (compare_buffers(data,min_size,buf2,min_size)==0) 159 | { 160 | printf("WPG -> DAT -> WPG: SUCCESS\n"); 161 | } 162 | else 163 | { 164 | printf("WPG -> DAT -> WPG: DIFFERENT WPGs\n"); 165 | } 166 | 167 | free(buf2); 168 | 169 | ////////////////////////////////////////////////////////////////////////// 170 | //CHECK TIL ENCODING/DECODING 171 | ////////////////////////////////////////////////////////////////////////// 172 | buf2_size = 640*1024; 173 | buf2 = malloc(buf2_size); 174 | memset(buf2,0xDD,buf2_size); 175 | 176 | enc_size = mel_til_enc(cpuSeries,cpuType,wpg,buf2,&tools); 177 | { 178 | FILE* fp_o; 179 | 180 | fp_o = fopen("out.til","wb+"); 181 | fwrite(buf2,1,enc_size,fp_o); 182 | fclose(fp_o); 183 | fflush(fp_o); 184 | } 185 | { 186 | void* wpg_til; 187 | 188 | wpg_til = mel_til_dec(buf2,enc_size,&cpuSeries,&cpuType,&tools,maxsteps); 189 | if (wpg_til) 190 | { 191 | unsigned char* buf3; 192 | int buf3_size; 193 | int enc_size3; 194 | 195 | buf3_size = 64*1024; 196 | buf3 = malloc(buf3_size); 197 | memset(buf3,0xDD,buf3_size); 198 | 199 | enc_size3 = mel_wpg_enc(cpuSeries,cpuType,wpg_til,buf3,prgMode,&tools,maxsteps); 200 | { 201 | FILE* fp_o; 202 | 203 | fp_o = fopen("til.wpg","wb+"); 204 | fwrite(buf3,1,enc_size3,fp_o); 205 | fclose(fp_o); 206 | fflush(fp_o); 207 | } 208 | 209 | if (compare_buffers(data,file_size,buf3,enc_size3)==0) 210 | { 211 | printf("WPG -> DAT -> TIL -> DAT -> WPG: SUCCESS\n"); 212 | } 213 | else 214 | { 215 | printf("WPG -> DAT -> TIL -> DAT -> WPG: DIFFERENT WPGs\n"); 216 | } 217 | 218 | free(buf3); 219 | mel_wpg_free(&tools,wpg_til); 220 | } 221 | else 222 | { 223 | printf("Can't decode TIL completely!\n"); 224 | } 225 | } 226 | free(buf2); 227 | mel_wpg_free(&tools,wpg); 228 | } 229 | else 230 | { 231 | printf("Can't decode WPG completely! Program Mode: %d\n",prgMode); 232 | } 233 | 234 | free(data); 235 | } 236 | 237 | fclose(fp_i); 238 | } 239 | 240 | return(0); 241 | } 242 | 243 | int process_til(int argc,char** argv) 244 | { 245 | char *file_name; 246 | FILE *fp_i = 0; 247 | 248 | file_name = argv[1]; 249 | 250 | fp_i = fopen(file_name,"rb"); 251 | if (fp_i) 252 | { 253 | unsigned char* data = 0; 254 | int file_size; 255 | 256 | fseek(fp_i,0,SEEK_END); 257 | file_size = ftell(fp_i); 258 | 259 | fseek(fp_i,0,SEEK_SET); 260 | 261 | data = (unsigned char*)malloc(file_size); 262 | if (data) 263 | { 264 | int cpuSeries = MEL_PLC_SERIES_FXCPU; 265 | int cpuType = MEL_PLC_FXCPU_TYPE_FX3U_C; 266 | 267 | void* wpg; 268 | MELTools tools; 269 | 270 | int maxsteps = 16000;//= wpa->page1.mem_capacity_in_steps 271 | 272 | fread(data,1,file_size,fp_i); 273 | 274 | wpg = mel_til_dec(data,file_size,&cpuSeries,&cpuType,&tools,maxsteps); 275 | if (wpg) 276 | { 277 | unsigned char* buf2; 278 | int enc_size; 279 | 280 | //buf2 = malloc(file_size); 281 | buf2 = malloc(64*1024); 282 | memset(buf2,0xDD,file_size); 283 | 284 | { 285 | WPG_FXCPU_FX3U* wpg_fx = wpg; 286 | 287 | printf("\tDEC TIL STEPS: %d\tNOPs: %d (%.2f %%)\tUSED: %d steps (%.2f %%)\n", 288 | wpg_fx->steps,wpg_fx->nop_steps, 289 | 100.0*(double)wpg_fx->nop_steps/(double)wpg_fx->steps, 290 | wpg_fx->steps - wpg_fx->nop_steps, 291 | 100.0*(double)(wpg_fx->steps-wpg_fx->nop_steps)/(double)wpg_fx->steps 292 | ); 293 | } 294 | 295 | enc_size = mel_wpg_enc(cpuSeries,cpuType,wpg,buf2,WPG_RPOGRAMM_MODE_LADDER,&tools,maxsteps); 296 | 297 | { 298 | FILE* fp_o; 299 | 300 | fp_o = fopen("til.wpg","wb+"); 301 | fwrite(buf2,1,enc_size,fp_o); 302 | fclose(fp_o); 303 | fflush(fp_o); 304 | } 305 | 306 | { 307 | WPG_FXCPU_FX3U* wpg_fx = wpg; 308 | 309 | printf("\tENC WPG STEPS: %d\tNOPs: %d (%.2f %%)\tUSED: %d steps (%.2f %%)\n", 310 | wpg_fx->steps,wpg_fx->nop_steps, 311 | 100.0*(double)wpg_fx->nop_steps/(double)wpg_fx->steps, 312 | wpg_fx->steps - wpg_fx->nop_steps, 313 | 100.0*(double)(wpg_fx->steps-wpg_fx->nop_steps)/(double)wpg_fx->steps 314 | ); 315 | } 316 | 317 | free(buf2); 318 | mel_wpg_free(&tools,wpg); 319 | } 320 | else 321 | { 322 | printf("Can't decode TIL completely!\n"); 323 | } 324 | 325 | 326 | free(data); 327 | } 328 | 329 | fclose(fp_i); 330 | } 331 | return(0); 332 | } 333 | 334 | int process_wpa(int argc,char** argv) 335 | { 336 | char *file_name; 337 | FILE *fp_i = 0; 338 | 339 | int file_size; 340 | 341 | // unsigned char header_0[64] = {0}; 342 | // int header_0_size = sizeof(header_0); 343 | MELTools tools; 344 | unsigned char *buff = 0; 345 | void* wpa; 346 | int cpuSeries; 347 | int cpuType; 348 | 349 | file_name = argv[1]; 350 | 351 | fp_i = fopen(file_name,"rb"); 352 | fseek(fp_i,0,SEEK_END); 353 | file_size = ftell(fp_i); 354 | 355 | fseek(fp_i,0,SEEK_SET); 356 | 357 | buff = malloc(file_size); 358 | fread(buff,1,file_size,fp_i); 359 | if (fp_i) fclose(fp_i); 360 | 361 | wpa = mel_wpa_dec(buff,file_size,&cpuSeries,&cpuType,&tools); 362 | if(wpa) 363 | { 364 | WPA_FXCPU_FX3U* options = (WPA_FXCPU_FX3U*)wpa; 365 | unsigned char* buf2; 366 | int enc_size; 367 | 368 | buf2 = malloc(file_size); 369 | memset(buf2,0xDD,file_size); 370 | 371 | enc_size = mel_wpa_enc(cpuSeries,cpuType,wpa,buf2,&tools); 372 | 373 | if (compare_buffers(buff,file_size,buf2,enc_size)==0) 374 | { 375 | printf("SUCCESS\n"); 376 | } 377 | else 378 | { 379 | printf("WPA: ENC != DEC\n"); 380 | } 381 | 382 | free(buf2); 383 | 384 | #if 0 385 | int i; 386 | 387 | printf( 388 | "\n\n\n" 389 | "%d\toptions->page1.mem_capacity_in_steps\n" 390 | "%d\toptions->page1.cmt_capacity_in_blocks\n" 391 | "%d\toptions->page1.freg_capacity_in_blocks\n" 392 | "%d\toptions->page1.SFBS_in_blocks\n" 393 | "%d\toptions->page1.PIS_in_blocks\n" 394 | "%d\toptions->page1.BCC_in_blocks\n" 395 | , 396 | options->page1.mem_capacity_in_steps, 397 | options->page1.cmt_capacity_in_blocks, 398 | options->page1.freg_capacity_in_blocks, 399 | options->page1.SFBS_in_blocks, 400 | options->page1.PIS_in_blocks, 401 | options->page1.BCC_in_blocks 402 | ); 403 | 404 | printf("%d\toptions->page2.n_editable_items\n",options->page2.n_editable_items); 405 | 406 | for (i = 0; i < options->page2.n_editable_items; i++) 407 | { 408 | printf("options->page2.editable_items[%d]:\n",i); 409 | printf( "\t%04X\t.device_code\n" 410 | "\t%4d\t.latched_start\n" 411 | "\t%4d\t.latched_length\n", 412 | options->page2.editable_items[i].device_code, 413 | options->page2.editable_items[i].latched_start, 414 | options->page2.editable_items[i].latched_length 415 | ); 416 | } 417 | 418 | printf("%d\toptions->page4.input_Totally\n" 419 | "%d\toptions->page4.input_Start_offset\n" 420 | "%d\toptions->page4.output_Totally\n" 421 | "%d\toptions->page4.output_Start_offset\n", 422 | options->page4.input_Totally, 423 | options->page4.input_Start_offset, 424 | options->page4.output_Totally, 425 | options->page4.output_Start_offset 426 | ); 427 | 428 | printf("\n" 429 | "%d\toptions->page5.is_battery_less_drive_mode\n" 430 | "%02X\toptions->page5.modem\n" 431 | "%04X\toptions->page5.terminal\n", 432 | options->page5.is_battery_less_drive_mode, 433 | options->page5.modem, 434 | options->page5.terminal 435 | ); 436 | 437 | //options->page6.ch1.is_enabled, 438 | printf 439 | ("\n" 440 | "\tCH1 enabled: %d\n" 441 | "%d\t.protocol\n" 442 | "%d\t.databits\n" 443 | "%d\t.parity\n" 444 | "%d\t.stopbits\n" 445 | "%d\t.baudrate\n" 446 | "%d\t.is_header_on\n" 447 | "%d\t.is_terminator_on\n" 448 | "%d\t.is_control_line_on\n" 449 | "%d\t.hw_type\n" 450 | "%d\t.is_sum_check_on\n" 451 | "%d\t.transmission_cntrl\n" 452 | "%d\t.station_number\n" 453 | "%d\t.timeout_judge_time_x10ms\n\n", 454 | options->page6.ch1.is_enabled, 455 | options->page6.ch1.protocol, 456 | options->page6.ch1.databits, 457 | options->page6.ch1.parity, 458 | options->page6.ch1.stopbits, 459 | options->page6.ch1.baudrate, 460 | options->page6.ch1.is_header_on, 461 | options->page6.ch1.is_terminator_on, 462 | options->page6.ch1.is_control_line_on, 463 | options->page6.ch1.hw_type, 464 | options->page6.ch1.is_sum_check_on, 465 | options->page6.ch1.transmission_cntrl, 466 | options->page6.ch1.station_number, 467 | options->page6.ch1.timeout_judge_time_x10ms 468 | ); 469 | 470 | printf 471 | ("\n" 472 | "\tCH2 enabled: %d\n" 473 | "%d\t.protocol\n" 474 | "%d\t.databits\n" 475 | "%d\t.parity\n" 476 | "%d\t.stopbits\n" 477 | "%d\t.baudrate\n" 478 | "%d\t.is_header_on\n" 479 | "%d\t.is_terminator_on\n" 480 | "%d\t.is_control_line_on\n" 481 | "%d\t.hw_type\n" 482 | "%d\t.is_sum_check_on\n" 483 | "%d\t.station_number\n" 484 | "%d\t.timeout_judge_time_x10ms\n\n", 485 | options->page6.ch2.is_enabled, 486 | options->page6.ch2.protocol, 487 | options->page6.ch2.databits, 488 | options->page6.ch2.parity, 489 | options->page6.ch2.stopbits, 490 | options->page6.ch2.baudrate, 491 | options->page6.ch2.is_header_on, 492 | options->page6.ch2.is_terminator_on, 493 | options->page6.ch2.is_control_line_on, 494 | options->page6.ch2.hw_type, 495 | options->page6.ch2.is_sum_check_on, 496 | options->page6.ch2.transmission_cntrl, 497 | options->page6.ch2.station_number, 498 | options->page6.ch2.timeout_judge_time_x10ms 499 | ); 500 | 501 | if(options->page1.PIS_in_blocks) 502 | { 503 | int i,j; 504 | 505 | for (i = 0; i < WPA_FX3U_POS_YTABS_COUNT; i++) 506 | { 507 | printf 508 | ("\nY[%d]\n" 509 | "%d\t.BiasSpeed_Hz\n" 510 | "%d\t.MaxSpeed_Hz\n" 511 | "%d\t.CreepSpeed_Hz\n" 512 | "%d\t.ZeroReturnSpeed_Hz\n" 513 | "%d\t.AccelerationTime_ms\n" 514 | "%d\t.DecelerationTime_ms\n" 515 | "%d\t.InterrInputSource\n" 516 | "%d\t.dont_init_postable\n" 517 | "%02X\t.head_address.type\n" 518 | "%d\t.head_address.index\n" 519 | "%02X\t.rotation_dir_signal.type\n" 520 | "%d\t.rotation_dir_signal.index\n", 521 | i, 522 | options->page7.indivs.ytabs[i].BiasSpeed_Hz, 523 | options->page7.indivs.ytabs[i].MaxSpeed_Hz, 524 | options->page7.indivs.ytabs[i].CreepSpeed_Hz, 525 | options->page7.indivs.ytabs[i].ZeroReturnSpeed_Hz, 526 | options->page7.indivs.ytabs[i].AccelerationTime_ms, 527 | options->page7.indivs.ytabs[i].DecelerationTime_ms, 528 | options->page7.indivs.ytabs[i].InterrInputSource, 529 | options->page7.indivs.ytabs[i].dont_init_postable, 530 | options->page7.indivs.ytabs[i].head_address.type, 531 | options->page7.indivs.ytabs[i].head_address.index, 532 | options->page7.indivs.ytabs[i].rotation_dir_signal.type, 533 | options->page7.indivs.ytabs[i].rotation_dir_signal.index 534 | ); 535 | 536 | for (j = 0; j < WPA_FX3U_POS_INSTR_COUNT; j++) 537 | { 538 | if (options->page7.indivs.ytabs[i].instructions[j].type != WPA_FX3U_POS_INSTR_TYPE_NONE) 539 | { 540 | printf( "\n\tINSTR[%d]:\n" 541 | "\t%d\ttype;\n" 542 | "\t%d\tpulse;\n" 543 | "\t%d\tfreq;\n", 544 | j, 545 | options->page7.indivs.ytabs[i].instructions[j].type, 546 | options->page7.indivs.ytabs[i].instructions[j].pulse, 547 | options->page7.indivs.ytabs[i].instructions[j].freq_Hz 548 | ); 549 | } 550 | } 551 | } 552 | } 553 | 554 | if(options->page1.BCC_in_blocks) 555 | { 556 | int i; 557 | 558 | printf( 559 | "\nBCC:\n" 560 | "%d\t.baudrate\n" 561 | "%d\t.point_mode\n", 562 | options->page8.baudrate, 563 | options->page8.point_mode 564 | ); 565 | 566 | for (i = 0; i < WPA_FX3U_STATIONS_COUNT; i++) 567 | { 568 | if(options->page8.stations[i].type != WPA_FX3U_BuiltInCCLink_LTSetup_STATIONTYPE_None) 569 | { 570 | printf( 571 | "[%d]" 572 | "\t%d\t.type\n" 573 | "\t%d\t.iopoints\n" 574 | "\t%d\t.reserved or not\n", 575 | i, 576 | options->page8.stations[i].type, 577 | options->page8.stations[i].iopoints, 578 | options->page8.stations[i].is_reserve_st 579 | ); 580 | } 581 | } 582 | } 583 | 584 | #endif 585 | mel_wpa_free(&tools,wpa); 586 | } 587 | else 588 | { 589 | printf("can't decode MEL wpa-file: unknown PLC\n"); 590 | } 591 | 592 | printf( 593 | "\n" 594 | "CPU Series:\t0x%02X\n" 595 | "CPU Type:\t0x%02X\n", 596 | cpuSeries,cpuType 597 | ); 598 | 599 | 600 | if(buff) free(buff); 601 | 602 | return(0); 603 | } 604 | 605 | 606 | int process_wcd(int argc,char** argv) 607 | { 608 | char *file_name; 609 | FILE *fp_i = 0; 610 | int file_size; 611 | 612 | MELTools tools; 613 | unsigned char *buff = 0; 614 | void* wcd; 615 | int cpuSeries; 616 | int cpuType; 617 | 618 | file_name = argv[1]; 619 | 620 | fp_i = fopen(file_name,"rb"); 621 | fseek(fp_i,0,SEEK_END); 622 | file_size = ftell(fp_i); 623 | 624 | fseek(fp_i,0,SEEK_SET); 625 | 626 | buff = malloc(file_size); 627 | fread(buff,1,file_size,fp_i); 628 | if (fp_i) fclose(fp_i); 629 | 630 | wcd = mel_wcd_dec(buff,file_size,&cpuSeries,&cpuType,&tools); 631 | if(wcd) 632 | { 633 | WCD_FXCPU_FX3U* comments = (WCD_FXCPU_FX3U*)wcd; 634 | unsigned char* buf2; 635 | int enc_size; 636 | // int i; 637 | 638 | buf2 = malloc(file_size); 639 | memset(buf2,0xDD,file_size); 640 | 641 | enc_size = mel_wcd_enc(cpuSeries,cpuType,wcd,buf2,&tools); 642 | 643 | { 644 | FILE* fp_o; 645 | 646 | fp_o = fopen("out.wcd","wb+"); 647 | fwrite(buf2,1,enc_size,fp_o); 648 | fclose(fp_o); 649 | fflush(fp_o); 650 | } 651 | 652 | if (compare_buffers(buff,file_size,buf2,enc_size)==0) 653 | { 654 | printf("SUCCESS\n"); 655 | } 656 | else 657 | { 658 | printf("WCD: ENC != DEC\n"); 659 | } 660 | 661 | printf( 662 | "%d\tcomments->n_codes\n" 663 | "%d\tcomments->n_names\n", 664 | comments->n_codes, 665 | comments->n_names 666 | ); 667 | #if 0 668 | for (i = 0; i < comments->n_codes; i++) 669 | { 670 | printf( 671 | "%02X\tcomments->codes[i].item.type\n" 672 | "%d\tcomments->codes[i].item.index\n" 673 | "%d\tcomments->codes[i].count\n", 674 | comments->codes[i].item.type, 675 | comments->codes[i].item.index, 676 | comments->codes[i].count 677 | ); 678 | } 679 | 680 | for (i = 0; i < comments->n_names; i++) 681 | { 682 | printf("[%48s]\tname[%d]\n", 683 | comments->names[i].raw,i 684 | ); 685 | } 686 | #endif 687 | 688 | 689 | free(buf2); 690 | 691 | mel_wcd_free(&tools,wcd); 692 | } 693 | else 694 | { 695 | printf("can't decode MEL wcd-file: unknown PLC\n"); 696 | } 697 | 698 | printf( 699 | "\n" 700 | "CPU Series:\t0x%02X\n" 701 | "CPU Type:\t0x%02X\n", 702 | cpuSeries,cpuType 703 | ); 704 | 705 | if(buff) free(buff); 706 | 707 | if (fp_i) 708 | { 709 | fclose(fp_i); 710 | } 711 | 712 | return(0); 713 | } 714 | 715 | #if 0 716 | int process_wcd(int argc,char** argv) 717 | { 718 | char *file_name; 719 | FILE *fp_i = 0; 720 | int file_size; 721 | int offset; 722 | 723 | unsigned char header_0[64] = {0}; 724 | int header_0_size = sizeof(header_0); 725 | 726 | int header_1_size = 10; 727 | 728 | unsigned int unknown_32b_0x42; 729 | 730 | unsigned short unknown_16b_0x46; 731 | unsigned short unknown_16b_0x48; 732 | 733 | unsigned short body_sizeof; 734 | unsigned short codes_sizeof; 735 | unsigned short names_sizeof; 736 | 737 | unsigned char *codes = 0; 738 | unsigned char *names = 0; 739 | 740 | int one_name_sizeof = WCD_NAME_SIZEOF; 741 | int n_names; 742 | 743 | file_name = argv[1]; 744 | 745 | fp_i = fopen(file_name,"rb"); 746 | fseek(fp_i,0,SEEK_END); 747 | file_size = ftell(fp_i); 748 | 749 | fseek(fp_i,0,SEEK_SET); 750 | 751 | fread(header_0,1,header_0_size,fp_i); 752 | fread(&body_sizeof,2,1,fp_i); 753 | 754 | fread(&unknown_32b_0x42,4,1,fp_i); 755 | fread(&unknown_16b_0x46,2,1,fp_i); 756 | fread(&unknown_16b_0x48,2,1,fp_i); 757 | 758 | codes_sizeof = body_sizeof - header_1_size; 759 | 760 | printf("file = %d bytes\n",file_size); 761 | 762 | printf("codes_sizeof = %d bytes\n",codes_sizeof); 763 | 764 | printf("unknown_16b_0x46 = %d\n",unknown_16b_0x46); 765 | printf("unknown_16b_0x48 = %d\n",unknown_16b_0x48); 766 | 767 | if (codes_sizeof > 0) 768 | { 769 | codes = (unsigned char*)malloc(codes_sizeof); 770 | 771 | offset = ftell(fp_i); 772 | printf("codes offset: %d [0x%04x]\n",offset,offset); 773 | 774 | fread(codes,1,codes_sizeof,fp_i); 775 | 776 | { 777 | int i; 778 | int n_tmp = 0; 779 | 780 | #define CODES_STEP 10 781 | for (i = 0; i < codes_sizeof; i += CODES_STEP) 782 | { 783 | int j; 784 | 785 | unsigned short code_id; 786 | unsigned int code_first; 787 | unsigned int code_count; 788 | 789 | memcpy(&code_id, &codes[i+0],2); 790 | memcpy(&code_first, &codes[i+2],4); 791 | memcpy(&code_count, &codes[i+6],4); 792 | 793 | printf("%d\t",i/CODES_STEP); 794 | for (j = 0; j < CODES_STEP; j++) 795 | { 796 | printf("%02x ",codes[i + j]); 797 | } 798 | printf("\t%04x\t%d\t%d",code_id,code_first,code_count); 799 | 800 | printf("\n"); 801 | 802 | n_tmp += code_count; 803 | } 804 | //printf("total N = %d\n",n_tmp); 805 | } 806 | 807 | names_sizeof = file_size - (header_0_size + header_1_size + codes_sizeof); 808 | names = (unsigned char*)malloc(names_sizeof); 809 | 810 | printf("names_sizeof = %d bytes\n",names_sizeof); 811 | 812 | printf("names / unknown_16b_0x46 = %d\n",names_sizeof/unknown_16b_0x46); 813 | printf("names / unknown_16b_0x48 = %d\n",names_sizeof/unknown_16b_0x48); 814 | 815 | printf("names / one_name_sizeof = %d\n",names_sizeof/one_name_sizeof); 816 | 817 | offset = ftell(fp_i); 818 | 819 | printf("names offset: %d [0x%04x]\n",offset,offset); 820 | fread(names,1,names_sizeof,fp_i); 821 | 822 | n_names = names_sizeof/one_name_sizeof; 823 | 824 | //one_name_sizeof 825 | { 826 | int i; 827 | 828 | for (i = 0; i < n_names; i++) 829 | { 830 | char one_name[WCD_NAME_SIZEOF+1]; 831 | 832 | memcpy(one_name,names+i*WCD_NAME_SIZEOF,WCD_NAME_SIZEOF); 833 | one_name[WCD_NAME_SIZEOF] = 0; 834 | 835 | printf("%d\t[%s]\n",i,one_name); 836 | } 837 | } 838 | } 839 | 840 | if (fp_i) 841 | { 842 | fclose(fp_i); 843 | } 844 | 845 | if(codes) free(codes); 846 | if(names) free(names); 847 | 848 | return(0); 849 | } 850 | 851 | int process_wpg(int argc,char** argv) 852 | { 853 | char *file_name; 854 | FILE *fp_i = 0; 855 | 856 | int file_size; 857 | int offset; 858 | 859 | unsigned char header_0[64] = {0}; 860 | int header_0_size = sizeof(header_0); 861 | 862 | unsigned short subcode_0; 863 | unsigned short subcode_1; 864 | 865 | unsigned char* data = 0; 866 | int data_size; 867 | 868 | int wpg_netto = 0; 869 | int wpg_commnt = 0; 870 | int wpg_brutto = 0; 871 | 872 | file_name = argv[1]; 873 | 874 | fp_i = fopen(file_name,"rb"); 875 | fseek(fp_i,0,SEEK_END); 876 | file_size = ftell(fp_i); 877 | 878 | fseek(fp_i,0,SEEK_SET); 879 | 880 | fread(header_0,1,header_0_size,fp_i); 881 | 882 | fread(&subcode_0,1,sizeof(unsigned short),fp_i); 883 | fread(&subcode_1,1,sizeof(unsigned short),fp_i); 884 | 885 | printf("two sub codes: %04x, %04x\n",subcode_0,subcode_1); 886 | 887 | data_size = file_size - (header_0_size + 2*sizeof(unsigned short)); 888 | data = (unsigned char*)malloc(data_size); 889 | 890 | fread(data,1,data_size,fp_i); 891 | 892 | //offset = ftell(fp_i); 893 | 894 | offset = 0; 895 | while(offset < data_size) 896 | { 897 | //unsigned short marker; 898 | unsigned char line_size; 899 | unsigned char line[256]; 900 | 901 | line_size = data[offset + 0]; 902 | 903 | if (line_size > 2) 904 | { 905 | switch(data[offset + 1]) 906 | { 907 | case 0x80://Statement 908 | case 0x82://Note 909 | 910 | wpg_commnt += line_size - 2; 911 | 912 | memcpy(line,data + offset + 3,line_size - 4); 913 | line[line_size - 4] = 0; 914 | 915 | if (data[offset + 1] == 0x80) 916 | { 917 | printf("\n\n"); 918 | } 919 | if (data[offset + 1] == 0x82) 920 | { 921 | printf("\n\n\t\t\t"); 922 | } 923 | printf("< %s >\n",line); 924 | break; 925 | 926 | default://Instruction 927 | 928 | wpg_netto += line_size - 2; 929 | 930 | memcpy(line,data + offset + 1,line_size - 2); 931 | 932 | { 933 | int i,n; 934 | n = line_size - 2; 935 | 936 | for (i = 0; i < n; i++) 937 | { 938 | printf("%02x ",line[i]); 939 | } 940 | 941 | printf("\t\t\t"); 942 | } 943 | 944 | { 945 | int enc_size; 946 | unsigned char* codes = line; 947 | unsigned int code32bit; 948 | unsigned short code16bit; 949 | 950 | enc_size = line_size - 2; 951 | 952 | switch(enc_size) 953 | { 954 | case 1: 955 | 956 | switch(codes[0]) 957 | { 958 | case 0x00://LD NO 959 | printf("LD"); 960 | break; 961 | 962 | case 0x06://OR 963 | printf("OR"); 964 | break; 965 | 966 | case 0x0c://AND 967 | printf("AND"); 968 | break; 969 | 970 | case 0x0d://ANI 971 | printf("ANI"); 972 | break; 973 | 974 | case 0x18://ORB 975 | printf("ORB"); 976 | break; 977 | 978 | case 0x19://ANB 979 | printf("ANB"); 980 | break; 981 | 982 | case 0x1A: 983 | printf("MPS"); 984 | break; 985 | case 0x1B: 986 | printf("MRD"); 987 | break; 988 | case 0x1C: 989 | printf("MPP"); 990 | break; 991 | 992 | case 0x20://OUT 993 | printf("OUT"); 994 | break; 995 | 996 | case 0x23://SET 997 | printf("SET"); 998 | break; 999 | 1000 | case 0x24://RST 1001 | printf("RST"); 1002 | break; 1003 | 1004 | case 0x33://FEND 1005 | printf("FEND"); 1006 | break; 1007 | 1008 | case 0x34://END 1009 | printf("END"); 1010 | break; 1011 | 1012 | case 0x3c://3c LABLE SHORT: Pxx 1013 | printf("LABLE (short)"); 1014 | break; 1015 | } 1016 | 1017 | break; 1018 | 1019 | case 2: 1020 | 1021 | code16bit = (unsigned int)codes[0]<<8; 1022 | code16bit|= (unsigned int)codes[1]; 1023 | 1024 | switch(code16bit) 1025 | { 1026 | case 0x0C02://NO 1027 | printf("NO (long)"); 1028 | break; 1029 | 1030 | case 0x0D02://NC 1031 | printf("NC (long)"); 1032 | break; 1033 | 1034 | case 0x0302://DOWN 1035 | printf("DOWN"); 1036 | break; 1037 | 1038 | case 0x2003://OUT 1039 | printf("OUT (with indexing, FX)"); 1040 | break; 1041 | 1042 | case 0x2103://OUT 1043 | printf("OUT (timer, FX)"); 1044 | break; 1045 | 1046 | case 0x2104://OUT Timer 1047 | printf("OUT (timer, Q02)"); 1048 | break; 1049 | 1050 | case 0x2302://SET long 1051 | printf("SET (long)"); 1052 | break; 1053 | 1054 | case 0x2402://RST Timer 1055 | printf("RST (long)"); 1056 | break; 1057 | 1058 | case 0x3c02://LABLE long 1059 | printf("LABLE (long)"); 1060 | break; 1061 | 1062 | case 0x2C03: 1063 | printf("MC"); 1064 | break; 1065 | case 0x3002: 1066 | printf("MCR"); 1067 | break; 1068 | 1069 | default: 1070 | 1071 | switch(codes[0]) 1072 | { 1073 | case MEL_DEV_TYPE_X: 1074 | printf("X%d",codes[1]); 1075 | break; 1076 | 1077 | case MEL_DEV_TYPE_Y: 1078 | printf("Y%d",codes[1]); 1079 | break; 1080 | 1081 | case MEL_DEV_TYPE_M: 1082 | printf("M%d",codes[1]); 1083 | break; 1084 | 1085 | case MEL_DEV_TYPE_D: 1086 | printf("D%d",codes[1]); 1087 | break; 1088 | 1089 | case MEL_DEV_TYPE_R: 1090 | printf("R%d",codes[1]); 1091 | break; 1092 | 1093 | case MEL_DEV_TYPE_T: 1094 | printf("T%d",codes[1]); 1095 | break; 1096 | 1097 | case MEL_DEV_TYPE_ZI: 1098 | printf("Z%d",codes[1]); 1099 | break; 1100 | case MEL_DEV_TYPE_VI: 1101 | printf("V%d",codes[1]); 1102 | break; 1103 | case MEL_DEV_TYPE_bI: 1104 | printf("bit[%d]",codes[1]); 1105 | break; 1106 | 1107 | case MEL_DEV_TYPE_K: 1108 | printf("#K=%d",codes[1]); 1109 | break; 1110 | 1111 | case MEL_DEV_TYPE_N: 1112 | printf("#N%d",codes[1]); 1113 | break; 1114 | } 1115 | } 1116 | break; 1117 | 1118 | case 3: 1119 | 1120 | code32bit = (unsigned int)codes[0]<<16; 1121 | code32bit|= (unsigned int)codes[1]<<8; 1122 | code32bit|= (unsigned int)codes[2]; 1123 | 1124 | switch(code32bit) 1125 | { 1126 | case 0x530519://53 05 19 ZRST 1127 | printf("ZRST"); 1128 | break; 1129 | 1130 | case 0x4a0300://4a 03 00 INC 1131 | printf("INC"); 1132 | break; 1133 | 1134 | case 0x4a0302://4a 03 02 DEC 1135 | printf("DEC"); 1136 | break; 1137 | 1138 | case 0x4b050f://4b 05 0f DNEG 1139 | printf("DNEG"); 1140 | break; 1141 | 1142 | case 0x4c0500://4c 05 00 MOV 1143 | printf("MOV"); 1144 | break; 1145 | 1146 | case 0x4c0706://4c 07 06 BMOV 1147 | printf("BMOV"); 1148 | break; 1149 | 1150 | case 0x4c0901://4c 09 01 DMOV 1151 | printf("DMOV"); 1152 | break; 1153 | 1154 | case 0x4c090f://4c 09 0f DEMOV 1155 | printf("DEMOV"); 1156 | break; 1157 | 1158 | case 0x4d0300://4d 03 00 CJ 1159 | printf("CJ"); 1160 | break; 1161 | 1162 | case 0x510500://51 05 00 SFR 1163 | printf("SFR"); 1164 | break; 1165 | 1166 | case 0x510501://51 05 01 SFL 1167 | printf("SFL"); 1168 | break; 1169 | 1170 | case 0x540301://54 03 01 CALL 1171 | printf("CALL"); 1172 | break; 1173 | 1174 | case 0x490728://49 07 28 ADD 1175 | printf("ADD"); 1176 | break; 1177 | 1178 | case 0x49072c://49 07 2c MUL 1179 | printf("MUL"); 1180 | break; 1181 | 1182 | case 0x490d2b://49 0d 2b DSUB 1183 | printf("DSUB"); 1184 | break; 1185 | 1186 | case 0x490d2d://49 0d 2d DMUL 1187 | printf("DMUL"); 1188 | break; 1189 | 1190 | case 0x690101://EI 1191 | printf("EI"); 1192 | break; 1193 | 1194 | case 0x690103://IRET 1195 | printf("IRET"); 1196 | break; 1197 | 1198 | case 0x6a0101://6a 01 01 NEXT 1199 | printf("NEXT"); 1200 | break; 1201 | 1202 | case 0x6a0107://6a 01 07 SRET 1203 | printf("SRET\n---------------------------------------\n"); 1204 | break; 1205 | 1206 | case 0x6a0300://6a 03 00 FOR 1207 | printf("FOR"); 1208 | break; 1209 | 1210 | case 0x560900://56 09 00 FROM 1211 | printf("FROM"); 1212 | break; 1213 | 1214 | case 0x560902://56 09 02 TO 1215 | printf("TO"); 1216 | break; 1217 | 1218 | case 0x5f0b1d://5f 0b 1d RS2 1219 | printf("RS2"); 1220 | break; 1221 | 1222 | case 0x4f0701://4f 07 01 WAND 1223 | printf("WAND"); 1224 | break; 1225 | 1226 | case 0x4f0703://4f 07 03 WOR 1227 | printf("WOR"); 1228 | break; 1229 | 1230 | case 0x4f0d09://4f 0d 09 DAND 1231 | printf("DAND"); 1232 | break; 1233 | 1234 | case 0x4f0d0b://4f 0d 0b DOR 1235 | printf("DOR"); 1236 | break; 1237 | } 1238 | 1239 | break; 1240 | 1241 | 1242 | case 4: 1243 | 1244 | code32bit = (unsigned int)codes[0]<<24; 1245 | code32bit|= (unsigned int)codes[1]<<16; 1246 | code32bit|= (unsigned int)codes[2]<<8; 1247 | code32bit|= (unsigned int)codes[3]; 1248 | 1249 | switch(code32bit) 1250 | { 1251 | case 0x40050111://40 05 01 11 <> 1252 | printf("<>"); 1253 | break; 1254 | 1255 | case 0x40050011://40 05 00 11 == 1256 | printf("=="); 1257 | break; 1258 | 1259 | case 0x40090611://40 09 06 11 D= 1260 | printf("D="); 1261 | break; 1262 | 1263 | case 0x40090811://40 09 08 11 D> 1264 | printf("D>"); 1265 | break; 1266 | 1267 | case 0x40090a11://40 09 0a 11 D< 1268 | printf("D<"); 1269 | break; 1270 | } 1271 | 1272 | break; 1273 | case 5: 1274 | if (codes[0]==MEL_DEV_TYPE_E) 1275 | { 1276 | union{ 1277 | unsigned int tint; 1278 | float tflt; 1279 | }tmp; 1280 | 1281 | tmp.tint = ((unsigned int)codes[4]<<24) 1282 | | ((unsigned int)codes[3]<<16) 1283 | | ((unsigned int)codes[2]<<8) 1284 | | ((unsigned int)codes[1]); 1285 | 1286 | printf("#E=%f",tmp.tflt); 1287 | } 1288 | break; 1289 | case 6: 1290 | break; 1291 | case 7: 1292 | break; 1293 | } 1294 | } 1295 | 1296 | printf("\n"); 1297 | } 1298 | } 1299 | 1300 | offset += line_size; 1301 | 1302 | /* 1303 | marker = data[offset + 0]; 1304 | marker|= (unsigned short)data[offset + 1]<<8; 1305 | 1306 | switch(marker) 1307 | { 1308 | case 0x0080://Statement 1309 | 1310 | comm_size = data[offset - 1]; 1311 | memcpy(comm,data + offset + 2,comm_size - 4); 1312 | comm[comm_size - 4] = 0; 1313 | 1314 | printf("\n\n80 comm: %s\n",comm); 1315 | offset += comm_size - 1; 1316 | break; 1317 | 1318 | case 0x0082://Note 1319 | 1320 | comm_size = data[offset - 1]; 1321 | memcpy(comm,data + offset + 2,comm_size - 4); 1322 | comm[comm_size - 4] = 0; 1323 | 1324 | printf("\n\n82 comm: %s\n",comm); 1325 | offset += comm_size - 1; 1326 | 1327 | break; 1328 | 1329 | default: 1330 | 1331 | printf("%02x ",data[offset + 0]); 1332 | 1333 | offset++; 1334 | } 1335 | */ 1336 | }; 1337 | 1338 | if(data) free(data); 1339 | 1340 | if (fp_i) 1341 | { 1342 | fclose(fp_i); 1343 | } 1344 | 1345 | wpg_brutto = file_size; 1346 | 1347 | printf("wpg netto: %d bytes (%x)\n", wpg_netto,wpg_netto); 1348 | printf("wpg cmnts: %d bytes (%x)\n", wpg_commnt,wpg_commnt); 1349 | printf("wpg brutto: %d bytes (%x)\n", wpg_brutto,wpg_brutto); 1350 | 1351 | return(0); 1352 | } 1353 | 1354 | 1355 | #endif 1356 | -------------------------------------------------------------------------------- /mel_common.c: -------------------------------------------------------------------------------- 1 | #include //memset 2 | #include //sprintf 3 | 4 | #include "mel_common.h" 5 | #include "mel_wpa_fxcpu_fx3.h" 6 | #include "mel_wcd_fxcpu_fx3.h" 7 | #include "mel_wpg_fxcpu_fx3.h" 8 | 9 | #ifdef WIN32 10 | #pragma warning (disable : 4996) 11 | #endif 12 | 13 | static const int MultiplyDeBruijnBitPosition2[32] = 14 | { 15 | 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 16 | 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 17 | }; 18 | 19 | int get_log2(unsigned int powerOf2) 20 | { 21 | //http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn 22 | return(MultiplyDeBruijnBitPosition2[(powerOf2 * 0x077CB531U) >> 27]); 23 | } 24 | 25 | int is_within_JIS8(unsigned char uc) 26 | { 27 | int isin = 0; 28 | 29 | //JIS8 http://www.ohsumap.ne.jp/lib/code/jis.htm 30 | 31 | if ( (uc >= 0x00 && uc <= 0x7F) || (uc >= 0xA0 && uc <= 0xDF) ) 32 | { 33 | isin = 1; 34 | } 35 | 36 | return(isin); 37 | } 38 | 39 | int mel_wpg_uint_sizeof(unsigned int number) 40 | { 41 | int data_size = 1; 42 | 43 | if (number > (256-1)) 44 | { 45 | if (number > (65536-1) ) 46 | { 47 | if (number > (16777216-1)) 48 | { 49 | data_size = 4; 50 | } 51 | else 52 | { 53 | data_size = 3; 54 | } 55 | } 56 | else{ 57 | data_size = 2; 58 | } 59 | } 60 | 61 | return(data_size); 62 | } 63 | 64 | int mel_get_toolbox (int cpuSeries,int cpuType,MELTools* tools) 65 | { 66 | //set all fields to 0 67 | memset(tools,0x00,sizeof(*tools)); 68 | 69 | switch((cpuSeries<<8)|cpuType) 70 | { 71 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX0_S): 72 | break; 73 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX0N): 74 | break; 75 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1): 76 | break; 77 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FXU_FX2C): 78 | break; 79 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX2N_C): 80 | break; 81 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1S): 82 | break; 83 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1N_S): 84 | break; 85 | 86 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX3U_C): 87 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX3G_C): 88 | tools->sizeof_wpax = sizeof(WPA_FXCPU_FX3U); 89 | tools->wpa_decoder = &mel_wpa_FXCPU_FX3_decoder; 90 | tools->wpa_encoder = &mel_wpa_FXCPU_FX3_encoder; 91 | tools->wpa_destroy = &mel_wpa_FXCPU_FX3U_free; 92 | 93 | tools->sizeof_wcdx = sizeof(WCD_FXCPU_FX3U); 94 | tools->wcd_decoder = &mel_wcd_FXCPU_FX3_decoder; 95 | tools->wcd_encoder = &mel_wcd_FXCPU_FX3_encoder; 96 | tools->wcd_destroy = &mel_wcd_FXCPU_FX3U_free; 97 | 98 | tools->sizeof_wpgx = sizeof(WPG_FXCPU_FX3U); 99 | tools->wpg_decoder = &mel_wpg_FXCPU_FX3_decoder; 100 | tools->wpg_encoder = &mel_wpg_FXCPU_FX3_encoder; 101 | tools->til_decoder = &mel_til_FXCPU_FX3_decoder; 102 | tools->til_encoder = &mel_til_FXCPU_FX3_encoder; 103 | tools->wpg_destroy = &mel_wpg_FXCPU_FX3_free; 104 | break; 105 | } 106 | 107 | tools->cpuSeries = cpuSeries; 108 | tools->cpuType = cpuType; 109 | 110 | return(tools->sizeof_wpax); 111 | } 112 | 113 | char* mel_wpg_fxcpu_get_plctypename(int plctype) 114 | { 115 | char* name = "UNKNOWN"; 116 | 117 | switch(plctype) 118 | { 119 | case MEL_PLC_FXCPU_TYPE_FX3U_C: name = "FX3U/C"; break; 120 | case MEL_PLC_FXCPU_TYPE_FX3G_C: name = "FX3G/C "; break; 121 | } 122 | 123 | return(name); 124 | } 125 | -------------------------------------------------------------------------------- /mel_common.h: -------------------------------------------------------------------------------- 1 | #ifndef __mel_common_h__ 2 | #define __mel_common_h__ 3 | 4 | ////////////////////////////////////////////////////////////////////////// 5 | //PLC SERIES 6 | 7 | #define MEL_PLC_SERIES_NULL 0x00 8 | 9 | #define MEL_PLC_SERIES_QCPU_Qmode MEL_PLC_SERIES_NULL 10 | #define MEL_PLC_SERIES_QCPU_QmodeRemoteIO 0x03 11 | #define MEL_PLC_SERIES_QCPU_Amode 0x01 12 | #define MEL_PLC_SERIES_LCPU MEL_PLC_SERIES_NULL 13 | #define MEL_PLC_SERIES_QSCPU MEL_PLC_SERIES_NULL 14 | #define MEL_PLC_SERIES_QnACPU MEL_PLC_SERIES_NULL 15 | #define MEL_PLC_SERIES_ACPU 0x01 16 | #define MEL_PLC_SERIES_MOTION_SCPU 0x06 17 | #define MEL_PLC_SERIES_FXCPU 0x02 18 | #define MEL_PLC_SERIES_CNC MEL_PLC_SERIES_NULL 19 | 20 | ////////////////////////////////////////////////////////////////////////// 21 | //PLC TYPE 22 | 23 | #define MEL_PLC_TYPE_NULL 0x00 24 | 25 | #define MEL_PLC_QCPU_Qmode_TYPE_Q00J 0x30 26 | #define MEL_PLC_QCPU_Qmode_TYPE_Q00 0x31 27 | #define MEL_PLC_QCPU_Qmode_TYPE_Q01 0x32 28 | #define MEL_PLC_QCPU_Qmode_TYPE_Q01U 0x82 29 | #define MEL_PLC_QCPU_Qmode_TYPE_Q00UJ 0x80 30 | #define MEL_PLC_QCPU_Qmode_TYPE_Q02H 0x22 31 | #define MEL_PLC_QCPU_Qmode_TYPE_Q02PH 0x45 32 | #define MEL_PLC_QCPU_Qmode_TYPE_Q02U 0x83 33 | #define MEL_PLC_QCPU_Qmode_TYPE_Q03UD 0x70 34 | #define MEL_PLC_QCPU_Qmode_TYPE_Q03UDE 0x90 35 | #define MEL_PLC_QCPU_Qmode_TYPE_Q04UDH 0x71 36 | #define MEL_PLC_QCPU_Qmode_TYPE_Q04UDEH 0x91 37 | #define MEL_PLC_QCPU_Qmode_TYPE_Q06H 0x23 38 | #define MEL_PLC_QCPU_Qmode_TYPE_Q06PH 0x46 39 | #define MEL_PLC_QCPU_Qmode_TYPE_Q06UDH 0x72 40 | #define MEL_PLC_QCPU_Qmode_TYPE_Q06UDEH 0x92 41 | #define MEL_PLC_QCPU_Qmode_TYPE_Q10UDH 0x75 42 | #define MEL_PLC_QCPU_Qmode_TYPE_Q10UDEH 0x95 43 | #define MEL_PLC_QCPU_Qmode_TYPE_Q12H 0x24 44 | #define MEL_PLC_QCPU_Qmode_TYPE_Q12PH 0x41 45 | #define MEL_PLC_QCPU_Qmode_TYPE_Q12PRH 0x43 46 | #define MEL_PLC_QCPU_Qmode_TYPE_Q13UDH 0x73 47 | #define MEL_PLC_QCPU_Qmode_TYPE_Q13UDEH 0x93 48 | #define MEL_PLC_QCPU_Qmode_TYPE_Q20UDH 0x76 49 | #define MEL_PLC_QCPU_Qmode_TYPE_Q20UDEH 0x96 50 | #define MEL_PLC_QCPU_Qmode_TYPE_Q25H 0x25 51 | #define MEL_PLC_QCPU_Qmode_TYPE_Q25PH 0x42 52 | #define MEL_PLC_QCPU_Qmode_TYPE_Q25PRH 0x44 53 | #define MEL_PLC_QCPU_Qmode_TYPE_Q26UDH 0x74 54 | #define MEL_PLC_QCPU_Qmode_TYPE_Q26UDEH 0x94 55 | #define MEL_PLC_QCPU_Qmode_TYPE_RemoteIO 0x04 56 | 57 | #define MEL_PLC_QCPU_Amode_TYPE_Q02H_A 0x41 58 | #define MEL_PLC_QCPU_Amode_TYPE_Q06H_A 0x42 59 | 60 | #define MEL_PLC_LCPU_TYPE_L02 0xA1 61 | #define MEL_PLC_LCPU_TYPE_L26BT 0xA2 62 | 63 | #define MEL_PLC_QSCPU_TYPE_QS001 0x60 64 | 65 | #define MEL_PLC_QnACPU_TYPE_Q2A 0x11 66 | #define MEL_PLC_QnACPU_TYPE_Q2AS_H MEL_PLC_QnACPU_TYPE_Q2A 67 | #define MEL_PLC_QnACPU_TYPE_Q2AS1 0x12 68 | #define MEL_PLC_QnACPU_TYPE_Q2AS_H_S1 MEL_PLC_QnACPU_TYPE_Q2AS1 69 | #define MEL_PLC_QnACPU_TYPE_Q3A 0x13 70 | #define MEL_PLC_QnACPU_TYPE_Q4A 0x14 71 | #define MEL_PLC_QnACPU_TYPE_Q4AR MEL_PLC_QnACPU_TYPE_Q4A 72 | 73 | #define MEL_PLC_CNC_TYPE_Q4A MEL_PLC_QnACPU_TYPE_Q4A 74 | 75 | #define MEL_PLC_ACPU_TYPE_A0JH 0x02 76 | #define MEL_PLC_ACPU_TYPE_A1FX 0x03 77 | #define MEL_PLC_ACPU_TYPE_A1S_S1 0x04 78 | #define MEL_PLC_ACPU_TYPE_A1SJ MEL_PLC_ACPU_TYPE_A1S_S1 79 | #define MEL_PLC_ACPU_TYPE_A1SH 0x05 80 | #define MEL_PLC_ACPU_TYPE_A1SJH MEL_PLC_ACPU_TYPE_A1SH 81 | #define MEL_PLC_ACPU_TYPE_A1N 0x06 82 | #define MEL_PLC_ACPU_TYPE_A2C 0x07 83 | #define MEL_PLC_ACPU_TYPE_A2CJ MEL_PLC_ACPU_TYPE_A2C 84 | #define MEL_PLC_ACPU_TYPE_A2N_S1 0x08 85 | #define MEL_PLC_ACPU_TYPE_A2S_S1 MEL_PLC_ACPU_TYPE_A2N_S1 86 | #define MEL_PLC_ACPU_TYPE_A2SH_S1 0x09 87 | #define MEL_PLC_ACPU_TYPE_A3N 0x0A 88 | #define MEL_PLC_ACPU_TYPE_A2A_S1 0x0C 89 | #define MEL_PLC_ACPU_TYPE_A3A 0x0D 90 | #define MEL_PLC_ACPU_TYPE_A2U_S1 0x0E 91 | #define MEL_PLC_ACPU_TYPE_A2US_S1 MEL_PLC_ACPU_TYPE_A2U_S1 92 | #define MEL_PLC_ACPU_TYPE_A2AS_S1 MEL_PLC_ACPU_TYPE_A2U_S1 93 | #define MEL_PLC_ACPU_TYPE_A2USH_S1 0x0F 94 | #define MEL_PLC_ACPU_TYPE_A2AS_S30 0x10 95 | #define MEL_PLC_ACPU_TYPE_A2AS_S60 MEL_PLC_ACPU_TYPE_A2AS_S30 96 | #define MEL_PLC_ACPU_TYPE_A3U MEL_PLC_ACPU_TYPE_A2AS_S30 97 | #define MEL_PLC_ACPU_TYPE_A4U 0x11 98 | 99 | #define MEL_PLC_MOTION_SCPU_TYPE_A171SH 0x01 100 | #define MEL_PLC_MOTION_SCPU_TYPE_A172SH 0x02 101 | #define MEL_PLC_MOTION_SCPU_TYPE_A273UH_S3 0x03 102 | #define MEL_PLC_MOTION_SCPU_TYPE_A173UH_S1 0x04 103 | 104 | typedef enum tagFXCPU_Types 105 | { 106 | MEL_PLC_FXCPU_TYPE_FX3U_C = 0, 107 | MEL_PLC_FXCPU_TYPE_FX3G_C, 108 | MEL_PLC_FXCPU_TYPE_FX1N_S, 109 | MEL_PLC_FXCPU_TYPE_FX1S, 110 | MEL_PLC_FXCPU_TYPE_FX2N_C, 111 | MEL_PLC_FXCPU_TYPE_FXU_FX2C, 112 | MEL_PLC_FXCPU_TYPE_FX1, 113 | MEL_PLC_FXCPU_TYPE_FX0N, 114 | MEL_PLC_FXCPU_TYPE_FX0_S, 115 | MEL_PLC_FXCPU_TYPE_LAST 116 | }FXCPU_Types; 117 | 118 | char* mel_wpg_fxcpu_get_plctypename(int plctype); 119 | 120 | #define MEL_PLC_FXCPU_TYPE_CODE_FX0_S 0x01 121 | #define MEL_PLC_FXCPU_TYPE_CODE_FX0N 0x02 122 | #define MEL_PLC_FXCPU_TYPE_CODE_FX1 0x03 123 | #define MEL_PLC_FXCPU_TYPE_CODE_FXU_FX2C 0x04 124 | #define MEL_PLC_FXCPU_TYPE_CODE_FX2N_C 0x05 125 | #define MEL_PLC_FXCPU_TYPE_CODE_FX1S 0x06 126 | #define MEL_PLC_FXCPU_TYPE_CODE_FX1N_S 0x07 127 | #define MEL_PLC_FXCPU_TYPE_CODE_FX3U_C 0x08 128 | #define MEL_PLC_FXCPU_TYPE_CODE_FX3G 0x09 129 | 130 | static unsigned char FXCPU_TYPE_CODES_by_type[MEL_PLC_FXCPU_TYPE_LAST] = 131 | { 132 | MEL_PLC_FXCPU_TYPE_CODE_FX3U_C, 133 | MEL_PLC_FXCPU_TYPE_CODE_FX3G, 134 | MEL_PLC_FXCPU_TYPE_CODE_FX1N_S, 135 | MEL_PLC_FXCPU_TYPE_CODE_FX1S, 136 | MEL_PLC_FXCPU_TYPE_CODE_FX2N_C, 137 | MEL_PLC_FXCPU_TYPE_CODE_FXU_FX2C, 138 | MEL_PLC_FXCPU_TYPE_CODE_FX1, 139 | MEL_PLC_FXCPU_TYPE_CODE_FX0N, 140 | MEL_PLC_FXCPU_TYPE_CODE_FX0_S 141 | }; 142 | static unsigned char FXCPU_TYPES_by_code[256] = 143 | { 144 | 0, 145 | MEL_PLC_FXCPU_TYPE_FX0_S, 146 | MEL_PLC_FXCPU_TYPE_FX0N, 147 | MEL_PLC_FXCPU_TYPE_FX1, 148 | MEL_PLC_FXCPU_TYPE_FXU_FX2C, 149 | MEL_PLC_FXCPU_TYPE_FX2N_C, 150 | MEL_PLC_FXCPU_TYPE_FX1S, 151 | MEL_PLC_FXCPU_TYPE_FX1N_S, 152 | MEL_PLC_FXCPU_TYPE_FX3U_C, 153 | MEL_PLC_FXCPU_TYPE_FX3G_C, 154 | 0 155 | }; 156 | ////////////////////////////////////////////////////////////////////////// 157 | 158 | #define WPA_HEADER_SIZE_BYTES 64 //0x40 159 | #define WPG_SFC_SUBHEADER_SIZE_BYTES 48 //0x30 160 | 161 | #define WPA_CPU_TYPE_OFFSET 0x26 162 | #define WPA_CPU_SERIES_OFFSET 0x27 163 | #define WPG_PROGRAMM_MODE_OFFSET 0x2A 164 | /* 165 | char* mnemonic; //D,M,X,Y,... 166 | int base; //number of first device 167 | int total;//[PLC model] //amount of all these devices 168 | */ 169 | 170 | #define WPA_CODE_MEMORY_CAPACITY 0xE0FF 171 | #define WPA_CODE_CMNT_CAPACITY 0x16FF 172 | #define WPA_CODE_DEVICES 0x0120 173 | #define WPA_CODE_PLCNAME 0x0100 174 | #define WPA_CODE_EOF 0xFFFF 175 | 176 | #define WPG_CODE_STATEMENT 0x80 177 | #define WPG_CODE_NOTE 0x82 178 | #define WPG_CODE_LABEL 0x3C 179 | 180 | typedef struct tagMELTools 181 | { 182 | int cpuSeries; 183 | int cpuType; 184 | 185 | int sizeof_wpax; 186 | /* returns: done stream size > 0, error =0. */ 187 | int (*wpa_decoder)(unsigned char* stream,int enc_size,void* wpax); 188 | /* returns: done stream size > 0, error =0. */ 189 | int (*wpa_encoder)(void* wpax,unsigned char* stream); 190 | void (*wpa_destroy)(void* wpax); 191 | 192 | int sizeof_wcdx; 193 | /* returns: done stream size > 0, error =0. */ 194 | int (*wcd_decoder)(unsigned char* stream,int enc_size,void* wcdx); 195 | /* returns: done stream size > 0, error =0. */ 196 | int (*wcd_encoder)(void* wcdx,unsigned char* stream); 197 | void (*wcd_destroy)(void* wcdx); 198 | 199 | int sizeof_wpgx; 200 | /* returns: done stream size > 0, error =0. */ 201 | int (*wpg_decoder)(unsigned char* stream,int enc_size,void* wpgx); 202 | int (*til_decoder)(unsigned char* stream,int enc_size,void* wpgx,int maxsteps); 203 | /* returns: done stream size > 0, error =0. */ 204 | int (*wpg_encoder)(void* wpgx,unsigned char* stream,int maxsteps); 205 | int (*til_encoder)(void* wpgx,unsigned char* stream); 206 | void (*wpg_destroy)(void* wpgx); 207 | 208 | }MELTools; 209 | 210 | /* 211 | Please, use it to setup "tools" properly. 212 | returns: required size of wpax instance, bytes; 0 - failure; 213 | */ 214 | int mel_get_toolbox (int cpuSeries,int cpuType,MELTools* tools); 215 | /* To check character */ 216 | int is_within_JIS8(unsigned char uc); 217 | 218 | int get_log2(unsigned int powerOf2); 219 | 220 | int mel_wpg_uint_sizeof (unsigned int number); 221 | 222 | #define MEL_WPG_MAX_STATEMENT_TEXT_SIZE 64 223 | #define MEL_WPG_MAX_NOTE_TEXT_SIZE 32 224 | 225 | #define MEL_WPG_MIN_TIL_SIZE 5 //END + (CR,LF/LF,CR) 226 | #define MEL_WPG_MIN_INSTR_TEXT_SIZE 2 //*x, EI,DI, etc. 227 | #define MEL_WPG_MAX_INSTR_TEXT_SIZE 256 //??? 228 | 229 | #endif //__mel_common_h__ 230 | -------------------------------------------------------------------------------- /mel_metrix.c: -------------------------------------------------------------------------------- 1 | #include "mel_metrix.h" 2 | #include "mel_wpg_tables.h" 3 | #include "mel_metrix_table.h" 4 | 5 | #include 6 | 7 | void mel_metrix_generate(void) 8 | { 9 | int i; 10 | 11 | for (i = 0; i < MEL_WPG_OpID_TOTALLY; i++) 12 | { 13 | int j; 14 | 15 | for (j = 0; j < MEL_INSTRUCT_OPERANDS_MAX; j++) 16 | { 17 | int cpu = 0; 18 | 19 | WPG_METRIX[i].operands[j].txt_usage = INSTRUCTIONS_METRIX_FXCPU[i].operands[j].txt_usage; 20 | 21 | for (cpu = 0; cpu < 2; cpu++) 22 | { 23 | WPG_METRIX[i].operands[j].txt_operands[cpu] = INSTRUCTIONS_METRIX_FXCPU[i].operands[j].txt_operands[cpu]; 24 | } 25 | } 26 | } 27 | 28 | return; 29 | } 30 | 31 | void mel_metrix_printf(void) 32 | { 33 | int i; 34 | 35 | printf("static WPGMetrixRecord WPG_METRIX[MEL_WPG_OpID_TOTALLY] =\n{\n"); 36 | 37 | for (i = 0; i < MEL_WPG_OpID_TOTALLY; i++) 38 | { 39 | int j; 40 | 41 | //printf("\t{ //\"%s\" ",INSTRUCTIONS_METRIX_FXCPU[i].name); 42 | printf("\t{ //\"%s\" ",WPG_OPNAMES[i].name); 43 | 44 | if (WPG_METRIX[i].operands[0].txt_usage) 45 | { 46 | for (j = 0; j < MEL_INSTRUCT_OPERANDS_MAX; j++) 47 | { 48 | int cpu = 0; 49 | 50 | if (WPG_METRIX[i].operands[j].txt_usage) 51 | { 52 | printf("\n\n\t\t\t\"%s\",",WPG_METRIX[i].operands[j].txt_usage); 53 | printf("\t{\t"); 54 | for (cpu = 0; cpu < 2; cpu++) 55 | { 56 | printf("\"%s\"",WPG_METRIX[i].operands[j].txt_operands[cpu]); 57 | if(cpu!=2-1) printf(",\n\t\t\t\t\t\t"); 58 | } 59 | printf("}"); 60 | } 61 | else 62 | { 63 | printf("0"); 64 | break; 65 | } 66 | 67 | if (j != MEL_INSTRUCT_OPERANDS_MAX-1) 68 | { 69 | printf(",\t"); 70 | } 71 | } 72 | } 73 | else 74 | { 75 | printf("\n\t\t\t0\t"); 76 | } 77 | 78 | printf("}"); 79 | 80 | if (i != MEL_WPG_OpID_TOTALLY-1) 81 | { 82 | printf(","); 83 | } 84 | 85 | printf("\n"); 86 | } 87 | 88 | printf("};\n"); 89 | 90 | return; 91 | } 92 | 93 | void mel_metrix_stats(void) 94 | { 95 | int i; 96 | int n_instractions = MEL_WPG_OpID_TOTALLY; 97 | int n_done = 0; 98 | 99 | for (i = 0; i < MEL_WPG_OpID_TOTALLY; i++) 100 | { 101 | //int j; 102 | //if (WPG_METRIX[i].operands[0].txt_usage) 103 | 104 | if(INSTRUCTIONS_METRIX_FXCPU[i].folder) 105 | { 106 | n_done++; 107 | } 108 | } 109 | 110 | printf("//Totally: %d instructions; %d done (%.0f %%)\n", 111 | n_instractions, 112 | n_done, 113 | (double)n_done*100/(double)n_instractions 114 | ); 115 | 116 | return; 117 | } 118 | 119 | void mel_opnames_printf(void) 120 | { 121 | int i; 122 | 123 | printf("static WPGOpNameRecord WPG_OPNAMES[MEL_WPG_OpID_TOTALLY] =\n{\n"); 124 | 125 | for (i = 0; i < MEL_WPG_OpID_TOTALLY; i++) 126 | { 127 | int name_strlen = WPG_OPNAMES[i].namelen; 128 | 129 | printf("\t{\"%s\",",WPG_OPNAMES[i].name); 130 | { 131 | int diff = 10 - name_strlen; 132 | 133 | while (diff-- > 0) 134 | { 135 | printf(" "); 136 | } 137 | } 138 | printf("%2d}",name_strlen); 139 | 140 | if (i != MEL_WPG_OpID_TOTALLY-1) 141 | { 142 | printf(","); 143 | } 144 | 145 | printf("\n"); 146 | } 147 | 148 | printf("};\n"); 149 | 150 | return; 151 | } -------------------------------------------------------------------------------- /mel_metrix.h: -------------------------------------------------------------------------------- 1 | #ifndef __mel_metrix_h__ 2 | #define __mel_metrix_h__ 3 | 4 | void mel_metrix_generate(void); 5 | void mel_metrix_printf(void); 6 | void mel_metrix_stats(void); 7 | 8 | void mel_opnames_printf(void); 9 | 10 | #endif //__mel_metrix_h__ 11 | -------------------------------------------------------------------------------- /mel_wcd.c: -------------------------------------------------------------------------------- 1 | #include "mel_wcd.h" 2 | 3 | #include //calloc 4 | #include //memset 5 | 6 | static unsigned char WCD_HEADER[WPA_HEADER_SIZE_BYTES] = 7 | { 8 | 0x40,0x00,0x22,0x01,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 9 | 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 10 | 11 | 0x20,0x20,0x20,0x20,0x04,0x02,0x08,0x02, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 12 | /* [type,series] */ 13 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF 14 | }; 15 | 16 | static int mel_enc_wcd_header (int cpuSeries,int cpuType,unsigned char* stream); 17 | 18 | /* returns: pointer to allocated (by malloc()) WCD_x structure; in case of failure: =0. */ 19 | void* mel_wcd_dec(unsigned char* stream,int enc_size,int* pcpuSeries,int* pcpuType,MELTools* tools) 20 | { 21 | void *wcd = 0; 22 | //set initially as unknown 23 | *pcpuSeries = MEL_PLC_SERIES_NULL; 24 | *pcpuType = MEL_PLC_TYPE_NULL; 25 | //check for too short streams 26 | if (enc_size > 0x40) 27 | { 28 | int hdr_length = (int)stream[0]|((int)stream[1]<<8); 29 | 30 | //0. check header 31 | if (hdr_length == WPA_HEADER_SIZE_BYTES) 32 | { 33 | int cpuSeries; 34 | int cpuType; 35 | 36 | unsigned char cpuTypeCode; 37 | 38 | //1. decode CPU Series & Type 39 | cpuTypeCode = stream[WPA_CPU_TYPE_OFFSET]; 40 | cpuSeries = stream[WPA_CPU_SERIES_OFFSET]; 41 | 42 | if (cpuSeries == MEL_PLC_SERIES_FXCPU) 43 | { 44 | cpuType = FXCPU_TYPES_by_code[cpuTypeCode]; 45 | } 46 | else 47 | { 48 | cpuType = cpuTypeCode; 49 | } 50 | 51 | *pcpuSeries = cpuSeries; 52 | *pcpuType = cpuType; 53 | 54 | //2. allocate appropriate WCD_x struct 55 | wcd = mel_wcd_allocate(cpuSeries,cpuType,tools); 56 | if (wcd) 57 | { 58 | int done_size; 59 | //3. decode all fields of WCD_x 60 | done_size = tools->wcd_decoder( stream +hdr_length, 61 | enc_size-hdr_length, 62 | wcd); 63 | //printf("done: %d\n",done_size); 64 | if (done_size != enc_size-hdr_length) 65 | { 66 | //error has happened during decoding: destroy wcd 67 | tools->wcd_destroy(wcd); 68 | wcd = 0; 69 | } 70 | //else{/* successfully done */} 71 | } 72 | //else{/* unknown CPU */} 73 | } 74 | //else{/* wrong encoded value of header's size */} 75 | } 76 | //else{/* stream is too short */} 77 | 78 | return(wcd); 79 | } 80 | /* returns: encoded size >0, failure: =0. */ 81 | int mel_wcd_enc(int cpuSeries,int cpuType,void* wcd,unsigned char* stream,MELTools* tools) 82 | { 83 | int enc_size = 0; 84 | 85 | if (wcd) 86 | { 87 | int hdr_length; 88 | //encode header 89 | hdr_length = mel_enc_wcd_header(cpuSeries,cpuType,stream); 90 | //encode rest of file 91 | enc_size = tools->wcd_encoder(wcd,stream + hdr_length); 92 | if (enc_size > 0) 93 | { 94 | enc_size += hdr_length; 95 | } 96 | } 97 | 98 | return(enc_size); 99 | } 100 | 101 | void* mel_wcd_allocate(int cpuSeries,int cpuType,MELTools* tools) 102 | { 103 | void* wcd = 0; 104 | 105 | if(mel_get_toolbox(cpuSeries,cpuType,tools)) 106 | { 107 | wcd = calloc(1,tools->sizeof_wcdx); 108 | } 109 | 110 | return(wcd); 111 | } 112 | 113 | void mel_wcd_free (MELTools* tools,void* wcd) 114 | { 115 | if(tools) if(tools->wcd_destroy) if(wcd) tools->wcd_destroy(wcd); 116 | return; 117 | } 118 | 119 | static int mel_enc_wcd_header (int cpuSeries,int cpuType,unsigned char* stream) 120 | { 121 | unsigned char cpuTypeCode; 122 | 123 | //copy all 124 | memcpy(stream,WCD_HEADER,WPA_HEADER_SIZE_BYTES); 125 | //tune CPU type & series 126 | if (cpuSeries == MEL_PLC_SERIES_FXCPU) 127 | { 128 | cpuTypeCode = FXCPU_TYPE_CODES_by_type[cpuType]; 129 | } 130 | else 131 | { 132 | cpuTypeCode = cpuType&0xFF; 133 | } 134 | 135 | 136 | stream[WPA_CPU_TYPE_OFFSET] = cpuTypeCode; 137 | stream[WPA_CPU_SERIES_OFFSET] = cpuSeries &0xFF; 138 | 139 | return(WPA_HEADER_SIZE_BYTES); 140 | } 141 | -------------------------------------------------------------------------------- /mel_wcd.h: -------------------------------------------------------------------------------- 1 | #ifndef __mel_wcd_h__ 2 | #define __mel_wcd_h__ 3 | 4 | #include "mel_wcd_fxcpu_fx3.h" 5 | 6 | /* 7 | returns: pointer to allocated (by malloc()) WCD_x structure; in case of failure: =0. 8 | Also, it calls internally mel_wpa_get_toolbox() to setup "tools" properly; 9 | */ 10 | void* mel_wcd_allocate (int cpuSeries,int cpuType,MELTools* tools); 11 | void mel_wcd_free (MELTools* tools,void* wcd); 12 | 13 | /* returns: pointer to allocated (by malloc()) WCD_x structure; in case of failure: =0. */ 14 | void* mel_wcd_dec (unsigned char* stream,int enc_size,int* pcpuSeries,int* pcpuType,MELTools* tools); 15 | 16 | /* returns: encoded size >0, failure: =0. */ 17 | int mel_wcd_enc (int cpuSeries,int cpuType,void* wcd,unsigned char* stream,MELTools* tools); 18 | 19 | 20 | #endif /* __mel_wcd_h__ */ 21 | -------------------------------------------------------------------------------- /mel_wcd_fxcpu_fx3.c: -------------------------------------------------------------------------------- 1 | #include "mel_wcd.h" 2 | #include //memset 3 | #include //free 4 | 5 | /* returns: done stream size > 0, error =0. */ 6 | int mel_wcd_FXCPU_FX3_decoder(unsigned char* stream,int enc_size,void* wcdx) 7 | { 8 | int done_size = 0; 9 | WCD_FXCPU_FX3U* wcd = (WCD_FXCPU_FX3U*)wcdx; 10 | 11 | if (enc_size > MEL_WCD_SUBHEADER_SIZE) 12 | { 13 | int body_size; 14 | 15 | body_size = (int)stream[0]|((int)stream[1]<<8); 16 | //[2-5]: 00 00 00 00 17 | //[6,7]: 20 08 18 | if (body_size > 0) 19 | { 20 | int i; 21 | unsigned char* ptr_codes = stream + MEL_WCD_SUBHEADER_SIZE; 22 | unsigned char* ptr_names; 23 | 24 | wcd->n_codes = (int)stream[8]|((int)stream[9]<<8); 25 | if (wcd->n_codes > 0) 26 | { 27 | wcd->codes = calloc(wcd->n_codes,sizeof(WCD_FX3U_DevRange)); 28 | if(wcd->codes == 0) goto __exit_point; 29 | } 30 | 31 | wcd->n_names = (enc_size - MEL_WCD_SUBHEADER_SIZE - wcd->n_codes*MEL_WCD_CODE_SIZE)/MEL_WCD_DEVICENAME_MAX_BYTES; 32 | if (wcd->n_names > 0) 33 | { 34 | wcd->names = calloc(wcd->n_names,sizeof(WCD_FX3U_DevName)); 35 | if(wcd->names == 0) goto __exit_point; 36 | } 37 | 38 | for (i = 0; i < wcd->n_codes; i++) 39 | { 40 | wcd->codes[i].item.dtype = (unsigned int)ptr_codes[0]|((unsigned int)ptr_codes[1]<<8); 41 | 42 | wcd->codes[i].item.index = (int)ptr_codes[2] 43 | |((int)ptr_codes[3]<<8) 44 | |((int)ptr_codes[4]<<16) 45 | |((int)ptr_codes[5]<<24); 46 | 47 | wcd->codes[i].count = (int)ptr_codes[6] 48 | |((int)ptr_codes[7]<<8) 49 | |((int)ptr_codes[8]<<16) 50 | |((int)ptr_codes[9]<<24); 51 | 52 | ptr_codes += MEL_WCD_CODE_SIZE; 53 | } 54 | ptr_names = ptr_codes; 55 | for (i = 0; i < wcd->n_names; i++) 56 | { 57 | memcpy(wcd->names[i].raw,ptr_names,MEL_WCD_DEVICENAME_MAX_BYTES); 58 | wcd->names[i].raw[MEL_WCD_DEVICENAME_MAX_BYTES] = 0x00; 59 | ptr_names += MEL_WCD_DEVICENAME_MAX_BYTES; 60 | } 61 | 62 | done_size = enc_size; 63 | } 64 | } 65 | __exit_point: 66 | return(done_size); 67 | } 68 | /* returns: done stream size > 0, error =0. */ 69 | int mel_wcd_FXCPU_FX3_encoder(void* wcdx,unsigned char* stream) 70 | { 71 | int done_size = 0; 72 | WCD_FXCPU_FX3U* wcd = (WCD_FXCPU_FX3U*)wcdx; 73 | 74 | if (wcd) 75 | { 76 | int body_size; 77 | int temp; 78 | 79 | body_size = wcd->n_codes*MEL_WCD_CODE_SIZE + MEL_WCD_SUBHEADER_SIZE; 80 | 81 | temp = body_size; 82 | stream[0] = temp&0xFF; 83 | stream[1] = (temp>>8)&0xFF; 84 | 85 | //[2-5]: 00 00 00 00 86 | //[6,7]: 20 08 87 | stream[2] = 0x00; 88 | stream[3] = 0x00; 89 | stream[4] = 0x00; 90 | stream[5] = 0x00; 91 | 92 | stream[6] = 0x20; 93 | stream[7] = 0x08; 94 | 95 | temp = wcd->n_codes; 96 | stream[8] = temp&0xFF; 97 | stream[9] = (temp>>8)&0xFF; 98 | 99 | if (wcd->n_codes > 0) 100 | { 101 | int i; 102 | unsigned char* ptr_codes = stream + MEL_WCD_SUBHEADER_SIZE; 103 | unsigned char* ptr_names; 104 | 105 | for (i = 0; i < wcd->n_codes; i++) 106 | { 107 | unsigned int temp1; 108 | int temp2; 109 | int temp3; 110 | 111 | temp1 = wcd->codes[i].item.dtype; 112 | ptr_codes[0] = temp1&0xFF; 113 | ptr_codes[1] = (temp1>>8)&0xFF; 114 | 115 | temp2 = wcd->codes[i].item.index; 116 | ptr_codes[2] = temp2&0xFF; 117 | ptr_codes[3] = (temp2>>8)&0xFF; 118 | ptr_codes[4] = (temp2>>16)&0xFF; 119 | ptr_codes[5] = (temp2>>24)&0xFF; 120 | 121 | temp3 = wcd->codes[i].count; 122 | ptr_codes[6] = temp3&0xFF; 123 | ptr_codes[7] = (temp3>>8)&0xFF; 124 | ptr_codes[8] = (temp3>>16)&0xFF; 125 | ptr_codes[9] = (temp3>>24)&0xFF; 126 | 127 | ptr_codes += MEL_WCD_CODE_SIZE; 128 | } 129 | ptr_names = ptr_codes; 130 | for (i = 0; i < wcd->n_names; i++) 131 | { 132 | memcpy(ptr_names,wcd->names[i].raw,MEL_WCD_DEVICENAME_MAX_BYTES); 133 | ptr_names += MEL_WCD_DEVICENAME_MAX_BYTES; 134 | } 135 | 136 | done_size = MEL_WCD_SUBHEADER_SIZE 137 | + wcd->n_codes*MEL_WCD_CODE_SIZE 138 | + wcd->n_names*MEL_WCD_DEVICENAME_MAX_BYTES; 139 | } 140 | } 141 | 142 | return(done_size); 143 | } 144 | 145 | /* destroy wcd instance */ 146 | void mel_wcd_FXCPU_FX3U_free(void* wcdx) 147 | { 148 | WCD_FXCPU_FX3U* wcd = (WCD_FXCPU_FX3U*)wcdx; 149 | 150 | if (wcd) 151 | { 152 | if (wcd->codes) 153 | { 154 | free(wcd->codes); 155 | } 156 | 157 | if (wcd->names) 158 | { 159 | free(wcd->names); 160 | } 161 | 162 | free(wcd); 163 | } 164 | 165 | return; 166 | } -------------------------------------------------------------------------------- /mel_wcd_fxcpu_fx3.h: -------------------------------------------------------------------------------- 1 | #ifndef __mel_wcd_fxcpu_fx3u_h__ 2 | #define __mel_wcd_fxcpu_fx3u_h__ 3 | 4 | #include "mel_common.h" 5 | #include "mel_wpg_device.h" 6 | 7 | #define MEL_WCD_SUBHEADER_SIZE 10 8 | #define MEL_WCD_CODE_SIZE 10 9 | 10 | typedef struct tagWCD_FX3U_DevRange{ 11 | 12 | PLCRegDevice item; 13 | int count; 14 | 15 | }WCD_FX3U_DevRange; 16 | 17 | typedef struct tagWCD_FX3U_DevName{ 18 | 19 | #define MEL_WCD_DEVICENAME_MAX_BYTES (40) 20 | unsigned char raw[MEL_WCD_DEVICENAME_MAX_BYTES+1]; 21 | 22 | }WCD_FX3U_DevName; 23 | 24 | ////////////////////////////////////////////////////////////////////////// 25 | //EXPORT DATA STRUCTURE 26 | typedef struct tagWCD_FXCPU_FX3U{ 27 | 28 | int n_codes; 29 | int n_names; 30 | 31 | WCD_FX3U_DevRange* codes; 32 | WCD_FX3U_DevName* names; 33 | 34 | }WCD_FXCPU_FX3U; 35 | ////////////////////////////////////////////////////////////////////////// 36 | 37 | /* returns: done stream size > 0, error =0. */ 38 | int mel_wcd_FXCPU_FX3_decoder(unsigned char* stream,int enc_size,void* wcdx); 39 | /* returns: done stream size > 0, error =0. */ 40 | int mel_wcd_FXCPU_FX3_encoder(void* wcdx,unsigned char* stream); 41 | /* destroy wcd instance */ 42 | void mel_wcd_FXCPU_FX3U_free(void* wcdx); 43 | 44 | #endif /* __mel_wcd_fxcpu_fx3u_h__ */ 45 | -------------------------------------------------------------------------------- /mel_wpa.c: -------------------------------------------------------------------------------- 1 | #include "mel_wpa.h" 2 | 3 | #include //calloc 4 | #include //memset 5 | 6 | static unsigned char WPA_HEADER[WPA_HEADER_SIZE_BYTES] = 7 | { 8 | 0x40,0x00,0x22,0x01,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 9 | 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 10 | 11 | 0x20,0x20,0x20,0x20,0x04,0x02,0x08,0x02, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 12 | /* [type,series] */ 13 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF 14 | }; 15 | 16 | static int mel_enc_wpa_header (int cpuSeries,int cpuType,unsigned char* stream); 17 | 18 | /* returns: pointer to allocated (by malloc()) WPA_x structure; in case of failure: =0. */ 19 | void* mel_wpa_dec(unsigned char* stream,int enc_size,int* pcpuSeries,int* pcpuType,MELTools* tools) 20 | { 21 | void *wpa = 0; 22 | //set initially as unknown 23 | *pcpuSeries = MEL_PLC_SERIES_NULL; 24 | *pcpuType = MEL_PLC_TYPE_NULL; 25 | //check for too short streams 26 | if (enc_size > 0x40) 27 | { 28 | int hdr_length = (int)stream[0]|((int)stream[1]<<8); 29 | 30 | //0. check header 31 | if (hdr_length == WPA_HEADER_SIZE_BYTES) 32 | { 33 | int cpuSeries; 34 | int cpuType; 35 | unsigned char cpuTypeCode; 36 | 37 | //1. decode CPU Series & Type 38 | cpuTypeCode = stream[WPA_CPU_TYPE_OFFSET]; 39 | cpuSeries = stream[WPA_CPU_SERIES_OFFSET]; 40 | 41 | if (cpuSeries == MEL_PLC_SERIES_FXCPU) 42 | { 43 | cpuType = FXCPU_TYPES_by_code[cpuTypeCode]; 44 | } 45 | else 46 | { 47 | cpuType = cpuTypeCode; 48 | } 49 | 50 | *pcpuSeries = cpuSeries; 51 | *pcpuType = cpuType; 52 | 53 | //2. allocate appropriate WPA_x struct 54 | wpa = mel_wpa_allocate(cpuSeries,cpuType,tools); 55 | if (wpa) 56 | { 57 | int done_size; 58 | //3. decode all fields of WPA_x 59 | done_size = tools->wpa_decoder( stream +hdr_length, 60 | enc_size-hdr_length, 61 | wpa); 62 | //printf("done: %d\n",done_size); 63 | if (done_size != enc_size-hdr_length) 64 | { 65 | //error has happened during decoding: destroy wpa 66 | tools->wpa_destroy(wpa); 67 | wpa = 0; 68 | } 69 | //else{/* successfully done */} 70 | } 71 | //else{/* unknown CPU */} 72 | } 73 | //else{/* wrong encoded value of header's size */} 74 | } 75 | //else{/* stream is too short */} 76 | 77 | return(wpa); 78 | } 79 | /* returns: encoded size >0, failure: =0. */ 80 | int mel_wpa_enc(int cpuSeries,int cpuType,void* wpa,unsigned char* stream,MELTools* tools) 81 | { 82 | int enc_size = 0; 83 | 84 | if (wpa) 85 | { 86 | //if(mel_set_wpa_toolbox(cpuSeries,cpuType,&toolbox)) 87 | { 88 | int hdr_length; 89 | //encode header 90 | hdr_length = mel_enc_wpa_header(cpuSeries,cpuType,stream); 91 | //encode rest of file 92 | enc_size = tools->wpa_encoder(wpa,stream + hdr_length); 93 | if (enc_size > 0) 94 | { 95 | enc_size += hdr_length; 96 | } 97 | } 98 | } 99 | 100 | return(enc_size); 101 | } 102 | 103 | static void* mel_wpa_allocate(int cpuSeries,int cpuType,MELTools* tools) 104 | { 105 | void* wpa = 0; 106 | 107 | if(mel_get_toolbox(cpuSeries,cpuType,tools)) 108 | { 109 | wpa = calloc(1,tools->sizeof_wpax); 110 | } 111 | 112 | return(wpa); 113 | } 114 | 115 | void mel_wpa_free (MELTools* tools,void* wpa) 116 | { 117 | if(tools) if(tools->wpa_destroy) if(wpa) tools->wpa_destroy(wpa); 118 | return; 119 | } 120 | 121 | static int mel_enc_wpa_header (int cpuSeries,int cpuType,unsigned char* stream) 122 | { 123 | unsigned char cpuTypeCode; 124 | 125 | //copy all 126 | memcpy(stream,WPA_HEADER,WPA_HEADER_SIZE_BYTES); 127 | //tune CPU type & series 128 | 129 | if (cpuSeries == MEL_PLC_SERIES_FXCPU) 130 | { 131 | cpuTypeCode = FXCPU_TYPE_CODES_by_type[cpuType]; 132 | } 133 | else 134 | { 135 | cpuTypeCode = cpuType&0xFF; 136 | } 137 | 138 | 139 | stream[WPA_CPU_TYPE_OFFSET] = cpuTypeCode; 140 | stream[WPA_CPU_SERIES_OFFSET] = cpuSeries &0xFF; 141 | 142 | return(WPA_HEADER_SIZE_BYTES); 143 | } -------------------------------------------------------------------------------- /mel_wpa.h: -------------------------------------------------------------------------------- 1 | #ifndef __mel_wpa_h__ 2 | #define __mel_wpa_h__ 3 | 4 | #include "mel_wpa_fxcpu_fx3.h" 5 | 6 | /* 7 | returns: pointer to allocated (by malloc()) WPA_x structure; in case of failure: =0. 8 | Also, it calls internally mel_wpa_get_toolbox() to setup "tools" properly; 9 | */ 10 | void* mel_wpa_allocate (int cpuSeries,int cpuType,MELTools* tools); 11 | void mel_wpa_free (MELTools* tools,void* wpa); 12 | 13 | /* returns: pointer to allocated (by malloc()) WPA_x structure; in case of failure: =0. */ 14 | void* mel_wpa_dec (unsigned char* stream,int enc_size,int* pcpuSeries,int* pcpuType,MELTools* tools); 15 | 16 | /* returns: encoded size >0, failure: =0. */ 17 | int mel_wpa_enc (int cpuSeries,int cpuType,void* wpa,unsigned char* stream,MELTools* tools); 18 | 19 | #endif //__mel_wpa_h__ 20 | -------------------------------------------------------------------------------- /mel_wpa_fxcpu_fx3.c: -------------------------------------------------------------------------------- 1 | #include "mel_wpa.h" 2 | #include //memset 3 | #include //free 4 | 5 | #define WPA_CODE_FXCPU_FX3U_FREG_CAPACITY 0x0011 6 | #define WPA_CODE_FXCPU_FX3U_ADDS_CAPACITY 0xE7FF 7 | #define WPA_CODE_FXCPU_FX3U_UNKNOWN1 0xE4FF 8 | #define WPA_CODE_FXCPU_FX3U_PLCSYSTEM1 0xEAFF 9 | #define WPA_CODE_FXCPU_FX3U_PLCSYSTEM2_CH1 0xEBFF 10 | #define WPA_CODE_FXCPU_FX3U_PLCSYSTEM2_CH2 0xECFF 11 | #define WPA_CODE_FXCPU_FX3U_UNKNOWN2 0xEDFF 12 | #define WPA_CODE_FXCPU_FX3U_POSITIONING 0xEEFF 13 | #define WPA_CODE_FXCPU_FX3U_IOASSIGMENT 0x0040 14 | #define WPA_CODE_FXCPU_FX3U_BCC 0xEFFF 15 | 16 | static int mel_wpa_FXCPU_FX3U_segment_decoder(int segcode,int segsize,unsigned char* segment,WPA_FXCPU_FX3U* wpa); 17 | static int mel_wpa_FXCPU_FX3U_segment_encoder(int* psegcode,WPA_FXCPU_FX3U* wpa,unsigned char* segment); 18 | 19 | int mel_wpa_FXCPU_FX3_decoder(unsigned char* stream,int enc_size,void* wpax) 20 | { 21 | int done_size = 0; 22 | WPA_FXCPU_FX3U* wpa = (WPA_FXCPU_FX3U*)wpax; 23 | int goon = 1; 24 | 25 | while(goon && done_size + 2 <= enc_size) 26 | { 27 | unsigned char* segment; 28 | int code; 29 | 30 | segment = stream + done_size; 31 | code = (int)stream[done_size+0]|((int)stream[done_size+1]<<8); 32 | 33 | //printf("code: %04X\t",code); 34 | 35 | done_size += 2; 36 | 37 | switch (code) 38 | { 39 | case WPA_CODE_EOF: 40 | done_size = enc_size;//successfully done 41 | goon = 0;//exit from loop 42 | break; 43 | 44 | default://treat code as a length of segment 45 | { 46 | int segsize = code; 47 | 48 | //printf("size: %4d\t",segsize); 49 | 50 | if (segsize >= 4 && done_size - 2 + segsize <= enc_size) 51 | { 52 | int segsize_done; 53 | 54 | code = (int)stream[done_size+1]|((int)stream[done_size+0]<<8); 55 | 56 | //printf("\t%04X\n",code); 57 | 58 | segsize_done = mel_wpa_FXCPU_FX3U_segment_decoder(code,segsize,segment,wpa); 59 | /* 60 | if (segsize_done != segsize) 61 | { 62 | done_size = -segsize + 2;// -segsize + segsize = 0; (error) 63 | goon = 0;//exit from loop 64 | } 65 | */ 66 | #if 0 67 | if (segsize_done != segsize) 68 | { 69 | int i; 70 | printf("\tunknown segment!\n\t\t\t"); 71 | 72 | for (i = 0; i < segsize; i++) 73 | { 74 | printf("%02X ",segment[i]); 75 | } 76 | printf("\n"); 77 | } 78 | #endif 79 | } 80 | //step over done segment 81 | done_size += segsize - 2; 82 | } 83 | } 84 | }; 85 | 86 | return(done_size); 87 | } 88 | 89 | static int mel_wpa_FXCPU_FX3U_segment_decoder(int segcode,int segsize,unsigned char* segment,WPA_FXCPU_FX3U* wpa) 90 | { 91 | int encsize = segsize;//Ok by default 92 | 93 | switch (segcode) 94 | { 95 | case WPA_CODE_MEMORY_CAPACITY: 96 | //Memory capacity in steps; encoded in thousands 97 | wpa->page1.mem_capacity_in_steps = ((int)segment[4]|((int)segment[5]<<8))*1000; 98 | break; 99 | 100 | case WPA_CODE_CMNT_CAPACITY: 101 | //Comments capacity in blocks (0 to (Mem.capacity/500) - 1); 1 block = 50 points; 102 | wpa->page1.cmt_capacity_in_blocks = (int)segment[4]|((int)segment[5]<<8); 103 | break; 104 | 105 | case WPA_CODE_FXCPU_FX3U_FREG_CAPACITY: 106 | /* 107 | Mem.capacity FileRegMaxBlocks 108 | 2000 3 109 | 4000 7 110 | 8000 14 111 | 16000 14 112 | 32000 14 113 | 64000 14 114 | */ 115 | wpa->page1.freg_capacity_in_blocks = (int)segment[16]|((int)segment[17]<<8); 116 | break; 117 | 118 | case WPA_CODE_FXCPU_FX3U_ADDS_CAPACITY: 119 | { 120 | int adds_in_blocks = (int)segment[6]|((int)segment[7]<<8); 121 | 122 | wpa->page1.BCC_in_blocks = adds_in_blocks & 1; 123 | adds_in_blocks -= wpa->page1.BCC_in_blocks; 124 | 125 | if (adds_in_blocks >= 18) 126 | { 127 | wpa->page1.PIS_in_blocks = 18;//PIS in blocks (0=no or 18=yes) 128 | } 129 | else 130 | { 131 | wpa->page1.PIS_in_blocks = 0;//PIS in blocks (0=no or 18=yes) 132 | } 133 | adds_in_blocks -= wpa->page1.PIS_in_blocks; 134 | 135 | wpa->page1.SFBS_in_blocks = (adds_in_blocks == 8)? 8:0; 136 | 137 | } 138 | break; 139 | 140 | case WPA_CODE_DEVICES: 141 | wpa->page2.n_editable_items = (int)segment[4]|((int)segment[5]<<8); 142 | { 143 | int i; 144 | for (i = 0; i < wpa->page2.n_editable_items && i < WPA_FX3U_MAX_EDITABLE_ITEMS; i++) 145 | { 146 | wpa->page2.editable_items[i].device_code = (int)segment[6*i+6+0]|((int)segment[6*i+6+1]<<8); 147 | wpa->page2.editable_items[i].latched_length = (int)segment[6*i+6+2]|((int)segment[6*i+6+3]<<8); 148 | wpa->page2.editable_items[i].latched_start = (int)segment[6*i+6+4]|((int)segment[6*i+6+5]<<8); 149 | } 150 | } 151 | break; 152 | 153 | case WPA_CODE_PLCNAME: 154 | //ASCII name of PLC (max: 32 bytes); by default: 33 0x20 + ending null 0x00 = 34 bytes totally 155 | memcpy(wpa->page3.raw,segment+4,WPA_FX3U_PLCNAME_MAX_BYTES+2); 156 | break; 157 | 158 | case WPA_CODE_FXCPU_FX3U_IOASSIGMENT: 159 | wpa->page4.input_Totally = (int)segment[12]|((int)segment[13]<<8); 160 | wpa->page4.input_Start_offset = (int)segment[14]|((int)segment[15]<<8); 161 | wpa->page4.output_Totally = (int)segment[34]|((int)segment[35]<<8); 162 | wpa->page4.input_Start_offset = (int)segment[36]|((int)segment[37]<<8); 163 | break; 164 | 165 | case WPA_CODE_FXCPU_FX3U_PLCSYSTEM1: 166 | wpa->page5.is_battery_less_drive_mode = segment[4]; 167 | wpa->page5.modem = segment[5]; 168 | wpa->page5.terminal = ((int)segment[6]<<8)|(int)segment[7]; 169 | break; 170 | 171 | case WPA_CODE_FXCPU_FX3U_PLCSYSTEM2_CH1: 172 | wpa->page6.ch1.protocol = segment[4]; 173 | wpa->page6.ch1.databits = segment[5]; 174 | wpa->page6.ch1.parity = segment[6]; 175 | wpa->page6.ch1.stopbits = segment[7]; 176 | wpa->page6.ch1.baudrate = segment[8]; 177 | wpa->page6.ch1.is_header_on = segment[9]; 178 | wpa->page6.ch1.is_terminator_on = segment[10]; 179 | wpa->page6.ch1.is_control_line_on = segment[11]; 180 | { 181 | int hw_type = ((int)segment[12]<<8)|(segment[13]); 182 | switch(hw_type) 183 | { 184 | case 0x0000: 185 | wpa->page6.ch1.hw_type = WPA_FX3U_PLCSYSTEM2_CNTRLINE_RegularRS232C; 186 | break; 187 | case 0x0101: 188 | wpa->page6.ch1.hw_type = WPA_FX3U_PLCSYSTEM2_CNTRLINE_RS485; 189 | break; 190 | case 0x0100: 191 | if(wpa->page6.ch1.is_control_line_on==0) 192 | { 193 | wpa->page6.ch1.hw_type = WPA_FX3U_PLCSYSTEM2_CNTRLINE_InterLinkRS232C; 194 | } 195 | else 196 | { 197 | wpa->page6.ch1.hw_type = WPA_FX3U_PLCSYSTEM2_CNTRLINE_ModemRS232C; 198 | } 199 | } 200 | } 201 | wpa->page6.ch1.is_sum_check_on = segment[14]; 202 | wpa->page6.ch1.transmission_cntrl = segment[15]; 203 | wpa->page6.ch1.station_number = segment[16]; 204 | wpa->page6.ch1.timeout_judge_time_x10ms = segment[17]; 205 | wpa->page6.ch1.is_enabled = (wpa->page6.ch1.baudrate!=WPA_FX3U_PLCSYSTEM2_BAUDRATE_CH_DESABLED)? 1:0; 206 | break; 207 | 208 | case WPA_CODE_FXCPU_FX3U_PLCSYSTEM2_CH2: 209 | //Channel index = 1 {segment[4] = 0x01; segment[5] = 0x00;} 210 | wpa->page6.ch2.protocol = segment[6]; 211 | wpa->page6.ch2.databits = segment[7]; 212 | wpa->page6.ch2.parity = segment[8]; 213 | wpa->page6.ch2.stopbits = segment[9]; 214 | wpa->page6.ch2.baudrate = segment[10]; 215 | wpa->page6.ch2.is_header_on = segment[11]; 216 | wpa->page6.ch2.is_terminator_on = segment[12]; 217 | wpa->page6.ch2.is_control_line_on = segment[13]; 218 | { 219 | int hw_type = ((int)segment[14]<<8)|(int)segment[15]; 220 | switch(hw_type) 221 | { 222 | case 0x0000: 223 | wpa->page6.ch2.hw_type = WPA_FX3U_PLCSYSTEM2_CNTRLINE_RegularRS232C; 224 | break; 225 | case 0x0101: 226 | wpa->page6.ch2.hw_type = WPA_FX3U_PLCSYSTEM2_CNTRLINE_RS485; 227 | break; 228 | case 0x0100: 229 | if(wpa->page6.ch2.is_control_line_on==0) 230 | { 231 | wpa->page6.ch2.hw_type = WPA_FX3U_PLCSYSTEM2_CNTRLINE_InterLinkRS232C; 232 | } 233 | else 234 | { 235 | wpa->page6.ch2.hw_type = WPA_FX3U_PLCSYSTEM2_CNTRLINE_ModemRS232C; 236 | } 237 | } 238 | } 239 | wpa->page6.ch2.is_sum_check_on = segment[16]; 240 | wpa->page6.ch2.transmission_cntrl = segment[17]; 241 | wpa->page6.ch2.station_number = segment[18]; 242 | wpa->page6.ch2.timeout_judge_time_x10ms = (int)segment[19]|((int)segment[20]<<8); 243 | //segment[21] = 0x00; 244 | wpa->page6.ch2.is_enabled = (wpa->page6.ch2.baudrate!=WPA_FX3U_PLCSYSTEM2_BAUDRATE_CH_DESABLED)? 1:0; 245 | break; 246 | 247 | case WPA_CODE_FXCPU_FX3U_POSITIONING: 248 | if (segsize > 4) 249 | { 250 | int i; 251 | int first_tab = 4; 252 | 253 | for (i = 0; i < WPA_FX3U_POS_YTABS_COUNT; i++) 254 | { 255 | int j; 256 | int i_tab = 4 + i*(28+WPA_FX3U_POS_INSTR_COUNT*10); 257 | int first_instr; 258 | 259 | wpa->page7.indivs.ytabs[i].BiasSpeed_Hz = (int)segment[i_tab+0]|((int)segment[i_tab+1]<<8); 260 | wpa->page7.indivs.ytabs[i].MaxSpeed_Hz = (int)segment[i_tab+2]|((int)segment[i_tab+3]<<8)|((int)segment[i_tab+4]<<16)|((int)segment[i_tab+5]<<24); 261 | wpa->page7.indivs.ytabs[i].CreepSpeed_Hz = (int)segment[i_tab+6]|((int)segment[i_tab+7]<<8); 262 | wpa->page7.indivs.ytabs[i].ZeroReturnSpeed_Hz = (int)segment[i_tab+8]|((int)segment[i_tab+9]<<8)|((int)segment[i_tab+10]<<16)|((int)segment[i_tab+11]<<24); 263 | wpa->page7.indivs.ytabs[i].AccelerationTime_ms = (int)segment[i_tab+12]|((int)segment[i_tab+13]<<8); 264 | wpa->page7.indivs.ytabs[i].DecelerationTime_ms = (int)segment[i_tab+14]|((int)segment[i_tab+15]<<8); 265 | wpa->page7.indivs.ytabs[i].InterrInputSource = (int)segment[i_tab+16]|((int)segment[i_tab+17]<<8); 266 | wpa->page7.indivs.ytabs[i].dont_init_postable = (int)segment[i_tab+18]|((int)segment[i_tab+19]<<8); 267 | wpa->page7.indivs.ytabs[i].head_address.dtype = (unsigned int)segment[i_tab+20]|((unsigned int)segment[i_tab+21]<<8); 268 | wpa->page7.indivs.ytabs[i].head_address.index = (int)segment[i_tab+22]|((int)segment[i_tab+23]<<8); 269 | wpa->page7.indivs.ytabs[i].rotation_dir_signal.dtype = (unsigned int)segment[i_tab+24]|((unsigned int)segment[i_tab+25]<<8); 270 | wpa->page7.indivs.ytabs[i].rotation_dir_signal.index= (int)segment[i_tab+26]|((int)segment[i_tab+27]<<8); 271 | 272 | first_instr = i_tab + 28; 273 | 274 | for (j = 0; j < WPA_FX3U_POS_INSTR_COUNT; j++) 275 | { 276 | int j_instr = first_instr + 10*j; 277 | 278 | wpa->page7.indivs.ytabs[i].instructions[j].type = (int)segment[j_instr + 0]|((int)segment[j_instr + 1]<<8); 279 | wpa->page7.indivs.ytabs[i].instructions[j].pulse = (int)segment[j_instr + 2]|((int)segment[j_instr + 3]<<8)|((int)segment[j_instr + 4]<<16)|((int)segment[j_instr + 5]<<24); 280 | wpa->page7.indivs.ytabs[i].instructions[j].freq_Hz = (int)segment[j_instr + 6]|((int)segment[j_instr + 7]<<8)|((int)segment[j_instr + 8]<<16)|((int)segment[j_instr + 9]<<24); 281 | } 282 | } 283 | } 284 | //else{/* empty segment */} 285 | break; 286 | 287 | case WPA_CODE_FXCPU_FX3U_BCC: 288 | wpa->page8.baudrate = segment[4]; 289 | wpa->page8.point_mode = segment[5]; 290 | /* segment[6] = 0x00; */ 291 | /* segment[7] = 0x01; */ 292 | { 293 | int i; 294 | 295 | for (i = 0; i < WPA_FX3U_STATIONS_COUNT; i++) 296 | { 297 | wpa->page8.stations[i].type = segment[8+i*4+0]; 298 | wpa->page8.stations[i].iopoints = segment[8+i*4+1]; 299 | wpa->page8.stations[i].is_reserve_st = segment[8+i*4+2]; 300 | /* segment[8+i*4+3] = 0x01 */ 301 | } 302 | } 303 | break; 304 | 305 | case WPA_CODE_FXCPU_FX3U_UNKNOWN1: 306 | //0C 00 [E4 FF] {20 20 20 20 20 20 20 20} 307 | case WPA_CODE_FXCPU_FX3U_UNKNOWN2: 308 | //26 00 [ED FF] [08 00] {04 00 00 00, 04 00 00 00, 04 00 00 00, 04 00 00 00, 04 00 00 00, 04 00 00 00, 04 00 00 00, 04 00 00 00} 309 | default: 310 | encsize = 0; 311 | } 312 | 313 | return(encsize); 314 | } 315 | 316 | int mel_wpa_FXCPU_FX3_encoder(void* wpax,unsigned char* stream) 317 | { 318 | int done_size = 0; 319 | WPA_FXCPU_FX3U* wpa = (WPA_FXCPU_FX3U*)wpax; 320 | int segcode; 321 | int goon = 1; 322 | 323 | /* 324 | size: 6 E0FF 325 | size: 6 16FF 326 | size: 18 0011 327 | size: 8 E7FF 328 | size: 36 0120 329 | size: 38 0100 330 | size: 12 E4FF 331 | unknown segment! 332 | size: 8 EAFF 333 | size: 18 EBFF 334 | size: 22 ECFF 335 | size: 38 EDFF 336 | unknown segment! 337 | size: 4116 EEFF 338 | size: 264 EFFF 339 | size: 54 0040 340 | */ 341 | 342 | segcode = WPA_CODE_MEMORY_CAPACITY; 343 | 344 | do 345 | { 346 | unsigned char* segment = stream + done_size; 347 | 348 | switch (segcode) 349 | { 350 | case WPA_CODE_EOF: 351 | //encode ending code 352 | segment[0] = (WPA_CODE_EOF>>8)&0xFF; 353 | segment[1] = WPA_CODE_EOF&0xFF; 354 | done_size += 2; 355 | //and exit from loop gracefully 356 | goon = 0; 357 | break; 358 | 359 | default: 360 | { 361 | int segsize; 362 | 363 | segsize = mel_wpa_FXCPU_FX3U_segment_encoder(&segcode,wpa,segment); 364 | done_size += segsize; 365 | } 366 | break; 367 | } 368 | 369 | } while (goon); 370 | 371 | return(done_size); 372 | } 373 | 374 | static int mel_wpa_FXCPU_FX3U_segment_encoder(int* psegcode,WPA_FXCPU_FX3U* wpa,unsigned char* segment) 375 | { 376 | int segsize = 0; 377 | int segcode = *psegcode; 378 | int nextcode = WPA_CODE_EOF; 379 | 380 | switch(segcode) 381 | { 382 | case WPA_CODE_MEMORY_CAPACITY: 383 | segsize = 6; 384 | { 385 | int temp = wpa->page1.mem_capacity_in_steps/1000; 386 | 387 | //Memory capacity in steps; encoded as 16-bit = in thousands 388 | segment[4] = temp&0xFF; 389 | segment[5] = (temp>>8)&0xFF; 390 | } 391 | nextcode = WPA_CODE_CMNT_CAPACITY; 392 | break; 393 | 394 | case WPA_CODE_CMNT_CAPACITY: 395 | segsize = 6; 396 | { 397 | int temp = wpa->page1.cmt_capacity_in_blocks; 398 | //Comments capacity in blocks (0 to (Mem.capacity/500) - 1); 1 block = 50 points; 399 | segment[4] = temp&0xFF; 400 | segment[5] = (temp>>8)&0xFF; 401 | } 402 | nextcode = WPA_CODE_FXCPU_FX3U_FREG_CAPACITY; 403 | break; 404 | 405 | case WPA_CODE_FXCPU_FX3U_FREG_CAPACITY: 406 | segsize = 18; 407 | { 408 | int temp = wpa->page1.freg_capacity_in_blocks; 409 | 410 | memset(segment+4,0x00,segsize-4-2); 411 | segment[16] = temp&0xFF; 412 | segment[17] = (temp>>8)&0xFF; 413 | } 414 | nextcode = WPA_CODE_FXCPU_FX3U_ADDS_CAPACITY; 415 | break; 416 | 417 | case WPA_CODE_FXCPU_FX3U_ADDS_CAPACITY: 418 | segsize = 8; 419 | { 420 | int temp; 421 | 422 | temp = wpa->page1.BCC_in_blocks 423 | + wpa->page1.PIS_in_blocks 424 | + wpa->page1.SFBS_in_blocks; 425 | 426 | segment[4] = 0x00; 427 | segment[5] = 0x00; 428 | segment[6] = temp&0xFF; 429 | segment[7] = (temp>>8)&0xFF; 430 | } 431 | nextcode = WPA_CODE_DEVICES; 432 | break; 433 | 434 | case WPA_CODE_DEVICES: 435 | segsize = 36; 436 | { 437 | int temp = wpa->page2.n_editable_items; 438 | int i; 439 | 440 | segment[4] = temp&0xFF; 441 | segment[5] = (temp>>8)&0xFF; 442 | 443 | for (i = 0; i < wpa->page2.n_editable_items && i < WPA_FX3U_MAX_EDITABLE_ITEMS; i++) 444 | { 445 | int temp1; 446 | int temp2; 447 | int temp3; 448 | 449 | temp1 = wpa->page2.editable_items[i].device_code; 450 | segment[6*i+6+0] = temp1&0xFF; 451 | segment[6*i+6+1] = (temp1>>8)&0xFF; 452 | 453 | temp2 = wpa->page2.editable_items[i].latched_length; 454 | segment[6*i+6+2] = temp2&0xFF; 455 | segment[6*i+6+3] = (temp2>>8)&0xFF; 456 | 457 | temp3 = wpa->page2.editable_items[i].latched_start; 458 | segment[6*i+6+4] = temp3&0xFF; 459 | segment[6*i+6+5] = (temp3>>8)&0xFF;; 460 | } 461 | } 462 | nextcode = WPA_CODE_PLCNAME; 463 | break; 464 | 465 | case WPA_CODE_PLCNAME: 466 | segsize = 38; 467 | //ASCII name of PLC (max: 32 bytes); by default: 33 0x20 + ending null 0x00 = 34 bytes totally 468 | memcpy(segment+4,wpa->page3.raw,WPA_FX3U_PLCNAME_MAX_BYTES+2); 469 | nextcode = WPA_CODE_FXCPU_FX3U_UNKNOWN1; 470 | break; 471 | 472 | case WPA_CODE_FXCPU_FX3U_UNKNOWN1: 473 | segsize = 12; 474 | //0C 00 [E4 FF] {20 20 20 20 20 20 20 20} 475 | memset(segment+4,0x20,segsize-4); 476 | nextcode = WPA_CODE_FXCPU_FX3U_PLCSYSTEM1; 477 | break; 478 | 479 | case WPA_CODE_FXCPU_FX3U_PLCSYSTEM1: 480 | segsize = 8; 481 | segment[4] = wpa->page5.is_battery_less_drive_mode; 482 | segment[5] = wpa->page5.modem; 483 | { 484 | int temp = wpa->page5.terminal; 485 | segment[6] = temp&0xFF; 486 | segment[7] = (temp>>8)&0xFF; 487 | } 488 | nextcode = WPA_CODE_FXCPU_FX3U_PLCSYSTEM2_CH1; 489 | break; 490 | 491 | case WPA_CODE_FXCPU_FX3U_PLCSYSTEM2_CH1: 492 | segsize = 18; 493 | 494 | if (wpa->page6.ch1.is_enabled) 495 | { 496 | segment[4] = wpa->page6.ch1.protocol; 497 | segment[5] = wpa->page6.ch1.databits; 498 | segment[6] = wpa->page6.ch1.parity; 499 | segment[7] = wpa->page6.ch1.stopbits; 500 | segment[8] = wpa->page6.ch1.baudrate; 501 | segment[9] = wpa->page6.ch1.is_header_on; 502 | segment[10] = wpa->page6.ch1.is_terminator_on; 503 | segment[11] = wpa->page6.ch1.is_control_line_on; 504 | { 505 | int temp = 0; 506 | switch(wpa->page6.ch1.hw_type) 507 | { 508 | case WPA_FX3U_PLCSYSTEM2_CNTRLINE_RegularRS232C: 509 | //0x0000 510 | break; 511 | case WPA_FX3U_PLCSYSTEM2_CNTRLINE_RS485: 512 | temp = 0x0101; 513 | break; 514 | case WPA_FX3U_PLCSYSTEM2_CNTRLINE_InterLinkRS232C: 515 | case WPA_FX3U_PLCSYSTEM2_CNTRLINE_ModemRS232C: 516 | temp = 0x0100; 517 | break; 518 | } 519 | segment[12] = (temp>>8)&0xFF; 520 | segment[13] = temp&0xFF; 521 | } 522 | segment[14] = wpa->page6.ch1.is_sum_check_on; 523 | segment[15] = wpa->page6.ch1.transmission_cntrl; 524 | segment[16] = wpa->page6.ch1.station_number; 525 | segment[17] = wpa->page6.ch1.timeout_judge_time_x10ms; 526 | } 527 | else 528 | { 529 | memset(segment+4,0x00,segsize-4); 530 | } 531 | 532 | nextcode = WPA_CODE_FXCPU_FX3U_PLCSYSTEM2_CH2; 533 | break; 534 | 535 | case WPA_CODE_FXCPU_FX3U_PLCSYSTEM2_CH2: 536 | segsize = 22; 537 | 538 | //Channel index = 1 539 | segment[4] = 0x01; segment[5] = 0x00; 540 | 541 | if(wpa->page6.ch2.is_enabled) 542 | { 543 | segment[6] = wpa->page6.ch2.protocol; 544 | segment[7] = wpa->page6.ch2.databits; 545 | segment[8] = wpa->page6.ch2.parity; 546 | segment[9] = wpa->page6.ch2.stopbits; 547 | segment[10] = wpa->page6.ch2.baudrate; 548 | segment[11] = wpa->page6.ch2.is_header_on; 549 | segment[12] = wpa->page6.ch2.is_terminator_on; 550 | segment[13] = wpa->page6.ch2.is_control_line_on; 551 | { 552 | int temp = 0; 553 | switch(wpa->page6.ch2.hw_type) 554 | { 555 | case WPA_FX3U_PLCSYSTEM2_CNTRLINE_RegularRS232C: 556 | //0x0000 557 | break; 558 | case WPA_FX3U_PLCSYSTEM2_CNTRLINE_RS485: 559 | temp = 0x0101; 560 | break; 561 | case WPA_FX3U_PLCSYSTEM2_CNTRLINE_InterLinkRS232C: 562 | case WPA_FX3U_PLCSYSTEM2_CNTRLINE_ModemRS232C: 563 | temp = 0x0100; 564 | break; 565 | } 566 | segment[14] = (temp>>8)&0xFF; 567 | segment[15] = temp&0xFF; 568 | } 569 | segment[16] = wpa->page6.ch2.is_sum_check_on; 570 | segment[17] = wpa->page6.ch2.transmission_cntrl; 571 | segment[18] = wpa->page6.ch2.station_number; 572 | { 573 | int temp = wpa->page6.ch2.timeout_judge_time_x10ms; 574 | segment[19] = temp&0xFF; 575 | segment[20] = (temp>>8)&0xFF; 576 | } 577 | segment[21] = 0x00; 578 | } 579 | else 580 | { 581 | memset(segment+6,0x00,segsize-6); 582 | } 583 | nextcode = WPA_CODE_FXCPU_FX3U_UNKNOWN2; 584 | break; 585 | 586 | case WPA_CODE_FXCPU_FX3U_UNKNOWN2: 587 | //26 00 [ED FF] [08 00] {04 00 00 00, 04 00 00 00, 04 00 00 00, 04 00 00 00, 04 00 00 00, 04 00 00 00, 04 00 00 00, 04 00 00 00} 588 | { 589 | int temp = 8; 590 | int i; 591 | segment[4] = temp&0xFF; 592 | segment[5] = (temp>>8)&0xFF; 593 | memset(segment+6,0x00,4*temp); 594 | for (i = 0; i < temp; i++) 595 | { 596 | segment[6+4*i+0] = 0x04; 597 | } 598 | segsize = 6 + 4*temp; 599 | } 600 | nextcode = WPA_CODE_FXCPU_FX3U_POSITIONING; 601 | break; 602 | 603 | case WPA_CODE_FXCPU_FX3U_POSITIONING: 604 | if (wpa->page1.PIS_in_blocks > 0) 605 | { 606 | int i; 607 | int first_tab = 4; 608 | 609 | segsize = 4116; 610 | 611 | for (i = 0; i < WPA_FX3U_POS_YTABS_COUNT; i++) 612 | { 613 | int j; 614 | int i_tab = 4 + i*(28+WPA_FX3U_POS_INSTR_COUNT*10); 615 | int first_instr; 616 | 617 | int temp1; 618 | int temp2; 619 | int temp3; 620 | int temp4; 621 | unsigned int utemp; 622 | 623 | temp1 = wpa->page7.indivs.ytabs[i].BiasSpeed_Hz; 624 | segment[i_tab+0] = temp1&0xFF; 625 | segment[i_tab+1] = (temp1>>8)&0xFF; 626 | 627 | temp2 = wpa->page7.indivs.ytabs[i].MaxSpeed_Hz; 628 | segment[i_tab+2] = temp2&0xFF; 629 | segment[i_tab+3] = (temp2>>8)&0xFF; 630 | segment[i_tab+4] = (temp2>>16)&0xFF; 631 | segment[i_tab+5] = (temp2>>24)&0xFF; 632 | 633 | temp3 = wpa->page7.indivs.ytabs[i].CreepSpeed_Hz; 634 | segment[i_tab+6] = temp3&0xFF; 635 | segment[i_tab+7] = (temp3>>8)&0xFF; 636 | 637 | temp4 = wpa->page7.indivs.ytabs[i].ZeroReturnSpeed_Hz; 638 | segment[i_tab+8] = temp4&0xFF; 639 | segment[i_tab+9] = (temp4>>8)&0xFF; 640 | segment[i_tab+10] = (temp4>>16)&0xFF; 641 | segment[i_tab+11] = (temp4>>24)&0xFF; 642 | 643 | temp1 = wpa->page7.indivs.ytabs[i].AccelerationTime_ms; 644 | segment[i_tab+12] = temp1&0xFF; 645 | segment[i_tab+13] = (temp1>>8)&0xFF; 646 | 647 | temp2 = wpa->page7.indivs.ytabs[i].DecelerationTime_ms; 648 | segment[i_tab+14] = temp2&0xFF; 649 | segment[i_tab+15] = (temp2>>8)&0xFF; 650 | 651 | temp3 = wpa->page7.indivs.ytabs[i].InterrInputSource; 652 | segment[i_tab+16] = temp3&0xFF; 653 | segment[i_tab+17] = (temp3>>8)&0xFF; 654 | 655 | temp4 = wpa->page7.indivs.ytabs[i].dont_init_postable; 656 | segment[i_tab+18] = temp4&0xFF; 657 | segment[i_tab+19] = (temp4>>8)&0xFF; 658 | 659 | utemp = wpa->page7.indivs.ytabs[i].head_address.dtype; 660 | segment[i_tab+20] = utemp&0xFF; 661 | segment[i_tab+21] = (utemp>>8)&0xFF; 662 | 663 | temp2 = wpa->page7.indivs.ytabs[i].head_address.index; 664 | segment[i_tab+22] = temp2&0xFF; 665 | segment[i_tab+23] = (temp2>>8)&0xFF; 666 | 667 | utemp = wpa->page7.indivs.ytabs[i].rotation_dir_signal.dtype; 668 | segment[i_tab+24] = utemp&0xFF; 669 | segment[i_tab+25] = (utemp>>8)&0xFF; 670 | 671 | temp4 = wpa->page7.indivs.ytabs[i].rotation_dir_signal.index; 672 | segment[i_tab+26] = temp4&0xFF; 673 | segment[i_tab+27] = (temp4>>8)&0xFF; 674 | 675 | first_instr = i_tab + 28; 676 | 677 | for (j = 0; j < WPA_FX3U_POS_INSTR_COUNT; j++) 678 | { 679 | int j_instr = first_instr + 10*j; 680 | 681 | temp1 = wpa->page7.indivs.ytabs[i].instructions[j].type; 682 | segment[j_instr + 0] = temp1&0xFF; 683 | segment[j_instr + 1] = (temp1>>8)&0xFF; 684 | 685 | temp2 = wpa->page7.indivs.ytabs[i].instructions[j].pulse; 686 | segment[j_instr + 2] = temp2&0xFF; 687 | segment[j_instr + 3] = (temp2>>8)&0xFF; 688 | segment[j_instr + 4] = (temp2>>16)&0xFF; 689 | segment[j_instr + 5] = (temp2>>24)&0xFF; 690 | 691 | temp3 = wpa->page7.indivs.ytabs[i].instructions[j].freq_Hz; 692 | segment[j_instr + 6] = temp3&0xFF; 693 | segment[j_instr + 7] = (temp3>>8)&0xFF; 694 | segment[j_instr + 8] = (temp3>>16)&0xFF; 695 | segment[j_instr + 9] = (temp3>>24)&0xFF; 696 | } 697 | } 698 | } 699 | else 700 | { 701 | segsize = 4; 702 | } 703 | 704 | //else{/* empty segment */} 705 | if (wpa->page1.BCC_in_blocks > 0) 706 | { 707 | nextcode = WPA_CODE_FXCPU_FX3U_BCC; 708 | }else 709 | { 710 | nextcode = WPA_CODE_FXCPU_FX3U_IOASSIGMENT; 711 | } 712 | break; 713 | 714 | case WPA_CODE_FXCPU_FX3U_BCC: 715 | segsize = 264; 716 | 717 | segment[4] = wpa->page8.baudrate; 718 | segment[5] = wpa->page8.point_mode; 719 | segment[6] = 0x00; 720 | segment[7] = 0x01; 721 | { 722 | int i; 723 | 724 | for (i = 0; i < WPA_FX3U_STATIONS_COUNT; i++) 725 | { 726 | segment[8+i*4+0] = wpa->page8.stations[i].type; 727 | segment[8+i*4+1] = wpa->page8.stations[i].iopoints; 728 | segment[8+i*4+2] = wpa->page8.stations[i].is_reserve_st; 729 | segment[8+i*4+3] = 0x01; 730 | } 731 | } 732 | 733 | nextcode = WPA_CODE_FXCPU_FX3U_IOASSIGMENT; 734 | break; 735 | 736 | case WPA_CODE_FXCPU_FX3U_IOASSIGMENT: 737 | segsize = 54; 738 | segment[4] = 0x02; 739 | segment[5] = 0x00; 740 | segment[6] = 0x00; 741 | segment[7] = 0x00; 742 | segment[8] = 0x00; 743 | segment[9] = 0x00; 744 | segment[10] = 0x00; 745 | segment[11] = 0x02; 746 | { 747 | int temp = wpa->page4.input_Totally; 748 | segment[12] = temp&0xFF; 749 | segment[13] = (temp>>8)&0xFF; 750 | } 751 | { 752 | int temp = wpa->page4.input_Start_offset; 753 | segment[14] = temp&0xFF; 754 | segment[15] = (temp>>8)&0xFF; 755 | } 756 | memset(segment+16,0x20,16); 757 | segment[32] = 0x01; 758 | segment[33] = 0x03; 759 | { 760 | int temp = wpa->page4.output_Totally; 761 | segment[34] = temp&0xFF; 762 | segment[35] = (temp>>8)&0xFF; 763 | } 764 | { 765 | int temp = wpa->page4.input_Start_offset; 766 | segment[36] = temp&0xFF; 767 | segment[37] = (temp>>8)&0xFF; 768 | } 769 | memset(segment+38,0x20,16); 770 | nextcode = WPA_CODE_EOF; 771 | break; 772 | 773 | default: 774 | break; 775 | } 776 | 777 | if (segsize>0) 778 | { 779 | //encode segment's header 780 | segment[0] = segsize&0xFF; 781 | segment[1] = (segsize>>8)&0xFF; 782 | segment[2] = (segcode>>8)&0xFF; 783 | segment[3] = segcode&0xFF; 784 | } 785 | 786 | *psegcode = nextcode; 787 | return segsize; 788 | } 789 | 790 | /* destroy wpa instance */ 791 | void mel_wpa_FXCPU_FX3U_free(void* wpax) 792 | { 793 | WPA_FXCPU_FX3U* wpa = (WPA_FXCPU_FX3U*)wpax; 794 | 795 | if (wpa) 796 | { 797 | 798 | free(wpa); 799 | } 800 | 801 | return; 802 | 803 | } -------------------------------------------------------------------------------- /mel_wpa_fxcpu_fx3.h: -------------------------------------------------------------------------------- 1 | #ifndef __wpa_fxcpu_fx3u_h__ 2 | #define __wpa_fxcpu_fx3u_h__ 3 | 4 | #include 5 | #include "mel_common.h" 6 | #include "mel_wpg_device.h" 7 | 8 | typedef struct tagWPA_FX3U_MemoryCapacity{ 9 | 10 | #define WPA_FX3U_MEMCAPACITY_2000 0x02 11 | #define WPA_FX3U_MEMCAPACITY_4000 0x04 12 | #define WPA_FX3U_MEMCAPACITY_8000 0x08//default 13 | #define WPA_FX3U_MEMCAPACITY_16000 0x10 14 | #define WPA_FX3U_MEMCAPACITY_32000 0x20 15 | #define WPA_FX3U_MEMCAPACITY_64000 0x40 16 | int mem_capacity_in_steps; 17 | int cmt_capacity_in_blocks; //0...15 18 | int freg_capacity_in_blocks; //0...14 19 | int SFBS_in_blocks; //0 or 8 20 | int PIS_in_blocks; //0 or 18 21 | int BCC_in_blocks; //0 or 1 22 | 23 | }WPA_FX3U_MemoryCapacity; 24 | 25 | #if 0 26 | int calc_SFM_capacity_in_steps (WPA_FX3U_MemoryCapacity* mem); 27 | int calc_Program_capacity_in_steps (WPA_FX3U_MemoryCapacity* mem); 28 | #endif //0 29 | 30 | typedef struct tagWPA_FX3U_LatchedDeviceRange{ 31 | 32 | int device_code; 33 | int latched_length; 34 | int latched_start; 35 | 36 | }WPA_FX3U_LatchedDeviceRange; 37 | 38 | typedef struct tagWPA_FX3U_Devices{ 39 | 40 | #define WPA_FX3U_MAX_EDITABLE_ITEMS 5 41 | int n_editable_items; 42 | WPA_FX3U_LatchedDeviceRange editable_items[WPA_FX3U_MAX_EDITABLE_ITEMS]; 43 | 44 | }WPA_FX3U_Devices; 45 | 46 | typedef struct tagWPA_FX3U_PLCName{ 47 | 48 | #define WPA_FX3U_PLCNAME_MAX_BYTES 32 49 | unsigned char raw[WPA_FX3U_PLCNAME_MAX_BYTES+2]; 50 | 51 | }WPA_FX3U_PLCName; 52 | 53 | typedef struct tagWPA_FX3U_BCCStation{ 54 | #define WPA_FX3U_BuiltInCCLink_LTSetup_STATIONTYPE_None 0x00 //default = disabled 55 | #define WPA_FX3U_BuiltInCCLink_LTSetup_STATIONTYPE_RemoteIOstation_In 0x01 56 | #define WPA_FX3U_BuiltInCCLink_LTSetup_STATIONTYPE_RemoteIOstation_Out 0x02 57 | #define WPA_FX3U_BuiltInCCLink_LTSetup_STATIONTYPE_RemoteIOstation_InOut 0x03 58 | #define WPA_FX3U_BuiltInCCLink_LTSetup_STATIONTYPE_RemoteDeviceStation 0x04 59 | int type; 60 | 61 | int iopoints; //1...16 62 | int is_reserve_st; //no(=0), yes(=1); 63 | 64 | }WPA_FX3U_BCCStation; 65 | 66 | typedef struct tagWPA_FX3U_BuiltInCCLink_LTSetup{ 67 | 68 | //08 01 {EF FF} (0x108 = 264 bytes totally: 4 + 4 + 256) 69 | #define WPA_FX3U_BuiltInCCLink_LTSetup_BAUDRATE_156kbps 0x00 //default 70 | #define WPA_FX3U_BuiltInCCLink_LTSetup_BAUDRATE_625kbps 0x01 71 | #define WPA_FX3U_BuiltInCCLink_LTSetup_BAUDRATE_2dot5Mbps 0x02 72 | int baudrate; 73 | #define WPA_FX3U_BuiltInCCLink_LTSetup_POINTMODE_16bit 0x01 //default 74 | #define WPA_FX3U_BuiltInCCLink_LTSetup_POINTMODE_4bit 0x00 75 | int point_mode; 76 | #define WPA_FX3U_STATIONS_COUNT 64 77 | WPA_FX3U_BCCStation stations[WPA_FX3U_STATIONS_COUNT]; 78 | 79 | }WPA_FX3U_BuiltInCCLink_LTSetup; 80 | 81 | typedef struct tagWPA_FX3U_IOAssignment{ 82 | 83 | //max range: [0-255] -> [0-377]octal 84 | int input_Start_offset; 85 | int input_Totally; 86 | 87 | //max range: [0-255] -> [0-377]octal 88 | int output_Start_offset; 89 | int output_Totally; 90 | 91 | }WPA_FX3U_IOAssignment; 92 | 93 | typedef struct tagWPA_FX3U_PLCSystem1{ 94 | 95 | int is_battery_less_drive_mode; //on(0x01)\off(0x00) 96 | 97 | #define WPA_FX3U_PLCSYSTEM1_MODEM_None 0x00 98 | #define WPA_FX3U_PLCSYSTEM1_MODEM_UserRegMode 0x01 99 | #define WPA_FX3U_PLCSYSTEM1_MODEM_AIWA 0x02 100 | #define WPA_FX3U_PLCSYSTEM1_MODEM_OMRON 0x03 101 | #define WPA_FX3U_PLCSYSTEM1_MODEM_UserModeCH1 0x04 102 | #define WPA_FX3U_PLCSYSTEM1_MODEM_UserModeCH2 0x05 103 | int modem; 104 | 105 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_None 0x0000 106 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X000 0x0100 107 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X001 0x0101 108 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X002 0x0102 109 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X003 0x0103 110 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X004 0x0104 111 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X005 0x0105 112 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X006 0x0106 113 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X007 0x0107 114 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X010 0x0108 115 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X011 0x0109 116 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X012 0x010A 117 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X013 0x010B 118 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X014 0x010C 119 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X015 0x010D 120 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X016 0x010E 121 | #define WPA_FX3U_PLCSYSTEM1_TERMINAL_X017 0x010F 122 | int terminal; 123 | 124 | }WPA_FX3U_PLCSystem1; 125 | 126 | typedef struct tagWPA_FX3U_PLCSystem2_CommChannel{ 127 | 128 | int is_enabled;//=(.baudrate!=0) 129 | //offset 0xC8 130 | #define WPA_FX3U_PLCSYSTEM2_PROTOCOL_NoneProcedural 0x00 131 | #define WPA_FX3U_PLCSYSTEM2_PROTOCOL_Dedicated 0x01 132 | int protocol; 133 | //offset 0xC9 134 | #define WPA_FX3U_PLCSYSTEM2_DATABITS_7bit 0x00 135 | #define WPA_FX3U_PLCSYSTEM2_DATABITS_8bit 0x01 136 | int databits; 137 | //offset 0xCA 138 | #define WPA_FX3U_PLCSYSTEM2_PARITY_None 0x00 139 | #define WPA_FX3U_PLCSYSTEM2_PARITY_Odd 0x01 140 | #define WPA_FX3U_PLCSYSTEM2_PARITY_Even 0x02 141 | int parity; 142 | //offset 0xCB 143 | #define WPA_FX3U_PLCSYSTEM2_STOPBITS_1bit 0x00 144 | #define WPA_FX3U_PLCSYSTEM2_STOPBITS_2bit 0x01 145 | int stopbits; 146 | //offset 0xCC 147 | #define WPA_FX3U_PLCSYSTEM2_BAUDRATE_38400 0x0A 148 | #define WPA_FX3U_PLCSYSTEM2_BAUDRATE_19200 0x09 149 | #define WPA_FX3U_PLCSYSTEM2_BAUDRATE_9600 0x08 150 | #define WPA_FX3U_PLCSYSTEM2_BAUDRATE_4800 0x07 151 | #define WPA_FX3U_PLCSYSTEM2_BAUDRATE_2400 0x06 152 | #define WPA_FX3U_PLCSYSTEM2_BAUDRATE_1200 0x05 153 | #define WPA_FX3U_PLCSYSTEM2_BAUDRATE_600 0x04 154 | #define WPA_FX3U_PLCSYSTEM2_BAUDRATE_300 0x03 155 | #define WPA_FX3U_PLCSYSTEM2_BAUDRATE_CH_DESABLED 0x00 156 | int baudrate; 157 | //offset 0xCD 158 | int is_header_on; //(off/on): 00/01 159 | //offset 0xCE 160 | int is_terminator_on; //(off/on): 00/01 161 | //offset 0xCF 162 | int is_control_line_on; //(off/on): 00/01 163 | //offset 0xD0-0xD1 164 | #define WPA_FX3U_PLCSYSTEM2_CNTRLINE_RegularRS232C 0x00 //Control line=00 (unlocked) 165 | #define WPA_FX3U_PLCSYSTEM2_CNTRLINE_RS485 0x01 //Control line=01 (locked) 166 | #define WPA_FX3U_PLCSYSTEM2_CNTRLINE_InterLinkRS232C 0x02 //Control line=00 (unlocked) 167 | #define WPA_FX3U_PLCSYSTEM2_CNTRLINE_ModemRS232C 0x03 //Control line=01 (locked) 168 | int hw_type; 169 | //offset 0xD2 170 | int is_sum_check_on; //(off/on): 00/01 171 | //offset 0xD3 172 | #define WPA_FX3U_PLCSYSTEM2_TRANSMCNTRL_Form1_noCRLF 0x00 173 | #define WPA_FX3U_PLCSYSTEM2_TRANSMCNTRL_Form4_byCRLF 0x01 174 | int transmission_cntrl; 175 | //offset 0xD4 176 | int station_number; //00...FF(ch1) or CCC(ch2) 177 | //offset 0xD5 178 | #define WPA_FX3U_PLCSYSTEM2_TIMEOUT_DISABLED 0x0000 179 | #define WPA_FX3U_PLCSYSTEM2_TIMEOUT_10ms 0x0001 //min 180 | #define WPA_FX3U_PLCSYSTEM2_TIMEOUT_2550ms 0x00FF //ch1-max 181 | #define WPA_FX3U_PLCSYSTEM2_TIMEOUT_32760ms 0x0CCC //ch2-max 182 | int timeout_judge_time_x10ms; 183 | 184 | }WPA_FX3U_PLCSystem2_CommChannel; 185 | 186 | typedef struct tagWPA_FX3U_PLCSystem2{ 187 | 188 | WPA_FX3U_PLCSystem2_CommChannel ch1; 189 | WPA_FX3U_PLCSystem2_CommChannel ch2; 190 | 191 | }WPA_FX3U_PLCSystem2; 192 | 193 | /* 194 | typedef struct tagWPA_FX3U_PosRecord{ 195 | 196 | #define WPA_FX3U_POSRECORD_INDEX_Y0 0 197 | #define WPA_FX3U_POSRECORD_INDEX_Y1 1 198 | #define WPA_FX3U_POSRECORD_INDEX_Y2 2 199 | #define WPA_FX3U_POSRECORD_INDEX_Y3 3 200 | int y[4]; 201 | 202 | }WPA_FX3U_PosRecord; 203 | */ 204 | typedef struct tagWPA_FX3U_PosRecordRange{ 205 | 206 | int min; 207 | int max; 208 | 209 | }WPA_FX3U_PosRecordRange; 210 | 211 | //WPA_FX3U_Positioning Limits 212 | static WPA_FX3U_PosRecordRange RangOf_BiasSpeed_Hz = {0,INT_MAX};//1/10 or less of max speed 213 | static WPA_FX3U_PosRecordRange RangOf_MaxSpeed_Hz = {10,200000}; 214 | static WPA_FX3U_PosRecordRange RangOf_CreepSpeed_Hz = {10,32767}; 215 | static WPA_FX3U_PosRecordRange RangOf_ZeroReturnSpeed_Hz = {10,200000}; 216 | static WPA_FX3U_PosRecordRange RangOf_AccelerationTime_ms= {50,5000}; 217 | static WPA_FX3U_PosRecordRange RangOf_DecelerationTime_ms= {50,5000}; 218 | 219 | typedef struct tagWPA_FX3U_PosInstruction{ 220 | 221 | #define WPA_FX3U_POS_INSTR_TYPE_NONE 0 //default 222 | #define WPA_FX3U_POS_INSTR_TYPE_DDVIT 1 223 | #define WPA_FX3U_POS_INSTR_TYPE_DPLSV 2 224 | #define WPA_FX3U_POS_INSTR_TYPE_DDRVI 3 225 | #define WPA_FX3U_POS_INSTR_TYPE_DDRVA 4 226 | int type; 227 | int pulse; //+/-(1...999999) default: ? 228 | int freq_Hz; //10...200000 default: 10 229 | 230 | }WPA_FX3U_PosInstruction; 231 | 232 | typedef struct tagWPA_FX3U_PosOneYInstructions{ 233 | 234 | int BiasSpeed_Hz; 235 | int MaxSpeed_Hz; 236 | int CreepSpeed_Hz; 237 | int ZeroReturnSpeed_Hz; 238 | int AccelerationTime_ms; 239 | int DecelerationTime_ms; 240 | 241 | #define WPA_FX3U_POSRECORD_INT_X0 0 //default[y0] 242 | #define WPA_FX3U_POSRECORD_INT_X1 1 //default[y1] 243 | #define WPA_FX3U_POSRECORD_INT_X2 2 //default[y2] 244 | #define WPA_FX3U_POSRECORD_INT_X3 3 //default[y3] 245 | #define WPA_FX3U_POSRECORD_INT_X4 4 246 | #define WPA_FX3U_POSRECORD_INT_X5 5 247 | #define WPA_FX3U_POSRECORD_INT_X6 6 248 | #define WPA_FX3U_POSRECORD_INT_X7 7 249 | #define WPA_FX3U_POSRECORD_INT_M864n 8 250 | int InterrInputSource; 251 | 252 | PLCRegDevice rotation_dir_signal; 253 | PLCRegDevice head_address; 254 | #define WPA_FX3U_POS_INSTR_COUNT 100 255 | WPA_FX3U_PosInstruction instructions[WPA_FX3U_POS_INSTR_COUNT]; 256 | int dont_init_postable;//init: 0(default)/ don't init: 1. 257 | 258 | }WPA_FX3U_PosOneYInstructions; 259 | 260 | typedef struct tagWPA_FX3U_PosInstructionsIndividualSetup{ 261 | 262 | #define WPA_FX3U_POS_YTABS_COUNT 4 263 | WPA_FX3U_PosOneYInstructions ytabs[WPA_FX3U_POS_YTABS_COUNT]; 264 | 265 | }WPA_FX3U_PosInstructionsIndividualSetup; 266 | 267 | typedef struct tagWPA_FX3U_Positioning{ 268 | 269 | WPA_FX3U_PosInstructionsIndividualSetup indivs; 270 | 271 | }WPA_FX3U_Positioning; 272 | 273 | ////////////////////////////////////////////////////////////////////////// 274 | //EXPORT DATA STRUCTURE 275 | typedef struct tagWPA_FXCPU_FX3U{ 276 | 277 | WPA_FX3U_MemoryCapacity page1; 278 | WPA_FX3U_Devices page2; 279 | WPA_FX3U_PLCName page3; 280 | WPA_FX3U_IOAssignment page4; 281 | WPA_FX3U_PLCSystem1 page5; 282 | WPA_FX3U_PLCSystem2 page6; 283 | WPA_FX3U_Positioning page7; 284 | 285 | WPA_FX3U_BuiltInCCLink_LTSetup page8;//if page1.BCC_in_blocks != 0 286 | WPA_FX3U_PosInstructionsIndividualSetup page9;//if page1.PIS_in_blocks != 0 287 | 288 | }WPA_FXCPU_FX3U; 289 | ////////////////////////////////////////////////////////////////////////// 290 | 291 | /* returns: done stream size > 0, error =0. */ 292 | int mel_wpa_FXCPU_FX3_decoder(unsigned char* stream,int enc_size,void* wpax); 293 | /* returns: done stream size > 0, error =0. */ 294 | int mel_wpa_FXCPU_FX3_encoder(void* wpax,unsigned char* stream); 295 | /* destroy wpa instance */ 296 | void mel_wpa_FXCPU_FX3U_free(void* wpax); 297 | 298 | #endif //__wpa_fxcpu_fx3u_h__ 299 | -------------------------------------------------------------------------------- /mel_wpg.c: -------------------------------------------------------------------------------- 1 | #include "mel_wpg.h" 2 | #include "mel_wpg_item.h" 3 | #include //printf 4 | #include //calloc 5 | #include //memset 6 | 7 | static unsigned char WPG_HEADER_LADDER[WPA_HEADER_SIZE_BYTES] = 8 | { 9 | 0x40,0x00,0x22,0x01,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 10 | /* file comment (32 bytes max) */ 11 | 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 12 | 0x20,0x20,0x20,0x20,0x04,0x02,0x08,0x02, 0x03,0x03,0x01,0xFF,0xFF,0xFF,0xFF,0xFF, 13 | /* [dtype,series] */ 14 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF 15 | }; 16 | 17 | static unsigned char WPG_HEADER_SFC[WPA_HEADER_SIZE_BYTES] = 18 | { 19 | 0x40,0x00,0x22,0x01,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 20 | 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 21 | 0x20,0x20,0x20,0x20,0x04,0x02,0x08,0x02, 0x03,0x03,0x00,0x04,0x05,0x00,0x00,0xFF, 22 | /* [dtype,series] [LADDER or SFC] */ 23 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF 24 | }; 25 | 26 | static unsigned char WPG_SUBHEADER_SFC[WPG_SFC_SUBHEADER_SIZE_BYTES] = 27 | { 28 | 0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x01,0x80,0xFF,0xFF, 29 | 0x00,0x00,0x00,0x00,0x04,0x80,0xFF,0xFF, 0xFF,0xFF,0x00,0x00,0x05,0x80,0x00,0x00, 30 | 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF, 0xFF,0xFF,0x06,0x00,0x00,0x80,0x00,0x00 31 | }; 32 | 33 | static int mel_enc_wpg_header (int cpuSeries,int cpuType,unsigned char* stream); 34 | 35 | /* returns: pointer to allocated (by malloc()) WPG_x structure; in case of failure: =0. */ 36 | void* mel_wpg_dec (unsigned char* stream,int stream_size,int* pcpuSeries,int* pcpuType,int* pprgMode,MELTools* tools) 37 | { 38 | void *wpg = 0; 39 | //set initially as unknown 40 | *pcpuSeries = MEL_PLC_SERIES_NULL; 41 | *pcpuType = MEL_PLC_TYPE_NULL; 42 | *pprgMode = WPG_RPOGRAMM_MODE_LADDER; 43 | //check for too short streams 44 | if (stream_size > 0x40) 45 | { 46 | int hdr_length = (int)stream[0]|((int)stream[1]<<8); 47 | 48 | //0. check header 49 | if (hdr_length == WPA_HEADER_SIZE_BYTES) 50 | { 51 | int cpuSeries; 52 | int cpuType; 53 | int prgMode; 54 | 55 | unsigned char cpuTypeCode; 56 | 57 | //1. decode CPU Series & Type 58 | cpuTypeCode = stream[WPA_CPU_TYPE_OFFSET]; 59 | cpuSeries = stream[WPA_CPU_SERIES_OFFSET]; 60 | prgMode = (stream[WPG_PROGRAMM_MODE_OFFSET] != 0x00)? WPG_RPOGRAMM_MODE_LADDER:WPG_RPOGRAMM_MODE_SFC; 61 | 62 | if (cpuSeries == MEL_PLC_SERIES_FXCPU) 63 | { 64 | cpuType = FXCPU_TYPES_by_code[cpuTypeCode]; 65 | } 66 | else 67 | { 68 | cpuType = cpuTypeCode; 69 | } 70 | 71 | *pcpuSeries = cpuSeries; 72 | *pcpuType = cpuType; 73 | *pprgMode = prgMode; 74 | 75 | if (prgMode == WPG_RPOGRAMM_MODE_LADDER) 76 | { 77 | //2. allocate appropriate WPG_x struct 78 | wpg = mel_wpg_allocate(cpuSeries,cpuType,tools); 79 | if (wpg) 80 | { 81 | int done_size = 0; 82 | 83 | //3. decode all fields of WPG_x 84 | done_size += tools->wpg_decoder(stream +hdr_length, 85 | stream_size -hdr_length, 86 | wpg); 87 | //printf("done: %d\n",done_size); 88 | #if 0 89 | if (done_size != stream_size-hdr_length) 90 | { 91 | printf("done_size (%d) != stream_size-hdr_length (%d)\n",done_size,stream_size-hdr_length); 92 | //error has happened during decoding: destroy wpg 93 | tools->wpg_destroy(wpg); 94 | wpg = 0; 95 | } 96 | //else{/* successfully done */} 97 | #endif 98 | } 99 | //else{/* unknown CPU or programm mode/format */} 100 | } 101 | } 102 | //else{/* wrong encoded value of header's size */} 103 | } 104 | //else{/* stream is too short */} 105 | 106 | return(wpg); 107 | } 108 | 109 | void* mel_til_dec (unsigned char* stream,int stream_size,int* pcpuSeries,int* pcpuType,MELTools* tools,int maxsteps) 110 | { 111 | void *wpg = 0; 112 | //set initially as unknown 113 | //*pcpuSeries = MEL_PLC_SERIES_NULL; 114 | //*pcpuType = MEL_PLC_TYPE_NULL; 115 | //check for too short streams 116 | //TODO 117 | { 118 | int cpuSeries; 119 | int cpuType; 120 | 121 | //1. decode CPU Series & Type 122 | //TODO 123 | 124 | cpuSeries = MEL_PLC_SERIES_FXCPU; 125 | cpuType = MEL_PLC_FXCPU_TYPE_FX3U_C; 126 | 127 | *pcpuSeries = cpuSeries; 128 | *pcpuType = cpuType; 129 | 130 | //2. allocate appropriate WPG_x struct 131 | wpg = mel_wpg_allocate(cpuSeries,cpuType,tools); 132 | if (wpg) 133 | { 134 | int done_size; 135 | //3. decode all fields of WPG_x 136 | done_size = tools->til_decoder(stream,stream_size,wpg,maxsteps); 137 | //printf("done: %d\n",done_size); 138 | #if 0 139 | if (done_size != stream_size) 140 | { 141 | printf("done_size (%d) != stream_size(%d)\n",done_size,stream_size); 142 | //error has happened during decoding: destroy wpg 143 | tools->wpg_destroy(wpg); 144 | wpg = 0; 145 | } 146 | //else{/* successfully done */} 147 | #endif 148 | } 149 | //else{/* unknown CPU */} 150 | } 151 | 152 | return(wpg); 153 | } 154 | 155 | /* returns: encoded size >0, failure: =0. */ 156 | int mel_wpg_enc (int cpuSeries,int cpuType,void* wpg,unsigned char* stream,int prgMode,MELTools* tools,int maxsteps) 157 | { 158 | int enc_size = 0; 159 | 160 | if (prgMode == WPG_RPOGRAMM_MODE_LADDER) 161 | { 162 | if (wpg) 163 | { 164 | int hdr_length; 165 | //encode header 166 | hdr_length = mel_enc_wpg_header(cpuSeries,cpuType,stream); 167 | //encode rest of file 168 | enc_size = tools->wpg_encoder(wpg,stream + hdr_length,maxsteps); 169 | if (enc_size > 0) 170 | { 171 | enc_size += hdr_length; 172 | } 173 | } 174 | } 175 | 176 | return(enc_size); 177 | } 178 | /* returns: encoded size >0, failure: =0. */ 179 | int mel_til_enc (int cpuSeries,int cpuType,void* wpg,unsigned char* stream,MELTools* tools) 180 | { 181 | int enc_size = 0; 182 | 183 | if (wpg) 184 | { 185 | enc_size = tools->til_encoder(wpg,stream); 186 | } 187 | 188 | return(enc_size); 189 | } 190 | 191 | /* 192 | returns: pointer to allocated (by malloc()) WPG_x structure; in case of failure: =0. 193 | Also, it calls internally mel_wpa_get_toolbox() to setup "tools" properly; 194 | */ 195 | void* mel_wpg_allocate (int cpuSeries,int cpuType,MELTools* tools) 196 | { 197 | void* wpg = 0; 198 | 199 | if(mel_get_toolbox(cpuSeries,cpuType,tools)) 200 | { 201 | wpg = calloc(1,tools->sizeof_wpgx); 202 | } 203 | 204 | return(wpg); 205 | } 206 | 207 | void mel_wpg_free (MELTools* tools,void* wpg) 208 | { 209 | if(tools) if(tools->wpg_destroy) if(wpg) tools->wpg_destroy(wpg); 210 | return; 211 | } 212 | 213 | static int mel_enc_wpg_header (int cpuSeries,int cpuType,unsigned char* stream) 214 | { 215 | unsigned char cpuTypeCode; 216 | //copy all 217 | memcpy(stream,WPG_HEADER_LADDER,WPA_HEADER_SIZE_BYTES); 218 | //tune CPU dtype & series 219 | if (cpuSeries == MEL_PLC_SERIES_FXCPU) 220 | { 221 | cpuTypeCode = FXCPU_TYPE_CODES_by_type[cpuType]; 222 | } 223 | else 224 | { 225 | cpuTypeCode = cpuType&0xFF; 226 | } 227 | 228 | stream[WPA_CPU_TYPE_OFFSET] = cpuTypeCode; 229 | stream[WPA_CPU_SERIES_OFFSET] = cpuSeries &0xFF; 230 | 231 | return(WPA_HEADER_SIZE_BYTES); 232 | } 233 | -------------------------------------------------------------------------------- /mel_wpg.h: -------------------------------------------------------------------------------- 1 | #ifndef __mel_wpg_h__ 2 | #define __mel_wpg_h__ 3 | 4 | #include "mel_wpg_fxcpu_fx3.h" 5 | 6 | ////////////////////////////////////////////////////////////////////////// 7 | /* 8 | returns: pointer to allocated (by malloc()) WPG_x structure; in case of failure: =0. 9 | Also, it calls internally mel_wpa_get_toolbox() to setup "tools" properly; 10 | */ 11 | void* mel_wpg_allocate (int cpuSeries,int cpuType,MELTools* tools); 12 | void mel_wpg_free (MELTools* tools,void* wpg); 13 | 14 | #define WPG_RPOGRAMM_MODE_LADDER 0 15 | #define WPG_RPOGRAMM_MODE_SFC 1 16 | 17 | /* returns: pointer to allocated (by malloc()) WPG_x structure; in case of failure: =0. */ 18 | void* mel_wpg_dec (unsigned char* stream,int stream_size,int* pcpuSeries,int* pcpuType,int* pprgMode,MELTools* tools); 19 | void* mel_til_dec (unsigned char* stream,int stream_size,int* pcpuSeries,int* pcpuType,MELTools* tools,int maxsteps); 20 | 21 | /* returns: encoded size >0, failure: =0. */ 22 | int mel_wpg_enc (int cpuSeries,int cpuType,void* wpg,unsigned char* stream,int prgMode,MELTools* tools,int maxsteps); 23 | int mel_til_enc (int cpuSeries,int cpuType,void* wpg,unsigned char* stream,MELTools* tools); 24 | 25 | #endif /* __mel_wpg_h__ */ 26 | -------------------------------------------------------------------------------- /mel_wpg_device.c: -------------------------------------------------------------------------------- 1 | #include "mel_common.h" 2 | #include "mel_wpg_device.h" 3 | #include "mel_wpg_fxcpu_regs.h" 4 | #include //memset 5 | #include //sprintf 6 | 7 | #ifdef WIN32 8 | #pragma warning (disable : 4996) 9 | #endif 10 | 11 | char* mel_get_device_name(unsigned int dev_type) 12 | { 13 | char* name = "Unknown"; 14 | 15 | if (dev_type & ( MEL_DEV_TYPE_M 16 | // |MEL_OTYPE_Msys 17 | ) 18 | ) 19 | { 20 | name = "M"; goto __exit_point; 21 | } 22 | 23 | if (dev_type & ( MEL_DEV_TYPE_Z 24 | |MEL_DEV_TYPE_ZI 25 | ) 26 | ) 27 | { 28 | name = "Z"; goto __exit_point; 29 | } 30 | 31 | if (dev_type & ( MEL_DEV_TYPE_V 32 | |MEL_DEV_TYPE_VI 33 | ) 34 | ) 35 | { 36 | name = "V"; goto __exit_point; 37 | } 38 | 39 | if (dev_type & ( MEL_DEV_TYPE_K 40 | |MEL_DEV_TYPE_K2 41 | |MEL_DEV_TYPE_Kn 42 | //|MEL_DEV_TYPE_KnM 43 | //|MEL_DEV_TYPE_KnS 44 | //|MEL_DEV_TYPE_KnX 45 | //|MEL_DEV_TYPE_KnY 46 | ) 47 | ) 48 | { 49 | name = "K"; goto __exit_point; 50 | } 51 | 52 | if (dev_type & ( MEL_DEV_TYPE_H 53 | |MEL_DEV_TYPE_H2 54 | ) 55 | ) 56 | { 57 | name = "H"; goto __exit_point; 58 | } 59 | 60 | switch(dev_type) 61 | { 62 | case MEL_DEV_TYPE_S: name = "S"; break; 63 | case MEL_DEV_TYPE_X: name = "X"; break; 64 | case MEL_DEV_TYPE_Y: name = "Y"; break; 65 | case MEL_DEV_TYPE_T: name = "T"; break; 66 | case MEL_DEV_TYPE_C: name = "C"; break; 67 | case MEL_DEV_TYPE_D: name = "D"; break; 68 | case MEL_DEV_TYPE_R: name = "R"; break; 69 | case MEL_DEV_TYPE_SU: name = "SU"; break;//name = "S"; break; 70 | case MEL_DEV_TYPE_bI: name = "."; break; 71 | case MEL_DEV_TYPE_E: name = "E"; break; 72 | case MEL_DEV_TYPE_P: name = "P"; break; 73 | case MEL_DEV_TYPE_I: name = "I"; break; 74 | case MEL_DEV_TYPE_N: name = "N"; break; 75 | case MEL_DEV_TYPE_STR: name = "";break; 76 | case MEL_DEV_TYPE_Un: name = "U"; break; 77 | case MEL_DEV_TYPE_Gn: name = "\\G"; break; 78 | case MEL_DEV_TYPE_ER: name = "ER"; break; 79 | } 80 | __exit_point: 81 | return(name); 82 | } 83 | 84 | unsigned int mel_approx_dtype_by_chars(char first,char second) 85 | { 86 | unsigned int dtype = MEL_DEV_TYPE_UNKNOWN; 87 | 88 | switch(first) 89 | { 90 | case 'M':case 'm': dtype = MEL_DEV_TYPE_M 91 | // |MEL_OTYPE_Msys 92 | ; 93 | break; 94 | 95 | case 'S':case 's': dtype = MEL_DEV_TYPE_S; break; 96 | case 'X':case 'x': dtype = MEL_DEV_TYPE_X; break; 97 | case 'Y':case 'y': dtype = MEL_DEV_TYPE_Y; break; 98 | case 'T':case 't': dtype = MEL_DEV_TYPE_T; break; 99 | case 'C':case 'c': dtype = MEL_DEV_TYPE_C; break; 100 | case 'D':case 'd': dtype = MEL_DEV_TYPE_D; break; 101 | case 'R':case 'r': dtype = MEL_DEV_TYPE_R; break; 102 | 103 | case '.': dtype = MEL_DEV_TYPE_bI; break; 104 | case '"': dtype = MEL_DEV_TYPE_STR; break; 105 | 106 | case 'V':case 'v': dtype = MEL_DEV_TYPE_V 107 | |MEL_DEV_TYPE_VI 108 | ; 109 | break; 110 | 111 | case 'Z':case 'z': dtype = MEL_DEV_TYPE_Z 112 | |MEL_DEV_TYPE_ZI 113 | ; 114 | break; 115 | 116 | case 'K':case 'k': dtype = MEL_DEV_TYPE_K 117 | |MEL_DEV_TYPE_K2 118 | |MEL_DEV_TYPE_Kn 119 | ; 120 | break; 121 | 122 | case 'E':case 'e': 123 | if (second == 'R' || second == 'r') 124 | { 125 | dtype = MEL_DEV_TYPE_ER; 126 | } 127 | else 128 | { 129 | dtype = MEL_DEV_TYPE_E; 130 | } 131 | break; 132 | 133 | 134 | case 'H':case 'h': dtype = MEL_DEV_TYPE_H 135 | |MEL_DEV_TYPE_H2 136 | ; 137 | break; 138 | 139 | case 'P':case 'p': dtype = MEL_DEV_TYPE_P; break; 140 | case 'I':case 'i': dtype = MEL_DEV_TYPE_I; break; 141 | case 'N':case 'n': dtype = MEL_DEV_TYPE_N; break; 142 | 143 | case 'U':case 'u': dtype = MEL_DEV_TYPE_Un; break; 144 | //case '\\': 145 | case 'G':case 'g': dtype = MEL_DEV_TYPE_Gn; break; 146 | } 147 | 148 | return(dtype); 149 | } 150 | 151 | unsigned int mel_get_device_code(unsigned int dev_type) 152 | { 153 | unsigned int code = 0; 154 | 155 | //filters 156 | 157 | if (dev_type & ( 158 | MEL_DEV_TYPE_M 159 | //|MEL_OTYPE_Msys 160 | )) 161 | { 162 | dev_type = MEL_DEV_TYPE_M; 163 | } 164 | if (dev_type & (// MEL_DEV_TYPE_KnX 165 | //|MEL_DEV_TYPE_KnY 166 | //|MEL_DEV_TYPE_KnM 167 | //|MEL_DEV_TYPE_KnS 168 | /*|*/MEL_DEV_TYPE_Kn 169 | ) 170 | ) 171 | { 172 | //printf("COMPLEX Kn: %08x\n",dev_type); 173 | dev_type = MEL_DEV_TYPE_Kn; 174 | } 175 | 176 | if (!code) 177 | { 178 | switch(dev_type) 179 | { 180 | case MEL_DEV_TYPE_M: //Supplement relay 181 | code = MEL_DEV_CODE_M; 182 | break; 183 | case MEL_DEV_TYPE_S: //State 184 | code = MEL_DEV_CODE_S; 185 | break; 186 | case MEL_DEV_TYPE_X: //Input 187 | code = MEL_DEV_CODE_X; 188 | break; 189 | case MEL_DEV_TYPE_Y: //Output 190 | code = MEL_DEV_CODE_Y; 191 | break; 192 | case MEL_DEV_TYPE_T: //Timer 193 | code = MEL_DEV_CODE_T; 194 | break; 195 | case MEL_DEV_TYPE_C: //Counter 196 | code = MEL_DEV_CODE_C; 197 | break; 198 | case MEL_DEV_TYPE_D: //Data registers 199 | code = MEL_DEV_CODE_D; 200 | break; 201 | case MEL_DEV_TYPE_R: //File registers 202 | code = MEL_DEV_CODE_R; 203 | break; 204 | case MEL_DEV_TYPE_SU://Special Unit 205 | code = MEL_DEV_CODE_SU; 206 | break; 207 | //indexes 208 | case MEL_DEV_TYPE_ZI: //Zx 209 | code = MEL_DEV_CODE_ZI; 210 | break; 211 | case MEL_DEV_TYPE_Z://Zx 212 | code = MEL_DEV_CODE_Z; 213 | break; 214 | case MEL_DEV_TYPE_Kn://Kx 215 | code = MEL_DEV_CODE_Kn; 216 | break; 217 | case MEL_DEV_TYPE_bI://D.b[x] 218 | code = MEL_DEV_CODE_bI; 219 | break; 220 | case MEL_DEV_TYPE_VI: //Vx 221 | code = MEL_DEV_CODE_VI; 222 | break; 223 | case MEL_DEV_TYPE_V: 224 | code = MEL_DEV_CODE_V; 225 | break; 226 | 227 | case MEL_DEV_TYPE_Un: 228 | code = MEL_DEV_CODE_Un; 229 | break; 230 | case MEL_DEV_TYPE_Gn: 231 | code = MEL_DEV_CODE_Gn; 232 | break; 233 | 234 | //constants 235 | case MEL_DEV_TYPE_K: //Kx 236 | code = MEL_DEV_CODE_K; 237 | break; 238 | case MEL_DEV_TYPE_K2://Kx 239 | code = MEL_DEV_CODE_K2; 240 | break; 241 | case MEL_DEV_TYPE_H: //Hx 242 | code = MEL_DEV_CODE_H; 243 | break; 244 | case MEL_DEV_TYPE_P: //Px 245 | code = MEL_DEV_CODE_P; 246 | break; 247 | case MEL_DEV_TYPE_I: //Ix 248 | code = MEL_DEV_CODE_I; 249 | break; 250 | case MEL_DEV_TYPE_N: //N0-N7 for MC,MCR 251 | code = MEL_DEV_CODE_N; 252 | break; 253 | 254 | case MEL_DEV_TYPE_H2://Hx 255 | code = MEL_DEV_CODE_H2; 256 | break; 257 | 258 | case MEL_DEV_TYPE_E: //Ex 259 | code = MEL_DEV_CODE_E; 260 | break; 261 | 262 | case MEL_DEV_TYPE_STR: 263 | code = MEL_DEV_CODE_STR; 264 | break; 265 | 266 | case MEL_DEV_TYPE_ER: 267 | code = MEL_DEV_CODE_ER; 268 | break; 269 | } 270 | 271 | } 272 | 273 | return(code); 274 | } 275 | 276 | unsigned int mel_get_device_type(unsigned int dev_code) 277 | { 278 | unsigned int dtype = MEL_DEV_TYPE_UNKNOWN; 279 | 280 | switch(dev_code) 281 | { 282 | case MEL_DEV_CODE_M: //Supplement relay 283 | dtype = MEL_DEV_TYPE_M; 284 | break; 285 | case MEL_DEV_CODE_S: //State 286 | dtype = MEL_DEV_TYPE_S; 287 | break; 288 | case MEL_DEV_CODE_X: //Input 289 | dtype = MEL_DEV_TYPE_X; 290 | break; 291 | case MEL_DEV_CODE_Y: //Output 292 | dtype = MEL_DEV_TYPE_Y; 293 | break; 294 | case MEL_DEV_CODE_T: //Timer 295 | dtype = MEL_DEV_TYPE_T; 296 | break; 297 | case MEL_DEV_CODE_C: //Counter 298 | dtype = MEL_DEV_TYPE_C; 299 | break; 300 | case MEL_DEV_CODE_D: //Data registers 301 | dtype = MEL_DEV_TYPE_D; 302 | break; 303 | case MEL_DEV_CODE_ER: //Extension File registers 304 | dtype = MEL_DEV_TYPE_ER; 305 | break; 306 | case MEL_DEV_CODE_R: //File registers 307 | dtype = MEL_DEV_TYPE_R; 308 | break; 309 | case MEL_DEV_CODE_SU://Special Unit 310 | dtype = MEL_DEV_TYPE_SU; 311 | break; 312 | //indexes 313 | case MEL_DEV_CODE_ZI: //Zx 314 | dtype = MEL_DEV_TYPE_ZI; 315 | break; 316 | case MEL_DEV_CODE_Z://Zx 317 | dtype = MEL_DEV_TYPE_Z; 318 | break; 319 | case MEL_DEV_CODE_Kn://Kx 320 | dtype = MEL_DEV_TYPE_Kn; 321 | break; 322 | case MEL_DEV_CODE_bI://D.b[x] 323 | dtype = MEL_DEV_TYPE_bI; 324 | break; 325 | case MEL_DEV_CODE_VI: //Vx 326 | dtype = MEL_DEV_TYPE_VI; 327 | break; 328 | case MEL_DEV_CODE_V: 329 | dtype = MEL_DEV_TYPE_V; 330 | break; 331 | case MEL_DEV_CODE_Un: 332 | dtype = MEL_DEV_TYPE_Un; 333 | break; 334 | case MEL_DEV_CODE_Gn: 335 | dtype = MEL_DEV_TYPE_Gn; 336 | break; 337 | //constants 338 | case MEL_DEV_CODE_K: //Kx 339 | dtype = MEL_DEV_TYPE_K; 340 | break; 341 | case MEL_DEV_CODE_K2://Kx 342 | dtype = MEL_DEV_TYPE_K2; 343 | break; 344 | case MEL_DEV_CODE_H: //Hx 345 | dtype = MEL_DEV_TYPE_H; 346 | break; 347 | case MEL_DEV_CODE_P: //Px 348 | dtype = MEL_DEV_TYPE_P; 349 | break; 350 | case MEL_DEV_CODE_I: //Ix 351 | dtype = MEL_DEV_TYPE_I; 352 | break; 353 | case MEL_DEV_CODE_N: //N0-N7 for MC,MCR 354 | dtype = MEL_DEV_TYPE_N; 355 | break; 356 | 357 | case MEL_DEV_CODE_H2://Hx 358 | dtype = MEL_DEV_TYPE_H2; 359 | break; 360 | 361 | case MEL_DEV_CODE_E: //Ex 362 | dtype = MEL_DEV_TYPE_E; 363 | break; 364 | 365 | case MEL_DEV_CODE_STR: 366 | dtype = MEL_DEV_TYPE_STR; 367 | break; 368 | } 369 | 370 | return(dtype); 371 | } 372 | 373 | char* mel_device2text(PLCRegDevice* dev,int* ptextsize) 374 | { 375 | char* retptr = 0; 376 | 377 | static char text[MEL_WPG_MAX_INSTR_TEXT_SIZE] = {0}; 378 | int textsize = 0; 379 | 380 | char devnumber[MEL_WPG_MAX_INSTR_TEXT_SIZE] = {0}; 381 | int devnumberlen; 382 | 383 | char* devname; 384 | int devnamelen; 385 | 386 | unsigned int dtype = dev->dtype; 387 | 388 | text[0] = 0; 389 | 390 | devname = mel_get_device_name(dtype); 391 | devnamelen = strlen(devname); 392 | 393 | strcat(text,devname); 394 | textsize += devnamelen; 395 | 396 | if ( !(dtype&(MEL_DEV_TYPE_K 397 | |MEL_DEV_TYPE_K2 398 | |MEL_DEV_TYPE_bI 399 | |MEL_DEV_TYPE_E 400 | |MEL_DEV_TYPE_H 401 | |MEL_DEV_TYPE_H2 402 | |MEL_DEV_TYPE_STR 403 | ) 404 | ) 405 | ) 406 | { 407 | if ( !(dtype&(MEL_DEV_TYPE_X|MEL_DEV_TYPE_Y))) 408 | { 409 | devnumberlen = sprintf(devnumber,"%d",dev->index); 410 | } 411 | else 412 | devnumberlen = sprintf(devnumber,"%03o",dev->index); 413 | } 414 | else 415 | { 416 | if (!(dtype&MEL_DEV_TYPE_E)) 417 | { 418 | if ( !(dtype&(MEL_DEV_TYPE_H 419 | |MEL_DEV_TYPE_H2 420 | |MEL_DEV_TYPE_bI 421 | |MEL_DEV_TYPE_STR 422 | ) 423 | ) 424 | ) 425 | { 426 | devnumberlen = sprintf(devnumber,"%d",dev->const_int); 427 | } 428 | else 429 | { 430 | if (dtype&(MEL_DEV_TYPE_H2|MEL_DEV_TYPE_H)) 431 | { 432 | devnumberlen = sprintf(devnumber,"%X",dev->const_uint); 433 | } 434 | 435 | if (dtype&MEL_DEV_TYPE_STR) 436 | { 437 | devnumberlen = sprintf(devnumber,"\"%s\"",dev->const_str); 438 | } 439 | 440 | if (dtype&MEL_DEV_TYPE_bI) 441 | { 442 | devnumberlen = sprintf(devnumber,"%X",dev->index); 443 | } 444 | } 445 | } 446 | else 447 | { 448 | devnumberlen = sprintf(devnumber,"%f",dev->const_flt); 449 | } 450 | } 451 | 452 | strcat(text,devnumber); 453 | textsize += devnumberlen; 454 | 455 | retptr = text; 456 | *ptextsize = textsize; 457 | return(retptr); 458 | } 459 | 460 | int mel_wpg_dec_device(int cpuSeries,int cpuType,unsigned char* stream,int stream_size,PLCRegDevice* dev) 461 | { 462 | int size_done = 0; 463 | 464 | if (stream_size > 2) 465 | { 466 | int size_brutto = stream[0]; 467 | if (size_brutto <= stream_size) 468 | { 469 | #if 0 470 | { 471 | int i_byte; 472 | printf("\t\t["); 473 | for (i_byte = 0; i_byte < size_brutto; i_byte++) 474 | { 475 | printf("%02X ",stream[i_byte]); 476 | } 477 | printf("]"); 478 | } 479 | #endif 480 | if (size_brutto == stream[size_brutto - 1]) 481 | { 482 | int size_netto = size_brutto - 2; 483 | int data_size = size_netto - 1; 484 | unsigned int data; 485 | unsigned int code; 486 | 487 | size_done = size_brutto; 488 | code = stream[1]; 489 | //fill common fields 490 | dev->dtype = mel_get_device_type(code); 491 | //decode value 492 | switch(data_size) 493 | { 494 | case 1: 495 | data = stream[2]; 496 | break; 497 | case 2: 498 | data = ((int)stream[3]<<8)|(int)stream[2]; 499 | break; 500 | case 3: 501 | data = ((int)stream[4]<<16)|((int)stream[3]<<8)|(int)stream[2]; 502 | break; 503 | case 4: 504 | data = ((int)stream[5]<<24)|((int)stream[4]<<16)|((int)stream[3]<<8)|(int)stream[2]; 505 | break; 506 | default: 507 | if (code == MEL_DEV_CODE_STR) 508 | { 509 | if (data_size > 32) 510 | { 511 | size_done = 0;//error: too long string 512 | goto __exit_point; 513 | } 514 | } 515 | else 516 | { 517 | size_done = 0;//error: too big encoded device's value 518 | goto __exit_point; 519 | } 520 | } 521 | 522 | //handle properly 523 | switch(code) 524 | { //devices 525 | case MEL_DEV_CODE_M: //Supplement relay 526 | //case MEL_OTYPE_Msys: //Special Supplement relay 527 | case MEL_DEV_CODE_S: //State 528 | case MEL_DEV_CODE_X: //Input 529 | case MEL_DEV_CODE_Y: //Output 530 | case MEL_DEV_CODE_T: //Timer 531 | case MEL_DEV_CODE_C: //Counter 532 | case MEL_DEV_CODE_D: //Data registers 533 | case MEL_DEV_CODE_R: //File registers 534 | case MEL_DEV_CODE_SU://Special Unit 535 | case MEL_DEV_CODE_Z: 536 | case MEL_DEV_CODE_V: 537 | //indexes 538 | case MEL_DEV_CODE_ZI://Z 539 | case MEL_DEV_CODE_Kn://Kn 540 | case MEL_DEV_CODE_bI://D.b[x] 541 | case MEL_DEV_CODE_VI://V 542 | case MEL_DEV_CODE_Un: 543 | case MEL_DEV_CODE_Gn: 544 | case MEL_DEV_CODE_P: //P 545 | case MEL_DEV_CODE_I: //I 546 | case MEL_DEV_CODE_N: //N0-N7 for MC,MCR 547 | dev->index = data; 548 | break; 549 | 550 | //constants 551 | case MEL_DEV_CODE_K: //K 552 | case MEL_DEV_CODE_K2: //K 553 | dev->const_int = data; 554 | break; 555 | 556 | case MEL_DEV_CODE_H: //H 557 | case MEL_DEV_CODE_H2: //H 558 | dev->const_uint = data; 559 | break; 560 | 561 | case MEL_DEV_CODE_E: //E 562 | if(data_size == 4) 563 | { 564 | union{ 565 | unsigned int tint; 566 | float tflt; 567 | }tmp; 568 | 569 | tmp.tint = data; 570 | dev->const_flt = tmp.tflt; 571 | } 572 | else 573 | { 574 | size_done = 0;//error 575 | } 576 | break; 577 | 578 | case MEL_DEV_CODE_STR: 579 | memcpy(dev->const_str,stream+2,data_size); 580 | dev->const_str[data_size] = 0;//add ending null 581 | dev->const_str_length = data_size; 582 | break; 583 | 584 | default: 585 | size_done = 0;//error 586 | } 587 | }//else{//error: wrong data in stream} 588 | }//else{//error: stream is too short} 589 | }//else{//error: stream is too short} 590 | __exit_point: 591 | return(size_done); 592 | } 593 | 594 | int mel_wpg_enc_device(PLCRegDevice* dev,int cpuSeries,int cpuType,unsigned char* stream) 595 | { 596 | int size_done = 0; 597 | int data_size = 0; 598 | unsigned int data = 0; 599 | unsigned int code = 0; 600 | unsigned int devices = MEL_DEV_TYPE_M //Supplement relay 601 | // |MEL_OTYPE_Msys //Special Supplement relay 602 | |MEL_DEV_TYPE_S //State 603 | |MEL_DEV_TYPE_X //Input 604 | |MEL_DEV_TYPE_Y //Output 605 | |MEL_DEV_TYPE_T //Timer 606 | |MEL_DEV_TYPE_C //Counter 607 | |MEL_DEV_TYPE_D //Data registers 608 | |MEL_DEV_TYPE_R //File registers 609 | |MEL_DEV_TYPE_ER //Extension File registers 610 | |MEL_DEV_TYPE_SU //Special Unit 611 | //indexes 612 | |MEL_DEV_TYPE_ZI //Zx 613 | |MEL_DEV_TYPE_Z //Zx 614 | |MEL_DEV_TYPE_Kn 615 | |MEL_DEV_TYPE_bI //D.b[x] 616 | |MEL_DEV_TYPE_VI //Vx 617 | |MEL_DEV_TYPE_V 618 | |MEL_DEV_TYPE_Un 619 | |MEL_DEV_TYPE_Gn 620 | |MEL_DEV_TYPE_P //Px 621 | |MEL_DEV_TYPE_I //Ix 622 | |MEL_DEV_TYPE_N //N0-N7 for MC,MCR 623 | ; 624 | 625 | //devices 626 | if ( !(dev->dtype & (~devices)) && (dev->dtype & devices) ) 627 | { 628 | data = dev->index; 629 | } 630 | else //constants: decimal 631 | if (dev->dtype & (MEL_DEV_TYPE_K 632 | |MEL_DEV_TYPE_K2 633 | ) 634 | ) 635 | { 636 | data = dev->const_int; 637 | } 638 | else //constants: hexadecimal 639 | if (dev->dtype & (MEL_DEV_TYPE_H 640 | |MEL_DEV_TYPE_H2 641 | ) 642 | ) 643 | { 644 | data = dev->const_uint; 645 | } 646 | else //constants: floating point numbers 647 | if (dev->dtype & MEL_DEV_TYPE_E) 648 | { 649 | { 650 | union{ 651 | unsigned int tint; 652 | float tflt; 653 | }tmp; 654 | 655 | tmp.tflt = dev->const_flt; 656 | data = tmp.tint; 657 | data_size = 4; 658 | } 659 | } 660 | else //constants: strings 661 | if (dev->dtype & MEL_DEV_TYPE_STR) 662 | { 663 | //data_size = strlen(dev->const_str); 664 | data_size = dev->const_str_length; 665 | memcpy(stream+2,dev->const_str,data_size); 666 | } 667 | else 668 | goto __exit_point;//error: unknown device dtype 669 | 670 | if (!(dev->dtype&MEL_DEV_TYPE_STR)) 671 | { 672 | if (data_size == 0) 673 | { 674 | data_size = mel_wpg_uint_sizeof(data); 675 | } 676 | 677 | switch(data_size) 678 | { 679 | case 1: 680 | stream[2] = data; 681 | break; 682 | case 2: 683 | stream[2] = data&0xFF; 684 | stream[3] = (data>>8)&0xFF; 685 | break; 686 | case 3: 687 | stream[2] = data&0xFF; 688 | stream[3] = (data>>8)&0xFF; 689 | stream[4] = (data>>16)&0xFF; 690 | break; 691 | case 4: 692 | stream[2] = data&0xFF; 693 | stream[3] = (data>>8)&0xFF; 694 | stream[4] = (data>>16)&0xFF; 695 | stream[5] = (data>>24)&0xFF; 696 | break; 697 | } 698 | } 699 | 700 | size_done = data_size + 1 + 2; 701 | stream[0] = size_done; 702 | stream[size_done - 1] = stream[0]; 703 | code = mel_get_device_code(dev->dtype); 704 | stream[1] = code; 705 | 706 | __exit_point: 707 | return(size_done); 708 | } 709 | 710 | #if 0 711 | int is_reg_in_range(PLCRegDevice* reg,int cpuSeries,int cpuType) 712 | { 713 | int isok = 1; 714 | int i_dtype = get_log2(reg->dtype); 715 | int lowest = REGS_METRIX_FXCPU[i_dtype][cpuType].lowest; 716 | int highest = REGS_METRIX_FXCPU[i_dtype][cpuType].highest; 717 | 718 | if (reg->dtype &( MEL_DEV_TYPE_M //Supplement relay 719 | // |MEL_OTYPE_Msys //Special Supplement relay 720 | |MEL_DEV_TYPE_S //State 721 | |MEL_DEV_TYPE_X //Input 722 | |MEL_DEV_TYPE_Y //Output 723 | |MEL_DEV_TYPE_T //Timer 724 | |MEL_DEV_TYPE_C //Counter 725 | |MEL_DEV_TYPE_D //Data registers 726 | |MEL_DEV_TYPE_R //File registers 727 | |MEL_DEV_TYPE_ER //Extension File registers 728 | |MEL_DEV_TYPE_SU//Special Unit 729 | |MEL_DEV_TYPE_ZI //Zx 730 | |MEL_DEV_TYPE_Z//Zx 731 | |MEL_DEV_TYPE_Kn 732 | |MEL_DEV_TYPE_bI//D.b[x] 733 | |MEL_DEV_TYPE_VI //Vx 734 | |MEL_DEV_TYPE_V 735 | |MEL_DEV_TYPE_Un 736 | |MEL_DEV_TYPE_Gn 737 | |MEL_DEV_TYPE_P //Px 738 | |MEL_DEV_TYPE_I //Ix 739 | |MEL_DEV_TYPE_N //N0-N7 for MC,MCR 740 | ) 741 | ) 742 | { 743 | if ( lowest != highest) 744 | { 745 | if (reg->index < lowest || reg->index > highest) 746 | { 747 | isok = 0; 748 | } 749 | } 750 | else 751 | { 752 | switch(cpuType) 753 | { 754 | case MEL_PLC_FXCPU_TYPE_FX3U_C: 755 | case MEL_PLC_FXCPU_TYPE_FX3G_C: 756 | if (reg->dtype & MEL_DEV_TYPE_I) 757 | { 758 | switch(reg->index) 759 | { 760 | //Input interrupt (interrupt triggered by external signal) 761 | case 0: //X000 I001 I000 762 | case 1: 763 | case 100://X001 I101 I100 764 | case 101: 765 | case 200://X002 I201 I200 766 | case 201: 767 | case 300://X003 I301 I300 768 | case 301: 769 | case 400://X004 I401 I400 770 | case 401: 771 | case 500://X005 I501 I500 772 | break; 773 | //Counter Interrupt - Interrupt Triggered by Counting Up of High-Speed Counter 774 | case 10: 775 | case 20: 776 | case 30: 777 | case 40: 778 | case 50: 779 | case 60: 780 | if(cpuType == MEL_PLC_FXCPU_TYPE_FX3G_C) 781 | { 782 | isok = 0; 783 | } 784 | break; 785 | 786 | default: 787 | //Timer interrupt (interrupt in constant cycle) 788 | if ( !(reg->index >= 610 && reg->index <= 699) 789 | && !(reg->index >= 710 && reg->index <= 799) 790 | && !(reg->index >= 810 && reg->index <= 899) 791 | ) 792 | { 793 | isok = 0; 794 | } 795 | } 796 | } 797 | break; 798 | } 799 | } 800 | } 801 | return(isok); 802 | } 803 | #endif 804 | 805 | int is_indexing_allowed(PLCRegDevice* reg,int cpuSeries,int cpuType) 806 | { 807 | int isok = 0;//not allowed (by default); 808 | 809 | switch((cpuSeries<<8)|cpuType) 810 | { 811 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX0_S): 812 | break; 813 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX0N): 814 | break; 815 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1): 816 | break; 817 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FXU_FX2C): 818 | break; 819 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX2N_C): 820 | break; 821 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1S): 822 | break; 823 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1N_S): 824 | break; 825 | 826 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX3U_C): 827 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX3G_C): 828 | if (//not allowed 829 | !(reg->dtype & 830 | ( 831 | MEL_DEV_TYPE_Un 832 | |MEL_DEV_TYPE_V 833 | |MEL_DEV_TYPE_Z 834 | |MEL_DEV_TYPE_bI 835 | |MEL_DEV_TYPE_E 836 | ) 837 | ) 838 | && 839 | //not allowed 840 | !(reg->dtype_ext & 841 | MEL_DEV_TYPE_EXT_Msys 842 | ) 843 | && 844 | //allowed 845 | (reg->dtype & 846 | (//bit devices 847 | MEL_DEV_TYPE_X 848 | |MEL_DEV_TYPE_Y 849 | |MEL_DEV_TYPE_M 850 | |MEL_DEV_TYPE_S 851 | |MEL_DEV_TYPE_T 852 | |MEL_DEV_TYPE_C//(16-bit only) 853 | //word devices 854 | |MEL_DEV_TYPE_D 855 | |MEL_DEV_TYPE_R 856 | |MEL_DEV_TYPE_ER 857 | |MEL_DEV_TYPE_P//!!! -> function pointers !!! 858 | //word/dword constants 859 | |MEL_DEV_TYPE_K|MEL_DEV_TYPE_K2 860 | |MEL_DEV_TYPE_H|MEL_DEV_TYPE_H2 861 | //BMF 862 | |MEL_DEV_TYPE_Gn 863 | ) 864 | ) 865 | ) 866 | { 867 | //except 32-bit counters 868 | if (reg->dtype & MEL_DEV_TYPE_C && reg->index >= 200) 869 | { 870 | goto __exit_point; 871 | } 872 | //allowed! 873 | isok = 1; 874 | } 875 | break; 876 | } 877 | 878 | __exit_point: 879 | return(isok); 880 | } 881 | 882 | int is_linking_allowed(PLCRegDevice* reg,int cpuSeries,int cpuType) 883 | { 884 | int isok = 0;//not allowed (by default); 885 | 886 | switch((cpuSeries<<8)|cpuType) 887 | { 888 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX0_S): 889 | break; 890 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX0N): 891 | break; 892 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1): 893 | break; 894 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FXU_FX2C): 895 | break; 896 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX2N_C): 897 | break; 898 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1S): 899 | break; 900 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1N_S): 901 | break; 902 | 903 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX3U_C): 904 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX3G_C): 905 | 906 | if (//allowed 907 | (reg->dtype & 908 | (//bit devices 909 | MEL_DEV_TYPE_X 910 | |MEL_DEV_TYPE_Y 911 | |MEL_DEV_TYPE_M//|MEL_OTYPE_Msys 912 | |MEL_DEV_TYPE_S 913 | ) 914 | ) 915 | ) 916 | { 917 | isok = 1;//allowed! 918 | } 919 | break; 920 | } 921 | return(isok); 922 | } 923 | 924 | int is_bitaccess_allowed(PLCRegDevice* reg,int cpuSeries,int cpuType) 925 | { 926 | int isok = 0;//not allowed (by default); 927 | 928 | switch((cpuSeries<<8)|cpuType) 929 | { 930 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX0_S): 931 | break; 932 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX0N): 933 | break; 934 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1): 935 | break; 936 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FXU_FX2C): 937 | break; 938 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX2N_C): 939 | break; 940 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1S): 941 | break; 942 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX1N_S): 943 | break; 944 | 945 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX3U_C): 946 | case ((MEL_PLC_SERIES_FXCPU<<8)|MEL_PLC_FXCPU_TYPE_FX3G_C): 947 | 948 | if (//not allowed 949 | !(reg->dtype & 950 | (//all other except D 951 | ~MEL_DEV_TYPE_D 952 | ) 953 | ) 954 | && 955 | //allowed 956 | (reg->dtype & 957 | (//word devices 958 | MEL_DEV_TYPE_D 959 | ) 960 | ) 961 | ) 962 | { 963 | isok = 1;//allowed! 964 | } 965 | break; 966 | } 967 | return(isok); 968 | } 969 | 970 | int is_it_VorZ(unsigned int dtype) 971 | { 972 | int yes_or_no = 0; 973 | 974 | if (dtype & (MEL_DEV_TYPE_V 975 | |MEL_DEV_TYPE_VI 976 | |MEL_DEV_TYPE_Z 977 | |MEL_DEV_TYPE_ZI 978 | ) 979 | ) 980 | { 981 | //V or Z without number -> V0 or Z0; 982 | yes_or_no = 1; 983 | } 984 | 985 | return(yes_or_no); 986 | } 987 | -------------------------------------------------------------------------------- /mel_wpg_device.h: -------------------------------------------------------------------------------- 1 | #ifndef __mel_wpg_device_h__ 2 | #define __mel_wpg_device_h__ 3 | 4 | #define MEL_DEV_CODE_M 0x90 //or supplement relay 5 | #define MEL_DEV_CODE_S 0x98 //State Relay 6 | #define MEL_DEV_CODE_X 0x9C //Input 7 | #define MEL_DEV_CODE_Y 0x9D //Output 8 | #define MEL_DEV_CODE_T 0xC2 //Timer 9 | #define MEL_DEV_CODE_C 0xC5 //Counter 10 | #define MEL_DEV_CODE_D 0xA8 //Data registers 11 | #define MEL_DEV_CODE_Gn 0xAB //Gx (as an [index]: MOV U3\G15) 12 | #define MEL_DEV_CODE_R 0xAF //File registers 13 | #define MEL_DEV_CODE_ER 0xAE //Extension File registers 14 | 15 | #define MEL_DEV_CODE_ZI 0xF0 //Zx (as an [index]: OUT Y000Z0) 16 | #define MEL_DEV_CODE_Kn 0xF1 //Kx (as an bits counter: OUT K8Y000) 17 | #define MEL_DEV_CODE_bI 0xF2 //D.b[x] 18 | #define MEL_DEV_CODE_VI 0xF4 //Vx (as an [index]: OUT Y000V0) 19 | #define MEL_DEV_CODE_Un 0xF8 //Ux (as an [index]: MOV U3\G15) 20 | #define MEL_DEV_CODE_Z 0xCC //Zx (as a variable: MOV K0 Z0) 21 | #define MEL_DEV_CODE_V 0xCD //Vx (as a variable: MOV K0 V0) 22 | 23 | #define MEL_DEV_CODE_SU 0xD8 //Special Unit 24 | 25 | #define MEL_DEV_CODE_K 0xE8 //Kx (16-bit signed integer) 26 | #define MEL_DEV_CODE_K2 0xE9 //Kx (32-bit signed integer) 27 | #define MEL_DEV_CODE_H 0xEA //Hx (16-bit unsigned integer in hex) 28 | #define MEL_DEV_CODE_H2 0xEB //Hx (32-bit unsigned integer in hex) 29 | #define MEL_DEV_CODE_E 0xEC //Ex (floating point number) 30 | #define MEL_DEV_CODE_STR 0xEE //"..." 31 | #define MEL_DEV_CODE_P 0xD0 //Px (label or subroutine) 32 | #define MEL_DEV_CODE_I 0xD1 //Ix (interrupt code) 33 | #define MEL_DEV_CODE_N 0xD2 //N0-N7 for MC,MCR 34 | 35 | 36 | typedef struct tagPLCRegDevice 37 | { 38 | #define MEL_DEV_TYPE_UNKNOWN (0) 39 | 40 | #define MEL_DEV_TYPE_M (1<<0) //1 //or supplement relay 41 | #define MEL_DEV_TYPE_S (1<<1) //2 //State Relay 42 | #define MEL_DEV_TYPE_X (1<<2) //4 //Input 43 | #define MEL_DEV_TYPE_Y (1<<3) //8 //Output 44 | #define MEL_DEV_TYPE_T (1<<4) //16 //Timer 45 | #define MEL_DEV_TYPE_C (1<<5) //32 //Counter 46 | #define MEL_DEV_TYPE_D (1<<6) //64 //Data registers 47 | #define MEL_DEV_TYPE_R (1<<7) //128 //File registers 48 | #define MEL_DEV_TYPE_ER (1<<8) //256 //Extension File Registers 49 | 50 | #define MEL_DEV_TYPE_ZI (1<<9) //512 //Zx (as an [index]: OUT Y000Z0) 51 | #define MEL_DEV_TYPE_Kn (1<<10) //1024 //Kx (as an bits counter: OUT K8Y000) 52 | #define MEL_DEV_TYPE_bI (1<<11) //2048 //D.b[x] 53 | #define MEL_DEV_TYPE_VI (1<<12) //4096 //Vx (as an [index]: OUT Y000V0) 54 | #define MEL_DEV_TYPE_Z (1<<13) //8192 //Zx (as a variable: MOV K0 Z0) 55 | #define MEL_DEV_TYPE_V (1<<14) //16384 //Vx (as a variable: MOV K0 V0) 56 | 57 | #define MEL_DEV_TYPE_K (1<<15) //32768 //Kx (16-bit signed integer) 58 | #define MEL_DEV_TYPE_K2 (1<<16) //65536 //Kx (32-bit signed integer) 59 | #define MEL_DEV_TYPE_H (1<<17) //131072 //Hx (16-bit unsigned integer in hex) 60 | #define MEL_DEV_TYPE_H2 (1<<18) //262144 //Hx (32-bit unsigned integer in hex) 61 | #define MEL_DEV_TYPE_E (1<<19) //524288 //Ex (floating point number) 62 | #define MEL_DEV_TYPE_P (1<<20) //1048576 //Px (label or subroutine) 63 | #define MEL_DEV_TYPE_I (1<<21) //2097152 //Ix (interrupt code) 64 | #define MEL_DEV_TYPE_N (1<<22) //4194304 //N0-N7 for MC,MCR 65 | 66 | #define MEL_DEV_TYPE_Un (1<<23) // U0 67 | #define MEL_DEV_TYPE_Gn (1<<24) // /G0 68 | #define MEL_DEV_TYPE_STR (1<<25) //"..." 69 | 70 | #define MEL_DEV_TYPE_SU (1<<26) //Special Unit !!!UNUSED!!! 71 | 72 | unsigned int dtype; 73 | 74 | #define MEL_DEV_TYPE_EXT_Msys (1<<0) 75 | #define MEL_DEV_TYPE_EXT_Dsys (1<<1) 76 | #define MEL_DEV_TYPE_EXT_Mronly (1<<2)//"Read only" [M] system regs 77 | #define MEL_DEV_TYPE_EXT_Dronly (1<<3)//"Read only" [D] system regs 78 | #define MEL_DEV_TYPE_EXT_C32bit (1<<4)//32-bit counters (>= C200) 79 | 80 | unsigned int dtype_ext; 81 | 82 | int index; 83 | 84 | int const_int; //K,K2 85 | unsigned int const_uint; //H,H2 86 | float const_flt; //E 87 | #define MEL_STRING_MAX_LENGTH 32 88 | char const_str[MEL_STRING_MAX_LENGTH+1];//"..." 89 | int const_str_length; 90 | 91 | }PLCRegDevice; 92 | 93 | char* mel_get_device_name(unsigned int dev_type); 94 | unsigned int mel_get_device_code(unsigned int dev_type); 95 | unsigned int mel_get_device_type(unsigned int dev_code); 96 | unsigned int mel_approx_dtype_by_chars(char first,char second); 97 | 98 | char* mel_device2text(PLCRegDevice* dev,int* ptextsize); 99 | 100 | typedef struct tagPLCRegDeviceRange 101 | { 102 | int lowest; 103 | int highest; 104 | 105 | }PLCRegDeviceRange; 106 | 107 | int mel_wpg_dec_device (int cpuSeries,int cpuType,unsigned char* stream,int stream_size,PLCRegDevice* dev); 108 | int mel_wpg_enc_device (PLCRegDevice* dev,int cpuSeries,int cpuType,unsigned char* stream); 109 | 110 | //[..] + V/Zn 111 | int is_indexing_allowed(PLCRegDevice* reg,int cpuSeries,int cpuType); 112 | //Kn + [..] 113 | int is_linking_allowed(PLCRegDevice* reg,int cpuSeries,int cpuType); 114 | //[..] + .n 115 | int is_bitaccess_allowed(PLCRegDevice* reg,int cpuSeries,int cpuType); 116 | 117 | int is_it_VorZ(unsigned int dtype); 118 | 119 | #endif //__mel_wpg_device_h__ 120 | -------------------------------------------------------------------------------- /mel_wpg_fxcpu_fx3.c: -------------------------------------------------------------------------------- 1 | #include "mel_wpg.h" 2 | #include "mel_wpg_fxcpu_fx3.h" 3 | #include "mel_wpg_instr.h" 4 | #include //memset 5 | #include //free 6 | #include //printf 7 | 8 | #ifdef WIN32 9 | #pragma warning (disable : 4996) 10 | #endif 11 | 12 | /* returns: 1-ok,0-ng */ 13 | int mel_wpg_FXCPU_FX3_link_item(void* wpgx,WPG_Item* item) 14 | { 15 | int ret_code = 0;//ng by default 16 | 17 | WPG_FXCPU_FX3U* wpg = (WPG_FXCPU_FX3U*)wpgx; 18 | 19 | if (wpg && item) 20 | { 21 | //back link to last one 22 | item->prev = wpg->last; 23 | 24 | //link last one to new item 25 | if (item->prev) 26 | { 27 | item->prev->next = item; 28 | } 29 | //ending linked list 30 | item->next = 0; 31 | 32 | if (wpg->first == 0) 33 | { 34 | wpg->first = item; 35 | } 36 | //set new one as a last one 37 | wpg->last = item; 38 | 39 | //if(item->nops) printf("NOP added!!![%d]\n",wpg->steps); 40 | 41 | //update program sizes 42 | wpg->steps += item->steps; 43 | wpg->nop_steps += item->nops; 44 | 45 | //printf("%d\t%d\n",wpg->steps,wpg->nop_steps); 46 | 47 | ret_code = 1;//ok 48 | } 49 | 50 | return(ret_code); 51 | } 52 | 53 | /* returns: 1-ok,0-ng */ 54 | int mel_wpg_FXCPU_FX3_unlink_item(void* wpgx,WPG_Item* item) 55 | { 56 | int ret_code = 0;//ng by default 57 | 58 | WPG_FXCPU_FX3U* wpg = (WPG_FXCPU_FX3U*)wpgx; 59 | 60 | if (wpg && item) 61 | { 62 | int is_exist = 0; 63 | WPG_Item* item_t; 64 | 65 | //search for item 66 | item_t = wpg->first; 67 | while(item_t) 68 | { 69 | if (item_t == item) 70 | { 71 | is_exist = 1; break;//exit loop 72 | } 73 | item_t = item_t->next; 74 | }; 75 | 76 | //delete it from program if found 77 | if (is_exist) 78 | { 79 | //unlink it from previous 80 | if (item->prev) 81 | { 82 | item->prev->next = item->next; 83 | } 84 | else 85 | { 86 | //it is first item in list: update pointer to first one. 87 | wpg->first = item->next; 88 | } 89 | 90 | //unlink it from next one 91 | if (item->next) 92 | { 93 | item->next->prev = item->prev; 94 | } 95 | else 96 | { 97 | //it is last item in list: update pointer to last one. 98 | wpg->last = item->prev; 99 | } 100 | 101 | //reset self links 102 | item->prev = 0; 103 | item->next = 0; 104 | 105 | //update program sizes 106 | wpg->steps -= item->steps; 107 | wpg->nop_steps -= item->nops; 108 | 109 | ret_code = 1;//ok 110 | } 111 | } 112 | 113 | return(ret_code); 114 | } 115 | 116 | /* returns: done stream size > 0, error =0. */ 117 | int mel_wpg_FXCPU_FX3_decoder(unsigned char* stream,int enc_size,void* wpgx) 118 | { 119 | int done_size = 0; 120 | WPG_FXCPU_FX3U* wpg = (WPG_FXCPU_FX3U*)wpgx; 121 | 122 | if (enc_size > MEL_WPG_SUBHEADER_SIZE) 123 | { 124 | wpg->magic_num0 = (int)stream[0]|((int)stream[1]<<8); 125 | wpg->magic_num1 = (int)stream[2]|((int)stream[3]<<8); 126 | done_size += MEL_WPG_SUBHEADER_SIZE; 127 | 128 | wpg->steps = 0; 129 | wpg->nop_steps = 0; 130 | wpg->first = 0; 131 | wpg->last = 0; 132 | 133 | while(done_size < enc_size) 134 | { 135 | WPG_Item* item; 136 | int item_enc_size = 0; 137 | int steps = wpg->steps; 138 | int nop_steps; 139 | 140 | item = mel_wpg_item_decoder(MEL_PLC_SERIES_FXCPU,MEL_PLC_FXCPU_TYPE_FX3U_C, 141 | stream+done_size,enc_size-done_size,&item_enc_size,&steps,&nop_steps); 142 | done_size += item_enc_size; 143 | 144 | if (item && item->body) 145 | { 146 | //add item to linked list: 147 | if(!mel_wpg_FXCPU_FX3_link_item(wpg,item)) 148 | { 149 | //error: can't add item to program. 150 | done_size = 0; break;//exit from loop 151 | } 152 | 153 | if (item->itype == WPG_ITEM_TYPE_NOTE && item->prev) 154 | { 155 | if (item->prev->itype == WPG_ITEM_TYPE_INSTRUCTION) 156 | { 157 | //swap: {instruction,note} -> {note,instruction} 158 | mel_wpg_item_swap_data(item->prev,item); 159 | } 160 | } 161 | } 162 | else 163 | { 164 | //EOF or error: exit from loop 165 | break; 166 | } 167 | }; 168 | } 169 | 170 | return(done_size); 171 | } 172 | /* returns: done stream size > 0, error =0. */ 173 | int mel_wpg_FXCPU_FX3_encoder(void* wpgx,unsigned char* stream,int maxsteps) 174 | { 175 | int done_size = 0; 176 | WPG_FXCPU_FX3U* wpg = (WPG_FXCPU_FX3U*)wpgx; 177 | WPG_Item* item; 178 | void* last_swaped_note = 0; 179 | int steps_totally = 0; 180 | 181 | stream[0] = wpg->magic_num0&0xFF; 182 | stream[1] = (wpg->magic_num0>>8)&0xFF; 183 | stream[2] = wpg->magic_num1&0xFF; 184 | stream[3] = (wpg->magic_num1>>8)&0xFF; 185 | done_size += MEL_WPG_SUBHEADER_SIZE; 186 | 187 | item = wpg->first; 188 | 189 | while(item) 190 | { 191 | int item_enc_size = 0; 192 | int steps; 193 | int nop_steps; 194 | 195 | if (item->itype == WPG_ITEM_TYPE_NOTE && item->body != last_swaped_note && item->next) 196 | { 197 | if (item->next->itype == WPG_ITEM_TYPE_INSTRUCTION) 198 | { 199 | last_swaped_note = item->body; 200 | 201 | //make (temporary) copies and swap them: {note,instruction} - > {instruction,note} 202 | { 203 | WPG_Item item_a; 204 | WPG_Item item_b; 205 | 206 | memcpy(&item_a,item,sizeof(WPG_Item)); 207 | memcpy(&item_b,item->next,sizeof(WPG_Item)); 208 | 209 | //link to each other 210 | item_a.next = &item_b; 211 | item_b.prev = &item_a; 212 | mel_wpg_item_swap_data(&item_a,&item_b); 213 | //switch to the swapped copy 214 | item = &item_a; 215 | } 216 | } 217 | } 218 | 219 | item_enc_size = mel_wpg_item_encoder( item, 220 | MEL_PLC_SERIES_FXCPU, 221 | MEL_PLC_FXCPU_TYPE_FX3U_C, 222 | stream+done_size, 223 | &steps, 224 | &nop_steps); 225 | if (item_enc_size <= 0) 226 | { 227 | done_size = 0; 228 | break;//error: can't encode item 229 | } 230 | 231 | done_size += item_enc_size; 232 | steps_totally += steps; 233 | //wpg->nop_steps += nop_steps; 234 | 235 | if (steps_totally > maxsteps) 236 | { 237 | done_size = 0; 238 | goto __exit_point;//error: can't encode item 239 | } 240 | 241 | item = item->next; 242 | }; 243 | 244 | //printf("totally: %d, max: %d\n",steps_totally,maxsteps); 245 | 246 | #if 1 247 | //fill the rest by NOPs 248 | { 249 | WPG_Item item = {0}; 250 | WPG_Instruction instr = {0}; 251 | int nop_steps = 0; 252 | 253 | //set rest by NOPs (virtually) 254 | if (wpg->steps < maxsteps) 255 | { 256 | wpg->nop_steps += maxsteps - wpg->steps; 257 | wpg->steps += maxsteps - wpg->steps; 258 | } 259 | 260 | instr.opid = MEL_WPG_OpID_NOP; 261 | instr.steps = INSTRUCTIONS_METRIX_FXCPU[instr.opid].steps; 262 | instr.bitdepth = INSTRUCTIONS_METRIX_FXCPU[instr.opid].bitdepth; 263 | instr.exectype = INSTRUCTIONS_METRIX_FXCPU[instr.opid].exectype; 264 | instr.n_params = INSTRUCTIONS_METRIX_FXCPU[instr.opid].n_operands; 265 | 266 | item.itype = WPG_ITEM_TYPE_INSTRUCTION; 267 | item.body = &instr; 268 | item.size = sizeof(instr); 269 | item.steps= instr.steps; 270 | item.nops = 1; 271 | 272 | while(steps_totally < maxsteps) 273 | { 274 | int item_enc_size = 0; 275 | int steps; 276 | 277 | item_enc_size = mel_wpg_item_encoder( &item, 278 | MEL_PLC_SERIES_FXCPU, 279 | MEL_PLC_FXCPU_TYPE_FX3U_C, 280 | stream+done_size, 281 | &steps, 282 | &nop_steps); 283 | 284 | if (item_enc_size <= 0) 285 | { 286 | done_size = 0; 287 | goto __exit_point;//error: can't encode item 288 | } 289 | 290 | done_size += item_enc_size; 291 | steps_totally += steps; 292 | 293 | if (steps_totally > maxsteps) 294 | { 295 | done_size = 0;break;//error: program is too big 296 | } 297 | }; 298 | } 299 | #endif 300 | __exit_point: 301 | return(done_size); 302 | } 303 | 304 | /* returns: done stream size > 0, error =0. */ 305 | int mel_til_FXCPU_FX3_decoder(unsigned char* stream,int enc_size,void* wpgx,int maxsteps) 306 | { 307 | int done_size = 0; 308 | WPG_FXCPU_FX3U* wpg = (WPG_FXCPU_FX3U*)wpgx; 309 | 310 | if (enc_size > MEL_WPG_MIN_TIL_SIZE) 311 | { 312 | //int is_END_reached = 0; 313 | 314 | wpg->magic_num0 = 0x0004; 315 | wpg->magic_num1 = 0xFFFF; 316 | 317 | wpg->steps = 0; 318 | wpg->nop_steps = 0; 319 | wpg->first = 0; 320 | wpg->last = 0; 321 | 322 | while(done_size < enc_size) 323 | { 324 | WPG_Item welldone = {0}; 325 | int item_enc_size = 0; 326 | int steps = wpg->steps; 327 | int nop_steps; 328 | 329 | unsigned int stcode; 330 | unsigned int stcodeInstr; 331 | int firstbad_operand; 332 | int firstbad_device; 333 | char line[MEL_WPG_MAX_INSTR_TEXT_SIZE+1] = {0}; 334 | int line_dec_size; 335 | 336 | //get one line from ASCII stream 337 | item_enc_size = mel_til_get_line( stream + done_size,enc_size - done_size, 338 | line,&line_dec_size,MEL_WPG_MAX_INSTR_TEXT_SIZE); 339 | done_size += item_enc_size; 340 | 341 | //try to construct item from line 342 | stcode = mel_wpg_text2item(MEL_PLC_SERIES_FXCPU, 343 | MEL_PLC_FXCPU_TYPE_FX3U_C, 344 | line,line_dec_size, 345 | &stcodeInstr, 346 | &firstbad_operand, 347 | &firstbad_device, 348 | &steps, 349 | &nop_steps, 350 | &welldone 351 | ); 352 | if (stcode == ITEM_STATE_OK) 353 | { 354 | WPG_Item* item; 355 | //create new item 356 | item = calloc(1,sizeof(WPG_Item)); 357 | if (item) 358 | { 359 | //setup new item 360 | memcpy(item,&welldone,sizeof(WPG_Item)); 361 | 362 | //add item to linked list: 363 | if(!mel_wpg_FXCPU_FX3_link_item(wpg,item)) 364 | { 365 | //error: can't add item to program. 366 | done_size = 0; break;//exit from loop 367 | } 368 | 369 | /* 370 | if( item->itype == WPG_ITEM_TYPE_INSTRUCTION 371 | && ((WPG_Instruction*)item->body)->opid== MEL_WPG_OpID_END 372 | ) 373 | { 374 | is_END_reached = 1; 375 | } 376 | */ 377 | 378 | if (wpg->steps > maxsteps) 379 | { 380 | done_size = 0; break;//exit from loop 381 | } 382 | } 383 | else 384 | { 385 | //ITEM_STATE_BAD_NO_MEMORY 386 | done_size = 0; break;//exit from loop 387 | } 388 | } 389 | else 390 | { 391 | //stcode,stcodeInstr 392 | done_size = 0; break;//exit from loop 393 | } 394 | }; 395 | 396 | //set rest by NOPs (virtually) 397 | if (done_size > 0) 398 | { 399 | wpg->nop_steps += maxsteps - wpg->steps; 400 | wpg->steps += maxsteps - wpg->steps; 401 | } 402 | } 403 | 404 | return(done_size); 405 | } 406 | 407 | int mel_til_FXCPU_FX3_encoder(void* wpgx,unsigned char* stream) 408 | { 409 | int done_size = 0; 410 | WPG_FXCPU_FX3U* wpg = (WPG_FXCPU_FX3U*)wpgx; 411 | WPG_Item* item; 412 | 413 | item = wpg->first; 414 | while(item) 415 | { 416 | int item_enc_size = 0; 417 | char* til_line; 418 | 419 | til_line = mel_wpg_item2text(MEL_PLC_SERIES_FXCPU,MEL_PLC_FXCPU_TYPE_FX3U_C,item,&item_enc_size); 420 | if (item_enc_size <= 0) 421 | { 422 | done_size = 0; break;//error: can't encode item 423 | } 424 | memcpy(stream + done_size,til_line,item_enc_size); 425 | stream[done_size + item_enc_size + 0] = 0x0D; 426 | stream[done_size + item_enc_size + 1] = 0x0A; 427 | done_size += item_enc_size + 2; 428 | 429 | if( item->itype == WPG_ITEM_TYPE_INSTRUCTION 430 | && ((WPG_Instruction*)item->body)->opid== MEL_WPG_OpID_END 431 | ) 432 | { 433 | break;//exit from loop 434 | } 435 | 436 | item = item->next; 437 | }; 438 | return(done_size); 439 | } 440 | 441 | /* destroy wpg instance */ 442 | void mel_wpg_FXCPU_FX3_free(void* wpgx) 443 | { 444 | WPG_FXCPU_FX3U* wpg = (WPG_FXCPU_FX3U*)wpgx; 445 | 446 | if (wpg) 447 | { 448 | WPG_Item* item; 449 | 450 | item = wpg->first; 451 | 452 | while(item) 453 | { 454 | WPG_Item* tobedead = item; 455 | 456 | if (item->body) 457 | { 458 | free(item->body); 459 | } 460 | 461 | item = item->next; 462 | 463 | free(tobedead); 464 | }; 465 | 466 | free(wpg); 467 | } 468 | 469 | return; 470 | } 471 | 472 | -------------------------------------------------------------------------------- /mel_wpg_fxcpu_fx3.h: -------------------------------------------------------------------------------- 1 | #ifndef __mel_wpg_fxcpu_fx3u_h__ 2 | #define __mel_wpg_fxcpu_fx3u_h__ 3 | 4 | #include "mel_common.h" 5 | #include "mel_wpg_item.h" 6 | 7 | #define MEL_WPG_SUBHEADER_SIZE 4 8 | 9 | ////////////////////////////////////////////////////////////////////////// 10 | //EXPORT DATA STRUCTURE 11 | typedef struct tagWPG_FXCPU_FX3U 12 | { 13 | int magic_num0; 14 | int magic_num1; 15 | 16 | int steps; 17 | int nop_steps; 18 | 19 | WPG_Item* first; 20 | WPG_Item* last; 21 | 22 | }WPG_FXCPU_FX3U; 23 | ////////////////////////////////////////////////////////////////////////// 24 | 25 | /* returns: done stream size > 0, error =0. */ 26 | int mel_wpg_FXCPU_FX3_decoder(unsigned char* stream,int enc_size,void* wpgx); 27 | /* returns: done stream size > 0, error =0. */ 28 | int mel_til_FXCPU_FX3_decoder(unsigned char* stream,int enc_size,void* wpgx,int maxsteps); 29 | /* returns: done stream size > 0, error =0. */ 30 | int mel_wpg_FXCPU_FX3_encoder(void* wpgx,unsigned char* stream,int maxsteps); 31 | /* returns: done stream size > 0, error =0. */ 32 | int mel_til_FXCPU_FX3_encoder(void* wpgx,unsigned char* stream); 33 | /* destroy wpg instance */ 34 | void mel_wpg_FXCPU_FX3_free(void* wpgx); 35 | 36 | /* returns: 1-ok,0-ng */ 37 | int mel_wpg_FXCPU_FX3_link_item(void* wpgx,WPG_Item* item); 38 | /* returns: 1-ok,0-ng */ 39 | int mel_wpg_FXCPU_FX3_unlink_item(void* wpgx,WPG_Item* item); 40 | 41 | #endif /* __mel_wpg_fxcpu_fx3u_h__ */ 42 | -------------------------------------------------------------------------------- /mel_wpg_fxcpu_regs.c: -------------------------------------------------------------------------------- 1 | #include "mel_wpg_fxcpu_regs.h" 2 | 3 | #include //INT_MIN,MAX 4 | #include //FLT_MIN,MAX 5 | 6 | int set_dtype_ext_fxcpu(PLCRegDevice* dev,int cpuType) 7 | { 8 | int isok = 0;//by default: not applicable device type; 9 | 10 | //Filter applicable device types only 11 | if (dev->dtype & ( 12 | MEL_DEV_TYPE_M 13 | |MEL_DEV_TYPE_D 14 | |MEL_DEV_TYPE_C 15 | ) 16 | ) 17 | { 18 | int i_ext_bit = 0; 19 | 20 | isok = 1;//maybe 21 | dev->dtype_ext = 0; 22 | 23 | for(i_ext_bit = 0; i_ext_bit < 5; i_ext_bit++) 24 | { 25 | unsigned int dtype_base; 26 | unsigned int ext_type_curr;// = 1<dtype & dtype_base) 47 | { 48 | PLCRegDeviceRange* t_range = 0; 49 | PLCRegDeviceRange range = {0}; 50 | //get range of extended devices 51 | t_range = get_device_range_fxcpu(dtype_base,ext_type_curr,cpuType,&range); 52 | if (t_range) 53 | {//is it extended or not? 54 | if (dev->index >= range.lowest && dev->index <= range.highest) 55 | { 56 | //set "clean" base type 57 | dev->dtype = dtype_base; 58 | //set approved extended type 59 | dev->dtype_ext |= ext_type_curr; 60 | //set extended type 61 | switch(i_ext_bit) 62 | { 63 | case 1: 64 | case 3: 65 | //test is it read-only or not 66 | //TODO 67 | if (0) 68 | { 69 | dev->dtype_ext |= MEL_DEV_TYPE_EXT_Mronly; 70 | dev->dtype_ext |= MEL_DEV_TYPE_EXT_Dronly; 71 | } 72 | break; 73 | } 74 | } 75 | //else{//not system} 76 | }else{isok = 0; break;}//error: wrong dev->dtype! 77 | } 78 | } 79 | } 80 | 81 | return (isok); 82 | } 83 | 84 | //returns: 1-yes,0-no; 85 | int is_valid_E_device_fxcpu (PLCRegDevice* dev) 86 | { 87 | int is_valid = 0;//NG by default; 88 | 89 | //filter NaNs 90 | if (dev->const_flt == dev->const_flt) 91 | { 92 | double number = (double)((dev->const_flt < 0)? -dev->const_flt : dev->const_flt); 93 | 94 | //filter values by range 95 | if (number >= FLT_MIN && number <= FLT_MAX) 96 | { 97 | is_valid = 1; 98 | } 99 | } 100 | //else{//is NaN!} 101 | 102 | return(is_valid); 103 | } 104 | 105 | int is_valid_I_device_fxcpu (PLCRegDevice* dev,int cpuType) 106 | { 107 | int is_valid = 1;//OK by default; 108 | 109 | switch(dev->index) 110 | { 111 | //Input interrupt (interrupt triggered by external signal) 112 | case 0: //X000 I001 I000 113 | case 1: 114 | case 100://X001 I101 I100 115 | case 101: 116 | case 200://X002 I201 I200 117 | case 201: 118 | case 300://X003 I301 I300 119 | case 301: 120 | case 400://X004 I401 I400 121 | case 401: 122 | case 500://X005 I501 I500 123 | break; 124 | //Counter Interrupt - Interrupt Triggered by Counting Up of High-Speed Counter 125 | case 10: 126 | case 20: 127 | case 30: 128 | case 40: 129 | case 50: 130 | case 60: 131 | if(cpuType == MEL_PLC_FXCPU_TYPE_FX3G_C) 132 | { 133 | is_valid = 0; 134 | } 135 | break; 136 | 137 | default: 138 | //Timer interrupt (interrupt in constant cycle) 139 | if ( !(dev->index >= 610 && dev->index <= 699) 140 | && !(dev->index >= 710 && dev->index <= 799) 141 | && !(dev->index >= 810 && dev->index <= 899) 142 | ) 143 | { 144 | is_valid = 0; 145 | } 146 | } 147 | 148 | return(is_valid); 149 | } 150 | 151 | int is_device_in_range_fxcpu(PLCRegDevice* dev,int cpuType) 152 | { 153 | int isok = 1; 154 | PLCRegDeviceRange* t_range; 155 | PLCRegDeviceRange range={0}; 156 | 157 | if (dev->dtype & ( MEL_DEV_TYPE_E 158 | |MEL_DEV_TYPE_H2 159 | |MEL_DEV_TYPE_I 160 | ) 161 | ) 162 | { 163 | if (dev->dtype & MEL_DEV_TYPE_I) 164 | { 165 | isok = is_valid_I_device_fxcpu(dev,cpuType); 166 | } 167 | else 168 | if (dev->dtype & MEL_DEV_TYPE_E) 169 | { 170 | isok = is_valid_E_device_fxcpu(dev); 171 | } 172 | /* 173 | else 174 | if (dev->dtype & MEL_DEV_TYPE_H2) 175 | { 176 | isok = 1;/always OK 177 | } 178 | */ 179 | } 180 | else 181 | { 182 | t_range = get_device_range_fxcpu( dev->dtype,dev->dtype_ext,cpuType,&range); 183 | if (t_range) 184 | { 185 | if (dev->dtype & (MEL_DEV_TYPE_K | MEL_DEV_TYPE_H)) 186 | { 187 | if (dev->dtype & MEL_DEV_TYPE_K) 188 | { 189 | int number = dev->const_int; 190 | if (number < range.lowest || number > range.highest) 191 | { 192 | // if (get_device_range_fxcpu(MEL_DEV_TYPE_K2,0,cpuType,&range)) 193 | // { 194 | // if (number < range.lowest || number > range.highest) 195 | // { 196 | // isok = 0;//impossible 197 | // } 198 | // else 199 | // { 200 | // //too big for 16-bit K, extend to 32-bit type: 201 | // dev->dtype = MEL_DEV_TYPE_K2; 202 | // } 203 | // } 204 | //too big for 16-bit K, extend to 32-bit type: 205 | dev->dtype = MEL_DEV_TYPE_K2; 206 | } 207 | } 208 | if (dev->dtype & MEL_DEV_TYPE_H) 209 | { 210 | unsigned int number = dev->const_uint; 211 | if (/*number < (unsigned int)range.lowest ||*/ number > (unsigned int)range.highest) 212 | { 213 | //too big for 16-bit H, extend to 32-bit type: 214 | dev->dtype = MEL_DEV_TYPE_H2; 215 | } 216 | } 217 | } 218 | else 219 | { 220 | if (dev->index < range.lowest || dev->index > range.highest) 221 | { 222 | isok = 0; 223 | } 224 | } 225 | } 226 | else 227 | { 228 | isok = 0;//unknown device type! 229 | } 230 | } 231 | 232 | return(isok); 233 | } 234 | 235 | PLCRegDeviceRange* get_device_range_fxcpu(unsigned int dtype,unsigned int dtype_ext,int cpuType,PLCRegDeviceRange* range) 236 | { 237 | //not supported by default 238 | PLCRegDeviceRange* t_range = 0; 239 | range->lowest = 0; 240 | range->highest = 0; 241 | 242 | if (//Filter devices with CPU-specific ranges 243 | !(dtype & ( 244 | MEL_DEV_TYPE_X 245 | |MEL_DEV_TYPE_Y 246 | |MEL_DEV_TYPE_T 247 | |MEL_DEV_TYPE_R 248 | |MEL_DEV_TYPE_P 249 | |MEL_DEV_TYPE_ER 250 | |MEL_DEV_TYPE_bI 251 | |MEL_DEV_TYPE_Un|MEL_DEV_TYPE_Gn 252 | |MEL_DEV_TYPE_STR 253 | ) 254 | ) 255 | ) 256 | { //COMMON RANGES FOR ALL CPUs 257 | 258 | if (dtype & MEL_DEV_TYPE_M) 259 | { 260 | if (dtype_ext & MEL_DEV_TYPE_EXT_Msys) 261 | { 262 | range->lowest = 8000; 263 | range->highest = 8511; 264 | } 265 | else 266 | { 267 | range->lowest = 0; 268 | range->highest = 7679; 269 | } 270 | } 271 | 272 | if (dtype & MEL_DEV_TYPE_D) 273 | { 274 | if (dtype_ext & MEL_DEV_TYPE_EXT_Dsys) 275 | { 276 | range->lowest = 8000; 277 | range->highest = 8511; 278 | } 279 | else 280 | { 281 | range->lowest = 0; 282 | range->highest = 7999; 283 | } 284 | } 285 | 286 | if (dtype_ext & MEL_DEV_TYPE_C) 287 | { 288 | if (dtype_ext & MEL_DEV_TYPE_EXT_C32bit) 289 | { 290 | range->lowest = 200; 291 | range->highest = 255; 292 | } 293 | else 294 | { 295 | range->lowest = 0; 296 | range->highest = 199; 297 | } 298 | } 299 | 300 | if (dtype & MEL_DEV_TYPE_S) 301 | { 302 | range->lowest = 0; 303 | range->highest = 4095; 304 | } 305 | 306 | if (dtype & (MEL_DEV_TYPE_N) 307 | ) 308 | { 309 | range->lowest = 0; 310 | range->highest = 7; 311 | } 312 | 313 | if (dtype & ( MEL_DEV_TYPE_V 314 | |MEL_DEV_TYPE_VI 315 | |MEL_DEV_TYPE_Z 316 | |MEL_DEV_TYPE_ZI 317 | ) 318 | ) 319 | { 320 | range->lowest = 0; 321 | range->highest = 7; 322 | } 323 | 324 | if (dtype & MEL_DEV_TYPE_Kn) 325 | { 326 | range->lowest = 1; 327 | range->highest = 8; 328 | } 329 | 330 | if (dtype & MEL_DEV_TYPE_K) 331 | { 332 | range->lowest = -32768; 333 | range->highest = +32767; 334 | } 335 | if (dtype & MEL_DEV_TYPE_K2) 336 | { 337 | range->lowest = INT_MIN; 338 | range->highest = INT_MAX; 339 | } 340 | 341 | if (dtype & MEL_DEV_TYPE_H) 342 | { 343 | range->lowest = 0; 344 | range->highest = 0xFFFF; 345 | } 346 | } 347 | else 348 | { 349 | switch(cpuType) 350 | { 351 | case MEL_PLC_FXCPU_TYPE_FX3U_C: 352 | 353 | if (dtype & MEL_DEV_TYPE_X) 354 | { 355 | range->lowest = 0; 356 | range->highest = 247; 357 | } 358 | 359 | if (dtype & MEL_DEV_TYPE_Y) 360 | { 361 | range->lowest = 0; 362 | range->highest = 247; 363 | } 364 | 365 | if (dtype & MEL_DEV_TYPE_T) 366 | { 367 | range->lowest = 0; 368 | range->highest = 511; 369 | } 370 | 371 | if (dtype & (MEL_DEV_TYPE_R|MEL_DEV_TYPE_ER)) 372 | { 373 | range->lowest = 0; 374 | range->highest = 32767; 375 | } 376 | 377 | if (dtype & MEL_DEV_TYPE_P) 378 | { 379 | range->lowest = 0; 380 | range->highest = 4095; 381 | } 382 | 383 | if (dtype & MEL_DEV_TYPE_bI) 384 | { 385 | range->lowest = 0; 386 | range->highest = 0xF; 387 | } 388 | 389 | if (dtype & (MEL_DEV_TYPE_Un)) 390 | { 391 | range->lowest = 0; 392 | range->highest = 7; 393 | } 394 | 395 | if (dtype & MEL_DEV_TYPE_Gn) 396 | { 397 | range->lowest = 0; 398 | range->highest = 32766; 399 | } 400 | 401 | if (dtype & MEL_DEV_TYPE_STR) 402 | { 403 | range->lowest = 0; 404 | range->highest = 32; 405 | } 406 | 407 | break; 408 | 409 | case MEL_PLC_FXCPU_TYPE_FX3G_C: 410 | 411 | if (dtype & MEL_DEV_TYPE_X) 412 | { 413 | range->lowest = 0; 414 | range->highest = 127; 415 | } 416 | if (dtype & MEL_DEV_TYPE_Y) 417 | { 418 | range->lowest = 0; 419 | range->highest = 127; 420 | } 421 | 422 | if (dtype & MEL_DEV_TYPE_T) 423 | { 424 | range->lowest = 0; 425 | range->highest = 319; 426 | } 427 | 428 | if (dtype & (MEL_DEV_TYPE_R|MEL_DEV_TYPE_ER)) 429 | { 430 | range->lowest = 0; 431 | range->highest = 23999; 432 | } 433 | 434 | if (dtype & MEL_DEV_TYPE_P) 435 | { 436 | range->lowest = 0; 437 | range->highest = 2047; 438 | } 439 | 440 | 441 | break; 442 | } 443 | } 444 | //return non-zero pointer if range is not empty; 445 | if (range->lowest + range->highest) 446 | { 447 | t_range = range; 448 | } 449 | return(t_range); 450 | } 451 | 452 | #if 0 453 | //M 454 | General dtype 455 | latched (battery backed) dtype 456 | Fixed latched (battery backed) dtype 457 | Special dtype 458 | Fixed latched (EEPROM keep) dtype 459 | //S 460 | Initial state dtype 461 | General dtype 462 | Latched (battery backed) dtype 463 | Fixed latched (battery backed) dtype 464 | Annunciator dtype 465 | Initial state dtype (EEPROM keep) 466 | Fixed latched (EEPROM keep) dtype 467 | Annunciator dtype (EEPROM keep) 468 | General dtype 469 | //T 470 | For 100 ms pulses 0.1 to 3276.7 sec 471 | For 10 ms pulses 0.01 to 327.67 sec 472 | Retentive dtype for 1 ms pulses 0.001 to 32.767 sec (battery backed) 473 | Retentive dtype for 100 ms pulses 0.1 to 3276.7 sec (battery backed) 474 | For 1 ms pulses 0.001 to 32.767 sec 475 | Retentive dtype for 1 ms pulses 0.001 to 32.767 sec (EEPROM keep) 476 | Retentive dtype for 100 ms pulses 0.1 to 3276.7 sec (EEPROM keep) 477 | Potentiometer dtype 0 to 255 (numeric value) 478 | //C 479 | 16-bit up counter Counting range: 0 to 32767 480 | 32-bit bi-directional counter Counting range: ?2,147,483,648 to +2,147,483,647 481 | -- 482 | General dtype 483 | Latched (battery backed) dtype (protected by battery against power failure) 484 | Latched (EEPROM keep) dtype 485 | -- 486 | High-Speed Counters: 487 | 1-phase 1-count input 488 | 1-phase 2-count input 489 | 2-phase 2-count input 490 | 491 | //D 492 | General dtype 493 | Latched (battery backed) dtype (backed up by battery against power failure) 494 | Fixed latched (battery backed) dtype (backed up by battery against power failure) 495 | Special dtype 496 | File registers (latched (battery backed) dtype) 497 | Latched dtype (EEPROM keep) 498 | File registers (latched (EEPROM keep) dtype) 499 | 500 | //R 501 | Extension register (R) (latched [battery backed] dtype) 502 | Extension file register (ER) (file dtype) 503 | Extension register (R) (General dtype) 504 | 505 | #endif 506 | -------------------------------------------------------------------------------- /mel_wpg_fxcpu_regs.h: -------------------------------------------------------------------------------- 1 | #ifndef __mel_wpg_fxcpu_regs_h__ 2 | #define __mel_wpg_fxcpu_regs_h__ 3 | 4 | #include "mel_common.h" 5 | #include "mel_wpg_device.h" 6 | 7 | //returns: 0 - failure: can't set (not applicable device type), 1 - successfully done; 8 | //useful only for: M,D,C 9 | int set_dtype_ext_fxcpu(PLCRegDevice* dev, // IN(dtype,index) / OUT (dtype,dtype_ext); 10 | int cpuType // IN 11 | ); 12 | 13 | /* 14 | returns: 0 - failure: can't get (not applicable device type), !0 - successfully done; 15 | 16 | unsigned int dtype, // IN 17 | unsigned int dtype_ext, // IN 18 | int cpuType, // IN 19 | PLCRegDeviceRange* range // OUT 20 | 21 | WARNING: 22 | 23 | do not apply for E,H2,I ! 24 | 25 | */ 26 | PLCRegDeviceRange* get_device_range_fxcpu( unsigned int dtype, // IN 27 | unsigned int dtype_ext, // IN 28 | int cpuType, // IN 29 | PLCRegDeviceRange* range // OUT 30 | ); 31 | /* 32 | returns: 0 - out of range; 1- within range; 33 | PLCRegDevice* dev, //IN(dtype,index,const_int,_uint,_flt) / OUT (dtype); 34 | int cpuType //IN 35 | */ 36 | int is_device_in_range_fxcpu( PLCRegDevice* dev, //IN(dtype,index,const_int,_uint,_flt) / OUT (dtype) 37 | int cpuType //IN 38 | ); 39 | 40 | //returns: 1-yes,0-no; 41 | int is_valid_E_device_fxcpu (PLCRegDevice* dev); 42 | int is_valid_I_device_fxcpu (PLCRegDevice* dev,int cpuType); 43 | 44 | #endif //__mel_wpg_fxcpu_regs_h__ 45 | -------------------------------------------------------------------------------- /mel_wpg_instr.h: -------------------------------------------------------------------------------- 1 | #ifndef __mel_wpg_opcodes_h__ 2 | #define __mel_wpg_opcodes_h__ 3 | 4 | #include "mel_wpg_item.h" 5 | #include "mel_wpg_device.h" 6 | #include "mel_wpg_tables.h" 7 | 8 | typedef struct tagWPG_Operand 9 | { 10 | #define MEL_OTYPE_EXT_KnM (1<<0) //->MEL_WPG_OPERAND_ATTRIB_LINKED 11 | #define MEL_OTYPE_EXT_KnS (1<<1) //->MEL_WPG_OPERAND_ATTRIB_LINKED 12 | #define MEL_OTYPE_EXT_KnX (1<<2) //->MEL_WPG_OPERAND_ATTRIB_LINKED 13 | #define MEL_OTYPE_EXT_KnY (1<<3) //->MEL_WPG_OPERAND_ATTRIB_LINKED 14 | 15 | unsigned int otype;//bit encoded composit operand type (based on included devices); 16 | 17 | #define MEL_WPG_MAX_NDEVS_PER_OPERAND 3 18 | int devs_count; 19 | PLCRegDevice devs[MEL_WPG_MAX_NDEVS_PER_OPERAND]; 20 | 21 | #define MEL_WPG_OPERAND_ATTRIB_INDEXED 1 //Vn,Zn 22 | #define MEL_WPG_OPERAND_ATTRIB_LINKED 2 //Kn 23 | #define MEL_WPG_OPERAND_ATTRIB_BITACCESS 4 //.b 24 | #define MEL_WPG_OPERAND_ATTRIB_UNITACCESS 8 //Un\Gm 25 | unsigned int attribs;//used by instruction operands validation (comparing with WPGOperandRecord.attribs_allowed); 26 | 27 | }WPG_Operand; 28 | 29 | typedef struct tagWPG_Instruction 30 | { 31 | int opid; 32 | int steps; 33 | unsigned int bitdepth; 34 | unsigned int exectype; 35 | 36 | WPG_Operand params[MEL_INSTRUCT_OPERANDS_MAX]; 37 | int n_params; 38 | unsigned int attribs;//bitwise accumulator of all params[i].attribs; -> used by steps calculation; 39 | 40 | }WPG_Instruction; 41 | 42 | WPG_Item* mel_wpg_dec_instruction (int cpuSeries,int cpuType,unsigned char* stream,int stream_size,int* psizedone,int* psteps); 43 | int mel_wpg_enc_instruction (WPG_Item* item,int cpuSeries,int cpuType,unsigned char* stream,int* psteps); 44 | 45 | #define MEL_WPG_OPCODE_SIZE_NETTO_MIN 0 46 | #define MEL_WPG_OPCODE_SIZE_NETTO_MAX 4 47 | 48 | //returns: (!0)-success; 0-failure: unknown code 49 | int mel_wpg_instr_setup_by_opcode( unsigned char* enc_code,int code_size,WPG_Instruction* instr); 50 | //returns: opcode's length in bytes; >=0 - success; <0 - failure: unknown opid 51 | int mel_wpg_instr_make_opcode(WPG_Instruction* instr,unsigned char* opcode_bytes); 52 | 53 | //works with correct instructions only (must be validated before calling!) 54 | int mel_wpg_instr_steps(WPG_Instruction* instr); 55 | 56 | enum 57 | { 58 | INSTR_STATE_OK = 0, 59 | INSTR_STATE_BAD_TOOSHORT, 60 | INSTR_STATE_BAD_TOOLONG, //index of first wrong char -> *pfirstbad 61 | INSTR_STATE_BAD_NAME, 62 | INSTR_STATE_BAD_LESSNOPERANDS, //min value of n_operands -> *pfirstbad 63 | INSTR_STATE_BAD_MORENOPERANDS, //index of last operand -> *pfirstbad 64 | 65 | INSTR_STATE_BAD_DEVICE_TYPE, //index of operand -> *pfirstbad 66 | INSTR_STATE_BAD_DEVICE_TYPE_EXT, //index of operand -> *pfirstbad 67 | INSTR_STATE_BAD_DEVICE_INDEX, //index of operand -> *pfirstbad 68 | 69 | INSTR_STATE_BAD_DEVICE_INDEXING, //index of operand -> *pfirstbad 70 | INSTR_STATE_BAD_DEVICE_LINKING, //index of operand -> *pfirstbad 71 | INSTR_STATE_BAD_DEVICE_BITACCESSING, //index of operand -> *pfirstbad 72 | INSTR_STATE_BAD_DEVICE_UNITACCESSING, //index of operand -> *pfirstbad 73 | 74 | INSTR_STATE_BAD_DEVICE_COUNT, //index of operand -> *pfirstbad 75 | 76 | INSTR_STATE_BAD_NO_STRCLOSING, //"..." -> "... 77 | INSTR_STATE_BAD_NO_SLASH, //U..\G.. -> U..G.. 78 | INSTR_STATE_BAD_NO_G, //U..\G.. -> U..G.. 79 | INSTR_STATE_BAD_CHAR //not JIS8 80 | }; 81 | unsigned int mel_wpg_text2instr(int cpuSeries,int cpuType,char* text,int textsize, 82 | int* pfirstbad_operand,int* pfirstbad_device, 83 | int* psteps, 84 | WPG_Instruction* welldone); 85 | char* mel_wpg_instr2text(int cpuSeries,int cpuType,WPG_Instruction* instr,int* ptextsize); 86 | 87 | void mel_wpg_printf_opcodes_FXCPU(void); 88 | void mel_wpg_generate_metrix_FXCPU(void); 89 | void mel_wpg_printf_metrix_FXCPU(void); 90 | 91 | #endif //__mel_wpg_opcodes_h__ 92 | -------------------------------------------------------------------------------- /mel_wpg_item.c: -------------------------------------------------------------------------------- 1 | #include "mel_wpg_item.h" 2 | #include "mel_wpg_instr.h" 3 | #include "mel_wpg_device.h" 4 | 5 | #include //printf,sprintf 6 | #include //calloc 7 | #include //memset 8 | 9 | #ifdef WIN32 10 | #pragma warning (disable : 4996) 11 | #endif 12 | 13 | WPG_Item* mel_wpg_item_decoder (int cpuSeries,int cpuType,unsigned char* stream,int stream_size,int* psizedone,int* psteps,int* pnopsteps) 14 | { 15 | WPG_Item* item = 0; 16 | int size_done = 0; 17 | int steps = 0; 18 | int nops = 0; 19 | 20 | if (stream_size > 0) 21 | { 22 | int size_brutto; 23 | 24 | size_brutto = stream[0]; 25 | 26 | if (size_brutto <= stream_size) 27 | { 28 | if (size_brutto == stream[size_brutto-1]) 29 | { 30 | int size_netto = size_brutto - 2; 31 | int code; 32 | 33 | code = stream[1]; 34 | 35 | switch(code) 36 | { 37 | case WPG_CODE_STATEMENT: 38 | case WPG_CODE_NOTE: 39 | 40 | item = calloc(1,sizeof(WPG_Item)); 41 | if (item) 42 | { 43 | int text_size = size_netto - 2; 44 | item->itype = (code==WPG_CODE_STATEMENT)? WPG_ITEM_TYPE_STATEMENT 45 | :WPG_ITEM_TYPE_NOTE; 46 | item->size = text_size; 47 | item->body = calloc(1,item->size+1); 48 | memcpy(item->body,stream+3,item->size); 49 | *((char*)item->body + item->size) = 0x00; 50 | } 51 | size_done = size_brutto; 52 | break; 53 | 54 | case WPG_CODE_LABEL: 55 | /* 56 | if (size_netto > 1 ) 57 | { 58 | if (stream[2]==0x02) 59 | { 60 | //long: 2 bytes index 61 | } 62 | } 63 | */ 64 | size_done += size_brutto; 65 | size_brutto = stream[size_done + 0]; 66 | if (size_brutto <= stream_size-size_done) 67 | { 68 | if (size_brutto == stream[size_done + size_brutto - 1]) 69 | { 70 | size_netto = size_brutto - 2; 71 | 72 | item = calloc(1,sizeof(WPG_Item)); 73 | if (item) 74 | { 75 | code = stream[size_done + 1]; 76 | switch(code) 77 | { 78 | case MEL_DEV_CODE_P: 79 | { 80 | WPG_Label* label; 81 | 82 | item->itype = WPG_ITEM_TYPE_LABEL; 83 | item->size = sizeof(WPG_Label); 84 | item->body = calloc(1,item->size); 85 | if(item->body) 86 | { 87 | label = item->body; 88 | label->is_long = (size_netto==3); 89 | label->index = (label->is_long)? (int)stream[size_done+2]|((int)stream[size_done+3]<<8) 90 | : stream[size_done+2]; 91 | 92 | steps = (label->is_long)? 2:1; 93 | } 94 | } 95 | break; 96 | case MEL_DEV_CODE_I: 97 | { 98 | WPG_Interrupt* interr; 99 | 100 | item->itype = WPG_ITEM_TYPE_INTERRUPT; 101 | item->size = sizeof(WPG_Interrupt); 102 | item->body = calloc(1,item->size); 103 | if (item->body) 104 | { 105 | interr = item->body; 106 | interr->index = (size_netto==3)? (int)stream[size_done+2]|((int)stream[size_done+3]<<8) 107 | : stream[size_done+2]; 108 | steps = 1; 109 | } 110 | } 111 | break; 112 | } 113 | } 114 | } 115 | } 116 | size_done += size_brutto; 117 | break; 118 | 119 | default: 120 | { 121 | int instr_whole_size = size_brutto; 122 | 123 | steps = *psteps; 124 | //instruction and operands (if any) 125 | item = mel_wpg_dec_instruction (cpuSeries,cpuType,stream,stream_size,&instr_whole_size,&steps); 126 | size_done = instr_whole_size; 127 | if (item) 128 | { 129 | WPG_Instruction* ins = item->body; 130 | 131 | if (ins->opid == MEL_WPG_OpID_NOP) 132 | { 133 | nops++; 134 | } 135 | } 136 | } 137 | break; 138 | } 139 | } 140 | } 141 | } 142 | if(item) 143 | { 144 | item->steps = steps; 145 | item->nops = nops*INSTRUCTIONS_METRIX_FXCPU[MEL_WPG_OpID_NOP].steps; 146 | } 147 | *psizedone = size_done; 148 | *psteps = steps; 149 | *pnopsteps = nops*INSTRUCTIONS_METRIX_FXCPU[MEL_WPG_OpID_NOP].steps; 150 | return(item); 151 | } 152 | 153 | int mel_wpg_item_encoder (WPG_Item* item,int cpuSeries,int cpuType,unsigned char* stream,int* psteps,int* pnopsteps) 154 | { 155 | int enc_size = 0; 156 | int size_netto = 0; 157 | int steps = 0; 158 | int nops = 0; 159 | 160 | switch(item->itype) 161 | { 162 | case WPG_ITEM_TYPE_INSTRUCTION: 163 | { 164 | int instr_whole_size; 165 | 166 | //instruction and operands (if any) 167 | instr_whole_size = mel_wpg_enc_instruction (item,cpuSeries,cpuType,stream,&steps); 168 | enc_size = instr_whole_size; 169 | { 170 | WPG_Instruction* ins = item->body; 171 | 172 | if (ins->opid == MEL_WPG_OpID_NOP) 173 | { 174 | nops++; 175 | } 176 | } 177 | } 178 | break; 179 | 180 | case WPG_ITEM_TYPE_STATEMENT: 181 | case WPG_ITEM_TYPE_NOTE: 182 | stream[1] = (item->itype==WPG_ITEM_TYPE_NOTE)? WPG_CODE_NOTE:WPG_CODE_STATEMENT; 183 | stream[2] = 0x00; 184 | memcpy(stream+3,item->body,item->size); 185 | size_netto = item->size + 2; 186 | break; 187 | 188 | case WPG_ITEM_TYPE_LABEL: 189 | { 190 | WPG_Label* label = (WPG_Label*)item->body; 191 | int size_brutto; 192 | 193 | stream[1] = WPG_CODE_LABEL; 194 | if (label->is_long) 195 | { 196 | size_netto = 2; 197 | stream[2] = 0x02; 198 | } 199 | else 200 | { 201 | size_netto = 1; 202 | } 203 | 204 | size_brutto = size_netto + 2; 205 | stream[0] = size_brutto; 206 | stream[size_brutto-1] = stream[0]; 207 | 208 | enc_size = size_brutto; 209 | 210 | stream[enc_size+1] = MEL_DEV_CODE_P; 211 | if(label->is_long) 212 | { 213 | stream[enc_size+2] = label->index&0xFF; 214 | stream[enc_size+3] = (label->index>>8)&0xFF; 215 | size_netto = 3; 216 | 217 | steps = 2; 218 | } 219 | else 220 | { 221 | stream[enc_size+2] = label->index&0xFF; 222 | size_netto = 2; 223 | 224 | steps = 1; 225 | } 226 | size_brutto = size_netto + 2; 227 | stream[enc_size+0] = size_brutto; 228 | stream[enc_size+size_brutto-1] = stream[enc_size+0]; 229 | 230 | enc_size += size_brutto; 231 | } 232 | break; 233 | 234 | case WPG_ITEM_TYPE_INTERRUPT: 235 | { 236 | WPG_Interrupt* interr = (WPG_Interrupt*)item->body; 237 | int size_brutto; 238 | 239 | stream[1] = WPG_CODE_LABEL; 240 | size_netto = 1; 241 | size_brutto = size_netto + 2; 242 | stream[0] = size_brutto; 243 | stream[size_brutto-1] = stream[0]; 244 | 245 | enc_size = size_brutto; 246 | 247 | stream[enc_size+1] = MEL_DEV_CODE_I; 248 | 249 | if(interr->index > 255) 250 | { 251 | stream[enc_size+2] = interr->index&0xFF; 252 | stream[enc_size+3] = (interr->index>>8)&0xFF; 253 | size_netto = 3; 254 | } 255 | else 256 | { 257 | stream[enc_size+2] = interr->index&0xFF; 258 | size_netto = 2; 259 | } 260 | 261 | size_brutto = size_netto + 2; 262 | stream[enc_size+0] = size_brutto; 263 | stream[enc_size+size_brutto-1] = stream[enc_size+0]; 264 | 265 | enc_size += size_brutto; 266 | steps = 1; 267 | } 268 | break; 269 | } 270 | if (enc_size==0) 271 | { 272 | if (size_netto > 0) 273 | { 274 | int size_brutto = size_netto + 2; 275 | 276 | stream[0] = size_brutto; 277 | stream[size_brutto-1] = stream[0]; 278 | enc_size = size_brutto; 279 | } 280 | } 281 | //printf("enc: itype[%d]\t%d bytes\n",item->itype,enc_size); 282 | *psteps = steps; 283 | *pnopsteps = nops*INSTRUCTIONS_METRIX_FXCPU[MEL_WPG_OpID_NOP].steps; 284 | return(enc_size); 285 | } 286 | 287 | //TXT -> ITEM {INSTRUCTION{OPERAND(S){DEVICE(S)}},STATEMENT,NOTE,LABEL,INTERRUPT} 288 | unsigned int mel_wpg_text2item(int cpuSeries,int cpuType,char* text,int textsize, 289 | unsigned int* pinstrerrcode,int* pfirstbad_operand,int* pfirstbad_device, 290 | int* psteps,int* pnopsteps, 291 | WPG_Item* welldone) 292 | { 293 | unsigned int stcode = ITEM_STATE_BAD_TOOSHORT; 294 | int steps = 0; 295 | int nops = 0; 296 | 297 | if (textsize >= 1) 298 | { 299 | switch(text[0]) 300 | { 301 | case '*'://STATEMENT or NOTE 302 | if (textsize >= 2) 303 | { 304 | int dataoffset; 305 | if (text[1]!='<') 306 | {//STATEMENT 307 | if (textsize <= MEL_WPG_MAX_STATEMENT_TEXT_SIZE+1) 308 | { 309 | dataoffset = 1; 310 | welldone->itype = WPG_ITEM_TYPE_STATEMENT; 311 | stcode = ITEM_STATE_OK; 312 | } 313 | else 314 | { 315 | //stcode = ITEM_STATE_BAD_STATEMENT; 316 | stcode = ITEM_STATE_BAD_TOOLONG; 317 | } 318 | } 319 | else 320 | { 321 | //NOTE 322 | if (textsize > 2) 323 | { 324 | if (textsize <= MEL_WPG_MAX_NOTE_TEXT_SIZE+2) 325 | { 326 | dataoffset = 2; 327 | welldone->itype = WPG_ITEM_TYPE_NOTE; 328 | stcode = ITEM_STATE_OK; 329 | } 330 | else 331 | { 332 | //stcode = ITEM_STATE_BAD_NOTE; 333 | stcode = ITEM_STATE_BAD_TOOLONG; 334 | } 335 | } 336 | } 337 | if (stcode == ITEM_STATE_OK) 338 | { 339 | welldone->size = textsize - dataoffset; 340 | welldone->body = calloc(1,welldone->size+1); 341 | if (welldone->body) 342 | { 343 | memcpy(welldone->body,text+dataoffset,welldone->size); 344 | *((char*)welldone->body + welldone->size) = 0x00; 345 | } 346 | else 347 | { 348 | stcode = ITEM_STATE_BAD_NO_MEMORY; 349 | } 350 | } 351 | } 352 | break; 353 | 354 | case 'I'://INTERRUPT or INSTRUCTION 355 | case 'i': 356 | case 'P'://LABEL or INSTRUCTION 357 | case 'p': 358 | if (textsize > 1) 359 | { 360 | stcode = ITEM_STATE_BAD_UNKNOWN; 361 | //try to separate labels/interrupts and 'P/p'-instructions 362 | //in case of labels/interrupts: all characters, starting from second one, must be decimal digits 363 | if (text[1] >= '0' && text[1] <= '9') 364 | { 365 | int is_wrong_char = 0; 366 | int i; 367 | //...all characters, starting from second one, must be decimal digits 368 | i = 2; 369 | while(i < textsize) 370 | { 371 | if (!(text[i] >= '0' && text[i] <= '9')) 372 | { 373 | is_wrong_char = 1; 374 | break; 375 | } 376 | i++; 377 | }; 378 | 379 | if (!is_wrong_char) 380 | { 381 | long int val; 382 | char* endptr = 0; 383 | 384 | //in case of labels/interrupts: second character is digit [0-9] 385 | errno = 0; 386 | val = strtol(text+1,&endptr,10); 387 | if (errno == 0) 388 | { 389 | if (endptr!=text) 390 | { 391 | if (*endptr == '\0')//"one parameter" argument 392 | { 393 | if ( text[0] == 'I' 394 | || text[0] == 'i') 395 | { //INTERRUPT 396 | if (val >= 0) 397 | { 398 | stcode = ITEM_STATE_OK; 399 | welldone->itype = WPG_ITEM_TYPE_INTERRUPT; 400 | welldone->size = sizeof(WPG_Interrupt); 401 | welldone->body = calloc(1,welldone->size); 402 | if (welldone->body) 403 | { 404 | WPG_Interrupt* interr; 405 | interr = welldone->body; 406 | interr->index = val; 407 | steps = 1; 408 | } 409 | else 410 | { 411 | stcode = ITEM_STATE_BAD_NO_MEMORY; 412 | } 413 | } 414 | else 415 | { 416 | 417 | stcode = ITEM_STATE_BAD_INTERRUPT; 418 | } 419 | } 420 | else 421 | { //LABEL 422 | if (val >= 0) 423 | { 424 | stcode = ITEM_STATE_OK; 425 | welldone->itype = WPG_ITEM_TYPE_LABEL; 426 | welldone->size = sizeof(WPG_Label); 427 | welldone->body = calloc(1,welldone->size); 428 | if (welldone->body) 429 | { 430 | WPG_Label* label; 431 | label = welldone->body; 432 | label->index = val; 433 | label->is_long = (val > 255)? 1:0; 434 | steps = (label->is_long)? 2:1; 435 | } 436 | else 437 | { 438 | stcode = ITEM_STATE_BAD_NO_MEMORY; 439 | } 440 | } 441 | else 442 | { 443 | 444 | stcode = ITEM_STATE_BAD_LABEL; 445 | } 446 | } 447 | } 448 | } 449 | } 450 | } 451 | else 452 | { 453 | if ( text[0] == 'I' 454 | || text[0] == 'i') 455 | { 456 | stcode = ITEM_STATE_BAD_INTERRUPT; 457 | } 458 | else 459 | { 460 | stcode = ITEM_STATE_BAD_LABEL; 461 | } 462 | 463 | } 464 | } 465 | else 466 | { 467 | goto __try_instruction; 468 | } 469 | } 470 | break; 471 | 472 | __try_instruction: 473 | default://maybe INSTRUCTION 474 | { 475 | unsigned int stcodeINSTR; 476 | WPG_Instruction doneInstr = {0}; 477 | 478 | stcodeINSTR = mel_wpg_text2instr(cpuSeries,cpuType,text,textsize, 479 | pfirstbad_operand,pfirstbad_device,&steps,&doneInstr); 480 | if (stcodeINSTR == INSTR_STATE_OK) 481 | { 482 | welldone->itype = WPG_ITEM_TYPE_INSTRUCTION; 483 | welldone->size = sizeof(WPG_Instruction); 484 | welldone->body = calloc(1,welldone->size); 485 | if (welldone->body) 486 | { 487 | memcpy(welldone->body,&doneInstr,welldone->size); 488 | stcode = ITEM_STATE_OK; 489 | if (doneInstr.opid == MEL_WPG_OpID_NOP) 490 | { 491 | nops++; 492 | } 493 | 494 | //DEBUG 495 | { 496 | unsigned char buf[1024] = {0}; 497 | int encsize; 498 | int tsteps; 499 | 500 | encsize = mel_wpg_enc_instruction(welldone,cpuSeries,cpuType,buf,&tsteps); 501 | if (encsize > 0) 502 | { 503 | /* 504 | int i; 505 | printf("%s (%d steps)\t",text,tsteps); 506 | for (i = 0; i < encsize; i++) 507 | { 508 | printf("%02X ",buf[i]); 509 | } 510 | printf("\n"); 511 | */ 512 | } 513 | else 514 | { 515 | printf("ERROR OF INSTR ENCODING! {%s}\n",text); 516 | exit(2); 517 | } 518 | } 519 | } 520 | else 521 | { 522 | stcode = ITEM_STATE_BAD_NO_MEMORY; 523 | } 524 | } 525 | else stcode = ITEM_STATE_BAD_INSTRUCTION; 526 | *pinstrerrcode = stcodeINSTR; 527 | } 528 | } 529 | } 530 | if (stcode == ITEM_STATE_OK) 531 | { 532 | welldone->steps = steps; 533 | welldone->nops = nops; 534 | } 535 | if (nops) 536 | { 537 | printf("NOP added!!![%d]\n",*psteps); 538 | } 539 | *psteps = steps; 540 | *pnopsteps = nops; 541 | return(stcode); 542 | } 543 | 544 | //ITEM {INSTRUCTION{OPERAND(S){DEVICE(S)}},STATEMENT,NOTE,LABEL,INTERRUPT} -> TXT 545 | char* mel_wpg_item2text(int cpuSeries,int cpuType,WPG_Item* item,int* ptextsize) 546 | { 547 | char* retptr = 0; 548 | static char text[MEL_WPG_MAX_INSTR_TEXT_SIZE] = {0}; 549 | int textsize = 0; 550 | 551 | text[0] = 0; 552 | 553 | switch(item->itype) 554 | { 555 | case WPG_ITEM_TYPE_INSTRUCTION: 556 | retptr = mel_wpg_instr2text(cpuSeries,cpuType,(WPG_Instruction*)item->body,ptextsize); 557 | break; 558 | case WPG_ITEM_TYPE_STATEMENT: 559 | *ptextsize = sprintf(text,"*%s",(char*)item->body); 560 | retptr = text; 561 | break; 562 | case WPG_ITEM_TYPE_NOTE: 563 | *ptextsize = sprintf(text,"*<%s",(char*)item->body); 564 | retptr = text; 565 | break; 566 | case WPG_ITEM_TYPE_LABEL: 567 | //*ptextsize = sprintf(text,"P%-5d",((WPG_Label*)item->body)->index); 568 | *ptextsize = sprintf(text,"P%d",((WPG_Label*)item->body)->index); 569 | retptr = text; 570 | break; 571 | case WPG_ITEM_TYPE_INTERRUPT: 572 | //*ptextsize = sprintf(text,"I%-5d",((WPG_Interrupt*)item->body)->index); 573 | *ptextsize = sprintf(text,"I%d",((WPG_Interrupt*)item->body)->index); 574 | retptr = text; 575 | break; 576 | } 577 | 578 | return(retptr); 579 | } 580 | 581 | int mel_til_get_line(unsigned char* stream,int stream_size,char* line,int* pline_dec_size,int max_line_size) 582 | { 583 | int line_enc_size = 0;//with LF,CR (0x0A,0x0D) 584 | int line_dec_size = 0;//without LF,CR and ending null 585 | 586 | while ( line_enc_size < stream_size 587 | && line_dec_size <= max_line_size 588 | ) 589 | { 590 | unsigned char curr_byte; 591 | 592 | curr_byte = stream[line_enc_size++]; 593 | if (curr_byte != 0x0A && curr_byte!= 0x0D) 594 | { 595 | line[line_dec_size++] = curr_byte; 596 | } 597 | else 598 | { 599 | line[line_dec_size] = 0x00;//C-string ending null 600 | } 601 | if (curr_byte == 0x0A) 602 | { 603 | break;//this is the end of line, so exit from loop 604 | } 605 | }; 606 | if (line[line_dec_size] != 0x00) 607 | { 608 | line[line_dec_size] = 0x00;//C-string ending null 609 | } 610 | *pline_dec_size = line_dec_size; 611 | return(line_enc_size); 612 | } 613 | 614 | void mel_wpg_item_swap_data(WPG_Item* item_a,WPG_Item* item_b) 615 | { 616 | WPG_Item item_t; 617 | //save a 618 | item_t.itype = item_a->itype; 619 | item_t.body = item_a->body; 620 | item_t.size = item_a->size; 621 | item_t.steps= item_a->steps; 622 | item_t.nops = item_a->nops; 623 | //a <- b 624 | item_a->itype = item_b->itype; 625 | item_a->body = item_b->body; 626 | item_a->size = item_b->size; 627 | item_a->steps= item_b->steps; 628 | item_a->nops = item_b->nops; 629 | //b <- saved a 630 | item_b->itype = item_t.itype; 631 | item_b->body = item_t.body; 632 | item_b->size = item_t.size; 633 | item_b->steps= item_t.steps; 634 | item_b->nops = item_t.nops; 635 | return; 636 | } -------------------------------------------------------------------------------- /mel_wpg_item.h: -------------------------------------------------------------------------------- 1 | #ifndef __mel_wpg_item_h__ 2 | #define __mel_wpg_item_h__ 3 | 4 | #include "mel_common.h" 5 | 6 | typedef struct tagWPG_Label 7 | { 8 | int is_long; 9 | int index; 10 | 11 | }WPG_Label; 12 | 13 | typedef struct tagWPG_Iterrupt 14 | { 15 | int index; 16 | 17 | }WPG_Interrupt; 18 | 19 | typedef struct tagWPG_Item 20 | { 21 | #define WPG_ITEM_TYPE_UNKNOWN 0 22 | #define WPG_ITEM_TYPE_INSTRUCTION 2 23 | #define WPG_ITEM_TYPE_STATEMENT 4 24 | #define WPG_ITEM_TYPE_NOTE 8 25 | #define WPG_ITEM_TYPE_LABEL 16 26 | #define WPG_ITEM_TYPE_INTERRUPT 32 27 | 28 | int itype; 29 | void* body; 30 | int size; 31 | int steps; 32 | int nops; 33 | ///////////////////////// 34 | struct tagWPG_Item* prev; 35 | struct tagWPG_Item* next; 36 | ///////////////////////// 37 | }WPG_Item; 38 | 39 | WPG_Item* mel_wpg_item_decoder (int cpuSeries,int cpuType,unsigned char* stream,int stream_size,int* psizedone,int* psteps,int* pnopsteps); 40 | int mel_wpg_item_encoder (WPG_Item* item,int cpuSeries,int cpuType,unsigned char* stream,int* psteps,int* pnopsteps); 41 | 42 | #define ITEM_STATE_OK 0 43 | #define ITEM_STATE_BAD_TOOSHORT (1<<0) 44 | #define ITEM_STATE_BAD_TOOLONG (1<<1) 45 | #define ITEM_STATE_BAD_INSTRUCTION (1<<2) 46 | #define ITEM_STATE_BAD_NOTE (1<<3) 47 | #define ITEM_STATE_BAD_STATEMENT (1<<4) 48 | #define ITEM_STATE_BAD_INTERRUPT (1<<5) 49 | #define ITEM_STATE_BAD_LABEL (1<<6) 50 | #define ITEM_STATE_BAD_UNKNOWN (1<<7) 51 | #define ITEM_STATE_BAD_NO_MEMORY (1<<31) 52 | 53 | //TXT -> ITEM {INSTRUCTION{OPERAND(S){DEVICE(S)}},STATEMENT,NOTE,LABEL,INTERRUPT} 54 | unsigned int mel_wpg_text2item(int cpuSeries,int cpuType,char* text,int textsize, 55 | unsigned int* pinstrerrcode,int* pfirstbad_operand,int* pfirstbad_device, 56 | int* psteps,int* pnopsteps, 57 | WPG_Item* welldone); 58 | //ITEM {INSTRUCTION{OPERAND(S){DEVICE(S)}},STATEMENT,NOTE,LABEL,INTERRUPT} -> TXT 59 | char* mel_wpg_item2text(int cpuSeries,int cpuType,WPG_Item* item,int* ptextsize); 60 | 61 | //return: encoded line size 62 | int mel_til_get_line(unsigned char* stream,int stream_size,char* line,int* pline_dec_size,int max_line_size); 63 | 64 | void mel_wpg_item_swap_data(WPG_Item* item_a,WPG_Item* item_b); 65 | 66 | #endif /* __mel_wpg_item_h__ */ 67 | -------------------------------------------------------------------------------- /mel_wpg_tables.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kernelbee/MitsubishiFX3/196ccdabbedb4edcf6906087371f30d8268262dc/mel_wpg_tables.h -------------------------------------------------------------------------------- /protocmn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "protocmn.h" 7 | 8 | int find_code_offset(unsigned char* stream,int stream_length,unsigned char code) 9 | { 10 | int is_exist = CODE_NOT_EXIST;//by default 11 | int i; 12 | for (i = 0; i < stream_length; i++) 13 | { 14 | if (stream[i]==code) 15 | { 16 | is_exist = i; 17 | break; 18 | } 19 | } 20 | return(is_exist); 21 | } 22 | 23 | void printf_buf_hex(unsigned char* buf,int size,char* header) 24 | { 25 | int i; 26 | 27 | if(header) printf("%s",header); 28 | for (i = 0; i 0) 142 | { 143 | int i; 144 | int strlength = stream[0]; 145 | 146 | if ((strlength > 2) && (strlength < 256) ) 147 | { 148 | retval = 1; 149 | 150 | //1.check ending null 151 | if (stream[strlength]==0) 152 | { 153 | //2.check every even byte 154 | for (i = 0; i < strlength-1; i+=2) 155 | { 156 | char ascii_ch; 157 | char ascii_ch2; 158 | 159 | ascii_ch = stream[i+1]; 160 | ascii_ch2 = stream[i+1+1]; 161 | 162 | if ( (ascii_ch<0x20) || (ascii_ch>0x7e) || (ascii_ch2!=0) ) 163 | //if ( (ascii_ch<9) || (ascii_ch>0x7e) || (ascii_ch2!=0) ) 164 | { 165 | retval = 0; 166 | //printf("\t\t%02x, %02x, %d, %02x: range!\n",stream[0],stream[strlength],strlength,ascii_ch); 167 | break; 168 | } 169 | 170 | //special case: " " 171 | if (strlength == 3) 172 | { 173 | if (ascii_ch == 0x20) 174 | { 175 | retval = 0; 176 | break; 177 | } 178 | } 179 | 180 | dstbuf[i/2] = stream[i+1]; 181 | } 182 | if (retval) 183 | { 184 | dstbuf[strlength/2] = 0; 185 | *plength = strlength+1; 186 | } 187 | } 188 | else 189 | { 190 | retval = 0; 191 | //printf("\t\t%02x, %02x, %d ending null!\n",stream[0],stream[strlength],strlength); 192 | } 193 | } 194 | } 195 | 196 | return(retval); 197 | } 198 | 199 | int enc_pascal_string(char* text,int textsize,unsigned char* stream) 200 | { 201 | int encsize; 202 | int i; 203 | 204 | encsize = 2*textsize+1; 205 | 206 | stream[0] = encsize; 207 | for (i = 0; i < textsize; i++) 208 | { 209 | stream[1+2*i+0] = text[i]; 210 | stream[1+2*i+1] = 0x00; 211 | } 212 | stream[encsize++] = 0x00; 213 | 214 | return(encsize); 215 | } 216 | 217 | void printf_buf_hex_N(unsigned char* buf,int size,char* header,int N) 218 | { 219 | int i; 220 | 221 | if(header) printf("%s",header); 222 | for (i = 0; i