Signal Handling Device
Another simple bus interface is the SignalIface
, the signal interface provide a simple single bit control involving the two raise()
and lower()
methods.
We will create a new model (you do not need any properties in it except the temu_Object
field) and add 4 signal interfaces to it.
While it is possible to add multiple interfaces with different names (signal_a
,
signal_b
, et.c.).
It is much more convenient to add multiple interfaces in an interface array, first define two functions that implements the SignalIface (in temu-c/Bus/Signal.h
) but extend the functions with an integer index parameter, then add a macro to synthesise the actual implementation in multiple copies:
static void
raise(void *obj, int idx)
{
temu_logInfo(obj, "signal %d raised", idx);
}
static void
lower(void *obj, int idx)
{
temu_logInfo(obj, "signal %d lowered", idx);
}
#define DEF_SIGNAL(n) \
static void \
raise ## n (void *obj) \
{ \
raise(obj, n); \
} \
static void \
lower ## n (void *obj) \
{ \
lower(obj, n); \
}
DEF_SIGNAL(0)
DEF_SIGNAL(1)
DEF_SIGNAL(2)
DEF_SIGNAL(3)
temu_SignalIface SignalIface[] = {
{ raise0, lower0 },
{ raise1, lower1 },
{ raise2, lower2 },
{ raise3, lower3 },
};
By implementing the interface like above, you can have a single implementation for the signal handling functions. This may of-course in some cases not be appropriate (e.g. if a signal need specific semantics), but in many cases it will work fine if the behaviour can be specialised via an index parameter.
To register an interface array with this device, use the following code:
TEMU_PLUGIN_INIT
{
temu_Class *c = temu_registerClass("MyDevice", create, dispose);
temu_addInterfaceArray(c, "signals", TEMU_SIGNAL_IFACE_TYPE,
&SignalIface[0], 4, sizeof(SignalIface[0]),
"signal interfaces");
}
Now we can connect to this from the GPGPIO device provided in the UT700 configuration:
temu> object-create class=MyDevice name=sigdev
temu> connect a=gpio0.outSignals[0] b=sigdev:signals[0]
temu> connect a=gpio0.outSignals[4] b=sigdev:signals[2]
And provide a small RTEMS program for triggering the updates:
rtems_task
Init(rtems_task_argument ignored)
{
*(volatile unsigned*)(0x80000908) = 0xffff; // Turn all pins to output
*(volatile unsigned*)(0x80000904) = 1; // Set pin 0
*(volatile unsigned*)(0x80000904) = 1 << 4; // Set pin 4, clear other pins
exit( 0 );
}
When running the program we will see first how the pins are updated when set as output pins, and secondly how they are toggled when modifying the GPIODOR register.