Best way to determine CPU type at compile time?

I am working on a (yet another...) pin change interrupt library. It underlies an encoder library that will allow connections on ANY pin, even when they map to two different ports...

I do a lot of work with smaller cpu - e.g. tiny25/45/85, 24/44/84 etc. The goal is to have the code compile on ALL variants I use. It currently works fine for UNO abd MEGA2560, but I know I'm going to need some #ifdef to get it working across the board.

I have the tiny IDE addons that has boards.txt and variants for "tiny8" and "tiny14"

For example, tiny8s only use one pinchange interrupt, so i'd like to #ifdef out the PCINT1_vect and PCINT2_vect handlers for efficiency...also I'd like to set constants for the different number of allowable PCINT -> digital pin mappings, e.g. 20 on the UNO but only 16 on the MEGA and 4 on a tiny85 (and/or use different names and correct lack of NUM_DIGITAL_PINS definition etc)

I know I could say #ifdef attiny25 || attiny45 || attiny85 (or similar) but i'd rather say #ifdef tiny8... #ifdef tiny14 etc

  • is there any way to get hold of the current variant at compile time? And whats the BEST way to determine processor, processor family @ compile time?

And whats the BEST way to determine processor, processor family @ compile time?

Ask the user to select one. Isn’t that the point of the Tools:Board selection?

Im talking about conditional compilation so that once a user has nominated a board, my #ifdef can tell what was selected and add/omit blocks of code depending on what processor it is being compiled for

Look inside the source for the current libraries. There are lots of tests for the processor type there.

This is how I do it in one of my multi-platform libs ( the AVR section anyway ), I think fat16lib did the hard work of gathering up all the processor defines.

This is what it can detect now. * ATmega - 32u4 - 168 - 168p - 328p - 644 - 644p - 1280 - 1284p - 2560

  • AT90USB
  • 646
  • 1286
// 168 and 328 Arduinos
#if defined(__AVR_ATmega168__) ||defined(__AVR_ATmega168P__) ||defined(__AVR_ATmega328P__)
  #define CHIPSET ATmega_168_168P_328P 
// Mega 1280 & 2560
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  #define CHIPSET ATmega_1280_2560 
// Sanguino
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
  #define CHIPSET ATmega_644_644P_1284P 
#elif defined(__AVR_ATmega32U4__)

  // Teensy 2.0
  #ifdef CORE_TEENSY 
    #define CHIPSET ATmega_32U4_A 

  // Teensy
    #define CHIPSET ATmega_32U4_B 
// Teensy++ 1.0 & 2.0
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  #define CHIPSET AT90USB_646_1286 


You can remove the CHIPSET define and the file include, then fill in with your own design.

thanks for that. It was what I first had in mind - I was hoping to avoid the complexity by being able to read the "variant" somehow..

Note that much of the core library has moved away from detecting individual processors, and toward detecting definitions associated with the particular peripherals. So instead of doing

ISR(PCINT0_vect) ... // always present
#if defined(__AVR_ATmega168__) ||defined(__AVR_ATmega168P__) ||defined(__AVR_ATmega328P__)
ISR(PCINT1_vect) ...  // Only present on mega cpus.
ISR(PCINT2_vect) ...

You would do

#if defined(PCINT0_vect)  // present on most CPUs.
ISR(PCINT0_vector) ...
#if defined(PCINT1_vect)  // present on some CPUs
ISR(PCINT1_vector) ...
#if defined(PCINT2_vect)  // prsent on some other CPUs.
ISR(PCINT2_vector) ...

Which is, IMO, MUCH nicer; it has a good chance of automatically working on CPUs you didn't think about. (although, things might not work correctly overall, on cpus you didn't think about. Which could be worse than not working at all.)

Yep, that is the sort of thing I had in mind. I was hoping to find some sort of "family" value, e.g. AVR1PCINT for tiny25/45/85 and AVR3PCINT for 328p etc. I had thought about checking for register definitions, your suggestion jusr convinvced me its the best way to go. Still wish there was a value for number of mapped pcints though...

the digitalPinToxxxx macros help a lot, but on the mega2560 NUM_DIGITAL_PINS is 70 whereas only 16 of them are my attiny cores, NUM_DIGITAL_PINS isnt defined at all for attiny85 and the version og gcc currently used by arduino doesnt include definitions for the 2313A (which differs a lot from the 2313) so whatever happens, its going to be a bit of a wrestling match and the code is going ro get scrappy!

So would all the things like

#if defined(PCINT0_vect)  // present on most CPUs.
ISR(PCINT0_vector) ...

go into a general pins_arduino.h, or a more general higher level (for lack of a better term)?