1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Diagnostics; 6 using System.IO.PortsTests; 7 using System.Threading; 8 using Legacy.Support; 9 using Xunit; 10 11 namespace System.IO.Ports.Tests 12 { 13 public class Parity_Property : PortsTest 14 { 15 //The default number of bytes to read/write to verify the speed of the port 16 //and that the bytes were transfered successfully 17 private const int DEFAULT_BYTE_SIZE = 512; 18 19 //If the percentage difference between the expected time to transfer with the specified parity 20 //and the actual time found through Stopwatch is greater then 10% then the Parity value was not correctly 21 //set and the testcase fails. 22 private const double MAX_ACCEPTABEL_PERCENTAGE_DIFFERENCE = .10; 23 24 //The default number of databits to use when testing Parity 25 private const int DEFUALT_DATABITS = 8; 26 private const int NUM_TRYS = 3; 27 28 private enum ThrowAt { Set, Open }; 29 30 #region Test Cases 31 [ConditionalFact(nameof(HasNullModem))] Parity_Default()32 public void Parity_Default() 33 { 34 using (SerialPort com1 = new SerialPort(TCSupport.LocalMachineSerialInfo.FirstAvailablePortName)) 35 { 36 SerialPortProperties serPortProp = new SerialPortProperties(); 37 38 Debug.WriteLine("Verifying default Parity"); 39 40 serPortProp.SetAllPropertiesToOpenDefaults(); 41 serPortProp.SetProperty("PortName", TCSupport.LocalMachineSerialInfo.FirstAvailablePortName); 42 com1.Open(); 43 44 serPortProp.VerifyPropertiesAndPrint(com1); 45 VerifyParity(com1, DEFAULT_BYTE_SIZE); 46 47 serPortProp.VerifyPropertiesAndPrint(com1); 48 } 49 } 50 51 [ConditionalFact(nameof(HasNullModem))] Parity_None_BeforeOpen()52 public void Parity_None_BeforeOpen() 53 { 54 Debug.WriteLine("Verifying None Parity before open"); 55 VerifyParityBeforeOpen((int)Parity.None, DEFAULT_BYTE_SIZE); 56 } 57 58 [ConditionalFact(nameof(HasNullModem))] Parity_Even_BeforeOpen()59 public void Parity_Even_BeforeOpen() 60 { 61 Debug.WriteLine("Verifying Even Parity before open"); 62 VerifyParityBeforeOpen((int)Parity.Even, DEFAULT_BYTE_SIZE); 63 } 64 65 66 [ConditionalFact(nameof(HasNullModem))] Parity_Odd_BeforeOpen()67 public void Parity_Odd_BeforeOpen() 68 { 69 Debug.WriteLine("Verifying Odd Parity before open"); 70 VerifyParityBeforeOpen((int)Parity.Odd, DEFAULT_BYTE_SIZE); 71 } 72 73 [ConditionalFact(nameof(HasNullModem))] Parity_Mark_BeforeOpen()74 public void Parity_Mark_BeforeOpen() 75 { 76 Debug.WriteLine("Verifying Mark Parity before open"); 77 VerifyParityBeforeOpen((int)Parity.Mark, DEFAULT_BYTE_SIZE); 78 } 79 80 [ConditionalFact(nameof(HasNullModem))] Parity_Space_BeforeOpen()81 public void Parity_Space_BeforeOpen() 82 { 83 Debug.WriteLine("Verifying Space before open"); 84 VerifyParityBeforeOpen((int)Parity.Space, DEFAULT_BYTE_SIZE); 85 } 86 87 [ConditionalFact(nameof(HasNullModem))] Parity_None_AfterOpen()88 public void Parity_None_AfterOpen() 89 { 90 Debug.WriteLine("Verifying None Parity after open"); 91 VerifyParityAfterOpen((int)Parity.None, DEFAULT_BYTE_SIZE); 92 } 93 94 [ConditionalFact(nameof(HasNullModem))] Parity_Even_AfterOpen()95 public void Parity_Even_AfterOpen() 96 { 97 Debug.WriteLine("Verifying Even Parity after open"); 98 VerifyParityAfterOpen((int)Parity.Even, DEFAULT_BYTE_SIZE); 99 } 100 101 [ConditionalFact(nameof(HasNullModem))] Parity_Odd_AfterOpen()102 public void Parity_Odd_AfterOpen() 103 { 104 Debug.WriteLine("Verifying Odd Parity after open"); 105 VerifyParityAfterOpen((int)Parity.Odd, DEFAULT_BYTE_SIZE); 106 } 107 108 [ConditionalFact(nameof(HasNullModem))] Parity_Mark_AfterOpen()109 public void Parity_Mark_AfterOpen() 110 { 111 Debug.WriteLine("Verifying Mark Parity after open"); 112 VerifyParityAfterOpen((int)Parity.Mark, DEFAULT_BYTE_SIZE); 113 } 114 115 [ConditionalFact(nameof(HasNullModem))] Parity_Space_AfterOpen()116 public void Parity_Space_AfterOpen() 117 { 118 Debug.WriteLine("Verifying Space Parity after open"); 119 VerifyParityAfterOpen((int)Parity.Space, DEFAULT_BYTE_SIZE); 120 } 121 122 [ConditionalFact(nameof(HasOneSerialPort))] Parity_Int32MinValue()123 public void Parity_Int32MinValue() 124 { 125 Debug.WriteLine("Verifying Int32.MinValue Parity"); 126 VerifyException(int.MinValue, ThrowAt.Set, typeof(ArgumentOutOfRangeException)); 127 } 128 129 [ConditionalFact(nameof(HasOneSerialPort))] Parity_Neg1()130 public void Parity_Neg1() 131 { 132 Debug.WriteLine("Verifying -1 Parity"); 133 VerifyException(-1, ThrowAt.Set, typeof(ArgumentOutOfRangeException)); 134 } 135 136 [ConditionalFact(nameof(HasOneSerialPort))] Parity_Int32MaxValue()137 public void Parity_Int32MaxValue() 138 { 139 Debug.WriteLine("Verifying Int32.MaxValue Parity"); 140 VerifyException(int.MaxValue, ThrowAt.Set, typeof(ArgumentOutOfRangeException)); 141 } 142 143 [ConditionalFact(nameof(HasNullModem))] Parity_Even_Odd()144 public void Parity_Even_Odd() 145 { 146 using (SerialPort com1 = new SerialPort(TCSupport.LocalMachineSerialInfo.FirstAvailablePortName)) 147 { 148 SerialPortProperties serPortProp = new SerialPortProperties(); 149 150 Debug.WriteLine("Verifying Parity Even and then Odd"); 151 152 serPortProp.SetAllPropertiesToOpenDefaults(); 153 serPortProp.SetProperty("PortName", TCSupport.LocalMachineSerialInfo.FirstAvailablePortName); 154 com1.Open(); 155 com1.Parity = Parity.Even; 156 com1.Parity = Parity.Odd; 157 serPortProp.SetProperty("Parity", Parity.Odd); 158 159 serPortProp.VerifyPropertiesAndPrint(com1); 160 VerifyParity(com1, DEFAULT_BYTE_SIZE); 161 162 serPortProp.VerifyPropertiesAndPrint(com1); 163 } 164 } 165 166 [ConditionalFact(nameof(HasNullModem))] Parity_Odd_Even()167 public void Parity_Odd_Even() 168 { 169 using (SerialPort com1 = new SerialPort(TCSupport.LocalMachineSerialInfo.FirstAvailablePortName)) 170 { 171 SerialPortProperties serPortProp = new SerialPortProperties(); 172 173 Debug.WriteLine("Verifying Parity Odd and then Even"); 174 175 serPortProp.SetAllPropertiesToOpenDefaults(); 176 serPortProp.SetProperty("PortName", TCSupport.LocalMachineSerialInfo.FirstAvailablePortName); 177 com1.Open(); 178 com1.Parity = Parity.Odd; 179 com1.Parity = Parity.Even; 180 serPortProp.SetProperty("Parity", Parity.Even); 181 182 serPortProp.VerifyPropertiesAndPrint(com1); 183 VerifyParity(com1, DEFAULT_BYTE_SIZE); 184 185 serPortProp.VerifyPropertiesAndPrint(com1); 186 } 187 } 188 189 [ConditionalFact(nameof(HasNullModem))] Parity_Odd_Mark()190 public void Parity_Odd_Mark() 191 { 192 using (SerialPort com1 = new SerialPort(TCSupport.LocalMachineSerialInfo.FirstAvailablePortName)) 193 { 194 SerialPortProperties serPortProp = new SerialPortProperties(); 195 196 Debug.WriteLine("Verifying Parity Odd and then Mark"); 197 198 serPortProp.SetAllPropertiesToOpenDefaults(); 199 serPortProp.SetProperty("PortName", TCSupport.LocalMachineSerialInfo.FirstAvailablePortName); 200 com1.Open(); 201 com1.Parity = Parity.Odd; 202 com1.Parity = Parity.Mark; 203 serPortProp.SetProperty("Parity", Parity.Mark); 204 205 serPortProp.VerifyPropertiesAndPrint(com1); 206 VerifyParity(com1, DEFAULT_BYTE_SIZE); 207 208 serPortProp.VerifyPropertiesAndPrint(com1); 209 } 210 } 211 #endregion 212 213 #region Verification for Test Cases VerifyException(int parity, ThrowAt throwAt, Type expectedException)214 private void VerifyException(int parity, ThrowAt throwAt, Type expectedException) 215 { 216 using (SerialPort com = new SerialPort(TCSupport.LocalMachineSerialInfo.FirstAvailablePortName)) 217 { 218 VerifyExceptionAtOpen(com, parity, throwAt, expectedException); 219 if (com.IsOpen) 220 com.Close(); 221 222 VerifyExceptionAfterOpen(com, parity, expectedException); 223 } 224 } 225 226 VerifyExceptionAtOpen(SerialPort com, int parity, ThrowAt throwAt, Type expectedException)227 private void VerifyExceptionAtOpen(SerialPort com, int parity, ThrowAt throwAt, Type expectedException) 228 { 229 int origParity = (int)com.Parity; 230 SerialPortProperties serPortProp = new SerialPortProperties(); 231 232 serPortProp.SetAllPropertiesToDefaults(); 233 serPortProp.SetProperty("PortName", TCSupport.LocalMachineSerialInfo.FirstAvailablePortName); 234 235 if (ThrowAt.Open == throwAt) 236 serPortProp.SetProperty("Parity", (Parity)parity); 237 238 try 239 { 240 com.Parity = (Parity)parity; 241 242 if (ThrowAt.Open == throwAt) 243 com.Open(); 244 245 if (null != expectedException) 246 { 247 Fail("ERROR!!! Expected Open() to throw {0} and nothing was thrown", expectedException); 248 } 249 } 250 catch (Exception e) 251 { 252 if (null == expectedException) 253 { 254 Fail("ERROR!!! Expected Open() NOT to throw an exception and {0} was thrown", e.GetType()); 255 } 256 else if (e.GetType() != expectedException) 257 { 258 Fail("ERROR!!! Expected Open() throw {0} and {1} was thrown", expectedException, e.GetType()); 259 } 260 } 261 262 serPortProp.VerifyPropertiesAndPrint(com); 263 com.Parity = (Parity)origParity; 264 } 265 VerifyExceptionAfterOpen(SerialPort com, int parity, Type expectedException)266 private void VerifyExceptionAfterOpen(SerialPort com, int parity, Type expectedException) 267 { 268 SerialPortProperties serPortProp = new SerialPortProperties(); 269 270 com.Open(); 271 serPortProp.SetAllPropertiesToOpenDefaults(); 272 serPortProp.SetProperty("PortName", TCSupport.LocalMachineSerialInfo.FirstAvailablePortName); 273 274 try 275 { 276 com.Parity = (Parity)parity; 277 if (null != expectedException) 278 { 279 Fail("ERROR!!! Expected setting the Parity after Open() to throw {0} and nothing was thrown", expectedException); 280 } 281 } 282 catch (Exception e) 283 { 284 if (null == expectedException) 285 { 286 Fail("ERROR!!! Expected setting the Parity after Open() NOT to throw an exception and {0} was thrown", e.GetType()); 287 } 288 else if (e.GetType() != expectedException) 289 { 290 Fail("ERROR!!! Expected setting the Parity after Open() throw {0} and {1} was thrown", expectedException, e.GetType()); 291 } 292 } 293 294 serPortProp.VerifyPropertiesAndPrint(com); 295 } 296 297 VerifyParityBeforeOpen(int parity, int numBytesToSend)298 private void VerifyParityBeforeOpen(int parity, int numBytesToSend) 299 { 300 using (SerialPort com1 = new SerialPort(TCSupport.LocalMachineSerialInfo.FirstAvailablePortName)) 301 { 302 SerialPortProperties serPortProp = new SerialPortProperties(); 303 304 serPortProp.SetAllPropertiesToOpenDefaults(); 305 serPortProp.SetProperty("PortName", TCSupport.LocalMachineSerialInfo.FirstAvailablePortName); 306 307 com1.Parity = (Parity)parity; 308 com1.Open(); 309 serPortProp.SetProperty("Parity", (Parity)parity); 310 311 serPortProp.VerifyPropertiesAndPrint(com1); 312 VerifyParity(com1, numBytesToSend); 313 serPortProp.VerifyPropertiesAndPrint(com1); 314 } 315 } 316 317 VerifyParityAfterOpen(int parity, int numBytesToSend)318 private void VerifyParityAfterOpen(int parity, int numBytesToSend) 319 { 320 using (SerialPort com1 = new SerialPort(TCSupport.LocalMachineSerialInfo.FirstAvailablePortName)) 321 { 322 SerialPortProperties serPortProp = new SerialPortProperties(); 323 324 serPortProp.SetAllPropertiesToOpenDefaults(); 325 serPortProp.SetProperty("PortName", TCSupport.LocalMachineSerialInfo.FirstAvailablePortName); 326 327 com1.Open(); 328 com1.Parity = (Parity)parity; 329 serPortProp.SetProperty("Parity", (Parity)parity); 330 331 serPortProp.VerifyPropertiesAndPrint(com1); 332 VerifyParity(com1, numBytesToSend); 333 serPortProp.VerifyPropertiesAndPrint(com1); 334 } 335 } 336 VerifyParity(SerialPort com1, int numBytesToSend)337 private void VerifyParity(SerialPort com1, int numBytesToSend) 338 { 339 VerifyParity(com1, numBytesToSend, DEFUALT_DATABITS); 340 } 341 VerifyParity(SerialPort com1, int numBytesToSend, int dataBits)342 private void VerifyParity(SerialPort com1, int numBytesToSend, int dataBits) 343 { 344 byte[] xmitBytes = new byte[numBytesToSend]; 345 byte[] expectedBytes = new byte[numBytesToSend]; 346 Random rndGen = new Random(); 347 using (SerialPort com2 = new SerialPort(TCSupport.LocalMachineSerialInfo.SecondAvailablePortName)) 348 { 349 byte shiftMask = 0xFF; 350 351 //Create a mask that when logicaly and'd with the transmitted byte will 352 //will result in the byte recievied due to the leading bits being chopped 353 //off due to Parity less then 8 354 if (8 > dataBits) 355 shiftMask >>= 8 - com1.DataBits; 356 357 //Generate some random bytes to read/write for this Parity setting 358 for (int i = 0; i < xmitBytes.Length; i++) 359 { 360 xmitBytes[i] = (byte)rndGen.Next(0, 256); 361 expectedBytes[i] = (byte)(xmitBytes[i] & shiftMask); 362 } 363 364 com2.DataBits = dataBits; 365 com2.Parity = com1.Parity; 366 com1.DataBits = dataBits; 367 com2.Open(); 368 369 PerformWriteRead(com1, com2, xmitBytes, expectedBytes); 370 } 371 } 372 373 VerifyReadParity(int parity, int dataBits, int numBytesToSend)374 private void VerifyReadParity(int parity, int dataBits, int numBytesToSend) 375 { 376 byte[] xmitBytes = new byte[numBytesToSend]; 377 byte[] expectedBytes = new byte[numBytesToSend]; 378 Random rndGen = new Random(); 379 using (SerialPort com1 = new SerialPort(TCSupport.LocalMachineSerialInfo.FirstAvailablePortName)) 380 using (SerialPort com2 = new SerialPort(TCSupport.LocalMachineSerialInfo.SecondAvailablePortName)) 381 { 382 byte shiftMask = 0xFF; 383 bool parityErrorOnLastByte = false, isParityError = false; 384 int parityIndex; 385 byte parityErrorByte; 386 387 if (8 > dataBits) 388 com1.DataBits = dataBits + 1; 389 else 390 com1.Parity = (Parity)parity; 391 392 com2.Parity = (Parity)parity; 393 com2.DataBits = dataBits; 394 com1.StopBits = StopBits.One; 395 com2.StopBits = StopBits.One; 396 397 //Create a mask that when logicaly and'd with the transmitted byte will 398 //will result in the byte recievied due to the leading bits being chopped 399 //off due to Parity less then 8 400 shiftMask >>= 8 - dataBits; 401 402 //Generate some random bytes to read/write for this Parity setting 403 for (int i = 0; i < xmitBytes.Length; i++) 404 { 405 do 406 { 407 xmitBytes[i] = (byte)rndGen.Next(0, 256); 408 isParityError = !VerifyParityByte(xmitBytes[i], com1.DataBits, (Parity)parity); 409 } while (isParityError); //Prevent adacent parity errors see VSWhidbey 103979 410 411 expectedBytes[i] = (byte)(xmitBytes[i] & shiftMask); 412 parityErrorOnLastByte = isParityError; 413 } 414 415 do 416 { 417 parityErrorByte = (byte)rndGen.Next(0, 256); 418 isParityError = !VerifyParityByte(parityErrorByte, com1.DataBits, (Parity)parity); 419 } while (!isParityError); 420 421 parityIndex = rndGen.Next(xmitBytes.Length / 4, xmitBytes.Length / 2); 422 xmitBytes[parityIndex] = parityErrorByte; 423 expectedBytes[parityIndex] = com2.ParityReplace; 424 425 Debug.WriteLine("parityIndex={0}", parityIndex); 426 427 parityIndex = rndGen.Next((3 * xmitBytes.Length) / 4, xmitBytes.Length - 1); 428 xmitBytes[parityIndex] = parityErrorByte; 429 expectedBytes[parityIndex] = com2.ParityReplace; 430 431 Debug.WriteLine("parityIndex={0}", parityIndex); 432 433 /* 434 for(int i=0; i<xmitBytes.Length; i++) { 435 do { 436 xmitBytes[i] = (byte)rndGen.Next(0, 256); 437 isParityError = !VerifyParityByte(xmitBytes[i], com1.DataBits, (Parity)parity); 438 }while(parityErrorOnLastByte && isParityError); //Prevent adacent parity errors see VSWhidbey 103979 439 440 expectedBytes[i] = isParityError ? com2.ParityReplace :(byte)(xmitBytes[i] & shiftMask); 441 parityErrorOnLastByte = isParityError; 442 } 443 */ 444 com1.Open(); 445 com2.Open(); 446 PerformWriteRead(com1, com2, xmitBytes, expectedBytes); 447 } 448 } 449 VerifyWriteParity(int parity, int dataBits, int numBytesToSend)450 private void VerifyWriteParity(int parity, int dataBits, int numBytesToSend) 451 { 452 byte[] xmitBytes = new byte[numBytesToSend]; 453 byte[] expectedBytes = new byte[numBytesToSend]; 454 Random rndGen = new Random(); 455 using (SerialPort com1 = new SerialPort(TCSupport.LocalMachineSerialInfo.FirstAvailablePortName)) 456 using (SerialPort com2 = new SerialPort(TCSupport.LocalMachineSerialInfo.SecondAvailablePortName)) 457 { 458 //Generate some random bytes to read/write for this Parity setting 459 for (int i = 0; i < xmitBytes.Length; i++) 460 { 461 xmitBytes[i] = (byte)rndGen.Next(0, 256); 462 expectedBytes[i] = SetParityBit((byte)(xmitBytes[i]), dataBits, (Parity)parity); 463 } 464 465 if (8 > dataBits) 466 com2.DataBits = dataBits + 1; 467 else 468 com2.Parity = (Parity)parity; 469 470 com1.Parity = (Parity)parity; 471 com1.DataBits = dataBits; 472 com1.Open(); 473 com2.Open(); 474 475 PerformWriteRead(com1, com2, xmitBytes, expectedBytes); 476 } 477 } 478 479 PerformWriteRead(SerialPort com1, SerialPort com2, byte[] xmitBytes, byte[] expectedBytes)480 private void PerformWriteRead(SerialPort com1, SerialPort com2, byte[] xmitBytes, byte[] expectedBytes) 481 { 482 byte[] rcvBytes = new byte[expectedBytes.Length * 4]; 483 Stopwatch sw = new Stopwatch(); 484 double expectedTime, actualTime, percentageDifference; 485 int numParityBits = (Parity)com1.Parity == Parity.None ? 0 : 1; 486 double numStopBits = GetNumberOfStopBits(com1); 487 int length = xmitBytes.Length; 488 int rcvLength; 489 490 // TODO: Consider removing all of the code to check the time it takes to transfer the bytes. 491 // This was likely just a copy and paste from another test case 492 actualTime = 0; 493 Thread.CurrentThread.Priority = ThreadPriority.Highest; 494 for (int i = 0; i < NUM_TRYS; i++) 495 { 496 com2.DiscardInBuffer(); 497 498 IAsyncResult beginWriteResult = com1.BaseStream.BeginWrite(xmitBytes, 0, length, null, null); 499 500 while (0 == com2.BytesToRead) ; 501 502 sw.Start(); 503 504 // Wait for all of the bytes to reach the input buffer of com2 505 TCSupport.WaitForReadBufferToLoad(com2, length); 506 507 sw.Stop(); 508 actualTime += sw.ElapsedMilliseconds; 509 beginWriteResult.AsyncWaitHandle.WaitOne(); 510 sw.Reset(); 511 } 512 513 Thread.CurrentThread.Priority = ThreadPriority.Normal; 514 actualTime /= NUM_TRYS; 515 expectedTime = ((xmitBytes.Length * (1 + numStopBits + com1.DataBits + numParityBits)) / com1.BaudRate) * 1000; 516 percentageDifference = Math.Abs((expectedTime - actualTime) / expectedTime); 517 518 //If the percentageDifference between the expected time and the actual time is to high 519 //then the expected baud rate must not have been used and we should report an error 520 if (MAX_ACCEPTABEL_PERCENTAGE_DIFFERENCE < percentageDifference) 521 { 522 Fail("ERROR!!! Parity not used Expected time:{0}, actual time:{1} percentageDifference:{2}", expectedTime, actualTime, percentageDifference); 523 } 524 525 rcvLength = com2.Read(rcvBytes, 0, rcvBytes.Length); 526 if (0 != com2.BytesToRead) 527 { 528 Fail("ERROR!!! BytesToRead={0} expected 0", com2.BytesToRead); 529 } 530 531 //Verify that the bytes we sent were the same ones we received 532 int expectedIndex = 0, actualIndex = 0; 533 534 for (; expectedIndex < expectedBytes.Length && actualIndex < rcvBytes.Length; ++expectedIndex, ++actualIndex) 535 { 536 if (expectedBytes[expectedIndex] != rcvBytes[actualIndex]) 537 { 538 if (actualIndex != rcvBytes.Length - 1 && expectedBytes[expectedIndex] == rcvBytes[actualIndex + 1]) 539 { 540 //Sometimes if there is a parity error an extra byte gets added to the input stream so 541 //look ahead at the next byte 542 actualIndex++; 543 } 544 else 545 { 546 Debug.WriteLine("Bytes Sent:"); 547 TCSupport.PrintBytes(xmitBytes); 548 549 Debug.WriteLine("Bytes Recieved:"); 550 TCSupport.PrintBytes(rcvBytes); 551 552 Debug.WriteLine("Expected Bytes:"); 553 TCSupport.PrintBytes(expectedBytes); 554 555 Fail( 556 "ERROR: Expected to read {0,2:X} at {1,3} actually read {2,2:X} sent {3,2:X}", 557 expectedBytes[expectedIndex], 558 expectedIndex, 559 rcvBytes[actualIndex], 560 xmitBytes[expectedIndex]); 561 } 562 } 563 } 564 565 if (expectedIndex < expectedBytes.Length) 566 { 567 Fail("ERRROR: Did not enumerate all of the expected bytes index={0} length={1}", expectedIndex, expectedBytes.Length); 568 } 569 } 570 GetNumberOfStopBits(SerialPort com)571 private double GetNumberOfStopBits(SerialPort com) 572 { 573 double stopBits = -1; 574 575 switch (com.StopBits) 576 { 577 case StopBits.One: 578 stopBits = 1.0; 579 break; 580 581 case StopBits.OnePointFive: 582 stopBits = 1.5; 583 break; 584 585 case StopBits.Two: 586 stopBits = 2.0; 587 break; 588 589 default: 590 throw new ArgumentOutOfRangeException(); 591 } 592 return stopBits; 593 } 594 595 SetParityBit(byte parityByte, int dataBitSize, Parity parity)596 private byte SetParityBit(byte parityByte, int dataBitSize, Parity parity) 597 { 598 byte result; 599 600 if (8 == dataBitSize) 601 { 602 return parityByte; 603 } 604 605 switch (parity) 606 { 607 case Parity.Even: 608 if (VerifyEvenParity(parityByte, dataBitSize)) 609 result = (byte)(parityByte & (0xFF >> 8 - dataBitSize)); 610 else 611 result = (byte)(parityByte | (0x80 >> 8 - (dataBitSize + 1))); 612 613 break; 614 615 case Parity.Odd: 616 if (VerifyOddParity(parityByte, dataBitSize)) 617 result = (byte)(parityByte & (0xFF >> 8 - dataBitSize)); 618 else 619 result = (byte)(parityByte | (0x80 >> 8 - (dataBitSize + 1))); 620 621 break; 622 623 case Parity.Mark: 624 result = (byte)(parityByte | (0x80 >> 8 - (dataBitSize + 1))); 625 break; 626 627 case Parity.Space: 628 result = (byte)(parityByte & (0xFF >> 8 - dataBitSize)); 629 break; 630 631 default: 632 result = 0; 633 break; 634 } 635 if (7 > dataBitSize) 636 result &= (byte)(0xFF >> 8 - (dataBitSize + 1)); 637 638 return result; 639 } 640 641 VerifyParityByte(byte parityByte, int parityWordSize, Parity parity)642 private bool VerifyParityByte(byte parityByte, int parityWordSize, Parity parity) 643 { 644 switch (parity) 645 { 646 case Parity.Even: 647 return VerifyEvenParity(parityByte, parityWordSize); 648 649 case Parity.Odd: 650 return VerifyOddParity(parityByte, parityWordSize); 651 652 case Parity.Mark: 653 return VerifyMarkParity(parityByte, parityWordSize); 654 655 case Parity.Space: 656 return VerifySpaceParity(parityByte, parityWordSize); 657 658 default: 659 return false; 660 } 661 } 662 VerifyEvenParity(byte parityByte, int parityWordSize)663 private bool VerifyEvenParity(byte parityByte, int parityWordSize) 664 { 665 return (0 == CalcNumberOfTrueBits(parityByte, parityWordSize) % 2); 666 } 667 VerifyOddParity(byte parityByte, int parityWordSize)668 private bool VerifyOddParity(byte parityByte, int parityWordSize) 669 { 670 return (1 == CalcNumberOfTrueBits(parityByte, parityWordSize) % 2); 671 } 672 VerifyMarkParity(byte parityByte, int parityWordSize)673 private bool VerifyMarkParity(byte parityByte, int parityWordSize) 674 { 675 byte parityMask = 0x80; 676 677 parityByte <<= 8 - parityWordSize; 678 return (0 != (parityByte & parityMask)); 679 } 680 VerifySpaceParity(byte parityByte, int parityWordSize)681 private bool VerifySpaceParity(byte parityByte, int parityWordSize) 682 { 683 byte parityMask = 0x80; 684 685 parityByte <<= 8 - parityWordSize; 686 return (0 == (parityByte & parityMask)); 687 } 688 CalcNumberOfTrueBits(byte parityByte, int parityWordSize)689 private int CalcNumberOfTrueBits(byte parityByte, int parityWordSize) 690 { 691 byte parityMask = 0x80; 692 int numTrueBits = 0; 693 694 //Debug.WriteLine("parityByte={0}", System.Convert.ToString(parityByte, 16)); 695 parityByte <<= 8 - parityWordSize; 696 697 for (int i = 0; i < parityWordSize; i++) 698 { 699 if (0 != (parityByte & parityMask)) 700 numTrueBits++; 701 702 parityByte <<= 1; 703 } 704 705 //Debug.WriteLine("Number of true bits: {0}", numTrueBits); 706 return numTrueBits; 707 } 708 #endregion 709 } 710 } 711