Hi Peter,
Peter Mueller wrote:
Hello,
I develop a small function block based application. Each function block
input and output is associated with a bit in a bitfield. Function blocks
can be simple logic, timers, ... By "wiring" these function blocks I get
a kind of very simple PLC.
My first try is to allocate a byte arrary. In addition there is a get
and set function that gets the bit number I want to read or write.
Internally I have to do some calculation to find the right bit in the
byte array. The attached file shows how it is implemented.
The function blocks uses these get and set functions for accessing their
input and output ports. I wonder if there is a better method to
implement such a functionality.
- Is it possible to get rid of the function calls (get/set) in the
function blocks? Or make these calls as efficient as possible?
You can get rid of your function calls (and their local variables) by
defining macros like in the attached example files. This makes certain
what you can also reach with your functions using most compilers'
optimization capabilities: remove automatic stack variables using
registers and inline function code to avoid function call overhead.
However macros force "code inlining" while using functions with
optimization is tool dependent and always restricted to their very
source file.
- Is there a more efficient way to implement my data store? E.g. does it
make sense to use bitfields?
Why? Your bit array uses eight bytes for 64 independent two-state
information. What more can any other implementation do to reduce this
(use some futuristic tri-state-logic computers ;-).
Bitfields sometimes have the slight disadvantage of special member
names: You can loop through members of a bit array (as your
implementation allows for) but not so for bit fields. I don't know if
this is needed by your current application.
- Any other ideas - maybe someone has developed something similar?
See attached files.
Regards
Arnd-Hendrik
Thanks,
Peter
P.S: I'm also looking for a windows tool to "wire" my blocks. Do anyone
knows a tool that can do that and is open for my own extension such as
downloading the "wires" to the uC.
Thanks a lot,
Peter
--
Peter Mueller
[email protected]
------------------------------------------------------------------------
#include "sps_types.h"
#ifdef WIN32
#include <assert.h>
#endif
/**
* The datastore holds all inputs and outpus of all functionblocks that can
* can exist in an application.
*
* The memory layout is the following:
*
* Byte[0 | 1 | ...
* Bit#[0,1,2,3,4,5,6,7 | 8,9,10,11,12,13,14,16, | ...
*
*/
#define LEN_DATA_STORE 8
#define MAX_POS_DATA_STORE (LEN_DATA_STORE*8)
static unsigned char data_store[LEN_DATA_STORE];
static const unsigned char mappingtable[8] = {128,64,32,16,8,4,2,1};
TBOOL ds_get_bool(TUSIGN8 pos){
unsigned int isInByte, rest;
#ifdef WIN32
assert(pos <= MAX_POS_DATA_STORE);
#endif
isInByte = pos/8;
rest = pos%8; // Bsp.: 9 mod 8 = 1
if((data_store[isInByte]) & mappingtable[rest])
return TRUE;
else
return FALSE;
}
TUSIGN8 ds_set_bool(TUSIGN8 pos, TBOOL val){
unsigned char isInByte, rest;
#ifdef WIN32
assert(pos <= MAX_POS_DATA_STORE);
#endif
isInByte = pos/8;
rest = pos%8;
if(val==1)
data_store[isInByte] |= mappingtable[rest];
else
data_store[isInByte] &= ~(mappingtable[rest]);
return 0;
}
#ifndef BIT_ARRAY_H
#define BIT_ARRAY_H
#define BIT_ARRAY_BIS(a,b) { a [ b / 8 ] |= ( 1 << ( b % 8 ) ); }
#define BIT_ARRAY_BIC(a,b) { a [ b / 8 ] &= ~ ( 1 << ( b % 8 ) ); }
#define BIT_ARRAY_BIT(a,b) ( ( a [ b / 8 ] >> ( b % 8 ) ) & 1 )
#define BIT_ARRAY_TEST(a,b) ( BIT_ARRAY_BIT ( a, b ) == 1 )
#endif /* BIT_ARRAY_H */
#include <stdio.h>
#include "bitarray.h"
#define NR_OF_PINS 100
static unsigned char ports [ ( NR_OF_PINS +7 ) / 8 ];
static void printPorts ( void )
{
int i;
printf ( " ports = [" );
for ( i = 0; i < sizeof ( ports ); ++i )
{
printf ( "%c 0x%X", ( i != 0 ) ? ',' : ' ', ports [ i ] );
}
printf ( " ];\n" );
return;
}
static void testPort ( int pin )
{
BIT_ARRAY_BIC ( ports, pin );
if ( ! BIT_ARRAY_TEST ( ports, pin ) )
{
printf ( "Test success: pin %d is cleared.\n", pin );
printPorts ();
}
else
{
printf ( "Test failed : pin %d is still set.\n", pin );
printPorts ();
}
BIT_ARRAY_BIS ( ports, pin );
if ( BIT_ARRAY_TEST ( ports, pin ) )
{
printf ( "Test success: pin %d is set.\n", pin );
printPorts ();
}
else
{
printf ( "Test failed : pin %d is still cleared.\n", pin );
printPorts ();
}
BIT_ARRAY_BIC ( ports, pin );
if ( ! BIT_ARRAY_TEST ( ports, pin ) )
{
printf ( "Test success: pin %d is cleared.\n", pin );
printPorts ();
}
else
{
printf ( "Test failed : pin %d is still set.\n", pin );
printPorts ();
}
return;
}
int main ( int argc, char** argv )
{
int i;
for ( i = 0; i < NR_OF_PINS; ++i )
{
testPort ( i );
}
return 0;
}