does not name a type error while using a template class

I’ve written a template class to utilize two hardware decoders for the Teensy 3.1 and I’ve had this working in an older project and I’m just trying to pull this class out and make it a library on it’s own (instead of being wrapped in with a bunch of other classes). But I keep getting this error

Wheel_Class_test:6: error: 'encoderA' does not name a type
Wheel_Class_test:7: error: 'encoderB' does not name a type
Wheel_Class_test:8: error: 'encoderA' does not name a type
'encoderA' does not name a type

I’ve tried declaring it multiple ways and tried putting the .h and .cpp in with the other libraries and keeping those files in with the sketch.
My sketch

#include <QuadDecoder.h>
#define mod 1959
QuadBase *encoderA = new QuadDecoder<1>();
QuadDecoder <2> encoderB();// = new QuadDecoder<2>();

encoderA->setup(mod,1);
encoderB.setup(mod,1);
encoderA->setFilter(31);

void setup() {
}

void loop() {}

My template class QuadDecoder.cpp

#include "kinetis.h"
#include "QuadDecoder.h"
QuadDecoder<1> *apQDcd1;    // Pointers to  correct instance for ISR
QuadDecoder<2> *apQDcd2;
void ftm1_isr(void) 
{
 apQDcd1->ftm_isr();
}

void ftm2_isr(void) 
{
 apQDcd2->ftm_isr();
}

I’ve looked around and saw similar problems but not one with a template class so I wasn’t sure if there is something more I should do to get it to work.

Thanks for any help in advance

the header file QuadDecoder.h

/*

#ifndef QuadDecoder_h_
#define QuadDecoder_h_
#include <vector>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "Arduino.h"
#include "kinetis.h"

enum reggister {CNTIN, MOD, SC, QDCTRL, MODE, CNT, FILTER, FMS, FLTCTRL, IRQ};


typedef volatile uint32_t* reg;
class QuadBase{
public:
 virtual ~QuadBase(){}
 virtual void reset() = 0;
 virtual void setup(int,int PINSET=1) = 0;
 virtual void setup(int PINSET=1) = 0;
 virtual void begin() = 0;
 virtual void stop() = 0;
 virtual void setMod(int) = 0;
 virtual int getMod() = 0;
 virtual void setCNTIN(int) = 0;
 virtual void setFilter(unsigned int) = 0;
 virtual void setPreScale(unsigned int) = 0;
 virtual void invertCHA() = 0;
 virtual void invertCHB() = 0;
 virtual int getCount() = 0;
 virtual void incREV(bool) = 0;
 virtual int getRev() = 0; 
 virtual int getRegister(reggister) = 0;
};
template <int N> class QuadDecoder;
extern QuadDecoder<1> *apQDcd1;    // Pointers to  correct instance for ISR
extern QuadDecoder<2> *apQDcd2;
template <int N>    // Valid values are 1 or 2 to set up as FTM1 or FTM2
class QuadDecoder : public QuadBase
{
public:
 QuadDecoder()
 {
    // Order of contstructor execution not guaranteed, 
    //   start with start()
    if (N<2)
 { // Point to this instance for ISR
 apQDcd1=reinterpret_cast<QuadDecoder<1>*>(this);
 // Without reintepret_cast compiler complains about unused 
 //   case.  Pointer for unused case not used, so don't
 //   care what it is.  Used case casts to existing type.
    }else
 {
 apQDcd2=reinterpret_cast<QuadDecoder<2>*>(this);
 };
    revs = 0;
 };
 void reset();
 void setup(int,int PINSET=1);
 void setup(int PINSET=1);
 void begin();
 void stop();
 void setMod(int);
 int getMod();
 void setCNTIN(int);
 void setFilter(unsigned int); 
 void setPreScale(unsigned int);
 void invertCHA();
 void invertCHB();
 int getCount();
 void incREV(bool);
 int getRev();
 int getRegister(reggister);

 void ftm_isr();
private:
 void checkProtection();
 void enProtection();
 int revs; // revolution based off modulus
 const reg FTM_CNTIN = ((N<2) ? &FTM1_CNTIN : &FTM2_CNTIN);
 const reg FTM_MOD = ((N<2) ? &FTM1_MOD : &FTM2_MOD);
 const reg FTM_SC = ((N<2) ? &FTM1_SC : &FTM2_SC);
 const reg FTM_QDCTRL = ((N<2) ? &FTM1_QDCTRL : &FTM2_QDCTRL);
 const reg FTM_MODE = ((N<2) ? &FTM1_MODE : &FTM2_MODE);
 const reg FTM_CNT = ((N<2) ? &FTM1_CNT : &FTM2_CNT);
 const reg FTM_FILTER = ((N<2) ? &FTM1_FILTER : &FTM2_FILTER);
 const reg FTM_FMS = ((N<2) ? &FTM1_FMS : &FTM2_FMS);
 const reg FTM_FLTCTRL = ((N<2) ? &FTM1_FLTCTRL : &FTM2_FLTCTRL);
 uint8_t IRQ_FTM = ((N<2) ? IRQ_FTM1 : IRQ_FTM2);
};

// FTM Interrupt Service routines - on overflow and position compare
/*void ftm1_isr(void){
    apQDcd1->ftm_isr();
};

void ftm2_isr(void){
    apQDcd2->ftm_isr();
};*/

