I have a java program with which I create a program using logic function blocks. AND gates, OR gates that sorta things. This program can generate functional source code for an arduino board. This essentially allows people to program an Arduino with only logic gates.
The core essentials work but I am only halfway there and I run into a slight problem.
I have this struct and array
typedef struct blox
{
uint8_t IN1 : 1 ; // generic for most blocks
uint8_t IN2 : 1 ; // generic for most blocks
uint8_t IN3 : 1 ; // generic for most blocks
uint8_t Q : 1 ; // generic for most blocks
uint8_t pin : 5 ; // only inputs and output types need this
uint8_t type : 4 ; // 16 combinations
uint32_t oldTime ; // bad idea to use this amount of memory per block if only delays need it?
const uint32_t interval ; // perhaps couple a function pointers or obj pointer to it?
} FunctionBlock ;
FunctionBlock block [ nBlocks ] ;
In the main loop()
I run all logic and I update the links. The links are hardcoded.
void loop()
{
/***************** UPDATE FUNCTION BLOCKS *****************/
for( int i = 0 ; i < nBlocks ; i ++ )
{
switch( block[i].type )
{
case AND:
block[i].Q = block[i].IN1 & block[i].IN2 & block[i].IN3 ; // unused inputs INx are initialized to '1'
break ;
case OR:
block[i].Q = block[i].IN1 | block[i].IN2 | block[i].IN3 ;
break ;
case M:
if( block[i].IN3 ) block[i].Q = 0 ; // R
else if( block[i].IN1 ) block[i].Q = 1 ; // S
break ;
case NOT:
block[i].Q = !block[i].IN2 ;
break ;
case INPUT_PIN:
block[i].Q = digitalRead( block[i].pin ) ;
break ;
case OUTPUT_PIN:
digitalWrite( block[i].pin, block[i].IN2 ) ;
break ;
case DEL: for( int i = 0 ; i < n_blocks ; i ++ )
{
if( block[i].Q != block[i].IN ) // if new state changes
{
if( millis() - block[i].oldTime >= block[i].interval ) // keep monitor if interval has expired
{
block[i].Q = block[i].IN ; // if so, adopt the new state
}
}
else
{
block[i].oldTime = millis() ; // if new state does not change, keep setting oldTime
}
}
break ;
}
}
/***************** UPDATE LINKS *****************/
block[3].IN2 = block[1].Q ; // hardcoded list of all links.
block[3].IN1 = block[0].Q ;
block[3].IN3 = block[2].Q ;
block[4].IN2 = block[3].Q ;
} ;
The problem is that the structure has variables for everything. Now AND and OR gates have a 'pin' variable and every block uses 8 bytes for timing, despite only the delay gate has need for it.
I also want to add analog (all that can be more than '0' or '1') components, like an analog input, servo motor, a map()
block (to map one range into an other range), comparator contants etc.
Using the struct like this will consume way too much memory.
My best guess would be to use classes and inheritance. But I haven't used inheritance yet in c++ and I do not know how I can stuff objectes and derived objects in a single array.
class FunctionBlock // AND, OR, MEMORY or NOT gates
{
public:
uint8_t IN1 : 1 ;
uint8_t IN2 : 1 ;
uint8_t IN3 : 1 ;
uint8_t Q : 1 ;
uint8_t type ; // if I create derived classes for OR, AND, MEMORY and not gates, I may discard this variable
} ;
class IO : public FunctionBlock // INPUT, OUTPUT
{
uint8_t pin ;
} ;
class DELAY : public FunctionBlock
{
uint32_t prevTime ;
const int delayTime ;
} ;
class MAP : public FunctionBlock
{
int32_t var ; // result = map( var, in1, in2, out1, out2 ) ;
int32_t result
int32_t in1 ;
int32_t in2 ;
int32_t out2 ;
int32_t out2 ;
} ;
// class analogIn, class constant, class comperator, class decadeCounter etc etc
Were this Java I would simply do:
ArrayList <FunctionBlock> blocks = new ArrayList() ;
...
blocks.add( new AND( arguments ) ;
How do I get these derived classes to work in c++ ?