1

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;
  • afaik, since you assign to a different place each leaf, you can't use a look-up array, you need flow. – dandavis Mar 30 '17 at 6:26
1

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.

2

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

  • That's wonderful, I didn't know about the token-pasting operator, msdn.microsoft.com/en-us/library/09dwwt6y.aspx – user8437812 Mar 30 '17 at 12:49
  • Note that this does not work with variables, so OCR_BY_INDEX(timer) does not work. This is a good solution if you don't need that. – Paul Jul 30 '18 at 15:10
1

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.