shorthauler Posted February 9 Report Posted February 9 I have a home cokcpit where I can set the standby frequencies using Event IDs. The C-47 by Manfred Jahn and others does not have standby frequencies. You are tuning the active radio (Coms and Navs). I a seeing it correctly that there is no Event ID for the active frequencies only for the standbys, so I will have to program a lua script? Best, shorthauler
John Dowson Posted February 10 Report Posted February 10 11 hours ago, shorthauler said: I a seeing it correctly that there is no Event ID for the active frequencies only for the standbys, so I will have to program a lua script? Of course there are events for active frequencies, e.g. 65707 COM_RADIO_SET 65708 NAV1_RADIO_SET 65636 COM_RADIO_WHOLE_DEC 65637 COM_RADIO_WHOLE_INC 65638 COM_RADIO_FRACT_DEC 65639 COM_RADIO_FRACT_INC 65640 NAV1_RADIO_WHOLE_DEC 65641 NAV1_RADIO_WHOLE_INC 65642 NAV1_RADIO_FRACT_DEC 65643 NAV1_RADIO_FRACT_INC 66434 COM_RADIO_FRACT_DEC_CARRY 66435 COM_RADIO_FRACT_INC_CARRY 66445 NAV1_RADIO_FRACT_DEC_CARRY 66446 NAV1_RADIO_FRACT_INC_CARRY 67361 COM1_RADIO_HZ_SET 68064 COM1_8333HZ_MODE_TOGGLE 68065 COM1_8333HZ_MODE_SET etc Basically you have all the same events on active frequencies as with standby.
shorthauler Posted February 10 Author Report Posted February 10 Hm, these are the onese that I am using: 65640 NAV1_RADIO_WHOLE_DEC 65641 NAV1_RADIO_WHOLE_INC 65642 NAV1_RADIO_FRACT_DEC 65643 NAV1_RADIO_FRACT_INC But they only change the standby frequency in the background (invisible, because just one Nav radio in the DC 3, no standby display). How do I know this? I have a frequency ("frequency 1") in the active (only) frequency display, I toggle via FSUIPC, I then have another frequency ("frequency 2") in the display. I dial my rotary encoders, "frequency 2" remains unchanged. I toggle again and "frequency 1" is back in the display, but this time modified according to how I have turned the dials.
John Dowson Posted February 10 Report Posted February 10 I guess it makes sense that the WHOLE / FRACT events control the standby, as there are no stnby equivalents...sorry about that. To set the active frequency directly, you would need to use the NAV1_RADIO_SET control, or write the new frequency (in BCD format) to offset 0x0350.
shorthauler Posted February 11 Author Report Posted February 11 Thank you for your reply. Do I understand correctly that using the NAV1_RADIO_SET control, one would send a frequency (for example one that has been generated in a Lua script) directly to the radio, without "turning the dials"?
John Dowson Posted February 11 Report Posted February 11 2 hours ago, shorthauler said: Do I understand correctly that using the NAV1_RADIO_SET control, one would send a frequency (for example one that has been generated in a Lua script) directly to the radio, without "turning the dials"? Well, the NAV1_RADIO_SET control will send the new frequency to the FS, but you need to trigger this and that would normally be done on a rotary button, i.e. when turning the dial. You could have a lua script that knows the current NAV1 frequency (i.e. via an event callback on offset 0x0350), and the lua script would also wait to be triggered using event.param. The rotary buttons can then be assigned to LuaValue to trigger the lua event.param callback function (with the parameter indicating an increment or decrement, or maybe both fast/slow inc/decs if you have fast/slow buttons), and in the event.param handling function/callback, you would take the current NAV1 frequency and then increment/decrement this value before sending to the FS. Note that NAV1_RADIO_SET takes BCD16 format, whereas NAV1_RADIO_SET_HZ takes a Hz value. Probably better to convert the current BCD NAV1 frequency (from offset 0x0350) to HZ before changing and send on using NAV1_RADIO_SET_HZ.
shorthauler Posted February 15 Author Report Posted February 15 Thank you very much, I tried this, but no luck: oldNav1 = ipc.readUW(0350) newNav1 = oldNav1 +100 function Nav1plus(param) ipc.writeLvar("L:NAV1_RADIO_SET", newNav1) end event.param ("Nav1plus") This is what I get in the log: ********* LUA: "C-47 Radios" Log [from FSUIPC version 4.977] ********* 7576015 System time = 15/02/2025 20:28:31, Simulator time = 13:45:33 (19:45Z) 7576015 LUA: beginning "E:\FSX\Flight Simulator X\Modules\C-47 Radios.lua" 7576031 >>> Thread forced exit (ipc.exit or os.exit) <<< 7576031 System time = 15/02/2025 20:28:31, Simulator time = 13:45:33 (19:45Z) ********* LUA execution terminated: Log Closed ********* Any idea what I could try that might work?
John Dowson Posted February 16 Report Posted February 16 12 hours ago, shorthauler said: This is what I get in the log: ********* LUA: "C-47 Radios" Log [from FSUIPC version 4.977] ********* 7576015 System time = 15/02/2025 20:28:31, Simulator time = 13:45:33 (19:45Z) 7576015 LUA: beginning "E:\FSX\Flight Simulator X\Modules\C-47 Radios.lua" 7576031 >>> Thread forced exit (ipc.exit or os.exit) <<< 7576031 System time = 15/02/2025 20:28:31, Simulator time = 13:45:33 (19:45Z) ********* LUA execution terminated: Log Closed ********* Any idea what I could try that might work? That log shows the lua exited16ms after it was started. How are you starting/stopping this lua? The lua didn't actually run and was killed during start-up... Also, the lua scrip is incorrect. As I said, 0ffset 0x0350 is in BCD format. Do, as an example, if the NAV1 frequency is 123.45, then that offset holds 0x2345, so when you read that as a decimal you will get 9029. Add 100, you get 9129, which is 0x23A9, i.e. a frequency of 123.A9, which is incorrect. There are also other issues. For speed you should have this lua auto-started and wait for the parameter event to be triggered, but you need to get the current value and increment it within the callback/handling function. You are not doing this and are just sending the same value in each parameter event... If you want further help, please attach the lua script, and your FSUIPC4.log and FSUIPC4.ini files. Please turn off log lua separately, and turn on logging for lua plugins and Buttons & Switches before generating the log file. John
shorthauler Posted February 16 Author Report Posted February 16 Hi John, These are the files, please let me know if something is missing. The script is triggered by a joystick button (for testing purposes) and should only increase the frequency by 1 MHz. Decreasing and kHz should follow once this works. Best, shorthauler This should be my script: oldNav1 = ipc.readUW(0350) => reading the offset newNav1_string = string.format(oldNav1, 0xaf) => converting the HEX value to a string newNav1_string_shortened = string.sub(newNav1_string, 3) => starting from the 3rd digit of the string, thereby cutting the first two digits from the string newNav1 = tonumber (newNav1_string_shortened) => converting the string to a (decimal) integer newNav1_Hz = newNav1*10000 => multiplying with 10^4 to obtain herz, newNav1_value = newNav1_Hz+1000000 => adding 1^6 Hz = 1 MHz ipc.writeLvar("L:NAV1_RADIO_SET_HZ", newNav1_value) => sending the result to FSX Files C-47 Radios.zip
John Dowson Posted February 17 Report Posted February 17 You could always try debugging this yourself....if you look in the log, you will see: Quote 161906 *** LUA Error: E:\FSX\Flight Simulator X\Modules\C-47 Radios.lua:10: attempt to perform arithmetic on global 'newNav1' (a nil value) This is also incorrect: Quote oldNav1 = ipc.readUW(0350) and should be either: oldNav1 = ipc.readUW(0x0350) or oldNav1 = ipc.readUW("0350") And this is wrong: Quote ipc.writeLvar("L:NAV1_RADIO_SET_HZ", newNav1_value) => sending the result to FSX I am pretty confident that there is no such lvar as NAV1_RADIO_SET_HZ. You should either write the new frequency to offset 0x0350 (so that is correct when in BCD) or use the (key) control NAV1_RADIO_SET_HZ (67251) via ipc.control. Your string.format is also incorrect.... Try something like: currentNav1 = ipc.readUW(0x0350) -- read the current NAV1 frequency currentNav1Nav1_string = "1" .. string.format("%04X", currentNav1Nav1) -- get frequenct as a string newNav1 = currentNav1Nav1_string + 100 -- lua has lazy types and will convert the string to a decimal and we increment by 1MHz newNav1Hz = newNav1*10000 -- convert to HZ ipc.control(67251, newNav1Hz) -- send to frequency to sim John
shorthauler Posted February 19 Author Report Posted February 19 Thank you very much. Does NAV1_RADIO_SET_HZ (67251) work for FSX? I am under the impression that it is only available for MSFS. For FSX, I have found NAV1 RADIO SET 65708, but I was not able to find an explication what it actually does. The script works as it sends the parameters to the values as I take from the FSUIPC log file: 8469032 [Buttons] 4=P2,4,CL18:R,0 8469110 FS Control Sent: Ctrl=67251, Param=118200000 8469313 Button changed: bRef=0, Joy=2, Btn=4, Released But there is no change in FSX. Same for 65708. Best, shorthauler Files C-47 Radios.zip
John Dowson Posted February 19 Report Posted February 19 1 hour ago, shorthauler said: Thank you very much. Does NAV1_RADIO_SET_HZ (67251) work for FSX? I am under the impression that it is only available for MSFS. Sorry, didn't realise (or forgot) that you were using FSX/FSUIPC4, No, it is not available - you should use NAV1_RADIO_SET (65708) instead. That takes the frequency in BCD format. 1 hour ago, shorthauler said: For FSX, I have found NAV1 RADIO SET 65708, but I was not able to find an explication what it actually does. Sets the chosen NAV frequency (BCD16 encoded Hz). 1 hour ago, shorthauler said: Same for 65708. But you cannot just change 67251 to 65708 and expect the script to work. You need to change the parameter to BCD format, or to an integer than when converted to hex shows the frequency in BCD format (with leading 1 dropped). Try and do that yourself - use logging to check that you are sending the correct parameter. If you have difficulties I can look at it for you, but you should at least try. I do not have much free time for these type of things at the moment.... John
John Dowson Posted February 19 Report Posted February 19 This may help - a lua function to convert a decimal frequency, in MHz not Hz) to BCD16: -- Convert frequency to BCD (e.g., "113.45" → 0x1345) function convertToBCD(freq) local cleanFreq = freq:gsub("%.", "") -- Remove decimal (e.g., "109.2" → "0920") local decimalNumber = tonumber(cleanFreq) -- Convert to number if not decimalNumber then return 0 end -- Return 0 if conversion fails local bcd = 0 local shift = 0 -- Convert each decimal digit to BCD format while decimalNumber > 0 do local digit = decimalNumber % 10 bcd = bcd + (digit * (16 ^ shift)) -- Use base 16 shift instead of bitwise left shift decimalNumber = math.floor(decimalNumber / 10) shift = shift + 1 end return bcd end John
shorthauler Posted February 22 Author Report Posted February 22 A quick update - I now have a working lua script. As I am still in the "lab phase" (experimenting), I am using a button to trigger. And so far I only increase the kHz. Decreasing the frequency, also Hz, using rotary encoders will follow later. Also, the kHz will increase until the limit of 117 and then do not not wrap around, this also needs to be sorted. But so far, I am quite happy. Thanks a lot, John! Will post the whole script when ready. currentNav1 = ipc.readUW(0x0350) -- read the current NAV1 frequency currentNav1_string = "1" .. string.format("%04X", currentNav1) -- convert decimal to string (maybe superflous as the next line will treat the string as a number) newNav1 = currentNav1_string + 100 -- lua has lazy types and will convert the string to a decimal and we increment by 1MHz newNav1_string =tostring(newNav1) -- converting the decimal to a string, so that the leading 1 can be cut newNav1_cut = newNav1_string:sub(2,-1) -- cutting the leading one function convertToBCD(freq) local cleanFreq = freq:gsub("%.", "") -- Remove decimal (e.g., "109.2" → "0920") local decimalNumber = tonumber(cleanFreq) -- Convert to number if not decimalNumber then return 0 end -- Return 0 if conversion fails local bcd = 0 local shift = 0 -- Convert each decimal digit to BCD format while decimalNumber > 0 do local digit = decimalNumber % 10 bcd = bcd + (digit * (16 ^ shift)) -- Use base 16 shift instead of bitwise left shift decimalNumber = math.floor(decimalNumber / 10) shift = shift + 1 end return bcd end newNav1_BCD = convertToBCD(newNav1_cut) -- calling the function suggested by John ipc.control(65708, newNav1_BCD) -- sending the BCD to FSX
shorthauler Posted March 1 Author Report Posted March 1 For possible further reference, this is the function as it stands now. I am using it with MobiFlight's "FUSIPC - Lua Macro" function that sends values to offset 0x0D6C. Depending on which encoder is turned in what direction, different values are sent that are triggering different operations to increase/decreas MHz/kHz. FSX EventIDs would only manipulate the standby frequencies that can then be swapped with the active frequency. Vintage aircraft do not have standby radios, so this script was needed for my home cockpit to manipulate the active frequency directly. A big thanks to John for all his help. Comments, especially corrections, are most welcome. feed_value = ipc.readUB(0x0D6C) -- depending on which rotary encoder is turned and into which direction, MobiFlight sends a feed value to offset 0x0D6C if feed_value==10 then -- if turned right, the left encoder (MHz) sends the value 10 to offset 0x0D6C currentNav1 = ipc.readUW(0x0350) -- read the current NAV1 frequency currentNav1_string = "1" .. string.format("%04X", currentNav1) -- convert decimal to string currentNav1_string_number = tonumber(currentNav1_string) -- convert string to number if currentNav1_string_number >= 11700 -- the following lines increase the MHz value by 1 MHz and wrap the frequency around, substracting 900, when 117 MHz is reached then newNav1 = currentNav1_string_number - 900 else newNav1 = currentNav1_string_number + 100 end newNav1_string =tostring(newNav1) -- converting the decimal to a string, so that the leading 1 can be cut newNav1_cut = newNav1_string:sub(2,-1) -- cutting the leading 1 elseif feed_value==20 then -- if turned left, the left encoder (MHz) sends the value 20 to offset 0x0D6C currentNav1 = ipc.readUW(0x0350) currentNav1_string = "1" .. string.format("%04X", currentNav1) currentNav1_string_number = tonumber(currentNav1_string) if currentNav1_string_number <= 10895 -- the following lines decrease the MHz value by 1 MHz and wrap the frequency around, adding 900, when 108.95 MHz is reached then newNav1 = currentNav1_string_number + 900 else newNav1 = currentNav1_string_number - 100 end newNav1_string =tostring(newNav1) newNav1_cut = newNav1_string:sub(2,-1) elseif feed_value==30 then -- if turned right, the right encoder (kHz) sends the value 30 to offset 0x0D6C currentNav1 = ipc.readUW(0x0350) currentNav1_string = "1" .. string.format("%04X", currentNav1) currentNav1_string_number = tonumber(currentNav1_string) if currentNav1_string_number == 11795 -- the following lines increase the kHz value by 50 kHz and wrap the frequency around, substracting 9995, when 117.95 MHz is reached then newNav1 = currentNav1_string_number - 9995 else newNav1 = currentNav1_string_number + 5 end newNav1_string =tostring(newNav1) newNav1_cut = newNav1_string:sub(2,-1) else -- if turned left, the right encoder (kHz) sends the value 40 to offset 0x0D6C, which for now is "else" currentNav1 = ipc.readUW(0x0350) currentNav1_string = "1" .. string.format("%04X", currentNav1) currentNav1_string_number = tonumber(currentNav1_string) if currentNav1_string_number == 10800 -- the following lines decrease the kHz value by 50 kHz and wrap the frequency around, adding 9995, when 108.00 MHz is reached then newNav1 = currentNav1_string_number + 9995 else newNav1 = currentNav1_string_number - 5 end newNav1_string =tostring(newNav1) newNav1_cut = newNav1_string:sub(2,-1) end function convertToBCD(freq) -- function to convert to BCD local cleanFreq = freq:gsub("%.", "") -- Remove decimal (e.g., "109.2" → "0920") local decimalNumber = tonumber(cleanFreq) -- Convert to number if not decimalNumber then return 0 end -- Return 0 if conversion fails local bcd = 0 local shift = 0 -- Convert each decimal digit to BCD format while decimalNumber > 0 do local digit = decimalNumber % 10 bcd = bcd + (digit * (16 ^ shift)) -- Use base 16 shift instead of bitwise left shift decimalNumber = math.floor(decimalNumber / 10) shift = shift + 1 end return bcd end newNav1_BCD = convertToBCD(newNav1_cut) -- calling the function ipc.control(65708, newNav1_BCD) -- sending BCD to FSUIPC
shorthauler Posted March 4 Author Report Posted March 4 Improved script. You can now turn the encoder for the kHz value completey seperately from the encoder for MHz. For example, if you reach "111.00" and continue decreasing the kHz value, you will get 111.95, not 110.95. feed_value = ipc.readUB(0x0D6C) -- depending on which rotary encoder is turned and into which direction, MobiFlight sends a feed value to offset 0x0D6C if feed_value==10 then -- if turned right, the left encoder (MHz) sends the value 10 to offset 0x0D6C currentNav1 = ipc.readUW(0x0350) -- read the current NAV1 frequency currentNav1_string = "1" .. string.format("%04X", currentNav1) -- convert decimal to string currentNav1_string_number = tonumber(currentNav1_string) -- convert string to number if currentNav1_string_number >= 11700 -- the following lines increase the MHz value by 1 MHz and wrap the frequency around, substracting 900, when 117 MHz is reached then newNav1 = currentNav1_string_number - 900 else newNav1 = currentNav1_string_number + 100 end newNav1_string =tostring(newNav1) -- converting the decimal to a string, so that the leading 1 can be cut newNav1_cut = newNav1_string:sub(2,-1) -- cutting the leading 1 elseif feed_value==20 then -- if turned left, the left encoder (MHz) sends the value 20 to offset 0x0D6C currentNav1 = ipc.readUW(0x0350) currentNav1_string = "1" .. string.format("%04X", currentNav1) currentNav1_string_number = tonumber(currentNav1_string) if currentNav1_string_number <= 10895 -- the following lines decrease the MHz value by 1 MHz and wrap the frequency around, adding 900, when 108.95 MHz is reached then newNav1 = currentNav1_string_number + 900 else newNav1 = currentNav1_string_number - 100 end newNav1_string =tostring(newNav1) newNav1_cut = newNav1_string:sub(2,-1) elseif feed_value==30 then -- if turned right, the right encoder (kHz) sends the value 30 to offset 0x0D6C currentNav1 = ipc.readUW(0x0350) currentNav1_string = "1" .. string.format("%04X", currentNav1) currentNav1_string_number = tonumber(currentNav1_string) if string.find(currentNav1_string, "%d%d%d95") -- this line checks whether the frequency ends with 95 and ... then newNav1 = currentNav1_string_number - 95 -- ... if so, substractss 95 kHz so as to prevent the frequency from carrying (changing the MHz value) when digit wraps. So you can turn the encoder for the kHz value seperately without increasing the MHz value. else newNav1 = currentNav1_string_number + 5 end newNav1_string =tostring(newNav1) newNav1_cut = newNav1_string:sub(2,-1) else -- if turned left, the right encoder (kHz) sends the value 40 to offset 0x0D6C, which for now is "else" currentNav1 = ipc.readUW(0x0350) currentNav1_string = "1" .. string.format("%04X", currentNav1) currentNav1_string_number = tonumber(currentNav1_string) if string.find(currentNav1_string, "%d%d%d00") -- this line checks whether the frequency ends with 00 and ... then newNav1 = currentNav1_string_number + 95 -- ... if so, adds 95 kHz so as to prevent the frequency from carrying (changing the MHz value) when digit wraps. So you can turn the encoder for the kHz value seperately without decreasing the MHz value. else newNav1 = currentNav1_string_number - 5 end newNav1_string =tostring(newNav1) newNav1_cut = newNav1_string:sub(2,-1) end function convertToBCD(freq) -- function to convert to BCD local cleanFreq = freq:gsub("%.", "") -- Remove decimal (e.g., "109.2" → "0920") local decimalNumber = tonumber(cleanFreq) -- Convert to number if not decimalNumber then return 0 end -- Return 0 if conversion fails local bcd = 0 local shift = 0 -- Convert each decimal digit to BCD format while decimalNumber > 0 do local digit = decimalNumber % 10 bcd = bcd + (digit * (16 ^ shift)) -- Use base 16 shift instead of bitwise left shift decimalNumber = math.floor(decimalNumber / 10) shift = shift + 1 end return bcd end newNav1_BCD = convertToBCD(newNav1_cut) -- calling the function ipc.control(65708, newNav1_BCD) -- sending BCD to FSUIPC
John Dowson Posted March 5 Report Posted March 5 The script looks overly complicated to me...not sure you need to be adding/removing the leading 1 so often, and rather convert to string to add/remove, you can just add (or remove) 10000 to the string value, and as lua is non-strict on types, you can just be lazy when adding/subtracting. i.e rather than: currentNav1 = ipc.readUW(0x0350) -- read the current NAV1 frequency currentNav1_string = "1" .. string.format("%04X", currentNav1) -- convert decimal to string currentNav1_string_number = tonumber(currentNav1_string) -- convert string to number if currentNav1_string_number >= 11700 -- the following lines increase the MHz value by 1 MHz and wrap the frequency around, substracting 900, when 117 MHz is reached then newNav1 = currentNav1_string_number - 900 else newNav1 = currentNav1_string_number + 100 end newNav1_string =tostring(newNav1) -- converting the decimal to a string, so that the leading 1 can be cut newNav1_cut = newNav1_string:sub(2,-1) -- cutting the leading 1 simpler would be currentNav1BCD = ipc.readUW(0x0350) -- read the current NAV1 frequency currentNav1 = string.format("%04X", currentNav1BCD) -- convert BCD to number (as string) -- the following lines increase the MHz value by 1 MHz and wrap the frequency around, substracting 900, when 117 MHz is reached if tonumber(currentNav1) >= 1700 then newNav1_cut = currentNav1 - 900 -- currentNav1 will be converted to a number implicitly else newNav1_cut = currentNav1 + 100 end -- -- etc -- Then to send: newNav1_BCD = convertToBCD(tostring(newNav1_cut)) -- convert to string before calling function ipc.control(65708, newNav1_BCD) -- sending BCD to FSUIPC Not a big deal though - just FYI. Also, even though the aircraft does not have standby frequencies, they are most probably still available in the model. So what you can also do, which may be easier, is: 1. Set standby frequency to be the same as the active frequency 2. Inc/dec the standby frequency as desired using the standard FS controls 3. swap the active/standby You can even compress 1 & 2 and just read the current active frequency (in Hz as easier!), change the value to the new required frequency, set that as the standby frequency and then swap. Regards, John P.S. Also a good idea to declare your function(s) at the top of the script and mot embedded in the logic - this aids readability!
John Dowson Posted March 5 Report Posted March 5 To be clear, something like the following, although this is untested: -- -- function to convert to BCD -- function convertToBCD(freq) local cleanFreq = freq:gsub("%.", "") -- Remove decimal (e.g., "109.2" → "0920") local decimalNumber = tonumber(cleanFreq) -- Convert to number if not decimalNumber then return 0 end -- Return 0 if conversion fails local bcd = 0 local shift = 0 -- Convert each decimal digit to BCD format while decimalNumber > 0 do local digit = decimalNumber % 10 bcd = bcd + (digit * (16 ^ shift)) -- Use base 16 shift instead of bitwise left shift decimalNumber = math.floor(decimalNumber / 10) shift = shift + 1 end return bcd end feed_value = ipc.readUB(0x0D6C) -- depending on which rotary encoder is turned and into which direction, MobiFlight sends a feed value to offset 0x0D6C currentNav1BCD = ipc.readUW(0x0350) -- read the current NAV1 frequency currentNav1 = string.format("%04X", currentNav1BCD) -- convert BCD to number (as string) if feed_value==10 then -- if turned right, the left encoder (MHz) sends the value 10 to offset 0x0D6C -- the following lines increase the MHz value by 1 MHz and wrap the frequency around, substracting 900, when 117 MHz is reached if tonumber(currentNav1) >= 1700 then newNav1 = currentNav1 - 900 -- currentNav1 will be converted to a number else newNav1 = currentNav1 + 100 end elseif feed_value==20 then -- if turned left, the left encoder (MHz) sends the value 20 to offset 0x0D6C -- the following lines decrease the MHz value by 1 MHz and wrap the frequency around, adding 900, when 108.95 MHz is reached if tonumber(currentNav1) <= 895 then newNav1 = currentNav1 + 900 -- currentNav1 will be converted to a number else newNav1 = currentNav1 - 100 end elseif feed_value==30 then -- if turned right, the right encoder (kHz) sends the value 30 to offset 0x0D6C if string.find(currentNav1, "%d%d95") then -- this line checks whether the frequency ends with 95 and ... newNav1 = currentNav1 - 95 -- ... if so, substractss 95 kHz so as to prevent the frequency from carrying (changing the MHz value) when digit wraps. So you can turn the encoder for the kHz value seperately without increasing the MHz value. else newNav1 = currentNav1 + 5 end else -- if turned left, the right encoder (kHz) sends the value 40 to offset 0x0D6C, which for now is "else" if string.find(currentNav1, "%d%d00") then -- this line checks whether the frequency ends with 00 and ... newNav1 = currentNav1 + 95 -- ... if so, adds 95 kHz so as to prevent the frequency from carrying (changing the MHz value) when digit wraps. So you can turn the encoder for the kHz value seperately without decreasing the MHz value. else newNav1 = currentNav1 - 5 end end newNav1_BCD = convertToBCD(tostring(newNav1)) -- convert to BCD ipc.control(65708, newNav1_BCD) -- sending BCD to FSUIPC John
shorthauler Posted March 5 Author Report Posted March 5 Thanks a lot, John. Yes this does work. I am pasting in an adapted script for the COM radio, reflecting the 25 kHz spacing. Trivia alert: With the 25 kHz spacing, the trailing 5 in the simulated radio dial is actually truncated, so the last digits will be 0, 2, 5 or 7. It's still found in FSX but has been replaced in real life by a 8.33 kHz spacing. -- -- function to convert to BCD -- function convertToBCD(freq) local cleanFreq = freq:gsub("%.", "") local decimalNumber = tonumber(cleanFreq) if not decimalNumber then return 0 end local bcd = 0 local shift = 0 while decimalNumber > 0 do local digit = decimalNumber % 10 bcd = bcd + (digit * (16 ^ shift)) decimalNumber = math.floor(decimalNumber / 10) shift = shift + 1 end return bcd end feed_value = ipc.readUB(0x0D6C) currentComBCD = ipc.readUW(0x034E) currentCom = string.format("%04X", currentComBCD) if feed_value==22 then if tonumber(currentCom) >= 3600 then newCom = currentCom - 1800 else newCom = currentCom + 100 end elseif feed_value==12 then if tonumber(currentCom) <= 1897 then newCom = currentCom + 1800 else newCom = currentCom - 100 end elseif feed_value==42 then -- the following lines reflect the 25 kHz spacing (found in FSX, but in real life nowadays superseded by a 8.33 kHz spacing) if string.find(currentCom, "%d%d97") then newCom = currentCom - 97 elseif string.find(currentCom, "%d%d%d7") then newCom = currentCom + 3 elseif string.find(currentCom, "%d%d%d2") then newCom = currentCom + 3 elseif string.find(currentCom, "%d%d%d0") then newCom = currentCom + 2 else newCom = currentCom + 2 end else if string.find(currentCom, "%d%d00") then newCom = currentCom + 97 elseif string.find(currentCom, "%d%d%d7") then newCom = currentCom - 2 elseif string.find(currentCom, "%d%d%d2") then newCom = currentCom - 2 elseif string.find(currentCom, "%d%d%d0") then newCom = currentCom - 3 else newCom = currentCom - 3 end end newCom_BCD = convertToBCD(tostring(newCom)) -- convert to BCD ipc.control(65707, newCom_BCD) -- sending BCD to FSUIPC
shorthauler Posted March 6 Author Report Posted March 6 Unfortunately, these scripts react rather slowly and it seems to me that they also make FSX freeze after a while. Can't say whether this is because I am using MobiFlight for my hardware (not the fastest to process inputs) or because I am feeding values through MobiFlight to 0X0D6C to indicate which encoder is being turned into what direction. I will have to set up other hardware (Stream Deck buttons) for comparison.
John Dowson Posted March 6 Report Posted March 6 Yes, I thought there might be performance issues... When a lua script is ran, the thread has to be created and the script compiled before it can be executed, This gives an overhead of 50ms+ (depending on hardware and available resources). When a lua script is triggered via a rotary (or on button/key repeat) the calls to start the lua can come before the previous lua has finished, and when this happens the previous lua invocation is killed and the next one started. This can result in nothing happening (as the scrip is continually being killed before it does anything) and a backlog of dying threads consuming resources. There are two things that you can do about this. The first, is to adjust/increase the LuaRerunDelay ini parameter. Default value is 66 - try incrementing by 20 until you reach a value where it works smoothly (although probably too slow...). You could also try setting the LuaAffinityMask ini parameter (undocumented) to an affinity mask to move lua thread execution off of the main core which may improve performance and allow a lower value to be used for the LuaRerunDelay ini parameter. The second, and better solution, would be to re-write the lua script to have it always running and re-act to events, which removes the thread creation and lua compilation overhead. It looks like you are currently writing a 'feed value' to offset 0x0D6C and then running the script which reads this value. Rather than doing this, you can have the script auto-ran, and rather than start the script with the Lua command, you send it the feed value using the LuaValue command. To auto-tun the script, you use the [Auto] (or profile specific [Auto.xxx]) ini file section - see the Advanced User guide, Here is the previous script adapted to be triggered via the LueValue command. -- -- function to convert to BCD -- function convertToBCD(freq) local cleanFreq = freq:gsub("%.", "") -- Remove decimal (e.g., "109.2" → "0920") local decimalNumber = tonumber(cleanFreq) -- Convert to number if not decimalNumber then return 0 end -- Return 0 if conversion fails local bcd = 0 local shift = 0 -- Convert each decimal digit to BCD format while decimalNumber > 0 do local digit = decimalNumber % 10 bcd = bcd + (digit * (16 ^ shift)) -- Use base 16 shift instead of bitwise left shift decimalNumber = math.floor(decimalNumber / 10) shift = shift + 1 end return bcd end function updateNav1(feed_value) currentNav1BCD = ipc.readUW(0x0350) -- read the current NAV1 frequency currentNav1 = string.format("%04X", currentNav1BCD) -- convert BCD to number (as string) if feed_value==10 then -- if turned right, the left encoder (MHz) sends the value 10 to offset 0x0D6C -- the following lines increase the MHz value by 1 MHz and wrap the frequency around, substracting 900, when 117 MHz is reached if tonumber(currentNav1) >= 1700 then newNav1 = currentNav1 - 900 -- currentNav1 will be converted to a number else newNav1 = currentNav1 + 100 end elseif feed_value==20 then -- if turned left, the left encoder (MHz) sends the value 20 to offset 0x0D6C -- the following lines decrease the MHz value by 1 MHz and wrap the frequency around, adding 900, when 108.95 MHz is reached if tonumber(currentNav1) <= 895 then newNav1 = currentNav1 + 900 -- currentNav1 will be converted to a number else newNav1 = currentNav1 - 100 end elseif feed_value==30 then -- if turned right, the right encoder (kHz) sends the value 30 to offset 0x0D6C if string.find(currentNav1, "%d%d95") then -- this line checks whether the frequency ends with 95 and ... newNav1 = currentNav1 - 95 -- ... if so, substractss 95 kHz so as to prevent the frequency from carrying (changing the MHz value) when digit wraps. So you can turn the encoder for the kHz value seperately without increasing the MHz value. else newNav1 = currentNav1 + 5 end else -- if turned left, the right encoder (kHz) sends the value 40 to offset 0x0D6C, which for now is "else" if string.find(currentNav1, "%d%d00") then -- this line checks whether the frequency ends with 00 and ... newNav1 = currentNav1 + 95 -- ... if so, adds 95 kHz so as to prevent the frequency from carrying (changing the MHz value) when digit wraps. So you can turn the encoder for the kHz value seperately without decreasing the MHz value. else newNav1 = currentNav1 - 5 end end newNav1_BCD = convertToBCD(tostring(newNav1)) -- convert to BCD ipc.control(65708, newNav1_BCD) -- sending BCD to FSUIPC end event.param("updateNav1") ipc.log("Nav1 ypdate lua script now running") John
shorthauler Posted March 6 Author Report Posted March 6 Thanks a lot, John. This sort of works. I might have found a way to send values via Mobiflight to scripts via the LuaValue function (which I think is undocumented, I will write later about this). But the Value only increases 100 up and further input (I tried my encoders but also a joystick button) do not further increase the value, same with decreasing. It stops after a decrease of 100. I will try to look into this later.
John Dowson Posted March 7 Report Posted March 7 15 hours ago, shorthauler said: I might have found a way to send values via Mobiflight to scripts via the LuaValue function (which I think is undocumented, I will write later about this). LueValue is documented in the Lua Plug-ins document, and also mentioned in the event.param documentation in the Lua Library document. I can see that the LuaValue is missing from the list of valid controls in the documentation for offset 0x0D70, but I think this is an omission error - it is certainly available. So you can use that offset to trigger the LuaValue via MobiFlight if you want to do it that way. 15 hours ago, shorthauler said: But the Value only increases 100 up and further input (I tried my encoders but also a joystick button) do not further increase the value, same with decreasing. It stops after a decrease of 100. I will try to look into this later. That is strange as the logic for the increment/decrement is exactly the same as the non-event based version. You can use FSUIPC's lua debugging facilities to see what is happening. John
shorthauler Posted March 7 Author Report Posted March 7 When I wrote "undocumented," I meant undocumented for MobiFlight, sorry. I have tried the debugging facilities, but to no avail. I have also added these lines to reset the feeder value: ipc.sleep(500) ipc.writeUB(0x0D6C,0) end newNav1_BCD = convertToBCD(tostring(newNav1)) -- convert to BCD ipc.control(65708, newNav1_BCD) -- sending BCD to FSUIPC ipc.sleep(500) ipc.writeUB(0x0D6C,0) end event.param("updateNav1") ipc.log("Nav1 update lua script now running") Unfortunately, I cannot figure out why the script only changes a value in one step up or down and then stopps changing the value. FSUIPC4 (2).zip
John Dowson Posted March 7 Report Posted March 7 1 hour ago, shorthauler said: I have also added these lines to reset the feeder value: ipc.sleep(500) ipc.writeUB(0x0D6C,0) 0x0D6C is 4 bytes, not an unsigned byte. But this is absolutely not necessary and even detrimental - please remove that. It is writing to offset 0D70 that triggers the action. This makes me think that you are not quite understanding the change to use events and LuaValue. Previously, MobiFlight started the script with the Lua command, and the script read the value from the offset. What should happen now is that the script is always running and waiting for a signal. This comes by calling LuaValue on the script, and the parameter to that call is the feed value. If you are still invoking the script with Lua, then you are killing the running script and restarting it and not passing in a value. So, please check how you are invoking the script from MobiFlight - this MUST be with LuaValue, and the parameter/feed value written to offset 0x0D6C first. And the log file doesn't show much as there is no lua plugin debugging information. So please add that, or you can also add some ipc.log statements to log what is happening. So first try and determine what is happening - is the correct feed value actually being passed to the script? If you need further help (but please try yourself first...), attach the files with the correct debugging enabled. As you have lots of lua scripts running, better to also log lua plugins separately, and also attach the plugin log, as well as the plugin itself.
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