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 >= uMCPPacket.MIN_SIZE) && (!isPacketStart)) { if (ring[rPos] == uMCP.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 uMCPPacketType pType = (uMCPPacketType)RingReadByte(rPosCache, rCntCache, out rPosCache, out rCntCache); if (pType != uMCPPacketType.INVALID) { int hSize; rPosCache = rPos; rCntCache = rCnt; if ((pType == uMCPPacketType.STR) || (pType == uMCPPacketType.STA)) { hSize = uMCP.STASTR_HSIZE; } else if (pType == uMCPPacketType.REP) { hSize = uMCP.REP_HSIZE; } else { hSize = uMCP.ACKDTA_HSIZE; } if (rCntCache >= hSize) { #region read header & its CRC var packet = RingRead(rPosCache, rCntCache, 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 packet CRC is OK #region decode control header byte sid = packet[uMCPPacket.SID_OFFSET]; byte tid = packet[uMCPPacket.TID_OFFSET]; #endregion if ((pType == uMCPPacketType.STR) || (pType == uMCPPacketType.STA)) { #region STR & STA isStep = true; packets.Add(new uMCPSTPacket(pType, sid, tid)); #endregion } else { byte tcnt = packet[uMCPPacket.RCNT_OFFSET]; if (pType == uMCPPacketType.REP) { #region REP isStep = true; packets.Add(new uMCPREPPacket(sid, tid, tcnt)); #endregion } else { byte rcnt = packet[uMCPPacket.TCNT_OFFSET]; if (pType == uMCPPacketType.ACK) { #region ACK isStep = true; packets.Add(new uMCPACKPacket(sid, tid, rcnt, tcnt)); #endregion } 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 uMCPDATAPacket(sid, tid, rcnt, tcnt, dataBlock, (pType == uMCPPacketType.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 uMCPACKPacket(sid, tid, rcnt, tcnt)); } } 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); }