Shop OBEX P1 Docs P2 Docs Learn Events
Need help getting propellent.dll and C sharp working together — Parallax Forums

Need help getting propellent.dll and C sharp working together

turbosupraturbosupra Posts: 1,088
edited 2014-12-22 05:52 in Propeller 1
I'm not sure what changed here, but I used to be able to call the propellent dll inside of c sharp (Visual Studio 2008/Win XP) and query my USB ports and get a response from a port with a version number, among some other serial info.

I tried this today at work and it is not working (Visual Studio 2012/Win 7 64bit). Is there a compatibility issue with 64 bit OS's or something else? I'm going to go home and look for my old app, but I'm not too confident I will find it.

If anyone has a small demo app to query the com ports and get the return value from the prop, that'd be even better.

Thanks :)

Comments

  • turbosupraturbosupra Posts: 1,088
    edited 2014-12-19 16:27
    I found my old code (that I know worked) and it wasn't working with .net 4.0 or above and a 64bit OS (PITA!). The problem is with pininvoke commands required for the propellent dll file and the compiler not suppressing an error that it did in 3.5 and below. More can be found here. http://stackoverflow.com/questions/17602450/calling-a-void-function-in-win32-from-c-sharp-with-parameters

    Anyway, I got it working and the code is a little sloppy, so I want to clean it up first and post it in case anyone else has this question. I don't know how many of you have any interest in .net and c sharp, but maybe this will help someone?
  • turbosupraturbosupra Posts: 1,088
    edited 2014-12-22 05:52
    So the main code is listed below and has been modified for Visual Studio 2012 and c sharp. You have to add the propellent.dll to your project. I'll also attach a zip file of the entire project too, which has the exe in it. This way if you are concerned about running an exe on your machine, you can compile the code yourself. Below also is what the gui looks like. The reset button is not working yet. I'm sure there are more bugs, but that's the only one I know of at the moment.

    The only thing I'd like to get rid of is the propellent dll port search splash screen and the message box window, which I don't know of a way to suppress? Maybe parallax could add a switch in their propellent.dll code to suppress those both or make them generic if you didn't want to advertise your hardware components?


    propeller_Serial1.jpg ___________________________ propeller_Serial2.jpg
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO.Ports;
    using System.Text.RegularExpressions;
    using System.Threading;
    using System.Runtime.InteropServices;
    using Microsoft.Win32;
    
    
    
    namespace SimpleSerial
    {
        public partial class PropellerSerialForm : Form
        {
            // Add this variable 
            string RxString;
    
            [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
            static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
    
            [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
            public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
    
            [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
            public static extern int FindWindow(string strClassName, string strWindowName);
    
            [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
            static extern IntPtr SendMessage(int hWnd, uint Msg, int wParam, int lParam);
    
            [DllImport("Propellent.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern void InitPropellent(IntPtr winHandle, bool storePrefs, string regPath );
    
            public IntPtr Handle { get; set; }
    
            public IntPtr HandleFake = (IntPtr)20;
    
            [DllImport("Propellent.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern IntPtr GetPropellerVersion();
    
            [DllImport("Propellent.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern void ShowEditPorts();
    
            [DllImport("Propellent.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern IntPtr GetPorts();
    
            [DllImport("Propellent.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern IntPtr GetSerialSearchRules();
    
            [DllImport("Propellent.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern void SetGUIMode(int mode);
    
            [DllImport("Propellent.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern void GetResetSignal();
    
            [DllImport("Propellent.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern void SetResetSignal();
    
            [DllImport("Propellent.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern void FinalizePropellent();
    
            
    
    
    
    
            public const int WM_SYSCOMMAND = 0x0112;
            public const int SC_CLOSE = 0xF060;
           // public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
    
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (serialPort1.IsOpen) serialPort1.Close();
                FinalizePropellent();
            }
    
            public PropellerSerialForm()
            {
                InitializeComponent();
                cbxSerialSpeed.Items.Add("115200");
                cbxSerialSpeed.Items.Add("57600");
                cbxSerialSpeed.Items.Add("38400");
                cbxSerialSpeed.Items.Add("28800");
                cbxSerialSpeed.Items.Add("19200");
                cbxSerialSpeed.Items.Add("14400");
                cbxSerialSpeed.Items.Add("9600");
                cbxSerialSpeed.Items.Add("4800");
                cbxSerialSpeed.SelectedIndex = 0;
    
                cbxParityBits.Items.Add("Even");
                cbxParityBits.Items.Add("Mark");
                cbxParityBits.Items.Add("None");
                cbxParityBits.Items.Add("Odd");
                cbxParityBits.Items.Add("Space");
                cbxParityBits.SelectedIndex = 2;
    
                cbxStopBits.Items.Add("None");
                cbxStopBits.Items.Add("1");
                cbxStopBits.Items.Add("1.5");
                cbxStopBits.Items.Add("2");
                cbxStopBits.SelectedIndex = 1;
    
                string[] ports = SerialPort.GetPortNames();
    
                if (ports.Length > 0)
                {
                    foreach (string port in ports)
                    {
                        cbxSerialPort.Items.Add(port);
                    }
                    cbxSerialPort.SelectedIndex = 0;      // problem here when no prop is selected or plugged in
                    InitPropellent(HandleFake, false, "");
                    SetGUIMode(0);
                }
            }
    
            private void buttonStart_Click(object sender, EventArgs e)
            {
                serialPort1.PortName = cbxSerialPort.SelectedItem.ToString();
                serialPort1.BaudRate = Convert.ToInt32(cbxSerialSpeed.SelectedItem.ToString()); 
                serialPort1.DataBits = Convert.ToInt32(tbxDataBits.Text);
                switch (cbxParityBits.SelectedItem.ToString())
                {
                    case "Even":
                        serialPort1.Parity = Parity.Even;
                        break;
                    case "Mark":
                        serialPort1.Parity = Parity.Mark;
                        break;
                    case "None":
                        serialPort1.Parity = Parity.None;
                        break;
                    case "Odd":
                        serialPort1.Parity = Parity.Odd;
                        break;
                    case "Space":
                        serialPort1.Parity = Parity.Space;
                        break;
                    default:
                        break;
                }
    
                switch (cbxStopBits.SelectedItem.ToString())
                {
                    case "None":
                        serialPort1.StopBits = StopBits.None;
                        break;
                    case "1":
                        serialPort1.StopBits = StopBits.One;
                        break;
                    case "1.5":
                        serialPort1.StopBits = StopBits.OnePointFive;
                        break;
                    case "2":
                        serialPort1.StopBits = StopBits.Two;
                        break;
                    
                    default:
                        break;
                } 
    
    
              
                if (serialPort1.IsOpen == false)
                {
                    int i = 0;
                    for (i = 0; i < 11; i++)
                    {
    
                        Thread dBox = new Thread(new ParameterizedThreadStart(displayBox));
                        dBox.Start(i);
                        Thread.Sleep(500);
                        int iHandle = FindWindow(null, "Waiting for serial port...");
                        SendMessage(iHandle, WM_SYSCOMMAND, SC_CLOSE, 0);
                        try
                        {
                            serialPort1.Open();
                        }
                        catch (Exception ex)
                        {
                            
                            
                        }
                        if (serialPort1.IsOpen)
                        {
                            break;
                        }
                    }
                    if (i == 10)
                    {
                        MessageBox.Show("Port cannot be opened");
                        return;
                    }
                }
                else
                {
                    serialPort1.Open();
                }
    
                
                if (serialPort1.IsOpen)
                {
                    btnStart.Enabled = false;
                    btnDetectPort.Enabled = false;
                    btnStop.Enabled = true;
                    tbxSerialData.ReadOnly = false;
                }
            }
    
            private void displayBox(object i)
            {
                
                MessageBox.Show("Waiting for serial port to become available, will try for another " + (10 - (Convert.ToInt32(i))) + " second(s)", "Waiting for serial port...");
            }
            private void findWin()
            {
                MessageBox.Show(FindWindow(null, "Waiting ...").ToString());
                int iHandle = FindWindow(null, "Waiting ...");
                SendMessage(iHandle, WM_SYSCOMMAND, SC_CLOSE, 0);
                Thread.Sleep(1000);
            }
    
            private void buttonStop_Click(object sender, EventArgs e)
            {
                if (serialPort1.IsOpen)
                {
                    serialPort1.Close();
                    btnStart.Enabled = true;
                    btnDetectPort.Enabled = true;
                    btnStop.Enabled = false;
                    tbxSerialData.ReadOnly = true;
                }
    
            }
    
          
            private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
            {
                if (!serialPort1.IsOpen) return;
                byte[] buff = new byte[1];
                buff[0] = (byte)e.KeyChar;
                serialPort1.Write(buff, 0, 1);
    
            
    
                //// If the port is closed, don't try to send a character.
                //if (!serialPort1.IsOpen) return;
    
                //// If the port is Open, declare a char[] array with one element.
                //char[] buff = new char[1];
    
                //// Load element 0 with the key character.
                //buff[0] = e.KeyChar;
    
                
                //// Send the one character buffer.
                //serialPort1.Write(buff, 0, 1);
    
    
                // Set the KeyPress event as handled so the character won't
                // display locally. If you want it to display, omit the next line.
                e.Handled = false;
            }
    
            private void DisplayText(object sender, EventArgs e)
            {
                RxString = Regex.Replace(RxString, @"\r", "\r\n", RegexOptions.None);
                tbxSerialData.AppendText(RxString);
            }
    
            private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
            {
                RxString = serialPort1.ReadExisting();
                this.Invoke(new EventHandler(DisplayText));
            }
    
            private Queue<byte> recievedData = new Queue<byte>();
    
            private void button1_Click(object sender, EventArgs e) // button detect port
            {
                cbxSerialPort.Items.Clear();
                string[] ports = SerialPort.GetPortNames();
                foreach (string port in ports)
                {
                    cbxSerialPort.Items.Add(port);
                    cbxSerialPort.SelectedIndex = 0;
                    serialPort1.PortName = port;
                    serialPort1.BaudRate = 115200;
                    serialPort1.Encoding = Encoding.ASCII;
                    serialPort1.Open();
                    serialPort1.Close();
                }
    
                var versionPtr = GetPropellerVersion();
                string version = Marshal.PtrToStringAnsi(versionPtr);
                int delimiter = version.IndexOf(':');
                if (delimiter > -1)
                {
                    string comPort = version.Remove(delimiter - 1);
                    string firmWare = version.Remove(0, delimiter + 2);
                    tbxPropPortFound.Text = comPort;
                    tbxPropChipVersion.Text = firmWare;
                    int comPortIndex = cbxSerialPort.FindString(comPort);
                    cbxSerialPort.SelectedIndex = comPortIndex;
                }
                 
            }
    
    
            private void button2_Click(object sender, EventArgs e)
            {
                tbxSerialData.Text = "";
            }
    
    
    
            private void serialPortWrite(string lineToWrite)
            {
                
                byte[] b1 = System.Text.Encoding.UTF8.GetBytes(lineToWrite);
                byte[] buff = new byte[b1.Length + 1];
                int i = 0;
                foreach (byte byt in b1)
                {
                    buff[i] = byt;
                    i = i + 1;
                }
                buff[i] = (byte)13;
      
                serialPort1.Write(buff, 0, buff.Length);
            }
    
            private void button4_Click(object sender, EventArgs e) // Test Segment
            {
    
                SetGUIMode(3);
                var versionPtr = GetPropellerVersion();
                string version = Marshal.PtrToStringAnsi(versionPtr);
                SetGUIMode(0);
                MessageBox.Show(version.ToString());
    
               
            }
    
            private void textBox2_TextChanged(object sender, EventArgs e)
            {
    
            }
    
            private void btnCopySerialDataTextBox_Click(object sender, EventArgs e)
            {
                Clipboard.SetText(tbxSerialData.Text); 
            }
    
            private void detectPropPort()
            {
                cbxSerialPort.Items.Clear();
                string[] ports = SerialPort.GetPortNames();
                foreach (string port in ports)
                {
                    cbxSerialPort.Items.Add(port);
                    cbxSerialPort.SelectedIndex = 0;
                    serialPort1.PortName = port;
                    serialPort1.BaudRate = 115200;
                    serialPort1.Encoding = Encoding.ASCII;
                    serialPort1.Open();
                    serialPort1.Close();
                }
    
                var versionPtr = GetPropellerVersion();
                string version = Marshal.PtrToStringAnsi(versionPtr);
                int delimiter = version.IndexOf(':');
                string comPort = version.Remove(delimiter - 1);
                string firmWare = version.Remove(0, delimiter + 2);
                tbxPropPortFound.Text = comPort;
                tbxPropChipVersion.Text = firmWare;
                int comPortIndex = cbxSerialPort.FindString(comPort);
                cbxSerialPort.SelectedIndex = comPortIndex;
            }
    
            private void SimpleSerial_Load(object sender, EventArgs e)
            {
                detectPropPort(); 
            }
    
            private void btnResetProp_Click(object sender, EventArgs e)
            {
                serialPortWrite("0");
            }
    
            private void btnSend_Click(object sender, EventArgs e)
            {
                serialPortWrite(tbxSendData.Text);
                tbxSendData.Text = "";
            }
        }
    }
    
    
Sign In or Register to comment.