Jump to content
Sign in to follow this  
badderjet

"Binary Coded Decimal"?

Recommended Posts

Guest zbobg

I really really like the execute_calculator_code method, but if you're doing a digital LCD or 'rolling tape' kind of gauge you'll still have to extract the digits. You might as well extract the digits directly if you have to extract them at all.Oddly, I've used a similar method to get the digits for a tape gauge using an sprintf to a string variable then extracting the strings's characters to get the individual digits. Sometimes an sprintf conversion saves some work.

Share this post


Link to post
Share on other sites

>Oddly, I've used a similar method to get the digits for a tape>gauge using an sprintf to a string variable then extracting>the strings's characters to get the individual digits.>Sometimes an sprintf conversion saves some work.Well, that's actually the beauty of using sprintf to a char[x] variable. You can 'extract' any digit by using the [index] number... ;)char cString[10] = ""; sprintf(cString, "%07.2f", adf1_frequency); // since the character "0" is ascii code 48, // then subtracting 48 from the character code of // the desired character gives us the numeric equivalent. adf1_freq_high_carry = cString[2] - 48;


Fr. Bill    

AOPA Member: 07141481 AARP Member: 3209010556


     Avsim Board of Directors | Avsim Forums Moderator

Share this post


Link to post
Share on other sites
Guest JeanLuc_

I've also made the switch to XML execute in most of the new gauges now, for convenience, and somewhat in prevision of FS11 changes (I suspect the data driven model will remain, while the token approach might change more).In order to help, I've also create a set of classes for this. Makes life easier and optimizes XML further in using pre-compiled code:class _xml_var_execute{public: _xml_var_execute() : _source_code(0), _precomp(false) {} ~_xml_var_execute() {if (_precomp && _source_code) {delete [] _source_code; _source_code = 0; _precomp = false;}} void Init(char* source_code, bool precomp =true) { if (!_source_code && source_code) { _source_code = source_code; if (precomp) { PCSTRINGZ pszCode; UINT32 uSize; if (gauge_calculator_code_precompile (&pszCode, &uSize, source_code)) { _source_code = new char[uSize]; memcpy(_source_code, pszCode, uSize); _precomp = true; } } } };protected: char* _source_code; bool _precomp;};class xml_var_dbl : public _xml_var_execute{public: xml_var_dbl(){};public: xml_var_dbl(char* source_code, bool precomp =true) {Init(source_code, precomp);}public: FLOAT64 Lookup() {FLOAT64 var; execute_calculator_code(_source_code,&var,0,0); return var;}};class xml_var_int : public _xml_var_execute{public: xml_var_int(){};public: xml_var_int(char* source_code, bool precomp =true) {Init(source_code, precomp);}public: SINT32 Lookup() {SINT32 var; execute_calculator_code(_source_code,0,&var,0); return var;}};You use these classes like this typically:create your variable:xml_var_dbl xvar_ADF_FREQ;init the variable, handy since you can do it at run time (when gauge load for example, to init on ADF1 or ADF2 like this) if (radio == AdfRadio2) { xvar_ADF_FREQ.Init ("(A:ADF ACTIVE FREQUENCY:2,KHz)"); xvar_ADF_SIGNAL.Init("(A:ADF SIGNAL:2,Number)"); xvar_ADF_RADIAL.Init("(A:ADF RADIAL:2,Degrees)"); } else { xvar_ADF_FREQ.Init ("(A:ADF ACTIVE FREQUENCY:1,KHz)"); xvar_ADF_SIGNAL.Init("(A:ADF SIGNAL:1,Number)"); xvar_ADF_RADIAL.Init("(A:ADF RADIAL:1,Degrees)"); }and then use it:radial = (float) xvar_ADF_RADIAL.Lookup();Hope this helps!(feel free to add this in your Wiki if you think it can help others)

Share this post


Link to post
Share on other sites

Thanks, Jean-Luc! As soon as I digest it myself and can understand how its used, I'll do just that.I'm assuming that another public class would be needed for retrieving string values, since you've only mentioned double and int in your example.


Fr. Bill    

AOPA Member: 07141481 AARP Member: 3209010556


     Avsim Board of Directors | Avsim Forums Moderator

Share this post


Link to post
Share on other sites

