From 8a3d20110d297ede1b686d2cafe5ef7557c496d4 Mon Sep 17 00:00:00 2001 From: jonnew Date: Tue, 17 Sep 2024 17:14:14 -0400 Subject: [PATCH 1/3] Squashed commit of the following: commit 7616b9013b43d2cedaf01f2f30a740ad2ec907e8 Author: jonnew Date: Tue Sep 17 17:11:02 2024 -0400 Add missing Design files - I didn't add these in my last commit commit 760215bf6e9ab5316b96d85d55d4a2b304fbed35 Author: jonnew Date: Tue Sep 17 16:49:30 2024 -0400 Combine all polled Bno055 classes into common type - ConfigurePolledBno055 and PolledBno055Data classes replace headstage specific versions of the same thing. Axis map is defined via a couple properties that are not browsable in editor - Old configuraiton and data operators are marked obsolete --- .../NeuropixelsV1eBno055Dialog.cs | 42 ---- .../NeuropixelsV1eHeadstageDialog.cs | 10 +- .../NeuropixelsV2eBno055Dialog.Designer.cs | 39 ---- .../NeuropixelsV2eBno055Dialog.cs | 42 ---- .../NeuropixelsV2eBno055Editor.cs | 35 --- .../NeuropixelsV2eHeadstageDialog.cs | 8 +- ...gner.cs => PolledBno055Dialog.Designer.cs} | 2 +- OpenEphys.Onix1.Design/PolledBno055Dialog.cs | 42 ++++ ...eBno055Editor.cs => PolledBno055Editor.cs} | 6 +- .../ConfigureNeuropixelsV1eBno055.cs | 121 ---------- .../ConfigureNeuropixelsV1eHeadstage.cs | 9 +- OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs | 4 +- .../ConfigureNeuropixelsV2eBeta.cs | 4 +- .../ConfigureNeuropixelsV2eBetaHeadstage.cs | 3 +- .../ConfigureNeuropixelsV2eBno055.cs | 122 ---------- .../ConfigureNeuropixelsV2eHeadstage.cs | 3 +- OpenEphys.Onix1/ConfigurePolledBno055.cs | 215 ++++++++++++++++++ OpenEphys.Onix1/NeuropixelsV1eBno055Data.cs | 88 ------- ...lsV2eBno055Data.cs => PolledBno055Data.cs} | 32 ++- 19 files changed, 306 insertions(+), 521 deletions(-) delete mode 100644 OpenEphys.Onix1.Design/NeuropixelsV1eBno055Dialog.cs delete mode 100644 OpenEphys.Onix1.Design/NeuropixelsV2eBno055Dialog.Designer.cs delete mode 100644 OpenEphys.Onix1.Design/NeuropixelsV2eBno055Dialog.cs delete mode 100644 OpenEphys.Onix1.Design/NeuropixelsV2eBno055Editor.cs rename OpenEphys.Onix1.Design/{NeuropixelsV1eBno055Dialog.Designer.cs => PolledBno055Dialog.Designer.cs} (96%) create mode 100644 OpenEphys.Onix1.Design/PolledBno055Dialog.cs rename OpenEphys.Onix1.Design/{NeuropixelsV1eBno055Editor.cs => PolledBno055Editor.cs} (77%) delete mode 100644 OpenEphys.Onix1/ConfigureNeuropixelsV1eBno055.cs delete mode 100644 OpenEphys.Onix1/ConfigureNeuropixelsV2eBno055.cs create mode 100644 OpenEphys.Onix1/ConfigurePolledBno055.cs delete mode 100644 OpenEphys.Onix1/NeuropixelsV1eBno055Data.cs rename OpenEphys.Onix1/{NeuropixelsV2eBno055Data.cs => PolledBno055Data.cs} (72%) diff --git a/OpenEphys.Onix1.Design/NeuropixelsV1eBno055Dialog.cs b/OpenEphys.Onix1.Design/NeuropixelsV1eBno055Dialog.cs deleted file mode 100644 index e08ab05..0000000 --- a/OpenEphys.Onix1.Design/NeuropixelsV1eBno055Dialog.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; - -namespace OpenEphys.Onix1.Design -{ - /// - /// Partial class to create a GUI for . - /// - public partial class NeuropixelsV1eBno055Dialog : GenericDeviceDialog - { - /// - /// Gets or sets the object attached to - /// the property grid. - /// - public ConfigureNeuropixelsV1eBno055 ConfigureNode - { - get => (ConfigureNeuropixelsV1eBno055)propertyGrid.SelectedObject; - set => propertyGrid.SelectedObject = value; - } - - /// - /// Initializes a new instance with the given - /// object. - /// - /// A object that contains configuration settings. - public NeuropixelsV1eBno055Dialog(ConfigureNeuropixelsV1eBno055 configureNode) - { - InitializeComponent(); - Shown += FormShown; - - ConfigureNode = new(configureNode); - } - - private void FormShown(object sender, EventArgs e) - { - if (!TopLevel) - { - splitContainer1.Panel2Collapsed = true; - splitContainer1.Panel2.Hide(); - } - } - } -} diff --git a/OpenEphys.Onix1.Design/NeuropixelsV1eHeadstageDialog.cs b/OpenEphys.Onix1.Design/NeuropixelsV1eHeadstageDialog.cs index 538cc65..8278cc7 100644 --- a/OpenEphys.Onix1.Design/NeuropixelsV1eHeadstageDialog.cs +++ b/OpenEphys.Onix1.Design/NeuropixelsV1eHeadstageDialog.cs @@ -7,7 +7,7 @@ namespace OpenEphys.Onix1.Design /// /// /// Within the GUI, there is a tab for both devices encapsulated by a , - /// specifically a and a . + /// specifically a and a . /// public partial class NeuropixelsV1eHeadstageDialog : Form { @@ -17,16 +17,16 @@ public partial class NeuropixelsV1eHeadstageDialog : Form public readonly NeuropixelsV1eDialog DialogNeuropixelsV1e; /// - /// Public method that provides access to the . + /// Public method that provides access to the . /// - public readonly NeuropixelsV1eBno055Dialog DialogBno055; + public readonly PolledBno055Dialog DialogBno055; /// /// Initializes a new instance of a . /// /// Configuration settings for a . - /// Configuration settings for a . - public NeuropixelsV1eHeadstageDialog(ConfigureNeuropixelsV1e configureNeuropixelsV1e, ConfigureNeuropixelsV1eBno055 configureBno055) + /// Configuration settings for a . + public NeuropixelsV1eHeadstageDialog(ConfigureNeuropixelsV1e configureNeuropixelsV1e, ConfigurePolledBno055 configureBno055) { InitializeComponent(); diff --git a/OpenEphys.Onix1.Design/NeuropixelsV2eBno055Dialog.Designer.cs b/OpenEphys.Onix1.Design/NeuropixelsV2eBno055Dialog.Designer.cs deleted file mode 100644 index 34e1bfb..0000000 --- a/OpenEphys.Onix1.Design/NeuropixelsV2eBno055Dialog.Designer.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace OpenEphys.Onix1.Design -{ - partial class NeuropixelsV2eBno055Dialog - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(800, 450); - this.Text = "NeuropixelsV2eBno055Dialog"; - } - - #endregion - } -} diff --git a/OpenEphys.Onix1.Design/NeuropixelsV2eBno055Dialog.cs b/OpenEphys.Onix1.Design/NeuropixelsV2eBno055Dialog.cs deleted file mode 100644 index a5009e1..0000000 --- a/OpenEphys.Onix1.Design/NeuropixelsV2eBno055Dialog.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; - -namespace OpenEphys.Onix1.Design -{ - /// - /// Partial class to create a GUI for . - /// - public partial class NeuropixelsV2eBno055Dialog : GenericDeviceDialog - { - /// - /// Gets or sets the object attached to - /// the property grid. - /// - public ConfigureNeuropixelsV2eBno055 ConfigureNode - { - get => (ConfigureNeuropixelsV2eBno055)propertyGrid.SelectedObject; - set => propertyGrid.SelectedObject = value; - } - - /// - /// Initializes a new instance of with the given - /// object. - /// - /// A object that contains configuration settings. - public NeuropixelsV2eBno055Dialog(ConfigureNeuropixelsV2eBno055 configureNode) - { - InitializeComponent(); - Shown += FormShown; - - ConfigureNode = new(configureNode); - } - - private void FormShown(object sender, EventArgs e) - { - if (!TopLevel) - { - splitContainer1.Panel2Collapsed = true; - splitContainer1.Panel2.Hide(); - } - } - } -} diff --git a/OpenEphys.Onix1.Design/NeuropixelsV2eBno055Editor.cs b/OpenEphys.Onix1.Design/NeuropixelsV2eBno055Editor.cs deleted file mode 100644 index 3a298ec..0000000 --- a/OpenEphys.Onix1.Design/NeuropixelsV2eBno055Editor.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.ComponentModel; -using Bonsai.Design; -using System.Windows.Forms; - -namespace OpenEphys.Onix1.Design -{ - /// - /// Class that opens a new dialog for a . - /// - public class NeuropixelsV2eBno055Editor : WorkflowComponentEditor - { - /// - public override bool EditComponent(ITypeDescriptorContext context, object component, IServiceProvider provider, IWin32Window owner) - { - if (provider != null) - { - var editorState = (IWorkflowEditorState)provider.GetService(typeof(IWorkflowEditorState)); - if (editorState != null && !editorState.WorkflowRunning && component is ConfigureNeuropixelsV2eBno055 configureBno055) - { - using var editorDialog = new NeuropixelsV2eBno055Dialog(configureBno055); - - if (editorDialog.ShowDialog() == DialogResult.OK) - { - configureBno055.Enable = editorDialog.ConfigureNode.Enable; - - return true; - } - } - } - - return false; - } - } -} diff --git a/OpenEphys.Onix1.Design/NeuropixelsV2eHeadstageDialog.cs b/OpenEphys.Onix1.Design/NeuropixelsV2eHeadstageDialog.cs index 5873ad2..ea11cbe 100644 --- a/OpenEphys.Onix1.Design/NeuropixelsV2eHeadstageDialog.cs +++ b/OpenEphys.Onix1.Design/NeuropixelsV2eHeadstageDialog.cs @@ -13,16 +13,16 @@ public partial class NeuropixelsV2eHeadstageDialog : Form public readonly NeuropixelsV2eDialog DialogNeuropixelsV2e; /// - /// A that configures a . + /// A that configures a . /// - public readonly NeuropixelsV2eBno055Dialog DialogBno055; + public readonly PolledBno055Dialog DialogBno055; /// /// Initializes a new instance of a . /// /// Configuration settings for a . - /// Configuration settings for a . - public NeuropixelsV2eHeadstageDialog(IConfigureNeuropixelsV2 configureNeuropixelsV2e, ConfigureNeuropixelsV2eBno055 configureBno055) + /// Configuration settings for a . + public NeuropixelsV2eHeadstageDialog(IConfigureNeuropixelsV2 configureNeuropixelsV2e, ConfigurePolledBno055 configureBno055) { InitializeComponent(); diff --git a/OpenEphys.Onix1.Design/NeuropixelsV1eBno055Dialog.Designer.cs b/OpenEphys.Onix1.Design/PolledBno055Dialog.Designer.cs similarity index 96% rename from OpenEphys.Onix1.Design/NeuropixelsV1eBno055Dialog.Designer.cs rename to OpenEphys.Onix1.Design/PolledBno055Dialog.Designer.cs index b21d567..9c47b50 100644 --- a/OpenEphys.Onix1.Design/NeuropixelsV1eBno055Dialog.Designer.cs +++ b/OpenEphys.Onix1.Design/PolledBno055Dialog.Designer.cs @@ -1,6 +1,6 @@ namespace OpenEphys.Onix1.Design { - partial class NeuropixelsV1eBno055Dialog + partial class PolledBno055Dialog { /// /// Required designer variable. diff --git a/OpenEphys.Onix1.Design/PolledBno055Dialog.cs b/OpenEphys.Onix1.Design/PolledBno055Dialog.cs new file mode 100644 index 0000000..53355d4 --- /dev/null +++ b/OpenEphys.Onix1.Design/PolledBno055Dialog.cs @@ -0,0 +1,42 @@ +using System; + +namespace OpenEphys.Onix1.Design +{ + /// + /// Partial class to create a GUI for . + /// + public partial class PolledBno055Dialog : GenericDeviceDialog + { + /// + /// Gets or sets the object attached to + /// the property grid. + /// + public ConfigurePolledBno055 ConfigureNode + { + get => (ConfigurePolledBno055)propertyGrid.SelectedObject; + set => propertyGrid.SelectedObject = value; + } + + /// + /// Initializes a new instance with the given + /// object. + /// + /// A object that contains configuration settings. + public PolledBno055Dialog(ConfigurePolledBno055 configureNode) + { + InitializeComponent(); + Shown += FormShown; + + ConfigureNode = new(configureNode); + } + + private void FormShown(object sender, EventArgs e) + { + if (!TopLevel) + { + splitContainer1.Panel2Collapsed = true; + splitContainer1.Panel2.Hide(); + } + } + } +} diff --git a/OpenEphys.Onix1.Design/NeuropixelsV1eBno055Editor.cs b/OpenEphys.Onix1.Design/PolledBno055Editor.cs similarity index 77% rename from OpenEphys.Onix1.Design/NeuropixelsV1eBno055Editor.cs rename to OpenEphys.Onix1.Design/PolledBno055Editor.cs index a6d9f80..8dfefdc 100644 --- a/OpenEphys.Onix1.Design/NeuropixelsV1eBno055Editor.cs +++ b/OpenEphys.Onix1.Design/PolledBno055Editor.cs @@ -5,16 +5,16 @@ namespace OpenEphys.Onix1.Design { - internal class NeuropixelsV1eBno055Editor : WorkflowComponentEditor + internal class PolledBno055Editor : WorkflowComponentEditor { public override bool EditComponent(ITypeDescriptorContext context, object component, IServiceProvider provider, IWin32Window owner) { if (provider != null) { var editorState = (IWorkflowEditorState)provider.GetService(typeof(IWorkflowEditorState)); - if (editorState != null && !editorState.WorkflowRunning && component is ConfigureNeuropixelsV1eBno055 configureBno055) + if (editorState != null && !editorState.WorkflowRunning && component is ConfigurePolledBno055 configureBno055) { - using var editorDialog = new NeuropixelsV1eBno055Dialog(configureBno055); + using var editorDialog = new PolledBno055Dialog(configureBno055); if (editorDialog.ShowDialog() == DialogResult.OK) { diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV1eBno055.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV1eBno055.cs deleted file mode 100644 index e77332c..0000000 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV1eBno055.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.ComponentModel; - -namespace OpenEphys.Onix1 -{ - /// - /// Configures a NeuropixelsV1eBno055 device. - /// - /// - /// This configuration operator can be linked to a data IO operator, such as , using a shared DeviceName. - /// - [Description("Configures a NeuropixelsV1eBno055 device.")] - [Editor("OpenEphys.Onix1.Design.NeuropixelsV1eBno055Editor, OpenEphys.Onix1.Design", typeof(ComponentEditor))] - public class ConfigureNeuropixelsV1eBno055 : SingleDeviceFactory - { - /// - /// Initializes a new instance of the class. - /// - public ConfigureNeuropixelsV1eBno055() - : base(typeof(NeuropixelsV1eBno055)) - { - } - - /// - /// Copy constructor for the class. - /// - public ConfigureNeuropixelsV1eBno055(ConfigureNeuropixelsV1eBno055 configureBno055) - : base(typeof(NeuropixelsV1eBno055)) - { - Enable = configureBno055.Enable; - DeviceName = configureBno055.DeviceName; - DeviceAddress = configureBno055.DeviceAddress; - } - - /// - /// Gets or sets the device enable state. - /// - /// - /// If set to true, will produce data. If set to false, - /// will not produce data. - /// - [Category(ConfigurationCategory)] - [Description("Specifies whether the Bno055 device is enabled.")] - public bool Enable { get; set; } = true; - - /// - /// Configures a NeuropixelsV1eBno055 device. - /// - /// - /// This will schedule configuration actions to be applied by a node - /// prior to data acquisition. - /// - /// A sequence of that holds all configuration actions. - /// - /// The original sequence with the side effect of an additional configuration action to configure - /// a NeuropixelsV1eBno055 device. - /// - public override IObservable Process(IObservable source) - { - var enable = Enable; - var deviceName = DeviceName; - var deviceAddress = DeviceAddress; - return source.ConfigureDevice(context => - { - // configure device via the DS90UB9x deserializer device - var device = context.GetPassthroughDeviceContext(deviceAddress, typeof(DS90UB9x)); - ConfigureDeserializer(device); - ConfigureBno055(device); - var deviceInfo = new NeuropixelsV1eBno055DeviceInfo(context, DeviceType, deviceAddress, enable); - return DeviceManager.RegisterDevice(deviceName, deviceInfo); - }); - } - - static void ConfigureDeserializer(DeviceContext device) - { - // configure deserializer I2C aliases - var deserializer = new I2CRegisterContext(device, DS90UB9x.DES_ADDR); - uint alias = NeuropixelsV1eBno055.BNO055Address << 1; - deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveID4, alias); - deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveAlias4, alias); - } - - static void ConfigureBno055(DeviceContext device) - { - // setup Bno055 device - var i2c = new I2CRegisterContext(device, NeuropixelsV1eBno055.BNO055Address); - i2c.WriteByte(0x3E, 0x00); // Power mode normal - i2c.WriteByte(0x07, 0x00); // Page ID address 0 - i2c.WriteByte(0x3F, 0x00); // Internal oscillator - i2c.WriteByte(0x41, 0b00010010); // Axis map config (configured to match hs64; X => -Z, Y => X, Z => -Y) - i2c.WriteByte(0x42, 0b00000011); // Axis sign (negate Y and Z) - i2c.WriteByte(0x3D, 8); // Operation mode is NOF - } - } - - static class NeuropixelsV1eBno055 - { - public const int BNO055Address = 0x28; - public const int DataAddress = 0x1A; - - internal class NameConverter : DeviceNameConverter - { - public NameConverter() - : base(typeof(NeuropixelsV1eBno055)) - { - } - } - } - - class NeuropixelsV1eBno055DeviceInfo : DeviceInfo - { - public NeuropixelsV1eBno055DeviceInfo(ContextTask context, Type deviceType, uint deviceAddress, bool enable) - : base(context, deviceType, deviceAddress) - { - Enable = enable; - } - - public bool Enable { get; } - } -} diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs index 65999bf..488b99a 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs @@ -8,7 +8,7 @@ namespace OpenEphys.Onix1 /// Configures a NeuropixelsV1e headstage on the specified port. /// /// - /// The NeuropixeslV1e Headstage is a 0.68g serialized, multifunction headstage for small animals. This + /// The NeuropixelsV1e Headstage is a 0.68g serialized, multifunction headstage for small animals. This /// headstage is designed to function with IMEC Neuropixels V1 probes. It provides the following features: /// /// Support for a single IMEC Neuropixels 1.0 probe that features: @@ -43,7 +43,7 @@ public ConfigureNeuropixelsV1eHeadstage() [Category(DevicesCategory)] [TypeConverter(typeof(SingleDeviceFactoryConverter))] [Description("Specifies the configuration for the NeuropixelsV1e device.")] - public ConfigureNeuropixelsV1e NeuropixelsV1e { get; set; } = new(); + public ConfigureNeuropixelsV1e NeuropixelsV1e { get; set; } = new(); /// /// Gets or sets the Bno055 9-axis inertial measurement unit configuration. @@ -51,8 +51,9 @@ public ConfigureNeuropixelsV1eHeadstage() [Category(DevicesCategory)] [TypeConverter(typeof(SingleDeviceFactoryConverter))] [Description("Specifies the configuration for the Bno055 device.")] - public ConfigureNeuropixelsV1eBno055 Bno055 { get; set; } = new(); - + public ConfigurePolledBno055 Bno055 { get; set; } = + new ConfigurePolledBno055 { AxisMap = Bno055AxisMap.ZXY, AxisSign = Bno055AxisSign.NegZ | Bno055AxisSign.NegY }; // Axis map: X => -Z, Y => X, Z => -Y. + /// /// Gets or sets the port. /// diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs index 525803e..f9e710a 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs @@ -51,7 +51,7 @@ public ConfigureNeuropixelsV2e(ConfigureNeuropixelsV2e configureNode) /// Configuration is accomplished using a GUI to aid in channel selection and relevant configuration properties. /// To open a probe configuration GUI, select the ellipses next the variable /// in the property pane, or double-click to configure both - /// probes and the simultaneously. + /// probes and the simultaneously. /// [Category(ConfigurationCategory)] [Description("Probe A electrode configuration.")] @@ -82,7 +82,7 @@ public ConfigureNeuropixelsV2e(ConfigureNeuropixelsV2e configureNode) /// Configuration is accomplished using a GUI to aid in channel selection and relevant configuration properties. /// To open a probe configuration GUI, select the ellipses next the variable /// in the property pane, or double-click to configure both - /// probes and the simultaneously. + /// probes and the simultaneously. /// [Category(ConfigurationCategory)] [Description("Probe B electrode configuration.")] diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs index b82ada7..40cfb0c 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs @@ -66,7 +66,7 @@ public ConfigureNeuropixelsV2eBeta(ConfigureNeuropixelsV2eBeta configureNode) /// Configuration is accomplished using a GUI to aid in channel selection and relevant configuration properties. /// To open a probe configuration GUI, select the ellipses next the variable /// in the property pane, or double-click to configure both - /// probes and the simultaneously. + /// probes and the simultaneously. /// [Category(ConfigurationCategory)] [Description("Probe A electrode configuration.")] @@ -97,7 +97,7 @@ public ConfigureNeuropixelsV2eBeta(ConfigureNeuropixelsV2eBeta configureNode) /// Configuration is accomplished using a GUI to aid in channel selection and relevant configuration properties. /// To open a probe configuration GUI, select the ellipses next the variable /// in the property pane, or double-click to configure both - /// probes and the simultaneously. + /// probes and the simultaneously. /// [Category(ConfigurationCategory)] [Description("Probe B electrode configuration.")] diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBetaHeadstage.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV2eBetaHeadstage.cs index af8f06d..ae186ef 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBetaHeadstage.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV2eBetaHeadstage.cs @@ -50,7 +50,8 @@ public ConfigureNeuropixelsV2eBetaHeadstage() [Category(DevicesCategory)] [TypeConverter(typeof(SingleDeviceFactoryConverter))] [Description("Specifies the configuration for the Bno055 device.")] - public ConfigureNeuropixelsV2eBno055 Bno055 { get; set; } = new(); + public ConfigurePolledBno055 Bno055 { get; set; } = + new ConfigurePolledBno055 { AxisMap = Bno055AxisMap.ZXY, AxisSign = Bno055AxisSign.Default }; // Axis map: X => Z, Y => X, Z => Y. /// /// Gets or sets the port. diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBno055.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV2eBno055.cs deleted file mode 100644 index 4db722f..0000000 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBno055.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System; -using System.ComponentModel; - -namespace OpenEphys.Onix1 -{ - /// - /// Configures a NeuropixelsV2eBno055 device. - /// - /// - /// This configuration operator can be linked to a data IO operator, such as , using a shared DeviceName. - /// - [Editor("OpenEphys.Onix1.Design.NeuropixelsV2eBno055Editor, OpenEphys.Onix1.Design", typeof(ComponentEditor))] - [Description("Configures a NeuropixelsV2eBno055 device.")] - public class ConfigureNeuropixelsV2eBno055 : SingleDeviceFactory - { - /// - /// Initializes a new instance of the class. - /// - public ConfigureNeuropixelsV2eBno055() - : base(typeof(NeuropixelsV2eBno055)) - { - } - - /// - /// Copy constructor for the class. - /// - /// A pre-existing object. - public ConfigureNeuropixelsV2eBno055(ConfigureNeuropixelsV2eBno055 configureNeuropixelsV2eBno055) - : base(typeof(NeuropixelsV2eBno055)) - { - Enable = configureNeuropixelsV2eBno055.Enable; - DeviceName = configureNeuropixelsV2eBno055.DeviceName; - DeviceAddress = configureNeuropixelsV2eBno055.DeviceAddress; - } - - /// - /// Gets or sets the device enable state. - /// - /// - /// If set to true, will produce data. If set to false, - /// will not produce data. - /// - [Category(ConfigurationCategory)] - [Description("Specifies whether the Bno055 device is enabled.")] - public bool Enable { get; set; } = true; - - /// - /// Configures a NeuropixelsV2eBno055 device. - /// - /// - /// This will schedule configuration actions to be applied by a node - /// prior to data acquisition. - /// - /// A sequence of that holds all configuration actions. - /// - /// The original sequence with the side effect of an additional configuration action to configure - /// a NeuropixelsV2eBno055 device. - /// - public override IObservable Process(IObservable source) - { - var enable = Enable; - var deviceName = DeviceName; - var deviceAddress = DeviceAddress; - return source.ConfigureDevice(context => - { - // configure device via the DS90UB9x deserializer device - var device = context.GetPassthroughDeviceContext(deviceAddress, typeof(DS90UB9x)); - ConfigureDeserializer(device); - ConfigureBno055(device); - var deviceInfo = new NeuropixelsV2eBno055DeviceInfo(context, DeviceType, deviceAddress, enable); - return DeviceManager.RegisterDevice(deviceName, deviceInfo); - }); - } - - static void ConfigureDeserializer(DeviceContext device) - { - // configure deserializer I2C aliases - var deserializer = new I2CRegisterContext(device, DS90UB9x.DES_ADDR); - uint alias = NeuropixelsV2eBno055.BNO055Address << 1; - deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveID4, alias); - deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveAlias4, alias); - } - - static void ConfigureBno055(DeviceContext device) - { - // setup Bno055 device - var i2c = new I2CRegisterContext(device, NeuropixelsV2eBno055.BNO055Address); - i2c.WriteByte(0x3E, 0x00); // Power mode normal - i2c.WriteByte(0x07, 0x00); // Page ID address 0 - i2c.WriteByte(0x3F, 0x00); // Internal oscillator - i2c.WriteByte(0x41, 0b00010010); // Axis map config (configured to match headstage; X => Z, Y => X, Z => Y) - i2c.WriteByte(0x42, 0b00000000); // Axis sign set to default - i2c.WriteByte(0x3D, 8); // Operation mode is NOF - } - } - - static class NeuropixelsV2eBno055 - { - public const int BNO055Address = 0x28; - public const int DataAddress = 0x1A; - - internal class NameConverter : DeviceNameConverter - { - public NameConverter() - : base(typeof(NeuropixelsV2eBno055)) - { - } - } - } - - class NeuropixelsV2eBno055DeviceInfo : DeviceInfo - { - public NeuropixelsV2eBno055DeviceInfo(ContextTask context, Type deviceType, uint deviceAddress, bool enable) - : base(context, deviceType, deviceAddress) - { - Enable = enable; - } - - public bool Enable { get; } - } -} diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV2eHeadstage.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV2eHeadstage.cs index 1813c04..e51e61b 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV2eHeadstage.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV2eHeadstage.cs @@ -50,7 +50,8 @@ public ConfigureNeuropixelsV2eHeadstage() [Category(DevicesCategory)] [TypeConverter(typeof(SingleDeviceFactoryConverter))] [Description("Specifies the configuration for the Bno055 device.")] - public ConfigureNeuropixelsV2eBno055 Bno055 { get; set; } = new(); + public ConfigurePolledBno055 Bno055 { get; set; } = + new ConfigurePolledBno055 { AxisMap = Bno055AxisMap.ZXY, AxisSign = Bno055AxisSign.Default }; // Axis map: X => Z, Y => X, Z => Y. /// /// Gets or sets the port. diff --git a/OpenEphys.Onix1/ConfigurePolledBno055.cs b/OpenEphys.Onix1/ConfigurePolledBno055.cs new file mode 100644 index 0000000..9e96cb4 --- /dev/null +++ b/OpenEphys.Onix1/ConfigurePolledBno055.cs @@ -0,0 +1,215 @@ +using System; +using System.ComponentModel; + +namespace OpenEphys.Onix1 +{ + /// + /// Configures a Bosch Bno055 9-axis inertial measurement unit (IMU) that is polled by the computer. + /// + /// + /// This configuration operator can be linked to a data IO operator, such as , using a shared DeviceName. + /// + [Editor("OpenEphys.Onix1.Design.PolledBno055Editor, OpenEphys.Onix1.Design", typeof(ComponentEditor))] + [Description("Configures a PolledBno055 device.")] + public class ConfigurePolledBno055 : SingleDeviceFactory + { + + /// + /// Initializes a new instance of the class. + /// + public ConfigurePolledBno055() + : base(typeof(PolledBno055)) + { + } + + /// + /// Copy constructor for the class. + /// + /// A pre-existing object. + public ConfigurePolledBno055(ConfigurePolledBno055 configurePolledBno055) + : base(typeof(PolledBno055)) + { + Enable = configurePolledBno055.Enable; + DeviceName = configurePolledBno055.DeviceName; + DeviceAddress = configurePolledBno055.DeviceAddress; + AxisMap = configurePolledBno055.AxisMap; + AxisSign = configurePolledBno055.AxisSign; + } + + /// + /// Gets or sets the device enable state. + /// + /// + /// If set to true, will produce data. If set to false, + /// will not produce data. + /// + [Category(ConfigurationCategory)] + [Description("Specifies whether the Bno055 device is enabled.")] + public bool Enable { get; set; } = true; + + /// + /// Gets or sets the axis map that will be applied during configuration. + /// + [Browsable(false)] + public Bno055AxisMap AxisMap { get; set; } + + /// + /// Gets or sets the axis map sign that will be applied during configuration + /// + [Browsable(false)] + public Bno055AxisSign AxisSign { get; set; } + + /// + /// Configures a PolledBno055 device. + /// + /// + /// This will schedule configuration actions to be applied by a node + /// prior to data acquisition. + /// + /// A sequence of that holds all configuration actions. + /// + /// The original sequence with the side effect of an additional configuration action to configure + /// a PolledBno055 device. + /// + public override IObservable Process(IObservable source) + { + var enable = Enable; + var deviceName = DeviceName; + var deviceAddress = DeviceAddress; + return source.ConfigureDevice(context => + { + // configure device via the DS90UB9x deserializer device + var device = context.GetPassthroughDeviceContext(deviceAddress, typeof(DS90UB9x)); + ConfigureDeserializer(device); + ConfigureBno055(device); + var deviceInfo = new PolledBno055DeviceInfo(context, DeviceType, deviceAddress, enable); + return DeviceManager.RegisterDevice(deviceName, deviceInfo); + }); + } + + static void ConfigureDeserializer(DeviceContext device) + { + // configure deserializer I2C aliases + var deserializer = new I2CRegisterContext(device, DS90UB9x.DES_ADDR); + uint alias = PolledBno055.BNO055Address << 1; + deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveID4, alias); + deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveAlias4, alias); + } + + void ConfigureBno055(DeviceContext device) + { + // setup Bno055 device + var i2c = new I2CRegisterContext(device, PolledBno055.BNO055Address); + i2c.WriteByte(0x3E, 0x00); // Power mode normal + i2c.WriteByte(0x07, 0x00); // Page ID address 0 + i2c.WriteByte(0x3F, 0x00); // Internal oscillator + i2c.WriteByte(0x41, (uint)AxisMap); // Axis map config + i2c.WriteByte(0x42, (uint)AxisSign); // Axis sign + i2c.WriteByte(0x3D, 8); // Operation mode is NOF + } + } + + static class PolledBno055 + { + public const int BNO055Address = 0x28; + public const int DataAddress = 0x1A; + + internal class NameConverter : DeviceNameConverter + { + public NameConverter() + : base(typeof(PolledBno055)) + { + } + } + } + + class PolledBno055DeviceInfo : DeviceInfo + { + public PolledBno055DeviceInfo(ContextTask context, Type deviceType, uint deviceAddress, bool enable) + : base(context, deviceType, deviceAddress) + { + Enable = enable; + } + + public bool Enable { get; } + } + + /// + /// Specifies the axis map of a Bno055 IMU + /// + /// + /// The axis of the device can be reconfigured to the new reference axis to account for + /// differences it its mounting position. The following values can be applied to the Bno055's + /// AXIS_MAP_CONFIG register at address 0x41. + /// + public enum Bno055AxisMap : uint + { + /// + /// Specifies X->X, Y->Y, Z->Z (chip default). + /// + XYZ = 0b00_10_01_00, + /// + /// Specifies X->X, Y->Z, Z->Y. + /// + XZY = 0b00_01_10_00, + /// + /// Specifies X->Y, Y->X, Z->Z. + /// + YXZ = 0b00_10_00_01, + /// + /// Specifies X->Y, Y->Z, Z->X. + /// + YZX = 0b00_00_10_01, + /// + /// Specifies X->Z, Y->X, Z->Y. + /// + ZXY = 0b00_01_00_10, + /// + /// Specifies X->Z, Y->Y, Z->X. + /// + ZYX = 0b00_00_01_10, + } + + /// + /// Specifies the axis map sign of a Bno055 IMU + /// + /// + /// The axis of the device can be reconfigured to the new reference axis to account for + /// differences it its mounting position. The following values can be applied to the Bno055's + /// AXIS_MAP_SIGN register at address 0x42. + /// + [Flags] + public enum Bno055AxisSign : uint + { + /// + /// Specifies that all axes are positive (chip default). + /// + Default = 0b00000_000, + /// + /// Specifies that Z axis should be mirrored. + /// + NegZ = 0b00000_001, + /// + /// Specifies that Y axis should be mirrored. + /// + NegY = 0b00000_010, + /// + /// Specifies that X axis should be mirrored. + /// + NegX = 0b00000_100, + } + + /// + [Obsolete("This operator is obsolete. Use ConfigurePolledBno055 instead. Will be removed in version 1.0.0.")] + public class ConfigureNeuropixelsV1eBno055 : ConfigurePolledBno055 { } + + /// + [Obsolete("This operator is obsolete. Use ConfigurePolledBno055 instead. Will be removed in version 1.0.0.")] + public class ConfigureNeuropixelsV2eBno055 : ConfigurePolledBno055 { } + + /// + [Obsolete("This operator is obsolete. Use ConfigurePolledBno055 instead. Will be removed in version 1.0.0.")] + public class ConfigureNeuropixelsV2eBetaBno055 : ConfigurePolledBno055 { } +} + diff --git a/OpenEphys.Onix1/NeuropixelsV1eBno055Data.cs b/OpenEphys.Onix1/NeuropixelsV1eBno055Data.cs deleted file mode 100644 index 6fdd577..0000000 --- a/OpenEphys.Onix1/NeuropixelsV1eBno055Data.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Reactive.Linq; -using Bonsai; - -namespace OpenEphys.Onix1 -{ - /// - /// Produces a sequence of objects from a NeuropixelsV1e headstage. - /// - /// - /// This data IO operator must be linked to an appropriate configuration, such as a , using a shared DeviceName. - /// - [Description("Produces a sequence of Bno055DataFrame objects from a NeuropixelsV1e headstage.")] - public class NeuropixelsV1eBno055Data : Source - { - /// - [TypeConverter(typeof(NeuropixelsV1eBno055.NameConverter))] - [Description(SingleDeviceFactory.DeviceNameDescription)] - [Category(DeviceFactory.ConfigurationCategory)] - public string DeviceName { get; set; } - - /// - /// Generates a sequence of Bno055DataFrames at approximately 100 - /// Hz. - /// - /// - /// This will generate a sequence of Bno055DataFrames at approximately 100 Hz. - /// This rate may be limited by the hardware. - /// - /// A sequence of Bno055DataFrames. - public override IObservable Generate() - { - // Max of 100 Hz, but limited by I2C bus - var source = Observable.Interval(TimeSpan.FromSeconds(0.01)); - return Generate(source); - } - - /// - /// Generates a sequence of Bno055DataFrames that is driven by an - /// input sequence. - /// - /// - /// This will attempt to produce a sequence of Bno055DataFrames that is updated whenever - /// an item in the sequence is received. This rate is be limited by the - /// hardware and has a maximum meaningful rate of 100 Hz. - /// - /// A sequence to drive sampling. - /// A sequence of objects. - public unsafe IObservable Generate(IObservable source) - { - return DeviceManager.GetDevice(DeviceName).SelectMany( - deviceInfo => - { - return !((NeuropixelsV1eBno055DeviceInfo)deviceInfo).Enable - ? Observable.Empty() - : Observable.Create(observer => - { - var device = deviceInfo.GetDeviceContext(typeof(NeuropixelsV1eBno055)); - var passthrough = device.GetPassthroughDeviceContext(typeof(DS90UB9x)); - var i2c = new I2CRegisterContext(passthrough, NeuropixelsV1eBno055.BNO055Address); - - return source.SubscribeSafe(observer, _ => - { - Bno055DataFrame frame = default; - device.Context.EnsureContext(() => - { - var data = i2c.ReadBytes(NeuropixelsV1eBno055.DataAddress, sizeof(Bno055DataPayload)); - ulong clock = passthrough.ReadRegister(DS90UB9x.LASTI2CL); - clock += (ulong)passthrough.ReadRegister(DS90UB9x.LASTI2CH) << 32; - fixed (byte* dataPtr = data) - { - frame = new Bno055DataFrame(clock, (Bno055DataPayload*)dataPtr); - } - }); - - if (frame != null) - { - observer.OnNext(frame); - } - }); - }); - }); - } - } -} diff --git a/OpenEphys.Onix1/NeuropixelsV2eBno055Data.cs b/OpenEphys.Onix1/PolledBno055Data.cs similarity index 72% rename from OpenEphys.Onix1/NeuropixelsV2eBno055Data.cs rename to OpenEphys.Onix1/PolledBno055Data.cs index cb10909..884d66c 100644 --- a/OpenEphys.Onix1/NeuropixelsV2eBno055Data.cs +++ b/OpenEphys.Onix1/PolledBno055Data.cs @@ -7,17 +7,18 @@ namespace OpenEphys.Onix1 { /// - /// Produces a sequence of objects from a NeuropixelsV2e headstage. + /// Produces a sequence of Bno055DataFrames from Bosch Bno055 + /// 9-axis inertial measurement unit (IMU) /// /// /// This data IO operator must be linked to an appropriate configuration, such as a , using a shared DeviceName. + /// cref="ConfigurePolledBno055"/>, using a shared DeviceName. /// - [Description("Produces a sequence of Bno055DataFrame objects from a NeuropixelsV2e headstage.")] - public class NeuropixelsV2eBno055Data : Source + [Description("Polls a Bno055 9-axis IMU to produce a sequence Bno055 data frames.")] + public class PolledBno055Data : Source { /// - [TypeConverter(typeof(NeuropixelsV2eBno055.NameConverter))] + [TypeConverter(typeof(PolledBno055.NameConverter))] [Description(SingleDeviceFactory.DeviceNameDescription)] [Category(DeviceFactory.ConfigurationCategory)] public string DeviceName { get; set; } @@ -54,20 +55,20 @@ public unsafe IObservable Generate(IObservable { - return !((NeuropixelsV2eBno055DeviceInfo)deviceInfo).Enable + return !((PolledBno055DeviceInfo)deviceInfo).Enable ? Observable.Empty() : Observable.Create(observer => { - var device = deviceInfo.GetDeviceContext(typeof(NeuropixelsV2eBno055)); + var device = deviceInfo.GetDeviceContext(typeof(PolledBno055)); var passthrough = device.GetPassthroughDeviceContext(typeof(DS90UB9x)); - var i2c = new I2CRegisterContext(passthrough, NeuropixelsV2eBno055.BNO055Address); + var i2c = new I2CRegisterContext(passthrough, PolledBno055.BNO055Address); return source.SubscribeSafe(observer, _ => { Bno055DataFrame frame = default; device.Context.EnsureContext(() => { - var data = i2c.ReadBytes(NeuropixelsV2eBno055.DataAddress, sizeof(Bno055DataPayload)); + var data = i2c.ReadBytes(PolledBno055.DataAddress, sizeof(Bno055DataPayload)); ulong clock = passthrough.ReadRegister(DS90UB9x.LASTI2CL); clock += (ulong)passthrough.ReadRegister(DS90UB9x.LASTI2CH) << 32; fixed (byte* dataPtr = data) @@ -85,4 +86,17 @@ public unsafe IObservable Generate(IObservablev + [Obsolete("This operator is obsolete. Use PolledBno055Data instead. Will be removed in version 1.0.0.")] + public class NeuropixelsV1eBno055Data : PolledBno055Data { } + + /// v + [Obsolete("This operator is obsolete. Use PolledBno055Data instead. Will be removed in version 1.0.0.")] + public class NeuropixelsV2eBno055Data : PolledBno055Data { } + + /// v + [Obsolete("This operator is obsolete. Use PolledBno055Data instead. Will be removed in version 1.0.0.")] + public class NeuropixelsV2eBetaBno055Data : PolledBno055Data { } + } From d4fa769a7c2d4874a8f3f9049fbffae61e69842e Mon Sep 17 00:00:00 2001 From: bparks13 Date: Wed, 18 Sep 2024 09:56:58 -0400 Subject: [PATCH 2/3] Update GenericDeviceDialog, and address review comments - GenericDeviceDialog was not updated to use `TableLayoutPanel` and `FlowLayoutPanel`, so the buttons were getting clipped at different scales. This has been corrected - Typos and whitespace fixes --- OpenEphys.Onix1.Design/Bno055Dialog.cs | 4 +- OpenEphys.Onix1.Design/Bno055Editor.cs | 2 + .../GenericDeviceDialog.Designer.cs | 82 ++++++++++--------- OpenEphys.Onix1.Design/PolledBno055Dialog.cs | 6 +- OpenEphys.Onix1.Design/PolledBno055Editor.cs | 2 + .../ConfigureNeuropixelsV1eHeadstage.cs | 2 +- OpenEphys.Onix1/ConfigurePolledBno055.cs | 5 +- 7 files changed, 55 insertions(+), 48 deletions(-) diff --git a/OpenEphys.Onix1.Design/Bno055Dialog.cs b/OpenEphys.Onix1.Design/Bno055Dialog.cs index 2fbb1a0..89e012a 100644 --- a/OpenEphys.Onix1.Design/Bno055Dialog.cs +++ b/OpenEphys.Onix1.Design/Bno055Dialog.cs @@ -32,8 +32,8 @@ private void FormShown(object sender, EventArgs e) { if (!TopLevel) { - splitContainer1.Panel2Collapsed = true; - splitContainer1.Panel2.Hide(); + tableLayoutPanel1.Controls.Remove(flowLayoutPanel1); + tableLayoutPanel1.RowCount = 1; MaximumSize = new System.Drawing.Size(0, 0); } diff --git a/OpenEphys.Onix1.Design/Bno055Editor.cs b/OpenEphys.Onix1.Design/Bno055Editor.cs index f8e099f..a998b81 100644 --- a/OpenEphys.Onix1.Design/Bno055Editor.cs +++ b/OpenEphys.Onix1.Design/Bno055Editor.cs @@ -23,6 +23,8 @@ public override bool EditComponent(ITypeDescriptorContext context, object compon if (editorDialog.ShowDialog() == DialogResult.OK) { configureBno055.Enable = editorDialog.ConfigureNode.Enable; + configureBno055.DeviceAddress = editorDialog.ConfigureNode.DeviceAddress; + configureBno055.DeviceName = editorDialog.ConfigureNode.DeviceName; return true; } diff --git a/OpenEphys.Onix1.Design/GenericDeviceDialog.Designer.cs b/OpenEphys.Onix1.Design/GenericDeviceDialog.Designer.cs index 2201264..da541dc 100644 --- a/OpenEphys.Onix1.Design/GenericDeviceDialog.Designer.cs +++ b/OpenEphys.Onix1.Design/GenericDeviceDialog.Designer.cs @@ -30,54 +30,31 @@ private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(GenericDeviceDialog)); this.propertyGrid = new System.Windows.Forms.PropertyGrid(); - this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.buttonCancel = new System.Windows.Forms.Button(); this.buttonOK = new System.Windows.Forms.Button(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); - this.splitContainer1.Panel1.SuspendLayout(); - this.splitContainer1.Panel2.SuspendLayout(); - this.splitContainer1.SuspendLayout(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); + this.tableLayoutPanel1.SuspendLayout(); + this.flowLayoutPanel1.SuspendLayout(); this.SuspendLayout(); // // propertyGrid // this.propertyGrid.Dock = System.Windows.Forms.DockStyle.Fill; - this.propertyGrid.Location = new System.Drawing.Point(0, 0); + this.propertyGrid.Location = new System.Drawing.Point(3, 2); this.propertyGrid.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.propertyGrid.Name = "propertyGrid"; - this.propertyGrid.Size = new System.Drawing.Size(336, 438); + this.propertyGrid.Size = new System.Drawing.Size(299, 429); this.propertyGrid.TabIndex = 0; // - // splitContainer1 - // - this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Right; - this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; - this.splitContainer1.IsSplitterFixed = true; - this.splitContainer1.Location = new System.Drawing.Point(0, 0); - this.splitContainer1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); - this.splitContainer1.Name = "splitContainer1"; - this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; - // - // splitContainer1.Panel1 - // - this.splitContainer1.Panel1.Controls.Add(this.propertyGrid); - // - // splitContainer1.Panel2 - // - this.splitContainer1.Panel2.Controls.Add(this.buttonCancel); - this.splitContainer1.Panel2.Controls.Add(this.buttonOK); - this.splitContainer1.Size = new System.Drawing.Size(336, 475); - this.splitContainer1.SplitterDistance = 438; - this.splitContainer1.TabIndex = 1; - // // buttonCancel // this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.buttonCancel.Location = new System.Drawing.Point(180, -2); + this.buttonCancel.Location = new System.Drawing.Point(185, 2); this.buttonCancel.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.buttonCancel.Name = "buttonCancel"; - this.buttonCancel.Size = new System.Drawing.Size(144, 31); + this.buttonCancel.Size = new System.Drawing.Size(111, 34); this.buttonCancel.TabIndex = 6; this.buttonCancel.Text = "Cancel"; this.buttonCancel.UseVisualStyleBackColor = true; @@ -86,20 +63,46 @@ private void InitializeComponent() // this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; - this.buttonOK.Location = new System.Drawing.Point(17, -2); + this.buttonOK.Location = new System.Drawing.Point(68, 2); this.buttonOK.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.buttonOK.Name = "buttonOK"; - this.buttonOK.Size = new System.Drawing.Size(144, 31); + this.buttonOK.Size = new System.Drawing.Size(111, 34); this.buttonOK.TabIndex = 5; this.buttonOK.Text = "OK"; this.buttonOK.UseVisualStyleBackColor = true; // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 1; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Controls.Add(this.propertyGrid, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 0, 1); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Right; + this.tableLayoutPanel1.Location = new System.Drawing.Point(4, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 42F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(305, 475); + this.tableLayoutPanel1.TabIndex = 2; + // + // flowLayoutPanel1 + // + this.flowLayoutPanel1.Controls.Add(this.buttonCancel); + this.flowLayoutPanel1.Controls.Add(this.buttonOK); + this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; + this.flowLayoutPanel1.Location = new System.Drawing.Point(3, 436); + this.flowLayoutPanel1.Name = "flowLayoutPanel1"; + this.flowLayoutPanel1.Size = new System.Drawing.Size(299, 36); + this.flowLayoutPanel1.TabIndex = 1; + // // GenericDeviceDialog // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(336, 475); - this.Controls.Add(this.splitContainer1); + this.ClientSize = new System.Drawing.Size(309, 475); + this.Controls.Add(this.tableLayoutPanel1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.MaximizeBox = false; @@ -108,18 +111,17 @@ private void InitializeComponent() this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Generic Device Configuration"; - this.splitContainer1.Panel1.ResumeLayout(false); - this.splitContainer1.Panel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); - this.splitContainer1.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.flowLayoutPanel1.ResumeLayout(false); this.ResumeLayout(false); } #endregion internal System.Windows.Forms.PropertyGrid propertyGrid; - internal System.Windows.Forms.SplitContainer splitContainer1; private System.Windows.Forms.Button buttonCancel; private System.Windows.Forms.Button buttonOK; + internal System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + internal System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; } } diff --git a/OpenEphys.Onix1.Design/PolledBno055Dialog.cs b/OpenEphys.Onix1.Design/PolledBno055Dialog.cs index 53355d4..0ed7b47 100644 --- a/OpenEphys.Onix1.Design/PolledBno055Dialog.cs +++ b/OpenEphys.Onix1.Design/PolledBno055Dialog.cs @@ -34,8 +34,10 @@ private void FormShown(object sender, EventArgs e) { if (!TopLevel) { - splitContainer1.Panel2Collapsed = true; - splitContainer1.Panel2.Hide(); + tableLayoutPanel1.Controls.Remove(flowLayoutPanel1); + tableLayoutPanel1.RowCount = 1; + + MaximumSize = new System.Drawing.Size(0, 0); } } } diff --git a/OpenEphys.Onix1.Design/PolledBno055Editor.cs b/OpenEphys.Onix1.Design/PolledBno055Editor.cs index 8dfefdc..bef16bb 100644 --- a/OpenEphys.Onix1.Design/PolledBno055Editor.cs +++ b/OpenEphys.Onix1.Design/PolledBno055Editor.cs @@ -19,6 +19,8 @@ public override bool EditComponent(ITypeDescriptorContext context, object compon if (editorDialog.ShowDialog() == DialogResult.OK) { configureBno055.Enable = editorDialog.ConfigureNode.Enable; + configureBno055.DeviceAddress = editorDialog.ConfigureNode.DeviceAddress; + configureBno055.DeviceName = editorDialog.ConfigureNode.DeviceName; return true; } diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs index 488b99a..a061f74 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs @@ -43,7 +43,7 @@ public ConfigureNeuropixelsV1eHeadstage() [Category(DevicesCategory)] [TypeConverter(typeof(SingleDeviceFactoryConverter))] [Description("Specifies the configuration for the NeuropixelsV1e device.")] - public ConfigureNeuropixelsV1e NeuropixelsV1e { get; set; } = new(); + public ConfigureNeuropixelsV1e NeuropixelsV1e { get; set; } = new(); /// /// Gets or sets the Bno055 9-axis inertial measurement unit configuration. diff --git a/OpenEphys.Onix1/ConfigurePolledBno055.cs b/OpenEphys.Onix1/ConfigurePolledBno055.cs index 9e96cb4..b0915d6 100644 --- a/OpenEphys.Onix1/ConfigurePolledBno055.cs +++ b/OpenEphys.Onix1/ConfigurePolledBno055.cs @@ -14,7 +14,6 @@ namespace OpenEphys.Onix1 [Description("Configures a PolledBno055 device.")] public class ConfigurePolledBno055 : SingleDeviceFactory { - /// /// Initializes a new instance of the class. /// @@ -140,7 +139,7 @@ public PolledBno055DeviceInfo(ContextTask context, Type deviceType, uint deviceA /// /// /// The axis of the device can be reconfigured to the new reference axis to account for - /// differences it its mounting position. The following values can be applied to the Bno055's + /// differences in its mounting position. The following values can be applied to the Bno055's /// AXIS_MAP_CONFIG register at address 0x41. /// public enum Bno055AxisMap : uint @@ -176,7 +175,7 @@ public enum Bno055AxisMap : uint /// /// /// The axis of the device can be reconfigured to the new reference axis to account for - /// differences it its mounting position. The following values can be applied to the Bno055's + /// differences in its mounting position. The following values can be applied to the Bno055's /// AXIS_MAP_SIGN register at address 0x42. /// [Flags] From 76edca06cd7ab0898f50fb4b0551257e63501200 Mon Sep 17 00:00:00 2001 From: jonnew Date: Thu, 19 Sep 2024 12:26:02 -0400 Subject: [PATCH 3/3] Make AxisMap and AxisSign public properties of ConfigurePolledBno055 - This way they can be set if this is used as a standalone device - Add PolledBno055SingleDeviceFactoryConverter to remove them from the properties pane when used in the context of MultiDeviceFactory with a specified orientation - Add correct AxisMap and AxisSign values to obsolete overrides of ConfigurePolledBno055 --- .../ConfigureNeuropixelsV1eHeadstage.cs | 8 +- .../ConfigureNeuropixelsV2eBetaHeadstage.cs | 6 +- .../ConfigureNeuropixelsV2eHeadstage.cs | 4 +- OpenEphys.Onix1/ConfigurePolledBno055.cs | 97 ++++++++++++++++--- 4 files changed, 90 insertions(+), 25 deletions(-) diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs index a061f74..3d954f8 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV1eHeadstage.cs @@ -49,11 +49,11 @@ public ConfigureNeuropixelsV1eHeadstage() /// Gets or sets the Bno055 9-axis inertial measurement unit configuration. /// [Category(DevicesCategory)] - [TypeConverter(typeof(SingleDeviceFactoryConverter))] + [TypeConverter(typeof(PolledBno055SingleDeviceFactoryConverter))] [Description("Specifies the configuration for the Bno055 device.")] - public ConfigurePolledBno055 Bno055 { get; set; } = - new ConfigurePolledBno055 { AxisMap = Bno055AxisMap.ZXY, AxisSign = Bno055AxisSign.NegZ | Bno055AxisSign.NegY }; // Axis map: X => -Z, Y => X, Z => -Y. - + public ConfigurePolledBno055 Bno055 { get; set; } = + new ConfigurePolledBno055 { AxisMap = Bno055AxisMap.ZXY, AxisSign = Bno055AxisSign.MirrorZ | Bno055AxisSign.MirrorY }; + /// /// Gets or sets the port. /// diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBetaHeadstage.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV2eBetaHeadstage.cs index ae186ef..62477db 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBetaHeadstage.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV2eBetaHeadstage.cs @@ -48,10 +48,10 @@ public ConfigureNeuropixelsV2eBetaHeadstage() /// Gets or sets the Bno055 9-axis inertial measurement unit configuration. /// [Category(DevicesCategory)] - [TypeConverter(typeof(SingleDeviceFactoryConverter))] + [TypeConverter(typeof(PolledBno055SingleDeviceFactoryConverter))] [Description("Specifies the configuration for the Bno055 device.")] - public ConfigurePolledBno055 Bno055 { get; set; } = - new ConfigurePolledBno055 { AxisMap = Bno055AxisMap.ZXY, AxisSign = Bno055AxisSign.Default }; // Axis map: X => Z, Y => X, Z => Y. + public ConfigurePolledBno055 Bno055 { get; set; } = + new ConfigurePolledBno055 { AxisMap = Bno055AxisMap.ZXY, AxisSign = Bno055AxisSign.Default }; /// /// Gets or sets the port. diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV2eHeadstage.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV2eHeadstage.cs index e51e61b..2a1c202 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV2eHeadstage.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV2eHeadstage.cs @@ -48,10 +48,10 @@ public ConfigureNeuropixelsV2eHeadstage() /// Gets or sets the Bno055 9-axis inertial measurement unit configuration. /// [Category(DevicesCategory)] - [TypeConverter(typeof(SingleDeviceFactoryConverter))] + [TypeConverter(typeof(PolledBno055SingleDeviceFactoryConverter))] [Description("Specifies the configuration for the Bno055 device.")] public ConfigurePolledBno055 Bno055 { get; set; } = - new ConfigurePolledBno055 { AxisMap = Bno055AxisMap.ZXY, AxisSign = Bno055AxisSign.Default }; // Axis map: X => Z, Y => X, Z => Y. + new ConfigurePolledBno055 { AxisMap = Bno055AxisMap.ZXY, AxisSign = Bno055AxisSign.Default }; /// /// Gets or sets the port. diff --git a/OpenEphys.Onix1/ConfigurePolledBno055.cs b/OpenEphys.Onix1/ConfigurePolledBno055.cs index b0915d6..5577f82 100644 --- a/OpenEphys.Onix1/ConfigurePolledBno055.cs +++ b/OpenEphys.Onix1/ConfigurePolledBno055.cs @@ -1,10 +1,12 @@ using System; using System.ComponentModel; +using System.Linq; namespace OpenEphys.Onix1 { /// - /// Configures a Bosch Bno055 9-axis inertial measurement unit (IMU) that is polled by the computer. + /// Configures a Bosch Bno055 9-axis inertial measurement unit (IMU) that is polled by the + /// computer. /// /// /// This configuration operator can be linked to a data IO operator, such as - /// Gets or sets the device enable state. + /// Gets or sets a value specifying whether the Bno055 device is enabled. /// /// /// If set to true, will produce data. If set to false, @@ -50,14 +52,26 @@ public ConfigurePolledBno055(ConfigurePolledBno055 configurePolledBno055) /// /// Gets or sets the axis map that will be applied during configuration. /// - [Browsable(false)] - public Bno055AxisMap AxisMap { get; set; } + /// + /// This value can be changed to compensate for the Bno055's mounting orientation. + /// Specifically, this value can be set to rotate the Bno055's coordinate system compared + /// to the default orientation presented on page 24 of the Bno055 datasheet. + /// + [Category(ConfigurationCategory)] + [Description("Specifies the axis map that will be applied during configuration.")] + public Bno055AxisMap AxisMap { get; set; } = Bno055AxisMap.XYZ; /// - /// Gets or sets the axis map sign that will be applied during configuration + /// Gets or sets the axis sign that will be applied during configuration. /// - [Browsable(false)] - public Bno055AxisSign AxisSign { get; set; } + /// + /// This value can be changed to compensate for the Bno055's mounting orientation. + /// Specifically, this value can be set to mirror specific axes in the Bno055's coordinate + /// system compared to the default orientation presented on page 24 of the Bno055 datasheet. + /// + [Category(ConfigurationCategory)] + [Description("Specifies axis sign that will be applied during configuration.")] + public Bno055AxisSign AxisSign { get; set; } = Bno055AxisSign.Default; /// /// Configures a PolledBno055 device. @@ -135,12 +149,14 @@ public PolledBno055DeviceInfo(ContextTask context, Type deviceType, uint deviceA } /// - /// Specifies the axis map of a Bno055 IMU + /// Specifies the axis map of a Bno055 compared to the default orientation. + /// the datasheet. /// /// /// The axis of the device can be reconfigured to the new reference axis to account for /// differences in its mounting position. The following values can be applied to the Bno055's - /// AXIS_MAP_CONFIG register at address 0x41. + /// AXIS_MAP_CONFIG register at address 0x41 in order to rotate the Bno055's coordinate system + /// compared to the default orientation presented on page 24 of the Bno055 datasheet. /// public enum Bno055AxisMap : uint { @@ -176,7 +192,8 @@ public enum Bno055AxisMap : uint /// /// The axis of the device can be reconfigured to the new reference axis to account for /// differences in its mounting position. The following values can be applied to the Bno055's - /// AXIS_MAP_SIGN register at address 0x42. + /// AXIS_MAP_SIGN register at address 0x42 to mirror specific axes in the Bno055's coordinate + /// system compared to the default orientation presented on page 24 of the Bno055 datasheet. /// [Flags] public enum Bno055AxisSign : uint @@ -188,27 +205,75 @@ public enum Bno055AxisSign : uint /// /// Specifies that Z axis should be mirrored. /// - NegZ = 0b00000_001, + MirrorZ = 0b00000_001, /// /// Specifies that Y axis should be mirrored. /// - NegY = 0b00000_010, + MirrorY = 0b00000_010, /// /// Specifies that X axis should be mirrored. /// - NegX = 0b00000_100, + MirrorX = 0b00000_100, + } + + // NB: Can be used to remove axis map and sign properties from MutliDeviceFactories that include a + // ConfigurePolledBno055 when having those options would cause confusion and potential + // commutator malfunction + internal class PolledBno055SingleDeviceFactoryConverter : SingleDeviceFactoryConverter + { + public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) + { + var properties = (from property in base.GetProperties(context, value, attributes).Cast() + where !property.IsReadOnly && + !(property.PropertyType == typeof(Bno055AxisMap)) && + !(property.PropertyType == typeof(Bno055AxisSign)) && + property.ComponentType != typeof(SingleDeviceFactory) + select property) + .ToArray(); + return new PropertyDescriptorCollection(properties).Sort(properties.Select(p => p.Name).ToArray()); + } } /// [Obsolete("This operator is obsolete. Use ConfigurePolledBno055 instead. Will be removed in version 1.0.0.")] - public class ConfigureNeuropixelsV1eBno055 : ConfigurePolledBno055 { } + public class ConfigureNeuropixelsV1eBno055 : ConfigurePolledBno055 + { + /// + /// Initializes a new instance of the class. + /// + public ConfigureNeuropixelsV1eBno055() + { + AxisMap = Bno055AxisMap.ZXY; + AxisSign = Bno055AxisSign.MirrorZ | Bno055AxisSign.MirrorY; + } + } /// [Obsolete("This operator is obsolete. Use ConfigurePolledBno055 instead. Will be removed in version 1.0.0.")] - public class ConfigureNeuropixelsV2eBno055 : ConfigurePolledBno055 { } + public class ConfigureNeuropixelsV2eBno055 : ConfigurePolledBno055 + { + /// + /// Initializes a new instance of the class. + /// + public ConfigureNeuropixelsV2eBno055() + { + AxisMap = Bno055AxisMap.ZXY; + AxisSign = Bno055AxisSign.Default; + } + } /// [Obsolete("This operator is obsolete. Use ConfigurePolledBno055 instead. Will be removed in version 1.0.0.")] - public class ConfigureNeuropixelsV2eBetaBno055 : ConfigurePolledBno055 { } + public class ConfigureNeuropixelsV2eBetaBno055 : ConfigurePolledBno055 + { + /// + /// Initializes a new instance of the class. + /// + public ConfigureNeuropixelsV2eBetaBno055() + { + AxisMap = Bno055AxisMap.ZXY; + AxisSign = Bno055AxisSign.Default; + } + } }