13

I have an application which connects with an external protocol using serial communication.

I need know if the wakeup bit is set on each packet it sends to me (the 9 bit), and as communication rates must be below 40ms, and response must be sent under 20 ms. The framework, encapsulates the bits read from the port, and only send back the 8 bits of data to me. Also, I cannot wait for the parity error event, because of timing issues.

I need to know how can I read the 9 bit, or if there is a free alternative to http://www.wcscnet.com/CdrvLBro.htm

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
miguel.hpsgaming
  • 461
  • 8
  • 17
  • 1
    This is not possible to reliably implement with standard serial port hardware, drivers and operating systems. You cannot reliably sync the extra bit with the data byte and there's no way to get guaranteed 20 msec responses in Windows user mode. Schemes like these are invented to tie the user into proprietary and expensive vendor solutions. Buy it or ditch it. – Hans Passant Nov 27 '11 at 22:20
  • I'm already below that times. I just need to know if the 9 bit is set, as based on this my response should change. I will post more examples of libraries that claim to do this on .net, as the one I posted to the free alternative im looking. – miguel.hpsgaming Nov 28 '11 at 12:39

1 Answers1

8

Did you try to put your serial read function right in the parity error event handler? Depending on the driver, this might be fast enough.

This wouldn't happen to be for a certain slot machine protocol, would it? I did this for fun for you. Maybe it will work?

{
    public Form1()
    {
        InitializeComponent();
    }

    SerialPort sp;
    private void Form1_Load(object sender, EventArgs e)
    {
        sp = new SerialPort("COM1", 19200, Parity.Space, 8, StopBits.One);
        sp.ParityReplace = 0;
        sp.ErrorReceived += new SerialErrorReceivedEventHandler(sp_SerialErrorReceivedEventHandler);          
        sp.ReadTimeout = 5;
        sp.ReadBufferSize = 256;
        sp.Open();
    }

    object msgsLock = new object();
    Queue<byte[]> msgs = new Queue<byte[]>();
    public void sp_SerialErrorReceivedEventHandler(Object sender, SerialErrorReceivedEventArgs e)
    {
        if (e.EventType == SerialError.RXParity)
        {
           byte[] buffer = new byte[256];            
           try
           {                   
               int cnt = sp.Read(buffer, 0, 256);
               byte[] msg = new byte[cnt];
               Array.Copy(buffer, msg, cnt);
               if (cnt > 0)
               {
                   lock (msgsLock)
                   {
                       msgs.Enqueue(msg);
                   }
               }
           }
           catch
           {
           }              
        }
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (msgs.Count > 0)
        {
            lock (msgsLock)
            {
                listBox1.Items.Insert(0, BitConverter.ToString(msgs.Dequeue()));
            }
        }
    }
}

}

Anyways, for more control over the serial port I suggest using the win32 calls to get what you want.

http://msdn.microsoft.com/en-us/magazine/cc301786.aspx

rare
  • 134
  • 4
  • I have already tried that, but I may have parsed several packets before I have the error event, thats why Im asking for another workaround. Timing is critical here. – miguel.hpsgaming Nov 27 '11 at 21:56
  • May I ask what serial hardware device you are using? USB to serial, built in COM port, etc? – rare Nov 27 '11 at 22:53
  • I'm using both of them, and can change the serial hardware device to the one I found a solution to be a system requirement if needed. – miguel.hpsgaming Nov 28 '11 at 12:35
  • OK, this may be realted or not, but something you should be aware of either way. Most USB to serial devices do not work properly as far as fast timings are concerned. Built in COM ports do usually work, however. – rare Nov 28 '11 at 17:50
  • 1
    More: Some of the USB devices have advanced settings for timings which will intentionally introduce delays of 100ms or more, or buffer sizes that can be set to a min. of only 64 bytes. There's not much you can do for these to get them to work. They just won't raise events properly. USB's may have a latency setting which you have to set as low as possible (1ms, etc..) Built in COM ports usually do work, however. What I had to do is change the 'Receive Buffer' size to be as small as possible for built in devices to get the event to raise. Ethernet to serial devices don't ever work. – rare Nov 28 '11 at 18:01