LightwaveRF
LightwaveRF copied to clipboard
Timer2 reliance - Fails to compile on 32u4 (No Timer2)
Currently the library is reliant on Timer2 use (8bit timer).
Unfortunately this makes it incompatible with ATMega 32u4 chips such as on the leonardo or Teensey. This chip has only the one 8-bit timer.
I'm quite confident that
Similar (subsequently solved) issue on IR library; https://code.google.com/p/rogue-code/issues/detail?id=13
Adding in something similar to this:
// Teensy 2.0 versus Leonardo
// These boards use the same chip but the pinouts are different.
#elif defined(__AVR_ATmega32U4__)
#ifdef CORE_TEENSY
// it's Teensy 2.0
//#define IR_USE_TIMER1 // tx = pin 14
//#define IR_USE_TIMER3 // tx = pin 9
#define IR_USE_TIMER4_HS // tx = pin 10
#else
// it's probably Leonardo
#define IR_USE_TIMER1 // tx = pin 9
//#define IR_USE_TIMER3 // tx = pin 5
//#define IR_USE_TIMER4_HS // tx = pin 13
#endif
as suggested here http://forum.arduino.cc/index.php?topic=115033.0 could handle some of the issues; although I don't think the pin needs changing but the interrupt enabling
Looking at you code for LwTx.h, this might fit in somewhere around line line 24, for example something like this;
// Teensy 2.0 versus Leonardo
// These boards use the same chip but the pinouts are different.
#elif defined(__AVR_ATmega32U4__)
#ifdef CORE_TEENSY
// it's Teensy 2.0
//#define TX_PIN_DEFAULT 14 // tx = pin 14 for Timer1
//#define TX_PIN_DEFAULT 9 // tx = pin 9 for Timer3
#define TX_PIN_DEFAULT 4 // tx = pin 10 for Timer4 high speed
#else
// it's probably Leonardo
#define IR_USE_TIMER1 9 // tx = pin 9
//#define IR_USE_TIMER3 5 // tx = pin 5
//#define IR_USE_TIMER4_HS 13 // tx = pin 13
#endif
and then in LwTx.cpp around line 248 add
// Teensy 2.0 versus Leonardo
// These boards use the same chip but the pinouts are different.
#elif defined(__AVR_ATmega32U4__)
#ifdef CORE_TEENSY
// it's Teensy 2.0
//code for timer4HS
#else
extern void lw_timer_Setup(void (*isrCallback)(), int period) {
isrRoutine = isrCallback; // unused here as callback is direct
byte clock = (period / 4) - 1;;
cli();//stop interrupts
//set timer1 interrupt at clock uSec (default 140)
TCCR1A = 0;// set entire TCCR21 register to 0
TCCR1B = 0;// same for TCCR21
TCNT1L = 0;//initialize counter low byte value to 0
TCNT1H = 0;//initialize counter high byte value to 0
// set compare match register for clock uSec
OCR1A = clock;// = 16MHz Prescale to 4 uSec * (counter+1)
// turn on CTC mode
TCCR1A |= (1 << WGM21);
// Set CS11 bit for 64 prescaler
TCCR1B |= (1 << CS22);
// disable timer compare interrupt
TIMSK1 &= ~(1 << OCIE1A);
sei();//enable interrupts
}
extern void lw_timer_Start() {
//enable timer 2 interrupts
TIMSK1 |= (1 << OCIE1A);
}
extern void lw_timer_Stop() {
//disable timer 1 interrupt
TIMSK1 &= ~(1 << OCIE1A);
}
//Hand over to real isr
ISR(TIMER1_COMPA_vect){
isrTXtimer();
}
#endif
However I have had enough difficulty getting it to compile I have eclipsed my very minimal coding knowledge. I am not sure if you would need to change the TOP value of the timer, or if the compare limit set by the code above would be enough. I am also not sure if the rest of your code will handle a 16-bit return or needs changing to address timer1
Just sharing my thoughts having run into difficulty, sorry if it annoys
Thanks for sharing that. I haven't uses TEENSY or 32u4 so far, but I will check that out further.
The reason why this code has been fairly easily ported to several environments is that the only real dependency for the tx side is that one can get a regular call-back from a timer at about 140uSec intervals. The state machine does the rest. Whether it is a 8 or 16 or even 32bit timer doesn't matter. The rest of the code does not access timers at all.
The rx side uses a pin change interrupt and the requirement there is to be able to read a clock at the interrupt which is good to within a few uSec.
What environment are you compiling in?
Below code works on my Sparkfun pro micro (equivalent to an Arduino Leonardo, uses the 32u4)
//Default case is Arduino Mega328 which uses the TIMER2 ***TL changed to 32u4 timer3
extern void lw_timer_Setup(void (*isrCallback)(), int period) {
isrRoutine = isrCallback; // unused here as callback is direct
byte clock = (period / 4) - 1;;
cli();//stop interrupts
//set timer2 interrupt at clock uSec (default 140)
TCCR3A = 0;// set entire TCCR2A register to 0
TCCR3B = 0;// same for TCCR2B
TCNT3 = 0;//initialize counter value to 0
// set compare match register for clock uSec
OCR3A = clock;// = 16MHz Prescale to 4 uSec * (counter+1)
// turn on CTC mode
TCCR3B |= (1 << WGM32);
// Set bits for 64 prescaler
TCCR3B |= (1 << CS31);
TCCR3B |= (1 << CS30);
// disable timer compare interrupt
TIMSK3 &= ~(1 << OCIE3A);
sei();//enable interrupts
}
extern void lw_timer_Start() {
//enable timer 2 interrupts
TIMSK3 |= (1 << OCIE3A);
}
extern void lw_timer_Stop() {
//disable timer 2 interrupt
TIMSK3 &= ~(1 << OCIE3A);
}
//Hand over to real isr
ISR(TIMER3_COMPA_vect){
isrTXtimer();
}
#endif
Thanks. I have added this in as a variant selected by the PRO32U4 #define in the header file