template <int N>
void QuadDecoder<N>::ftm_isr(void)
{
 *FTM_SC &= 0x19;
 ((*FTM_QDCTRL & FTM_QDCTRL_TOFDIR)==2) ? incREV(true) : incREV(false);
 *FTM_SC |= FTM_SC_TOIE;
}

template <int N>
int QuadDecoder<N>::getRegister(reggister name)
{
 switch(name)
 {
 case CNTIN:
 return *FTM_CNTIN;
 break;
 case MOD:
 return *FTM_MOD;
 break;
 case SC:
 return *FTM_SC;
 break;
 case QDCTRL:
 return *FTM_QDCTRL;
 break;
 case MODE:
 return *FTM_MODE;
 break;
 case CNT:
 return *FTM_CNT;
 break;
 case FILTER:
 return *FTM_FILTER;
 break;
 case FMS:
 return *FTM_FMS;
 break;
 case FLTCTRL:
 return *FTM_FLTCTRL;
 break;
 case IRQ:
 return IRQ_FTM;
 break;
  default:
    return 0;
    break;
 }
}

// Set Registers
template <int N>
void QuadDecoder<N>::setup(int MOD, int PINSET)
{
 *FTM_SC &= 0x00;
 *FTM_CNT = 0;
 *FTM_MOD = MOD;
 
 // enable the clock FTM
 (N<2) ? SIM_SCGC3 |= SIM_SCGC3_FTM2 : SIM_SCGC6 |= SIM_SCGC6_FTM1;
 

 // CHECK WRITE PROTECTION
 checkProtection();
 // FTM mode enable
 *FTM_MODE |= FTM_MODE_FTMEN;
 // Quad enable
 *FTM_QDCTRL |= FTM_QDCTRL_QUADEN;
 // set clk as external & set prescale
 *FTM_SC |= FTM_SC_CLKS(3);
 *FTM_SC |= FTM_SC_PS(2);

 // Multiplex PINS
 if(PINSET == 0 && N == 1)
 {
 PORTB_PCR0 = PORT_PCR_MUX(6); // FTM1 CH0 PHASE A Teensy PIN 16/A2
 PORTB_PCR1 = PORT_PCR_MUX(6); // FTM1 CH1 PHASE B Teensy PIN 17/A3
 }
 else if (N == 1)
 {
 PORTA_PCR12 = PORT_PCR_MUX(7); // FTM1 CH0 PHASE A Teensy PIN 3
 PORTA_PCR13 = PORT_PCR_MUX(7); // FTM1 CH1 PHASE B Teensy PIN 4
 }
 else
 {
 PORTB_PCR18 = PORT_PCR_MUX(6); // FTM2 CH0 PHASE A Teensy PIN 32
 PORTB_PCR19 = PORT_PCR_MUX(6); // FTM2 CH1 PHASE B Teensy PIN 25
 }
 // Enable write protection
 //enProtection();
 *FTM_FMS |= FTM_FMS_WPEN;
}
template <int N>
void QuadDecoder<N>::setup(int PINSET)
{ 
 *FTM_SC &= 0x00;
 *FTM_CNT = 0;
 
 // enable the clock FTM
 (N<2) ? SIM_SCGC3 |= SIM_SCGC3_FTM2 : SIM_SCGC6 |= SIM_SCGC6_FTM1;
 
 // CHECK WRITE PROTECTION
 checkProtection();
 // FTM mode enable
 *FTM_MODE |= FTM_MODE_FTMEN;
 // Quad enable
 *FTM_QDCTRL |= FTM_QDCTRL_QUADEN;
 // set clk as external & set prescale
 *FTM_SC |= FTM_SC_CLKS(3);
 *FTM_SC |= FTM_SC_PS(2);

 // Multiplex PINS
 if(PINSET == 0 && N <2)
 {
 PORTB_PCR0 = PORT_PCR_MUX(6); // FTM1 CH0 PHASE A Teensy PIN 16/A2
 PORTB_PCR1 = PORT_PCR_MUX(6); // FTM1 CH1 PHASE B Teensy PIN 17/A3
 }
 else if (N<2)
 {
 PORTA_PCR12 = PORT_PCR_MUX(7); // FTM1 CH0 PHASE A Teensy PIN 3
 PORTA_PCR13 = PORT_PCR_MUX(7); // FTM1 CH1 PHASE B Teensy PIN 4
 }
 else
 {
 PORTB_PCR18 = PORT_PCR_MUX(6); // FTM2 CH0 PHASE A Teensy PIN 32
 PORTB_PCR19 = PORT_PCR_MUX(6); // FTM2 CH1 PHASE B Teensy PIN 25
 }
 // Enable write protection
 //enProtection();
 *FTM_FMS |= FTM_FMS_WPEN;
}
// Function to handle inverting channel A
template <int N>
void QuadDecoder<N>::invertCHA()
{
 // determine channel is inverted
 *FTM_QDCTRL |= FTM_QDCTRL_PHAPOL;
}
// Function to handle inverting channel B
template <int N>
void QuadDecoder<N>::invertCHB()
{
 // determine channel is inverted

 *FTM_QDCTRL |= FTM_QDCTRL_PHBPOL;
}
// CHECK WRITE PROTECTION
template <int N>
void QuadDecoder<N>::checkProtection()
{
 if((*FTM_FMS&FTM_FMS_WPEN) == 1)
 {
 *FTM_MODE |= FTM_MODE_WPDIS;
 }
}
// Enable write protection
template <int N>
void QuadDecoder<N>::enProtection()
{
 *FTM_FMS |= FTM_FMS_WPEN;
}
// Set mod value
template <int N>
void QuadDecoder<N>::setMod(int modNum)
{
 // CHECK WRITE PROTECTION
 //checkProtection();
 *FTM_CNT = 0;
 *FTM_MOD = modNum;
 // Enable write protection
 //enProtection();
}
// set Filter value IMPLEMENT THIS
template <int N>
void QuadDecoder<N>::setFilter(unsigned int filtNum)
{
 *FTM_FILTER |= FTM_FILTER_CH0FVAL(filtNum);
 *FTM_FILTER |= FTM_FILTER_CH1FVAL(filtNum);
 *FTM_QDCTRL |= FTM_QDCTRL_PHAFLTREN |FTM_QDCTRL_PHBFLTREN;
}

