I'm trying to write a function that can Shift out data to 74HC595 shift registers which can shift out 8, 16, and 32 bit values.
Using an overloaded function, I have this:
/**********************************************************************************
* Software SPI Pin Settings
*********************************************************************************/
#define SPIPINPORT PORTB //The Port that the Pins are on.
#define LatchPin 2 //_RCLK Shift register clock pin
#define DataPin 3 //SER DS Serial data input
#define ClockPin 5
/**********************************************************************************
* Preproccesor PIN to PIN Mask
*********************************************************************************/
#define LATCHMASK (1 << LatchPin)
#define MOSIMASK (1 << DataPin)
#define CLOCKMASK (1 << ClockPin)
/**********************************************************************************
* Macros
*********************************************************************************/
#define tggl(port,bit) (port)^=(1<<(bit))
#define LATCH (SPIPINPORT &=~ LATCHMASK)
#define unLATCH (SPIPINPORT |= LATCHMASK)
#define PULSE { tggl(SPIPINPORT,ClockPin); tggl(SPIPINPORT,ClockPin); }
void zShiftClass::ShiftOut(uint8_t value)
{
LATCH;
for (uint8_t i = 0; i <= 7; i++)
{
if( !!(value&(1<<i)) == true) //If value is not a 1, turn off MOSIMASK
{ SPIPINPORT |= MOSIMASK; }
else
{ SPIPINPORT &= ~MOSIMASK; }
PULSE; //Pulse the Clock
}
unLATCH;
}
void zShiftClass::ShiftOut(uint16_t value)
{
LATCH;
for (uint8_t i = 0; i <= 15; i++)
{
if( !!(value&(1<<i)) == true) //If value is not a 1, turn off MOSIMASK
{ SPIPINPORT |= MOSIMASK; }
else
{ SPIPINPORT &= ~MOSIMASK; }
PULSE; //Pulse the Clock
}
unLATCH;
}
void zShiftClass::ShiftOut(uint32_t value)
{
LATCH;
for (uint8_t i = 0; i <= 31; i++)
{
if( !!(value&(1<<i)) == true) //If value is not a 1, turn off MOSIMASK
{ SPIPINPORT |= MOSIMASK; }
else
{ SPIPINPORT &= ~MOSIMASK; }
PULSE; //Pulse the Clock
}
unLATCH;
}
And I want to use this template to replace these functions:
template<typename TYPE>void Shift(TYPE value)
{
uint8_t loops = (( 8 * sizeof(value) ) - 1 );
LATCH;
for (uint8_t i = 0; i <= loops; i++)
{
if( !!(value&(1<<i)) == true) //If value is not a 1, turn off MOSIMASK
{ SPIPINPORT |= MOSIMASK; }
else
{ SPIPINPORT &= ~MOSIMASK; }
PULSE; //Pulse the Clock
}
unLATCH;
}
When I compile, I get the following errors:
Compiling 'zLEDArray' for 'Arduino Uno'
zLEDArray.ino : variable or field 'Shift' declared void
zLEDArray.ino : 'TYPE' was not declared in this scope
Error compiling
What am I doing wrong?
Okay, this falls in the category of "beware of dev tools bearing gifts". The Arduino sketch tool is your problem. If you turn on verbose compiler output on the preferences menu, you will get some insight into what happens. With your code, I can duplicate your error. When compiling a test project called template1, the same error is reported, but now can see the compiler command line:
The key point is that .CPP file. That is a file that the dev environment constructs from your .INO and is what is the actual input to the compiler. If you go grab that file, you will see all your code with some bonus lines included:
The build tool added for you, 4 lines:
The attempt at producing a forward declaration from the function template is incorrect, and produces the code that results in the compiler error.
The solution is to move the template out from the .INO file.
You can get rid of the error by adding the correct forward declaration in your ino file. The inuntuitive thing is that you must also do this if you define the function before you use it:
The explanation why this is the case is in jdr5ca's answer. Thanks for clarifying, I found this out by trial and error.