My Arduino API macro "wrapper" library will not compile

I have written a set of macros to wrap the SPI libraries from different Arduino boards
types in a common set of calls. This allows the same code to be used on any number of boards.

How can I configure this code to get it working?

These macros are in SPI_A.h. I have 3 variables that are used to hold the active SS Pin, and port register and mask
DATA_TYPE_SS pinSS;
IO_BASE_TYPE Base;
IO_MASK_TYPE Mask;

I initially placed these 3 in the SPI_A.h file with the macros. In my test project, these macros are only used in raster.cpp to communicate with the SPI library. But I receive errors no matter where I place these variables.

My inculude lines are:
#include <SPI_A.h> //Arduino ATMEGA boards
#include <SPI.h>

Error Case 1. If I place the includes ONLY in the raster.cpp I receive:

    MB_raster.cpp:41:44: fatal error: SPI_A.h: No such file or directory
    :#include <SPI_A.h>  \\Arduino ATMEGA boards

Case 2. If I place the includes in raster.cpp AND in the .ino sketch, SPI_A.h is found, but I receive the error:

[ 33%] Creating D:\Arduino\BUILD\MB_Project_Timers\lib_SPI_A\SPI_A.cpp.o...
    D:/Arduino/Sketches/libraries/SPI_A/SPI_A.cpp:8:14: error: redefinition of 'unsigned int _pinSS_' DATA_TYPE_SS _pinSS_; 
    In file included from D:/Arduino/Sketches/libraries/SPI_A/SPI_A.cpp:5:0:
    D:/Arduino/Sketches/libraries/SPI_A/SPI_A.h:26:14: error: 'unsigned int _pinSS_' previously declared here   DATA_TYPE_SS _pinSS_;

Case 3. If I move the variables are moved to SPI_A.cpp from SPI_A.h I receive this error:

    SPI_A.h:30:34: error: '_pinSS_' was not declared in this scope
    :SS; _Base_ = PIN_TO_BASEREG(_pinSS_); _Mask_ = PIN_TO_BITMASK(_pinSS_)

Here is my SPI_A.h file:

//SPI_A.h
/*
See the SPI_MB manual for use and other details
*/
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ATMEGA)

#ifndef SPI_A_H
#define SPI_A_H

#include <Arduino.h>
#include <digitalPinTo.h>   //macros for fast bit banging

#if defined(__AVR__)             //UNO and MEGA)
    #else
        #error  "Not a UNO or MEGA compatible"
    #endif
#else
    #error  "Not an Arduino compatible board"
#endif

#define DATA_TYPE_SS  unsigned int

//moved to .cpp to avoid conflicts
DATA_TYPE_SS _pinSS_; 

//need to use my digitalPinTo.h macros to max the speed
//IO_BASE_TYPE _Base_;
//IO_MASK_TYPE _Mask_;

#define GET_REGISTER(_pinSS)     _pinSS_ = _pinSS ? _pinSS : SS; _Base_ = PIN_TO_BASEREG(_pinSS_); _Mask_ = PIN_TO_BITMASK(_pinSS_) 

#define SPI_BEGIN(_pinSS)                               GET_REGISTER(_pinSS); \
                                                        DIRECT_MODE_OUTPUT(_Base_, _Mask_); \
                                                        DIRECT_WRITE_HIGH(_Base_, _Mask_); \
                                                        SPI.begin()

#define SPI_SET_BIT_ORDER(_bitOrder)                    SPI.setBitOrder(_bitOrder) 
#define SPI_SET_DATA_MODE(_mode)                        SPI.setDataMode(_mode)
#define SPI_SET_CLOCK_DIVIDER(_divider)                 SPI.setClockDivider(_divider)

#define SPI_TRANSFER1(_sendbyte)                        DIRECT_WRITE_LOW(_Base_, _Mask_); \
                                                        SPDR = _sendbyte;while (!(SPSR & _BV(SPIF))); \
                                                        DIRECT_WRITE_HIGH(_Base_, _Mask_)

#define SPI_TRANSFER(_sendarray, _numBytes)             DIRECT_WRITE_LOW(_Base_, _Mask_); \
                                                        for(unsigned char i = _numBytes; i > 0 ; i--){ \
                                                        SPDR = _sendarray[i-1];while (!(SPSR & _BV(SPIF)));} \
                                                        DIRECT_WRITE_HIGH(_Base_, _Mask_)

#define SPI_TRANSFER_L(_sendarray, _numBytes)           DIRECT_WRITE_LOW(_Base_, _Mask_); \
                                                        for(unsigned char i = 0; i < _numBytes ; i++){ \
                                                        SPDR = _sendarray[i];while (!(SPSR & _BV(SPIF)));} \
                                                        DIRECT_WRITE_HIGH(_Base_, _Mask_)
//Pin MUST be Initalized once before making Active  
#define ACTIVE_SS_PIN(_pinSS)                           GET_REGISTER(_pinSS)
                                                
//INIT also makes this the Active Pin
#define INIT_SS_PIN(_pinSS)                             GET_REGISTER(_pinSS); \
                                                        DIRECT_MODE_OUTPUT(_Base_, _Mask_); \
                                                        DIRECT_WRITE_HIGH(_Base_, _Mask_)    

#define SPI_END()                                        SPI.end()

#endif //Arduino ATMEL boards

It's difficult to tell from those snippets ( http://snippets-r-us.com/ ) however in general you can't have a #define in the main (.ino) file and expect it to affect things in libraries. That's just the way C compiles things.

Error case #1: the way the Arduino IDE works it won't copy .h files into the temporary working directory used for compiling unless it is mentioned in the .ino file.

Error case #2: Not sure, would have to see all your code.

Error case #3: Probably what I said at the start of my reply.

I have attached the project as a zip file.

\MB_Project_Timers if the sketch and raster files
\TimerOne_A is my macro library for the timerOne.h library
\SPI_A is my macro library for the UNO SPI.h library
\digitalPinTo.h is my macro library for port bit banging

MB_Project.zip (16.2 KB)

Are all those files in the same directory? Or are some in the sketch folder and some in the libraries folder?

If some are in the libraries folder, you MUST include SPI_A.h in the sketch.

The \MB_Project_Timers is in the \Arduino\Sketchs folder. The others are in the \Arduino\Sketchs\libraries folder.

If I put these 3 variables in a class in SPI_A.cpp, then instantiated the class would that work? The defines and macros could stay in SPI_A.h I assume.

Work, in what sense? You might make the compile errors go away. Why not try and see?

Fixed! Creating SPI_A.cpp, containing a class, and moving my 3 problem variables into the class results in a clean compile. Obvious in hindsight. This also allows multiple instances to be created for boards with multiple SPI capabilities.

Thanks for your patience.

Here’s the cpp.

//SPI_A.cpp

//variables need to be a class in this .cpp

#include "SPI_A.h"

//just need to instantiate this object
SPI_Class spiMB;

SPI_Class::SPI_Class(){
    SS = 0; 
    Base = 0;
    Mask = 0;
}