Truth tables in code? How to structure state machine? - c

I have a (somewhat) large truth table / state machine that I need to implement in my code (embedded C). I anticipate the behavior specification of this state machine to change in the future, and so I'd like to keep this easily modifiable in the future.
My truth table has 4 inputs and 4 outputs. I have it all in an Excel spreadsheet, and if I could just paste that into my code with a little formatting, that would be ideal.
I was thinking I would like to access my truth table like so:
u8 newState[] = decisionTable[input1][input2][input3][input4];
And then I could access the output values with:
setOutputPin( LINE_0, newState[0] );
setOutputPin( LINE_1, newState[1] );
setOutputPin( LINE_2, newState[2] );
setOutputPin( LINE_3, newState[3] );
But in order to get that, it looks like I would have to do a fairly confusing table like so:
static u8 decisionTable[][][][][] =
{{{{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 }},
{{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 }}},
{{{ 0, 0, 1, 1 },
{ 0, 1, 1, 1 }},
{{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 }}}},
{{{{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 }},
{{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 }}},
{{{ 0, 1, 1, 1 },
{ 0, 1, 1, 1 }},
{{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 }}}};
Those nested brackets can be somewhat confusing -- does anyone have a better idea for how I can keep a pretty looking table in my code?
Thanks!
Edit based on HUAGHAGUAH's answer:
Using an amalgamation of everyone's input (thanks -- I wish I could "accept" 3 or 4 of these answers), I think I'm going to try it as a two dimensional array. I'll index into my array using a small bit-shifting macro:
#define SM_INPUTS( in0, in1, in2, in3 ) ((in0 << 0) | (in1 << 1) | (in2 << 2) | (in3 << 3))
And that will let my truth table array look like this:
static u8 decisionTable[][] = {
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 }};
And I can then access my truth table like so:
decisionTable[ SM_INPUTS( line1, line2, line3, line4 ) ]
I'll give that a shot and see how it works out. I'll also be replacing the 0's and 1's with more helpful #defines that express what each state means, along with /**/ comments that explain the inputs for each line of outputs. Thanks for the help, everyone!

I'd suggest either (preferred approaches first):
Use a macro to intialize each "row" - this will hide the braces within the macro call.
Use comments to break up the rows.
Use an init function to initialize the context explicitly - perhaps use functions to initialize each section. This is similar to the first option above but has a disadvantage that the init function must be invoked before the state machine can be used.

No need for a multidimensional table. With a 4 bit => 4 bit mapping, you can have a single u8[16] array mapping inputs to outputs. State lookups will be much cheaper, and you can extract individual bits with some shift-and-mask ops.
If the algorithm to populate rows is easy to codify, you could #define a macro to populate each row by index number.

Personally, I'd read it from a configuration file. CSV, perhaps, which is easy to export to from Excel. Or you could just copy and paste from Excel into plain text, which gives you space-separated values, which is equally easy to import.
This also means, given that you are working with C, that you won't have to recompile your code each time the decision table changes.

if your truth-table is all booleans, you could just collapse it to a list of pairs, e.g.
1111,0000
1110,0110
...
for data compression, represent the values as bytes (two nybbles)...
where/how to store it for soft-coding in your particular embedded-system configuration, only you can say ;-)

If the truth table is really only 4x4x4x4 then I'd use macros. If it's ever going to grow past that, I'd use Ragel. Chances are it will make smaller, faster C code than you will.

I don't see any reference to the current state in order to get your output state. This means it is not a state machine, but only a truth table. There are four inputs, so there are only 16 possible input combinations. So, a table with 16 positions ought to do it.

Usually when you have a problem like this, one tries to reduce it to a simple boolean formula. I don't see why that wouldn't be the best approach here. It would be much more compact and more readable, plus it has the potential to be faster (I imagine a handful of ANDs and ORs would execute more quickly than the collection of multiplies/shifts + memory access needed for the lookup table approach). The easiest way to reduce this table to a boolean formula is with a K-Map.

Related

Format for sending location data in body

