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",
]