Question

I have some problems with memory. Is it possible to reduce memory of compiled program in this function?

It makes some calculations with time variables {hh,mm,ss.0} and returns time (in millis) that depends on current progress (_SHOOT_COUNT)

unsigned long hour_koef=3600000L;
unsigned long min_koef=60000;

unsigned long timeToMillis(int* time)
{
  return (hour_koef*time[0]+min_koef*time[1]+1000*time[2]+100*time[3]);
}

float Func1(float x)
{
  return (x*x)/(x*x+(1-x)*(1-x));
}

float EaseFunction(byte percent,byte type)
{
  if(type==0)
    return Func1(float(percent)/100); 
}


unsigned long DelayEasyControl()
{

  long dd=timeToMillis(D1); 
  long dINfrom=timeToMillis(Din);
  long dOUTto=timeToMillis(Dout);
  if(easyINmode==0 && easyOUTmode==0) return dd;
  if(easyINmode==1 && easyOUTmode==0)
  {
    if(_SHOOT_COUNT<duration) return (dINfrom+(dd-dINfrom)*EaseFunction(_SHOOT_COUNT*100/duration,0));
    else return dd;
  } 
  if(easyOUTmode==1)
  {
    if(_SHOOT_COUNT>=_SHOOT_activation && _SHOOT_activation!=-1)
    {   
      if((_SHOOT_COUNT-_SHOOT_activation)<current_settings.delay_easyOUT_duration) return (dOUTto-(dOUTto-dd)*(1-EaseFunction((_SHOOT_COUNT-_SHOOT_activation)*100/duration,0)));
      else return dOUTto;
    } 
    else 
    {
      if(easyINmode==0) return dd;
      else if(_SHOOT_COUNT<duration) return (dINfrom+(dd-dINfrom)*EaseFunction(_SHOOT_COUNT*90/duration,0));
      else return dd;
    }
  }
}
Was it helpful?

Solution

You mention that it's code size you want to optimize, and that you're doing this on an Arduino clone (based on the ATmega32U4).

Those controllers don't have hardware support for floating-point, so it's all going to be emulated in software which takes up a lot of code.

Try re-writing it to do fixed-point arithmetic, you will save a lot of code space that way.

You might see minor gains by optimizing the other data types, i.e. uint16_t instead of long might suffice for some of the values, and marking functions as inline can save the instructions needed to do the jump. The compiler might already be inlining, of course.

OTHER TIPS

Most compilers have an option for optimizing for size, try it first. Then you may try a non-standard 24-bit float type available in some compilers for 8-bit MCUs like NXP's MRK III or MPLAB XC8

By default, the XC8 compiler uses a 24-bit floating-point format that is a truncated form of the 32-bit format and that has eight bits of exponent but only 16 bits of signed mantissa.

Understanding Floating-Point Values

That'll reduce the floating-point math library size a lot without any code changes, but it may still be too big for your MCU. In this case you'll need to rewrite the program. The most effective solution is to switch to fixed-point (A.K.A scaled integers) like @unwind said if you don't need very wide ranges. In fact that's a lot faster and takes much less ROM size than a software floating-point solution. Microchip's document above also suggests that solution:

The larger IEEE formats allow precise numbers, covering a large range of values to be handled. However, these formats require more data memory to store values of this type and the library routines that process these values are very large and slow. Floating-point calculations are always much slower than integer calculations and should be avoided if at all possible, especially if you are using an 8-bit device. This page indicates one alternative you might consider.

Also, you can try storing duplicated expressions like x*x and 1-x to a variable instead of calculating them twice like this (x*x)/(x*x+(1-x)*(1-x)), which helps a little bit if the compiler is too dumb. Same to easyINmode==0, easyOUTmode==1...


Some other things:

  • ALL_CAPS should be used for macros and constants only
  • Identifiers begin with _ and a capital letter is reserved for libraries. C may also use it for future features like _Bool or _Atomic. See What are the rules about using an underscore in a C++ identifier? (Arduino is probably C++)
  • Use functions instead of macros for things that are reused many times, because the inline expansion will eat some space each time it's used
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top