• Welcome to PiBoSo Official Forum. Please login or sign up.
 
November 21, 2019, 11:23:04 am

Plugin dll complied in c#?

Started by h106frp, November 19, 2014, 10:36:09 pm

Previous topic - Next topic

h106frp

I'm thinking of creating my own plugin to stream data (revs/temp maybe timing data) via USB to a PIC microcontroller. I have source code for the PC end of the USB device but its C# based, does anyone know if GPB will have any issues communicating with this dll?

I just fancy the idea of having an old school tacho/temp gauge (maybe NC30/35) sat in front of my monitor simpit style, more of a novelty really as i like projects involving soldering irons and bits of wire :) The PIC end seems straight forward using PWM to generate a typical real life pulse from the data.

Thanks

HornetMaX

Have a look at this (Proxy plugin).

I don't know C#, but from what I read around (http://www.codeproject.com/Articles/29000/How-to-do-CreateFileMapping-in-a-C-DLL-and-access), it should be possible to call a dll from C# code, so I'd simply compile gpb_proxy.c into a GPB plugin (just  a dll renamed to .dlo ) and then create another C dll that accesses the memory mapped data (as described by Piboso in his post). Your C# app should then "link" to that dll to access the data.

That assuming there's no C# equivalent of Piboso's code to read the memory mapped data (OpenFileMapping and MapViewOfFile): if that exists, you don't need the intermediate C dll.

Or you can always rewrite your C# code into c/c++ :)

MaX.

h106frp

Thanks for the info, had another look and found examples for C++ so this might be a better start point.

h106frp

OK Thanks for the help so far, i have succeeded in linking to the shared memory space, but the example code i can find references SProxyData_t as the data structure and i do not see where this is created in the example dll.

Can you explain the structure of SProxyData_t so that i can declare it in my code?

Thanks

h106frp

Just had a look at the kart racing plugin and some of the fog has lifted :)

HornetMaX

Quote from: h106frp on November 22, 2014, 04:42:20 pm
OK Thanks for the help so far, i have succeeded in linking to the shared memory space, but the example code i can find references SProxyData_t as the data structure and i do not see where this is created in the example dll.

The data is created within GPB (or WRS, KRP, MXB). In your (output) plugin you can only read that data.

MaX.

h106frp

With help from your links i have created and compiled a working dll using codeblocks in c++ and i have a working USB enumerator and data transfer to a pic18f microcontroller applet in visual c++.

I can concentrate on the micro firmware now which is a bit more fun to do.

Thanks for the help so far. :)

h106frp

Hoorah, working rev counter, used an RVF400 unit which threw up a few issues with it using a non standard PWM signal. Water temp next, bit more challenging :) Then limiter lights.....etc

tseklias

do you want to share your setup please? it will be really grateful if your willing to do so. here's what i've found so far about plugins but i've tested nothing so far. http://www.xsimulator.net/community/marketplace/gp-bikes-plugin.53/
Eat Sleep GpBikes -Socrates

h106frp

Took a while to get my head around until i studied HornetMax code for a Kart plugin, so all credit to HornetMax as the author;

You create a new structure within the PiBoso template that bundles all the parameter data together;
HANDLE g_hMapFile;
void *g_pBuffer;

typedef struct
{
   int m_iVersion;
   int m_iState;      /* -1: software not running; 0: software running; 1: on-track, simulation paused; 2: on-track, simulation running */
   SPluginsBikeEvent_t m_sEvent;
   SPluginsBikeSession_t m_sSession;
   SPluginsBikeLap_t m_sLap;
   int m_iSplit;
   SPluginsBikeSplit_t m_sSplit;
   SPluginsBikeData_t m_sData;
   float m_fTime;
   float m_fPos;
} SProxyData_t;

SProxyData_t g_sData;

Then you creat a shared memory area with your own reference (still in the dll template);
   g_hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,sizeof(SProxyData_t),"Local\\GPBProxyObject");
   if (g_hMapFile)
   {
      g_pBuffer = MapViewOfFile(g_hMapFile,FILE_MAP_WRITE,0,0,sizeof(SProxyData_t));
   }

   if (g_pBuffer)
      memcpy(g_pBuffer,&g_sData,sizeof(SProxyData_t));

