tags:

views:

55

answers:

3

I´m currently writing a software in Ansi-C and are struggling to get one of the basic functionality to work.

The software will receive messages over a CAN-network and when these messages arrive, I need to make sure that they are delivered before a expected time and after the previous message.

Only unsigned variables are allowed to be used, so there will be problems with wrap around when the timers reach their maximum value (255 in my case).

It is easy to verify that messages arrive before the expected time, since I know the maximum time between two messages.

This example handles wrap around and discovers messages that are late:

UC_8 arrival = 250;  
UC_8 expected = 15;
UC_8 maxInterArrTime = 30;

result = expected - arrival;

if(result <= maxInterArrTime){
// ON TIME!
}
else{
// DELAYED
}

This is the easy part, but I must also check that the arrived message actually have arrived after the previous message. My problem is that I do not know how to solve this with the wrap around problem. I tried to mimic the solution that finds delayed messages, but without any luck.

UC_8 arrival = 10; // Wrapped around
UC_8 lastArrival = 250;  
UC_8 expected = 15;
UC_8 maxInterArrTime = 30;

result = expected - arrival;
result2 = lastArrival - arrival; //Problem

if(result2 >= ???){ // How should I compare and with what?
  //Message received after previous msg

  if(result <= maxInterArrTime){
  // ON TIME!
  }
  else{
  // DELAYED
  }
else{
  //Message received before previous msg - ERROR
}

My problem is when the arrival time value is lower than the previous arrival time, but is actually "larger" since it has wrapped around. I guess I might need to do it i several steps.

Any suggestions how I can solve this? I need to keep the number of if-statements low, the code will be analysed for complexity and other stuff.

+1  A: 

Huh? You can't magically code your way around a case of missing information. If you only have 8-bit unsigned timestamps, then you will not be able to differentiate between something that happened 3 ticks ago, and something that happened 259 ticks ago, and so on.

Look into making larger (more bits) timestamps available.

unwind
Yes that is true, I am aware of that problem, this is only a part of the total solution with sequence numbers, message tables etc.As stated earlier in the post, the first solution works to find out if a message is delayed or delivered before the expected time. The problem is to find out if a message is delivered within a specific time frame(after previous and before expected time).
Jesper Melin
+1  A: 

If you can GUARANTEE that the delay between packets will not be 256 or more then the following will account for wrap around

if (newerTime >= olderTime)
  delay = newerTime - olderTime;
else
  delay = 256 - olderTime + newerTime;

If you can't guarantee the delay is less than 256 then unwind is correct, and you can't do what you want to do.

torak
Thanks for the answer. There might be a chance that messages are delayed for more than 256 time units, I need to investigate the system specification and the other documents to answer that correctly.
Jesper Melin
A: 

If you can ensure that the absolute value of the time delta is less than 1/2 of the maximum measurable time span then you can determine the time delta.

int8_t delta_u8(uint8_t a, uint8_t b) {
    int8_t delta = a - b;
    return delta;
}

...

  delta = delta_u8(newerTime, olderTime);
  delay = abs( (int) delta ); // or you could have a byte version of abs, since
                              // I suspect that you may be doing embedded stuff
                              // and care about such things.

If you can ensure that time always move forward then you can do better. By time moving forward I mean that in your case newerTime is always greater than olderTime, regardless of how they numerically compare. In this case you can measure deltas up to the maximum measurable time span -- which really goes without saying.

uint8_t delta_i8(uint8_t a, uint8_t b) {
    return a - b;
}

If you know that two events can't happen during the same tick you can do even better by 1. If you know that two events can't happen closer together than a certain amount of time then you can calculate deltas up to maximum time span representable by your time stamp + the amount of time that must be between events, but then you have to use a larger variable size to do the actual math.

All of these work because the values rap around when you do math on them. You can very easily think of this as turning one of your known time values into the new origin (0) and adjusting the other time value to match this shift.

nategoose
In `delta_u8()`, assigning a result from `a - b` that is out of range for `int8_t` formally gives an implementation-defined result.
caf