Re: How can I make this initialization happen at compile time?

what is setupPin()?

Doing this through a template will not make the code prettier or shorter - I think you will have to explicitly specialize the template for each pin variant.

can you just statically initialize those 3 fields of each instance of the class using a macro of setup()?

Is stepPin known at compile time? If it is a parameter of your constructor I don't see that it is known at compile time.

Sounds like an opportunity for EEPROM to save the variant between runs, or an unused input pin to be strapped/tested for either variant at runtime.

Why give up the ability to choose the pin dynamically at run-time? With that ability, a single code could serve multiple hardware setups with the pin chosen by strapping option, user input, or the previous value from non-volatile storage.

Seems to me that the run-time cost of the setupStepPin() function is pretty low (i.e. not worth the effort and loss of flexibility of making it a compile-time thing), especially given that it probably only happens once at start up. I'd use an lookup table of R_GPT0_Type* values and index it with the pin number.

But then it can't be selected by user input, strapping option, or EEPROM value. So, if the user has multiple hardware setups, they must write and compile a separate code for each one.

That's the point, it could ... once at startup.

I still don't see the bang for the buck of doing all that template specialization .... for a function that only runs once anyway. What's the benefit?

2 Likes

Yup.

How about:

template<uint8_t PIN>
void setupStepPin() {
  Serial.print("Illegal Pin: ");
  Serial.println(PIN);
}

template<>
void setupStepPin<1>() {
  Serial.println("I Know How to Set Up for Pin 1");
}

template<>
void setupStepPin<2>() {
  Serial.println("I Know How to Set Up for Pin 2");
}

template<>
void setupStepPin<3>() {
  Serial.println("I Know How to Set Up for Pin 3");
}

template<>
void setupStepPin<4>() {
  Serial.println("I Know How to Set Up for Pin 4");
}

void setup() {
  Serial.begin(115200);
  delay(3000);
  setupStepPin<1>();
  setupStepPin<2>();
  setupStepPin<3>();
  setupStepPin<4>();
  setupStepPin<5>();
}

void loop() {
}
I Know How to Set Up for Pin 1
I Know How to Set Up for Pin 2
I Know How to Set Up for Pin 3
I Know How to Set Up for Pin 4
Illegal Pin: 5

But, it's still a run-time function.

Post that code.

Choose a pin without having to know what timer to use to make it work.
= "hobbyist"-friendly library

But the user will define it only in the .ino file. If you provide your code as a library, than it is compiled separately, and the pin is not known at compile time in this compiler run. You have to include your complete class definition into the .ino and the user must define the pin before the include. It must all be compiled in one run. That's not how libraries usually work.

С++ templates do not able a partial specialization for a class. You will have to copy entire class to each specialization option.
To avoid this you could define a base class with all data and methods, and inherit a child class from it, where you just override the setupStepPin() method. Then define the pin specialization for the child class, similar to that as @gfvalvo presented.

Some previous discussion on the topic :

However, it seems like if you change the underlying pin abstraction then you also need to rewrite each and every library that uses IO pins.

One application area that needs flexible compile-time user config and also efficient run time is in 3D printer/CNC firmware, e.g. grbl, Marlin. I'm very much in the "Keep it Simple" camp, and so far I haven't seen a C++ abstraction for IO pins that I would use; macros and inline functions are "good enough".

The sad thing about computer science is that despite all our efforts to engineer better software, these come at a cost of greater complexity. But the hardware guys can just drop in a new CPU which is cheaper and faster, and then many of our concerns about RAM and CPU cycles disappear.

You completely missed the point. The discussions was about whether the automatic (hobbyist friendly) binding of pin to timer works at compile time or run time. Either way, it's automatic.

There are many templated Arduino libraries. And that's how they work. The entire implementation is either in a .h file or an #included(d) .hpp file.

That's how templated libraries work. Check out FastLED for example, not to mention the entire C++ STL.

1 Like

Ok, never came across such libraries so far. Obviously I don't know enough about class templates :wink: :innocent:.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.