Search code examples
cmacrosc-preprocessoravr

Building Macro from Parts


I'm working on a an AVR, and the libraries include device interrupt vectors like TCD0_OVF_vect and TCD0_CCA_vect using preprocessor #defines as follows:

#define TCD0_OVF_vect_num  77
#define TCD0_OVF_vect      _VECTOR(77)  /* Overflow Interrupt */

They also include timer objects:

typedef struct TC0_struct
{
  register8_t CTRLA;  /* Control  Register A */
  ...snip...
} TC0_t;

#define TCD0    (*(TC0_t *) 0x0900)  /* 16-bit Timer/Counter 0 */

I want to be able to define a macro that will expand a named timer object, TCD0, to TCD0_OVF_vect using a syntax similar to VECT(TCD0, OVF_vect). For example:

ISR(VECT(TCD0, CCA_vect)) {}

converts to

ISR(TCD0_CCA_vect) {}

where TCD0_CCA_vect is a macro that needs to be expanded.

Is there a way to do this?

Edit: In addition, I would love to be able to do:

#define TIMER TCD0
#define VECT(a, b) ##SOMETHING##

and then be able to use VECT(TIMER, CCA_vect) and end up with TCD0_CCA_vect. I know this requires another level of indirection, but I can't quite wrap my head around it.


Solution

  • That's quite easy:

    #define VECT(a, b)  a##_##b
    

    The X##Y will concatenate X and Y as a single identifier.

    In your particular case, you need to concatenate TCD0, _ and CCA_vect into a single identifier TCD0_CCA_vect.

    Note that this won't work with variables!