///============================================================================
/// This file is part of MIKROKOPTER SERIAL CONTROL TUTORIAL.
/// by JOHN C. MACDONALD at Ira A. Fulton College of Engineering and Technology
/// (http://hdl.lib.byu.edu/1877/2747)
/// (http://hdl.lib.byu.edu/1877/2748)
///============================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.Ports;
namespace MKLiveView
{
public partial class SerialPortCtrl
: UserControl
{
private SerialPort port
;
public event PortOpenedHandler PortOpened
;
public delegate void PortOpenedHandler
();
public event PortClosedHandler PortClosed
;
public delegate void PortClosedHandler
();
public event DataReceivedHandler DataReceived
;
public delegate void DataReceivedHandler
(byte[] buffer
);
public SerialPortCtrl
()
{
InitializeComponent
();
port
= new SerialPort
();
port
.ReadTimeout = 10000;
port
.WriteTimeout = 1000;
textBoxStatus
.Text = "closed";
textBoxBaudRate
.Text = "57600";
textBoxDataBits
.Text = port
.DataBits.ToString();
populateComboBoxes
();
setComboBoxDefaultValues
();
}
public SerialPort Port
{
get
{
return port
;
}
}
public void Connect
(bool bConn
)
{
if (bConn
)
Dispatcher
.Invoke((Action
)(() => buttonOpen_Click
(null,
null)));
else
Dispatcher
.Invoke((Action
)(() => buttonClose_Click
(null,
null)));
}
private void buttonOpen_Click
(object sender, RoutedEventArgs e
)
{
try
{
if (port
.IsOpen == true)
{
port
.DataReceived -= SerialPortDataReceived
;
port
.Close();
}
lastoffset
= 0;
append
= false;
port
.PortName = comboBoxPortName
.Text;
port
.BaudRate = Convert
.ToInt32(textBoxBaudRate
.Text);
port
.DataBits = Convert
.ToInt32(textBoxDataBits
.Text);
port
.StopBits = (StopBits
)Enum.Parse(typeof(StopBits
), comboBoxStopBits
.Text);
port
.Parity = (Parity
)Enum.Parse(typeof(Parity
), comboBoxParity
.Text);
port
.DataReceived += SerialPortDataReceived
;
port
.Open();
textBoxStatus
.Text = "open";
textBoxStatus
.Background = Brushes
.LightGreen;
if (PortOpened
!= null)
{
// PortOpened(port.BaseStream);
PortOpened
();
}
}
catch (Exception ex
)
{
textBoxStatus
.Text = "error: " + ex
;
textBoxStatus
.Background = Brushes
.Coral;
}
}
private void buttonClose_Click
(object sender, RoutedEventArgs e
)
{
port
.DataReceived -= SerialPortDataReceived
;
port
.Close();
if (PortClosed
!= null)
PortClosed
();
textBoxStatus
.Text = "closed";
textBoxStatus
.Background = Brushes
.LightGray;
lastoffset
= 0;
append
= false;
}
public string[] getPortNameValues
()
{
try
{
return SerialPort
.GetPortNames().Reverse().ToArray();
}
catch
{
return new string[0];
}
}
public string[] getStopBitValues
()
{
return Enum.GetNames(typeof(StopBits
));
}
public string[] getParityValues
()
{
return Enum.GetNames(typeof(Parity
));
}
private void populateComboBoxes
()
{
comboBoxPortName
.ItemsSource = getPortNameValues
();
comboBoxStopBits
.ItemsSource = getStopBitValues
();
comboBoxParity
.ItemsSource = getParityValues
();
}
private void setComboBoxDefaultValues
()
{
try { comboBoxPortName
.SelectedIndex = 0; }
catch { }
try { comboBoxStopBits
.SelectedIndex = 1; }
catch { }
try { comboBoxParity
.SelectedIndex = 0; }
catch { }
}
byte[] messageBuffer
= new byte[4096];
int lastoffset
= 0;
bool append
= false;
byte sentinel
= Convert
.ToByte('\r');
object oLock
= 0;
private void SerialPortDataReceived
(object sender, SerialDataReceivedEventArgs e
)
{
System.Threading.Monitor.Enter(oLock
);
int offset
= 0;
try
{
byte[] buffer
= new byte[port
.BytesToRead];
port
.Read(buffer,
0, port
.BytesToRead);
bool bFound
= false;
for (int i
= 0; (i
< buffer
.Length) && port
.IsOpen; i
++)
{
if (buffer
[i
] == sentinel
)
{
if (!append
)
{
byte[] message
= new byte[i
+ 1 - offset
];
if (buffer
[offset
] != '#')
System.Diagnostics.Debug.Print(buffer
[offset
].ToString());
Buffer
.BlockCopy(buffer, offset, message,
0, i
+ 1 - offset
);
if (DataReceived
!= null)
DataReceived
(message
);
}
else
{
Buffer
.BlockCopy(buffer,
0, messageBuffer, lastoffset, i
+ 1);
byte[] message
= new byte[lastoffset
+ i
+ 1];
Buffer
.BlockCopy(messageBuffer,
0, message,
0, message
.Length);
messageBuffer
.Initialize();
append
= false;
lastoffset
= 0;
// System.Diagnostics.Debug.Print(message.Length.ToString());
// System.Diagnostics.Debug.Print(BitConverter.ToString(message));
if (DataReceived
!= null)
DataReceived
(message
);
}
offset
= i
+ 1;
if (buffer
.Length > i
+ 1)
{
//offset = i + 1;
bFound
= false;
}
else
{
// offset = 0;
bFound
= true;
}
}
}
if (!bFound
&& port
.IsOpen)
{
if (!append
)
{
if (buffer
[offset
] != '#')
System.Diagnostics.Debug.Print(buffer
[offset
].ToString("X2"));
Buffer
.BlockCopy(buffer, offset, messageBuffer,
0, buffer
.Length - offset
);
lastoffset
= (buffer
.Length - offset
);
}
else
{
if (messageBuffer
[0] != '#')
System.Diagnostics.Debug.Print(buffer
[0].ToString("X2"));
Buffer
.BlockCopy(buffer, offset, messageBuffer, lastoffset, buffer
.Length - offset
);
lastoffset
+= (buffer
.Length - offset
);
}
append
= true;
}
}
catch (Exception ex
)
{
System.Diagnostics.Debug.Print(ex
.Message);
}
finally
{
System.Threading.Monitor.Exit(oLock
);
}
}
private void btnRefresh_Click
(object sender, RoutedEventArgs e
)
{
if (!port
.IsOpen)
{
// comboBoxPortName.Items.Clear();
comboBoxPortName
.ItemsSource = getPortNameValues
();
}
else
MessageBox
.Show("Port has to be closed!");
}
}
}