diff --git a/vJoySerialFeeder/MonitorForm.cs b/vJoySerialFeeder/MonitorForm.cs index 17554b3..8aac616 100644 --- a/vJoySerialFeeder/MonitorForm.cs +++ b/vJoySerialFeeder/MonitorForm.cs @@ -94,6 +94,7 @@ void MonitorFormFormClosing(object sender, FormClosingEventArgs e) { Hide(); e.Cancel = true; + min = max = -1; } } } diff --git a/vJoySerialFeeder/SerialProtocols/IbusReader.cs b/vJoySerialFeeder/SerialProtocols/IbusReader.cs index ead5c92..2f9fb2c 100644 --- a/vJoySerialFeeder/SerialProtocols/IbusReader.cs +++ b/vJoySerialFeeder/SerialProtocols/IbusReader.cs @@ -5,6 +5,7 @@ * Time: 17:47 ч. */ using System; +using System.Collections; using System.IO.Ports; using System.Windows.Forms; @@ -46,12 +47,11 @@ public class IbusReader : SerialReader const int MAX_CHECKSUM_RETRIES = 3; const byte PROTOCOL_IA6_MAGIC = 0x55; const int PROTOCOL_IA6_LENGTH = 31; - const int PROTOCOL_IA6_NUM_CHANNELS = 14; int numDiscards = 0; bool ia6Ibus; - UInt16[] tempIa6Channels; + bool use16bitChannels; public override void Start() { @@ -60,7 +60,6 @@ public override void Start() serialPort.ReadTimeout = 500; if(ia6Ibus) { Buffer.FrameLength = PROTOCOL_IA6_LENGTH; - tempIa6Channels = new UInt16[PROTOCOL_IA6_NUM_CHANNELS]; } else { Buffer.FrameLength = PROTOCOL_MAX_LENGTH; @@ -122,13 +121,17 @@ public int ReadChannelsStandard() data_start++; // skip command byte int ch = 0; int index = data_start; + ushort mask = (ushort)(use16bitChannels ? 0xFFFF : 0x0FFF); while (index + 1 < data_end) - channelData[ch++] = (Buffer[index++] | ((Buffer[index++] & 0x0F) << 8)); - //see https://github.com/betaflight/betaflight/pull/8749 - index = data_start + 1; - while (index + 1 < data_end) { - channelData[ch++] = ((Buffer[index] & 0xF0) >> 4) | (Buffer[index + 2] & 0xF0) | ((Buffer[index + 4] & 0xF0) << 4); - index += 6; + channelData[ch++] = ReadU16(ref index) & mask; + + if(!use16bitChannels) { + //see https://github.com/betaflight/betaflight/pull/8749 + index = data_start + 1; + while (index + 5 < data_end) { + channelData[ch++] = ((Buffer[index] & 0xF0) >> 4) | (Buffer[index + 2] & 0xF0) | ((Buffer[index + 4] & 0xF0) << 4); + index += 6; + } } Buffer.Slide(idx); @@ -178,8 +181,6 @@ public int ReadChannelsIa6() { int idx = 0; // index in the buffer UInt16 chksum = 0; - int tempChIdx = 0; - UInt16 val; // check magic first byte if(Buffer[idx++] != PROTOCOL_IA6_MAGIC) { @@ -188,32 +189,36 @@ public int ReadChannelsIa6() return 0; } - // consume all the data - while(true) { - val = (UInt16)(Buffer[idx++] | (Buffer[idx++] << 8)); - - if(idx >= PROTOCOL_IA6_LENGTH) - break; // val will hold the checksum - - tempIa6Channels[tempChIdx++] = val; - chksum += val; - } - - // check checksum - if(chksum == val) { - // Valid packet - tempIa6Channels.CopyTo(channelData, 0); - Buffer.Slide(idx); - - return tempIa6Channels.Length; + while(idx < PROTOCOL_IA6_LENGTH - 2) { + chksum += ReadU16(ref idx); } - else { + + // last u16 is the checksum + if(chksum != ReadU16(ref idx)) { // incorrect checksum Buffer.Slide(idx); System.Diagnostics.Debug.WriteLine("bad checksum"); + return 0; } + + + int ch = 0; + int index = 1; + ushort mask = (ushort)(use16bitChannels ? 0xFFFF : 0x0FFF); + while (index + 1 < PROTOCOL_IA6_LENGTH - 2) + channelData[ch++] = ReadU16(ref index) & mask; - return 0; + if(!use16bitChannels) { + //see https://github.com/betaflight/betaflight/pull/8749 + index = 2; + while (index + 5 < PROTOCOL_IA6_LENGTH - 2) { + channelData[ch++] = ((Buffer[index] & 0xF0) >> 4) | (Buffer[index + 2] & 0xF0) | ((Buffer[index + 4] & 0xF0) << 4); + index += 6; + } + } + + Buffer.Slide(idx); + return ch; } public override Configuration.SerialParameters GetDefaultSerialParameters() @@ -236,27 +241,49 @@ public override Configuration.SerialParameters GetDefaultSerialParameters() public override string Configure(string config) { parseConfig(config); - using(var d = new IbusSetupForm(ia6Ibus)) { + using(var d = new IbusSetupForm(ia6Ibus, use16bitChannels)) { d.ShowDialog(); if(d.DialogResult == DialogResult.OK) { ia6Ibus = d.Ia6Ibus; + use16bitChannels = d.Use16bitChannels; return buildConfig(); } return null; } } + private ushort ReadU16(ref int index) { + return (ushort)(Buffer[index++] | (Buffer[index++] << 8)); + } + /// /// Ibus configuration - "ia6" string if IA6 ibus should be used + /// "16bit" if 16bit channels are to be used /// /// /// private void parseConfig(string config) { - ia6Ibus = config != null && config.Contains("ia6"); + var tokens = config == null ? + new string[0] + : + config.Split(','); + + foreach(var s in tokens) { + if(s == "ia6") + ia6Ibus = true; + else if(s == "16bit") + use16bitChannels = true; + } } private string buildConfig() { - return ia6Ibus ? "ia6b" : ""; + var cfg = new ArrayList(); + if(ia6Ibus) + cfg.Add("ia6"); + if(use16bitChannels) + cfg.Add("16bit"); + + return string.Join(",", cfg.ToArray()); } } } diff --git a/vJoySerialFeeder/SerialProtocols/IbusSetupForm.Designer.cs b/vJoySerialFeeder/SerialProtocols/IbusSetupForm.Designer.cs index b6a5a13..997ec1a 100644 --- a/vJoySerialFeeder/SerialProtocols/IbusSetupForm.Designer.cs +++ b/vJoySerialFeeder/SerialProtocols/IbusSetupForm.Designer.cs @@ -37,11 +37,12 @@ private void InitializeComponent() this.buttonOK = new System.Windows.Forms.Button(); this.buttonCancel = new System.Windows.Forms.Button(); this.checkIa6Ibus = new System.Windows.Forms.CheckBox(); + this.checkUse16bitChannels = new System.Windows.Forms.CheckBox(); this.SuspendLayout(); // // buttonOK // - this.buttonOK.Location = new System.Drawing.Point(122, 42); + this.buttonOK.Location = new System.Drawing.Point(121, 63); this.buttonOK.Name = "buttonOK"; this.buttonOK.Size = new System.Drawing.Size(75, 23); this.buttonOK.TabIndex = 0; @@ -52,7 +53,7 @@ private void InitializeComponent() // buttonCancel // this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.buttonCancel.Location = new System.Drawing.Point(41, 42); + this.buttonCancel.Location = new System.Drawing.Point(40, 63); this.buttonCancel.Name = "buttonCancel"; this.buttonCancel.Size = new System.Drawing.Size(75, 23); this.buttonCancel.TabIndex = 1; @@ -69,13 +70,23 @@ private void InitializeComponent() this.checkIa6Ibus.Text = "IA6 Compatible IBUS protocol"; this.checkIa6Ibus.UseVisualStyleBackColor = true; // + // checkUse16bitChannels + // + this.checkUse16bitChannels.Location = new System.Drawing.Point(12, 37); + this.checkUse16bitChannels.Name = "checkUse16bitChannels"; + this.checkUse16bitChannels.Size = new System.Drawing.Size(185, 24); + this.checkUse16bitChannels.TabIndex = 3; + this.checkUse16bitChannels.Text = "Use 16-bit channels (Arduino)"; + this.checkUse16bitChannels.UseVisualStyleBackColor = true; + // // IbusSetupForm // this.AcceptButton = this.buttonOK; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.buttonCancel; - this.ClientSize = new System.Drawing.Size(208, 76); + this.ClientSize = new System.Drawing.Size(208, 98); + this.Controls.Add(this.checkUse16bitChannels); this.Controls.Add(this.checkIa6Ibus); this.Controls.Add(this.buttonCancel); this.Controls.Add(this.buttonOK); @@ -87,6 +98,7 @@ private void InitializeComponent() this.Text = "IBUS Setup"; this.ResumeLayout(false); } + private System.Windows.Forms.CheckBox checkUse16bitChannels; private System.Windows.Forms.CheckBox checkIa6Ibus; private System.Windows.Forms.Button buttonCancel; private System.Windows.Forms.Button buttonOK; diff --git a/vJoySerialFeeder/SerialProtocols/IbusSetupForm.cs b/vJoySerialFeeder/SerialProtocols/IbusSetupForm.cs index b9127c6..6be24a1 100644 --- a/vJoySerialFeeder/SerialProtocols/IbusSetupForm.cs +++ b/vJoySerialFeeder/SerialProtocols/IbusSetupForm.cs @@ -18,20 +18,23 @@ namespace vJoySerialFeeder public partial class IbusSetupForm : Form { public bool Ia6Ibus { get; private set; } + public bool Use16bitChannels { get; private set; } - public IbusSetupForm(bool ia6Ibus) + public IbusSetupForm(bool ia6Ibus, bool use16bitChannels) { // // The InitializeComponent() call is required for Windows Forms designer support. // InitializeComponent(); - checkIa6Ibus.Checked = ia6Ibus; + checkIa6Ibus.Checked = ia6Ibus; + checkUse16bitChannels.Checked = use16bitChannels; } void ButtonOKClick(object sender, EventArgs e) { Ia6Ibus = checkIa6Ibus.Checked; + Use16bitChannels = checkUse16bitChannels.Checked; DialogResult = DialogResult.OK; Close(); }