public int InputDataProcess(byte[] data) { while (Interlocked.CompareExchange(ref rLock, 1, 0) == 0) { Thread.SpinWait(1); } #region write data to ring for (int i = 0; i < data.Length; i++) { ring[wPos] = data[i]; wPos = (wPos + 1) % rSize; rCnt++; } #endregion bool isStep = false; bool isEmpty = false; while (!isEmpty) { #region look for a packet start bool isPacketStart = false; while ((rCnt >= uMCPInoPacket.MIN_SIZE) && (!isPacketStart)) { if (ring[rPos] == uMCPIno.SIGN) { isPacketStart = true; } else { rPos = (rPos + 1) % rSize; rCnt--; } } #endregion if (isPacketStart) { #region try to parse int rPosCache = rPos; int rCntCache = rCnt; RingReadByte(rPosCache, rCntCache, out rPosCache, out rCntCache); // skip SIGN uMCPInoPacketType pType = (uMCPInoPacketType)RingReadByte(rPosCache, rCntCache, out rPosCache, out rCntCache); if (pType != uMCPInoPacketType.INVALID) { rPosCache = rPos; rCntCache = rCnt; if (rCntCache >= uMCPIno.HSIZE) { #region read header & its CRC var packet = RingRead(rPosCache, rCntCache, uMCPIno.HSIZE, out rPosCache, out rCntCache); byte declaredPacketCRC = packet[packet.Length - 1]; byte actualPacketCRC = CRC.CRC8_Get(packet, 0, packet.Length - 1); #endregion if (declaredPacketCRC == actualPacketCRC) { #region if ctrl header CRC is OK #region decode control header byte trcnt = packet[uMCPInoPacket.TRCNT_OFFSET]; byte tcnt = Convert.ToByte((trcnt >> 4) & 0x0F); byte rcnt = Convert.ToByte(trcnt & 0x0F); #endregion if ((pType != uMCPInoPacketType.DTA) && (pType != uMCPInoPacketType.DTE)) { isStep = true; packets.Add(new uMCPInoCTRLPacket(pType, tcnt, rcnt)); } else { #region DTA & DTE // try to get dcnt if (rCntCache > 1) { byte actualDBlockCRC = 0xFF; byte dcnt = RingReadByte(rPosCache, rCntCache, out rPosCache, out rCntCache); if (dcnt >= 1) { actualDBlockCRC = CRC.CRC8_Update(dcnt, actualDBlockCRC); if (rCntCache >= dcnt + 1) { var dataBlock = RingRead(rPosCache, rCntCache, dcnt, out rPosCache, out rCntCache); actualDBlockCRC = CRC.CRC8_Update(dataBlock, 0, dataBlock.Length, actualDBlockCRC); byte declaredDBlockCRC = RingReadByte(rPosCache, rCntCache, out rPosCache, out rCntCache); if (declaredDBlockCRC == actualDBlockCRC) { packets.Add(new uMCPInoDATAPacket(tcnt, rcnt, dataBlock, (pType == uMCPInoPacketType.DTE))); } isStep = true; // even if bad crc } else { // wait for data... isEmpty = true; } } else { // bad data block, use only header isStep = true; packets.Add(new uMCPInoCTRLPacket(uMCPInoPacketType.ACK, tcnt, rcnt)); } } else { // wait for data... isEmpty = true; } #endregion } #endregion } else { // bad crc, just skip it isStep = true; } } else { // leave, wait for data isEmpty = true; } } else { // bad or not a packet, skip isStep = true; } if (isStep) { rPos = rPosCache; rCnt = rCntCache; } #endregion } else { // no packet start found isEmpty = true; } } // while (!isEmpty)... Interlocked.Decrement(ref rLock); return(packets.Count); }