Now in each function where data is updated we need to update the buffer linked to the shared memory, typically;
__declspec(dllexport) void RunTelemetry(void *_pData,int _iDataSize,float _fTime,float _fPos)
   SPluginsBikeData_t *psBikeData;

   psBikeData = (SPluginsBikeData_t*)_pData;

   g_sData.m_iState = 2;

   memcpy(&g_sData.m_sData,psBikeData,sizeof(SPluginsBikeData_t));

   g_sData.m_fTime = _fTime;
   g_sData.m_fPos = _fPos;

   if (g_pBuffer)
      memcpy(g_pBuffer,&g_sData,sizeof(SProxyData_t));

This is then compile to your dll, i use codeblocks/GNU compiler as its nice and simple. This is renamed .dlo and placed in the plugins folder.

In your client you reverse the process,
Add the same data structure  as in the dll and create it, then open the shared memory access;
         TCHAR szName[]=TEXT("Local\\GPBProxyObject");



         hMapFile = OpenFileMapping(FILE_MAP_READ,FALSE,szName);
                   //FILE_MAP_ALL_ACCESS,   // read/write access
                   //FALSE,                 // do not inherit the name
                   //szName);               // name of mapping object

         if (hMapFile == NULL)
         {
            //Flag no connection
            DLLLinked=0;
            this->GPBObjectlabel->Text = L"Could not open file mapping object";
         //return 1;
         }
         else
         {
            pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
               FILE_MAP_READ,  // read/write permission
               0,
               0,
               sizeof(SProxyData_t));
            
         this->GPBObjectlabel->Text = L"mapped object";
         //Flag active connection
         DLLLinked=1;
         //SProxyData_t *p = (SProxyData_t *) pBuf;
         
         //SProxyData_t data;
         memcpy(&data, pBuf, sizeof(SProxyData_t));

Now you can read the shared memory and copy it to a readable structure, i poll it with a timer
         if (servicingtimer==0)
         {
            servicingtimer=1;
            //Fills pBuf send rpm data
            //Refresh data linked from GPB
            if (DLLLinked)
            {
               pBuf = (LPTSTR) MapViewOfFile(hMapFile,FILE_MAP_READ,0,0,sizeof(SProxyData_t));
            
               this->GPBObjectlabel->Text = L"reading data";
               //Flag active connection
               DLLLinked=1;
               memcpy(&data, pBuf, sizeof(SProxyData_t));
            //   If (data.m_iState==2)
            //   {
               //On track running

               //Send data to HID/PIC
                  this->GPBdlldatalabel->Text = Convert::ToString (data.m_sData.m_fRPM);


Regards,
h106frp

tseklias

so i guess this should be written in a program(like notepad) and then be exported in what format? where do you put the file and how to connect it to the game. more, how you connected the external instruments(via usb?a board helped?). please be more specific if possible cause i would like a lot to be informed or probably build something similar. thanks a lot for all the information you developed and shared with us.
Eat Sleep GpBikes -Socrates

h106frp

December 01, 2014, 08:47:53 am #11 Last Edit: December 01, 2014, 09:04:31 am by h106frp
This is the code that is required to be compiled into machine code using a C compiler of some sort, it can be written in a text editor, but to save a lot of work people usually use an integrated development environment (IDE) the best free ones i have found are codeblocks (opensource) or the free MS visual studio enterprise.

For the microprocessor either PIC or ARM, both can be programmed in C using the relevant developers IDE, i used a PIC development board from http://www.mikroe.com/startusb/pic/ Cheaper than building up from bits and the built in bootloader means you do not need any other programming tools for flashing the microcontroller memory.

Im using the older MPLAB 8.92 for microcontroller, vs c++ 10 for the PC host and codeblocks/GNU for the DLL, all free from their developers.

I used a base class written by http://www.waitingforfriday.com/index.php/Building_a_PIC18F_USB_device this supplies a code template for both the host pc code and the microcontroller. This saved a lot of headaches :)

If you starting from scratch i would load up codeblocks and run through some simple online c++ tutorials to get you started. http://www.codeblocks.org/downloads/26 you want the download with the compiler included otherwise you have to add it later.

When i get everything tidied up and a bit more complete i will post all the stuff i have done if anyone is interested. Planning for rev counter, temp gauge, gear position indication and shift/limiter lights. Will probably add small display via I2C for timing data.

This link might be an easier first project as it does not require a custom host as the HID device does, it just links to the generic windows USB oystick device. Possibly build a handlebar controller with realistic movement ranges..... ......then we will add force feedback later on ;)