Jump to content
The simFlight Network Forums

petdocvmd

Members
  • Posts

    28
  • Joined

  • Last visited

Posts posted by petdocvmd

  1. The value is not a "short" (16 bit) but a signed byte (8 bit).

    Two odd things there:

    1: dwResult is a 32-bit result code, it won't fit into a byte.

    2: You are correctly reading the 1 byte at offset 0C49, but into a 32-bit integer. You need to set that to zero first, or it is likely to contain rubbish in the unused 24 bits.

    If you correct (2) then you will not see negative numbers -- the range will be 0 to 255. This is because the negative sign is in the single byte you have read, and will not be propagated into the other 24 bits. So to correct this you would need to OR into the 32-bit integer hex FFFFFF00 is the byte value is >= 128.

    Pete,

    VB.net has no signed byte data type. You have to use a short which covers -32768 to +32767.

    VB.net "number" variables are initialized to zero implicitly upon declaration (and booleans to false, strings to 'Nothing', etc)(yeah I know, programmers should be allowed to fall on their own swords ).

    I've been buried in 8051-variant assembler these days - feels kinda good mucking around in the"down 'n' dirty" stuff :-)

    Scott

    Scott L. Fausel, VMD

    Integrated Flight Systems

  2. The more I read about .NET, the more convinced I am I should stick with Legacy VB as long as humanly possible. In my case I have little choice anyway - my video editing hardware has no drivers available for anything after Win98, so I can't shift to .NET for my own usage.

    To be honest, I really can't understand why anyone has already shifted to writing in .NET - as long as there is still a large Win98 / Win95 user base out there who can't use .NET based software I would think anyone who wanted to write widely distributable software would stick to a language that all OS's can run.

    Richard

    Well Richard, we're off topic now but I'll give you my $0.02. Many folks made similar comments regarding the move from DOS to Windows - why write Windows-based code when DOS was faster/better/?

    VB.net is a quantum leap from VB6. Exception handling, Garbage collection, true OOP, xcopy deployment (no need for the registry), built in base class libraries, structures vs User defined types are all major improvements and there are many more. ADO.net makes data-driven web programming enormously easier and you can cater to all web clients.

    Yes, you do make a choice to target Win2k+ for non-web applications. That's a personal decision you must make after weighing the pros and cons of the improvements vs. the reduction in client scope. Another large factor is the learning curve - much of VB.net (especially OOP) is very different than VB and it's a steep climb. Well worth it IMHO.

    -Scott

  3. Yep, that did it. For the sake of those still following along or searching the forum in the future, here's the summary for programming Offset &H3200 via vb.net:

    1. Create a 12 element Byte array.

    2. Stuff elements 0-3 with Bytes 0-3 of message (&H100 or CONST WM_KEYDOWN for keydown, &H101 or CONST WM_KEYUP for keyup. I stripped the bytes out of the LONG integer via a for/next loop, the ">>" operator, an &HFF mask and the CByte() function.

    3. Likewise stuff elements 4-7 with Bytes 0-3 of the virtual keycode you are sending (e.g. &H47 for the letter "G").

    4. ibid for elements 8-11 and Bytes 0-3 of lParam (0 unless you are looking to send repeats i.e. "acceleration").

    5. Write the byte array to fsuipc:

    FSUIPC_Write(&H3200, 12, KeyData, t_keyData, _intError)

    where KeyData is the resultant byte array.

    6. Process when appropriate.

    Seems obvious once it's figured out but then I suppose most things do !

    -Scott

  4. How does it know what they are? The interface just wants an address and a byte size. It doesn't care at all what the data in or how it is composed. A 12 byte array might be 12 bytes, 6 16-bit words, 3 32-bit ones, or some weird mixture. All it wants is an address and size so it can keep building the block which will be sent by the Process call.

    ...All the FSUIPC interface needs is an address and a size. I would have thought that's all the parameters to the calls needed to be, whatver the real data is. I know there's a problem in VB about passing pointers to strings, which is why the WriteS function was added. That seemed a bit odd to me too, but you seem to imply that it goes much much further. Ugh.

    Yes, that is the crux of the biscuit. Unlike C++, VB.net is based upon a *managed* memory scheme. Except for some little advertised workarounds, dotnet does not use pointers to memory. It is all mapped and managed by the system. A benefit is the elimination of circular reference and other induced memory leaks but the cost is inflexibility in interacting with unmanaged code. The following is an excerpt from a previous Bob Scott Post:

    The pesky FSUIPC_Get was written to allow VB.Net to place the results of FSUIPC_Read operations into a managed data structure which is compatible with the .net memory management system. The basic approach is to pass the FSUIPC_Read a reference to a table offset token, and the function returns the offset into the local, .net-managed buffer which will contain the result after the FSUIPC_Process call. The FSUIPC_Get function retrieves the value at the specified offset from the local r/w buffer.

    This was necessary because just passing FSUIPC_Read a pointer to a variable as in previous versions will not work with the .Net heap manager moving things around. The referenced variable may be moved by the heap manager in the interval between when the FSUIPC_Read and the FSUIPC_Process calls are made, leaving one with a nasty dangling pointer problem.

    ...the first param in the FSUIPC_Get call is the integer offset token returned by FSUIPC_Read, the second param is a reference to the var where the actual result will be passed. The overloaded function defs will pass the correct size/type of data based on the type of the second param used in the call, except for passing of arrays where number of bytes to return must be explicitly coded.

    So you see the size/type is needed for the dotnet sdk functions - not the "raw" fsuipc Read or write. But re-reading Bob's post made me realize that we should be able to write a 12 element Byte array to 3200 by using the Byte() overload of FSUIPC_Write and setting size to 12.

    You can also see how queuing reads for a group process becomes more complex when one has to retrieve all data with unique tokens in individual "Get" functions after a Process call. Makes shared helper functions much more difficult to code. Theoretically one can "pin" managed memory and protect it from the system's "shuffles" but Bob reported he tried valiantly but unsuccessfully to make that work correctly before resorting to the buffered table.

    Well, time to put this to the test. I'll keep you posted.

    Regards,

    Scott

  5. I think you can omit the scan code -- if not I think there is a Windows API which will give you a scan code for a virtual key code.

    Indeed there is but I'll try without it at first.

    Why not use the names for the Keycodes as Rick says you can? Seems odd, if you have them defined in VB, to have to revert to numbers after all we discussed on this.

    That was just for example - actually I'd just pass the variable that I stuffed the code into when originally captured.

    I normally find out what sequences are needed, to make sure I get the order correct, by using the Spyxx program that comes with MS Visual Studio and seeing the actual sequences when I press the real buttons I want to use. I find this is the only accurate way. However, that said, I seem to recall that, yes, you's do Shift-down, Char-down, Char-up, Shift-up. Horrible, isn't it?.

    Good idea, thanks and yes it is quite horrid!

    Of course, WideClient, my user of the facility, doesn't have much complication as all it is doing is relaying real WM_KEYDOWN and WM_KEYUP messages it receives on the Client PC to FS via the 3200 offset. All it needs to do is copy the wParam and lParam it receives. Similarly, those writing keynoard emulators normally need to know all this stuff in any case, to get keypresses into other programs. I think this is actually the first time anyone has wanted to use this facility with no prior knowlegde at all.

    Yes, well that's because no API knowledge is required to do this stuff in dotnet

    Really? For every individual read and write? That is GROSSLY inefficient! Each "Process" call does a Process change to get into FS, activates FSUIPC's offset scanning, processes your changes, then needs another process change back to your program! The whole reason the FSUIPC_Read and FSUIPC_Write procedures were split from the FSUIPC_Process procedure was to allow EVERY read and write you needed to do to be performed in one process. For instance, if your program operates on a 55 mSec cycle (the most usual, based on the standard windows TIMER facility which ticks at 18Hz), you'd build up the complete set of Reads and Writes then do one Process call for the lot, in each such cycle.

    If all VB programs operate one read or write, one process, then I am not surprised they all seem so slow and inefficient to me -- I thought it was just the horrible code ther compiler was producing! :o

    Oops, no sorry - you misunderstand me. The dotnet fsuipc sdk works the same way. However there are frequently times when one cannot queue reads and writes. For example, many functions need the information from a read (or reads from several different offsets) prior to writing some data because the data is dependent upon what is read (such as functions that toggle one bit in a Word or branch depending upon the data read). Thus you must process the read or reads before writing otherwise you don't know what to write.

    I could potentially code a static boolean flag into each function that postpones writes such that only every other time the dispatcher calls the function it performs the writes. Each cycle would have its own group process. One issue is that many functions share a common helper function which currently (re)creates a token that would lead to conflicts if the function executed more than once in a process cycle. However I could have the parent function pass in token and result parameters to keep them unique. Ok, I see a lot of debugging and testing ahead but yes I would love to eliminate single read/write processing from my code altogether!

    No, that won't work in this case. The complete structure of three values is one data value.

    The largest structure is 8 bytes!!!? Surely you mean the longest single data type, not structure?

    Yes, sorry - was referring to a data type, not a structure. Poor choice of words but it was getting a bit into the wee hours when I wrote that!

    The 12 bytes should be defined as a simple 3 32-bit integer structure or array. Don't tell me VB.NET doesn't support structures at all? If not, then surely it must have integer arrays? At least in this instance all three parts are the same size, so an array would do. But it doesn't have 12 elements, only 3 -- the three 32 bit values (unsigned really, in Windows, but I don't suppose VB.Net supports unsigned values either -- or does it?)

    By "one write" it means "one write" -- i.e. one call to the FSUIPC_Write procedure, or whatever it is called in VB.NET, to write the 12 bytes, no matter how you manage to cobble them together before hand.

    Actually, the vb.net implementation of structures is very robust - they are basically classes without some of the bells & whistles. Much improved from VB6 User defined types. However I don't know that I could pass such a structure to the fsuipc.write function - I don't see an overload for it in Bob's SDK code. That's what prompted my concern about a 12 byte value - the sdk write function appears to only accept 1-, 2-, 4- and 8-byte values plus byte arrays.

    My thought was passing a 12 element array of single bytes - would that fit your definition of "cobble together" ? It's no problem to create a 3 element arrray of 32 bit unsigned values (Long in vb.net - and yes, it does support unsigned values) - I just don't know if the SDK fsuipc.write function can accept such an array of Long Integers.

    I can see why no one can use Windows APIs in VB.NET then -- if it doesn't support structures then a large portion of the Windows API is unusable, as it is very structure dependent. :(

    I have passed structures to the API in my programs via a C++ function library in order to interact with another developer's USB input board. The difference is that I wrote the wrapper function signature so as to solicit a structure as a parameter whereas the fsuipc vb.net sdk does not appear to have a write function with a structure as the data parameter. I'll have to check with Bob Scott about passing structures to fsuipc from vb.net. If this cannot be done via a byte array then I will work on coding a function that will accept structures and adding it to the sdk.

    Thanks,

    Scott

  6. Rick pointed out the VB5/6 way of grabbing key codes and I think we can all agree that each language implements a way of capturing these and enumerating them.

    OK, I've waded through the API docs and here is where I am at:

    1. WM_KEYDOWN is &H100 and WM_KEYUP is &H101

    2. wParam specifies virtual keycode of the key to be sent

    3. lparam specifies repeat count and several other items.

    Question 1: bits 16-23 of lparam specify the device dependent scan code...seems not useful as we already have virtual KC. Can we simply use lparam bits 0-15 for repeat count and zero the rest of the double word e.g. lparam = 0 if there are to be no repeats (and assuming not an extended key as set in bit 24)?

    Question 2: Is it correct to say that to transmit a "shift-K" I would send a WM_KEYDOWN + &H10 + 0 followed by WM_KEYDOWN + &H48 + 0 and then the corresponding KEYUPs to simulate holding the while "K" is depressed (&H10 is VKC for shift and &H48 is vkc for K)?

    Question 3: The FSUIPC guide indicates that all 12 Bytes must be written in "one IPC write." In the fsuipc VB.net sdk writing an offset is done via a Write followed by a Process. Can I write to 3200, write to 3204, write to 3208 and then process? Or are you saying I have to write 12 Bytes to 3200 in one function call - is that even possible given the largest data structure (Long or Double) is 8 bytes? Or do I use a 12 element byte array?

    Sorry - I know my lack of familiarity with C and the Windows API are making this stuff murkier to me than it should be though I think I've just about got it.

    Thanks for your help,

    Scott

  7. Ah, I hate all thsat high level stuff. It does the same things as it always did, yet in much more convoluted and expensive ways. It is this sort of development that means that the vast improvement we get in computer speeds and capacity is all but totally lost to code inflation and inefficiency. I am afraid I am a die-hard assembly-level programmer who uses C with some reluctance, but at least in C I've a fair notion of what is really happening!

    I don't mean any of this as an insult to you. I do realise that this makes coding simple and easy, but the cost is horrendous, both as a loss of understanding in most programmers about what actually happens and in the bloat I already mentioned.

    No insult taken (in my case I believe it's not a loss of understanding but a divergence of language and syntax) and we could probably fill an entire discussion forum with programming debates .

    However IMO you are overstating the cost of "code inflation and inefficiency." The dotnet framework is actually equal in efficiency and speed to unmanaged C++. Managed code (be it C++, C# or VB) is all compiled to a common intermediate language that is fed to the JIT (just in time) compiler. The resultant compilation is as fast and efficient as compiled C.

    All of the "bells and whistles" are rapid development tools only. The intermediate language that results is "lean and mean" and dotnet programs are far from "bloated."

    I dabbled a bit in 8086 assembler way back when and still program PICs in assembler so I know how you feel - kind of like digging in the garden vs. picking out veggies at the market .

    Nonetheless with high level RAD languages like vb.net I can cut my development time enormously. And I do indeed know what is really happening - it's still full of Do and For loops and function calls, etc. What's improved is the standardization - namespaces, classes, etc. It is now very easy to look up the hierarchy of an object or method and figure out how to use it.

    Sorry, if Virtual Keycodes are never used in VB.net I am rather at a loss to explain them to you. Surely you don't distinguish between, say, ESCAPE and ENTER by using their numeric representations? Most languages, even Assembly Code, uses names for common constants -- doesn't VB? In the C and C++ headers the Keycodes are defined by #defines with names like VK_ESC or whatever. Then you need not worry that this is in fact number 27, or whatever..

    Yes - simply called "Constants" in VB like so:

    Public CONST ESC_KEY = 27

    But it's unnecessary as these are already defined in a dotnet enumeration (keyChar) for me:

    labelKey.text = e.KeyChar (displays actual key e.g. "K" in label)

    where e is the argument passed to my function automatically if this function handles the keypress event. I can also obtain e.KeyValue integer representation of the key (i.e. keycode).

    That's an example of the opposite of "code bloat" - I do not need to add a keycode/value constant map to my code as you would in C - it's already embedded in the framework (within the forms namespace)

    Anyway, I still haven't had a chance to review the API to see how 3200 wants those parameters formatted. Hope to get to it tonight. Thanks for the lively discussion !

    Regards,

    Scott

  8. They are the parameters for the Windows WM_KEYDOWN and WM_KEYUP messages which you are asking FSUIPC to send on your behalf. The documentation is in the Windows API documentation only (or in multitudes of Windows' programming books), not in any Flight Simulation reference.

    Roger. I wasn't sure that they mimicked the Windows API and a quick Google search was unrewarding. I'll search the API docs.

    When I do any programming in Windows I have to constantly look stuff like this up, I don't learn it. How do you manage without such a reference? I don't understand. Doesn't VB.NET allow you to process Key messages?

    Yes but it is so easy it should be illegal. No API required. I can intercept keyup, keydown and keypress like this:

    Function DoSomething(ByVal s as Object, ByVal e asKeyEventArgs) Handles MyBase.KeyDown

    ...Do something with e.keycode and e.Shift, etc - all enumerated for me

    End Function

    Sending is just as easy using built in "SendKeys" function - in fact you can use enumeration syntax e.g. {Backspace} and even avoid keycodes.

    DotNet has obviated 99% of the Windows API (in fact it will probably become legacy in next release - 'Longhorn').

    If you really cannot find the references, whether in books or in your Compiler's help, I can try to make a copy of some of it here, but I'm not sure that's properly legal.

    I'm sure I can find them now that I know they are WIndows API terms.

    The keycodes used are those named VK_xxx ("virtual Key") and must be defined somewhere in your compiler's headers if it allows Windows programming. However, the main ones are the same as the key values used by FS in its CFG file and are therefore also listed in my "FSxxxx Controls" documents, and, in fact, in the FSUIPC Advanced User'sa Guide for Key programming.

    I'm not quite sure about what you mean by defining keycodes here. VB.net has no header file. Won't my program just need to "know" (e.g. via constant definitions) that keycode 112 = F1, etc? I have copies of the sections you mention but the application will capture the keycode information in the section that accepts user input for the key(s) to be mapped to a particular switch i.e. "recording mode"

    Get back if you are really stuck, but I am rather puzzled by the question -- the programmer's guide is aimed at programmers and I thought all programmers in Windows would have such data, which is why the documentation is worded to suit. Sorry if this isn't always true.

    Well, that's cause I let dotnet do all that dirty work for me . I guess it might be considered "cheating" by some but it sure saves me time to foucs on other programming issues ! Where I run into issues is in trying to interface with COM code conventions - as in this case.

    BTW an alternative to sending Keystrokes is to use the "virtual buttons" facilities in FSUIPC -- offsets 3340 ff. Then the buttons so activated can be programmed in FSUIPC's Buttons page, so saving you the chore.

    That's a great idea and I will probably offer both. My application handles a fair amount of stuff not modeled in FS or PM but some folks might just want basic interface stuff. That would essentially let me model my inputs as joystick buttons for functions I may not yet have coded.

    Thanks!

    Scott

  9. Hi Pete,

    I'm looking to add a generic keypress simulator to my flight deck interface program so that users can assign hardware switches to mimic a keypress in MSFS. These are not joystick buttons so I'll be creating an xref table where the user can save switch-key mappings. The program will use FSUIPC offset 3200 to send the appropriate key to FS where it will (hopefully) do whatever the user has assigned in FS.

    Can you please define or give an example of "wParam" and "lParam" for me? I assume they represent keycodes and modifiers that are to be parameters of an API function but I am unfamiliar with the nomenclature and unsure of which is which (Don't use APIs much in vb.net ). I could not find details in the documentation nor via a search of this forum.

    Perhaps you could indicate the value to be written to 3200 for a simple "G" and say "Ctl-K" for me?

    Thanks!

    Scott L. Fausel, VMD

  10. A few more possible errors found:

    Public FSUIPC_FS_Version As Short

    Public FSUIPC_Lib_Version As Short

    FSUIPC_Open fails unless these are declared as Integers due to truncation when checking FSUIPC FS Version.

    For those of us who code with Option strict:

    643: Dim idx = Token + 4 should be:

    Dim idx as Integer = Token + 4

    --> keeps idx from being created as generic object and then being boxed to Integer.

    The declaration of t_FSUIPC_Lib_Version was originally done as part of debug code and may have been cut out with that in the latest version. Works fine for me if I just enter the declaration back in.

    Prior bug is still with me...

    Address: 1252 Data: 262384

    262384 Error# 1925

    Address: 1252 Data: 262384

    262384 Error# 1926

    Address: 1252 Data: 240

    Address: 1252 Data: 240

    Translates into 1,926 iterations where I got back "262384" from fsuipc instead of the "240" I should have (and which FSInterrogate displayed constantly).

    I'm sure hoping that this is an error code of some sort...

    -Scott

    This is for the VB.net gurus:

    However there are 2 build errors in the sample:

    505: VersionGet = FSUIPC_Get(t_FSUIPC_Lib_Version, FSUIPC_Lib_Version)

    "t_FSUIPC_Lib_Version" is never declared. Looks like it should be declared as an integer within FSUIPC_Open, correct?

    636: Marshal.FreeHGlobal(heapbuf);

    Perhaps a late night translating C++ code ? Stray semicolon alert.

  11. This is for the VB.net gurus:

    I just downloaded the updated vb.net sdk hoping it might solve a nasty bug in my app that seems to come from within the old sdk code I adapted.

    However there are 2 build errors in the sample:

    505: VersionGet = FSUIPC_Get(t_FSUIPC_Lib_Version, FSUIPC_Lib_Version)

    "t_FSUIPC_Lib_Version" is never declared. Looks like it should be declared as an integer within FSUIPC_Open, correct?

    636: Marshal.FreeHGlobal(heapbuf);

    Perhaps a late night translating C++ code ? Stray semicolon alert.

    My original issue was this: The following function is called as a helper function from other functions that are called from a timing loop every 90ms. It's used to obtain values from Project Magenta to be displayed on the autopilot:

    Private Function ReadPMAPDigits(ByVal _Address As Integer) As Integer

    'This function reads appropriate Digits from MCP or FCU and returns in _Data

    'Declare Vars

    Dim blnStatus As Boolean

    Dim t_PMAP, _intError As Integer

    Dim _Data As Integer

    blnStatus = myFSUIPC.FSUIPC_Read(_Address, 2, t_PMAP, _intError) 'Obtain value

    If blnStatus Then

    'Read Successful

    blnStatus = myFSUIPC.FSUIPC_Process(_intError)

    If blnStatus Then

    'Process Successful

    blnStatus = myFSUIPC.FSUIPC_Get(t_PMAP, _Data)

    If blnStatus Then

    'Get Successful

    Console.WriteLine("Address: " & _Address.ToString & " Data: " & _Data.ToString)

    Return _Data

    End If

    End If

    End If

    End Function

    The debug output to the console produces a steady stream of the offset address & data for about 5 minutes and then - anywhere from 127 to multitudes of iterations of nonsense values (correct address, nonsense value). FSInterrogate verifies that PM is not to blame - it's buffer value never wavers. Here's my trace:

    Address: 1252 Data: 240

    Address: 1252 Data: 240

    Address: 1252 Data: 240

    Address: 1252 Data: -86114064

    86114064 Error# 1

    Address: 1252 Data: 262384

    262384 Error# 2

    Address: 1252 Data: 262384

    262384 Error# 3

    Address: 1252 Data: 262384

    and so on 127 times before reverting back to the correct value (240, which is multiplied by 100 to get current ALT setting of FL240 in this example).

    Are these "nonsense" values error codes? If so, is there an xref table or some way I can trap them cleanly?

    "MyFSUIPC" is just an instance of a class I created with the fsuipc vb.net functionality. I'm utilizing the procedures as written in the (original) SDK.

    I'm going to rework the new sdk into a class but was wondering if anyone had heard of this behavior and if it might relate to a known bug. I seemed to remember a post here about some errors in the original code but I couldnt turn it up in a search (I think it was archived from the server).

    Thanks for any advice!

    Scott

  12. Hey Bob, I wonder if it would be possible to use the GCHandle class to pin a managed address and then pass it to fsuipc_read as type IntPtr? That would protect it from the heap manager until you chose to free it - after grabbing the info. Anyone tried this?

    -Scott

    The pesky FSUIPC_Get was written to allow VB.Net to place the results of FSUIPC_Read operations into a managed data structure which is compatible with the .net memory management system. The basic approach is to pass the FSUIPC_Read a reference to a table offset token, and the function returns the offset into the local, .net-managed buffer which will contain the result after the FSUIPC_Process call. The FSUIPC_Get function retrieves the value at the specified offset from the local r/w buffer.

    This was necessary because just passing FSUIPC_Read a pointer to a variable as in previous versions will not work with the .Net heap manager moving things around. The referenced variable may be moved by the heap manager in the interval between when the FSUIPC_Read and the FSUIPC_Process calls are made, leaving one with a nasty dangling pointer problem.

    In any event, some of the previously posted difficulties came from trying to read the offset token as data...the first param in the FSUIPC_Get call is the integer offset token returned by FSUIPC_Read, the second param is a reference to the var where the actual result will be passed. The overloaded function defs will pass the correct size/type of data based on the type of the second param used in the call, except for passing of arrays where number of bytes to return must be explicitly coded.

    Clear as mud?

    Regards

  13. Well, from the sorts of questions I get on VB problems I think most are due to the language, not the user. I think it is ambiguous and imprecise, and the more I know about it the more I think it's a bad choice for beginners (or for anyone, for that matter). But maybe I'm just a little prejudiced! :D

    Hey Pete, I can't just let ya bash VB like that ! Although I'd be the first to admit that older versions were - shall we say - "less than desirable" VB.net is a bona fide programming language. It's a tool every bit as powerful as C++...in the right hands.

    What I see on this forum and elsewhere is misunderstanding and misuse by programmers. There's nothing ambiguous or imprecise about the language - it just seems that way if one doesn't know a short from a long or an OR from a XOR !

    The class structure of dotnet allows very straightforward implementation of complex functions - for example runtime construction of function delegates - as long as one is willing to put in some time and learn them!

    Yes, direct memory manipulation requires a bit more stealth than C++ but one really only needs it when interfacing with C++ functions that "play" in unmanaged memory...and risk memory leaks - mostly a thing of the past in dotnet managed memory where circular references are killed and garbage collected automatically. Your earlier surprise that writing an Integer to a Byte did not cause a crash? Not an issue in VB as it would either be flagged in compilation if 'Option Strict' is (as it should always be) set or cause automatic downcasting if not - leading to the aforementioned truncation error but never overwriting a neighbor's memory.

    Anyway, I've blathered enough already. Suffice to say that imho (and programming experience) VB is a great tool when used correctly - "with power comes responsibility" as the cliche goes . My forthcoming cockpit I/O module's software interface will be written entirely in vb.net and I've had zero problems interacting with fsuipc or the hardware .

    Thanks,

    Scott L. Fausel, VMD

  14. No, I don't think any of them are pressure altitude -- that isn't the same as AMSL which is the true altitude above sea level. Pressure altitudes vary according to pressure and are used in aircraft performance calculations and conversions between TAS and Mach, things like that.

    Got it. I hadn't tried changing the pressure to check that.

    The ground altitude is provided in two places -- 0020 and more accurately at 0B4C. the aircraft's altitude is given at 0570. Both of these are AMSL and have no dependency whatsoever on any altimeter setting or pressure variations. Calculating the aircraft altitude AGL is simply a matter of subtracting one from the other, which is what all currently implemented radar altitude gauges do.

    Right. Knowing that it is true AMSL is the key. Thanks for the help!

    Scott

  15. I am finishing up the logic for my reverse thrust mechanism and need to read absolute altitude AGL a la a radio altimeter for one of the conditions (the 737-700 RT can engage if a/c is <10' AGL via radio altimeter).

    Looking at the offsets in FSInterrogate while on the ground seems to indicate that all of the offsets pertaining to altitude are reading pressure altitude (MSL).

    Did I miss one that gives AGL? If not, can it be simulated with the info that is available (including maintaining accuracy even if the pilot has the wrong pressure dialed into the altimeter)?

    Thanks for your help!

    Scott Fausel

  16. I'm trying to find a tidy way to do all this with a single 100k slide pot. I could wire a contact switch to the armed detent position that could set the armed flag but would prefer to do this in the software.

    Well I answered my own question by monkeying around with FSInterrogate and my control :oops:

    Looks like the actual spoiler positions (as reported in 0BD4 and 0BD8) do not change until the spoiler axis (0BD0) exceeds 4800. So I simply picked an arbitrary range (3300-4800) in the spoiler axis that triggers a function to arm the spoilers if the spoiler control falls within that range. Below it or above it I clear the armed flag (0BCC).

    Tested and functional - no need for a separate switch - works just fine as is.

    Scott

  17. I'm a little unclear as to the interaction between the spoilers arm offset (0BBC) and the spoilers control offset (0BD0).

    Specifically I'm trying to figure out how wire the physical lever and then code to mimic the functionality of the B737-700 spoiler control. The first detent corresponds to no spoiler extension and an unarmed state. The next detente is armed but not extended. Then follows a variable range of extension up to the next detent which is max inflight extension. Finally there is a detent for maximum ground extension (though probably identical to the previous detent in FS2K2 since there do not appear to be separate air and ground spoilers in FS).

    I'm trying to find a tidy way to do all this with a single 100k slide pot. I could wire a contact switch to the armed detent position that could set the armed flag but would prefer to do this in the software.

    Is there an offset to read the spoiler pot value post calibration but before being sent to FS2K2 similar to how the throttle axes can be manipulated? I suppose I could intercept the windows values in my program and write those to 0BD0 after resetting the range so that I could use an arbitrary low range of values to signify an armed condition (and set the flag) and then the rest of the range as flight extension settings.

    Am I missing something easy here?

    Thanks,

    Scott

  18. Im trying to set COM freq using VB6(I dont do C or C++ unfortunatly)& I dont have time, at present, to get up to speed with dotNET.

    Reading these values is not a problem, as long as you remeber that VB dosnt do Binary or BCD.

    But right them back to the offset, well...Mike

    Mike,

    I struggled with this a bit myself recently and with some help from Pete solved it in VB.net. The algorithms are still clumsy as I was just trying to make it work and though in .net should easily translate to vb6. You'll have to change SHORTs to INTEGERs but otherwise should run.

    Here are the algorithms:

    ****************************************************

    Public Class CHelper

    'This class serves to separate out conversion functions, etc

    Public Function DECtoBCD(ByVal intDEC As Integer) As Integer

    'This function takes the decimal equivalent of a BCD and returns the BCD

    Dim mThous As Short

    Dim mHund As Short

    Dim mTen As Short

    Dim mOne As Short

    mThous = (intDEC And 61440) / 4096 * 1000

    mHund = (intDEC And 3840) / 256 * 100

    mTen = (intDEC And 240) / 16 * 10

    mOne = (intDEC And 15)

    DECtoBCD += mThous + mHund + mTen + mOne

    Return DECtoBCD

    End Function

    Public Function BCDtoDEC(ByVal intBCD As Integer) As Integer

    'This function takes a BCD and returns decimal equivalent

    Dim mThous, MHund, MTen, MOne As Short

    mThous = Int(intBCD / 1000) * 1000

    MHund = Int((intBCD - mThous) / 100) * 100

    MTen = Int((intBCD - mThous - MHund) / 10) * 10

    MOne = Int((intBCD - mThous - MHund - MTen))

    BCDtoDEC = mThous / 1000 * 4096 + MHund / 100 * 256 + MTen / 10 * 16 + MOne

    End Function

    End Class

    ***********************************************

    And here is the code that uses it:

    If ReadCOM1(FSCOM1, intError) Then

    'Able to read com1

    'Let's try to write incremented value

    Dim temp_FSCOM1 As Integer = myCHelper.DECtoBCD(FSCOM1) 'temp var to increment FSCOM1's value

    Dim case_FSCOM1 As Integer

    case_FSCOM1 = temp_FSCOM1 - (Int(temp_FSCOM1 / 1000) * 1000)

    case_FSCOM1 = case_FSCOM1 - Int(case_FSCOM1 / 100) * 100

    case_FSCOM1 = case_FSCOM1 - Int(case_FSCOM1 / 10) * 10

    Select Case case_FSCOM1 'selects last digit of BCD

    Case 0

    'BCD ends in 0 so add 2

    temp_FSCOM1 += 2

    Case 2

    'BCD ends in 2 so add 3

    temp_FSCOM1 += 3

    Case 5

    'BCD ends in 5 so add 2

    temp_FSCOM1 += 2

    Case 7

    'BCD ends in 7 so add 3

    temp_FSCOM1 += 3

    Case Else

    MessageBox.Show("Error - shouldnt get here")

    End Select

    If temp_FSCOM1 > 3597 Then

    'exceeds highest freq - return to low

    temp_FSCOM1 = 1800

    End If

    temp_FSCOM1 = myCHelper.BCDtoDEC(temp_FSCOM1)

    If WriteCOM1(temp_FSCOM1, intError) Then

    'Write Successful

    Else

    MessageBox.Show("Error writing to COM1", "Error!")

    Exit Sub

    End If

    Else

    'Problem reading - therefore cannot change

    Exit Sub

    End If

    Readcom and writecom are simply functions that pass the info to the generic read/write/process/get functions - intError is the same as dwResult, etc.

    Hope this helps! I've tested it with a rotary and it works. Of course there's a lot of tweaking to do e.g. if you want separate whole and fractional frequency controls and obviously a complementary decrement function but this should give you the picture.

    Scott

  19. If you check the Programmers Guide for FSUIPC you will see that at offsets 3328-3337 you can read the axis input values -- those read by FS itself, and at 310A you'll find switches to allow these to be disconnected from FS. Hence you can read the values yourself, manipulate them how you like, then write the results to the Throttle control areas at 088C, 0924 et cetera.

    Great Pete, thanks! Question: Is the range of values read at (e.g.) 3330 (Throttle 1 axis) the same as that expected at 088C (i.e. -4096 to 16384) assuming calibration done? Also, does FS interpret any part of the range at 088C as reverse thrust or is -4096 idle and 16384 max?

    Thanks,

    Scott

  20. No. Unless you can get pots which are really very precisely matched I don't think you can ever get them perfectly lined up. (Actually, I don't really think the real throttle levers in the aircraft are necessarily precisely aligned to get the exact same performance from the engines -- at least they don't look that way when I've been in the jump seat, especially with Auto-Throttle engaged, which it invariably is after take-off).

    Understood. And no, I don't want perfect match - just fairly close.

    To get values the same for each physical position of the throttles, each one would need many calibration points, with a table to convert the input value to the desired output. This is actually a facility provided on EPIC cards -- each input axis is processed through a 256 byte table (the raw inputs are in the range 0-255, so this suits). I could consider something like that for a future version of FSUIPC -- I have been considering adding full axis assignment and calibration facilities in any case (by-passing the FS CFG stuff), and would certainly add this then. But I cannot consider any such addition yet -- not till well after "conquering" FS2004!

    Hmm - is this possibly doable by mere mortals using the fsuipc sdk? If I sample the pot input via Direct Input I could run it through such a table in my app. I don't have the docs in front of me - can this "digitized" data be output to fs2k2 via an axis or offset(s) in fsuipc?

    Thanks,

    Scott (hoping that fs2004 won't bring radical programming changes )

  21. I'm building and testing a throttle quad for the 737-700. I've used 100k linear taper slide pots and have a question about calibration.

    For now the pots are set up as part of a generic 2-button 3-axis joystick in which the 3rd axis is assigned to flaps via a "ghost" Engine 4 mixture axis.

    I calibrated in Windows as best as possible considering throttles are using x/y axes. I set sensitivity to max and null to 0 in FS2k2.

    On the FSUIPC joystick page for throttles I went through the steps to set and calibrate the throttles but here's the thing: They each work fine but don't line up very well with each other at the same N1 except at idle or max.

    I think I could improve this by physically detaching the pot for 1 lever and moving it back a bit. However this involves pulling some nails, etc - am I missing a way to do this in the software?

    Thanks for your advice,

    Scott

  22. I'm having a couple of problems as I try to implement FS2K2 COM radio freq changing via rotaries.

    1. I have a rotary decoder that runs through a 64 button USB input device. This input is translated to keypress macros by a helper application (KB emulator). Using the (latest) FSUIPC Options "Keys" tab I mapped some key combinations to various selections. I found that ADF and NAV mapping worked perfectly but many coms did not: e.g. selecting "com stdby whole increase" from the dropdown actually caused the selected keypress to map to the pilot's AP course selector and "com stdby fract increase mapped to the copilot's AP course selector. Is the "keys" function of FSUIPC a "caveat emptor" area throughout with regard to FS2K2? If so, has anyone charted the dropdown selections and created a mappings table that shows what each selection really does in FS2K2?

    2. Offset 034E (and similar) are described as "4 digits in BCD format. A freq of 123.45 is represented by 0x2345. The leading 1 is assumed." Well when I read that offset and display the value in my vb.net test procedure I get (e.g.) "6567" for the offset value with the FS COM1 freq set to 120.07. This looks like some combination of BCD and Hex conversion but I just can't solve the puzzle. I want to increment/dec either the "(1)20" or the ".07" when the rotary turns but how do I manipulate "6567" to accomplish this in my sub that captures the rotary input i.e. what is the formula for conversion? This is probably incredibly obvious but it is escaping me (straight hex conversion was close as decimal 6567 = 19A7h, but I would then have to parse each digit of the resultant hex # and if >9 set to 0 and carry left...got rather involved and I expect there must be an easier way).

    Thanks for any help you can provide!

    Scott

  23. Richard:

    In FSUIPC, does the "dummy" axis you are using respond to the flaps control input if you disable any mapping in FSUIPC? If not and yet visible in FS you might try replacing FSUIPC.dll in the modules folder.

    If it does then double check the FS2k2 control # you are mapping for the axis and your syntax in FSUIPC.ini and make certain you are restarting FS after any changes.

    I'm using FlapsSetControl=66431 for AXIS_MIXTURE4_SET.

    Also be certain the control sensitivity is maxed and null 0.

    Good luck!

    Scott

    Having trouble getting flaps to work again.

    They were working fine with FlapSetControl=66291 while running ME. Upgraded to XP Home (reloaded FS2002) and can't seem to get the flaps working again. I don't think the OS would cause my problem.

    Have set up flap control according to Advanced User Guide. I can see the axis move when looking at the FS2002 joystick calibration section. But when I look at Flaps under FSUIPC, I see no change in values while moving th flap lever.

    I have tried:

    AXIS_PAN_HEADING

    AXIS_PROPELLER_SET

    AXIS_RUDDER_SET

    AXIS_MIXTURE4_SET

    No FSUIPC flap movement on any of these.

    Any ideas?

    Richard

  24. Richard:

    In FSUIPC, does the "dummy" axis you are using respond to the flaps control input if you disable any mapping in FSUIPC? If not and yet visible in FS you might try replacing FSUIPC.dll in the modules folder.

    If it does then double check the FS2k2 control # you are mapping for the axis and your syntax in FSUIPC.ini and make certain you are restarting FS after any changes.

    I'm using FlapsSetControl=66431 for AXIS_MIXTURE4_SET.

    Also be certain the control sensitivity is maxed and null 0.

    Good luck!

    Scott

    Having trouble getting flaps to work again.

    They were working fine with FlapSetControl=66291 while running ME. Upgraded to XP Home (reloaded FS2002) and can't seem to get the flaps working again. I don't think the OS would cause my problem.

    Have set up flap control according to Advanced User Guide. I can see the axis move when looking at the FS2002 joystick calibration section. But when I look at Flaps under FSUIPC, I see no change in values while moving th flap lever.

    I have tried:

    AXIS_PAN_HEADING

    AXIS_PROPELLER_SET

    AXIS_RUDDER_SET

    AXIS_MIXTURE4_SET

    No FSUIPC flap movement on any of these.

    Any ideas?

    Richard

  25. Thanks, Jose - yes I realized after some more research that the variable resistance is used indirectly to vary the voltage and THAT is what determines the scale.

    I wonder if at least part of the issue is the resolution of the USB adapter - from what I hear the "bit depth" of its pseudo A-D converter is poor, and thus there are rather large gaps between the resultant output values sent to FS.

    I'm going to try to run it directly into my PCI card gameport and see if there's a noticeable difference.

    Still open for other suggestions!

    Thanks!

    How is the voltage variation? As far I know that's what counts not the resistance. If the Pot is a 3 point one you can try this solution:
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. Guidelines Privacy Policy We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.