3

I am trying to write a function in CAPL that takes a signal and calculates the physical value with the signal value, the signal factor and the signal offset.

This is how a simple gateway normally works:

message CAN1.myMessage1 myMessage1 = {DIR = RX};//message from the database
message CAN2.myMessage2 myMessage2 = {DIR = TX};//another message from the database

on message CAN1.*
{
   if(this.id == myMessage1.id)
   {
      myMessage1 = this;
      myMessage2.mySignalB = myMessage1.mySignalA * myMessage1.mySignalA.factor + myMessage1.mySignalA.offset;
   }
}

And this is what I am trying to do:

...
on message CAN1.*
{
   if(this.id ==myMessage1.id)
   {
      myMessage1 = this;
      myMessage2.mySignalB = PhysicalValue(myMessage1.mySignalA);
   }
}

double PhysicalValue(signal * s)
{
  return s*s.factor+s.offset;
}

There are two problems with this code:
Firstly when I pass the signal as the parameter the compiler says that the types don't match. The second problem is that inside the function the attributes (factor and offset) are no longer recognized. These problems might have something to do with the weird object-oriented-but-not-really nature of CAPL. The value of the signals can be accessed directly but it also has attributes?

int rawValue = myMessage1.mySignalA;

If you are familiar with C you might say that the problem is that I am specifying a pointer in the function but that I am not passing a pointer into it. But in CAPL there are no pointers and the * simply means anything. Without the * I would have needed to use a specific signal which would have defeated the purpose of the function.

EDIT:
I have found the attribute .phys by now which does exactly what my demo function would have done.

double physValue = myMessage1.mySignalA.phys;

This has already made my code much shorter but there are other operations that I need to perform for multiple signals so being able to use signals as a function parameter would still be useful.

TomMaier
  • 131
  • 1
  • 2
  • 9
  • Could you please show your code? Above all, what is `message`? Is it a CAN message? I have never seen, that you can access the signals of a CAN message like this. Apart from that, when you access the signal value in CAPL directly, you already get the physical value, no need to calculate that yourself. – MSpiller Jul 05 '19 at 08:02
  • I hope the changes I made clarify the question. – TomMaier Jul 07 '19 at 23:30
  • I suppose that the `on signal` event is not going to suit your purpose, right? However, I fail to see why. Because you'd like to have this generalized? If so, you could mirror any desired signal with a system variable, and maybe use that as trigger for the event? I've never tried it, so it is pure imagination. Let me know what you think. – Daemon Painter Jul 10 '19 at 06:41
  • I thought about using system variables but I came to the conclusion that it wouldn't change the problem because I would still have to handle every signal separately. That is also the reason why I can't use on signal. Of course I could replace on message + id check with on signal but that would mean a lot of extra code. – TomMaier Jul 10 '19 at 23:29

2 Answers2

2

What you can do is this:

double PhysicalValue(signal * s)
{
  // access signal by prepending a $
  return $s.phys;
}

Call like this

on message CAN1.*
{
   if(this.id ==myMessage1.id)
   {
      myMessage1 = this;
      myMessage2.mySignalB = PhysicalValue(CAN1::myMessage1::mySignalA);
   }
}

I.e. when you call your function, you have to provide the qualified name of the signal (with colons rather than dots). To my knowledge it is not possible to use myMessage1.mySignalA, since signals itself are not a CAPL datatype.

Apart from this, you might re-think whether you really should be using on message, but rather switch to on signal. Handling the signal values no matter with which message they are sent is done by CANoe's signal server.

MSpiller
  • 3,500
  • 2
  • 12
  • 24
  • Thanks for the great answer. Unfortunately I get the error "Signal oriented CAPL is not allowed within the current context (CANalyzer, Analyze, Test...)" So I am guessing the $ is not compatible with CANalyzer? – TomMaier Jul 10 '19 at 23:20
  • Seems like that. I was using CANoe and was not aware that CANalyzer has this limitation. – MSpiller Jul 12 '19 at 10:10
0

Note that CANoe already has a function which does exactly what you're trying to do (multiplying by factor and adding offset). It's called getSignal:

on message CAN1.*
{
   if(this.id == myMessage1.id)
   {
      myMessage2.mySignalB = getSignal(myMessage1::mySignalA);
   }
}

Offsets and factors are defined in e.g. the DBC files.

Dmitry Grigoryev
  • 3,156
  • 1
  • 25
  • 53