From 77451af4a265b2da94b62eec429f500839e75df6 Mon Sep 17 00:00:00 2001 From: Andras Schaffer Date: Tue, 28 Nov 2023 21:45:29 +0100 Subject: [PATCH] Setup: SerialPort settings screen (#3240) * Setup: SerialPort settings screen * Clean up usings to make OSX build happy * Moved down tab below Servo Output Add BRD_SERx_RTSCTS check Increase cell sizes to decrease clutter --- ExtLibs/Utilities/DisplayView.cs | 2 + .../ConfigSerial.Designer.cs | 131 ++ GCSViews/ConfigurationView/ConfigSerial.cs | 509 +++++ GCSViews/ConfigurationView/ConfigSerial.resx | 120 ++ GCSViews/InitialSetup.cs | 5 +- GCSViews/InitialSetup.resx | 1897 +++++++++-------- MissionPlanner.csproj | 12 + SerialOptionRules.json | 22 + 8 files changed, 1750 insertions(+), 948 deletions(-) create mode 100644 GCSViews/ConfigurationView/ConfigSerial.Designer.cs create mode 100644 GCSViews/ConfigurationView/ConfigSerial.cs create mode 100644 GCSViews/ConfigurationView/ConfigSerial.resx create mode 100644 SerialOptionRules.json diff --git a/ExtLibs/Utilities/DisplayView.cs b/ExtLibs/Utilities/DisplayView.cs index e06247cbb3..8b935879c2 100644 --- a/ExtLibs/Utilities/DisplayView.cs +++ b/ExtLibs/Utilities/DisplayView.cs @@ -95,6 +95,7 @@ public class DisplayView public Boolean displayParachute { get; set; } public Boolean displayEsp { get; set; } public Boolean displayAntennaTracker { get; set; } + public Boolean displaySerialPorts { get; set; } //config tuning @@ -189,6 +190,7 @@ public DisplayView() displayAntennaTracker = true; displayRTKInject = true; displayJoystick = true; + displaySerialPorts = true; //config tuning diff --git a/GCSViews/ConfigurationView/ConfigSerial.Designer.cs b/GCSViews/ConfigurationView/ConfigSerial.Designer.cs new file mode 100644 index 0000000000..c5d5f93ca4 --- /dev/null +++ b/GCSViews/ConfigurationView/ConfigSerial.Designer.cs @@ -0,0 +1,131 @@ +namespace MissionPlanner.GCSViews.ConfigurationView +{ + partial class ConfigSerial + { + /// + /// 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 Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.myLabel1 = new MissionPlanner.Controls.MyLabel(); + this.myLabel2 = new MissionPlanner.Controls.MyLabel(); + this.myLabel3 = new MissionPlanner.Controls.MyLabel(); + this.myLabel4 = new MissionPlanner.Controls.MyLabel(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 5; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 152F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 114F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 132F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 307F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 10F)); + this.tableLayoutPanel1.Controls.Add(this.myLabel1, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.myLabel2, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.myLabel3, 2, 0); + this.tableLayoutPanel1.Controls.Add(this.myLabel4, 3, 0); + this.tableLayoutPanel1.Location = new System.Drawing.Point(9, 10); + this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(2); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 12; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.090908F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.090908F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.090908F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.090908F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.090908F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.090908F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.090908F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.090908F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.090908F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.090908F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.090908F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(789, 497); + this.tableLayoutPanel1.TabIndex = 0; + // + // myLabel1 + // + this.myLabel1.Anchor = System.Windows.Forms.AnchorStyles.None; + this.myLabel1.Location = new System.Drawing.Point(38, 9); + this.myLabel1.Name = "myLabel1"; + this.myLabel1.resize = false; + this.myLabel1.Size = new System.Drawing.Size(75, 23); + this.myLabel1.TabIndex = 0; + this.myLabel1.Text = "Port Name"; + // + // myLabel2 + // + this.myLabel2.Anchor = System.Windows.Forms.AnchorStyles.None; + this.myLabel2.Location = new System.Drawing.Point(171, 9); + this.myLabel2.Name = "myLabel2"; + this.myLabel2.resize = false; + this.myLabel2.Size = new System.Drawing.Size(75, 23); + this.myLabel2.TabIndex = 1; + this.myLabel2.Text = "Speed"; + // + // myLabel3 + // + this.myLabel3.Anchor = System.Windows.Forms.AnchorStyles.None; + this.myLabel3.Location = new System.Drawing.Point(294, 9); + this.myLabel3.Name = "myLabel3"; + this.myLabel3.resize = false; + this.myLabel3.Size = new System.Drawing.Size(75, 23); + this.myLabel3.TabIndex = 2; + this.myLabel3.Text = "Protcol"; + // + // myLabel4 + // + this.myLabel4.Anchor = System.Windows.Forms.AnchorStyles.None; + this.myLabel4.Location = new System.Drawing.Point(514, 9); + this.myLabel4.Name = "myLabel4"; + this.myLabel4.resize = false; + this.myLabel4.Size = new System.Drawing.Size(75, 23); + this.myLabel4.TabIndex = 3; + this.myLabel4.Text = "Options"; + // + // ConfigSerial + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tableLayoutPanel1); + this.Margin = new System.Windows.Forms.Padding(2); + this.Name = "ConfigSerial"; + this.Size = new System.Drawing.Size(812, 519); + this.tableLayoutPanel1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private Controls.MyLabel myLabel1; + private Controls.MyLabel myLabel2; + private Controls.MyLabel myLabel3; + private Controls.MyLabel myLabel4; + } +} diff --git a/GCSViews/ConfigurationView/ConfigSerial.cs b/GCSViews/ConfigurationView/ConfigSerial.cs new file mode 100644 index 0000000000..cbc19c3150 --- /dev/null +++ b/GCSViews/ConfigurationView/ConfigSerial.cs @@ -0,0 +1,509 @@ +using MissionPlanner.ArduPilot; +using MissionPlanner.ArduPilot.Mavlink; +using MissionPlanner.Controls; +using MissionPlanner.Utilities; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading; +using System.Windows.Forms; + +namespace MissionPlanner.GCSViews.ConfigurationView +{ + public partial class ConfigSerial : MyUserControl, IActivate, IDeactivate + { + + private bool _gotUARTNames = false; + private bool _gotOptionRules = false; + private Dictionary _uartNames = new Dictionary(); + private Dictionary _optionRules = new Dictionary(); + + private Label noteLabel; + + public ConfigSerial() + { + InitializeComponent(); + } + + //This is a long function, but I did not extract methods that are used once only + //because it is easier to follow the logic this way + + public void Activate() + { + //Get OptionRules if not already done + if (!_gotOptionRules) + { + _optionRules.Clear(); + var filename = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "SerialOptionRules.json"); + //Check if the file exist + if (File.Exists(filename)) + { + try + { + using (StreamReader r = new StreamReader(filename)) + { + string json = r.ReadToEnd(); + _optionRules = JsonConvert.DeserializeObject>(json); + } + } + catch(Exception ex) + { + CustomMessageBox.Show("Error reading SerialOptionRules.json file: " + ex.Message); + } + } + var baudOptions = ParameterMetaDataRepository.GetParameterOptionsInt("SERIAL1_BAUD", MainV2.comPort.MAV.cs.firmware.ToString()); + //sanitize data, check for baudrates + foreach (var item in _optionRules) + { + int key = item.Key; + int baudrate = item.Value.baudrate; + if (baudrate > -1) + { + if (!baudOptions.Any(pair => pair.Key == baudrate)) + { + _optionRules[key].baudrate = -1; + } + } + } + _gotOptionRules = true; + } + + //Try to Get UART names from MAVftp, if not already done + if (!_gotUARTNames) + { + _gotUARTNames = true; + + var filename = @"@SYS/uarts.txt"; + MAVFtp _mavftp = new MAVFtp(MainV2.comPort, MainV2.comPort.MAV.sysid, MainV2.comPort.MAV.compid); + ProgressReporterDialogue prd = new ProgressReporterDialogue(); + CancellationTokenSource cancel = new CancellationTokenSource(); + MemoryStream ms = new MemoryStream(); + + prd.doWorkArgs.CancelRequestChanged += (o, args) => + { + prd.doWorkArgs.ErrorMessage = "User Cancel"; + cancel.Cancel(); + _mavftp.kCmdResetSessions(); + }; + prd.doWorkArgs.ForceExit = false; + Action progress = delegate (string message, int i) + { + prd.UpdateProgressAndStatus(i, "Trying to download uarts.txt\r\nFrom FC"); + }; + _mavftp.Progress += progress; + + prd.DoWork += (iprd) => + { + try + { + ms = _mavftp.GetFile(filename, cancel, false); + } + catch (Exception ex) + { + //prd.doWorkArgs.ErrorMessage = ex.Message; + //fail silently + } + if (cancel.IsCancellationRequested) + { + iprd.doWorkArgs.CancelAcknowledged = true; + iprd.doWorkArgs.CancelRequested = true; + return; + } + }; + + prd.RunBackgroundOperationAsync(); + _mavftp.Progress -= progress; + + if (ms.Length > 0) + { + if (_uartNames.Count > 0) + { + _uartNames.Clear(); + } + + //catch any errors that happens when parsing the file + try + { + + using (System.IO.StreamReader reader = new System.IO.StreamReader(ms)) + { + string line; + while ((line = reader.ReadLine()) != null) + { + var s = line.Split(' '); + if (s.Length >= 2) + { + //get the trailing number from the first string + if (s[0].Length >= 7 && s[0].Substring(0, 6) == "SERIAL") + { + var n = 0; + var success = Int32.TryParse(s[0].Substring(6), out n); + if (success) + { + if (n > 0) + { + _uartNames.Add(n, s[1]); + } + } + } + } + } + } + } + catch { } //fail silently + } + } + + //find the largest numbered serialx_baud param + int serialPorts = 0; + foreach (var param in MainV2.comPort.MAV.param.Keys) + { + if (param.StartsWith("SERIAL") && param.EndsWith("_BAUD")) + { + int port; + Int32.TryParse(param.Substring(6, 1), out port); //if unable to parse, then port = 0 + if (port > serialPorts) + { + serialPorts = port; + } + } + } + + if (serialPorts == 0) + { + //No serial ports found + return; + } + + //Populate the table + tableLayoutPanel1.SuspendLayout(); + for (int i = 1; i <= serialPorts; i++) + { + string portName = "SERIAL" + i.ToString(); + string uartName = ""; + + if (_uartNames.ContainsKey(i)) + { + uartName = _uartNames[i]; + } + + //Get the RTS/CTS options if there is any + string ctsrtsParamName = "BRD_SER" +i.ToString() + "_RTSCTS"; + if (MainV2.comPort.MAV.param.ContainsKey(ctsrtsParamName)) + { + var ctsValue = MainV2.comPort.MAV.param[ctsrtsParamName].Value; + if (ctsValue == 1) + { + uartName = uartName + " (RTS/CTS)"; + } + if (ctsValue == 2) + { + uartName = uartName + " (RTS/CTS Auto)"; + } + } + //Port Name Label + Label label = new Label(); + label.Text = "SERIAL PORT " + i.ToString() + "\n" + uartName; + label.Location = new Point(0, 0); + label.Size = new Size(100, 40); + label.Anchor = AnchorStyles.None; + label.Dock = DockStyle.Fill; + label.TextAlign = ContentAlignment.MiddleCenter; + Font f = label.Font; + label.Font = new Font(Font, FontStyle.Bold); + ThemeManager.ApplyThemeTo(label); + tableLayoutPanel1.GetControlFromPosition(0, i)?.Dispose() ; + tableLayoutPanel1.Controls.Add(label, 0, i); + + //Baud setting combobox + string baudParamName = portName + "_BAUD"; + var baudOptions = ParameterMetaDataRepository.GetParameterOptionsInt(baudParamName, MainV2.comPort.MAV.cs.firmware.ToString()); + if (baudOptions.Count > 0) + { + ComboBox cmb = new ComboBox() { Dock = DockStyle.Fill }; + cmb.DropDownStyle = ComboBoxStyle.DropDownList; + cmb.DataSource = baudOptions; + cmb.DisplayMember = "Value"; + cmb.ValueMember = "Key"; + cmb.Anchor = AnchorStyles.None; + cmb.Name = baudParamName; + widenComboBox(cmb); + ThemeManager.ApplyThemeTo(cmb); + tableLayoutPanel1.GetControlFromPosition(1, i)?.Dispose(); + tableLayoutPanel1.Controls.Add(cmb, 1, i); + int val = -1; + if (int.TryParse(MainV2.comPort.MAV.param[baudParamName].Value.ToString(), out val)) + { + cmb.SelectedValue = val; + } + else + { + cmb.SelectedIndex = -1; + } + cmb.SelectedIndexChanged += (s, a) => + { + setParam(cmb.Name, cmb.SelectedValue.ToString()); + }; + } + + //Protocol setting combobox + string protParamName = portName + "_PROTOCOL"; + var protOptions = ParameterMetaDataRepository.GetParameterOptionsInt(protParamName, MainV2.comPort.MAV.cs.firmware.ToString()); + if (protOptions.Count > 0) + { + ComboBox cmb = new ComboBox() + { + Dock = DockStyle.Fill, + DropDownStyle = ComboBoxStyle.DropDownList, + DataSource = protOptions, + DisplayMember = "Value", + ValueMember = "Key", + Anchor = AnchorStyles.None, + Name = protParamName + }; + + widenComboBox(cmb); + ThemeManager.ApplyThemeTo(cmb); + tableLayoutPanel1.GetControlFromPosition(2, i)?.Dispose(); + tableLayoutPanel1.Controls.Add(cmb, 2, i); + + // Populate the current selection from the cell value, if it's valid + int val = -1; + if (int.TryParse(MainV2.comPort.MAV.param[protParamName].Value.ToString(), out val)) + { + cmb.SelectedValue = val; + } + else + { + cmb.SelectedIndex = -1; + } + cmb.SelectedIndexChanged += (s, a) => + { + setParam(cmb.Name, cmb.SelectedValue.ToString()); + //Apply rules + doApplyRules(portName, cmb.SelectedValue.ToString()); + }; + } + + //Options label + string param_name = portName + "_OPTIONS"; + + var binlist = ParameterMetaDataRepository.GetParameterBitMaskInt(param_name, MainV2.comPort.MAV.cs.firmware.ToString()); + var param_value = MainV2.comPort.MAV.param[param_name].Value; + + Label label1 = new Label() + { + Text = "", + Anchor = AnchorStyles.None, + Dock = DockStyle.Fill, + AutoSize = true, + MaximumSize = new Size(300, 200), + Location = new Point(0, 0), + Size = new Size(100, 20), + TextAlign = ContentAlignment.MiddleLeft + }; + //populate the label based on the options value + setLabelOptions(param_name, label1); + ThemeManager.ApplyThemeTo(label1); + tableLayoutPanel1.GetControlFromPosition(3, i)?.Dispose(); + tableLayoutPanel1.Controls.Add(label1, 3, i); + + //Bit setting button and form + var bitmask = ParameterMetaDataRepository.GetParameterBitMaskInt(param_name, MainV2.comPort.MAV.cs.firmware.ToString()); + if (bitmask.Count > 0) + { + MyButton optionsControl = new MyButton() { Text = "Set Bitmask" }; + optionsControl.Click += (s, a) => + { + var mcb = new MavlinkCheckBoxBitMask(); + var list = new MAVLink.MAVLinkParamList(); + + // Try and get type so the correct bitmask to value conversion is done + var type = MAVLink.MAV_PARAM_TYPE.INT32; + if (MainV2.comPort.MAV.param.ContainsKey(param_name)) + { + type = MainV2.comPort.MAV.param[param_name].TypeAP; + } + + list.Add(new MAVLink.MAVLinkParam(param_name, double.Parse(MainV2.comPort.MAV.param[param_name].Value.ToString(), CultureInfo.InvariantCulture), + type)); + mcb.setup(param_name, list); + mcb.ValueChanged += (o, x, value) => + { + setParam(param_name, value.ToString()); + setLabelOptions(param_name, label1); + mcb.Focus(); + }; + var frm = mcb.ShowUserControl(); + frm.TopMost = true; + //set the location of the form to center of the screen + frm.Location = new Point((Screen.PrimaryScreen.WorkingArea.Width - frm.Width) / 2, + (Screen.PrimaryScreen.WorkingArea.Height - frm.Height) / 2); + }; + + ThemeManager.ApplyThemeTo(optionsControl); + tableLayoutPanel1.GetControlFromPosition(4, i)?.Dispose(); + tableLayoutPanel1.Controls.Add(optionsControl, 4, i); + } + } + //Add the message to the bottom of the table + noteLabel = new Label() + { + Text = "Note: Changes to the serial port settings will not take effect until the board is rebooted.", + Anchor = AnchorStyles.None, + Dock = DockStyle.Fill, + AutoSize = true, + MaximumSize = new Size(600, 200), + Location = new Point(0, 0), + Size = new Size(100, 20), + TextAlign = ContentAlignment.MiddleLeft + }; + ThemeManager.ApplyThemeTo(noteLabel); + tableLayoutPanel1.GetControlFromPosition(0, serialPorts + 1)?.Dispose(); + tableLayoutPanel1.Controls.Add(noteLabel, 0, serialPorts + 1); + //make the label span the whole row + tableLayoutPanel1.SetColumnSpan(noteLabel, 5); + + tableLayoutPanel1.ResumeLayout(); + + } + + //Apply baud rate and options rules based on protocol + //Rule definition is in SerialOptionRules.json file + private void doApplyRules(string portName, string v) + { + //extract the port number from the port name + int port; + Int32.TryParse(portName.Substring(6), out port); //if unable to parse, then port = 0 + //Check if there is a rule for this protocol + if (_optionRules.ContainsKey(int.Parse(v))) + { + //Apply the rule + var rule = _optionRules[int.Parse(v)]; + if (rule.baudrate > -1) + { + //CMB selected value will set the param via the event handler + ComboBox cmb = tableLayoutPanel1.GetControlFromPosition(1, port) as ComboBox; + cmb.SelectedValue = rule.baudrate; + } + if (rule.options > -1) + { + //set the options + setParam(portName + "_OPTIONS", rule.options.ToString()); + setLabelOptions(portName + "_OPTIONS", tableLayoutPanel1.GetControlFromPosition(3, port) as Label); + } + noteLabel.Text = portName + " : " + rule.comment; + } + else + { + noteLabel.Text = ""; + } + //Check if there are four or more port set to mavlink + //In Ardupilot GCS_Mavlink.cpp : #define MAVLINK_COMM_NUM_BUFFERS 5 + //But this includes the USB port, so we can only have 4 ports set to mavlink + + int mavlinkPorts = 0; + for (int i = 1; i <= 5; i++) + { + string protParamName = "SERIAL" + i.ToString() + "_PROTOCOL"; + if (MainV2.comPort.MAV.param[protParamName].Value.ToString() == "1" + || MainV2.comPort.MAV.param[protParamName].Value.ToString() == "2") + { + mavlinkPorts++; + } + } + if (mavlinkPorts >= 4) + { + noteLabel.Text = noteLabel.Text + "\r\nWarning: Maximum number of Mavlink ports are 5 including the USB port!"; + } + } + + // Widen the drop-down menu if the text is too long + // https://www.codeproject.com/Articles/5801/Adjust-combo-box-drop-down-list-width-to-longest-s + void widenComboBox(ComboBox c) + { + c.DropDown += (s, ev) => + { + ComboBox senderComboBox = (ComboBox)s; + int width = senderComboBox.DropDownWidth; + Graphics g = senderComboBox.CreateGraphics(); + Font font = senderComboBox.Font; + int vertScrollBarWidth = + (senderComboBox.Items.Count > senderComboBox.MaxDropDownItems) + ? SystemInformation.VerticalScrollBarWidth : 0; + + int newWidth; + foreach (KeyValuePair item in ((ComboBox)s).Items) + { + newWidth = (int)g.MeasureString(item.Value, font).Width + + vertScrollBarWidth; + if (width < newWidth) + { + width = newWidth; + } + } + senderComboBox.DropDownWidth = width; + }; + } + + public void setLabelOptions(string param_name, Label l) + { + var binlist = ParameterMetaDataRepository.GetParameterBitMaskInt(param_name, MainV2.comPort.MAV.cs.firmware.ToString()); + var param_value = MainV2.comPort.MAV.param[param_name].Value; + l.Text = string.Join(" / ", binlist.Where(bin => ((uint)param_value & (1 << bin.Key)) > 0).Select(bin => bin.Value)); + } + + public bool setParam(string param_name, string param_value) + { + + double val = 0; + val = double.TryParse(param_value, out val) ? val : 0; + + if (MainV2.comPort.MAV.param.ContainsKey(param_name)) + { + bool ans = MainV2.comPort.setParam((byte)MainV2.comPort.sysidcurrent, (byte)MainV2.comPort.compidcurrent, param_name, val); + if (!ans) + { + CustomMessageBox.Show("Unable to set parameter " + param_name); + return false; + } + else + { + return true; + } + } + else + { + CustomMessageBox.Show("Parameter " + param_name + " not found"); + return false; + } + } + + public void Deactivate() + { + //This needs to be here even when empty + } + } + + //Class to hold the rules for baud rate and options + //The SerialOptionRules.json file is deserialized into a dictionary of this class where the key is the protocol number + public class SerialOptionRuleItem + { + [JsonPropertyAttribute("PresetBaudRate")] + // if -1 , then baud rate is not changed + public int baudrate; + + [JsonPropertyAttribute("PresetOptionsByte")] + // if -1 , then options byte is not changed + public int options; + + [JsonPropertyAttribute("Comment")] + public string comment; + } + +} diff --git a/GCSViews/ConfigurationView/ConfigSerial.resx b/GCSViews/ConfigurationView/ConfigSerial.resx new file mode 100644 index 0000000000..29dcb1b3a3 --- /dev/null +++ b/GCSViews/ConfigurationView/ConfigSerial.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GCSViews/InitialSetup.cs b/GCSViews/InitialSetup.cs index 1b9dda5b93..af446600ae 100644 --- a/GCSViews/InitialSetup.cs +++ b/GCSViews/InitialSetup.cs @@ -173,7 +173,6 @@ private void HardwareConfig_Load(object sender, EventArgs e) AddBackstageViewPage(typeof(ConfigHWCompass), rm.GetString("backstageViewPagecompass.Text"), isConnected && gotAllParams, mand); } - if (MainV2.DisplayConfiguration.displayRadioCalibration) { AddBackstageViewPage(typeof(ConfigRadioInput), rm.GetString("backstageViewPageradio.Text"), isConnected && gotAllParams, mand); @@ -183,6 +182,10 @@ private void HardwareConfig_Load(object sender, EventArgs e) AddBackstageViewPage(typeof(ConfigRadioOutput), "Servo Output", isConnected && gotAllParams, mand); } + if (MainV2.DisplayConfiguration.displaySerialPorts) + { + AddBackstageViewPage(typeof(ConfigSerial), rm.GetString("backstageViewPageSerial.Text"), isConnected && gotAllParams, mand); + } if (MainV2.DisplayConfiguration.displayEscCalibration) { AddBackstageViewPage(typeof(ConfigESCCalibration), "ESC Calibration", isConnected && gotAllParams, mand); diff --git a/GCSViews/InitialSetup.resx b/GCSViews/InitialSetup.resx index cb4d74caa9..ac9e70f68d 100644 --- a/GCSViews/InitialSetup.resx +++ b/GCSViews/InitialSetup.resx @@ -1,951 +1,954 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - Fill - - - - 0, 0 - - - 4, 4, 4, 4 - - - 658, 462 - - - - 1 - - - backstageView - - - MissionPlanner.Controls.BackstageView.BackstageView, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - - $this - - - 29 - - - 34, 246 - - - 100, 23 - - - 0 - - - Accel Calibration - - - Initial Tune Parameter - - - False - - - backstageViewPageaccel - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 0 - - - 34, 223 - - - 100, 23 - - - 1 - - - Airspeed - - - False - - - backstageViewPageairspeed - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 1 - - - 34, 200 - - - 100, 23 - - - 2 - - - Antenna tracker - - - False - - - backstageViewPageAntTrack - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 2 - - - 34, 177 - - - 100, 23 - - - 3 - - - Battery Monitor - - - False - - - backstageViewPagebatmon - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 3 - - - 34, 154 - - - 100, 23 - - - 4 - - - Battery Monitor 2 - - - False - - - backstageViewPageBatt2 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 4 - - - 34, 131 - - - 100, 23 - - - 5 - - - Compass - - - False - - - backstageViewPagecompass - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 5 - - - 34, 108 - - - 100, 23 - - - 6 - - - Compass/Motor Calib - - - False - - - backstageViewPagecompassmot - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 6 - - - 34, 85 - - - 100, 23 - - - 7 - - - ESC Calibration - - - False - - - backstageViewPageESC - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 7 - - - 34, 62 - - - 100, 23 - - - 8 - - - ESP8266 Setup - - - False - - - backstageViewPageESP - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 8 - - - 34, 39 - - - 100, 23 - - - 9 - - - Flight Modes - - - False - - - backstageViewPageflmode - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 9 - - - 34, 269 - - - 100, 23 - - - 10 - - - Frame Type - - - False - - - backstageViewPageframetype - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 10 - - - 34, 292 - - - 100, 23 - - - 11 - - - FailSafe - - - False - - - backstageViewPagefs - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 11 - - - 34, 315 - - - 100, 23 - - - 12 - - - Install Firmware - - - False - - - backstageViewPagefw - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 12 - - - 34, 338 - - - 100, 23 - - - 13 - - - Install Firmware - - - False - - - backstageViewPagefwdisabled - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 13 - - - 34, 361 - - - 100, 23 - - - 14 - - - Camera Gimbal - - - False - - - backstageViewPagegimbal - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 14 - - - 34, 384 - - - 100, 23 - - - 15 - - - Bluetooth Setup - - - False - - - backstageViewPagehwbt - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 15 - - - 34, 407 - - - 100, 23 - - - 16 - - - Install Firmware - - - False - - - backstageViewPageinstfw - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 16 - - - 34, 430 - - - 100, 23 - - - 17 - - - Mandatory Hardware - - - False - - - backstageViewPagemand - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 17 - - - 196, 39 - - - 100, 23 - - - 18 - - - Motor Test - - - False - - - backstageViewPageMotorTest - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 18 - - - 196, 62 - - - 100, 23 - - - 19 - - - Optional Hardware - - - False - - - backstageViewPageopt - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 19 - - - 196, 85 - - - 100, 23 - - - 20 - - - Optical Flow - - - False - - - backstageViewPageoptflow - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 20 - - - 196, 108 - - - 100, 23 - - - 21 - - - OSD - - - False - - - backstageViewPageosd - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 21 - - - 196, 131 - - - 100, 23 - - - 22 - - - Parachute - - - False - - - backstageViewPageParachute - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 22 - - - 196, 154 - - - 100, 23 - - - 23 - - - PX4Flow - - - False - - - backstageViewPagePX4Flow - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 23 - - - 196, 177 - - - 100, 23 - - - 24 - - - Radio Calibration - - - False - - - backstageViewPageradio - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 24 - - - 196, 200 - - - 100, 23 - - - 25 - - - Sik Radio - - - False - - - backstageViewPageSikradio - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 25 - - - 196, 223 - - - 100, 23 - - - 26 - - - Range Finder - - - False - - - backstageViewPagesonar - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 26 - - - 196, 246 - - - 100, 23 - - - 27 - - - Heli Setup - - - False - - - backstageViewPagetradheli - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 27 - - - 196, 269 - - - 100, 23 - - - 28 - - - Wizard - - - False - - - backstageViewPagewizard - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 28 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Fill + + + + 0, 0 + + + 4, 4, 4, 4 + + + 658, 462 + + + + 1 + + + backstageView + + + MissionPlanner.Controls.BackstageView.BackstageView, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + $this + + + 29 + + + 34, 246 + + + 100, 23 + + + 0 + + + Accel Calibration + + + Initial Tune Parameter + + + False + + + backstageViewPageaccel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + 34, 223 + + + 100, 23 + + + 1 + + + Airspeed + + + False + + + backstageViewPageairspeed + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 34, 200 + + + 100, 23 + + + 2 + + + Antenna tracker + + + False + + + backstageViewPageAntTrack + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + 34, 177 + + + 100, 23 + + + 3 + + + Battery Monitor + + + False + + + backstageViewPagebatmon + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 34, 154 + + + 100, 23 + + + 4 + + + Battery Monitor 2 + + + False + + + backstageViewPageBatt2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + 34, 131 + + + 100, 23 + + + 5 + + + Compass + + + False + + + backstageViewPagecompass + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + 34, 108 + + + 100, 23 + + + 6 + + + Compass/Motor Calib + + + False + + + backstageViewPagecompassmot + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + 34, 85 + + + 100, 23 + + + 7 + + + ESC Calibration + + + False + + + backstageViewPageESC + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + + + 34, 62 + + + 100, 23 + + + 8 + + + ESP8266 Setup + + + False + + + backstageViewPageESP + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 8 + + + 34, 39 + + + 100, 23 + + + 9 + + + Flight Modes + + + False + + + backstageViewPageflmode + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 9 + + + 34, 269 + + + 100, 23 + + + 10 + + + Frame Type + + + False + + + backstageViewPageframetype + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 10 + + + 34, 292 + + + 100, 23 + + + 11 + + + FailSafe + + + False + + + backstageViewPagefs + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 11 + + + 34, 315 + + + 100, 23 + + + 12 + + + Install Firmware + + + False + + + backstageViewPagefw + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 12 + + + 34, 338 + + + 100, 23 + + + 13 + + + Install Firmware + + + False + + + backstageViewPagefwdisabled + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 13 + + + 34, 361 + + + 100, 23 + + + 14 + + + Camera Gimbal + + + False + + + backstageViewPagegimbal + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 14 + + + 34, 384 + + + 100, 23 + + + 15 + + + Bluetooth Setup + + + False + + + backstageViewPagehwbt + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 15 + + + 34, 407 + + + 100, 23 + + + 16 + + + Install Firmware + + + False + + + backstageViewPageinstfw + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 16 + + + 34, 430 + + + 100, 23 + + + 17 + + + Mandatory Hardware + + + False + + + backstageViewPagemand + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 17 + + + 196, 39 + + + 100, 23 + + + 18 + + + Motor Test + + + False + + + backstageViewPageMotorTest + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 18 + + + 196, 62 + + + 100, 23 + + + 19 + + + Optional Hardware + + + False + + + backstageViewPageopt + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 19 + + + 196, 85 + + + 100, 23 + + + 20 + + + Optical Flow + + + False + + + backstageViewPageoptflow + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 20 + + + 196, 108 + + + 100, 23 + + + 21 + + + OSD + + + False + + + backstageViewPageosd + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 21 + + + 196, 131 + + + 100, 23 + + + 22 + + + Parachute + + + False + + + backstageViewPageParachute + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 22 + + + 196, 154 + + + 100, 23 + + + 23 + + + PX4Flow + + + False + + + backstageViewPagePX4Flow + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 23 + + + 196, 177 + + + 100, 23 + + + 24 + + + Radio Calibration + + + False + + + backstageViewPageradio + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 24 + + + 196, 200 + + + 100, 23 + + + 25 + + + Sik Radio + + + False + + + backstageViewPageSikradio + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 25 + + + 196, 223 + + + 100, 23 + + + 26 + + + Range Finder + + + False + + + backstageViewPagesonar + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 26 + + + 196, 246 + + + 100, 23 + + + 27 + + + Heli Setup + + + False + + + backstageViewPagetradheli + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 27 + + + 196, 269 + + + 100, 23 + + + 28 + + + Wizard + + + False + + + backstageViewPagewizard + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 28 + - True + True - 226 + 226 - - 658, 462 - - - InitialSetup - - - System.Windows.Forms.MyUserControl, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - + + 658, 462 + + + InitialSetup + + + System.Windows.Forms.MyUserControl, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + Serial Ports + + diff --git a/MissionPlanner.csproj b/MissionPlanner.csproj index 7d4a1a94ab..a33c1dcda6 100644 --- a/MissionPlanner.csproj +++ b/MissionPlanner.csproj @@ -276,6 +276,9 @@ ConfigSecureAP.cs Designer + + ConfigSerial.cs + ConfigSerialInjectGPS.cs @@ -868,6 +871,12 @@ ConfigSecureAP.cs + + UserControl + + + ConfigSerial.cs + ConfigSerialInjectGPS.cs @@ -5189,6 +5198,9 @@ Always + + PreserveNewest + Always diff --git a/SerialOptionRules.json b/SerialOptionRules.json new file mode 100644 index 0000000000..73ae39e81e --- /dev/null +++ b/SerialOptionRules.json @@ -0,0 +1,22 @@ +{ + "1": { + "PresetBaudRate": 115, + "PresetOptionsByte": 0, + "Comment": "If connecting a Mavlink sensor, consider setting 'Do not forward Mavlink to/from'" + }, + "2": { + "PresetBaudRate": -1, + "PresetOptionsByte": 0, + "Comment": "If connecting a Mavlink sensor, consider setting 'Do not forward Mavlink to/from'" + }, + "10": { + "PresetBaudRate": -1, + "PresetOptionsByte": 7, + "Comment": "If not using inverter, remove 'Half Duplex' if not a H7 board remove 'invert Tx/RX' and add 'Pullup' if neccessary" + }, + "23": { + "PresetBaudRate": -1, + "PresetOptionsByte": 7, + "Comment": "If not using inverter, remove 'Half Duplex' if not a H7 board remove 'invert Tx/RX' and add 'Pullup' if neccessary" + } +} \ No newline at end of file