Пример #1
0
        /// <summary>
        /// Writes frame to the CAN Bus
        /// </summary>
        /// <param name="data">Data to write (at most 8 bytes)</param>
        /// <param name="id">Recipient identifier</param>
        /// <remarks><paramref name="id"/> can be ignored by recipient - anyone connected to the bus can read or write any frames</remarks>
        public void WriteFrame(ReadOnlySpan <byte> data, CanId id)
        {
            if (!id.IsValid)
            {
                throw new ArgumentException(nameof(id), "Id is not valid. Ensure Error flag is not set and that id is in the valid range (11-bit for standard frame and 29-bit for extended frame).");
            }

            if (data.Length > CanFrame.MaxLength)
            {
                throw new ArgumentException(nameof(data), $"Data length cannot exceed {CanFrame.MaxLength} bytes.");
            }

            CanFrame frame = new CanFrame();

            frame.Id     = id;
            frame.Length = (byte)data.Length;
            Debug.Assert(frame.IsValid);

            unsafe
            {
                Span <byte> frameData = new Span <byte>(frame.Data, data.Length);
                data.CopyTo(frameData);
            }

            ReadOnlySpan <CanFrame> frameSpan = MemoryMarshal.CreateReadOnlySpan(ref frame, 1);
            ReadOnlySpan <byte>     buff      = MemoryMarshal.AsBytes(frameSpan);

            Interop.Write(_handle, buff);
        }
Пример #2
0
        /// <summary>
        /// Writes frame to the CAN Bus
        /// </summary>
        /// <param name="data">Data to write (at most 8 bytes)</param>
        /// <param name="id">Recipient identifier</param>
        /// <remarks><paramref name="id"/> can be ignored by recipient - anyone connected to the bus can read or write any frames</remarks>
        public void WriteFrame(ReadOnlySpan <byte> data, CanId id)
        {
            if (!id.IsValid)
            {
                throw new ArgumentException("Id is not valid. Ensure Error flag is not set and that id is in the valid range (11-bit for standard frame and 29-bit for extended frame).", nameof(id));
            }

            if (data.Length > CanFrame.MaxLength)
            {
                throw new ArgumentException($"Data length cannot exceed {CanFrame.MaxLength} bytes.", nameof(data));
            }

            CanFrame frame = new CanFrame();

            frame.Id     = id;
            frame.Length = (byte)data.Length;
            Debug.Assert(frame.IsValid, "Frame is not valid");

            unsafe
            {
                Span <byte> frameData = new Span <byte>(frame.Data, data.Length);
                data.CopyTo(frameData);

                byte *buff = (byte *)&frame;
                Interop.Write(_handle, buff, Marshal.SizeOf <CanFrame>());
            }
        }
Пример #3
0
        /// <summary>
        /// Reads frame from the bus
        /// </summary>
        /// <param name="data">Data where output data should be written to</param>
        /// <param name="frameLength">Length of the data read</param>
        /// <param name="id">Recipient identifier</param>
        /// <returns></returns>
        public bool TryReadFrame(Span <byte> data, out int frameLength, out CanId id)
        {
            if (data.Length < CanFrame.MaxLength)
            {
                throw new ArgumentException($"Value must be a minimum of {CanFrame.MaxLength} bytes.", nameof(data));
            }

            CanFrame frame = new CanFrame();

            int remainingBytes = Marshal.SizeOf <CanFrame>();

            unsafe
            {
                while (remainingBytes > 0)
                {
                    int read = Interop.Read(_handle, (byte *)&frame, remainingBytes);
                    remainingBytes -= read;
                }
            }

            id          = frame.Id;
            frameLength = frame.Length;

            if (!frame.IsValid)
            {
                // invalid frame
                // we will leave id filled in case it is useful for anyone
                frameLength = 0;
                return(false);
            }

            // This is guaranteed by minimum buffer length and the fact that frame is valid
            Debug.Assert(frame.Length <= data.Length, "Invalid frame length");

            unsafe
            {
                // We should not use input buffer directly for reading:
                // - we do not know how many bytes will be read up front without reading length first
                // - we should not write anything more than pointed by frameLength
                // - we still need to read the remaining bytes to read the full frame
                // Considering there are at most 8 bytes to read it is cheaper
                // to copy rather than doing multiple syscalls.
                Span <byte> frameData = new Span <byte>(frame.Data, frame.Length);
                frameData.CopyTo(data);
            }

            return(true);
        }
Пример #4
0
        public bool TryReadFrame(Span <byte> buffer, out int frameLength, out CanId id)
        {
            if (buffer.Length < CanFrame.MaxLength)
            {
                throw new ArgumentException($"Buffer length must be at minimum {CanFrame.MaxLength} bytes", nameof(buffer));
            }

            CanFrame frame = new CanFrame();

            Span <CanFrame> frameSpan = MemoryMarshal.CreateSpan(ref frame, 1);
            Span <byte>     buff      = MemoryMarshal.AsBytes(frameSpan);

            while (buff.Length > 0)
            {
                int read = Interop.Read(_handle, buff);
                buff = buff.Slice(read);
            }

            id          = frame.Id;
            frameLength = frame.Length;

            if (!frame.IsValid)
            {
                // invalid frame
                // we will leave id filled in case it is useful for anyone
                frameLength = 0;
                return(false);
            }

            // This is guaranteed by minimum buffer length and the fact that frame is valid
            Debug.Assert(frame.Length <= buffer.Length);

            unsafe
            {
                // We should not use input buffer directly for reading:
                // - we do not know how many bytes will be read up front without reading length first
                // - we should not write anything more than pointed by frameLength
                // - we still need to read the remaining bytes to read the full frame
                // Considering there are at most 8 bytes to read it is cheaper
                // to copy rather than doing multiple syscalls.
                Span <byte> frameData = new Span <byte>(frame.Data, frame.Length);
                frameData.CopyTo(buffer);
            }

            return(true);
        }