/// <summary> /// Function used for packet transmission in xmodem protocol /// </summary> private static void TransmitPacket(Sym mode) { if (mode == Sym.NAK) { PortWriteByte((byte)Sym.SOH); // Sending StartOfHeader symbol for packet initialization //Console.WriteLine("SOH") } else if (mode == Sym.C) { PortWriteByte((byte)Sym.C); // Sending C symbol for CRC packet initialization } else { throw new Exception("Bad protocol mode passed"); } if (seq == 0) { seq = 1; } PortWriteByte(seq); // Sending sequence number //Console.WriteLine("seq: " + seq); PortWriteByte((byte)(255 - (255 & seq))); // Calculating and sending the complement of seq //Console.WriteLine("cmpl: " + (byte)(255 - seq)); seq++; // Increasing the sequence number // Copying 128 bytes of data to transmit // If there is any underflow, the following bytes will be left null (0) byte[] temp = new byte[128]; Array.Copy(transmitData, offset, temp, 0, transmitData.Length - offset >= 128 ? 128 : transmitData.Length - offset); offset += 128; //DisplayData(temp); // Sending 128 bytes of data port.Write(temp, 0, 128); if (mode == Sym.NAK) { // Calculating and sending checksum PortWriteByte(Checksum(temp)); } else if (mode == Sym.C) { ShiftRegister register = new ShiftRegister(temp, true); ushort crcOut = register.CalcCRC_16(); PortWriteByte((byte)(crcOut >> 8)); PortWriteByte((byte)crcOut); } // Wait for accept from the receiver Sym result = WaitForAny(10); if (result == Sym.NAK) { // If cheksum was incorrect - transmit packet once again Console.WriteLine("Bad checksum!"); offset -= 128; } else if (result != Sym.ACK) { throw new InvalidOperationException(); } }
private static Sym ReceivePacket(int timeoutSeconds, Sym protocolMode) { port.ReadTimeout = timeoutSeconds * 1000; byte byteBuffer = 0; byte[] dataBuffer = new byte[128]; byteBuffer = (byte)port.ReadByte(); //First time (for seq == 1) it shouldn't check for SOH, as the initialization has already read the SOH byte to check if data is coming if (!first) { if (byteBuffer == (byte)Sym.SOH || byteBuffer == (byte)Sym.C) { byteBuffer = (byte)port.ReadByte(); // Here the seq number should be read Console.WriteLine("Seq: " + byteBuffer); } else if (byteBuffer == (byte)Sym.EOT) { Console.WriteLine("Received EOT, cleaning up..."); return(Sym.EOT); } else if (byteBuffer == (byte)Sym.CAN) { throw new Exception("File transfer cancelled"); } } else { first = false; } // This isn't the best way to do this, but it works so whatever. if (byteBuffer == seq) { // seq number received succesfully byteBuffer = (byte)port.ReadByte(); // Here the cmpl seq should be read if (byteBuffer == 255 - (255 & seq)) { // cmpl seq received succesfully // Increase seq seq++; if (seq == 0) { seq = 1; //Never let seq be 0, or the whole thing will fall apart } // Reading 128 bytes of data for (int i = 0; i < 128; i++) { dataBuffer[i] = (byte)port.ReadByte(); } Console.WriteLine("Received data:"); DisplayData(dataBuffer); // Verifying checksum // Warning! Here should be the switch for the checksum/CRC transmission if (protocolMode == Sym.NAK) { byteBuffer = (byte)port.ReadByte(); if (byteBuffer != Checksum(dataBuffer)) { //Handle wrong checksum return(Sym.NAK); } else { //Handle succesful checksum //Copy all bytes from buffer to receivedData foreach (byte elem in dataBuffer) { receivedData.Enqueue(elem); } return(Sym.ACK); } } else if (protocolMode == Sym.C) { byte[] dataCrc = new byte[130]; dataBuffer.CopyTo(dataCrc, 0); dataCrc[128] = (byte)port.ReadByte(); dataCrc[129] = (byte)port.ReadByte(); ShiftRegister register = new ShiftRegister(dataCrc, false); if (register.CalcCRC_16() == 0) { // Crc ok, proceed foreach (byte elem in dataBuffer) { receivedData.Enqueue(elem); } return(Sym.ACK); } else { // Bad crc, repeat process Console.WriteLine("Bad crc received, requesting retry."); return(Sym.NAK); } } } else { throw new Exception("Bad complement of seq received!"); } } else { throw new Exception("Bad symbol or seq number!"); } throw new InvalidOperationException("Reached unwanted area of ReceivePacket function!"); }