Main Site Documentation

CDC to serial port bridge - windows forms to fez domino wrap around test - please help


#1

Hello Forum,

I am hoping one of you kind folks can help me out with with a CDC to serial port bridge issue.

I have a windows forms application with 6 trackbars that emulate an audio mixer.
When the trackbar/slider is moved, the trackbar id and trackbar position (0 to 63) is sent to my Fez Domino. For now, I just want the Domino to echo the trackbar id and position back to my Windows application. (ie: a wrap-around test to validate what I am sending is being received).

If I move a trackbar very slowly (1 step/second),the trackbar position and id is echo’d back correctly. If I move the trackbar a little faster, the data retreived starts to lag behind the data sent.

For example, if I send 1,2,3,4,5 if get back 1,2,3.
If I move the trackbar one more step to 6, I get back 4.

Given the CDC bridge runs at 12M, I figure I do not have a timing or latency issue.
I suspect I am doing something stupid, but after hours of looking, I can not find it.
I am hoping one of you kind folks can help me out. I provided pigeon code below demonstrating my approach.

Thanks much for your help,
Larry Scott,
Walnut Creek, CA

==============================================
== CSHARP WINDOWS ‘FORMS’ APPLICATION

// When trackbar is moved, this method is invoked.
// I can see here the command being written to the listbox and serial port.

 private void trackBarS1A_Scroll(object sender, EventArgs e)
    { 
        Control control = (Control) sender; 
        String name = control.Name;
        String nm = "";

        int position = 0;
        if (name.Equals("trackBarS1A")) { position = trackBarS1A.Value; nm="P1A"; } else
        if (name.Equals("trackBarS1B")) { position = trackBarS1B.Value; nm="P1B"; } else
        if (name.Equals("trackBarS2A")) { position = trackBarS2A.Value; nm="P2A"; } else
        if (name.Equals("trackBarS2B")) { position = trackBarS2B.Value; nm="P2B"; } else
        if (name.Equals("trackBarS3A")) { position = trackBarS3A.Value; nm="P3A"; } else
        if (name.Equals("trackBarS3B")) { position = trackBarS3B.Value; nm="P3B"; } else
        if (name.Equals("trackBarS4A")) { position = trackBarS4A.Value; nm="P4A"; } else
        if (name.Equals("trackBarS4B")) { position = trackBarS4B.Value; nm="P4B"; }

        listBox1.Items.Add(name + ": " + position);
        if (!(serialPort == null))
        {
                String cmd = nm + "~" + position;
                listBox1.Items.Add("Send: " + cmd);
                serialPort.Write(cmd + "\n");                    
         }
     }

==============================================
== FEZ DOMINO CODE

  public static void Main()
    {
    boolean usbFound = false; 
    if (Configuration.DebugInterface.GetCurrent() == Configuration.DebugInterface.Port.USB1) usbFound = true;
    if (usbFound) cdc = USBClientController.StandardDevices.StartCDC_WithDebugging(); 

    while (true)
      {
      String rcvd = ReadString(cdc);
      if (rcvd.Length > 0) cdcWrite(rcvd + "\n");
      } 
     } // main

    ---------------------

    #region cdcread
    public static string ReadString(USBC_CDC cdc)
    {
        String s = "";
        while (true)
        {
            byte[] CDCBuffer = new byte[256];
            int USBread = cdc.Read(CDCBuffer, 0, 256);
            if (USBread <= 0) return s;
            else
              for (int i = 0; i < USBread; i++) 
                s += ((char)CDCBuffer[i]).ToString();
        }
    }
    #endregion


    ---------------------

    #region cdcwrite
    static void cdcWrite(String s)
    {
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s);
        cdc.Write(bytes, 0, bytes.Length);
    }
    #endregion

#2

Funny, we’ve just had a string discussion today on serial ports.

You read your data into a byte array. Don’t put it in a string (if you have ever done a DEBUG and done a step-into on a ToString() operation you’d know how many steps that takes!). Then just pump it back out. Your data is reasonably well structured, so you should be fine manually parsing it, right? :slight_smile:


#3

Hi Brett,

Thanks very much for your help!
Your suggestion to not convert the byte data to string data helped, but the problem persists.

Here is the revised domino code to echo data back to my windows app.
Also, attached is a picture that shows data that was sent and received (echo’d).
Notice I send 10 write commands, but only receive 4 back.
I do not think I am over-taxing the domino of cdc drive.
Please let me know your thoughts.

