0

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;
    }
  }
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
redcapp
  • 3
  • 2
  • I can't see a single allocation of memory here. What does `EaseFunction` do? How did you arrive at the conclusion that this function is using too much memory? – Lasse V. Karlsen Apr 16 '14 at 12:06
  • Sorry, I meant compiled programm size ) EaseFunction look like this `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); }` – redcapp Apr 16 '14 at 12:11
  • The you should edit the question, makes it easier for others to both find and understand your question. – Lasse V. Karlsen Apr 16 '14 at 12:13
  • That code doesn't look big. What kind of machine/microcontroller/environnment are you targeting ? – Jabberwocky Apr 16 '14 at 12:35
  • It's for arduino clone leonardo pro micro with ATmega32U4 onboard – redcapp Apr 16 '14 at 12:38
  • 2
    Did you try the -Os option for gcc (take a look here: http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html)? also you could try to strip your binary after compiling (http://sourceware.org/binutils/docs-2.16/binutils/strip.html). – mschoenebeck Apr 16 '14 at 12:41
  • I'm currently using arduino Ide 1.05, i'll try gcc, thanks – redcapp Apr 16 '14 at 12:43
  • Btw you are not allowed to use names starting with underscores followed by an uppercase in C, those are reserved for the standard library implementation. – Étienne Apr 16 '14 at 12:51
  • Yes names like `_Bool` are reserved – phuclv Apr 16 '14 at 13:38

2 Answers2

4

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.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • yep ! thanks again - it works ) using FIXED calculations I saved more than 2.5kB over programm ) `#define FIXED_FBITS 8 #define FIXED_TO_INT(a) ((a) >> FIXED_FBITS) #define FIXED_FROM_INT(a) (int32_t)((a) << FIXED_FBITS) #define FIXED_MAKE(a) (int32_t)((a*(1 << FIXED_FBITS))) static int32_t FIXED_Mul(int32_t a, int32_t b) { return(((int32_t)a*(int32_t)b) >> FIXED_FBITS); }` – redcapp Apr 17 '14 at 10:30
0

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
Community
  • 1
  • 1
phuclv
  • 37,963
  • 15
  • 156
  • 475