I'm coding in React-Native.
Glympse docs says that location data should be sent in a delta-compressed array. I don't really know what that means. I think I get the idea of each element being the amount of change (delta) from the previous element, but I still don't have a clear picture of how the body should look when I make the POST request.
Can anyone show an example of this process?
Examples of location arrays that are compressed can be found here https://developer.glympse.com/docs/core/api/reference/objects/location-points#examples
The idea behind this format is that the first item in the array contains specific values for each parameter, but each item that comes after that only contains the change (or delta) from the previous point.
[
[1339989715000, 37123450, -112123450, 18000, 55, null, 2, 4],
[1000, 1000000, 1000000, 0, null, 1000, 1, -1],
[1000, 0, 0, 0, 1, 0, 0, 0],
[1000, 0, 0, 0, 0, 0, 0, 0],
[1000, 0, 0, 0, 0, 0, 0, 0]
]
The first parameter is the timestamp, so if we look at the second item it shows 1000 which means it's the first timestamp + 1000ms.
The second parameter is latitude * 10^6. The first item shows latitude 37.123450, and the second item in the array has the value 1000000 which represents 37123450 + 1000000 or the latitude 38.123450. Not likely to have something moving that fast in real data, but that's the idea of how this format works.
Timestamp, latitude, and longitude are the only required fields. A POST body with only the required fields would look like this.
[
[1339989715000, 37123450, -112123450],
[1000, 1000000, 1000000],
[1000, 0, 0],
[1000, 0, 0],
]

Chart line jumping instead interpolating correctly

I'm using AMCharts 4 and I am passing hour - values data pairs. So for example at 15h there is value of 10, at 16h value of 15, etc.
[...{
"date": new Date(2020, 1, 1, 15, 0, 0, 0),
"value": 10,
}, {
"date": new Date(2020, 1, 1, 16, 0, 0, 0),
"value": 15,
}...]
Chart is not plotting lines between points correctly (it is displaying correct data, but line is not printed as it should).
Example:
As you can see in the example above, it is displaying correct data but it does not have correct interpolation between lines. From example from picture it is obvious that from 14h to 15h it is a uptrend and that line should go up gradually and be there for 15h. Instead, it gradually goes down and when it realizes the value for 15h it moves up instantly to correct it.
I tried series.sequencedInterpolation = true but it does not have any effect.
Any ideas?
After so much time wasted on this, I figured it out.
DateAxis has baseInterval which is calculated automatically if not set manually. Obviously it did not calculate it correctly and it was glitching out. By setting it to following settings it worked:
xAxes1.baseInterval = [
{ timeUnit: "hour", count: 1 },
...];
In the array you can specify for each time unit the count that you have.
Docs: https://www.amcharts.com/docs/v4/reference/dateaxis/

Gdscript Bug or strange behaviour

I've noticed some strange behaviour in gdscript.
when you declare variables
var value = [0, 0, 0, 0, 0]
var values = []
and append one to the other
values.append(value)
and then change something in the array
value[1] = 1
If you would then print the results [print(value, values)]
You get
prints: [0, 1, 0, 0, 0][[0, 1, 0, 0, 0]]
expected behaviour
prints: [0, 1, 0, 0, 0][[0, 0, 0, 0, 0]]
What is happening is that, in GDScript, when you append the array value to values, you're actually appending it's reference to the array. So you end up with an array values which has as it's first entry a reference to the array value. So when you change the value of the reference in values, you're also changing it for your original variable.
for further reading, check out this wikipedia page
Arrays in gdscript are passed by the reference, so when you append an array to other array, it only stores the pointer to the first array, so every change made in first array will be visible in the second array. What you want to do is to copy the first array and append that copy to the second array.
In gdscript currently there is no direct method to copy an array. Maybe this will change with godot 4.0. Now you can use:
values.append([] + value)

DroneKit :Changing groundspeed in AUTO mode/ implementing "MAV_CMD_DO_CHANGE_SPEED"

