creating a library - general help needed

Hi,
I wrote a complex day shedule for LEDs.
You can define day schedules (programs) and align them to single LEDs (chanels).
You can change the programs for a chanel during runtime.
You can switch a temporary "non-changing-light" for a chanel.
The programs are defined with "brightnesses"; they may be corrected by gamma-arrays to get the output values for the pin.

I would like to transform this code into a library, but I need some major help.
1.) I do not have an arduino around, so I cannot test it right now.
2.) I use a lot of arrays. For most of them I do not know its size during compiling time. Do I have to declare huge arrays to be on the safe side?
3.) How do I save this code to use it as a library?
4.) Any other suggestions are welcome, too.

Here is my code:

#define max_milliseconds   86400000           // milliseconds per day
#define max_chanels        15                 // 3x RGBWW
#define max_programs       15                 // should be at least max_chanels
#define max_events         100                // max. changes per day
#define max_gamma          6                  // should be one for each color (0rgbww)
#define max_nameLength     12                 // maximum length of program name

class cEvent
{
  public:
    long   time;                              // timestamp | milliseconds until 00:00
    byte   bright;                            // brightness | 0-255
};

class cProgram
{
  public:
    char       name[max_nameLength];
    cEvent     arrEvents[max_events];
    int        SizeArrEvent;                  // size of the array arrEvents
};

class cChanel
{
  public:
    cProgram  *currProgram;                   // pointer to current program
    cProgram  *strdProgram;                   // pointer to standard program
    int        actEvent;                      // active event | or rather passed event
    byte       pin;                           // pin for this chanel
    byte       gamma_ID;                      // ID of color | ID of corresponding gamma array
    long       tmpEndTime;                    // end time of temporary setting
    boolean    tmpActive;                     // status of temporary setting
};

cProgram  arrPrograms[max_programs];          // array of all possible programs
cProgram  arrTmpProg[max_chanels];            // array of temporary programs for each chanel
cChanel  *arrChanels[max_chanels];            // array of all active chanels | one chanel has one pin

byte      arrGamma[max_gamma][256];        // array to get LED-value from brightness

// ****************************************************************
// extern SETUP functions

// sets the initial settings
void LED_init()
{
  long tmpTime[2];
  byte tmpBright[2];
  
  // arrGamma[0] is simply  linear
  for (byte i = 0; i <=255; i++) {arrGamma[0][i] = i;}

  byte o = 22;

  // chanel 0 has sunrise at 07:00 (2h) and sunset at 17:00 (2h)
  tmpTime[0] = 25200000;
  tmpTime[1] = 32400000;
  tmpTime[2] = 61200000;
  tmpTime[3] = 68400000;  
  tmpBright[0] = 0;
  tmpBright[0] = 191;
  tmpBright[0] = 191;
  tmpBright[0] = 0;
  
  LED_setProgram(0, "Standard", 4, tmpTime, tmpBright);
  LED_setChanel(0, 14, 0);
  LED_alignProg2Chan(0, 0);

  // FOR TEST: chanel 1 starts rising 20 seconds after program start, holds 3 seconds and dims down again
  long tmpNow = getDayTime();
  tmpTime[0] = tmpNow + 20000;
  tmpTime[1] = tmpTime[0] + 5000;
  tmpTime[2] = tmpTime[0] + 3000;
  tmpTime[3] = tmpTime[0] + 10000;  
  tmpBright[0] = 0;
  tmpBright[0] = 255;
  tmpBright[0] = 255;
  tmpBright[0] = 0;

  LED_setProgram(1, "Test", 4, tmpTime, tmpBright);
  LED_setChanel(1, 15, 0);
  LED_alignProg2Chan(1, 1);

}

// sets a given program. Defines its name and events.
void LED_setProgram(byte prog_ID, String strName, int evCnt, long arrTime[], byte arrBright[])
{
  strName.toCharArray(arrPrograms[prog_ID].name,max_nameLength); // convert the String to a char array
  arrPrograms[prog_ID].SizeArrEvent = evCnt;
  for (int ev = 0; ev < evCnt; ev++) {
    arrPrograms[prog_ID].arrEvents[ev].time = arrTime[ev];
    arrPrograms[prog_ID].arrEvents[ev].bright = arrBright[ev];
  }  
}

//sets a given chanel. Defines its pin and gamma correction array.
void LED_setChanel(byte chan_ID, byte pin, byte calc_ID)
{
  arrChanels[chan_ID]->pin = pin;  
  arrChanels[chan_ID]->gamma_ID = calc_ID;
  arrChanels[chan_ID]->currProgram = &arrPrograms[0];  
  arrChanels[chan_ID]->strdProgram = &arrPrograms[0];  
  arrChanels[chan_ID]->actEvent = 0;
  arrChanels[chan_ID]->tmpActive = false;  
}

// ****************************************************************
// extern LOOP functions

// sets a given program for a given chanel
void LED_alignProg2Chan(byte prog_ID, byte chan_ID)
{
  arrChanels[chan_ID]->currProgram = &arrPrograms[prog_ID];  
}

// sets a non-changing program and starts it for a given chanel
void LED_setTMP(byte chan_ID, long endTime, byte brightness)
{
  // set the tmp program to given brightness
  arrTmpProg[chan_ID].arrEvents[0].time   = 0;
  arrTmpProg[chan_ID].arrEvents[0].bright = brightness;
  arrTmpProg[chan_ID].arrEvents[1].time   = 10000;
  arrTmpProg[chan_ID].arrEvents[1].bright = brightness;
  // sets the tmp program as current program
  arrChanels[chan_ID]->currProgram = &arrTmpProg[chan_ID];
  
  arrChanels[chan_ID]->tmpEndTime = endTime;
  arrChanels[chan_ID]->tmpActive = true;  
}