Thanks very much for your help!
Larry Scott

        // Fez Domino code to echo data received over CDC interface
        byte[] CDCBuffer = new byte[256];
        byte[] crlf = new byte[2];
        crlf[0] = 0x0A;
        crlf[1] = 0x0D;

        while (true)
        {
            int USBread = cdc.Read(CDCBuffer, 0, 256);
            if (USBread > 256) blinkLed(10);   // overflow warning
            if (USBread > 0)
            {
                cdc.Write(CDCBuffer, 0, USBread);
                cdc.Write(crlf, 0, 2);
            }

#4

OK, so tell us what you can see from Domino end; does it send the data, drop the data, never read the data, or what?

You might note that your “blink LED” will never occur; the return when you ask it to read a maximum of 256 bytes will never be greater than 256 bytes.

Over-taxing. Well you’re possibly right, possibly wrong. Serial transfer of text is not fast. It’s simple, but not fast. I don’t think you can determine what is and isn’t fast at this point, so lets keep optimising first. In what length of time do you send your sample data?

If you have a full working Windows and Domino app it might be worth posting; it would allow someone else to try it and see (ie I have a Domino).


#5

Using code tags will make your post more readable. This can be done in two ways:[ol]
Click the “101010” icon and paste your code between the

 tags or...
Select the code within your post and click the "101010" icon.[/ol]
(Generated by QuickReply)

#6

Hi Brett,

Thanks for all your good points.

As you suggested, I replaced all string io with byte io to minimize the serial io.
The problem still persists. It appears not all serial data is making it to the Fez mini.

I attached a zip file with two sample projects.
(I could not find where to upload code attachments so I renamed sample.zip to sample.jpg… please rename sample.jpg to sample.zip and extract code).

Attached code:
1: A windows app, visual studio 2010, C#.
As the trackbar is moved, serial data (4 bytes per tick) is sent to the Fez mini.
2: A Fez Mini app that receives CDC serial IO and echo’s it back to Windows.

If you run these programs, you will see that not all data sent to the fez mini is echo’d back to windows. My theory is that not all data sent is reaching the Fez Mini.

Thanks for discussing the issue. If nothing else, it has forced me to slow down and think more clearly about my issue. Hopefully I am not doing something stupid…

Larry Scott
Walnut Creek, CA


#7

Sorry, file wasn’t included… email me brett_pound at hotmail


#8

Hi Brett,
sorry for the long winded message…

I needed to step away from this problem for a week to clear my head…
Please recall, I have a PC host application that displays a slider/trrackbar. As the trackbar is moved, the tackbar id and position are sent to the FEZ Panda2 over the CDC interface. The FEZ Panda2’s only job is to receive the data and send it back to the PC host. (ie: a wrap around test).

Here is what I discovered.
As I slowly slide the trackbar, the trackbar’s id and position is sent to the FEZ Panda 2 and sent back to the PC Host correctly. If I speed up movement of the trackbar/slider, all trackbar info is sent to the FEZ Panda 2 and the FEZ Panda is correctly wrapping the data back to the PC host. The problem is the PC Host sp_DataReceived interrupt handler. It is not firing. Consequently, the wrapped data is just left hanging in the CDC endpoint buffer / pipeline.

At this point, if I manually send a CR&LF from the PC host to the FEZ Panda 2 (to pump the pipeline), the PC host sp_DataReceived interrupt fires and I receive the next (lost) packet. If I continue to pump/send CR&LF to the FEZ Panda, I eventually receive all of the lost packets

Lastly, I can ‘flush’ the received buffer, and get every packet that was lost, but this is only a band-aid fix.

My PC host serial port is setup like this:
serialPort = new SerialPort(“COM4”, 19200, Parity.None, 8, StopBits.One);
serialPort.Handshake = Handshake.None;
serialPort.DataReceived += new
SerialDataReceivedEventHandler(sp_DataReceived);
serialPort.ReadTimeout = 500;
serialPort.WriteTimeout = 500;
serialPort.Open();

Here is my theory and question.
I suspect that I am trying to operate the serial port faster than the maximum ‘managed application’ speed for the device. Do you think I might achieve better performance if I write RLP SPI driver ? Do you have any suggestions how I might improve comminucation between my PC host and FEZ Panda 2 (either using or not using the CDC driver) ? Any code samples you have would be appreciated.

If you still want to see my project code/demo, I will send it.
Thanks again for your help.
Larry Scott
Walnut Creek, CA


#9

DataReceived handlers are based on reading the full data available to you and getting out of dodge and letting the rest of the app continue. Personally, I would go away from using a handler and use polling in a thread.

If you wanted to continue using this approach though, post your handler code (from both ends)… I actually think you are possibly doing something wrong on the PC side, so it’d be a worthwhile thing to post.