md_max72xx matrix type #define

Hi,

I have now a couple of matrices modules, one work with USE_FC16_HW and the other with USE_ICSTATION_HW.
Can anyone see a way to define this without having to change the MD_MAX72XX.h file every time I want to compile for one matrix or to the other ?

I guess this means it is not possible to use the 2 matrices in the same sketch, not that I need it now, I just noticed it.

thanks.

ocsav:
Can anyone see a way to define this without having to change the MD_MAX72XX.h file

When you mention a 3rd party library on the forum it's helpful to add a link to where we can find that library (in this case https://github.com/MajicDesigns/MD_MAX72XX/blob/master/src/MD_MAX72xx.h). Note that I used the chain links icon in the toolbar to make the URL clickable. We shouldn't need to go on a search to find a library just to help you out. Sometimes there are even multiple libraries of the same name so we might get the wrong one and end up in a lot of confusion.

ocsav:
having to change the MD_MAX72XX.h file every time I want to compile for one matrix or to the other ?

Do you want to use the different configurations in the same sketch, or in two different sketches?

ocsav:
I guess this means it is not possible to use the 2 matrices in the same sketch, not that I need it now, I just noticed it.

I wonder if it was actually necessary to use the preprocessor for this purpose in the library? If the library was written so that you could configure it at runtime (e.g. mx.configure(USE_FC16_HW)) then you could switch between configurations as needed (at the expense of some overhead).

You have to set it every time. In practice this is not an issue for most people as they only have one type of matrix.

Allowing different matrices in the chain would add a level of complexity that has little practical benefit, so this is not supported.

I wonder if it was actually necessary to use the preprocessor for this purpose in the library?

What would be even better would be if the Arduino environment allowed the #define to be in your code and just picked up in the libraries...

pert:
When you mention a 3rd party library on the forum it's helpful to add a link to where we can find that library (in this case https://github.com/MajicDesigns/MD_MAX72XX/blob/master/src/MD_MAX72xx.h). Note that I used the chain links icon in the toolbar to make the URL clickable. We shouldn't need to go on a search to find a library just to help you out. Sometimes there are even multiple libraries of the same name so we might get the wrong one and end up in a lot of confusion.

I'm really sorry, I didn't stop to think about it. You are right of course. It wont happen again.

Do you want to use the different configurations in the same sketch, or in two different sketches?

I was thinking in 2 different sketches.
As it is now, if sketch_A uses a matrix that needs USE_FC16_HW you have to edit the library .h in order to compile, and if you have sketch_B that uses another matrix you'll have to change it again, it can become confusing fast...
[/quote]

For the situation of two sketches I would recommend bundling a copy of the library with each sketch, that way you can have each copy customized for the specific sketch it's bundled with.

sketch_A
|_sketch_A.ino
|_src
|_MD_MAX72XX

All the library files are not shown in the above diagram, but you get the idea,

Then in sketch_A.ino, the #include directive for the library looks like this:

#include "src/MD_MAX72XX/src/MD_MAX72xx.h"

And do the same for sketch_B as well.

Note this requires a relatively recent version of the Arduino IDE, something like 1.6.9 and newer.

marco_c:
You have to set it every time. In practice this is not an issue for most people as they only have one type of matrix.

Allowing different matrices in the chain would add a level of complexity that has little practical benefit, so this is not supported.
What would be even better would be if the Arduino environment allowed the #define to be in your code and just picked up in the libraries…

