Sign in to follow this  
Guest Soccy

C# BCD16 Frequency Com1

Recommended Posts

Hi all,I don't get how to read the "Com1 Active Frequency:1" Simconnect thingie in managed environment (C#). I manage to get some crypted result, but nothing readable. How can I convert the cryptics to a readable com frequency like "118.75"?What I did to get the crypted result:[structLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] struct Comstruct { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public String comthing; public ushort dunno1; public ushort dunno2; public ushort com1; public ushort dunno3; }Also I added the com1 thing via AddToDataDefinition to the pool:simconnect.AddToDataDefinition(DEFINITIONS.Comstruct, "COM ACTIVE FREQUENCY:1", "Frequency BCD16", SIMCONNECT_DATATYPE.INT32, 0.0f, SimConnect.SIMCONNECT_UNUSED);Well, the problem is, the result (Comstruct.com1.ToString()) is cryptic ?!Btw, I also dont understand, why comstruct must consist of 5 variables instead of just 1.Can someone help me?Thanx alot! Any comment welcome!Sincerely,Chris.

Share this post


Link to post
Share on other sites
Help AVSIM continue to serve you!
Please donate today!

Nav frequencies will be returned as BCD16 - marshal as a single unsigned int (uint in C#). Try that instead of your struct.Here's some code in C# if you need to convert the encoded number to non encoded, and vice-versa (original source by Arne Bartels, modified by me for .NET C#): /// /// Converts from binary coded decimal to integer /// /// /// public static uint Bcd2Dec(uint num) { return HornerScheme(num, 0x10, 10); } /// /// Converts from integer to binary coded decimal /// /// /// public static uint Dec2Bcd(uint num) { return HornerScheme(num, 10, 0x10); } static private uint HornerScheme(uint Num, uint Divider, uint Factor) { uint Remainder = 0, Quotient = 0, Result = 0; Remainder = Num % Divider; Quotient = Num / Divider; if (!(Quotient == 0 && Remainder == 0)) Result += HornerScheme(Quotient, Divider, Factor) * Factor + Remainder; return Result; }Hope this helps,Etienne

Share this post


Link to post
Share on other sites

Hello Etienne,thanx alot for your reply.For bad luck, it's not solving at least the 2nd part of my question. If i change my comstruct to this:-----[structLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] struct Comstruct { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public uint com1; }-----I will still get an error. That is why I wonder, why that struct must consist either of a type "string" (thats giving no error) or consist of 5 elements as in my first code snippet shown. System.ArgumentException: Es kann keine sinnvolle Gr

Share this post


Link to post
Share on other sites

Well, I have two suggestions not seeing your particular code. You may want to post it so we can have a look at it to see if anything is odd. I'm in particular interested in the structure you create and the AddToDataDefinition statement you use.I'm assuming that you are getting the proper data back from SimConnect as a SIMCONNECT_RECV_SIMOBJECT_DATA structure. If you're not getting there, the problem is elsewhere.You should be able to use the following definitions when you register your variables and units with AddToDataDefinition():"COM ACTIVE FREQUENCY:1" "Frequency BCD32" // uint 32 bit BCD"COM ACTIVE FREQUENCY:1" "Frequency BCD16" // UInt16 BCDOne trick you can always do is when you get the SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE or SIMCONNECT_RECV_SIMOBJECT_DATA object in your event processing routine, cast the DwData[0] member as an IntPtr (basically, a pointer), and marshal that IntPtr to your struct using:Marshal.PtrToStructure(ptr, t); // ptr = pointer to data as intptr, t = typeof(mystruct)It may also be helpful to create a byte array in your struct (make it large enough, like 256 bytes) and use the debugger to manually see what bytes you get back. That's what I use when I get garbage back and the documentation doesn't quite help.Hope this helps,Etienne

Share this post


Link to post
Share on other sites

Hi again,thank you once more.It doesn't help me too much so far, since i cannot define a byte array in my struct. Something like "public byte[] testbyte = new byte[256];" won't work in a struct.So far, I can give you my struct and my AddToDataDefinition, so that you can see, what I do:[structLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] struct Comstruct { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public int com1; }Then my AddToDataDefinition:simconnect.AddToDataDefinition(DEFINITIONS.Comstruct, "COM ACTIVE FREQUENCY:1", "Frequency BCD16", SIMCONNECT_DATATYPE.INT32, 0.0f, SimConnect.SIMCONNECT_UNUSED);Then my Cast:case DATA_REQUESTS.REQUEST_COM: s7 = (Comstruct)data.dwData[0]; uint comfreq1 = Bcd2Dec((uint)s7.com1);break;Your idea about the byte sounds very interesting, also the marshaling in the receive event. So far, I don't know exactly how to do that marshaling stuff. Could you make it more concrete (like your code to handle this)?Thank you very much, really appreciate your expertise!Sincerely,Chris.

Share this post


Link to post
Share on other sites

Hi again,Im proud to announce, that I solved the problem. It was simple, once you know it: The marshalling as [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] caused the problem. Taking it out solved the error.So far, Im still interested in that events-marshalling and the byte-find-the-garbage solution!Thanx,Chris.

Share this post


Link to post
Share on other sites

Glad you solved the problem. Relating to your question on handling byte arrays, there are two methods.The first looks something like this:struct TEST{[MarshalAs(UnmanagedType.ByValArray, SizeConst=array_size)]byte[] myArray;}This only works if you know the size of the array at compile time, because the size is hard coded via the attribute. The default MarshalAs attribute in 2.0 or 3.0 doesn't yet know how to handle variable arrays (read, convert variable size at runtime). The only exception: strings, if you consider them arrays of characters. Hopefully, this will be corrected in future versions.When you don't know the size of the array, the second method has you marshal the same array member as an IntPtr instead of an array. The IntPtr really stores the pointer to the data when marshaling is completed. Then, you manually do the conversion to your array as follows:struct TEST{ IntPtr ptrToMyData;}...Byte[] myArray = new Byte[array_size]; // this can vary at runtimeMarshal.Copy(ptrToMyData, myArray , 0, array_size); // fills the variable size arrayWhen SimConnects gets the data from the unmanaged side, you will end up with a pointer to the first element of the array in ptrToMyData. Once this is done, you can use the Copy() or PtrToStruct() of the Marshal class to convert between data structures.This is also a convenient way to duplicate the functionality of unions in C or C++ that do not exist in C#. PtrToStruct will let you map the same IntPtr to different structs, for interesting effects.I know this is low level stuff, but it does wonders with data coming back from FSX...There are other ways as well using field offsets and the unsafe keyword, but the above should get you well underway with pesky conversions problems.Cheers,Etienne

Share this post


Link to post
Share on other sites

>Hi again,>>Im proud to announce, that I solved the problem. It was>simple, once you know it: The marshalling as>[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] caused>the problem. Taking it out solved the error.>>So far, Im still interested in that events-marshalling and the>byte-find-the-garbage solution!>>Thanx,>Chris.I read this and I can't believe I missed it.That line was basically overriding the custom marshaller built into the managed SimConnect library to tell it to receive the integer as string data.

Share this post


Link to post
Share on other sites

Thanx alot, specially Etienne! You helped me much, the bcdtodec code was a big hint also!Thank ya :)Chris.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this