diff --git a/docs/README.md b/docs/README.md index 7a1260b..c2ca368 100644 --- a/docs/README.md +++ b/docs/README.md @@ -60,7 +60,7 @@ var implementation = generator.GenerateImplementation(); ## Generating Python interface code -Assuming the `deviceMetadata` object loaded above is available, a Python interface targeting the [pyharp](https://github.com/harp-tech/pyharp) register and payload API can be generated from the same metadata. +Assuming the `deviceMetadata` object loaded above is available, an interface targeting [Harp Python](https://harp-tech.org/python) can be generated from the same metadata. ```csharp ... diff --git a/src/Python.cs b/src/Python.cs index 53b1c51..c66620c 100644 --- a/src/Python.cs +++ b/src/Python.cs @@ -455,7 +455,7 @@ static PythonField BuildPythonField( if (string.IsNullOrEmpty(member.InterfaceType)) { module.ProtocolImports.Add("IdentityConverter"); - if (memberLength > 1) + if (memberLength > 0) { module.UsesNDArray = true; return new PythonField @@ -524,7 +524,7 @@ static string GetMemberAnnotation(PayloadMemberInfo member, RegisterInfo registe static string GetPythonDefaultArgument(PayloadMemberInfo member, string typeName, RegisterInfo register, DeviceInfo deviceMetadata) { var defaultValue = member.DefaultValue ?? member.MinValue; - if (!defaultValue.HasValue || member.Length > 1) + if (!defaultValue.HasValue || member.Length > 0) return string.Empty; var value = defaultValue.GetValueOrDefault(); diff --git a/tests/ExpectedOutput/device.app_funcs.c b/tests/ExpectedOutput/device.app_funcs.c index ea3572a..4dbe860 100644 --- a/tests/ExpectedOutput/device.app_funcs.c +++ b/tests/ExpectedOutput/device.app_funcs.c @@ -21,6 +21,9 @@ void (*app_func_rd_pointer[])(void) = { &app_read_REG_PORT_DIO_SET, &app_read_REG_PULSE_DO_PORT0, &app_read_REG_PULSE_DO0, + &app_read_REG_MULTI_ELEMENT_PAYLOAD, + &app_read_REG_SINGLE_ELEMENT_PAYLOAD, + &app_read_REG_MIXED_MEMBER_LENGTH, &app_read_REG_START_PULSE, &app_read_REG_START_PULSE_TRAIN, &app_read_REG_ENCODER_MODE @@ -39,6 +42,9 @@ bool (*app_func_wr_pointer[])(void*) = { &app_write_REG_PORT_DIO_SET, &app_write_REG_PULSE_DO_PORT0, &app_write_REG_PULSE_DO0, + &app_write_REG_MULTI_ELEMENT_PAYLOAD, + &app_write_REG_SINGLE_ELEMENT_PAYLOAD, + &app_write_REG_MIXED_MEMBER_LENGTH, &app_write_REG_START_PULSE, &app_write_REG_START_PULSE_TRAIN, &app_write_REG_ENCODER_MODE @@ -212,6 +218,60 @@ bool app_write_REG_PULSE_DO0(void *a) return true; } +/************************************************************************/ +/* REG_MULTI_ELEMENT_PAYLOAD */ +/************************************************************************/ +// This register is an array with 3 positions +void app_read_REG_MULTI_ELEMENT_PAYLOAD(void) +{ + //app_regs.REG_MULTI_ELEMENT_PAYLOAD[0] = 0; + +} + +bool app_write_REG_MULTI_ELEMENT_PAYLOAD(void *a) +{ + uint16_t *reg = ((uint16_t*)a); + + app_regs.REG_MULTI_ELEMENT_PAYLOAD[0] = reg[0]; + return true; +} + +/************************************************************************/ +/* REG_SINGLE_ELEMENT_PAYLOAD */ +/************************************************************************/ +// This register is an array with 1 positions +void app_read_REG_SINGLE_ELEMENT_PAYLOAD(void) +{ + //app_regs.REG_SINGLE_ELEMENT_PAYLOAD[0] = 0; + +} + +bool app_write_REG_SINGLE_ELEMENT_PAYLOAD(void *a) +{ + uint16_t *reg = ((uint16_t*)a); + + app_regs.REG_SINGLE_ELEMENT_PAYLOAD[0] = reg[0]; + return true; +} + +/************************************************************************/ +/* REG_MIXED_MEMBER_LENGTH */ +/************************************************************************/ +// This register is an array with 4 positions +void app_read_REG_MIXED_MEMBER_LENGTH(void) +{ + //app_regs.REG_MIXED_MEMBER_LENGTH[0] = 0; + +} + +bool app_write_REG_MIXED_MEMBER_LENGTH(void *a) +{ + uint8_t *reg = ((uint8_t*)a); + + app_regs.REG_MIXED_MEMBER_LENGTH[0] = reg[0]; + return true; +} + /************************************************************************/ /* REG_START_PULSE */ /************************************************************************/ diff --git a/tests/ExpectedOutput/device.app_funcs.h b/tests/ExpectedOutput/device.app_funcs.h index f247f28..e743107 100644 --- a/tests/ExpectedOutput/device.app_funcs.h +++ b/tests/ExpectedOutput/device.app_funcs.h @@ -32,6 +32,9 @@ void app_read_REG_COUNTER0(void); void app_read_REG_PORT_DIO_SET(void); void app_read_REG_PULSE_DO_PORT0(void); void app_read_REG_PULSE_DO0(void); +void app_read_REG_MULTI_ELEMENT_PAYLOAD(void); +void app_read_REG_SINGLE_ELEMENT_PAYLOAD(void); +void app_read_REG_MIXED_MEMBER_LENGTH(void); void app_read_REG_START_PULSE(void); void app_read_REG_START_PULSE_TRAIN(void); void app_read_REG_ENCODER_MODE(void); @@ -48,6 +51,9 @@ bool app_write_REG_COUNTER0(void *a); bool app_write_REG_PORT_DIO_SET(void *a); bool app_write_REG_PULSE_DO_PORT0(void *a); bool app_write_REG_PULSE_DO0(void *a); +bool app_write_REG_MULTI_ELEMENT_PAYLOAD(void *a); +bool app_write_REG_SINGLE_ELEMENT_PAYLOAD(void *a); +bool app_write_REG_MIXED_MEMBER_LENGTH(void *a); bool app_write_REG_START_PULSE(void *a); bool app_write_REG_START_PULSE_TRAIN(void *a); bool app_write_REG_ENCODER_MODE(void *a); diff --git a/tests/ExpectedOutput/device.app_ios_and_regs.c b/tests/ExpectedOutput/device.app_ios_and_regs.c index 7609ccf..14413dc 100644 --- a/tests/ExpectedOutput/device.app_ios_and_regs.c +++ b/tests/ExpectedOutput/device.app_ios_and_regs.c @@ -78,6 +78,9 @@ uint8_t app_regs_type[] = { TYPE_U16, TYPE_U16, TYPE_U16, + TYPE_U8, + TYPE_U16, + TYPE_U16, TYPE_U8 }; @@ -94,6 +97,9 @@ uint16_t app_regs_n_elements[] = { 1, 1, 1, + 3, + 1, + 4, 1, 2, 1 @@ -112,6 +118,9 @@ uint8_t *app_regs_pointer[] = { (uint8_t*)(&app_regs.REG_PORT_DIO_SET), (uint8_t*)(&app_regs.REG_PULSE_DO_PORT0), (uint8_t*)(&app_regs.REG_PULSE_DO0), + (uint8_t*)(&app_regs.REG_MULTI_ELEMENT_PAYLOAD), + (uint8_t*)(&app_regs.REG_SINGLE_ELEMENT_PAYLOAD), + (uint8_t*)(&app_regs.REG_MIXED_MEMBER_LENGTH), (uint8_t*)(&app_regs.REG_START_PULSE), (uint8_t*)(&app_regs.REG_START_PULSE_TRAIN), (uint8_t*)(&app_regs.REG_ENCODER_MODE) diff --git a/tests/ExpectedOutput/device.app_ios_and_regs.h b/tests/ExpectedOutput/device.app_ios_and_regs.h index 8b630ec..9591353 100644 --- a/tests/ExpectedOutput/device.app_ios_and_regs.h +++ b/tests/ExpectedOutput/device.app_ios_and_regs.h @@ -143,6 +143,9 @@ typedef struct uint8_t REG_PORT_DIO_SET; uint16_t REG_PULSE_DO_PORT0; uint16_t REG_PULSE_DO0; + uint16_t REG_MULTI_ELEMENT_PAYLOAD[3]; + uint16_t REG_SINGLE_ELEMENT_PAYLOAD[1]; + uint8_t REG_MIXED_MEMBER_LENGTH[4]; uint16_t REG_START_PULSE; uint16_t REG_START_PULSE_TRAIN[2]; uint8_t REG_ENCODER_MODE; @@ -164,6 +167,9 @@ typedef struct #define ADD_REG_PORT_DIO_SET 41 // U8 #define ADD_REG_PULSE_DO_PORT0 42 // U16 #define ADD_REG_PULSE_DO0 43 // U16 +#define ADD_REG_MULTI_ELEMENT_PAYLOAD 44 // U16 +#define ADD_REG_SINGLE_ELEMENT_PAYLOAD 45 // U16 +#define ADD_REG_MIXED_MEMBER_LENGTH 46 // U8 #define ADD_REG_START_PULSE 100 // U16 Starts a PWM pulse. #define ADD_REG_START_PULSE_TRAIN 101 // U16 Starts a PWM pulse train. #define ADD_REG_ENCODER_MODE 103 // U8 Configures the operation mode of the encoder. @@ -177,7 +183,7 @@ typedef struct /* Memory limits */ #define APP_REGS_ADD_MIN 0x20 #define APP_REGS_ADD_MAX 0x67 -#define APP_NBYTES_OF_REG_BANK 118 +#define APP_NBYTES_OF_REG_BANK 130 /************************************************************************/ /* Registers' bits */ diff --git a/tests/ExpectedOutput/device.async.cs b/tests/ExpectedOutput/device.async.cs index 2b36d15..344db4d 100644 --- a/tests/ExpectedOutput/device.async.cs +++ b/tests/ExpectedOutput/device.async.cs @@ -502,6 +502,144 @@ public async Task WritePulseDO0Async(ushort value, CancellationToken cancellatio await CommandAsync(request, cancellationToken); } + /// + /// Asynchronously reads the contents of the register. + /// + /// + /// A which can be used to cancel the operation. + /// + /// + /// A task that represents the asynchronous read operation. The task result contains + /// the register payload. + /// + public async Task ReadMultiElementPayloadAsync(CancellationToken cancellationToken = default) + { + var reply = await CommandAsync(HarpCommand.ReadUInt16(MultiElementPayload.Address), cancellationToken); + return MultiElementPayload.GetPayload(reply); + } + + /// + /// Asynchronously reads the timestamped contents of the register. + /// + /// + /// A which can be used to cancel the operation. + /// + /// + /// A task that represents the asynchronous read operation. The task result contains + /// the timestamped register payload. + /// + public async Task> ReadTimestampedMultiElementPayloadAsync(CancellationToken cancellationToken = default) + { + var reply = await CommandAsync(HarpCommand.ReadUInt16(MultiElementPayload.Address), cancellationToken); + return MultiElementPayload.GetTimestampedPayload(reply); + } + + /// + /// Asynchronously writes a value to the register. + /// + /// The value to write in the register. + /// + /// A which can be used to cancel the operation. + /// + /// The task object representing the asynchronous write operation. + public async Task WriteMultiElementPayloadAsync(ushort[] value, CancellationToken cancellationToken = default) + { + var request = MultiElementPayload.FromPayload(MessageType.Write, value); + await CommandAsync(request, cancellationToken); + } + + /// + /// Asynchronously reads the contents of the register. + /// + /// + /// A which can be used to cancel the operation. + /// + /// + /// A task that represents the asynchronous read operation. The task result contains + /// the register payload. + /// + public async Task ReadSingleElementPayloadAsync(CancellationToken cancellationToken = default) + { + var reply = await CommandAsync(HarpCommand.ReadUInt16(SingleElementPayload.Address), cancellationToken); + return SingleElementPayload.GetPayload(reply); + } + + /// + /// Asynchronously reads the timestamped contents of the register. + /// + /// + /// A which can be used to cancel the operation. + /// + /// + /// A task that represents the asynchronous read operation. The task result contains + /// the timestamped register payload. + /// + public async Task> ReadTimestampedSingleElementPayloadAsync(CancellationToken cancellationToken = default) + { + var reply = await CommandAsync(HarpCommand.ReadUInt16(SingleElementPayload.Address), cancellationToken); + return SingleElementPayload.GetTimestampedPayload(reply); + } + + /// + /// Asynchronously writes a value to the register. + /// + /// The value to write in the register. + /// + /// A which can be used to cancel the operation. + /// + /// The task object representing the asynchronous write operation. + public async Task WriteSingleElementPayloadAsync(ushort[] value, CancellationToken cancellationToken = default) + { + var request = SingleElementPayload.FromPayload(MessageType.Write, value); + await CommandAsync(request, cancellationToken); + } + + /// + /// Asynchronously reads the contents of the register. + /// + /// + /// A which can be used to cancel the operation. + /// + /// + /// A task that represents the asynchronous read operation. The task result contains + /// the register payload. + /// + public async Task ReadMixedMemberLengthAsync(CancellationToken cancellationToken = default) + { + var reply = await CommandAsync(HarpCommand.ReadByte(MixedMemberLength.Address), cancellationToken); + return MixedMemberLength.GetPayload(reply); + } + + /// + /// Asynchronously reads the timestamped contents of the register. + /// + /// + /// A which can be used to cancel the operation. + /// + /// + /// A task that represents the asynchronous read operation. The task result contains + /// the timestamped register payload. + /// + public async Task> ReadTimestampedMixedMemberLengthAsync(CancellationToken cancellationToken = default) + { + var reply = await CommandAsync(HarpCommand.ReadByte(MixedMemberLength.Address), cancellationToken); + return MixedMemberLength.GetTimestampedPayload(reply); + } + + /// + /// Asynchronously writes a value to the register. + /// + /// The value to write in the register. + /// + /// A which can be used to cancel the operation. + /// + /// The task object representing the asynchronous write operation. + public async Task WriteMixedMemberLengthAsync(MixedMemberLengthPayload value, CancellationToken cancellationToken = default) + { + var request = MixedMemberLength.FromPayload(MessageType.Write, value); + await CommandAsync(request, cancellationToken); + } + /// /// Asynchronously reads the contents of the register. /// diff --git a/tests/ExpectedOutput/device.cs b/tests/ExpectedOutput/device.cs index 82436b7..f2317e1 100644 --- a/tests/ExpectedOutput/device.cs +++ b/tests/ExpectedOutput/device.cs @@ -49,6 +49,9 @@ public Device() : base(WhoAmI) { } { 41, typeof(PortDIOSet) }, { 42, typeof(PulseDOPort0) }, { 43, typeof(PulseDO0) }, + { 44, typeof(MultiElementPayload) }, + { 45, typeof(SingleElementPayload) }, + { 46, typeof(MixedMemberLength) }, { 100, typeof(StartPulse) }, { 101, typeof(StartPulseTrain) }, { 103, typeof(EncoderMode) } @@ -278,6 +281,9 @@ public IObservable> Process(IObservable /// /// + /// + /// + /// /// /// /// @@ -293,6 +299,9 @@ public IObservable> Process(IObservable /// /// + /// + /// + /// /// /// /// @@ -344,6 +356,9 @@ string INamedElement.Name [XmlInclude(typeof(PortDIOSet))] [XmlInclude(typeof(PulseDOPort0))] [XmlInclude(typeof(PulseDO0))] + [XmlInclude(typeof(MultiElementPayload))] + [XmlInclude(typeof(SingleElementPayload))] + [XmlInclude(typeof(MixedMemberLength))] [XmlInclude(typeof(StartPulse))] [XmlInclude(typeof(StartPulseTrain))] [XmlInclude(typeof(EncoderMode))] @@ -359,6 +374,9 @@ string INamedElement.Name [XmlInclude(typeof(TimestampedPortDIOSet))] [XmlInclude(typeof(TimestampedPulseDOPort0))] [XmlInclude(typeof(TimestampedPulseDO0))] + [XmlInclude(typeof(TimestampedMultiElementPayload))] + [XmlInclude(typeof(TimestampedSingleElementPayload))] + [XmlInclude(typeof(TimestampedMixedMemberLength))] [XmlInclude(typeof(TimestampedStartPulse))] [XmlInclude(typeof(TimestampedStartPulseTrain))] [XmlInclude(typeof(TimestampedEncoderMode))] @@ -392,6 +410,9 @@ public Parse() /// /// /// + /// + /// + /// /// /// /// @@ -407,6 +428,9 @@ public Parse() [XmlInclude(typeof(PortDIOSet))] [XmlInclude(typeof(PulseDOPort0))] [XmlInclude(typeof(PulseDO0))] + [XmlInclude(typeof(MultiElementPayload))] + [XmlInclude(typeof(SingleElementPayload))] + [XmlInclude(typeof(MixedMemberLength))] [XmlInclude(typeof(StartPulse))] [XmlInclude(typeof(StartPulseTrain))] [XmlInclude(typeof(EncoderMode))] @@ -1700,6 +1724,314 @@ public static Timestamped GetPayload(HarpMessage message) } } + /// + /// Represents a register that manipulates messages from register MultiElementPayload. + /// + [Description("")] + public partial class MultiElementPayload + { + /// + /// Represents the address of the register. This field is constant. + /// + public const int Address = 44; + + /// + /// Represents the payload type of the register. This field is constant. + /// + public const PayloadType RegisterType = PayloadType.U16; + + /// + /// Represents the length of the register. This field is constant. + /// + public const int RegisterLength = 3; + + /// + /// Returns the payload data for register messages. + /// + /// A object representing the register message. + /// A value representing the message payload. + public static ushort[] GetPayload(HarpMessage message) + { + return message.GetPayloadArray(); + } + + /// + /// Returns the timestamped payload data for register messages. + /// + /// A object representing the register message. + /// A value representing the timestamped message payload. + public static Timestamped GetTimestampedPayload(HarpMessage message) + { + return message.GetTimestampedPayloadArray(); + } + + /// + /// Returns a Harp message for the register. + /// + /// The type of the Harp message. + /// The value to be stored in the message payload. + /// + /// A object for the register + /// with the specified message type and payload. + /// + public static HarpMessage FromPayload(MessageType messageType, ushort[] value) + { + return HarpMessage.FromUInt16(Address, messageType, value); + } + + /// + /// Returns a timestamped Harp message for the + /// register. + /// + /// The timestamp of the message payload, in seconds. + /// The type of the Harp message. + /// The value to be stored in the message payload. + /// + /// A object for the register + /// with the specified message type, timestamp, and payload. + /// + public static HarpMessage FromPayload(double timestamp, MessageType messageType, ushort[] value) + { + return HarpMessage.FromUInt16(Address, timestamp, messageType, value); + } + } + + /// + /// Provides methods for manipulating timestamped messages from the + /// MultiElementPayload register. + /// + /// + [Description("Filters and selects timestamped messages from the MultiElementPayload register.")] + public partial class TimestampedMultiElementPayload + { + /// + /// Represents the address of the register. This field is constant. + /// + public const int Address = MultiElementPayload.Address; + + /// + /// Returns timestamped payload data for register messages. + /// + /// A object representing the register message. + /// A value representing the timestamped message payload. + public static Timestamped GetPayload(HarpMessage message) + { + return MultiElementPayload.GetTimestampedPayload(message); + } + } + + /// + /// Represents a register that manipulates messages from register SingleElementPayload. + /// + [Description("")] + public partial class SingleElementPayload + { + /// + /// Represents the address of the register. This field is constant. + /// + public const int Address = 45; + + /// + /// Represents the payload type of the register. This field is constant. + /// + public const PayloadType RegisterType = PayloadType.U16; + + /// + /// Represents the length of the register. This field is constant. + /// + public const int RegisterLength = 1; + + /// + /// Returns the payload data for register messages. + /// + /// A object representing the register message. + /// A value representing the message payload. + public static ushort[] GetPayload(HarpMessage message) + { + return message.GetPayloadArray(); + } + + /// + /// Returns the timestamped payload data for register messages. + /// + /// A object representing the register message. + /// A value representing the timestamped message payload. + public static Timestamped GetTimestampedPayload(HarpMessage message) + { + return message.GetTimestampedPayloadArray(); + } + + /// + /// Returns a Harp message for the register. + /// + /// The type of the Harp message. + /// The value to be stored in the message payload. + /// + /// A object for the register + /// with the specified message type and payload. + /// + public static HarpMessage FromPayload(MessageType messageType, ushort[] value) + { + return HarpMessage.FromUInt16(Address, messageType, value); + } + + /// + /// Returns a timestamped Harp message for the + /// register. + /// + /// The timestamp of the message payload, in seconds. + /// The type of the Harp message. + /// The value to be stored in the message payload. + /// + /// A object for the register + /// with the specified message type, timestamp, and payload. + /// + public static HarpMessage FromPayload(double timestamp, MessageType messageType, ushort[] value) + { + return HarpMessage.FromUInt16(Address, timestamp, messageType, value); + } + } + + /// + /// Provides methods for manipulating timestamped messages from the + /// SingleElementPayload register. + /// + /// + [Description("Filters and selects timestamped messages from the SingleElementPayload register.")] + public partial class TimestampedSingleElementPayload + { + /// + /// Represents the address of the register. This field is constant. + /// + public const int Address = SingleElementPayload.Address; + + /// + /// Returns timestamped payload data for register messages. + /// + /// A object representing the register message. + /// A value representing the timestamped message payload. + public static Timestamped GetPayload(HarpMessage message) + { + return SingleElementPayload.GetTimestampedPayload(message); + } + } + + /// + /// Represents a register that manipulates messages from register MixedMemberLength. + /// + [Description("")] + public partial class MixedMemberLength + { + /// + /// Represents the address of the register. This field is constant. + /// + public const int Address = 46; + + /// + /// Represents the payload type of the register. This field is constant. + /// + public const PayloadType RegisterType = PayloadType.U8; + + /// + /// Represents the length of the register. This field is constant. + /// + public const int RegisterLength = 4; + + static MixedMemberLengthPayload ParsePayload(byte[] payload) + { + MixedMemberLengthPayload result; + result.Absent = payload[0]; + result.Single = PayloadMarshal.GetSubArray(payload, 1, 1); + result.Multiple = PayloadMarshal.GetSubArray(payload, 2, 2); + return result; + } + + static byte[] FormatPayload(MixedMemberLengthPayload value) + { + byte[] result; + result = new byte[4]; + result[0] = value.Absent; + PayloadMarshal.Write(new ArraySegment(result, 1, 1), value.Single); + PayloadMarshal.Write(new ArraySegment(result, 2, 2), value.Multiple); + return result; + } + + /// + /// Returns the payload data for register messages. + /// + /// A object representing the register message. + /// A value representing the message payload. + public static MixedMemberLengthPayload GetPayload(HarpMessage message) + { + return ParsePayload(message.GetPayloadArray()); + } + + /// + /// Returns the timestamped payload data for register messages. + /// + /// A object representing the register message. + /// A value representing the timestamped message payload. + public static Timestamped GetTimestampedPayload(HarpMessage message) + { + var payload = message.GetTimestampedPayloadArray(); + return Timestamped.Create(ParsePayload(payload.Value), payload.Seconds); + } + + /// + /// Returns a Harp message for the register. + /// + /// The type of the Harp message. + /// The value to be stored in the message payload. + /// + /// A object for the register + /// with the specified message type and payload. + /// + public static HarpMessage FromPayload(MessageType messageType, MixedMemberLengthPayload value) + { + return HarpMessage.FromByte(Address, messageType, FormatPayload(value)); + } + + /// + /// Returns a timestamped Harp message for the + /// register. + /// + /// The timestamp of the message payload, in seconds. + /// The type of the Harp message. + /// The value to be stored in the message payload. + /// + /// A object for the register + /// with the specified message type, timestamp, and payload. + /// + public static HarpMessage FromPayload(double timestamp, MessageType messageType, MixedMemberLengthPayload value) + { + return HarpMessage.FromByte(Address, timestamp, messageType, FormatPayload(value)); + } + } + + /// + /// Provides methods for manipulating timestamped messages from the + /// MixedMemberLength register. + /// + /// + [Description("Filters and selects timestamped messages from the MixedMemberLength register.")] + public partial class TimestampedMixedMemberLength + { + /// + /// Represents the address of the register. This field is constant. + /// + public const int Address = MixedMemberLength.Address; + + /// + /// Returns timestamped payload data for register messages. + /// + /// A object representing the register message. + /// A value representing the timestamped message payload. + public static Timestamped GetPayload(HarpMessage message) + { + return MixedMemberLength.GetTimestampedPayload(message); + } + } + /// /// Represents a register that starts a PWM pulse. /// @@ -2044,6 +2376,9 @@ public static Timestamped GetPayload(HarpMessage message) /// /// /// + /// + /// + /// /// /// /// @@ -2059,6 +2394,9 @@ public static Timestamped GetPayload(HarpMessage message) [XmlInclude(typeof(CreatePortDIOSetPayload))] [XmlInclude(typeof(CreatePulseDOPort0Payload))] [XmlInclude(typeof(CreatePulseDO0Payload))] + [XmlInclude(typeof(CreateMultiElementPayloadPayload))] + [XmlInclude(typeof(CreateSingleElementPayloadPayload))] + [XmlInclude(typeof(CreateMixedMemberLengthPayload))] [XmlInclude(typeof(CreateStartPulsePayload))] [XmlInclude(typeof(CreateStartPulseTrainPayload))] [XmlInclude(typeof(CreateEncoderModePayload))] @@ -2074,6 +2412,9 @@ public static Timestamped GetPayload(HarpMessage message) [XmlInclude(typeof(CreateTimestampedPortDIOSetPayload))] [XmlInclude(typeof(CreateTimestampedPulseDOPort0Payload))] [XmlInclude(typeof(CreateTimestampedPulseDO0Payload))] + [XmlInclude(typeof(CreateTimestampedMultiElementPayloadPayload))] + [XmlInclude(typeof(CreateTimestampedSingleElementPayloadPayload))] + [XmlInclude(typeof(CreateTimestampedMixedMemberLengthPayload))] [XmlInclude(typeof(CreateTimestampedStartPulsePayload))] [XmlInclude(typeof(CreateTimestampedStartPulseTrainPayload))] [XmlInclude(typeof(CreateTimestampedEncoderModePayload))] @@ -2844,6 +3185,184 @@ public HarpMessage GetMessage(double timestamp, MessageType messageType) } } + /// + /// Represents an operator that creates a message payload + /// for register MultiElementPayload. + /// + [DisplayName("MultiElementPayloadPayload")] + [Description("Creates a message payload for register MultiElementPayload.")] + public partial class CreateMultiElementPayloadPayload + { + /// + /// Gets or sets the value for register MultiElementPayload. + /// + [Description("The value for register MultiElementPayload.")] + public ushort[] MultiElementPayload { get; set; } + + /// + /// Creates a message payload for the MultiElementPayload register. + /// + /// The created message payload value. + public ushort[] GetPayload() + { + return MultiElementPayload; + } + + /// + /// Creates a message for register MultiElementPayload. + /// + /// Specifies the type of the created message. + /// A new message for the MultiElementPayload register. + public HarpMessage GetMessage(MessageType messageType) + { + return Harp.Generators.Tests.MultiElementPayload.FromPayload(messageType, GetPayload()); + } + } + + /// + /// Represents an operator that creates a timestamped message payload + /// for register MultiElementPayload. + /// + [DisplayName("TimestampedMultiElementPayloadPayload")] + [Description("Creates a timestamped message payload for register MultiElementPayload.")] + public partial class CreateTimestampedMultiElementPayloadPayload : CreateMultiElementPayloadPayload + { + /// + /// Creates a timestamped message for register MultiElementPayload. + /// + /// The timestamp of the message payload, in seconds. + /// Specifies the type of the created message. + /// A new timestamped message for the MultiElementPayload register. + public HarpMessage GetMessage(double timestamp, MessageType messageType) + { + return Harp.Generators.Tests.MultiElementPayload.FromPayload(timestamp, messageType, GetPayload()); + } + } + + /// + /// Represents an operator that creates a message payload + /// for register SingleElementPayload. + /// + [DisplayName("SingleElementPayloadPayload")] + [Description("Creates a message payload for register SingleElementPayload.")] + public partial class CreateSingleElementPayloadPayload + { + /// + /// Gets or sets the value for register SingleElementPayload. + /// + [Description("The value for register SingleElementPayload.")] + public ushort[] SingleElementPayload { get; set; } + + /// + /// Creates a message payload for the SingleElementPayload register. + /// + /// The created message payload value. + public ushort[] GetPayload() + { + return SingleElementPayload; + } + + /// + /// Creates a message for register SingleElementPayload. + /// + /// Specifies the type of the created message. + /// A new message for the SingleElementPayload register. + public HarpMessage GetMessage(MessageType messageType) + { + return Harp.Generators.Tests.SingleElementPayload.FromPayload(messageType, GetPayload()); + } + } + + /// + /// Represents an operator that creates a timestamped message payload + /// for register SingleElementPayload. + /// + [DisplayName("TimestampedSingleElementPayloadPayload")] + [Description("Creates a timestamped message payload for register SingleElementPayload.")] + public partial class CreateTimestampedSingleElementPayloadPayload : CreateSingleElementPayloadPayload + { + /// + /// Creates a timestamped message for register SingleElementPayload. + /// + /// The timestamp of the message payload, in seconds. + /// Specifies the type of the created message. + /// A new timestamped message for the SingleElementPayload register. + public HarpMessage GetMessage(double timestamp, MessageType messageType) + { + return Harp.Generators.Tests.SingleElementPayload.FromPayload(timestamp, messageType, GetPayload()); + } + } + + /// + /// Represents an operator that creates a message payload + /// for register MixedMemberLength. + /// + [DisplayName("MixedMemberLengthPayload")] + [Description("Creates a message payload for register MixedMemberLength.")] + public partial class CreateMixedMemberLengthPayload + { + /// + /// Gets or sets a value to write on payload member Absent. + /// + [Description("")] + public byte Absent { get; set; } + + /// + /// Gets or sets a value to write on payload member Single. + /// + [Description("")] + public byte[] Single { get; set; } + + /// + /// Gets or sets a value to write on payload member Multiple. + /// + [Description("")] + public byte[] Multiple { get; set; } + + /// + /// Creates a message payload for the MixedMemberLength register. + /// + /// The created message payload value. + public MixedMemberLengthPayload GetPayload() + { + MixedMemberLengthPayload value; + value.Absent = Absent; + value.Single = Single; + value.Multiple = Multiple; + return value; + } + + /// + /// Creates a message for register MixedMemberLength. + /// + /// Specifies the type of the created message. + /// A new message for the MixedMemberLength register. + public HarpMessage GetMessage(MessageType messageType) + { + return Harp.Generators.Tests.MixedMemberLength.FromPayload(messageType, GetPayload()); + } + } + + /// + /// Represents an operator that creates a timestamped message payload + /// for register MixedMemberLength. + /// + [DisplayName("TimestampedMixedMemberLengthPayload")] + [Description("Creates a timestamped message payload for register MixedMemberLength.")] + public partial class CreateTimestampedMixedMemberLengthPayload : CreateMixedMemberLengthPayload + { + /// + /// Creates a timestamped message for register MixedMemberLength. + /// + /// The timestamp of the message payload, in seconds. + /// Specifies the type of the created message. + /// A new timestamped message for the MixedMemberLength register. + public HarpMessage GetMessage(double timestamp, MessageType messageType) + { + return Harp.Generators.Tests.MixedMemberLength.FromPayload(timestamp, messageType, GetPayload()); + } + } + /// /// Represents an operator that creates a message payload /// that starts a PWM pulse. @@ -3337,6 +3856,60 @@ public override string ToString() } } + /// + /// Represents the payload of the MixedMemberLength register. + /// + public struct MixedMemberLengthPayload + { + /// + /// Initializes a new instance of the structure. + /// + /// + /// + /// + public MixedMemberLengthPayload( + byte absent, + byte[] single, + byte[] multiple) + { + Absent = absent; + Single = single; + Multiple = multiple; + } + + /// + /// + /// + public byte Absent; + + /// + /// + /// + public byte[] Single; + + /// + /// + /// + public byte[] Multiple; + + /// + /// Returns a that represents the payload of + /// the MixedMemberLength register. + /// + /// + /// A that represents the payload of the + /// MixedMemberLength register. + /// + public override string ToString() + { + return "MixedMemberLengthPayload { " + + "Absent = " + Absent + ", " + + "Single = " + Single + ", " + + "Multiple = " + Multiple + " " + + "}"; + } + } + /// /// Represents the payload of the StartPulse register. /// diff --git a/tests/ExpectedOutput/device.py b/tests/ExpectedOutput/device.py index 2153c9b..eccfb82 100644 --- a/tests/ExpectedOutput/device.py +++ b/tests/ExpectedOutput/device.py @@ -19,6 +19,7 @@ RegisterBase, RegisterS32, RegisterU16, + RegisterU16Array, RegisterU8, StringConverter, StructPayload, @@ -44,6 +45,7 @@ "CustomMemberConverterPayload", "BitmaskSplitterPayload", "PortDIOSetPayload", + "MixedMemberLengthPayload", "StartPulsePayload", "StartPulseTrainPayload", "EncoderModePayload", @@ -59,6 +61,9 @@ "PortDIOSet", "PulseDOPort0", "PulseDO0", + "MultiElementPayload", + "SingleElementPayload", + "MixedMemberLength", "StartPulse", "StartPulseTrain", "EncoderMode", @@ -155,6 +160,14 @@ class PortDIOSetPayload(AnonymousPayload[np.uint8]): __value__: PortDigitalIOS = BitMask(enum=PortDigitalIOS) +class MixedMemberLengthPayload(StructPayload[np.uint8], length=4): + """Represents the payload of the MixedMemberLength register.""" + + absent: np.uint8 = Field(IdentityConverter(np.uint8)) + single: NDArray[np.uint8] = Field(IdentityConverter(np.dtype((np.uint8, (1,)))), offset=1) + multiple: NDArray[np.uint8] = Field(IdentityConverter(np.dtype((np.uint8, (2,)))), offset=2) + + class StartPulsePayload(StructPayload[np.uint16]): """Represents the payload of the StartPulse register.""" @@ -241,6 +254,22 @@ class PulseDO0(RegisterU16): address: ClassVar[int] = 43 +class MultiElementPayload(RegisterU16Array): + address: ClassVar[int] = 44 + length: ClassVar[int] = 3 + + +class SingleElementPayload(RegisterU16Array): + address: ClassVar[int] = 45 + length: ClassVar[int] = 1 + + +class MixedMemberLength(RegisterBase[MixedMemberLengthPayload]): + address: ClassVar[int] = 46 + payload_type: ClassVar[PayloadType] = PayloadType.U8 + payload_class = MixedMemberLengthPayload + + class StartPulse(RegisterBase[StartPulsePayload]): """Starts a PWM pulse.""" @@ -279,6 +308,9 @@ class EncoderMode(RegisterBase[EncoderModeMask]): 41: PortDIOSet, 42: PulseDOPort0, 43: PulseDO0, + 44: MultiElementPayload, + 45: SingleElementPayload, + 46: MixedMemberLength, 100: StartPulse, 101: StartPulseTrain, 103: EncoderMode, diff --git a/tests/Metadata/device.yml b/tests/Metadata/device.yml index 38b87cc..d882b3c 100644 --- a/tests/Metadata/device.yml +++ b/tests/Metadata/device.yml @@ -127,6 +127,30 @@ registers: PulseDO0: <<: *pulseDO address: 43 + MultiElementPayload: + address: 44 + type: U16 + length: 3 + access: Write + SingleElementPayload: + address: 45 + type: U16 + length: 1 + access: Write + MixedMemberLength: + address: 46 + type: U8 + length: 4 + access: Write + payloadSpec: + Absent: + offset: 0 + Single: + offset: 1 + length: 1 + Multiple: + offset: 2 + length: 2 StartPulse: address: 100 type: U16 diff --git a/tests/Python/pyproject.toml b/tests/Python/pyproject.toml index 21805f6..3e514b9 100644 --- a/tests/Python/pyproject.toml +++ b/tests/Python/pyproject.toml @@ -3,10 +3,8 @@ name = "harp-generators-interop" version = "0" description = "Cross-stack interop test for the generated Python device interface." requires-python = ">=3.11" -# harp-protocol and harp-device are pinned to a pyharp main commit until a release including the -# harp.device namespace split is published to PyPI. dependencies = [ - "harp-protocol @ git+https://github.com/harp-tech/pyharp.git@371a0fb7903e80c93783476f0d08cee9a27709fb#subdirectory=src/packages/harp-protocol", - "harp-device @ git+https://github.com/harp-tech/pyharp.git@371a0fb7903e80c93783476f0d08cee9a27709fb#subdirectory=src/packages/harp-device", + "harp-protocol>=0.5.0", + "harp-device>=0.5.0", "pytest>=8", ]