CAN message signals, CAPL - can-bus

I am trying to save the signal data in the each my of a CAN message in separate variables.
For eg. I have a CAN message 'msg1' of dlc =4, with signals {8, 5, 7, 21} in CANalyzer's CAPL,
I would like to save them in variables like:
int var1 = msg1.byte(0);
but I keep getting zero (0) as the final value of the variable after the operation.
Any help is much appreciated.
Thanks

If you are not doing this already, implement an on message event using the keyword this:
on message msg1 {
var1 = this.byte(0);
...
}
The event will always be triggered when CANalyzer receives the message specified in the on message event. This way you can also make sure that the value stored by var1 is up to date.
You can also use a more general approach using arrays.
on message msg1 {
int i;
int var[msg1.dlc];
for (i = 0; i < msg1.dlc; i++) {
var[i] = this.byte(i);
}
}

Related

Is it atomic operation when exchange std::atomic with itself?

Will following code be executed atomically?
const int oldId = id.exchange((id.load()+1) % maxId);
Where id is std::atomic<int>, and maxId is some integer value.
I searched google and stackoverflow for std::atomic modulo increment. And I found some topics but I can't find clear answer how to do that properly.
In my case even better would be to use:
const int newId = id.exchange((++id) % maxId);
But I am still not sure if it will be executed atomically.
No, this is not atomic, because the load() and the exchange() are separate operations, and nothing is preventing id from getting updated after the load, but before the exchange. In that case your exchange would write a value that has been calculated based on a stale input, so you end up with a missed update.
You can implement a modulo increment using a simple compare_exchange loop:
int val = id.load();
int newVal = (val + 1) % maxId;
while (!id.compare_exchange_weak(val, newVal) {
newVal = (val + 1) % maxId;
}
If the compare_exchange fails it performs a reload and populates val with the updated value. So we can re-calculate newVal and try again.
Edit:
The whole point of the compare-exchange-loop is to handle the case that between the load and the compare-exchange somebody might change id. The idea is to:
load the current value of id
calculate the new value
update id with our own value if and only if the value currently stored in id is the same one as we read in 1. If this is the case we are done, otherwise we restart at 1.
compare_exchange is allows us to perform the comparison and the conditional update in one atomic operation. The first argument to compare_exchange is the expected value (the one we use in our comparison). This value is passed by reference. So when the comparison fails, compare_exchange automatically reloads the current value and updates the provided variable (in our case val).
And since Peter Cordes pointed out correctly that this can be done in a do-while loop to avoid the code duplication, here it is:
int val = id.load();
int newVal;
do {
newVal = (val + 1) % maxId;
} while (!id.compare_exchange_weak(val, newVal);

How to update another byte of a CAN message while changing a byte in real-time?

I'm new to CANoe and CAPL scripting. I need to update a byte of CAN message based on a change in another byte through a panel. I added a CAPL script for the automatic change/update but when I send/update the byte through the panel it sends the default values for the other bytes. It gets corrected in the next sample.
includes
{
}
variables
{
message M2P_0x101 msg1;
msTimer timer10ms;
byte counter = 1;
}
on message M2P_0x101
{
if(counterAlive == 15)
{
counterAlive = 0;
}
else
{
counter++;
}
msg1.byte(0) = this.byte(0);
msg1.byte(1) = this.byte(1);
msg1.byte(2) = this.byte(2);
msg1.byte(3) = this.byte(3); // Changing through the Panel
msg1.byte(4) = this.byte(3)+1;
msg1.byte(5) = this.byte(5);
msg1.byte(6) = counter;
msg1.byte(7) = this.byte(7);
}
on timer timer10ms
{
output(msg1);
}
on start
{
setTimerCyclic(timer10ms, 10);
}
4th & 6th byte has default value because 3rd byte was changed from the panel.
I expected the 4th byte to be 1(value of 3rd byte + 1) and the 6th byte to be 4(counter value).
How to solve it? As far as I understand, it seems that the panel inputs/changes are sent to the CAN bus first and then CAPL node reads it and makes changes. This could be the reason for overwriting the other bytes of the message with default values.
Is there a way to include the changes made by CAPL before the panel sends the message to the CAN bus? A combination of Panel & CAPL node?

ThinkOrSwim function equivalent in MQL

I have never heard of ThinkOrSwrim till yesterday when someone asked me to convert a ThinkOrSwim script to an MQL4 indicator.
A part of the code is as follows:
input length = 21;
input price = close;
input ATRs=1;
input trueRangeAverageType = AverageType.WILDERS;
def flag;
def EMA = ExpAverage(close, length);
def shift1 = ATRs * MovingAverage(trueRangeAverageType, TrueRange(high, close, low), length);
I want to ask you to kindly check and let me know if my understanding is correct.
input ATRs=1; // This should be a multiplier for ATR, then I think I should give it a double
//type for more flexible control.
input trueRangeAverageType = AverageType.WILDERS;
//As far as I understood, wilders is the same as SMMA in MQL.
.
def shift1 = ATRs * MovingAverage(trueRangeAverageType, TrueRange(high, close, low), length);
Here is the main piece of this code which I need your help with.
My understanding is as follows
ATRs ==>> Just a multiplier
I think the rest of this line is calculating the ATR, right?
If so, then I can see that I cannot simply convert this to iATR (in mql), because we are not able to choose MA Methode of ATR in mql4.
Then I think first I have to put the "True Range" of each bar in an array and then use this array as a price source to get the averages.
MQL4:
for(int i = 0; i < rates_total; i++)
{
data[i] = iATR(_Symbol, TF_1, 1, i);
}
for(int i = 0; i < limit; i++)
{
ExtBuffer[i] = iMAOnArray(data, 0, Inplenght, 0, InpMAMethod, i);
}
If I'm in the right way yet, Then I think the iATR period has to be 1, to have the TrueRange of each bar and not the average of the TrueRanges.
And then have the variable length (from thinkOrSwim inputs) as the period parameter for iMAOnArray.
I would appreciate any help with it.
Regards
Edit:
I forgot to ask you something,
why should the programmer who wrote this thinkscript code call this variable shift1?

ActionScript Haxe Evaluate a referenced variable inside a loop in a closure

I've been programming some stuff in ActionScript (Haxe) and arrived this very specific problem.
Here's the code (pseudo :S):
var func:Array = new Array(256);
(A) var i:Int = 0;
for(;i<256;i++) { // OR // for(i in 0...256) {
func[i] = function() { trace(i); }
}
func[0]();
func[127]();
func[256]();
The above code outputs (a):
256
256
256
I want that to be (b):
0
127
256
That doesn't happen, because ActionScript/Haxe is assigning the reference of i to the function, and since i equals 256 at the end of the loop where the functions get evaluated, that's why I get (a).
Does anyone know of a way to avoid that and get the expected results at (b) ?
Thanks to all of you guys and your responses.
I think I've found the answer. If you remove the line marked with (A) it works, if you leave it it doesn't. I'm pretty sure you could all figure out why that happens. Thanks again!
it's not neccessary to use callback, this should work as expected (haxe creates a local var in each loop):
var func = [];
for(i in 0...256)
func[i] = function() trace(i);
func[0]();
func[127]();
The one you show is the expected/desired behavior. To retain the value of "i" you must use "callback":
/* not pseudo code ;) */
var func = [];
for(i in 0...256)
func[i] = callback(function(v) trace(v), i);
func[0]();
func[127]();
func[256]();

Getting the index of an array element of EDT Dimension

I need to write a job where i could fetch the index of an array element of EDT Dimension
e.g. In my EDT Dimension i have array elements A B C when i click over them for properties I see the index for A as 1, B as 2 and C as 3. Now with a job ui want to fetch the index value. Kindly Assist.
I'm not sure if I did understand the real problem. Some code sample could help.
The Dimensions Table has some useful methods like arrayIdx2Code.
Maybe the following code helps:
static void Job1(Args _args)
{
Counter idx;
Dimension dimension;
DimensionCode dimensionCode;
str name;
;
for (idx = 1; idx <= dimof(dimension); idx++)
{
dimensionCode = Dimensions::arrayIdx2Code(idx);
name = enum2str(dimensionCode);
// if (name == 'B') ...
info(strfmt("%1: %2", idx, name));
}
}
I found a way but still looking if there is any other solution.
static void Job10(Args _args)
{
Dicttype dicttype;
counter i;
str test;
;
test = "Client";
dicttype = new dicttype(132);//132 here is the id of edt dimension
for (i=1;i<=dicttype.arraySize();i++)
{
if ( dicttype.label(i) == test)
{
break;
}
}
print i;
pause;
}
Array elements A B C from your example are nothing else but simple labels - they cannot be used as identifiers. First of all, for user convenience the labels can be modified anytime, then even if they aren't, the labels are different in different languages, and so on and so forth.
Overall your approach (querying DictType) would be correct but I cannot think of any scenario that would actually require such a code.
If you clarified your business requirements someone could come up with a better solution.

Resources