Jump to content
The simFlight Network Forums

Recommended Posts

Posted

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

Posted
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.

Posted

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.

Posted

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.

Posted

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"?

Posted
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.

Posted

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?

Posted
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

Posted

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

Posted

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

Posted

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

Posted
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

Posted

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

Posted

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

 

 

Posted

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

 

Mobiflight.JPG

Posted

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

 

Posted

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!

Posted

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

Posted

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

 

Posted

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.

Posted

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

Posted

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.

Posted
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

Posted

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

Posted
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.

 

Create an account or sign in to comment

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

Create an account

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

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • 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.