/// <summary> /// Generates frames for a broadcast transfer. /// </summary> /// <remarks> /// If the node is in passive mode, only single frame transfers will be allowed (they will be transmitted as anonymous). /// /// For anonymous transfers, maximum data type ID is limited to 3 (see specification for details). /// /// Pointer to the Transfer ID should point to a persistent variable and should be updated after every transmission. /// The Transfer ID value cannot be shared between transfers that have different descriptors. /// </remarks> public static IEnumerable <CanFrame> Broadcast( ulong dataTypeSignature, int dataTypeId, byte transferId, byte nodeId, UavcanPriority priority, byte[] payload, int payloadOffset, int payloadLen) { if (payload == null && payloadLen > 0) { throw new ArgumentException(nameof(payload)); } if (priority > UavcanPriority.Lowest) { throw new ArgumentException(nameof(priority)); } uint canId; ushort crc = Crc16.InitialValue; if (nodeId == 0) { if (payloadLen > 7) { throw new ArgumentException("Node ID expected.", nameof(nodeId)); } const ushort DTIDMask = (ushort)(1U << UavcanConstants.AnonymousMessageDataTypeIdBitLen) - 1; if ((dataTypeId & DTIDMask) != dataTypeId) { throw new ArgumentException(nameof(dataTypeId)); } // Anonymous transfer, random discriminator. ushort discriminator = (ushort)((Crc16.Add(Crc16.InitialValue, payload, payloadOffset, payloadLen)) & 0x7FFEU); canId = ((uint)priority << 24) | ((uint)discriminator << 9) | ((uint)(dataTypeId & DTIDMask) << 8) | nodeId; } else { canId = ((uint)priority << 24) | ((uint)dataTypeId << 8) | nodeId; if (payloadLen > 7) { crc = Crc16.AddSignature(crc, dataTypeSignature); crc = Crc16.Add(crc, payload, payloadOffset, payloadLen); } } return(CreateTxFrames(canId, transferId, crc, payload, payloadOffset, payloadLen)); }
/// <summary> /// Generates frames for a request or a response transfer. /// </summary> /// <remarks> /// Fails if the node is in passive mode. /// /// Pointer to the Transfer ID should point to a persistent variable and should be updated after every transmission. /// The Transfer ID value cannot be shared between transfers that have different descriptors. /// </remarks> public static IEnumerable <CanFrame> RequestOrRespond( int destinationNodeId, ulong dataTypeSignature, int dataTypeId, byte transferId, byte nodeId, UavcanPriority priority, UavcanRequestResponse kind, byte[] payload, int payloadOffset, int payloadLen) { if ((destinationNodeId < UavcanConstants.MinNodeId) || (destinationNodeId > UavcanConstants.MaxNodeId)) { throw new ArgumentOutOfRangeException(nameof(destinationNodeId)); } if (payload == null && payloadLen > 0) { throw new ArgumentException(nameof(payload)); } if (priority > UavcanPriority.Lowest) { throw new ArgumentException(nameof(priority)); } if (nodeId == UavcanConstants.BroadcastNodeId) { throw new ArgumentException("Anonymous node can send broadcast messages only.", nameof(nodeId)); } uint canId = ((uint)priority << 24) | ((uint)dataTypeId << 16) | ((uint)kind << 15) | ((uint)destinationNodeId << 8) | (1U << 7) | nodeId; ushort crc = Crc16.InitialValue; if (payloadLen > 7) { crc = Crc16.AddSignature(crc, dataTypeSignature); crc = Crc16.Add(crc, payload, payloadOffset, payloadLen); } return(CreateTxFrames(canId, transferId, crc, payload, payloadOffset, payloadLen)); }
public void Crc16Test1() { var dtCrc = Crc16.AddSignature(Crc16.InitialValue, 0xEE468A8121C46A9E); Assert.Equal(0xD9A7, dtCrc); }