As a sequel to the hint Edwin gave (poll your pin(s)), maybe the code
below can serve as a starting point:
void C8575Io::Execute( void )
{
FUNCLOG( "Execute( void )" );
struct timeval tvTimeVal;
unsigned int uiWhileCounter = 0;
unsigned int uiRow = 0;
unsigned int uiColumn = 0;
unsigned int uiTimeDelta = 0;
unsigned int uiCheckPattern = 0;
LOG( "C8575Io - Running thread object in a new thread: %d"
, (int)GetThreadID()
);
tvTimeVal.tv_sec = 0;
while ( !bTerminateThread )
{
tvTimeVal.tv_usec = 10000; /* 10ms is minimal timer tick of
system */
select( 0, NULL, NULL, NULL, &tvTimeVal);
/* Compose bitcheck pattern */
uiCheckPattern = 0;
/* Check which pins have to be observed for this 10ms timeslot */
for ( uiRow = 0; uiRow <= PORT1; uiRow++ )
{
for ( uiColumn = 0; uiColumn <= PINMAX; uiColumn++ )
{
if ( Expander.PollTime[ uiRow ][ uiColumn ] )
{
if ( ( uiWhileCounter % Expander.PollTime[ uiRow
][ uiColumn ] ) == 0 )
{
uiCheckPattern |= ( 1 << ( ( uiRow * 8 ) +
uiColumn ) );
}
}
}
}
/* Are there any pins to be checked for this 10ms timeslot? */
if ( uiCheckPattern )
{
unsigned int uiResult = GetBytes();
unsigned int uiMask = 0x01;
uiRow = 0;
uiColumn = 0;
while ( uiMask != 0x10000 )
{
if ( uiCheckPattern & uiMask ) /* This bit has to be
checked */
{
if ( !( uiResult & uiMask ) )
{ /* Button has been pressed */
Expander.CurrPinVal |= uiMask;
if ( ( Expander.CurrPinVal & uiMask ) != (
Expander.PrevPinVal & uiMask ) )
{
Expander.CurrTimeVal[ uiRow ][ uiColumn ]
= uiWhileCounter;
Expander.PrevTimeVal[ uiRow ][ uiColumn ]
= Expander.CurrTimeVal[ uiRow ][ uiColumn ];
Expander.PrevPinVal = Expander.CurrPinVal;
}
}
else
{ /* Button has been released */
Expander.CurrPinVal &= ~uiMask; /* Reset pin
value */
if ( ( Expander.CurrPinVal & uiMask ) != (
Expander.PrevPinVal & uiMask ) )
{
Expander.CurrTimeVal[ uiRow ][ uiColumn ]
= uiWhileCounter;
if ( Expander.CurrTimeVal[ uiRow ][
uiColumn ] >= Expander.PrevTimeVal[ uiRow ][ uiColumn ] )
{
uiTimeDelta = Expander.CurrTimeVal[
uiRow ][ uiColumn ]
- Expander.PrevTimeVal[
uiRow ][ uiColumn ];
}
else
{
uiTimeDelta = Expander.CurrTimeVal[
uiRow ][ uiColumn ]
+ ( UINT_MAX -
Expander.PrevTimeVal[ uiRow ][ uiColumn ] );
}
Expander.PrevTimeVal[ uiRow ][ uiColumn ]
= Expander.CurrTimeVal[ uiRow ][ uiColumn ] = 0;
Expander.PrevPinVal = Expander.CurrPinVal;
MyIoMqStruct.MsgType = 2;
MyIoMqStruct.MqUn.IoStruct.IoPin = ( uiRow
* 8 ) + uiColumn;
MyIoMqStruct.MqUn.IoStruct.Time = (
uiTimeDelta * 10 );
// LOG( "PCF85755 - Button %d pressed for
about %d ms..."
// , ( uiRow * 8 ) + uiColumn
// , ( uiTimeDelta * 10 ) /* compensate
for time slot */
// );
/* Info gathered, so send it to message
queue... */
if ( CMqMgrUnique::GetMqId() >= 0 )
{
CMqMgrUnique::SendMsg( (struct
MqStruct*)&MyIoMqStruct
, sizeof(
MyIoMqStruct )
, 0
);
}
}
}
}
uiMask <<= 1;
uiColumn++;
if ( uiMask == 0x0100 )
{
uiColumn = 0;
uiRow++;
}
}
}
uiWhileCounter++;
}
LOG( "Quitting 8575 Exectute()\n" );
} /* Execute */
The above code is polling the status of IO pins of an PCF8575. Each
pin can have a different polling time (for instance, pin 0 can be
polled every 50ms, but pin 14 can be polled every 30ms).
The basics is a separate thread where this function "Execute()" is
running in.
The "while" loop you see, is running every 10ms (so, the polling times
that can be assigned to each and every IO pin individually must be a
multiple of 10ms).
To avoid almost 100% occupation of the CPU power, the function
"select()" is used to put the process/thread into sleep for about 10ms.
In fact, I should say "misused", since I profit from the time-out
value you can specify for that function before it returns. So, since
no parameters are given, the function will wait for input that will
never come. So, it will time-out after (in my case) 10ms.
This reduces the CPU time occupied by this application to next to 0%
(almost nothing).
If you don't do this, then your CPU will be busy almost 100% doing
this loop!
This is a very robust way of polling input pins. If I see that your
requirements are to poll a pin every 10 seconds, then there's a
tremendous amount of time free for the processor to do other things.
The code is given just as an example code, to show you that with using
the correct set-up, many interrupts can be replaced by polling
techniques. Many, but not all, of course. A lot depends on the
requirements you give, but in your case that should absolutely not be
any problem at all...
Best rgds,
--Geert