Hi!
I'm working on an AVR Butterfly port for the Arduino, and I'm cleaning up a library that was made for the Arduino IDE 0.19 or so. I got the code working but not like I want. Here's a little information:
The code is forked of the Butteruino project, and hasn't been updated in 8 years. I've done some changes to make this work with the latest IDE. The AVR Butterfly has an onboard 32.768 kHz oscillator thats connected to an 8 bit timer. The original timer library lets you display the current time on the Butterfly LCD. The timer class object, RTCTimer, is located inside the header the library (using 'extern'), but I want to move this to the main inn file. The problem is that there is an ISR (interrupt service routine) inside the cpp file which runs the time keeping function and a user defined callback, and is depending on a known object.
How can I move the object of the class out of the function without messing up the ISR?
I've attached the code as a ZIP file, if you prefer that ![]()
Main.ino
#include "timer2_RTC.h"
#include "Butterfly.h"
// Butterfly LCD object
ButterflyLCD lcd;
// I want this object to work properly
//ButterflyRTC RTCTimer;
void setup()
{
// Buzzer on pin 13
pinMode(BUZZER, OUTPUT);
// Initialize the LCD
lcd.begin();
lcd.print("Butterfly RTC");
delay(4000);
// The RTCTimer can be started with a 'tick' callback. In this
// case there is no need to check whether the time has changed,
// RTCTimer will call the routine you specify when the time changes.
RTCTimer.begin(secTick);
lcd.showColons(true);
}
void secTick()
{
lcd.setCursor(0);
lcd.print(RTCTimer.hour, DEC);
lcd.setCursor(2);
lcd.print(RTCTimer.minute, DEC);
lcd.setCursor(4);
lcd.print(RTCTimer.second, DEC);
}
void loop()
{
//The ISR handles everything
}
Header file:
#ifndef timer2_RTC_h
#define timer2_RTC_h
#include <avr/pgmspace.h>
#include <stdint.h>
class ButterflyRTC
{
public:
// Constructor
ButterflyRTC(void);
// Function callback
typedef void (*ClockChangeCallback_t) (void);
ClockChangeCallback_t clockChangeCallback;
// Public methods
void begin(ClockChangeCallback_t clockChangeCallback = 0);
void timerTick();
// Public variables
volatile uint8_t timeChanged;
volatile uint8_t second;
volatile uint8_t minute;
volatile uint8_t hour;
volatile uint8_t day;
volatile uint8_t month;
volatile uint16_t year;
};
// I want to get rid of this!
extern ButterflyRTC RTCTimer;
#endif
CPP file:
#include <avr/io.h>
#include <avr/interrupt.h>
#include "timer2_RTC.h"
#include "Arduino.h"
// Month length lookup table
const char PROGMEM MonthLength[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// How can we deal with this?
ButterflyRTC RTCTimer = ButterflyRTC();
ButterflyRTC::ButterflyRTC(void)
{
// begin();
}
ISR(TIMER2_OVF_vect)
{
// Enable global interrupts to be able to update the LCD
sei();
// execute a "tick"
// ButterflyRTC RTCTimer;
RTCTimer.timerTick();
}
void ButterflyRTC::begin(ClockChangeCallback_t userCallback)
{
// Save callback
clockChangeCallback = userCallback;
// Startup date and time.
timeChanged = 0;
second = 0;
minute = 0;
hour = 0;
day = 0;
month = 0;
year = 0;
// Disable global interrupts
cli();
TIMSK2 &= ~(1 << TOIE2); // disable OCIE2A and TOIE2
ASSR = (1 << AS2); // select asynchronous operation of Timer2
TCNT2 = 0; // clear TCNT2A
TCCR2A |= (1 << CS22); // select precaler: 32.768 kHz / 64 = 1 sec between each overflow
while ((ASSR & 0x01) | (ASSR & 0x04)); // wait for TCN2UB and TCR2UB to be cleared
TIFR2 = 0xFF; // clear interrupt-flags
TIMSK2 |= (1 << TOIE2); // enable Timer2 overflow interrupt
// Enable global interrupts
sei();
}
void ButterflyRTC::timerTick(void)
{
static char LeapMonth;
second++;
if (second == 60)
{
second = 0;
minute++;
if (minute > 59)
{
minute = 0;
hour++;
if (hour > 23)
{
hour = 0;
day++;
// If February check for leap year
if (month == 2)
if (!(year & 0x0003))
if (year % 100 == 0)
if (year % 400 == 0)
LeapMonth = 1;
else
LeapMonth = 0;
else
LeapMonth = 1;
else
LeapMonth = 0;
else
LeapMonth = 0;
// Check for month length
if (day > (MonthLength[month] + LeapMonth))
{
day = 1;
month++;
if (month > 12)
{
month = 1;
year++;
}
}
}
}
}
timeChanged++;
// If the user has provided a callback, call it now.
if (clockChangeCallback != 0)
clockChangeCallback();
}
Timer2RTC.zip (3.2 KB)