FT232RL module as GPIO for softphone

FT232RL module
This kind of USB to UART converter based on FT232RL (or more likely its clone) might be cheapest way of adding general purpose inputs and outputs to PC:

tSIP plugin

CommState.zip - source + binary
Plugin is built with Code::Blocks 16 / MinGW 32-bit.
Installing:

Controlling outputs

DLL is using EscapeCommFunction to control state of DTR and/or RTS line.

-- Lua script lines to control outputs:

PluginSendMessageText("CommState.dll", "SET DTR 1")

PluginSendMessageText("CommState.dll", "SET DTR 0")

PluginSendMessageText("CommState.dll", "SET RTS 1")

PluginSendMessageText("CommState.dll", "SET RTS 0")

Note: settings DTR or RTS to 1 sets physical line to 0V, setting state to 0 sets 3.3V or 5V depending on jumper. I think that initial output state should be assumed to be unknown, thus be careful when using it in critical application or when controlling power hungry devices.

For controlling lines from multiple serial interfaces make multiple copies of the DLL (named e.g. Comm1.dll, Comm2.dll, ... CommX.dll) and set different COM number for each of them.

Reading inputs

DLL is using GetCommModemStatus to read current state of COM lines. State is then available to Lua scripts as variable with name that consist of lowercase dll name (without extension) and "State" string, e.g. commstateState with default DLL name.

To test inputs you may use resistor (4.7k works) - connecting input to GND through resistor sets its state to 1.

local function bitand(a, b)
    local result = 0
    local bitval = 1
    while a > 0 and b > 0 do
      if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
          result = result + bitval      -- set the current bit
      end
      bitval = bitval * 2 -- shift left
      a = math.floor(a/2) -- shift right
      b = math.floor(b/2)
    end
    return result
end

local state, isSet = GetVariable("commstateState")
if isSet == 0 then
	print("commstateState variable is not set (port not opened? DLL not activated?)\n")
else
	print(string.format("commstateState = %s\n", state))
	state = tonumber(state)
	if bitand(state, 128) ~= 0 then
		print("DCD line is set\n")
	end
	if bitand(state, 64) ~= 0 then
		print("RI line is set\n")
	end
	if bitand(state, 32) ~= 0 then
		print("RSD line is set\n")
	end
	if bitand(state, 16) ~= 0 then
		print("CTS line is set\n")
	end
end

Note: state variable is refreshed once per second. Rebuild DLL from source code if faster refreshing is needed, optionally SetCommMask function can be used to react on event, not read state. If COM port would be detached state variable would be cleared.

As variable name depends on DLL name multiple DLLs can be used simultaneously to monitor multiple ports.

Back to tSIP softphone