// function to be called in the main-loop
void LED_loop(long tNow)
{
  for (byte i = 0; i < max_chanels; i++) {
    if (arrChanels[i]->tmpActive) {
      if (arrChanels[i]->tmpEndTime == 0) { // 0 is for endless
        if (tDiff(tNow,arrChanels[i]->tmpEndTime) < (max_milliseconds - 3000)) { // still active
          arrChanels[i]->currProgram = &arrTmpProg[i];
        } else {
          arrChanels[i]->tmpActive = false;
          arrChanels[i]->currProgram = arrChanels[i]->strdProgram;
        }
      }
    }
  }
  // if this is to slow than I change to one pin per loop
  for (byte chanel = 0; chanel < max_chanels;chanel++) {setBrightness(chanel,tNow);}
}

// ****************************************************************
// intern functions

// get time of day in milliseconds from 00:00
long getDayTime()
{

}

// calculates the time difference between timeA and timeB
long tDiff(long timeB, long timeA)
{
  // rollover
  if (timeB < timeA) timeB = timeB + max_milliseconds;
  return (timeB - timeA);
}

// checks if event is last event and calculates next event
int nextEvent(int Ch, int event)
{
  if (event < arrChanels[Ch]->currProgram->SizeArrEvent) {
    return event + 1;
  } else {
    return 0;
  }
}

//calculates and sets value of a single chanel (pin)
void setBrightness(byte Ch, long time)
{
  int event;
  long time1;
  long time2;
  boolean eventChecked = false;

  do
  {
    event = arrChanels[Ch]->actEvent;
    time1 = arrChanels[Ch]->currProgram->arrEvents[event].time;
    time2 = arrChanels[Ch]->currProgram->arrEvents[nextEvent(Ch, event)].time;
    // move to next event if necessary
    if ((tDiff(time,time2)) < (tDiff(time,time1))) {arrChanels[Ch]->actEvent = nextEvent(Ch,event);} else {eventChecked = true;}
  } while (!eventChecked);

  byte bright1 = arrChanels[Ch]->currProgram->arrEvents[event].bright;
  byte bright2 = arrChanels[Ch]->currProgram->arrEvents[nextEvent(Ch, event)].bright;

  // milliseconds per one increment
  int millisPerInk = round((tDiff(time2,time1)) / (bright2 - bright1));

  byte brightness = byte(bright1 + ((tDiff(time,time1)) / millisPerInk));
    
  byte value = arrGamma[arrChanels[Ch]->gamma_ID][brightness];
  analogWrite(arrChanels[Ch]->pin, value);
}

void setup()
{
  LED_init();
}



void loop()
{
  long tNow = getDayTime();
  // check if temporary programs are active
  LED_loop(tNow);
}

Kevin

make all constants at least explicit unsigned long by adding UL after the number e.g. 86400000UL

I do not have any constants in my code. Should I use a constant for the max_milliseconds?
All the other defines are for defining array sizes. That touches my question #2. How could I use constants for that?

KevinT:
All the other defines are for defining array sizes.

Constants are values that do not change during run-time. The values used in the #define directives don't change during run-time, therefore, they are constants.

You are right, of course, but I do not understand why setting them to explicit unsigned should make any difference.

#define max_chanels        15                 // 3x RGBWW
#define max_programs       15                 // should be at least max_chanels
#define max_events         100                // max. changes per day
...
#define max_nameLength     12                 // maximum length of program name
...
class cEvent
{
  public:
    long   time;                              // timestamp | milliseconds until 00:00
    byte   bright;                            // brightness | 0-255
};

class cProgram
{
  public:
    char       name[max_nameLength];
    cEvent     arrEvents[max_events];
    int        SizeArrEvent;                  // size of the array arrEvents
};
...

cProgram  arrPrograms[max_programs];          // array of all possible programs
cProgram  arrTmpProg[max_chanels];            // array of temporary programs for each chanel

That's 9420 bytes of RAM gone right there. What Arduino are you planning to run this on?

byte      arrGamma[max_gamma][256];        // array to get LED-value from brightness

Another 1536 bytes there.

Even the Atmega2560 has only got 8 Kb of RAM.

I do have the Atmega2560, but you are right. That is way to much. My big problem is the fixed array size. In most cases I need 3-4 events in a program, but there are cases where I need 70-80. That is what I meant by my question concerning the array sizes.

To make the code work I should set the max_events to 10 and max_gamma to 1, but for the future I would love to loosen these restrictions. Is there any way to do this without the tricky task of designing dynamic arrays?

Aside from the storage problems (which could be solved by an additional memory) how do I make a library? Simply saving the file as library.h would not do right?
And how do I declare variables or functions as private or as public?

Here are some useful links.

http://www.cplusplus.com/doc/tutorial/
http://www.cplusplus.com/doc/tutorial/classes/
http://www.cplusplus.com/doc/tutorial/classes2/

And how do I declare variables or functions as private or as public?

by declaring them within the appropriate section: public, protected or private.

class A{
  public:

    void public_function( void );

  protected:

    void protected_helper_function( void );

  private:
    
    char private_data;
};

Thanks for the links.