Hi Jean-Luc,I'm trying to learn as much C++ as I can these days, so the code you posted seems an interesting example for my proposals.However, after digging a bit, I must say I don't quite understand the advantage of defining a class to handle xml vars' data considering that:-execute_calculator_code is a function that retrieves values from properties ("variables") already defined and instantiated within Panel/aircraft classes.- you can handle any kind of operations with regular C++ variables and functions through this own function in a very simple way.-going through another instantiation of another class should have some cost in performance ?I'm probably missing something :-)Tom

Share this post


Link to post
Share on other sites

The primary purpose of his class is encapsulation.The performance hit should be minimal, unless he writes bad code. ;)The irony is object oriented design isn't primarily for encapsulation, but for reusability and expandability. Something you can't do with hard-coded function calls. Not J-L's fault... FS's fault.


Ed Wilson

Mindstar Aviation
My Playland - I69

Share this post


Link to post
Share on other sites
Guest JeanLuc_

Hi,First, it can be used (with precomp=false) as a dynamic "handler" to retrieving any XML var. If can come handy like in the example to have an "xml_adf_freq" var, and init it to either ADF1 or ADF2 in the loop. Then the code just uses xml_adf_freq.Lookup(), whatever it looks up for. Just one use of a class, can be one simpler in C.Now if you look closely, the Init can pre-compile your XML code and store it (default). Since this requires having FS first compile, then copy the compiled code someplace, it is easier and versatile to just new [] the buffer needed, which the class does. In that case, the destructor is handy for cleanup. You can fire and forget. (I new in my class, because I also have a very efficient memory allocator which supercedes C++ new/delete - you can store it anyplace you want). In that case, you init once, and reuse many.The is not a performance hit more than calling exec_calc_code directly and in fact it is faster with precompiled code (default behavior). In the end, it will be executed with the same SDK API. The only drawback is a couple bytes more allocated someplace (either on the heap if you new xml_var_dbl types for example), or in the .data section of the dll. Not much overhead and more convenient to me, but there could be other ways to do as well that can proove being better.As for string, I have not needed to implement them (no use yet on my projects) so they are missing for this reason, and you are right, this should be easy to add a class.In fact, I wanted to have a single class (and not use RTTI of any sort), but function overloading does not work with return type, just with argument types. So if anyone is C++ expert to have a single xml_var class that can return INT or DOUBLE based on on the arguments for example and with the generic lookup() function call, he is more than welcome (and without RTTI i.e. either class stored with a class type var -explicit- or compiler generated -behind the scene a if (type) then else). Otherwise, the cost of if then else can offset the benefit sometimes in inner loops.

Share this post


Link to post
Share on other sites

>So if anyone is C++ expert to>have a single xml_var class that can return INT or DOUBLE>based on on the argumentsThat's what C++ Templates are for, something like this:// function declarationtemplate T myfunc( T arg1 ){ return arg1 + 1; // do something }read more about this techinque here:http://www.codersource.net/cpp_template_function.htmlTemplates are probably the most powerful C++ feature...regards,

Share this post


Link to post
Share on other sites
Guest JeanLuc_

Yes of course, I could use templates. I do with some other classes too. I wanted something that permits typing less code though LOL, instead ofxml_var myvar;But, if you look closely, in the end, the call to the SDK function uses 3 pointers to string, int or double vars. So it has to differenciate based on function call arguments to the C SDK function. A template would not help to that matter.Look at the function call the class wraps:execute_calculator_code(_source_code,&var,0,0); // doubleexecute_calculator_code(_source_code,0,&var,0); // intit has to come down to RTTI of some sort. Either a member var set to an enum/int to differenciate the function call at runtime, or, implicit compiler generated. In any case, it will end up with a if then else (or switch/case whatever), which I'd like to avoid. I'd prefer a compiler generated direct function call to the right one for the xml_var class type.Any idea?

Share this post


Link to post
Share on other sites

