/// <summary> /// Request to read bytes from memory map /// </summary> /// <param name="serial">A double precision number.</param> /// <param name="addres">A double precision number.</param> /// <param name="bytesToRead">A double precision number.</param> /// <param name="timeut">A double precision number.</param> /// <returns> /// Memory Map values from read address request /// </returns> /// <example> /// <code> /// lx.Read(new USBSerial("COM5"), 0, 1, 400) /// </code> /// </example> /// <exception cref="System.TimeoutException">Thrown response Timeout is reached </exception> /// <exception cref="System.IO.InvalidDataException">Thrown when response data or CRC is not valid </exception> /// See <see cref="Read(UInt32 addres, uint data)"/> to add doubles. /// <seealso cref="Write(byte addres, byte[] data)"/> /// <seealso cref="Write(ISerial serial, UInt32 addres, byte[] data, int timeout)"/> private async Task <byte[]> Read(ISerial serial, UInt32 address, uint bytesToRead, int timeout) { int TEST = new Random().Next(0, 999); Utils.PrintDeep(Environment.NewLine + "--------LEXI_READ-------| " + TEST + " |--"); Utils.PrintDeep("Lexi.Read = Write + UpdateBuffer + Read"); try { byte[] stream; var info = GeneratePackage(LexiAction.Read, out stream, address, null, bytesToRead); Utils.PrintDeep("Lexi.Read.. " + "Stream = " + "0x" + info.header + " ( " + Convert.ToInt32(info.header, 16) + " ) + " + "WriteCmd 0x" + info.cmd + " ( " + Convert.ToInt32(info.cmd, 16) + " ) + " + "Address 0x" + info.startAddress + " ( " + Convert.ToInt32(info.startAddress, 16) + " ) + " + "Checksum 0x" + info.checksum + " ( " + Convert.ToInt32(info.checksum, 16) + " )"); Utils.PrintDeep("Lexi.Read.. " + Utils.ByteArrayToString(stream).Trim() + " [ Length " + stream.Length + " ]"); // Send Lexi Read command await serial.Write(stream, 0, stream.Length); Utils.PrintDeep("------BUFFER_START-------"); //define response buffer size byte[] rawBuffer = new byte[0]; int headerOffset = (serial.isEcho()) ? stream.Length : 0; Array.Resize(ref rawBuffer, headerOffset + ( int )bytesToRead + 2); // Package + Data + ACK Utils.PrintDeep("Lexi.Read -> Array.Resize.." + " Echo " + serial.isEcho() + " [ " + rawBuffer.Length + " = " + bytesToRead + " + Header " + headerOffset + " + CRC 2 ]"); // Whait untill the response buffer data is available or timeout limit is reached long timeout_limit = DateTimeOffset.Now.ToUnixTimeMilliseconds() + (timeout); await Task.Run(() => { while (checkResponseOk(serial, rawBuffer)) { if (DateTimeOffset.Now.ToUnixTimeMilliseconds() > timeout_limit) { int num = serial.BytesReadCount(); Utils.PrintDeep("Lexi.Read -> BytesToRead: " + num); if (num <= headerOffset) { Utils.PrintDeep("Lexi.Read -> CheckResponseOk IOException"); throw new IOException(); } else { Utils.PrintDeep("Lexi.Read -> CheckResponseOk TimeoutException"); throw new TimeoutException(); } } Thread.Sleep(10); } }); Utils.PrintDeep("------BUFFER_FINISH------"); //read the response buffer serial.Read(rawBuffer, 0, rawBuffer.Length); /* * +------------+-------+---------------+--------------------------------------------------------+ * | Byte Index | Field | Value(s) | Notes | * +------------+-------+---------------+--------------------------------------------------------+ * | 0..N-1 | Data | Read from RAM | N = number of bytes specified in Data field of Request | * | N..N+1 | CRC | Calculated | CRC over all data bytes. See section 7.2 | * +------------+-------+---------------+--------------------------------------------------------+ */ // Removes header and get only the ACK byte[] response = new byte[2]; Array.Resize(ref response, response.Length + ( int )bytesToRead); Array.Copy(rawBuffer, headerOffset, response, 0, response.Length); Utils.PrintDeep("Lexi.Read ->" + " CheckCRC " + Utils.ByteArrayToString(response) + " [ " + response.Length + " = BytesToRead " + bytesToRead + " + ACK 2 ]"); // Validates CRC and if everything is ok, returns recovered data return(validateReadResponse(response, bytesToRead)); } catch (Exception e) { throw new LexiReadingException(); } finally { Utils.PrintDeep("----LEXI_READ_FINISH----| " + TEST + " |--" + Environment.NewLine); } }