The problem is that you can have to use different HW types just because you have the same type of modules wired in a different way.
I had a 4x1 matrix of USE_FC16_HW modules, it worked ok with the input wires to the right.
I have now a 2x2 matrix, the modules looks to be the same but they are wired like this (the / means there is a link between the bottom left module and top right module.

[out]O

O

O

O[in]

[out]O = O
/
O = O[in]

In order for this to work I have the 4x1 matrix as USE_FC16_HW and the 2x2 as USE_ICSTATION_HW.

I don’t know enough about C++ to know if it would be very difficult to accept a parameter when creating the ‘P’ object, but I totally accept your answer that it would not be trivial.

But I think it would not be very difficult if we had to do a

#define USE_HW 1 (or 2 or 3 or 4)
#include <MD_MAX72XX.h>
#include <SPI.h>

and set the correct values inside MD_MAX72XX.h with #ifdef.
I don’t think it is a good idea to have the user to change the library .h, bad things can easily happen. I can see for the documentation that you are sick and tired of replying “edit MD_MAX72XX.h and set your matrix type” to complains of md_parola is not working. With this, if you had a

#ifndef USE_HW
#error "You must define your matrix type before including MD_MAX72XX.h, use 1 for ....."
#endif

That would stop compilation on the spot and end the “it’s not working with my matrix” complains.

pert:
For the situation of two sketches I would recommend bundling a copy of the library with each sketch, that way you can have each copy customized for the specific sketch it's bundled with.

sketch_A
|_sketch_A.ino
|_src
|_MD_MAX72XX

Yes, that is a way to do it, I think I'd use 'libs' instead of 'src' the the effect is the same, however I don't like to have multiple copies of the same lib, one day they'll be out of sync as I can't use the IDE's library manager any more.

But it fact that might be the best way to make sure that the code keeps working even if the lib evolves in an incompatible way.

Thank you.

ocsav:
But I think it would not be very difficult if we had to do a

#define USE_HW 1 (or 2 or 3 or 4)

#include <MD_MAX72XX.h>
#include <SPI.h>

Unfortunately that’s not possible with the library in its current form. The problem is that the library’s .cpp files are a separate translation unit from the .ino file so the macros you #define in the .ino will not be seen by the .cpp. The workaround would be to move all the code that relies on the macros to the .h files, where it is visible.

ocsav:
Yes, that is a way to do it, I think I’d use ‘libs’ instead of ‘src’ the the effect is the same

That won’t work. The Arduino IDE has special handling of the ‘src’ subfolder of the sketch folder. That is the only folder where recursive compilation will be done. You could add a ‘libs’ folder under the ‘src’ folder if you like.

ocsav:
however I don’t like to have multiple copies of the same lib, one day they’ll be out of sync as I can’t use the IDE’s library manager any more.

Yes, that’s definitely a problem. I always prefer to avoid the bundled library solution if at all possible. The whole point of a library is to share code between multiple projects. However, I do think this is the most simple solution. The other potential solutions would either involve modifying boards.txt for any board that you will be using the library with (and redoing that modification whenever you update the hardware package). Or a significant restructuring of the library (either moving code to the .h files or permitting configuration via the library API).

pert:
Unfortunately that’s not possible with the library in its current form. The problem is that the library’s .cpp files are a separate translation unit from the .ino file so the macros you #define in the .ino will not be seen by the .cpp. The workaround would be to move all the code that relies on the macros to the .h files, where it is visible.

Ok I was thinking that I could use #if to test for a value, I see that it’s not the case.
I don’t have access to Arduino IDE here, but I made up something with gcc (in linux) that might work.

///// file a.c
#define USE_HW_3
#include "a.h"

#include <stdio.h>
main()
{
        printf("%d - %d - %d\n", AAA, BBB, CCC);
}
/////// file a.h
#if !defined(USE_HW_1) && !defined(USE_HW_2) && !defined(USE_HW_3)
#error "You must define USE_HW_1 or USE_HW_2 or USE_HW_3"
#else
        #ifdef USE_HW_1
                #define AAA 1
                #define BBB 0
                #define CCC 0
        #else
                #ifdef USE_HW_2
                        #define AAA 0
                        #define BBB 1
                        #define CCC 0
                #else
                        #ifdef USE_HW_3
                                #define AAA 0
                                #define BBB 0
                                #define CCC 1
                        #endif
                #endif
        #endif
#endif

The only problem is that I thought that #error would stop the compilation on the spot, but it does not, it fails in the end but it might be difficult to spot the error when compiling with the IDE.

That won’t work. The Arduino IDE has special handling of the ‘src’ subfolder of the sketch folder. That is the only folder where recursive compilation will be done. You could add a ‘libs’ folder under the ‘src’ folder if you like.

Oh! I didn’t knew that.

pert:
Unfortunately that's not possible with the library in its current form. The problem is that the library's .cpp files are a separate translation unit from the .ino file so the macros you #define in the .ino will not be seen by the .cpp. The workaround would be to move all the code that relies on the macros to the .h files, where it is visible.

Ok, now I understand this paragraph. :frowning:
I tried to do it as I said just to discover that when MD_MAX72xx.h is #included from MD_MAX72xx.cpp my #define is not there... :frowning: Sorry to be so dense but that wasn't making sense to me.
I've been playing with C for more than 20 years (not as a developer of course) and it's the 1st time I noticed this.
Is this an Arduino 'feature' ??

No, it’s not specific to Arduino. I know this is universal in C++ and am certain it’s the same with C. The Arduino IDE converts the .ino sketch file to .cpp files after some minor preprocessing (adding function prototypes primarily) so they are compiled as C++.

You can set a #define in a .h file and then #include the .h file from multiple source files to share the value of that #define among them but the difficulty with that is you can’t easily #include a .h file in the sketch folder from a library file.

The possible workarounds are:

  • Modify the library to be configured via functions.
  • Move all the library code that is dependent on the macro to .h files.
  • Modify the hardware definition for all boards you want to use the sketch with to add the temporary build folder to the include path. Add a .h configuration file to the sketch. Modify the library to #include that configuration file. This is not very portable and needs to be redone whenever you update to a new version of the package.
  • Use PlatformIO instead of the Arduino IDE and set the macro from a build flag in the platformio.ini for each sketch.