JeanLuc,"Now if you look closely, the Init can pre-compile your XML code and store it (default). Since this requires having FS first compile, then copy the compiled code someplace, it is easier and versatile to just new [] the buffer needed, which the class does"Which XML code are you talking about? There is none involved in execute_calculator function that I know of. In fact, the "XML" char argument passed/retrieved by the function is an ID that points to an ID string member of data structure within PANEL classes. Those classes interact and exchange info with all the set of token vars handled by panels.dll (those are the "real" vars, even settable through Simconnect), so maybe what you want to do is access directly to the tokens? "As for string, I have not needed to implement them (no use yet on my projects) so they are missing for this reason, and you are right, this should be easy to add a class."Well, it happens that the posibility to handle strings through custom defined varsets is one of the most powerful enhancements I've found in the new SDK.Tom

Share this post


Link to post
Share on other sites
Guest JeanLuc_

Tom,please re-read the post above and look at:gauge_calculator_code_precompile()the "string" you pass as an argument to the execute_calc_code is an actual XML code. It is interpreted by FS. It goes this way:1) it is tokenized (like visual basic used to do up to at least v3)2) it is interpreted (from the tokenized representation3) while being interpreted, it will call some support internal function to retrieve the data asked for4) result is converted if need be (asking for Mhz instead of Khz is an example of that)5) result is returned.This class encapsulates the "tokenization" part of the process, in doing it at init. This way, anytime you "lookup", you skip step 1 above. This can save a lot when dealing with a high number of vars to lookup for.Now, it is an actual XML code, I bet you can pass very complex expressions in execute_calc_code too.No doubt for strings, I'have never had the oppotunity to use the XML system to retrieve strings yet. Can you give us a good example you are using XML to retrieve string for? I'm definitely interested to learn more too!PS: the "ID" thing is not with exec_calc_code, it is with this function instead: aircraft_varget().

Share this post


Link to post
Share on other sites

JeanLuc,I'm begining to understand now :-)The string argument is in fact a script code and not only an ID, you're right here. I had the idea before that this code was actually "compiled" when the gauge/dll is compiled, so it wouldn't look like text if editing the gauge/dll with a hex editor, but it seems I was wrong?Besides, when you say it is tokenized (1) do you mean it's "translated" at run time continuosly, before being interpreted?Refering to strings handling, it can be done using custom varsets (classes) that are identified in XML with the prefix C: (for example fs9gps is a custom class) The string code is actually saved on public char arrays defined inside classes -hence they are visible only on the XML gauge that instantiated the class- or can be put in public arrays within the main dll, being visible across the entire gaugeset. This is almost the way gps system works in XML.Maybe I'd ask more questions regarding this stuff if you don't mind :-)Tom

Share this post


Link to post
Share on other sites
Guest JeanLuc_

Yes, any time you call exec_calc_code, the string argument is tokenized. It is not CPU intensive by itslef, but done on 100 vars at 18Hz, it counts. Mind you, if you'd see how a simple lookup_var() is sometimes so much convoluted and does dozens of function calls where a simple direct func call or lookup in an array would do, no wonder we sometimes have a poorly running flight simulator.I see what kind of strings you are refering to now. In that particular department of course, I already have my own version of the GNS so it was not needed. Can be handy for EFIS gauges though instead of using the legacy gps_export.dll!

Share this post


Link to post
Share on other sites

It's too bad the forum software doesn't allow square braces as your example would not have thrown me off for a sec. :-)What are those angle brackets doing there? Aha, they're supposed to be square braces!


Jeff Bea

I am an avid globetrotter with my trusty Lufthansa B777F, Polar Air Cargo B744F, and Atlas Air B748F.

Share this post


Link to post
Share on other sites

The script code used as argument is indeed saved in plain text within the dll, so I see now the reason it is constantly tokenized at run time. I undesrtand then what your Init precomp does it almost similar to what panels.dll does when loading xml gauges at aircraft init, in terms to avoid step 1 at run time (scrip is interpreted from the compiled source held in memory)If I did a right interpretation, now I see the advantage of working xml scripts through a bridge class.Thank you for the clarification :-)Tom

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  

  • Tom Allensworth,
    Founder of AVSIM Online


  • Flight Simulation's Premier Resource!

    AVSIM is a free service to the flight simulation community. AVSIM is staffed completely by volunteers and all funds donated to AVSIM go directly back to supporting the community. Your donation here helps to pay our bandwidth costs, emergency funding, and other general costs that crop up from time to time. Thank you for your support!

    Click here for more information and to see all donations year to date.
×
×
  • Create New...