Wednesday, 7 November 2007

Queueing, queueing, queueing...

I'm currently busy making a mechanism whereby my IO expanders, used as inputs, are polling their inputs at a rate of a multiple of 10ms.

Each input pin can be polled independently at different times (but always a multiple of 10ms, with 10ms as a minimum poll time). For instance, if I take the PCF8575 IO expander, all 16 pins can have an individual polling time.

Polling is done on a separate thread. The thread is made as a "while ( 1 )" loop, with a "sleep" condition of 10ms. That sleep is accomplished using the function "select()", which normally is doing some IO to external devices.
However, you can set a time-out time and that's what I'm "misusing" for the moment. All other parameters are 0 or NULL, while the time-out is set to 10ms.

Every 10ms, a check is done to see if for (a) certain pin(s) the polling time has elapsed.

For instance, suppose the polling time for pin 1 is every 40ms and for pin 3 every 60ms, then at 40, 80 and 120ms pin 1 will be checked and at 60 and 120ms pin 3 will be checked. You see that every 120ms both pins 1 and 3 are checked!

When I have the result, I should of course do something with it. The IO pins are checking if a connected button is pressed or not. Since I'm checking at regular times, I can know when the button has been pressed, but also when the button has been released. So, I can measure the time the button has been pressed.

This is very interesting: this way, I can give multiple functions to one and the same button. For instance, if a button is pressed less than 500ms, it has a "normal" function (e.g. switching on/off a certain light), but if it has been pressed for more than, say, 2 seconds, I can for instance start dimming up/down that certain light!

All this info is gathered at the level of the IO expander class, but it has also to be sent to another IO expander which is used as output (for instance, to control a relays).

Since more than one IO expander is used as input, I needed a mechanism to not loose any information (which button is pressed, how long has it been pressed, to which IO expander is the button connected, etc.)

Therefore, I've created a structure which contains all that data. Next to this, I've created a message queue (in the same process, so not an IPC message queue). That message queue is bringing all that information into a queue manager.

That queue manager has a blocking receive call on the message queue and the moment a message arrives, the queue manager will analyse that message and see which destination it has to addressed it to.

I'm currently implementing that queue mechanism and the last thing I have to do, is to allow the queue manager (messages are already sent from the IO input expanders via the message queue to the queue manager, that already works great) to distribute the received data.

No comments: