dazz Posted January 17, 2011 Report Posted January 17, 2011 Hi everyone. I'm working in a script to filter my TQ spikes. It looks like this so far: while (true) do new1 = ipc.get("old1") new2 = ipc.get("old2") new3 = ipc.readSW(0x66C0) if new1 == nil then new1 = 0 end if new2 == nil then new2 = 0 end if new3 == nil then new3 = 0 end ipc.log("new1 = " .. new1) ipc.log("new2 = " .. new2) ipc.log("new3 = " .. new3) ipc.log("-----------------------") ipc.set("old1", new2) ipc.set("old2", new3) nextV = new3 if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then nextV = new2 end if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then nextV = new1 end nextV = nextV * -1 ipc.control(66504, nextV) ipc.log("nextV = " .. nextV) ipc.log("***********************") ipc.sleep(50) end It's of course in it's infancy yet. Couple questions please. I want to expand it to filter all 4 throttle axis independantly, and a stack would come in handy. 1.- Any suggestions on a stack implementation for Lua? Don't even need it to take care of concurrency, as I will only have one writer 2.- Can I store the stacks in the global just like ipc.set does or do I need to build the stacks for each iteration? If I can't I might as well forget about using "complex" data structures and keep it simple instead 3.- Also considering assigning the axis to a Lua pluggin that will update a global variable via ipc.set instead of using the 0x66C0 offset. What is the best approach performance wise? I take it when I assign my throttle axis to the 0x66C0 offset, FSUIPC is also running a thread to update the value the same way the Lua plugin would. Is that correct? ...more questions to come Thanks in advance
Pete Dowson Posted January 17, 2011 Report Posted January 17, 2011 Hi everyone. I'm working in a script to filter my TQ spikes. It looks like this so far: Have you considered making it event driven rather than running a never ending loop? It would also then not need to use global variables as the plug-in would be always there and running on demand. I want to expand it to filter all 4 throttle axis independantly, and a stack would come in handy. Why a stack? Tables are very easy in Lua. You could use a table in stack fashion of course. I take it when I assign my throttle axis to the 0x66C0 offset, FSUIPC is also running a thread to update the value the same way the Lua plugin would. Is that correct? It's scanning axes the same way no matter what you assign them to. If an axis is assigned to send a control to FS, it sends the control to FS. If it is assigned to update an offset, it updates an offset. Whether any of that is done in the main thread or an axis scanning thread isn't really relevant to anything. Regards Pete
dazz Posted January 17, 2011 Author Report Posted January 17, 2011 Thanks Pete Have you considered making it event driven rather than running a never ending loop? It would also then not need to use global variables as the plug-in would be always there and running on demand. Yes, I have also considered intercepting the axis, but the idea is to pick the last n axis readings, discard the max and min value and apply the average of the rest. In an event driven approach I would be discarding the last reading even if it's a valid value. With the loop, the next iteration would ensure the proper value is applied. I will try different implementations including event driven, but for now that's what I'm trying to do Why a stack? Tables are very easy in Lua. You could use a table in stack fashion of course. A stack seems to fit my needs just perfectly with this approach since I can keep the last n relevant values updated naturally. I can see that Lua has a native implementation of a stack, but a table would do too. So, is there a way to store a complex structure like a stack or a table in the global space like ipc.set does please?, or maybe ipc.set works with any kind of data structure? I can always try that before asking hehe
Pete Dowson Posted January 17, 2011 Report Posted January 17, 2011 Yes, I have also considered intercepting the axis, but the idea is to pick the last n axis readings, discard the max and min value and apply the average of the rest. In an event driven approach I would be discarding the last reading even if it's a valid value. I was thinking more of an even like on the offset you are changing or possibly a timer event so you can sample as you do now. A stack seems to fit my needs just perfectly with this approach since I can keep the last n relevant values updated naturally. I can see that Lua has a native implementation of a stack, but a table would do too. Ah, you've perhaps read more than me. I've read most of the Lua manual once, but forgot most of it too! ;-0 So, is there a way to store a complex structure like a stack or a table in the global space like ipc.set does please?, or maybe ipc.set works with any kind of data structure? I can always try that before asking hehe No, it only works with strings and numbers. Sorry. Maybe another reason to use events? You can do the same as what you've got but with a 50 mSec timer even instead of a 50msec sleep in a loop. Then keep all of your variables in-thread. Regards Pete
dazz Posted January 17, 2011 Author Report Posted January 17, 2011 I was thinking more of an even like on the offset you are changing or possibly a timer event so you can sample as you do now. Ah, you've perhaps read more than me. I've read most of the Lua manual once, but forgot most of it too! ;-0 No, it only works with strings and numbers. Sorry. Maybe another reason to use events? You can do the same as what you've got but with a 50 mSec timer even instead of a 50msec sleep in a loop. Then keep all of your variables in-thread. Regards Pete Might as well keep it simple with just 3 readings and avoid the need of building a stack or a table, and also calculating the average. I'm testing with 3 readings and it works great already Ok, the timer event sound like a much more elegant solution, thanks for the suggestion. Do I need to worry about thread overlapping if the event is triggered when the previous one has not finished jet?
Pete Dowson Posted January 17, 2011 Report Posted January 17, 2011 Might as well keep it simple with just 3 readings and avoid the need of building a stack or a table, and also calculating the average. I'm testing with 3 readings and it works great already Ok, the timer event sound like a much more elegant solution, thanks for the suggestion. Do I need to worry about thread overlapping if the event is triggered when the previous one has not finished jet? No. The event only executes when you exit. The timer just sets a flag. So, no matter how many timer events occur, you only get entered once if they all pile up because you take a while executing. Regards Pete
dazz Posted January 17, 2011 Author Report Posted January 17, 2011 No. The event only executes when you exit. The timer just sets a flag. So, no matter how many timer events occur, you only get entered once if they all pile up because you take a while executing. Regards Pete Ok, then I guess I'll have to be careful not to overflow the call stack, but it's definitely a nice approach. Thanks again Pete
dazz Posted January 17, 2011 Author Report Posted January 17, 2011 Ok, it's working pretty well already, but I'd like to improve a couple of aspects. 1.- This is really no big deal, and guess there's nothing that can be done about it, but, is there a way to increase the rate at which the axis are polled? as it stands now I get readings slower than I'd like and it makes the throttles a bit jerky, and add some lag 2.- I'm using the 0x66C0 and 0x66D0 offsets at the moment, but I'd like to avoid that just in case someone is using them already, but can't think of a way to do this. Is there a way to pass a parameter to a Lua pluggin so that I assign the throttle axis to it and the pluggin updates a global variable with the new value of the axis? There's probably a better way to do this, so any suggestions are welcome
Pete Dowson Posted January 17, 2011 Report Posted January 17, 2011 1.- This is really no big deal, and guess there's nothing that can be done about it, but, is there a way to increase the rate at which the axis are polled? as it stands now I get readings slower than I'd like and it makes the throttles a bit jerky, and add some lag The default is 50 times a second, which is a *lot* faster than the FS default. It is controlled by the PollInterval value in the main [buttons] section of the INI file. You could speed it up, but if it's too fast I doubt that the Lua could execute fast enough to catch every value received. Are you sure that what you observe isn't a result of the 'delta' value which prevents values which are only slightly different being supplied? You also need to make the Lua program as compact as possible -- each statement is executed with a thread yield between, so the fewer executed the faster it executes as it yields less to other threads. Of course that means other threads (like FS) get less time ... 2.- I'm using the 0x66C0 and 0x66D0 offsets at the moment, but I'd like to avoid that just in case someone is using them already, but can't think of a way to do this. Is there a way to pass a parameter to a Lua pluggin so that I assign the throttle axis to it and the pluggin updates a global variable with the new value of the axis? When you assign an Axis directly to a Lua program execution the Lua program gets the axis value in ipcPARAM. However, that's not really what you want in this case as you should be using events. I could look at providing an assignable control to set ipcPARAM to a given value (the axis in this case) for a specified Lua plugin, a bit like the LuaSet for Lua flags (LuaValue", perhaps). There's probably a better way to do this, so any suggestions are welcome You could try assigning to the normal axes as usual, but then disconnecting them from FS via offset 310A. you can then read the post-calibration values which WOULD have been sent to FS in offsets 3328 ff., and write the resluts of your computations to the relevant FS-actioning offsets. this is how fly-by-wire can be done, which is a similar control-manipulation process. Regards Pete
dazz Posted January 17, 2011 Author Report Posted January 17, 2011 Yeah, I love the 310A thing. I'll do that. Now time to re-read the guide again before I ask any more unnecessary questions, should have noticed the PollInterval is described there, so sorry about that. I'll double check my delta value too I could look at providing an assignable control to set ipcPARAM to a given value (the axis in this case) for a specified Lua plugin, a bit like the LuaSet for Lua flags (LuaValue", perhaps). That would be awesome, if it's something that won't take too long it would be a nice addition Thanks Pete
bojote Posted January 17, 2011 Report Posted January 17, 2011 Hi everyone. I'm working in a script to filter my TQ spikes. It looks like this so far: Hi Dario, I would love to try this! I had my TQ replaced but I still get a bit of noise on the throttles, I hate it when they go to 100% when taxing! annoying. Can you post the final version or send it to jaltuve@gmail.com? Gracias!
dazz Posted January 17, 2011 Author Report Posted January 17, 2011 Hi Dario, I would love to try this! I had my TQ replaced but I still get a bit of noise on the throttles, I hate it when they go to 100% when taxing! annoying. Can you post the final version or send it to jaltuve@gmail.com? Gracias! Hola Jesús! :) This is what I got so far: Throttle_1: ipc.set("old11", -16384) ipc.set("old12", -16384) ipc.writeSW(0x66C0, -16384) while (true) do new1 = ipc.get("old11") new2 = ipc.get("old12") new3 = ipc.readSW(0x66C0) ipc.set("old11", new2) ipc.set("old12", new3) nextV = new3 if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then nextV = new2 end if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then nextV = new1 end nextV = (nextV / 2) + 8192 ipc.control(66420, nextV) ipc.sleep(30) end Throttle_2: ipc.set("old21", -16384) ipc.set("old22", -16384) ipc.writeSW(0x66D0, -16384) while (true) do new1 = ipc.get("old21") new2 = ipc.get("old22") new3 = ipc.readSW(0x66D0) ipc.set("old21", new2) ipc.set("old22", new3) nextV = new3 if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then nextV = new2 end if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then nextV = new1 end nextV = (nextV / 2) + 8192 ipc.control(66423, nextV) ipc.sleep(30) end You'll need to assign your throttles 1 & 2 to offsets 0x66C0 and 0x66D0 via Offset Dword Set and start the Lua pluggins in the Auto section of your 767, as you most than likely know already, but just in case someone else feels like giving it a try. Truth be told, my spiking is not that bad, so if you need a more agressive filtering let me know
dazz Posted January 18, 2011 Author Report Posted January 18, 2011 Next version, using the throttle disconnect offset. Now axes should be normally assigned to throttle 1 & 2 in FSUIPC: Throttle 1: ipc.set("old11", -16384) ipc.set("old12", -16384) while (true) do ipc.writeUB(0x310A, logic.Or(ipc.readUB(0x310A), 64)) new1 = ipc.get("old11") new2 = ipc.get("old12") new3 = ipc.readSW(0x3330) ipc.set("old11", new2) ipc.set("old12", new3) nextV = new3 if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then nextV = new2 end if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then nextV = new1 end nextV = (nextV / 2) + 8192 ipc.writeSW(0x088C, nextV) ipc.sleep(50) end Throttle 2 ipc.set("old21", -16384) ipc.set("old22", -16384) while (true) do ipc.writeUB(0x310A, logic.Or(ipc.readUB(0x310A), 128)) new1 = ipc.get("old21") new2 = ipc.get("old22") new3 = ipc.readSW(0x3332) ipc.set("old21", new2) ipc.set("old22", new3) nextV = new3 if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then nextV = new2 end if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then nextV = new1 end nextV = (nextV / 2) + 8192 ipc.writeSW(0x0924, nextV) ipc.sleep(50) end There's something wrong with this, because it tends to crash the sim very often. It happened also with the previous version, so time to try the event triggered approach Also, post-calibration readings don't seem to be actually calibrated, so I need to do that crappy adjustment to the axis value: nextV = (nextV / 2) + 8192
Pete Dowson Posted January 18, 2011 Report Posted January 18, 2011 There's something wrong with this, because it tends to crash the sim very often. It happened also with the previous version 1. i'd like to know more about that. I don't see anything there which should crash the sim, though the furious use of Globals (which are stored in a separate Lua thread) is, to put in mildly, very unusual and may be exposing a weakness somewhere in the Lua memory management. 2. Since they both run 'forever', why are you using ipc.set and ipc.get to store global copies anyway? There's no need at all. You could just use variables local to that Lua plug-in. It seems to add unnecessary complexity, and will slow it down somewhat. 3. Why two separate plug-ins? Even without tables or stacks you could put all that into one loop, or probably one loop and one local function, called twice each loop, once for each throttle. 4. Reading and writing offset 310A 40 times a second (20 times each, twice) seems a bit over the top when it only needs refreshing once every few seconds. An ideal candidate for a separate time-event called function. Also, post-calibration readings don't seem to be actually calibrated Really? No calibration? So changing thingfs in the calibration tab in FSUIPC makes no difference to the values? Ouch! Can you shown me your FSUIPC INI file please? The values stored should most certainly be post-calibration. There are quite a few applications which depend on that. Maybe you have the NRZ option selected? Folks with Saitek quadrants seem to use that a lot. Maybe that gets you a forward thrust value going from -ve min to +ive max rather than 0 to +ve max ... if so I'll need to fix that. The NRZ option was added much later and this may be an oversight. However, they should still be calibrated, just to the -16k to +16k range used by FS Axis Throttle Set controls for forward thrust, not the 0 - 16k use by the older ThrottleN Set controls for forward thrust. How did you arrive at (nextV / 2) + 8192? That sounds like the input values you see are -16k to +16k, not 0 to 16k, right? What makes them look uncalibrated? Regards Pete
dazz Posted January 18, 2011 Author Report Posted January 18, 2011 1. How are you starting these programs running? via ipcReady.lua? You shouldn't have them assigned to anything, except possibly a button or keypress you use once ot start them if not via ipcReady. For now I'm using a keypress, for debugging purposes 2. Since they run forever, why are you using ipc.set and ipc.get to store global copies?. Thanks for making me look as the idiot I am hahaha (ok, I don't need help with that). Yeah, I totally screwed up there :) Really? Can you shown me your FSUIPC INI file please? The values stored should most certainly be post-calibration. There are quite a few applications which depend on that. Maybe you have the NRZ option selected? Folks with Saitek quadrants seem to use that a lot. Maybe that gets you a forward thrust value going from -ve min to +ive max rather than 0 to +ve max ... if so I'll need to fix that. The NRZ option was added much later and this may be an oversight. Regards Pete I'm not using UseAxisControlsForNRZ. Actually I didn't even have the axes set in the calibration section *blush*, so no wonder the post-calibration offsets' output are not calibrated. I've tested so many configs that I mistakenly thought I had them calibrated via FSUIPC. Again, sorry about that Yes, the axes work like that ( -16K to +16K), and yes, it's an effin saitek TQ. Best advise would be to stay away from saitek stuff actually
dazz Posted January 18, 2011 Author Report Posted January 18, 2011 3. Why two separate plug-ins? Even without tables or stacks you could put all that into one loop, or probably one loop and one local function, called twice each loop, once for each throttle. tried that, but the levers move out of sync 4. Reading and writing offset 310A 40 times a second (20 times each, twice) seems a bit over the top when it only needs refreshing once every few seconds. An ideal candidate for a separate time-event called function. Yes, that's one of the things I had left to try. An independant thread that will do that every 8-9 seconds. Silly question, but just in case. ipc.sleep puts the thread to sleep and it's not an active wait right? or would it be better to use a timer triggered event fot this?
dazz Posted January 18, 2011 Author Report Posted January 18, 2011 Event triggered, same idea. Works great with one axis. when I run the second one it crashes within seconds ipc.set("old11", -16384) ipc.set("old12", -16384) ipc.writeUB(0x310A, logic.Or(ipc.readUB(0x310A), 64)) function throttle1(off, new3) new1 = ipc.get("old11") new2 = ipc.get("old12") nextV = new3 if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then nextV = new2 end if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then nextV = new1 end ipc.set("old11", new2) ipc.set("old12", new3) nextV = (nextV / 2) + 8192 ipc.writeSW(0x088C, nextV) end event.offset(0x3330, "SW", "throttle1") is there something that explains the crashes?
Pete Dowson Posted January 18, 2011 Report Posted January 18, 2011 tried that, but the levers move out of sync Really? Even though you are writing them both at the same time? ipc.sleep puts the thread to sleep and it's not an active wait right? Yes. Your thread will get no time at all until the sleep period expires. It would be daft to put your thread to sleep for 8 seconds -- how will it update the throttle values? ... or would it be better to use a timer triggered event fot this? For everything, yes, as I keep advising. All three of your activitiies can be in one Lua driven by a couple of timer events -- one at 50 mSecs for the two throttles and the other at 8 secs for 310A. regards Pete
dazz Posted January 18, 2011 Author Report Posted January 18, 2011 Really? Even though you are writing them both at the same time?<br><br>It's much smoother with two separate pluggins. Guess it has to do with the yield in between statements<br>It would be daft to put your thread to sleep for 8 seconds -- how will it update the throttle values?<br><br>I was obviously talking about the thread to reset the bits for throttle disconnects, not the one to intercept the throttles<br>All three of your activitiies can be in one Lua driven by a couple of timer events -- one at 50 mSecs for the two throttles and the other at 8 secs for 310A.<br><br>There doesn't seem to be a built-in timer implementation in Lua, nor can I find any info about timers in the documentation or the examples provided. What do you use for a timer please?<br><br>By the way, I keep getting FSUIPC.dll crashes no matter what.<br> <br>On a side note, the script work ok with spikes, but it doesn't help much with noise induced by other levers, and I'm not sure there's nothing a reasonably simple script can do about it
Pete Dowson Posted January 18, 2011 Report Posted January 18, 2011 There doesn't seem to be a built-in timer implementation in Lua, nor can I find any info about timers in the documentation or the examples provided. What do you use for a timer please? The event.timer function, as added in a recent version. Please check the Download Links subforum. I think you must be referring to out of date documentation for the FSUIPC Lua libraries. By the way, I keep getting FSUIPC.dll crashes no matter what. I tried your own Lua programs and even shortened the "sleep" down to 10 mSecs, and it took me 15 minutes of almost constant throttle movement before I could get even one crash, which I am pretty sure was some sort of Lua memory management problem, where it had run out of memory and was tidying up. I'm afraid the core Lua code is not mine and I cannot fix that. The problem is arising anyway because of the wrong use of the global "set" and "get" functions. The inter-thread operations are not at all suited to hight intensity use. You offer no information for me to assist in diagnosing your "FSUIPC.DLL crashes" in any case, so I really don't know what you expect me to do. Sorry. On a side note, the script work ok with spikes, but it doesn't help much with noise induced by other levers, and I'm not sure there's nothing a reasonably simple script can do about it Well, i don't know much about filters, but yours seems less capable, according to my testing, than the built-in Fliter facilities in FSUIPC's calibration pages. Why did you not use those? Regards Pete
dazz Posted January 18, 2011 Author Report Posted January 18, 2011 (edited) The event.timer function, as added in a recent version. Please check the Download Links subforum. I think you must be referring to out of date documentation for the FSUIPC Lua libraries. Ok, I did it again. Should have thought of that. Thanks I tried your own Lua programs and even shortened the "sleep" down to 10 mSecs, and it took me 15 minutes of almost constant throttle movement before I could get even one crash, which I am pretty sure was some sort of Lua memory management problem, where it had run out of memory and was tidying up. I'm afraid the core Lua code is not mine and I cannot fix that. The problem is arising anyway because of the wrong use of the global "set" and "get" functions. The inter-thread operations are not at all suited to hight intensity use. You offer no information for me to assist in diagnosing your "FSUIPC.DLL crashes" in any case, so I really don't know what you expect me to do. Sorry. I have a timer based version ready to test, using local variables so hope that puts an end to the crashes. I'll get back to you with more relevant info if it keeps happenning, but I'm pretty sure everything will be ok Well, i don't know much about filters, but yours seems less capable, according to my testing, than the built-in Fliter facilities in FSUIPC's calibration pages. Why did you not use those? I can't seem to get these Saitek axes working properly via FSUIPC calibration due to the -16K ~ 16K range thing, so I can't use the built in filter. What I could do is to use the calibration to filter the axes, and then intercept the post calibration offset to apply the (nextV / 2) + 8192 correction EDIT: ok, I just needed to check the "No Reverse Zone" option. Damn it, this is embarrasing :) Edited January 18, 2011 by dazz
Pete Dowson Posted January 18, 2011 Report Posted January 18, 2011 I have a timer based version ready to test, using local variables so hope that puts an end to the crashes. I'll get back to you with more relevant info if it keeps happenning, but I'm pretty sure everything will be ok There's one other thing. I think you should only be setting the throttle when it needs changing. Continually writing the same value, whether to the Throttle offset or via ipc.control will both result in lots of unnecessary messages flying about through the Windows message queue. With a complex aircraft that's the last thing you want to do -- there's usually far too many already! Just keep a copy of the last value sent and only send the next when it is different. That'll remove most of the unnecessary stuff going on. I've also just completed changes to provide the direct method of setting ipcPARAM that I hinted at. Basically then all you need to do is assign the axis to "LuaValue xxxx" where xxxx is the name of your ready-running Lua plugin for that throttle, and you can do it all from ipcPARAM. There's also an event.param so it can be properly event driven without bothering with timer adjustments (unless you want to add more sophistication for filtering only fast changes, not slow ones. Here's your Throttle 1 Lua re-written using the new facilities: new1 = -16384 new2 = -16384 prevV = -16384 function param(new3) nextV = new3 if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then nextV = new2 end if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then nextV = new1 end new1 = new2 new2 = new3 if nextV ~= prevV then ipc.control(66420, nextV) prevV = nextV end end event.param("param") You can still calibrate, and set NRZ if you wish, as this sends the Axis Throttle1 Set control just like FS would. Note that "PrevV" is used to stop it sending non-changing values, though in fact this is less necessary because the event.param function will not call the operating function ("param") if ipcPARAM doesn't change. The function doesn't even need to read ipcPARAM because its value is supplied as the parameter to the function. The versions of FSUIPC3 and FSUIPC4 with these facilities should be ready for release tomorrow (Wednesday), or the day after at the latest, I hope. It will also contain new Lua functions: ipc.togglebitsUB, ipc.togglebitsUW, ipc.togglebitsUD ipc.setbitsUB, ipc.setbitsUW, ipc.setbitsUD ipc.clearbitsUB, ipc.clearbitsUW, ipc.clearbitsUD Those will also feature in a revised WideClient. Regards Pete
dazz Posted January 19, 2011 Author Report Posted January 19, 2011 I just added the prevV check and the code looks like this now. I know I could encapsulate things in functions, but it's a bit more compact like this... that and because I'm a lazy bum :P Runs flawlessly, no crashes at all, even though there's no reason left for this anymore but I'll hang on just for the fun of it, and it will help with future scripts ipc.set("old11", -16384) ipc.set("old12", -16384) ipc.set("prev1V", -16384) ... function throttle1(off, new3) new1 = ipc.get("old11") new2 = ipc.get("old12") nextV = new3 if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then nextV = new2 end if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then nextV = new1 end new1 = new2 new2 = new3 new3 = ipc.readSW(0x3330) ipc.set("old11", new2) ipc.set("old12", new3) nextV = new3 if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then nextV = new2 end if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then nextV = new1 end if nextV ~= prev1V then --ipc.control(66420, nextV) ipc.writeSW(0x088C, nextV) prev1V = nextV end end function throttle2(off, new3) ... end function resetBits() ipc.writeUB(0x310A, logic.Or(ipc.readUB(0x310A), 64)) ipc.writeUB(0x310A, logic.Or(ipc.readUB(0x310A), 128)) end event.offset(0x3330, "SW", "throttle1") event.offset(0x3332, "SW", "throttle2") event.timer(5000, "resetBits") resetBits() There's something about the event.param solution that I'm not sure about. Is it shared globally? I mean if I have both axes writing there how do I know what offset fired the event.param? You're also using local variables in an event driven implementation? I would have thought that every time an event triggers the action, it runs in a separate instance... time to test it myself :)
Pete Dowson Posted January 19, 2011 Report Posted January 19, 2011 I just added the prevV check and the code looks like this now. You are still using globals (ipc.get and ipc.set) unnecessarily, though. That makes it a lot jerkier than it need to be, because every get and every set is a multi-threaded synching operation -- it actually has to get and put the values from/to a separate thread, every single access! All you need to do is replace the global references by direct variable names. i.e. old11 = -16384 old12 = -16384 prev1V = -16384 etc, throughout. There's something about the event.param solution that I'm not sure about. Is it shared globally? I mean if I have both axes writing there how do I know what offset fired the event.param? The parameter it refers to being changed is the ipcPARAM specific to this current plug-in. It isn't a shared global accessed via get and set. You obviously would need to have separate plug-ins for each throttle if using the "param" method. with your method you could combine the throttle actions for all throttles into one plug-in using tables. But not using ipcPARAM because you can't tell which throttle sent it. You're also using local variables in an event driven implementation? I would have thought that every time an event triggers the action, it runs in a separate instance... time to test it myself :) No, you are misunderstanding the whole advantage of the event methods. The fact that you've established one or more events keeps the plug-in loaded, ready-compiled and ready to run. It is merely 'sleeping', with its event functions being called as needed according to the events defined. It's truly like adding code to FSUIPC. If, in the functions, you eventually cancel all outstanding events (via event.cancel), only then is the plug-in "unplugged". Regards Pete
dazz Posted January 19, 2011 Author Report Posted January 19, 2011 (edited) True, I misunderstood your first post where you clearly stated that in an event triggered solution the plug-in would be always there and running on demand Does this mean that a single thread is serving both events the same way it would with a sleep clause? If that's the case I think it's better to run each throttle in a separate pluggin EDIT: I put some ipc.log lines in both functions and it looks like it's actually a single thread Is that the reason why there can only be one timer per pluggin? Is the timer function also running in the same thread? Logs seem to confirm that also EDIT2: I simplified the code: old2 = -16384 function throttle2(off, newV) nextV = ipc.readSW(0x3332) if not (newV > nextV and newV > old2) and not (newV < nextV and newV < old2) then nextV = newV end ipc.writeSW(0x0924, nextV) old2 = nextV end event.offset(0x3332, "SW", "throttle2") In the event driven version I don't really need to check if the previous value equals the new one, since the function is called when the lever is actioned so most of the times it will be a new value. I'm not polling the axis anymore, so I can skip that and make the code simpler. I also store the filtered value as the "old" one, so if a reading is discarded as a probable spike, it won't be used for further calculations. This "old" or previous value is compared to the one that triggered the event (newV) and a new reading (nextV). The new reading is to make sure that the last value is not unnecessarily discarded, so in normal conditions, the last time the event is triggered (when the lever is realeased) nextV and newV will be the same. I have another pluggin for the throttle2 and a third one for the axes disconnects. With ipcParam I'll get rid of the last one since I won't need to assign the throttles to the axes, but to the Lua pluggins instead Edited January 19, 2011 by dazz
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now