In C I simply do a memcpy from my data buffer array to the address of my struct. I am not sure how to do this in C# for the desktop side of things. This is my struct in C#
struct frame_type
{
public UInt32 start_of_frame;
public UInt32 frame_id;
public UInt16 frame_len;
public UInt32 crc;
public UInt32 end_of_frame;
}
And I have a Datareceived serial port callback, the dataIn variable below is a string but obviously I can change it something else to make it easier to grab all those bytes and assemble the frame.
private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
dataIN = port.ReadExisting();
//increment variable and when i have 34 bytes assemble a frame
//and checkl if it is an ack frame.
bytes_received_count ;
if(bytes_received_count == 34)
{
//assemble a frame_type frame
}
this.Invoke(new EventHandler(sendFirmware));
}
So any suggestions are welcome.
CodePudding user response:
ok big caveat, I have no serial port so cannot test
MemoryStream buffer = new MemoryStream();
private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) {
for (int i = 0; i < port.BytesToRead; i ) {
if (buffer.Length == 34)
break;
// write needs an array even though its only 1
byte[] bytes = new bytes[1];
bytes[0] = port.ReadByte();
buffer.Write(bytes, 0, 1);
}
// ok we now have the next 34 bytes in buffer
var frame = new frame_type();
// rewind to the beginning
buffer.Seek(0, SeekOrigin.Begin);
using (var br = new BinaryReader(buffer)) {
frame.start_of_frame = br.ReadUInt32();
frame.frame_id = br.ReadUint32();
.......
}
// rewind to be ready for next block
buffer.Seek(0, SeekOrigin.Begin);
}
the core is using BinaryReader this reads serialized elements from a byte stream, ReadUInt32 pulls the next 4 bytes and marshalls to a UIn32 etc.
The fiddly bit is getting the bytes from thr port into a stream since we cant connect a stream directly to the port (I coulsnt see how to do it) so I use a MemoryStream which, as the name suggests , is a byte stream in memory
CodePudding user response:
In C I simply do a memcpy from my data buffer array to the address of my struct.
I suppose the following is something similar, but I'm not in a position to test it:
[StructLayout(LayoutKind.Sequential)]
struct frame_type
{
public UInt32 start_of_frame;
public UInt32 frame_id;
public UInt16 frame_len;
public UInt32 crc;
public UInt32 end_of_frame;
public static implicit operator frame_type(byte[] data)
{
unsafe
{
fixed (byte* b = &data[0])
{
return *(frame_type*)b;
}
}
}
}
It should allow you to just straight assign a byte array of length 18 to the struct
frame_type f = aByteArray18Long;
Of course, it is the root of all evil and a safe approach would perhaps look like:
static public implicit operator frame_type(byte[] b)
{
var f = new frame_type();
f.start_of_frame = (uint)(b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3]);
f.frame_id = (uint)(b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7]);
f.frame_len = (ushort)(b[8]<<8 | b[9]);
f.crc = (uint)(b[10]<<24 | b[11]<<16 | b[12]<<8 | b[13]);
f.end_of_frame = (uint)(b[14]<<24 | b[15]<<16 | b[16]<<8 | b[17]);
return f;
}
ps; it's perhaps easiest to get your bytes by something like:
var buf = new byte[18];
for(int x = 0; x<18; x )
buf[x] = port.Read();