1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Does anyone here know a little C#

Discussion in 'Computers and Networks' started by Ian Rogers, Mar 3, 2014.

  1. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK
    This is whats doing my nut in... In another HID example they use ReadFile slightly differently.. I can set the Write function to data.length -1 but the flush fails... I will try your changes and get back to you
     
  2. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK
    Okay.... Making the buffer 65 bytes then calling FileStream.Write() works.... Then Flush() fails... If I comment out Flush() the the next FileStream.Read() fails with a slightly different exception..

    "The supplied user buffer is not valid for the requested operation."

    I wish I had learned .Net a while since.... Ive been neglecting my brain updates...
     
  3. NorthGuy

    NorthGuy Well-Known Member

    Joined:
    Sep 8, 2013
    Messages:
    1,218
    Likes:
    206
    Location:
    Northern Canada
    When reading you need to do the same thing - 65 bytes and first byte of the buffer set to zero. Zero is needed because it is ReportId. If you had multiple reports, you could read them by putting their Ids as a first byte, but since you don't have report Ids you need to set the first byte to zero before reading.

    I don't think you need Flush, because it's nothing to flush. These are blocking operations. They won't return until the device responds.
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK

    The plot thickens.... Or not!!

    I have run the original project "As is" in Visual studio 2013 using .NET 4..

    The project failed at exactly the same place.. If I change the filestream Buffer to 65 ( the report buffer is 64 )
    AND!!!! change the report buffer to 65.... Viola!!! I know it works because a little LED on the pic board flashes..

    This interface is too temperamental for my liking...

    Cheers NorthGuy I was going to chuck the monitor through the window...

    I was assuming that the filestream write was working.... But because it returned NULL there was no buffer to flush!!!

    All done.... Now I have to get the feature transfer done!!
     
  6. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK
    Ahhhh! I get it!!! I have 64 bytes to play with..... 65 gets transferred but the first is reserved! So My first byte is report[1]... and my last is report[64]...
     
  7. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK
    Okay! Re-typed into visual studio 2008... Success!!

    Now I am faced with a C programmers nightmare!!.... In C a byte array is basically a string!! in C# they are worlds apart!!

    In C

    char str[] = {"Hello World!!");

    printf("%s",str);

    In C#

    byte[] whatever = new byte[65];

    /*fill array via report...*/

    whatever.ToString(); <---- Apparently not!!!!
     
  8. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,677
    Likes:
    215
    Location:
    Brisbane, Australia
    What are you trying to do? If you want to convert a byte array to an ASCII string, just use
    Code (text):
    byte[] bytes = new byte[100];  // get some dummy data of 100 zeros
    string mystring = Encoding.ASCII.GetString(bytes);
     
  9. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK
    Sorry ! I should have posted...

    I used this...

    Console.WriteLine(Encoding.Default.GetString(report));

    Now its a string I can get on with parsing.... Basically I have a datalogger with a single text file!! I have it running on an SD on Fat32.... Now via HID I want to transfer the text file to the PC... each line of the text file will have the same sized format of 25 bytes... So I'm going to send two lines each transfer.... I believe Split() is the function to retrieve each line after its converted t a string...

    I also want to have time / date change facility, but this is secondary as the datalogger has a graphical touch screen and you can modify any parameter in situ!!!

    Things are going better now... I've converted to a Form application so I can make it user friendly..

    I have found a website that will let you use a VID and a PID for free as long as you keep to 3~5 rules

    https://github.com/obdev/v-usb/blob/master/usbdrv/USB-IDs-for-free.txt

    It will make it more professional than the basic VID of 1234.... and PID of 0001
     
  10. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK
    Right! This isn't really C# related but more on the USB side...

    I have my C# application running... It recognizes and talks to my device... Now I instigate a read... This will be a multiple read as fast as I can muster.... Can I just send report after report or do I have to receive at the same time????

    Basically I'm supposed to poll the USB periodically, but a multiple read would be faster without the polling, bu I may loose synchronization.... If the PC is reading and the pic is writing I'll need some sort of handshake... But sending a report just to say "Got it, send the next" will add to the transfer time...
     
  11. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,677
    Likes:
    215
    Location:
    Brisbane, Australia
    Can you use a thread that keeps trying to read from the USB device, so that you are unlikely to miss anything?

    If you can receive duplicate reports from your read() function, you could put a counter byte at the start of the report so that you can detect duplicates. If you still want a handshaking mechanism, then you could do acknowledgement of multiple reports in a single write (use the counter byte of the received reports as the ID). This way you could send an acknowledgement message every 60 reports or so...
     
  12. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK
    Not clever enough for cross threading... I have achieved it but never really understood the invoke method.. I believe its similar to function pointers or friend functions in C++..

    Until I'm up to speed I'll try and get this working within the scope of a single form...

    I'll first try to multiple read with the first usable byte as a counter!!! If that is a problem I'll use a report echo.. It'll be slower but at least it will work..

    In C we can manipulate a byte array using a pointer... ie

    char report[65];
    char * arrayptr = &report[1];

    so I could loose the report ID byte...

    How is this done in C# other than a loop ???
     
  13. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,677
    Likes:
    215
    Location:
    Brisbane, Australia
    It's probably easier than in C++. Here's an example; just paste into a new windows forms application
    Code (text):

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.IO;
    using System.Threading;

    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            bool abortThread = false;
            Thread myThread;
            int cnt = 0;
            void myThreadFunc()
            {
                while(!abortThread && !this.IsDisposed)
                {
                    byte[] bytes = new byte[10];// File.ReadAllBytes("example.usb.txt");        // read in report (apparently this is a blocking call)
                    Thread.Sleep(300);
                    bytes[1] = (byte)cnt++;
                    if(!this.IsDisposed)
                        this.BeginInvoke(new Action<byte[]>(reportReceived), bytes);
                }
            }

            void reportReceived(byte[] report)      // this is run in the form thread, so you can access the controls in here if you wanted
            {
                Text = report[1].ToString();
            }

            public Form1()
            {
                InitializeComponent();

                // start the thread
                myThread = new Thread(myThreadFunc);
                myThread.Start();
            }
        }
    }
    It will just display a number counting from 0 to 255 in the form title text. Obviously for your use, you would read in the data from the usb device, and wouldn't sleep for 300ms (that's just for a demo).

    Just use an index.
    Code (text):
    int reportCnt = report[1];
    If you want to iterate through all bytes, you can use the normal indexed C++ version
    Code (text):
    for(int i = 0; i < report.Length; i++)
        doSomething(report[i]);
    Or use an enumerable
    Code (text):
    foreach(byte b in report)
       doSomething(b);
     
    Last edited: Feb 15, 2015

Share This Page