Subversion Repositories Projects

Rev

Rev 2287 | Blame | Last modification | View Log | RSS feed

///============================================================================
/// 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!");
        }

    }

}