template <int N>
int QuadDecoder<N>::getCount()
{
 return *FTM_CNT;
}
// Reset variables and clears count register
template <int N>
void QuadDecoder<N>::reset()
{
 revs = 0;
 *FTM_CNT = 0;
}

template <int N>
void QuadDecoder<N>::begin()
{
 NVIC_ENABLE_IRQ(IRQ_FTM);
 *FTM_SC |= FTM_SC_TOIE;
}

template <int N>
void QuadDecoder<N>::stop()
{
 NVIC_DISABLE_IRQ(IRQ_FTM);
 *FTM_SC &= !FTM_SC_TOIE;
}

template <int N>
void QuadDecoder<N>::incREV(bool increase)
{
 increase ? revs++ : revs--;
}

template <int N>
void QuadDecoder<N>::setCNTIN(int cnt)
{
 *FTM_CNTIN = cnt;
}

template <int N>
void QuadDecoder<N>::setPreScale(unsigned int num)
{
 if((*FTM_FMS&FTM_FMS_WPEN) == 1)
 {
 *FTM_FMS |= FTM_FMS_WPEN;
 }
 *FTM_SC |= FTM_SC_PS(num);
 *FTM_FMS |= FTM_FMS_WPEN;
}

template <int N>
int QuadDecoder<N>::getRev()
{
 return revs;
}

template <int N>
int QuadDecoder<N>::getMod()
{
 return *FTM_MOD;
}

#endif

Had to post this separately because it was too long :stuck_out_tongue:

encoderA->setup(mod,1);
encoderB.setup(mod,1);
encoderA->setFilter(31);

You can’t have that code outside of a function. Put it in setup and it will take it.

That worked thank you very much!

I find it can be helpful to think of a reference as a pointer that you are not allowed to do array arithmetic with. So when you don’t have arrays of things, it’s often reasonable to mostly use references rather than pointers.

QuadBase &encoderA = new QuadDecoder<1>();
QuadDecoder <2> encoderB();// = new QuadDecoder<2>();

setup() {
  encoderA.setup(mod,1); 
  encoderB.setup(mod,1);
  encoderA.setFilter(31);
}

Unless you are making in-memory data structures that change over time (eg, linked lists), there’s not much point using new.