I need help figuring out how to set groundspeed in AUTO mode (which is apparently implemented with the Mavlink command "MAV_CMD_DO_CHANGE_SPEED"—but I can't find any examples of this). What I thought would work:
vehicle.commands.add(Command( 0, 0, 0, mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT, mavutil.mavlink.MAV_CMD_DO_CHANGE_SPEED, 0, 0, 1, 0.25, 0, 0, 0, 0, 0))
Based off of:
https://pixhawk.ethz.ch/mavlink/
and
https://github.com/mavlink/mavlink/blob/master/message_definitions/v1.0/common.xml
But it does not work.
Can anyone help me out?
msg = vehicle.message_factory.command_long_encode(
0, 0, # target system, target component
mavutil.mavlink.MAV_CMD_DO_CHANGE_SPEED, #command
0, #confirmation
0, #speed type, ignore on ArduCopter
speed, # speed
0, 0, 0, 0, 0 #ignore other parameters
)
# send command to vehicle
vehicle.send_mavlink(msg)
vehicle.flush()
You can set the parameter 'WPNAV_SPEED' to the desired speed (in cm) before setting the mode to AUTO.
Something like this:
vehicle.parameters['WPNAV_SPEED'] = 500
The following will work:
speed_type = 1 # 0 is airspeed (for plane with airspeed sensor), 1 is groundspeed
speed = 15
throttle_setting = 0
cmds.add( Command( 0, 0, 0, mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT, mavutil.mavlink.MAV_CMD_DO_CHANGE_SPEED, 0, 0, speed_type, speed, throttle_setting, 0, 0, 0, 0) )
You can double check it by running the code then connecting to a GCS and downloading the mission from the vehicle.

How can I sum arrays element-wise in Perl?

I have two arrays:
#arr1 = ( 1, 0, 0, 0, 1 );
#arr2 = ( 1, 1, 0, 1, 1 );
I want to sum items of both arrays to get new one like
( 2, 1, 0, 1, 2 );
Can I do it without looping through arrays?
for Perl 5:
use List::MoreUtils 'pairwise';
#sum = pairwise { $a + $b } #arr1, #arr2;
If you're using Perl 6:
#a = (1 0 0 0 1) <<+>> (1 1 0 1 1) #NB: the arrays need to be the same size
The Perl 6 Advent Calendar has more examples.
Fundamentally, no, you can't do it without "looping through arrays" because you need to access every element of both arrays in order to sum them. Both the answers so far just hide the looping under a layer of abstraction but it's still there.
If you're concerned about looping over very large arrays, it's probably best to consider other ways of keeping the sum up-to-date as you go.
what's wrong with looping over arrays? that's the fundamentals.
#arr1 = ( 1, 0, 0, 0, 1 );
#arr2 = ( 1, 1, 0, 1, 1 );
for ($i=0;$i<scalar #arr1;$i++){
print $arr[$i] + $arr2[$i] ."\n";
}
You've seen a C style for loop, and pairwise. Here's an idiomatic Perl for loop and map:
my #arr1 = ( 1, 0, 0, 0, 1 );
my #arr2 = ( 1, 1, 0, 1, 1 );
my #for_loop;
for my $i ( 0..$#arr1 ) {
push #for_loop, $arr1[$i] + $arr2[$i];
}
my #map_array = map { $arr1[$_] + $arr2[$_] } 0..$#arr1;
I like map and pairwise best. I'm not sure that I have a preference between those two options. pairwise handles some boring details of plumbing for you, but it is not a built-in like map. On the other hand, the map solution is very idiomatic, and may be opaque to a part-time perler.
So, no real wins for either approach. IMO, both pairwise and map are good.
From http://www.perlmonks.org/?node_id=122393
#a = qw(1 2 3 4);
#b = qw(1 2 3 4);
#c = ();
#c = map { $a[$_] + $b[$_] } ( 0 .. (#a > #b ? $#a : $#b) );
Or:
$c[#c] = $a[#c] + $b[#c] while defined $a[#c] or defined $b[#c];
Or:
$c[$_] = $a[$_] + $b[$_] for 0 .. (#a > #b ? $#a : $#b);
Or (in Perl 6):
#c = #a ^+ #b
If you're really afraid of looping, then you can binary chop the arrays, sum the pairs, then recursively reassemble the resulting array. No looping there, and as a bonus you get to learn how part of the fast-fourier transform derivation works.
To avoid (explicit) looping, here is a solution that uses recursion "instead":
#!/usr/bin/perl
use v5.20;
my #arr1 = ( 1, 0, 0, 0, 1 );
my #arr2 = ( 1, 1, 0, 1, 1 );
my #result=non_looping_pairwise_sum([ #arr1 ], [ #arr2 ]); # pass in copies, so the originals are not modified
say "#result";
sub non_looping_pairwise_sum { # only handles lists that have the same length
my ($a1, $a2)=#_;
return () if (scalar(#$a1)==0 and scalar(#$a2)==0);
my $e1=shift #$a1;
my $e2=shift #$a2;
return ($e1+$e2, non_looping_pairwise_sum($a1, $a2));
}
Output:
2 1 0 1 2
Note that use v5.20 means you don't have to write use strict; use warnings, I think.
Apologies/kudos to #parm for the idea.
I'm not sure what you plan to do with the sum once you have it, but you plan to do more vector-y type stuff, then Math::Matrix might be a good fit.
use Math::Matrix;
my $foo = Math::Matrix->new([ 1, 0, 0, 0, 1 ]);
my $bar = Math::Matrix->new([ 1, 1, 0, 1, 1 ]);
my $sum = $foo->add($bar);

Resources