Controlling Output Bufferes
As far as I/O line/port control goes, there are two kinds of Tibbo devices and corresponding platforms — those without output buffer control and those with output buffer control. You can find this information in your device's platform documentation (for example, the EM1000's is here).
On devices without output buffer control, each I/O line's output driver is always enabled. If you want to use this line as an input, set its state to HIGH. After that, you can read this line's state. If the line is left unconnected or is not being pulled LOW externally, you will read HIGH. If the line is being pulled LOW externally, you will read LOW. Pulling the line LOW externally while this line's output driver is at HIGH will do no damage to the line.
Here is a code example in which we wait for line #1 to become LOW:
io.num=PL_IO_NUM_1 'select the line
io.state=HIGH 'set it to HIGH so we can use it as an input
While io.state=HIGH 'wait until the line is pulled LOW externally
Wend
On devices with explicit output buffer control, you need to define whether the line is an output (set io.enabled = 1 — YES) or input (set io.enabled = 0 — NO). Trying to read the line while it is in the output mode will simply return the state of the line's own output driver. Forcing the line externally while it works as an output may cause a permanent damage to the device. For this kind of devices, the above code must be modified to look like this:
io.num=PL_IO_NUM_1 'select the line
io.enabled=NO 'disable the output driver (line will function as an input now)
While io.state=HIGH 'wait until the line is pulled LOW externally
Wend
Since ports consist of individual lines, the same applies to ports as well. What needs to be understood is that each port line can be configured as an input or output individually. Hence, a particular port doesn't have to be "all outputs" or "all inputs." Here is an example where the lower half of the port lines is configured for output and the rest of the lines serve as inputs:
'This is an example for devices with explicit output buffer control
io.portnum=PL_IO_PORT_1
io.portenabled= &h0F 'configure lower 4 lines as outputs, the rest will be used as inputs
Some I/O lines are shared with the inputs/outputs of special function blocks (serial ports, etc.). When a special function block is enabled, certain (not all) I/O lines it uses may be configured for input or output automatically. For such lines, when the corresponding special function block is disabled, the state of the output buffer is restored automatically to what it used to be prior to enabling this function block.
Note that I/O line and port names are platform-specific and are defined by pl_io_num and pl_io_port_num enums, respectively. The declarations for these enums can be found in your device's platform documentation (for example, the EM1000's is here).