Subversion Repositories Projects

Rev

Rev 2257 | 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.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;

namespace SimpleSerialPort
{
    public partial class SimpleSerialPort : UserControl
    {
        private SerialPort port;

        public event PortOpenedHandler PortOpened;
        public delegate void PortOpenedHandler();
        public event PortClosedHandler PortClosed;
        public delegate void PortClosedHandler();
  //      public delegate void PortOpenedHandler(Stream stream);

        public event DataReceivedHandler DataReceived;
        public delegate void DataReceivedHandler(byte[] buffer);
        public SimpleSerialPort()
        {
            InitializeComponent();

            port = new SerialPort();
            port.ReadTimeout = 10000;
            port.WriteTimeout = 1000;
            textBoxStatus.Text = "closed";
            //textBoxBaudRate.Text = port.BaudRate.ToString();
            textBoxBaudRate.Text = "57600";
            textBoxDataBits.Text = port.DataBits.ToString();
            populateComboBoxes();
            setComboBoxDefaultValues();
          //  PortOpened += SimpleSerialPort_PortOpened;
        }


        public SerialPort Port
        {
            get
            {
                return port;
            }
        }

        public void Connect(bool bConn)
        {
                if (bConn)
                    buttonOpen.Invoke((Action)(()=> buttonOpen_Click(null, null)));
                else
                    buttonClose.Invoke((Action)(() => buttonClose_Click(null, null)));
        }

        private void buttonOpen_Click(object sender, EventArgs 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";
                if (PortOpened != null)
                {
                   // PortOpened(port.BaseStream);
                    PortOpened();
                }
            }
            catch (Exception ex)
            {
                textBoxStatus.Text = "error: " + ex;
            }
        }

        private void buttonClose_Click(object sender, EventArgs e)
        {
            port.DataReceived -= SerialPortDataReceived;
            port.Close();
            PortClosed();
            textBoxStatus.Text = "closed";
            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.Items.AddRange(getPortNameValues());
            comboBoxStopBits.Items.AddRange(getStopBitValues());
            comboBoxParity.Items.AddRange(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, EventArgs e)
        {
            if (!port.IsOpen)
            {
                comboBoxPortName.Items.Clear();
                comboBoxPortName.Items.AddRange(getPortNameValues());
            }
            else
                MessageBox.Show("Port has to be closed!");
        }
    }
}