├── .gitignore ├── FX3Simulation.cpp ├── FX3Simulation.sln ├── FX3Simulation.vcxproj ├── FX3Simulation.vcxproj.filters ├── LICENSE ├── Pictures ├── DeviceManager.PNG ├── Run_DetectPLC.png ├── Run_DetectPLC_EN.png └── run_result.png ├── Readme.md ├── RxProc.cpp ├── RxProc.h └── Videos └── 2022-04-26 17-09-01.mp4 /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 298 | *.vbp 299 | 300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 301 | *.dsw 302 | *.dsp 303 | 304 | # Visual Studio 6 technical files 305 | *.ncb 306 | *.aps 307 | 308 | # Visual Studio LightSwitch build output 309 | **/*.HTMLClient/GeneratedArtifacts 310 | **/*.DesktopClient/GeneratedArtifacts 311 | **/*.DesktopClient/ModelManifest.xml 312 | **/*.Server/GeneratedArtifacts 313 | **/*.Server/ModelManifest.xml 314 | _Pvt_Extensions 315 | 316 | # Paket dependency manager 317 | .paket/paket.exe 318 | paket-files/ 319 | 320 | # FAKE - F# Make 321 | .fake/ 322 | 323 | # CodeRush personal settings 324 | .cr/personal 325 | 326 | # Python Tools for Visual Studio (PTVS) 327 | __pycache__/ 328 | *.pyc 329 | 330 | # Cake - Uncomment if you are using it 331 | # tools/** 332 | # !tools/packages.config 333 | 334 | # Tabs Studio 335 | *.tss 336 | 337 | # Telerik's JustMock configuration file 338 | *.jmconfig 339 | 340 | # BizTalk build output 341 | *.btp.cs 342 | *.btm.cs 343 | *.odx.cs 344 | *.xsd.cs 345 | 346 | # OpenCover UI analysis results 347 | OpenCover/ 348 | 349 | # Azure Stream Analytics local run output 350 | ASALocalRun/ 351 | 352 | # MSBuild Binary and Structured Log 353 | *.binlog 354 | 355 | # NVidia Nsight GPU debugger configuration file 356 | *.nvuser 357 | 358 | # MFractors (Xamarin productivity tool) working folder 359 | .mfractor/ 360 | 361 | # Local History for Visual Studio 362 | .localhistory/ 363 | 364 | # Visual Studio History (VSHistory) files 365 | .vshistory/ 366 | 367 | # BeatPulse healthcheck temp database 368 | healthchecksdb 369 | 370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 371 | MigrationBackup/ 372 | 373 | # Ionide (cross platform F# VS Code tools) working folder 374 | .ionide/ 375 | 376 | # Fody - auto-generated XML schema 377 | FodyWeavers.xsd 378 | 379 | # VS Code files for those working on multiple tools 380 | .vscode/* 381 | !.vscode/settings.json 382 | !.vscode/tasks.json 383 | !.vscode/launch.json 384 | !.vscode/extensions.json 385 | *.code-workspace 386 | 387 | # Local History for Visual Studio Code 388 | .history/ 389 | 390 | # Windows Installer files from build outputs 391 | *.cab 392 | *.msi 393 | *.msix 394 | *.msm 395 | *.msp 396 | 397 | # JetBrains Rider 398 | *.sln.iml 399 | 400 | -------------------------------------------------------------------------------- /FX3Simulation.cpp: -------------------------------------------------------------------------------- 1 | // FX3Simulation.cpp : This file contains the 'main' function. Program execution begins and ends there. 2 | // 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "RxProc.h" 9 | 10 | // Want to open communcation port 11 | #define LINK_COMPORT L"COM4" 12 | 13 | int main() 14 | { 15 | std::cout << "FX3 Simulation Application" << std::endl; 16 | std::cout << "press 'ESC' key for quit" << std::endl; 17 | 18 | HANDLE hComm; 19 | DCB dcb; 20 | HANDLE hArray[2]; 21 | OVERLAPPED osReader = { 0 }; 22 | OVERLAPPED osEvent = { 0 }; 23 | OVERLAPPED osWrite = { 0 }; 24 | const DWORD dwCommEvent = EV_TXEMPTY | EV_RXCHAR | EV_ERR | EV_BREAK; 25 | const WCHAR COMPORT[] = L"\\\\.\\" LINK_COMPORT; 26 | COMMTIMEOUTS timeout = { 0 }; 27 | COMSTAT comState = { 0 }; 28 | DWORD dwError = 0; 29 | BOOL bWaitingOnRead = FALSE; 30 | BOOL bWaitingOnStat = FALSE; 31 | 32 | do { 33 | hComm = CreateFileW(COMPORT, //port name 34 | GENERIC_READ | GENERIC_WRITE, //Read/Write 35 | 0, // No Sharing 36 | NULL, // No Security 37 | OPEN_EXISTING, // Open existing port only 38 | FILE_FLAG_OVERLAPPED, // Non Overlapped I/O 39 | NULL); // Null for Comm Devices 40 | 41 | if (hComm == INVALID_HANDLE_VALUE) { 42 | std::cout << "Error in opening serial port" << std::endl; 43 | break; 44 | } 45 | else 46 | std::cout << "opening serial port successful" << std::endl; 47 | 48 | dcb.DCBlength = sizeof dcb; 49 | if (GetCommState(hComm, &dcb)) { 50 | // 115200,E,7,1 51 | //dcb.BaudRate = CBR_19200; 52 | dcb.BaudRate = CBR_115200; 53 | dcb.Parity = EVENPARITY; 54 | dcb.ByteSize = 7; 55 | dcb.StopBits = ONESTOPBIT; 56 | dcb.fParity = TRUE; 57 | dcb.fBinary = TRUE; 58 | dcb.fInX = FALSE; 59 | dcb.fOutX = FALSE; 60 | dcb.fDtrControl = DTR_CONTROL_DISABLE; 61 | dcb.fRtsControl = RTS_CONTROL_DISABLE; 62 | if (FALSE == SetCommState(hComm, &dcb)) { 63 | std::cout << "Error in configuration of serial port" << std::endl; 64 | break; 65 | } 66 | else 67 | std::cout << "configuration 115200,E,7,1 successful" << std::endl; 68 | } 69 | 70 | if (FALSE == SetupComm(hComm, 1024, 1024)) { 71 | std::cout << "Error in setting buffer length of serial port" << std::endl; 72 | break; 73 | } 74 | 75 | timeout.ReadIntervalTimeout = 100; // 100 milliseconds 76 | timeout.ReadTotalTimeoutMultiplier = 50; // 50 milliseconds 77 | timeout.ReadTotalTimeoutConstant = 200; 78 | if (FALSE == SetCommTimeouts(hComm, &timeout)) { 79 | std::cout << "Error in setting timeout of serial port" << std::endl; 80 | break; 81 | } 82 | 83 | if (FALSE == PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) { 84 | std::cout << "Error in purge buffer of serial port" << std::endl; 85 | break; 86 | } 87 | 88 | if (FALSE == SetCommMask(hComm, dwCommEvent)) { 89 | std::cout << "Error in SetCommMask of serial port" << std::endl; 90 | break; 91 | } 92 | 93 | if (FALSE == ClearCommError(hComm, &dwError, &comState)) { 94 | 95 | } 96 | 97 | // Create an event object for use by WaitCommEvent. 98 | osEvent.hEvent = CreateEvent( 99 | NULL, // default security attributes 100 | TRUE, // manual-reset event 101 | FALSE, // not signaled 102 | NULL // no name 103 | ); 104 | if (osEvent.hEvent == NULL) { 105 | std::cout << "Error in CreateEvent for osEvent" << std::endl; 106 | break; 107 | } 108 | 109 | osReader.hEvent = CreateEvent( 110 | NULL, // default security attributes 111 | TRUE, // manual-reset event 112 | FALSE, // not signaled 113 | NULL // no name 114 | ); 115 | if (osReader.hEvent == NULL) { 116 | std::cout << "Error in CreateEvent for osReader" << std::endl; 117 | break; 118 | } 119 | 120 | rxProc.osWrite.hEvent = CreateEvent( 121 | NULL, // default security attributes 122 | TRUE, // manual-reset event 123 | FALSE, // not signaled 124 | NULL // no name 125 | ); 126 | if (rxProc.osWrite.hEvent == NULL) { 127 | std::cout << "Error in CreateEvent for osReader" << std::endl; 128 | break; 129 | } 130 | 131 | hArray[0] = osReader.hEvent; 132 | hArray[1] = osEvent.hEvent; 133 | 134 | initSystem(); 135 | rxProc.State = STATE_IDLE; 136 | rxProc.DataLen = 0; 137 | 138 | do { 139 | BYTE Buffer[512]; 140 | BOOL bExit = FALSE; 141 | DWORD dwRead = 0; 142 | DWORD dwEvent = 0; 143 | 144 | if (bWaitingOnStat == FALSE) 145 | { 146 | if (WaitCommEvent(hComm, &dwEvent, &osEvent)) 147 | { 148 | if (dwEvent != 0x01 ) 149 | std::cout << "got event 0x" << std::setfill('0') << std::setw(4) << dwEvent << std::endl; 150 | 151 | if (dwEvent & EV_BREAK) 152 | ClearCommBreak(hComm); 153 | 154 | if (dwEvent & EV_ERR) 155 | ClearCommError(hComm, &dwError, &comState); 156 | 157 | } 158 | else 159 | { 160 | DWORD error = GetLastError(); 161 | if (error != ERROR_IO_PENDING) { 162 | 163 | } 164 | bWaitingOnStat = TRUE; 165 | } 166 | } 167 | 168 | if (bWaitingOnRead == FALSE) 169 | { 170 | if (FALSE == ReadFile(hComm, Buffer, sizeof(Buffer), &dwRead, &osReader)) 171 | { 172 | bWaitingOnRead = TRUE; 173 | } 174 | else { 175 | 176 | } 177 | } 178 | 179 | if (bWaitingOnRead && bWaitingOnStat) 180 | { 181 | //DWORD dwReadSize; 182 | dwEvent = WaitForMultipleObjects(2, hArray, FALSE, 50); 183 | switch (dwEvent) { 184 | case WAIT_OBJECT_0: 185 | bWaitingOnRead = FALSE; 186 | if (GetOverlappedResult(hComm, &osReader, &dwRead, FALSE)) 187 | { 188 | } 189 | else 190 | { 191 | DWORD error = GetLastError(); 192 | if (error != ERROR_IO_INCOMPLETE) { 193 | std::cout << "GetOverlappedResult(), got error code:" << std::hex << error << std::endl; 194 | } 195 | } 196 | break; 197 | case (WAIT_OBJECT_0 + 1): 198 | bWaitingOnStat = FALSE; 199 | break; 200 | case WAIT_TIMEOUT: 201 | break; 202 | default: 203 | bExit = TRUE; 204 | break; 205 | } 206 | } 207 | 208 | if (dwRead) { 209 | RxProc(hComm, rxProc, Buffer, dwRead); 210 | } 211 | 212 | if (bExit == TRUE) { 213 | std::cout << "exit program" << std::endl; 214 | break; 215 | } 216 | 217 | if (_kbhit()) { 218 | int ch; 219 | switch ((ch = _getch())) 220 | { 221 | case 27: 222 | std::cout << "got ESC key" << std::endl; 223 | bExit = TRUE; 224 | break; 225 | case '\r': 226 | // bExit = TRUE; 227 | break; 228 | case '\n': 229 | break; 230 | } 231 | if (bExit == TRUE) 232 | break; 233 | } 234 | 235 | if (bExit == TRUE) { 236 | std::cout << "exit program" << std::endl; 237 | break; 238 | } 239 | } while(1); 240 | 241 | } while (0); 242 | 243 | if (rxProc.osWrite.hEvent) 244 | CloseHandle(rxProc.osWrite.hEvent); 245 | 246 | if (osReader.hEvent) 247 | CloseHandle(osReader.hEvent); 248 | 249 | if (osEvent.hEvent) 250 | CloseHandle(osEvent.hEvent); 251 | 252 | //ReadFile(hComm, ) 253 | if (hComm != INVALID_HANDLE_VALUE) 254 | CloseHandle(hComm);//Closing the Serial Port 255 | } 256 | 257 | // Run program: Ctrl + F5 or Debug > Start Without Debugging menu 258 | // Debug program: F5 or Debug > Start Debugging menu 259 | 260 | // Tips for Getting Started: 261 | // 1. Use the Solution Explorer window to add/manage files 262 | // 2. Use the Team Explorer window to connect to source control 263 | // 3. Use the Output window to see build output and other messages 264 | // 4. Use the Error List window to view errors 265 | // 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project 266 | // 6. In the future, to open this project again, go to File > Open > Project and select the .sln file 267 | -------------------------------------------------------------------------------- /FX3Simulation.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.32228.343 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FX3Simulation", "FX3Simulation.vcxproj", "{7C4EEF3C-233E-4126-8CB4-C1BC11F51D34}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {7C4EEF3C-233E-4126-8CB4-C1BC11F51D34}.Debug|x64.ActiveCfg = Debug|x64 17 | {7C4EEF3C-233E-4126-8CB4-C1BC11F51D34}.Debug|x64.Build.0 = Debug|x64 18 | {7C4EEF3C-233E-4126-8CB4-C1BC11F51D34}.Debug|x86.ActiveCfg = Debug|Win32 19 | {7C4EEF3C-233E-4126-8CB4-C1BC11F51D34}.Debug|x86.Build.0 = Debug|Win32 20 | {7C4EEF3C-233E-4126-8CB4-C1BC11F51D34}.Release|x64.ActiveCfg = Release|x64 21 | {7C4EEF3C-233E-4126-8CB4-C1BC11F51D34}.Release|x64.Build.0 = Release|x64 22 | {7C4EEF3C-233E-4126-8CB4-C1BC11F51D34}.Release|x86.ActiveCfg = Release|Win32 23 | {7C4EEF3C-233E-4126-8CB4-C1BC11F51D34}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {87368A1B-7467-422B-9096-F33195109E61} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /FX3Simulation.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {7c4eef3c-233e-4126-8cb4-c1bc11f51d34} 25 | FX3Simulation 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | true 130 | true 131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | 134 | 135 | Console 136 | true 137 | true 138 | true 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /FX3Simulation.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022, KunYi Chen 2 | All rights reserved. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Pictures/DeviceManager.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunYi/FX3U_Simulation/73b668dc6bf9240c8162e3e21933aaafe4b9bd6c/Pictures/DeviceManager.PNG -------------------------------------------------------------------------------- /Pictures/Run_DetectPLC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunYi/FX3U_Simulation/73b668dc6bf9240c8162e3e21933aaafe4b9bd6c/Pictures/Run_DetectPLC.png -------------------------------------------------------------------------------- /Pictures/Run_DetectPLC_EN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunYi/FX3U_Simulation/73b668dc6bf9240c8162e3e21933aaafe4b9bd6c/Pictures/Run_DetectPLC_EN.png -------------------------------------------------------------------------------- /Pictures/run_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunYi/FX3U_Simulation/73b668dc6bf9240c8162e3e21933aaafe4b9bd6c/Pictures/run_result.png -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | Simulation Mitsubish FX3U PLC Serial Communication(Programming Port) 2 | === 3 | 4 | the code for studying FX3U with Melsoft communcation. 5 | 6 | running on Windows with [com0com](https://sourceforge.net/projects/com0com/). 7 | 8 | 9 | --- 10 | Work setting 11 | --- 12 | 13 | * COM3 for GX2 Works access 14 | * COM4 for our FX3U simulation program (definition in code) 15 | 16 | GX2 Work <<\==>> COM3 (com0com) << bind >> COM4 (com0com) <\==> FX3U simulation Program 17 | 18 | 19 | if you need change COMPORT, search ***LINK_COMPORT*** in source code. 20 | 21 | Status 22 | --- 23 | testing on Windows 10 x64 21H2 (19044.1645). 24 | 25 | connection test passed 26 | 27 | 28 | Screen shot 29 | --- 30 | install [com0com](https://sourceforge.net/projects/com0com/) 31 | 32 | ![Dvice Manager](Pictures/DeviceManager.PNG "Dvice Manager") 33 | 34 | 35 | Connection Test 36 | --- 37 | ![Result](Pictures/Run_DetectPLC_EN.png "Result") 38 | 39 | 40 | Another Testing 41 | --- 42 | ![Another testing video clip, play on github](https://github.com/KunYi/FX3U_Simulation/blob/master/Videos/2022-04-26%2017-09-01.mp4?raw=true) 43 | 44 | or 45 | 46 | [Another Testing Video clip, play on Youtube](https://youtu.be/r_XOcbTEAzA "Another testing") 47 | 48 | 49 | Build tools 50 | --- 51 | Visual Studio 2019 52 | -------------------------------------------------------------------------------- /RxProc.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "RxProc.h" 8 | 9 | #define PRINT_ASCII_MODE (1) 10 | 11 | struct RX_PROC rxProc; 12 | 13 | 14 | const uint16_t kSpecial[128] = { 15 | 0x00C8, 0x5EA8, 0x0008, 0x0010, 0x1F82, 0x0020, 0x0018, 0x0003, /* 8 */ 16 | 0x000A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 16 */ 17 | 0x0000, 0x0000, 0x0000, 0x0000, 0x000A, 0x0000, 0x0000, 0x0000, /* 24 */ 18 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x003D, 0x001C, /* 32 */ 19 | 0x0000, 0x0000, 0x0014, 0x00FF, 0x03D7, 0x0000, 0x0000, 0x0000, /* 40 */ 20 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* 48 */ 21 | 0x0000, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 56 */ 22 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x183B, 0x0000, /* 64 */ 23 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01F4, 0x0000, /* 72 */ 24 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 80 */ 25 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 88 */ 26 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 96 */ 27 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0064, 0x3F68, 0x0008, 0x0000, /* 104 */ 28 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 112 */ 29 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0DDC, 0x3DB6, 0x0000, 0x0000, /* 120 */ 30 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0003, 0x0000, 0x0000, /* 128 */ 31 | }; 32 | 33 | uint16_t PLCBuffer[(16 * 1024) + 216]; 34 | 35 | /* PLC code buffer*/ 36 | uint8_t CodeBuf[(33 * 1024) + 208] = { 37 | 0x10, 0x00, 0xD8, 0xBA, 0x00, 0x00, 0x00, 0x00, /* 8 */ 38 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* 16 */ 39 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* 24 */ 40 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* 32 */ 41 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* 40 */ 42 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* 48 */ 43 | 0xF4, 0x09, 0xFF, 0x0B, 0xF4, 0x01, 0xE7, 0x03, /* 56 */ 44 | 0x64, 0x0E, 0xC7, 0x0E, 0xDC, 0x0E, 0xFF, 0x0E, /* 64 */ 45 | 0x90, 0x01, 0xFE, 0x03, 0x00, 0x00, 0x00, 0x00, /* 72 */ 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80 */ 47 | 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 88 */ 48 | 0x00, 0x00, 0x00, 0x00, 0X0F, 0X00, 0XFF, 0XFF, /* 96 */ 49 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, /* 104 */ 50 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, /* 112 */ 51 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, /* 117 */ 52 | }; 53 | 54 | uint8_t Ex8000h[1024]; 55 | 56 | void initSystem(void) 57 | { 58 | for (uint8_t i = 0; i < 126; i++) 59 | { // offset 3KW 60 | PLCBuffer[0x0C00 + i] = kSpecial[i]; 61 | } 62 | 63 | PLCBuffer[0x2000] = CodeBuf[52] * 256; 64 | PLCBuffer[0x2000] += CodeBuf[53]; 65 | } 66 | 67 | uint8_t asc2hex(BYTE v) 68 | { 69 | return (v > '9') ? v - 'A' + 10 : v - '0'; 70 | } 71 | 72 | UINT16 hex2asc(BYTE v) 73 | { 74 | const char table[] = { '0', '1', '2', '3', 75 | '4', '5', '6', '7', 76 | '8', '9', 'A', 'B', 77 | 'C', 'D', 'E', 'F' }; 78 | return (table[(v >> 4) & 0xF] * 0x100) + table[v & 0xF]; 79 | } 80 | 81 | UINT8 Array2UINT8(BYTE* data) 82 | { 83 | return (asc2hex(data[0]) << 4) + 84 | asc2hex(data[1]); 85 | } 86 | 87 | UINT16 Array2UINT16(BYTE* data) 88 | { 89 | return (asc2hex(data[0]) << 12) + 90 | (asc2hex(data[1]) << 8) + 91 | (asc2hex(data[2]) << 4) + 92 | asc2hex(data[3]); 93 | } 94 | 95 | UINT32 Array2UINT32(BYTE* data) 96 | { 97 | return (asc2hex(data[0]) << 28) + 98 | (asc2hex(data[1]) << 24) + 99 | (asc2hex(data[2]) << 20) + 100 | (asc2hex(data[3]) << 16) + 101 | (asc2hex(data[4]) << 12) + 102 | (asc2hex(data[5]) << 8) + 103 | (asc2hex(data[6]) << 4) + 104 | asc2hex(data[7]); 105 | } 106 | 107 | uint8_t calcChecksum(uint8_t* pB) 108 | { 109 | uint8_t chksum = 0; 110 | while (*pB != ETX) { 111 | chksum += *pB; 112 | pB++; 113 | } 114 | return (chksum + ETX); 115 | } 116 | 117 | void InputLog(uint8_t buff[], uint16_t len) 118 | { 119 | for (uint16_t i = 0; i < len; i++) { 120 | 121 | #if PRINT_ASCII_MODE 122 | if (i == 0 && len == 1) { 123 | if (buff[i] == 0x05) std::cout << "ENQ"; 124 | else if (buff[i] == 0x02) std::cout << "STX,"; 125 | else if (buff[i] == 0x15) std::cout << "NACK"; 126 | else 127 | std::cout << buff[i]; 128 | } 129 | else if (buff[i] == 0x03) std::cout << ",ETX,"; 130 | else 131 | std::cout << buff[i]; 132 | #else 133 | std::cout << " " << std::hex << std::setfill('0') << std::setw(2) << static_cast(buff[i]); 134 | #endif 135 | } 136 | } 137 | 138 | void OutputLog(uint8_t buff[], uint16_t len) 139 | { 140 | std::cout << "<<<"; 141 | 142 | for (uint16_t i = 0; i < len; i++) { 143 | #if PRINT_ASCII_MODE 144 | if (i == 0) { 145 | if (buff[i] == 0x06) std::cout << "ACK"; 146 | else if (buff[i] == 0x02) std::cout << "STX,"; 147 | else if (buff[i] == 0x15) std::cout << "NACK"; 148 | } 149 | else { 150 | if (buff[i] == 0x03) std::cout << ",ETX,"; 151 | else 152 | std::cout << buff[i]; 153 | } 154 | #else 155 | std::cout << " " << std::hex << std::setfill('0') << std::setw(2) << static_cast(buff[i]); 156 | #endif 157 | } 158 | std::cout << std::endl; 159 | } 160 | 161 | void reponseAck(HANDLE hComm, struct RX_PROC& rp) 162 | { 163 | uint8_t buff[1]; 164 | DWORD dwWrite; 165 | buff[0] = ACK; 166 | WriteFile(hComm, buff, 1, &dwWrite, &rp.osWrite); 167 | 168 | OutputLog(buff, 1); 169 | } 170 | 171 | void reponseNAck(HANDLE hComm, struct RX_PROC& rp) 172 | { 173 | uint8_t buff[1]; 174 | DWORD dwWrite; 175 | buff[0] = NACK; 176 | WriteFile(hComm, buff, 1, &dwWrite, &rp.osWrite); 177 | 178 | OutputLog(buff, 1); 179 | } 180 | 181 | void reponseNibbleData(HANDLE hComm, struct RX_PROC& rp, uint8_t value) 182 | { 183 | uint8_t buff[6]; 184 | uint8_t chksum; 185 | uint16_t u16Data; 186 | DWORD dwWrite; 187 | 188 | buff[0] = STX; 189 | buff[1] = '0' + value; 190 | buff[2] = ETX; 191 | chksum = calcChecksum(&buff[1]); 192 | u16Data = hex2asc(chksum); 193 | buff[4] = (u16Data >> 8); 194 | buff[5] = u16Data & 0xFF; 195 | WriteFile(hComm, buff, 6, &dwWrite, &rp.osWrite); 196 | 197 | OutputLog(buff, 6); 198 | } 199 | 200 | void reponseF50110(HANDLE hComm, struct RX_PROC& rp) 201 | { 202 | uint8_t buff[8]; 203 | uint8_t chksum; 204 | uint16_t u16Data; 205 | DWORD dwWrite; 206 | 207 | buff[0] = STX; 208 | buff[1] = '1'; 209 | buff[2] = '0'; 210 | buff[3] = '0'; 211 | buff[4] = '0'; 212 | buff[5] = ETX; 213 | chksum = calcChecksum(&buff[1]); 214 | u16Data = hex2asc(chksum); 215 | buff[6] = (u16Data >> 8); 216 | buff[7] = u16Data & 0xFF; 217 | WriteFile(hComm, buff, 8, &dwWrite, &rp.osWrite); 218 | 219 | OutputLog(buff, 8); 220 | } 221 | 222 | void reponseF50104(HANDLE hComm, struct RX_PROC& rp) 223 | { 224 | uint8_t buff[8]; 225 | uint8_t chksum; 226 | uint16_t u16Data; 227 | DWORD dwWrite; 228 | 229 | buff[0] = STX; 230 | buff[1] = '0'; 231 | buff[2] = ETX; 232 | chksum = calcChecksum(&buff[1]); 233 | u16Data = hex2asc(chksum); 234 | buff[3] = (u16Data >> 8); 235 | buff[4] = u16Data & 0xFF; 236 | WriteFile(hComm, buff, 5, &dwWrite, &rp.osWrite); 237 | 238 | OutputLog(buff, 8); 239 | } 240 | 241 | void reponseCodeBuff(HANDLE hComm, struct RX_PROC& rp, uint16_t address, uint8_t len) 242 | { 243 | uint8_t buff[512]; 244 | uint8_t chksum; 245 | uint16_t u16Data; 246 | DWORD dwWrite; 247 | uint16_t i; 248 | 249 | buff[0] = STX; 250 | for (i = 0; i < len; i++) { 251 | u16Data = hex2asc(CodeBuf[i]); 252 | buff[(i * 2) + 1] = (u16Data / 0x100); 253 | buff[(i * 2) + 2] = (u16Data % 0x100); 254 | } 255 | 256 | buff[i * 2 + 1] = ETX; 257 | chksum = calcChecksum(&buff[1]); 258 | u16Data = hex2asc(chksum); 259 | buff[i * 2 + 2] = (u16Data / 0x100); 260 | buff[i * 2 + 3] = (u16Data % 0x100); 261 | WriteFile(hComm, buff, (i * 2) + 4, &dwWrite, &rp.osWrite); 262 | 263 | OutputLog(buff, (len * 2) + 4); 264 | } 265 | 266 | void reponseSpecialArray(HANDLE hComm, struct RX_PROC& rp, uint16_t address, uint8_t len) 267 | { 268 | uint8_t buff[512]; 269 | uint8_t chksum; 270 | uint16_t u16Data; 271 | DWORD dwWrite; 272 | uint16_t i; 273 | const uint8_t* pByte = reinterpret_cast(&kSpecial[0]) + address; 274 | 275 | buff[0] = STX; 276 | for (i = 0; i < len; i++) { 277 | u16Data = hex2asc(*(pByte + i)); 278 | buff[i * 2 + 1] = u16Data / 0x100; 279 | buff[i * 2 + 2] = u16Data % 0x100; 280 | } 281 | buff[i * 2 + 1] = ETX; 282 | chksum = calcChecksum(&buff[1]); 283 | u16Data = hex2asc(chksum); 284 | buff[i * 2 + 2] = (u16Data / 0x100); 285 | buff[i * 2 + 3] = (u16Data % 0x100); 286 | WriteFile(hComm, buff, (i * 2) + 4, &dwWrite, &rp.osWrite); 287 | 288 | OutputLog(buff, (len * 2) + 4); 289 | } 290 | 291 | void reponseArray(HANDLE hComm, struct RX_PROC& rp, uint16_t address, uint8_t len) 292 | { 293 | uint8_t buff[512]; 294 | uint8_t chksum; 295 | uint16_t u16Data; 296 | DWORD dwWrite; 297 | 298 | buff[0] = STX; 299 | for (uint16_t i = 1; i < (len * 2) + 1; i += 2) { 300 | buff[i] = '0'; 301 | buff[i + 1] = '0'; 302 | } 303 | buff[len * 2 + 1] = ETX; 304 | chksum = calcChecksum(&buff[1]); 305 | u16Data = hex2asc(chksum); 306 | buff[len * 2 + 2] = (u16Data / 0x100); 307 | buff[len * 2 + 3] = (u16Data % 0x100); 308 | WriteFile(hComm, buff, (len * 2) + 4, &dwWrite, &rp.osWrite); 309 | 310 | OutputLog(buff, (len * 2) + 4); 311 | } 312 | 313 | void reponseUINT16(HANDLE hComm, struct RX_PROC& rp, uint16_t val) 314 | { 315 | uint8_t buff[8]; 316 | uint8_t chksum; 317 | uint16_t u16Data; 318 | DWORD dwWrite; 319 | uint8_t* pData = reinterpret_cast(&val); 320 | 321 | buff[0] = STX; 322 | u16Data = hex2asc(*pData); 323 | buff[1] = (u16Data / 0x100); 324 | buff[2] = (u16Data % 0x100); 325 | u16Data = hex2asc(*(pData+1)); 326 | buff[3] = (u16Data / 0x100); 327 | buff[4] = (u16Data % 0x100); 328 | buff[5] = ETX; 329 | chksum = calcChecksum(&buff[1]); 330 | u16Data = hex2asc(chksum); 331 | buff[6] = (u16Data / 0x100); 332 | buff[7] = (u16Data % 0x100); 333 | 334 | WriteFile(hComm, buff, 8, &dwWrite, &rp.osWrite); 335 | 336 | OutputLog(buff, 8); 337 | } 338 | 339 | 340 | void procBasicReadCmd(HANDLE hComm, struct RX_PROC& rp) 341 | { 342 | uint16_t address = Array2UINT16(&rp.Data[1]); 343 | uint8_t len = Array2UINT8(&rp.Data[5]); 344 | if (address >= 0x0E00) { 345 | reponseSpecialArray(hComm, rp, (address - 0x0E00), len); 346 | return; 347 | } 348 | std::cout << "not implement" << std::endl; 349 | } 350 | 351 | void procBasicWriteCmd(HANDLE hComm, struct RX_PROC& rp) 352 | { 353 | uint8_t buff[256]; 354 | uint16_t address = Array2UINT16(&rp.Data[1]); 355 | uint8_t len = Array2UINT8(&rp.Data[5]); 356 | uint16_t i; 357 | 358 | if (static_cast(len * 2) > (rp.DataLen - 10)) { 359 | std::cout << "data length error" << std::endl; 360 | return; 361 | } 362 | for (i = 0; i < len; i++) { 363 | buff[i] = Array2UINT8(&rp.Data[(i * 2) + 7]); 364 | } 365 | 366 | reponseAck(hComm, rp); 367 | } 368 | 369 | void procExtensionCmd(HANDLE hComm, struct RX_PROC& rp) 370 | { 371 | if (rp.Data[1] == '0') 372 | { 373 | /* 'E00' Read PLC confiuration */ 374 | if (rp.Data[2] == '0') { 375 | uint16_t address = Array2UINT16(&rp.Data[3]); 376 | uint8_t len = Array2UINT8(&rp.Data[7]); 377 | if (address >= 0x8000) { 378 | reponseSpecialArray(hComm, rp, address - 0x8000, len); 379 | return; 380 | } 381 | } 382 | /* 'E01' for Read PLC code */ 383 | else if (rp.Data[2] == '1') { 384 | uint16_t address = Array2UINT16(&rp.Data[3]); 385 | uint8_t len = Array2UINT8(&rp.Data[7]); 386 | if (address >= 0x8000) { 387 | reponseSpecialArray(hComm, rp, address - 0x8000, len); 388 | return; 389 | } 390 | } 391 | } 392 | else if (rp.Data[1] == '1') { 393 | /* 'E10' for Write PLC confiuration */ 394 | if (rp.Data[2] == '0') { 395 | uint16_t address = Array2UINT16(&rp.Data[3]); 396 | uint8_t len = Array2UINT8(&rp.Data[7]); 397 | if (address >= 0x8000) { 398 | //reponseCodeBuff(hComm, rp, address - 0x8000, len); 399 | reponseAck(hComm, rp); 400 | return; 401 | } 402 | } 403 | /* 'E11' for Write PLC code */ 404 | else if (rp.Data[2] == '1') { 405 | uint16_t address = Array2UINT16(&rp.Data[3]); 406 | uint8_t len = Array2UINT8(&rp.Data[7]); 407 | if (address >= 0x8000) { 408 | //reponseCodeBuff(hComm, rp, address - 0x8000, len); 409 | reponseAck(hComm, rp); 410 | return; 411 | } 412 | } 413 | } 414 | /* 'E7 for force set bit */ 415 | else if (rp.Data[1] == '7') { 416 | // return; 417 | } 418 | /* 'E7 for force reset bit */ 419 | else if (rp.Data[1] == '8') { 420 | // return; 421 | } 422 | std::cout << "not implement" << std::endl; 423 | } 424 | 425 | void DispatchCmd(HANDLE hComm, struct RX_PROC& rp) 426 | { 427 | switch (rp.Data[0]) { 428 | case '0': 429 | procBasicReadCmd(hComm, rp); 430 | break; 431 | case '1': 432 | procBasicWriteCmd(hComm, rp); 433 | break; 434 | 435 | case 'E': { 436 | procExtensionCmd(hComm, rp); 437 | break; 438 | } 439 | case 'F': { 440 | uint32_t cmd = (rp.Data[1] << 24) + (rp.Data[2] << 16) + (rp.Data[3] << 8) + rp.Data[4]; 441 | if (cmd == 0x35303131) 442 | reponseF50110(hComm, rp); 443 | else if (cmd == 0x35303130) 444 | reponseF50104(hComm, rp); 445 | else 446 | reponseNibbleData(hComm, rp, 1); 447 | } 448 | break; 449 | } 450 | } 451 | 452 | BOOL RxProc(HANDLE hComm, struct RX_PROC& rp, BYTE* buff, DWORD len) 453 | { 454 | BOOL ret = FALSE; 455 | BOOL bNewLine = TRUE; 456 | 457 | // for timeout over 200ms 458 | if ((rp.State != STATE_IDLE) && 459 | (GetTickCount() - rp.LastTick) > 200) 460 | rp.State = STATE_IDLE; 461 | 462 | rp.LastTick = GetTickCount(); 463 | 464 | for (DWORD i = 0; i < len; i++) { 465 | if (bNewLine) { 466 | std::cout << ">>>"; 467 | bNewLine = FALSE; 468 | } 469 | //std::cout << " " << std::hex << std::setfill('0') << std::setw(2) << static_cast(buff[i]); 470 | switch (rp.State) { 471 | case STATE_IDLE: 472 | if (buff[i] == ENQ) { 473 | InputLog(&buff[i], 1); 474 | std::cout << std::endl; 475 | reponseAck(hComm, rp); 476 | bNewLine = TRUE; 477 | } 478 | if (buff[i] == STX) { 479 | InputLog(&buff[i], 1); 480 | rp.State = STATE_RXPKT; 481 | rp.DataLen = 0; 482 | } 483 | break; 484 | case STATE_RXPKT: 485 | rp.Data[rp.DataLen++] = buff[i]; 486 | if (buff[i] == ETX) { 487 | rp.State = STATE_CHK1; 488 | } 489 | break; 490 | case STATE_CHK1: 491 | rp.Data[rp.DataLen++] = buff[i]; 492 | rp.State = STATE_CHK2; 493 | break; 494 | case STATE_CHK2: 495 | { 496 | rp.Data[rp.DataLen++] = buff[i]; 497 | if (calcChecksum(rp.Data) == Array2UINT8(&rp.Data[rp.DataLen - 2])) 498 | { 499 | InputLog(rp.Data, rp.DataLen); 500 | std::cout << std::endl; 501 | ret = TRUE; 502 | } 503 | rp.State = STATE_IDLE; 504 | } 505 | break; 506 | } /* end of swith(rp.State) */ 507 | } 508 | if (ret) 509 | DispatchCmd(hComm, rxProc); 510 | return ret; 511 | } -------------------------------------------------------------------------------- /RxProc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define STX (0x02) 4 | #define ETX (0x03) 5 | #define ENQ (0x05) 6 | #define ACK (0x06) 7 | #define NACK (0x15) 8 | 9 | enum RX_STATE { 10 | STATE_IDLE, 11 | STATE_RXPKT, 12 | STATE_CHK1, 13 | STATE_CHK2, 14 | }; 15 | 16 | struct RX_PROC { 17 | RX_STATE State; 18 | uint32_t DataLen; 19 | BYTE Data[256]; 20 | OVERLAPPED osWrite; 21 | DWORD LastTick; 22 | }; 23 | 24 | extern struct RX_PROC rxProc; 25 | 26 | void initSystem(void); 27 | BOOL RxProc(HANDLE hComm, struct RX_PROC& rp, BYTE* buff, DWORD len); 28 | -------------------------------------------------------------------------------- /Videos/2022-04-26 17-09-01.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunYi/FX3U_Simulation/73b668dc6bf9240c8162e3e21933aaafe4b9bd6c/Videos/2022-04-26 17-09-01.mp4 --------------------------------------------------------------------------------