user32118: I'm writing a helper class to manage timers, and I'm writing a lot of code like
if (timer == 1)
        ICR1 = icr;
    else if (timer == 3)
        ICR3 = icr;
    else if (timer == 4)
        ICR4 = icr;
    else if (timer == 5)
        ICR5 = icr;

Is there a better way to store these registers?
e.g. an array
timers {
{ ICR1, TCCR1A, OCR1A, OCR1B },
{ ICR2, TCCR2A, OCR2A, OCR2B }

etc.
to be accessed like
timers[1][0]

for ICR1.
And ultimately, how would I assign a value? e.g.
*timers[1][0] = 100;

UPDATE:
I solved the problem with
volatile uint16_t* ICRs[5];
ICRs[1] = &ICR1;
ICRs[3] = &ICR3;
ICRs[4] = &ICR4;
ICRs[5] = &ICR5;

*ICRs[1] = x;


user31105: You can better use a switch statement:
switch (timer)
{
case 1:
    ICR1 = icr;
    break;

case 3:
    ICR3 = icr;
    break;

case 4:
    ICR4 = icr;
    break;

case 5:
    ICR5 = icr;
    break;

default:
    // Handle other cases
    break;
}

About the variables:
You can make a 2 dimensional array:
typedef enum
{
   TYPE_ICR,   // Value 0
   TYPE_TCCRA, // Value 1
   TYPE_OCRA,  // Value 2
   TYPE_OCRB,  // Value 3
   TYPE_LAST,  // Value 4
} EType;

EType timers[TYPE_LAST][2]; 

You can access it by
timers[(int) TYPE_OCRB][0] = 3;
timers[(int) TYPE_OCRA][1] = 0;

Maybe the (int) cast is not needed.
You also can just iterate over the type:
for (int type = 0; type < (int) TYPE_LAST; type++)
{
    timers[type][0] = -1;
    timers[type][1] = -1;
}

Note 1: if a cast is needed probably static_cast(...) is better to use.
Note 2: I haven't tested the code above

user30005: registers are nothing but pointers to memory addresses. so the best way to "parameterize" them is to do so via pointers.
assuming that ICRi is of 8-bit types - they are NOT to be sure:
uint8_t *ICRs[4];  //isr pointers

//initialize the icrs
ICRs[0]=(uint8_t *)&ICR0;
ICRs[1]=(uint8_t *)&ICR1;
...

*ICRs[i]=icr; //assign value to ICRi

note: that piece of code isn't operable in reality. The way to go is to use a pointer to void. But I'm sure you can figure that out.

user29899: i would suggest creating macro definitions for the timers you want
Something along the lines of:
#define OCR_BY_INDEX(i) OCR##i
//...other code...
OCR_BY_INDEX(1) = value;

and then have the indices in an array

32118: <p>I'm writing a helper class to manage timers, and I'm writing a lot of code like</p>

<pre><code>if (timer == 1)
        ICR1 = icr;
    else if (timer == 3)
        ICR3 = icr;
    else if (timer == 4)
        ICR4 = icr;
    else if (timer == 5)
        ICR5 = icr;
</code></pre>

<p>Is there a better way to store these registers?
e.g. an array</p>

<pre><code>timers {
{ ICR1, TCCR1A, OCR1A, OCR1B },
{ ICR2, TCCR2A, OCR2A, OCR2B }
</code></pre>

<p>etc.</p>

<p>to be accessed like</p>

<pre><code>timers[1][0]
</code></pre>

<p>for ICR1.</p>

<p>And ultimately, how would I assign a value? e.g.</p>

<pre><code>*timers[1][0] = 100;
</code></pre>

<p><strong>UPDATE:</strong></p>

<p>I solved the problem with</p>

<pre><code>volatile uint16_t* ICRs[5];
ICRs[1] = &amp;ICR1;
ICRs[3] = &amp;ICR3;
ICRs[4] = &amp;ICR4;
ICRs[5] = &amp;ICR5;

*ICRs[1] = x;
</code></pre>
 31105: <p>You can better use a switch statement:</p>

<pre><code>switch (timer)
{
case 1:
    ICR1 = icr;
    break;

case 3:
    ICR3 = icr;
    break;

case 4:
    ICR4 = icr;
    break;

case 5:
    ICR5 = icr;
    break;

default:
    // Handle other cases
    break;
}
</code></pre>

<p>About the variables:</p>

<p>You can make a 2 dimensional array:</p>

<pre><code>typedef enum
{
   TYPE_ICR,   // Value 0
   TYPE_TCCRA, // Value 1
   TYPE_OCRA,  // Value 2
   TYPE_OCRB,  // Value 3
   TYPE_LAST,  // Value 4
} EType;

EType timers[TYPE_LAST][2]; 
</code></pre>

<p>You can access it by</p>

<pre><code>timers[(int) TYPE_OCRB][0] = 3;
timers[(int) TYPE_OCRA][1] = 0;
</code></pre>

<p>Maybe the (int) cast is not needed.</p>

<p>You also can just iterate over the type:</p>

<pre><code>for (int type = 0; type &lt; (int) TYPE_LAST; type++)
{
    timers[type][0] = -1;
    timers[type][1] = -1;
}
</code></pre>

<p>Note 1: if a cast is needed probably static_cast(...) is better to use.
Note 2: I haven't tested the code above</p>
 30005: <p>registers are nothing but pointers to memory addresses. so the best way to "parameterize" them is to do so via pointers.</p>

<p><em>assuming</em> that ICRi is of 8-bit types - they are NOT to be sure:</p>

<pre><code>uint8_t *ICRs[4];  //isr pointers

//initialize the icrs
ICRs[0]=(uint8_t *)&amp;ICR0;
ICRs[1]=(uint8_t *)&amp;ICR1;
...

*ICRs[i]=icr; //assign value to ICRi
</code></pre>

<p><em>note:</em> that piece of code isn't operable in reality. The way to go is to use a pointer to void. But I'm sure you can figure that out.</p>
 29899: <p>i would suggest creating macro definitions for the timers you want</p>

<p>Something along the lines of:</p>

<pre><code>#define OCR_BY_INDEX(i) OCR##i
//...other code...
OCR_BY_INDEX(1) = value;
</code></pre>

<p>and then have the indices in an array</p>
