Lab_interaccio/2012/ASK-Shield/References/waspmote-api-v.021/WaspRTC.cpp
Miguel Angel de Heras 451795bb92 Second commit
2025-03-05 15:57:19 +01:00

1264 lines
34 KiB
C++

/*
* Copyright (C) 2009 Libelium Comunicaciones Distribuidas S.L.
* http://www.libelium.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Version: 1.1
* Design: David Gascón
* Implementation: Alberto Bielsa, David Cuartielles, Marcos Yarza
*/
#ifndef __WPROGRAM_H__
#include "WaspClasses.h"
#endif
// Constructors ////////////////////////////////////////////////////////////////
WaspRTC::WaspRTC()
{
// nothing to do when constructing
}
// Public Methods //////////////////////////////////////////////////////////////
/*
* ON (void) - It opens I2C bus and powers the RTC
*
* It opens I2C bus and powers the RTC
*/
void WaspRTC::ON(void)
{
begin();
}
/*
* OFF (void) - It closes I2C bus and powers off the RTC
*
* It closes I2C bus and powers off the RTC
*/
void WaspRTC::OFF(void)
{
close();
setMode(RTC_OFF, RTC_NORMAL_MODE);
}
/* begin() - inits I2C bus and used pins
*
* It enables internal pull-up resistor for the RTC interrupt pin, so as this pin is set to HIGH when init
* It inits I2C bus for communicating with RTC
* It reads from RTC time,date and alarms, setting the corresponding variables
*
* Returns nothing
*/
void WaspRTC::begin()
{
// Powers RTC UP
setMode(RTC_ON, RTC_NORMAL_MODE);
// Inits I2C bus
if( !Wire.I2C_ON ) Wire.begin();
// initialize the variables used to store the data
// from the RTC
clearAlarmFlag();
resetVars();
readRTC(RTC_ALARM2_ADDRESS);
}
/* close() - closes I2C bus and used pins
*
* It enables internal pull-up resistor for the RTC interrupt pin, so as this pin is set to HIGH when init
* It inits I2C bus for communicating with RTC
* It reads from RTC time,date and alarms, setting the corresponding variables
*
* Returns nothing
*/
void WaspRTC::close()
{
if( Wire.I2C_ON && !ACC.isON) PWR.closeI2C();
}
/* setMode(mode) - set power mode
*
* It sets the power mode on the RTC. It has two possibilities: ON or OFF
*/
void WaspRTC::setMode(uint8_t mode, uint8_t I2C_mode)
{
_pwrMode=mode;
pinMode(RTC_PW,OUTPUT);
switch(_pwrMode)
{
case RTC_ON : digitalWrite(RTC_PW,HIGH);
if( I2C_mode==RTC_I2C_MODE ) isON = 2;
else if( I2C_mode==RTC_NORMAL_MODE ) isON = 1;
break;
case RTC_OFF : digitalWrite(RTC_PW,LOW);
isON = 0;
break;
}
}
/* getMode() - gets power mode
*
* It gets the power mode of the RTC.
*/
uint8_t WaspRTC::getMode()
{
return _pwrMode;
}
/* resetVars() - resets variables to zero
*
* It resets all the used variables to default value
*/
void WaspRTC::resetVars()
{
year = 0;
month = 0;
day = 0;
hour = 0;
minute = 0;
second = 0;
date = 0;
second_alarm1 = 0;
minute_alarm1 = 0;
hour_alarm1 = 0;
day_alarm1 = 0;
minute_alarm2 = 0;
hour_alarm2 = 0;
day_alarm2 = 0;
alarm1Mode = 0;
alarm2Mode = 0;
temp=0;
tempNegative=false;
}
/* getRTCarray() - gets the last array taken from the RTC
*
* It gets the 'registersRTC' variable which contains the last values given by the RTC
*
* It returns a string containing this array
*/
char* WaspRTC::getRTCarray()
{
char aux[60];
for(uint8_t i = 0; i < RTC_DATA_SIZE; i++) {
sprintf(aux, "%u", registersRTC[i]);
}
return aux;
}
/* getTimestamp() - returns a string containing variables related with time and date
*
* It returns a string containing variables related with time and date. These values are the last taken from RTC
*/
char* WaspRTC::getTimestamp()
{
free(timeStamp);
timeStamp=NULL;
timeStamp=(char*)calloc(31,sizeof(char));
switch (day) {
case 1: sprintf (timeStamp, "%s, %02d/%02d/%02d - %02d:%02d.%02d", DAY_1, year, month, date, hour, minute, second);
break;
case 2: sprintf (timeStamp, "%s, %02d/%02d/%02d - %02d:%02d.%02d", DAY_2, year, month, date, hour, minute, second);
break;
case 3: sprintf (timeStamp, "%s, %02d/%02d/%02d - %02d:%02d.%02d", DAY_3, year, month, date, hour, minute, second);
break;
case 4: sprintf (timeStamp, "%s, %02d/%02d/%02d - %02d:%02d.%02d", DAY_4, year, month, date, hour, minute, second);
break;
case 5: sprintf (timeStamp, "%s, %02d/%02d/%02d - %02d:%02d.%02d", DAY_5, year, month, date, hour, minute, second);
break;
case 6: sprintf (timeStamp, "%s, %02d/%02d/%02d - %02d:%02d.%02d", DAY_6, year, month, date, hour, minute, second);
break;
case 7: sprintf (timeStamp, "%s, %02d/%02d/%02d - %02d:%02d.%02d", DAY_7, year, month, date, hour, minute, second);
break;
}
return timeStamp;
}
/* readRTC(endAddress) - reads from RTC the specified addresses
*
* It reads from RTC the specified addresses by 'endAddress'. This input specifies the last address wants to be read.
*
* 'endAddress' may be any address, but it is recommended to use one of the following:
*
* --> RTC_DATE_ADDRESS: to read time and date
* --> RTC_ALARM1_ADDRESS: to read time, date and alarm1
* --> RTC_ALARM2_ADDRESS: to read time, date, alarm1 and alarm2
*
* It stores in corresponding variables the read values up to alarm2 values and stores then in 'registersRTC' array too.
*/
void WaspRTC::readRTC(uint8_t endAddress)
{
uint16_t timecount = 0;
// ADDRESSING FROM MEMORY POSITION ZERO
Wire.beginTransmission(RTC_ADDRESS); // transmit to device #104 (0x68)
// the address specified in the datasheet is 208 (0xD0)
// but i2c adressing uses the high 7 bits so it's 104
Wire.send(RTC_START_ADDRESS); // start from address zero
Wire.endTransmission();
// START READING
Wire.requestFrom(RTC_ADDRESS, RTC_DATA_SIZE); // transmit to device #104 (0x68)
// the address specified in the datasheet is 208 (0xD0)
// but i2c adressing uses the high 7 bits so it's 104
while(timecount <= endAddress) // slave may send less than requested
{
if (Wire.available()) {
uint8_t c = Wire.receive(); // receive a byte as character
registersRTC[timecount] = c;
switch (timecount) {
case 0:
second = BCD2byte(c>>4, c&B00001111);
break;
case 1:
minute = BCD2byte(c>>4, c&B00001111);
break;
case 2:
hour = BCD2byte(c>>4, c&B00001111);
break;
case 3:
day = c;
break;
case 4:
date = BCD2byte(c>>4, c&B00001111);
break;
case 5:
month = BCD2byte(c>>4, c&B00001111);
break;
case 6:
year = BCD2byte(c>>4, c&B00001111);
break;
case 7:
second_alarm1 = BCD2byte((c>>4)&B00000111, c&B00001111);
break;
case 8:
minute_alarm1 = BCD2byte((c>>4)&B00000111, c&B00001111);
break;
case 9:
hour_alarm1 = BCD2byte((c>>4)&B00000011, c&B00001111);
break;
case 10:
day_alarm1 = BCD2byte((c>>4)&B00000011, c&B00001111);
break;
case 11:
minute_alarm2 = BCD2byte((c>>4)&B00000111, c&B00001111);
break;
case 12:
hour_alarm2 = BCD2byte((c>>4)&B00000011, c&B00001111);
break;
case 13:
day_alarm2 = BCD2byte((c>>4)&B00000011, c&B00001111);
break;
}
timecount++;
}
}
timecount = 0;
}
/* writeRTC() - writes the stored variables to the RTC
*
* It writes the stored variables corresponding to time and date to the RTC. It loads the variables into 'registersRTC'
* array and then, this array is sent to the RTC
*/
void WaspRTC::writeRTC()
{
int timecount = 0;
Wire.beginTransmission(RTC_ADDRESS); // transmit to device #104 (0x4A)
// the address specified in the datasheet is 208 (0xD0)
// but i2c adressing uses the high 7 bits so it's 104
Wire.send(RTC_START_ADDRESS); // start from address zero
registersRTC[RTC_SECONDS_ADDRESS] = byte2BCD(second);
registersRTC[RTC_MINUTES_ADDRESS] = byte2BCD(minute);
registersRTC[RTC_HOURS_ADDRESS] = byte2BCD(hour);
registersRTC[RTC_DAYS_ADDRESS] = day;
registersRTC[RTC_DATE_ADDRESS] = byte2BCD(date);
registersRTC[RTC_MONTH_ADDRESS] = byte2BCD(month);
registersRTC[RTC_YEAR_ADDRESS] = byte2BCD(year);
for(timecount = 0; timecount <= 0x06; timecount++) {
Wire.send(registersRTC[timecount]);
}
Wire.endTransmission();
}
/* writeRTCalarm1() - writes stored alarm1 to the RTC
*
* It writes stored time in corresponding alarm1 variables to the RTC. It loads these values to 'registersRTC' array
* and then is sent to the RTC
*/
void WaspRTC::writeRTCalarm1()
{
byte timecount = 0;
Wire.beginTransmission(RTC_ADDRESS); // transmit to device #104 (0x4A)
// the address specified in the datasheet is 208 (0xD0)
// but i2c adressing uses the high 7 bits so it's 104
Wire.send(RTC_ALM1_START_ADDRESS); // start from address zero
registersRTC[RTC_ALM1_SECONDS_ADDRESS] = 0x7F & byte2BCD(second_alarm1);
registersRTC[RTC_ALM1_MINUTES_ADDRESS] = 0x7F & byte2BCD(minute_alarm1);
registersRTC[RTC_ALM1_HOURS_ADDRESS] = 0x7F & byte2BCD(hour_alarm1);
registersRTC[RTC_ALM1_DAYS_ADDRESS] = 0x3F & byte2BCD(day_alarm1);
for(timecount = 7; timecount <= 0x0A; timecount++) {
Wire.send(registersRTC[timecount]);
}
Wire.endTransmission();
}
/* writeRTCalarm2() - writes stored alarm2 to the RTC
*
* It writes stored time in corresponding alarm2 variables to the RTC. It loads these values to 'registersRTC' array
* and then is sent to the RTC
*/
void WaspRTC::writeRTCalarm2()
{
byte timecount = 0;
Wire.beginTransmission(RTC_ADDRESS); // transmit to device #104 (0x4A)
// the address specified in the datasheet is 208 (0xD0)
// but i2c adressing uses the high 7 bits so it's 104
Wire.send(RTC_ALM2_START_ADDRESS); // start from address 0x0B
registersRTC[RTC_ALM2_MINUTES_ADDRESS] = 0x7F & byte2BCD(minute_alarm2);
registersRTC[RTC_ALM2_HOURS_ADDRESS] = 0x7F & byte2BCD(hour_alarm2);
registersRTC[RTC_ALM2_DAYS_ADDRESS] = 0x3F & byte2BCD(day_alarm2);
for(timecount = 0X0B; timecount <= 0x0D; timecount++) {
Wire.send(registersRTC[timecount]);
}
Wire.endTransmission();
}
/* configureAlarmMode(alarmNum, alarmMode) - configures alarmMode and enables interrupt
*
* It configures the mode for the alarm and enables interrupt. After calling this function, the alarm is set in the RTC.
* Prior to this, time and date should be set.
*
* 'alarNum' specifies if the selected alarm is 1 or 2
* 'alarMode' specifies the selected mode. The different modes are:
*
* --> RTC_ALM1_MODE1 0 // Day,hours,minutes and seconds match
* --> RTC_ALM1_MODE2 1 // Date,hours,minutes and seconds match
* --> RTC_ALM1_MODE3 2 // Hours,minutes and seconds match
* --> RTC_ALM1_MODE4 3 // Minutes and seconds match
* --> RTC_ALM1_MODE5 4 // Seconds match
* --> RTC_ALM1_MODE6 5 // Once per second
*
* --> RTC_ALM2_MODE1 0 // Day,hours and minutes match
* --> RTC_ALM2_MODE2 1 // Date,hours and minutes match
* --> RTC_ALM2_MODE3 2 // Hours and minutes
* --> RTC_ALM2_MODE4 3 // Minutes match
* --> RTC_ALM2_MODE5 4 // Once per minute
*/
void WaspRTC::configureAlarmMode (uint8_t alarmNum, uint8_t alarmMode)
{
if (alarmNum == 1){
registersRTC[RTC_CONTROL_ADDRESS] &= B11111101; // activate the INT/SQW output on alarm match
registersRTC[RTC_CONTROL_ADDRESS] |= B00000101;
writeRTCregister(RTC_CONTROL_ADDRESS);
registersRTC[RTC_STATUS_ADDRESS] &= B11111100; // reset the alarm flags
writeRTCregister(RTC_STATUS_ADDRESS);
switch (alarmMode){
case 0: // when day, hours, minutes and seconds match
registersRTC[RTC_ALM1_SECONDS_ADDRESS] &= B01111111; // set A1M1 bit to 0
writeRTCregister(RTC_ALM1_SECONDS_ADDRESS);
registersRTC[RTC_ALM1_MINUTES_ADDRESS] &= B01111111; // set A1M2 bit to 0
writeRTCregister(RTC_ALM1_MINUTES_ADDRESS);
registersRTC[RTC_ALM1_HOURS_ADDRESS] &= B01111111; // set A1M3 bit to 0
writeRTCregister(RTC_ALM1_HOURS_ADDRESS);
registersRTC[RTC_ALM1_DAYS_ADDRESS] &= B01111111; // set A1M4 bit to 0
registersRTC[RTC_ALM1_DAYS_ADDRESS] |= B01000000; // set DY/DT bit to 1
writeRTCregister(RTC_ALM1_DAYS_ADDRESS);
break;
case 1: // when date, hours, minutes and seconds match
registersRTC[RTC_ALM1_SECONDS_ADDRESS] &= B01111111; // set A1M1 bit to 0
writeRTCregister(RTC_ALM1_SECONDS_ADDRESS);
registersRTC[RTC_ALM1_MINUTES_ADDRESS] &= B01111111; // set A1M2 bit to 0
writeRTCregister(RTC_ALM1_MINUTES_ADDRESS);
registersRTC[RTC_ALM1_HOURS_ADDRESS] &= B01111111; // set A1M3 bit to 0
writeRTCregister(RTC_ALM1_HOURS_ADDRESS);
registersRTC[RTC_ALM1_DAYS_ADDRESS] &= B00111111; // set A1M4 bit to 0 and DY/DT to 0
writeRTCregister(RTC_ALM1_DAYS_ADDRESS);
break;
case 2: // when hours, minutes and seconds match
registersRTC[RTC_ALM1_SECONDS_ADDRESS] &= B01111111; // set A1M1 bit to 0
writeRTCregister(RTC_ALM1_SECONDS_ADDRESS);
registersRTC[RTC_ALM1_MINUTES_ADDRESS] &= B01111111; // set A1M2 bit to 0
writeRTCregister(RTC_ALM1_MINUTES_ADDRESS);
registersRTC[RTC_ALM1_HOURS_ADDRESS] &= B01111111; // set A1M3 bit to 0
writeRTCregister(RTC_ALM1_HOURS_ADDRESS);
registersRTC[RTC_ALM1_DAYS_ADDRESS] |= B10000000; // set A1M4 bit to 1
writeRTCregister(RTC_ALM1_DAYS_ADDRESS);
break;
case 3: // when minutes and seconds match
registersRTC[RTC_ALM1_SECONDS_ADDRESS] &= B01111111; // set A1M1 bit to 0
writeRTCregister(RTC_ALM1_SECONDS_ADDRESS);
registersRTC[RTC_ALM1_MINUTES_ADDRESS] &= B01111111; // set A1M2 bit to 0
writeRTCregister(RTC_ALM1_MINUTES_ADDRESS);
registersRTC[RTC_ALM1_HOURS_ADDRESS] |= B10000000; // set A1M3 bit to 1
writeRTCregister(RTC_ALM1_HOURS_ADDRESS);
registersRTC[RTC_ALM1_DAYS_ADDRESS] |= B10000000; // set A1M4 bit to 1
writeRTCregister(RTC_ALM1_DAYS_ADDRESS);
break;
case 4: // when seconds match
registersRTC[RTC_ALM1_SECONDS_ADDRESS] &= B01111111; // set A1M1 bit to 0
writeRTCregister(RTC_ALM1_SECONDS_ADDRESS);
registersRTC[RTC_ALM1_MINUTES_ADDRESS] |= B10000000; // set A1M2 bit to 1
writeRTCregister(RTC_ALM1_MINUTES_ADDRESS);
registersRTC[RTC_ALM1_HOURS_ADDRESS] |= B10000000; // set A1M3 bit to 1
writeRTCregister(RTC_ALM1_HOURS_ADDRESS);
registersRTC[RTC_ALM1_DAYS_ADDRESS] |= B10000000; // set A1M4 bit to 1
writeRTCregister(RTC_ALM1_DAYS_ADDRESS);
break;
case 5: // once per second
registersRTC[RTC_ALM1_SECONDS_ADDRESS] |= B10000000; // set A1M1 bit to 1
writeRTCregister(RTC_ALM1_SECONDS_ADDRESS);
registersRTC[RTC_ALM1_MINUTES_ADDRESS] |= B10000000; // set A1M2 bit to 1
writeRTCregister(RTC_ALM1_MINUTES_ADDRESS);
registersRTC[RTC_ALM1_HOURS_ADDRESS] |= B10000000; // set A1M3 bit to 1
writeRTCregister(RTC_ALM1_HOURS_ADDRESS);
registersRTC[RTC_ALM1_DAYS_ADDRESS] |= B10000000; // set A1M4 bit to 1
writeRTCregister(RTC_ALM1_DAYS_ADDRESS);
break;
case 6: // alarm1 OFF
registersRTC[RTC_CONTROL_ADDRESS] &= B11111000; // de-activate the INT/SQW output on alarm match
writeRTCregister(RTC_CONTROL_ADDRESS);
detachInt();
break;
}
}
if (alarmNum == 2){
registersRTC[RTC_CONTROL_ADDRESS] &= B11111110; // activate the INT/SQW output on alarm match
registersRTC[RTC_CONTROL_ADDRESS] |= B00000110;
writeRTCregister(RTC_CONTROL_ADDRESS);
registersRTC[RTC_STATUS_ADDRESS] &= B11111100; // reset the alarm flags
writeRTCregister(RTC_STATUS_ADDRESS);
switch (alarmMode){
case 0: // when day, hours and minutes match
registersRTC[RTC_ALM2_MINUTES_ADDRESS] &= B01111111; // set A2M2 bit to 0
writeRTCregister(RTC_ALM2_MINUTES_ADDRESS);
registersRTC[RTC_ALM2_HOURS_ADDRESS] &= B01111111; // set A2M3 bit to 0
writeRTCregister(RTC_ALM2_HOURS_ADDRESS);
registersRTC[RTC_ALM2_DAYS_ADDRESS] &= B01111111; // set A2M4 bit to 0
registersRTC[RTC_ALM2_DAYS_ADDRESS] |= B01000000; // set DY/DT bit to 1
writeRTCregister(RTC_ALM2_DAYS_ADDRESS);
break;
case 1: // when date,hours and minutes match
registersRTC[RTC_ALM2_MINUTES_ADDRESS] &= B01111111; // set A2M2 bit to 0
writeRTCregister(RTC_ALM2_MINUTES_ADDRESS);
registersRTC[RTC_ALM2_HOURS_ADDRESS] &= B01111111; // set A2M3 bit to 0
writeRTCregister(RTC_ALM2_HOURS_ADDRESS);
registersRTC[RTC_ALM2_DAYS_ADDRESS] &= B00111111; // set A2M4 bit to 0 and DY/DT to 0
writeRTCregister(RTC_ALM2_DAYS_ADDRESS);
break;
case 2: // when hours and minutes match
registersRTC[RTC_ALM2_MINUTES_ADDRESS] &= B01111111; // set A2M2 bit to 0
writeRTCregister(RTC_ALM2_MINUTES_ADDRESS);
registersRTC[RTC_ALM2_HOURS_ADDRESS] &= B01111111; // set A2M3 bit to 0
writeRTCregister(RTC_ALM2_HOURS_ADDRESS);
registersRTC[RTC_ALM2_DAYS_ADDRESS] |= B10000000; // set A2M4 bit to 1
writeRTCregister(RTC_ALM2_DAYS_ADDRESS);
break;
case 3: // when minutes match
registersRTC[RTC_ALM2_MINUTES_ADDRESS] &= B01111111; // set A2M2 bit to 0
writeRTCregister(RTC_ALM2_MINUTES_ADDRESS);
registersRTC[RTC_ALM2_HOURS_ADDRESS] |= B10000000; // set A2M3 bit to 1
writeRTCregister(RTC_ALM2_HOURS_ADDRESS);
registersRTC[RTC_ALM2_DAYS_ADDRESS] |= B10000000; // set A2M4 bit to 1
writeRTCregister(RTC_ALM2_DAYS_ADDRESS);
break;
case 4: // Once per minute
registersRTC[RTC_ALM2_MINUTES_ADDRESS] |= B10000000; // set A2M2 bit to 1
writeRTCregister(RTC_ALM2_MINUTES_ADDRESS);
registersRTC[RTC_ALM2_HOURS_ADDRESS] |= B10000000; // set A2M3 bit to 1
writeRTCregister(RTC_ALM2_HOURS_ADDRESS);
registersRTC[RTC_ALM2_DAYS_ADDRESS] |= B10000000; // set A2M4 bit to 1
writeRTCregister(RTC_ALM2_DAYS_ADDRESS);
break;
case 5: // alarm 2 OFF
registersRTC[RTC_CONTROL_ADDRESS] &= B11111000; // de-activate the INT/SQW output on alarm match
writeRTCregister(RTC_CONTROL_ADDRESS);
detachInt();
break;
}
}
attachInt();
}
/* writeRTCregister(theaddress) - writes the specified register into the RTC
*
* It writes the specified register into the RTC. It takes the data from 'registersRTC' array.
*
* - FIXME: modify it to write to EEPROM
*/
void WaspRTC::writeRTCregister(uint8_t theAddress)
{
// ADDRESSING FROM MEMORY POSITION RECEIVED AS PARAMETER
Wire.beginTransmission(RTC_ADDRESS); // transmit to device #104 (0x68)
// the address specified in the datasheet is 208 (0xD0)
// but i2c adressing uses the high 7 bits so it's 104
Wire.send(theAddress); // start from address theAddress
// START SENDING
Wire.send(registersRTC[theAddress]);
Wire.endTransmission();
}
/* readRTCregister(theaddress) - reads from RTC the specified register
*
* It reads from RTC the specified register and stores into 'registersRTC' array in corresponding position
*
* - FIXME: modify it to read from EEPROM
*/
void WaspRTC::readRTCregister(uint8_t theAddress)
{
// ADDRESSING FROM MEMORY POSITION RECEIVED AS PARAMETER
Wire.beginTransmission(RTC_ADDRESS); // transmit to device #104 (0x68)
// the address specified in the datasheet is 208 (0xD0)
// but i2c adressing uses the high 7 bits so it's 104
Wire.send(theAddress); // start from address theAddress
Wire.endTransmission();
// START READING
Wire.requestFrom(RTC_ADDRESS, 0x01); // transmit to device #104 (0x68)
// the address specified in the datasheet is 208 (0xD0)
// but i2c adressing uses the high 7 bits so it's 104
while(!Wire.available()) {};
registersRTC[theAddress] = Wire.receive();
Wire.endTransmission();
}
/* setTime(time) - sets time and date in the RTC
*
* It sets time and date in the RTC.
*
* After setting the variables, function 'writeRTC' is called to write to RTC the values
*
* 'time' must be set in a specify format: YY:MM:DD:dow:hh:mm:ss
*/
void WaspRTC::setTime(const char* time)
{
uint8_t aux=0, aux2=0;
aux=(uint8_t) time[0] - 48;
aux2=(uint8_t) time[1] - 48;
year = RTC.BCD2byte(aux, aux2);
aux=(uint8_t) time[3] - 48;
aux2=(uint8_t) time[4] - 48;
month = RTC.BCD2byte(aux, aux2);
aux=(uint8_t) time[6] - 48;
aux2=(uint8_t) time[7] - 48;
date = RTC.BCD2byte(aux, aux2);
aux=(uint8_t) time[9] - 48;
aux2=(uint8_t) time[10] - 48;
day = RTC.BCD2byte(aux, aux2);
aux=(uint8_t) time[12] - 48;
aux2=(uint8_t) time[13] - 48;
hour = RTC.BCD2byte(aux, aux2);
aux=(uint8_t) time[15] - 48;
aux2=(uint8_t) time[16] - 48;
minute = RTC.BCD2byte(aux, aux2);
aux=(uint8_t) time[18] - 48;
aux2=(uint8_t) time[19] - 48;
second = RTC.BCD2byte(aux, aux2);
writeRTC();
}
/* setTime(_year,_month,_date,day_week,_hour,_minute,_second) - sets time and date in the RTC
*
* It sets time and date in the RTC.
*
* After setting the variables, function 'writeRTC' is called to write to RTC the values
*
* Each input corresponds to the relayed part of time and date.
*/
void WaspRTC::setTime(uint8_t _year, uint8_t _month, uint8_t _date, uint8_t day_week, uint8_t _hour, uint8_t _minute, uint8_t _second)
{
uint8_t aux=0, aux2=0;
if(_year<10)
{
aux=0;
aux2=_year;
year = RTC.BCD2byte(aux, aux2);
}
else if(_year>=10)
{
aux2=_year%10;
aux=_year/10;
year = RTC.BCD2byte(aux, aux2);
}
if(_month<10)
{
aux=0;
aux2=_month;
month = RTC.BCD2byte(aux, aux2);
}
else if(_month>=10)
{
aux2=_month%10;
aux=_month/10;
month = RTC.BCD2byte(aux, aux2);
}
if(_date<10)
{
aux=0;
aux2=_date;
date = RTC.BCD2byte(aux, aux2);
}
else if(_date>=10)
{
aux2=_date%10;
aux=_date/10;
date = RTC.BCD2byte(aux, aux2);
}
if(day_week<10)
{
aux=0;
aux2=day_week;
day = RTC.BCD2byte(aux, aux2);
}
else if(day_week>=10)
{
aux2=day_week%10;
aux=day_week/10;
day = RTC.BCD2byte(aux, aux2);
}
if(_hour<10)
{
aux=0;
aux2=_hour;
hour = RTC.BCD2byte(aux, aux2);
}
else if(_hour>=10)
{
aux2=_hour%10;
aux=_hour/10;
hour = RTC.BCD2byte(aux, aux2);
}
if(_minute<10)
{
aux=0;
aux2=_minute;
minute = RTC.BCD2byte(aux, aux2);
}
else if(_minute>=10)
{
aux2=_minute%10;
aux=_minute/10;
minute = RTC.BCD2byte(aux, aux2);
}
if(_second<10)
{
aux=0;
aux2=_second;
second = RTC.BCD2byte(aux, aux2);
}
else if(_second>=10)
{
aux2=_second%10;
aux=_second/10;
second = RTC.BCD2byte(aux, aux2);
}
writeRTC();
}
/* getTime() - gets time and date
*
* It gets time and date, storing them in 'registersRTC' array.
*
* It returns a string containing time and data in the following format: "YY:MM:DD:dw:hh:mm:ss"
*/
char* WaspRTC::getTime()
{
readRTC(RTC_DATE_ADDRESS_2);
return getTimestamp();
}
/* setTimeFromGPS() - sets time and date from the GPS to the RTC. GPS has to be initialized first and got the time/date
*
* It sets time and date from the GPS to the RTC. GPS has to be initialized first and got the time/date
*
* It returns nothing
*/
void WaspRTC::setTimeFromGPS()
{
int day, month, year, hour, minute, second = 0;
day = (GPS.dateGPS[0]-'0')*10 + (GPS.dateGPS[1]-'0');
month = (GPS.dateGPS[2]-'0')*10 + (GPS.dateGPS[3]-'0');
year = (GPS.dateGPS[4]-'0')*10 + (GPS.dateGPS[5]-'0');
hour = (GPS.timeGPS[0]-'0')*10 + (GPS.timeGPS[1]-'0');
minute = (GPS.timeGPS[2]-'0')*10 + (GPS.timeGPS[3]-'0');
second = (GPS.timeGPS[4]-'0')*10 + (GPS.timeGPS[5]-'0');
RTC.setTime(year, month, day, 1, hour, minute, second);
}
/* getTemperature() - gets temperature
*
* It gets temperature from RTC. It reads associated registers to temperature and stores the temperature in a variable
* called 'temp'. If temperature is negative, a variable called 'tempNegative' is set to TRUE.
*
* It returns temperature value.
*/
uint8_t WaspRTC::getTemperature()
{
readRTCregister(RTC_MSB_TEMP_ADDRESS);
readRTCregister(RTC_LSB_TEMP_ADDRESS);
temp = (registersRTC[RTC_MSB_TEMP_ADDRESS]&B01111111) + (registersRTC[RTC_LSB_TEMP_ADDRESS]>>6);
if (registersRTC[RTC_MSB_TEMP_ADDRESS]>>7 == 1)
{
tempNegative=true;
~(temp);
temp++;
}
else tempNegative=false;
return temp;
}
/* setAlarm1(time,offset,mode) - sets Alarm1 to the specified time, offset and mode
*
* It sets Alarm1 to the specified time, offset and mode.
*
* 'time' --> has the following format : "dd:hh:mm:ss"
* 'offset' --> possible values are:
* RTC_OFFSET--> 'time' is added to the actual time read from RTC
* RTC_ABSOLUTE--> 'time' is set as the time for Alarm1
* 'mode' --> specifies the mode for Alarm1. Possible values are the same as specified in 'configureAlarmMode'
*
* This function specifies the time for alarm, sets alarm in RTC and enables interrupt.
*/
void WaspRTC::setAlarm1(const char* time, uint8_t offset, uint8_t mode)
{
uint8_t aux=0, aux2=0;
aux=(uint8_t) time[0] - 48;
aux2=(uint8_t) time[1] - 48;
day_alarm1 = BCD2byte(aux, aux2);
aux=(uint8_t) time[3] - 48;
aux2=(uint8_t) time[4] - 48;
hour_alarm1 = BCD2byte(aux, aux2);
aux=(uint8_t) time[6] - 48;
aux2=(uint8_t) time[7] - 48;
minute_alarm1 = BCD2byte(aux, aux2);
aux=(uint8_t) time[9] - 48;
aux2=(uint8_t) time[10] - 48;
second_alarm1 = BCD2byte(aux, aux2);
if(offset==RTC_OFFSET) // add the date to the actual date
{
readRTC(RTC_DATE_ADDRESS_2);
second_alarm1+=second;
if(second_alarm1>=60)
{
second_alarm1-=60;
minute_alarm1++;
}
minute_alarm1+=minute;
if(minute_alarm1>=60)
{
minute_alarm1-=60;
hour_alarm1++;
}
hour_alarm1+=hour;
if(hour_alarm1>=24)
{
hour_alarm1-=24;
day_alarm1++;
}
if(mode==RTC_ALM1_MODE1)
{
day_alarm1+=day;
if( day_alarm1>7 ) day_alarm1-=7;
}
else
{
day_alarm1+=date;
if( month==1 || month==3 || month==5 || month==7 || month==8 || month==12 )
{
if( day_alarm1>31 ) day_alarm1-=31;
}
if( month==4 || month==6 || month==9 || month==10 || month==11 )
{
if( day_alarm1>30 ) day_alarm1-=30;
}
if( month==2 )
{
if( day_alarm1>28 ) day_alarm1-=28;
}
}
}
RTC.writeRTCalarm1();
RTC.configureAlarmMode(1,mode);
}
/* setAlarm1(day_date,_hour,_minute,_second,offset,mode) - sets Alarm1 to the specified time, offset and mode
*
* It sets Alarm1 to the specified time, offset and mode.
*
* 'day_date,_hour,,_minute,_second' --> specifies the time for Alarm1
* 'offset' --> possible values are:
* RTC_OFFSET--> 'time' is added to the actual time read from RTC
* RTC_ABSOLUTE--> 'time' is set as the time for Alarm1
* 'mode' --> specifies the mode for Alarm1. Possible values are the same as specified in 'configureAlarmMode'
*
* This function specifies the time for alarm, sets alarm in RTC and enables interrupt.
*/
void WaspRTC::setAlarm1(uint8_t day_date, uint8_t _hour, uint8_t _minute, uint8_t _second, uint8_t offset, uint8_t mode)
{
uint8_t aux=0, aux2=0;
if(day_date<10)
{
aux=0;
aux2=day_date;
day_alarm1 = BCD2byte(aux, aux2);
}
else if(day_date>=10)
{
aux2=day_date%10;
aux=day_date/10;
day_alarm1 = BCD2byte(aux, aux2);
}
if(_hour<10)
{
aux=0;
aux2=_hour;
hour_alarm1 = BCD2byte(aux, aux2);
}
else if(_hour>=10)
{
aux2=_hour%10;
aux=_hour/10;
hour_alarm1 = BCD2byte(aux, aux2);
}
if(_minute<10)
{
aux=0;
aux2=_minute;
minute_alarm1 = BCD2byte(aux, aux2);
}
else if(_minute>=10)
{
aux2=_minute%10;
aux=_minute/10;
minute_alarm1 = BCD2byte(aux, aux2);
}
if(_second<10)
{
aux=0;
aux2=_second;
second_alarm1 = BCD2byte(aux, aux2);
}
else if(_second>=10)
{
aux2=_second%10;
aux=_second/10;
second_alarm1 = BCD2byte(aux, aux2);
}
if(offset==RTC_OFFSET) // add the date to the actual date
{
readRTC(RTC_DATE_ADDRESS_2);
second_alarm1+=second;
if(second_alarm1>=60)
{
second_alarm1-=60;
minute_alarm1++;
}
minute_alarm1+=minute;
if(minute_alarm1>=60)
{
minute_alarm1-=60;
hour_alarm1++;
}
hour_alarm1+=hour;
if(hour_alarm1>=24)
{
hour_alarm1-=24;
day_alarm1++;
}
if(mode==RTC_ALM1_MODE1)
{
day_alarm1+=day;
if( day_alarm1>7 ) day_alarm1-=7;
}
else
{
day_alarm1+=date;
if( month==1 || month==3 || month==5 || month==7 || month==8 || month==12 )
{
if( day_alarm1>31 ) day_alarm1-=31;
}
if( month==4 || month==6 || month==9 || month==10 || month==11 )
{
if( day_alarm1>30 ) day_alarm1-=30;
}
if( month==2 )
{
if( day_alarm1>28 ) day_alarm1-=28;
}
}
}
RTC.writeRTCalarm1();
RTC.configureAlarmMode(1,mode);
}
/* getAlarm1() - gets Alarm1 time
*
* It gets Alarm1 time from RTC.
*
* It returns a string containing this time and date for Alarm1
*/
char* WaspRTC::getAlarm1()
{
char aux[40];
readRTC(RTC_ALARM1_ADDRESS);
sprintf(aux, "%02d, %02d:%02d:%02d - %02d:%02d:%02d", date, year, month, day_alarm1, hour_alarm1, minute_alarm1, second_alarm1);
return aux;
}
/* setAlarm2(time,offset,mode) - sets Alarm2 to the specified time, offset and mode
*
* It sets Alarm2 to the specified time, offset and mode.
*
* 'time' --> has the following format : "dd:hh:mm"
* 'offset' --> possible values are:
* RTC_OFFSET--> 'time' is added to the actual time read from RTC
* RTC_ABSOLUTE--> 'time' is set as the time for Alarm2
* 'mode' --> specifies the mode for Alarm2. Possible values are the same as specified in 'configureAlarmMode'
*
* This function specifies the time for alarm, sets alarm in RTC and enables interrupt.
*/
void WaspRTC::setAlarm2(const char* time, uint8_t offset, uint8_t mode)
{
uint8_t aux=0, aux2=0;
aux=(uint8_t) time[0] - 48;
aux2=(uint8_t) time[1] - 48;
day_alarm2 = BCD2byte(aux, aux2);
aux=(uint8_t) time[3] - 48;
aux2=(uint8_t) time[4] - 48;
hour_alarm2 = BCD2byte(aux, aux2);
aux=(uint8_t) time[6] - 48;
aux2=(uint8_t) time[7] - 48;
minute_alarm2 = BCD2byte(aux, aux2);
if(offset==RTC_OFFSET) // add the date to the actual date
{
readRTC(RTC_DATE_ADDRESS_2);
minute_alarm2+=minute;
if(minute_alarm2>=60)
{
minute_alarm2-=60;
hour_alarm2++;
}
hour_alarm2+=hour;
if(hour_alarm2>=24)
{
hour_alarm2-=24;
day_alarm2++;
}
if(mode==RTC_ALM2_MODE1)
{
day_alarm2+=day;
if( day_alarm2>7 ) day_alarm2-=7;
}
else
{
day_alarm2+=date;
if( month==1 || month==3 || month==5 || month==7 || month==8 || month==12 )
{
if( day_alarm2>31 ) day_alarm2-=31;
}
if( month==4 || month==6 || month==9 || month==10 || month==11 )
{
if( day_alarm2>30 ) day_alarm2-=30;
}
if( month==2 )
{
if( day_alarm2>28 ) day_alarm2-=28;
}
}
}
RTC.writeRTCalarm2();
RTC.configureAlarmMode(2,mode);
}
/* setAlarm2(day_date,_hour,_minute,offset,mode) - sets Alarm2 to the specified time, offset and mode
*
* It sets Alarm2 to the specified time, offset and mode.
*
* 'day_date,_hour,_minute' --> specifies the time for Alarm2
* 'offset' --> possible values are:
* RTC_OFFSET--> 'time' is added to the actual time read from RTC
* RTC_ABSOLUTE--> 'time' is set as the time for Alarm2
* 'mode' --> specifies the mode for Alarm2. Possible values are the same as specified in 'configureAlarmMode'
*
* This function specifies the time for alarm, sets alarm in RTC and enables interrupt.
*/
void WaspRTC::setAlarm2(uint8_t day_date, uint8_t _hour, uint8_t _minute, uint8_t offset, uint8_t mode)
{
uint8_t aux=0, aux2=0;
if(day_date<10)
{
aux=0;
aux2=day_date;
day_alarm2 = BCD2byte(aux, aux2);
}
else if(day_date>=10)
{
aux2=day_date%10;
aux=day_date/10;
day_alarm2 = BCD2byte(aux, aux2);
}
if(_hour<10)
{
aux=0;
aux2=_hour;
hour_alarm2 = BCD2byte(aux, aux2);
}
else if(_hour>=10)
{
aux2=_hour%10;
aux=_hour/10;
hour_alarm2 = BCD2byte(aux, aux2);
}
if(_minute<10)
{
aux=0;
aux2=_minute;
minute_alarm2 = BCD2byte(aux, aux2);
}
else if(_minute>=10)
{
aux2=_minute%10;
aux=_minute/10;
minute_alarm2 = BCD2byte(aux, aux2);
}
if(offset==RTC_OFFSET) // add the date to the actual date
{
readRTC(RTC_DATE_ADDRESS_2);
minute_alarm2+=minute;
if(minute_alarm2>=60)
{
minute_alarm2-=60;
hour_alarm2++;
}
hour_alarm2+=hour;
if(hour_alarm2>=24)
{
hour_alarm2-=24;
day_alarm2++;
}
if(mode==RTC_ALM2_MODE1)
{
day_alarm2+=day;
if( day_alarm2>7 ) day_alarm2-=7;
}
else
{
day_alarm2+=date;
if( month==1 || month==3 || month==5 || month==7 || month==8 || month==12 )
{
if( day_alarm2>31 ) day_alarm2-=31;
}
if( month==4 || month==6 || month==9 || month==10 || month==11 )
{
if( day_alarm2>30 ) day_alarm2-=30;
}
if( month==2 )
{
if( day_alarm2>28 ) day_alarm2-=28;
}
}
}
RTC.writeRTCalarm2();
RTC.configureAlarmMode(2,mode);
}
/* getAlarm1() - gets Alarm1 time
*
* It gets Alarm1 time from RTC.
*
* It returns a string containing this time and date for Alarm1
*/
char* WaspRTC::getAlarm2()
{
char aux[35];
readRTC(RTC_ALARM2_ADDRESS);
sprintf (aux, "%02d, %02d:%02d:%02d - %02d:%02d", date, year, month, day_alarm2, hour_alarm2, minute_alarm2);
return aux;
}
/* clearAlarmFlag() - clear alarm flags in RTC
*
* It clears alarm flags (A1F and A2F) in the RTC.
* If these flags are not cleared after an interrupt is captured, no more interrupts could be captured.
*/
void WaspRTC::clearAlarmFlag()
{
RTC.registersRTC[RTC_STATUS_ADDRESS] &= B11111100; // reset the alarm flags in RT
RTC.writeRTCregister(RTC_STATUS_ADDRESS);
}
/* BCD2byte ( number ) - converts a BCD number to an integer
*
*/
uint8_t WaspRTC::BCD2byte(uint8_t number)
{
return (number>>4)*10 | (number & 0x0F);
}
/* BCD2byte ( high, low ) - converts a BCD number to an integer
*/
uint8_t WaspRTC::BCD2byte(uint8_t high, uint8_t low)
{
return high*10 + low;
}
/* byte2BCD ( number ) - converts an integer number to a BCD number
*/
uint8_t WaspRTC::byte2BCD(uint8_t theNumber)
{
return (theNumber%10 | ((theNumber-theNumber%10)/10)<<4); // note that binary operations have preference on the others
}
/*******************************************************************************
* HANDLING HARDWARE INTERRUPTS
*******************************************************************************/
/*
* attachInterrupt(void) - configure the specific hardware interrupt for the RTC
*
* the default interrupt functions are defined inside WInterrupts.c
*/
void WaspRTC::attachInt(void)
{
enableInterrupts(RTC_INT);
}
/*
* detachInterrupt(void) - unset the specific hardware interrupt for the RTC
*
* It also clear Alarm Flags so as to provide RTC the correct parameters for future alarms
*/
void WaspRTC::detachInt(void)
{
disableInterrupts(RTC_INT);
clearAlarmFlag();
}
// Private Methods /////////////////////////////////////////////////////////////
// Preinstantiate Objects //////////////////////////////////////////////////////
WaspRTC RTC = WaspRTC();