From 9c9164c4475aeec5935aa366dd05b410991579e9 Mon Sep 17 00:00:00 2001 From: BlackMark Date: Sat, 16 Dec 2017 19:48:54 +0100 Subject: [PATCH] Renamed rtc tm and implemented DST --- ds3231/clock.h | 2 +- ds3231/ds3231.cppproj | 133 +++++++++++++++++++++++------------------- ds3231/main.cpp | 120 ++++++++++++++++++++++++++++++++----- ds3231/rtc.cpp | 50 ++++++++-------- ds3231/rtc.h | 12 ++-- 5 files changed, 210 insertions(+), 107 deletions(-) diff --git a/ds3231/clock.h b/ds3231/clock.h index cbdc6c5..a04b5ea 100644 --- a/ds3231/clock.h +++ b/ds3231/clock.h @@ -7,7 +7,7 @@ #ifndef CLOCK_H #define CLOCK_H -#define F_CPU 16000000 +#define F_CPU 8000000 #include diff --git a/ds3231/ds3231.cppproj b/ds3231/ds3231.cppproj index d937a3f..25a4d45 100644 --- a/ds3231/ds3231.cppproj +++ b/ds3231/ds3231.cppproj @@ -38,7 +38,7 @@ - com.atmel.avrdbg.tool.simulator + com.atmel.avrdbg.tool.stk500 0x1E950F @@ -53,7 +53,7 @@ Custom Programming Tool - + ISP @@ -66,68 +66,83 @@ Simulator + 0 + + + + + 125000 + + ISP + + com.atmel.avrdbg.tool.stk500 + + + STK500 + + 125000 - -mmcu=atmega328p -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\gcc\dev\atmega328p" - True - True - True - True - False - True - True - - - %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include - - - True - True - True - True - True - - - %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include - - - True - True - True - True - -Wextra -std=c++11 - - - libm - - - - - %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include - - - - - NDEBUG - - - Optimize for size (-Os) - - - NDEBUG - - - Optimize for size (-Os) - + -mmcu=atmega328p -B "%24(PackRepoDir)\Atmel\ATmega_DFP\1.2.193\gcc\dev\atmega328p" + True + True + True + True + False + True + True + + + NDEBUG + + + + + %24(PackRepoDir)\Atmel\ATmega_DFP\1.2.193\include + + + Optimize for size (-Os) + True + True + True + True + True + + + NDEBUG + + + + + %24(PackRepoDir)\Atmel\ATmega_DFP\1.2.193\include + + + Optimize for size (-Os) + True + True + True + True + -Wextra -std=c++14 + + + libm + + + + + %24(PackRepoDir)\Atmel\ATmega_DFP\1.2.193\include + + + - echo "C:\avrdude-6.2\avrdude.exe" -v -p$(avrdevice) %%* -Uflash:w:"$(OutputDirectory)\$(Name).hex":i > "$(MSBuildProjectDirectory)\avrdude.bat" + echo "C:\bin\avrdude-6.3\avrdude.exe" -v -p$(avrdevice) %%* -Uflash:w:"$(OutputDirectory)\$(Name).hex":i > "$(MSBuildProjectDirectory)\avrdude.bat" - -mmcu=atmega328p -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\gcc\dev\atmega328p" + -mmcu=atmega328p -B "%24(PackRepoDir)\Atmel\ATmega_DFP\1.2.193\gcc\dev\atmega328p" True True True @@ -142,7 +157,7 @@ - %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include + %24(PackRepoDir)\Atmel\ATmega_DFP\1.2.193\include Optimize (-O1) @@ -159,7 +174,7 @@ - %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include + %24(PackRepoDir)\Atmel\ATmega_DFP\1.2.193\include Optimize (-O1) @@ -176,13 +191,13 @@ - %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include + %24(PackRepoDir)\Atmel\ATmega_DFP\1.2.193\include Default (-Wa,-g) - echo "C:\avrdude-6.2\avrdude.exe" -v -p$(avrdevice) %%* -Uflash:w:"$(OutputDirectory)\$(Name).hex":i > "$(MSBuildProjectDirectory)\avrdude.bat" + echo "C:\bin\avrdude-6.3\avrdude.exe" -v -p$(avrdevice) %%* -Uflash:w:"$(OutputDirectory)\$(Name).hex":i > "$(MSBuildProjectDirectory)\avrdude.bat" diff --git a/ds3231/main.cpp b/ds3231/main.cpp index 207cf25..0a65b3c 100644 --- a/ds3231/main.cpp +++ b/ds3231/main.cpp @@ -1,11 +1,12 @@ /* * Copyright (c) by BlackMark 2017 -* Date 26/04/2017 -* Version 1.0 +* Date 16/12/2017 +* Version 1.1 */ #include #include +#include #include #include "usart/usart.h" @@ -14,6 +15,52 @@ #include "twi.h" #include "rtc.h" +// DST magic by Edgar Bonet +int eu_dst( const time_t *timer, int32_t *z ) +{ + static_cast( z ); + + uint32_t t = *timer; + + if( static_cast( t >> 24 ) >= 194 ) + t -= 3029443200U; + + t = ( t + 655513200 ) / 604800 * 28; + + if( static_cast( t % 1461 ) < 856 ) + return ONE_HOUR; + else + return 0; +} + +tm getTime() +{ + tm sTime; + + rtc_tm* ptmTime = rtc_get_time(); + + sTime.tm_sec = ptmTime->sec; + sTime.tm_min = ptmTime->min; + sTime.tm_hour = ptmTime->hour; + sTime.tm_mday = ptmTime->mday; + sTime.tm_mon = ptmTime->mon - 1; + sTime.tm_year = ptmTime->year - 1900; + sTime.tm_isdst = 0; + + time_t timeNow = mk_gmtime( &sTime ); + sTime.tm_isdst = eu_dst( &timeNow, nullptr ); + + mktime( &sTime ); + + return sTime; +} + +void setSystemTime() +{ + tm sTime = getTime(); + set_system_time( mktime( &sTime ) ); +} + void setup() { USART0 &cSerial = USART0::inst(); @@ -29,17 +76,37 @@ void setup() { cSerial << "ERROR - No RTC detected!" << "\r\n"; } + + set_zone( 1 * ONE_HOUR ); + set_dst( eu_dst ); + + setSystemTime(); } void setTime() { USART0 &cSerial = USART0::inst(); - tm* tmTime = rtc_get_time(); + rtc_tm* tmTime = rtc_get_time(); constexpr auto BUFFER_SIZE = 32; char szBuffer[BUFFER_SIZE]; + cSerial << "Set time:" << "\r\n" << "Year: "; + cSerial.receiveLine( szBuffer, BUFFER_SIZE, "\r" ); + cSerial << szBuffer << "\r\n"; + tmTime->year = atoi( szBuffer ); + + cSerial << "Set time:" << "\r\n" << "Month: "; + cSerial.receiveLine( szBuffer, BUFFER_SIZE, "\r" ); + cSerial << szBuffer << "\r\n"; + tmTime->mon = atoi( szBuffer ); + + cSerial << "Set time:" << "\r\n" << "Day: "; + cSerial.receiveLine( szBuffer, BUFFER_SIZE, "\r" ); + cSerial << szBuffer << "\r\n"; + tmTime->mday = atoi( szBuffer ); + cSerial << "Set time:" << "\r\n" << "Hour: "; cSerial.receiveLine( szBuffer, BUFFER_SIZE, "\r" ); cSerial << szBuffer << "\r\n"; @@ -56,13 +123,15 @@ void setTime() tmTime->sec = atoi( szBuffer ); rtc_set_time( tmTime ); + + setSystemTime(); } void setAlarm() { USART0 &cSerial = USART0::inst(); - tm* tmAlarm = rtc_get_alarm(); + rtc_tm* tmAlarm = rtc_get_alarm(); constexpr auto BUFFER_SIZE = 32; char szBuffer[BUFFER_SIZE]; @@ -85,6 +154,16 @@ void setAlarm() rtc_set_alarm( tmAlarm ); } +bool timeDiff( const tm &sTime1, const tm &sTime2 ) +{ + if( sTime1.tm_sec != sTime2.tm_sec || sTime1.tm_min != sTime2.tm_min || sTime1.tm_hour != sTime2.tm_hour ) + return true; + if( sTime1.tm_mday != sTime2.tm_mday || sTime1.tm_mon != sTime2.tm_mon || sTime1.tm_year != sTime2.tm_year ) + return true; + + return false; +} + int main() { uint8_t ui8MCUSR = handleReset(); @@ -101,24 +180,25 @@ int main() setup(); - uint8_t ui8Hour; - uint8_t ui8Minute; - uint8_t ui8Second; - - char szBuffer[32]; + tm sTime; + + constexpr auto BUFFER_SIZE = 32; + char szBuffer[BUFFER_SIZE]; while( true ) { - tm* tmTime = rtc_get_time(); + tm sTimeNow = getTime(); - if( tmTime->hour != ui8Hour || tmTime->min != ui8Minute || tmTime->sec != ui8Second ) + if( timeDiff( sTime, sTimeNow ) ) { - ui8Hour = tmTime->hour; - ui8Minute = tmTime->min; - ui8Second = tmTime->sec; + system_tick(); - sprintf( szBuffer, "%02d:%02d:%02d\r\n", ui8Hour, ui8Minute, ui8Second ); - cSerial << "Time: " << szBuffer; + time_t timeNow = time( nullptr ); + tm *psLocalTime = localtime( &timeNow ); + + strftime( szBuffer, BUFFER_SIZE, "%F %T %z", psLocalTime ); + + cSerial << "Time: " << szBuffer << "\r\n"; if( rtc_check_alarm() ) { @@ -126,6 +206,8 @@ int main() } } + sTime = sTimeNow; + uint8_t ui8Cmd; if( cSerial.receiveByte( ui8Cmd ) ) @@ -146,6 +228,10 @@ int main() } else if( ui8Cmd == 'p' ) { + uint8_t ui8Hour; + uint8_t ui8Minute; + uint8_t ui8Second; + rtc_get_alarm_s( &ui8Hour, &ui8Minute, &ui8Second ); sprintf( szBuffer, "Alarm set to: %02d:%02d:%02d", ui8Hour, ui8Minute, ui8Second ); cSerial << szBuffer << "\r\n"; @@ -156,6 +242,8 @@ int main() cSerial.transmitByte( ui8Cmd ); cSerial << "'" << "\r\n"; } + + setSystemTime(); } } diff --git a/ds3231/rtc.cpp b/ds3231/rtc.cpp index 2e76f8e..a64a5b2 100644 --- a/ds3231/rtc.cpp +++ b/ds3231/rtc.cpp @@ -79,7 +79,7 @@ #define CH_BIT 7 // clock halt bit // statically allocated structure for time value -struct tm _tm; +struct rtc_tm _rtc_tm; uint8_t dec2bcd(uint8_t d) { @@ -146,7 +146,7 @@ bool rtc_is_ds3231(void) { return s_is_ds3231; } void rtc_set_ds1307(void) { s_is_ds1307 = true; s_is_ds3231 = false; } void rtc_set_ds3231(void) { s_is_ds1307 = false; s_is_ds3231 = true; } -struct tm* rtc_get_time(void) +struct rtc_tm* rtc_get_time(void) { uint8_t rtc[9]; uint8_t century = 0; @@ -169,27 +169,27 @@ struct tm* rtc_get_time(void) // This starts the clock for a DS1307, and has no effect for a DS3231 rtc[0] &= ~(_BV(CH_BIT)); // clear bit - _tm.sec = bcd2dec(rtc[0]); - _tm.min = bcd2dec(rtc[1]); - _tm.hour = bcd2dec(rtc[2]); - _tm.mday = bcd2dec(rtc[4]); - _tm.mon = bcd2dec(rtc[5] & 0x1F); // returns 1-12 + _rtc_tm.sec = bcd2dec(rtc[0]); + _rtc_tm.min = bcd2dec(rtc[1]); + _rtc_tm.hour = bcd2dec(rtc[2]); + _rtc_tm.mday = bcd2dec(rtc[4]); + _rtc_tm.mon = bcd2dec(rtc[5] & 0x1F); // returns 1-12 century = (rtc[5] & 0x80) >> 7; - _tm.year = century == 1 ? 2000 + bcd2dec(rtc[6]) : 1900 + bcd2dec(rtc[6]); // year 0-99 - _tm.wday = bcd2dec(rtc[3]); // returns 1-7 + _rtc_tm.year = century == 1 ? 2000 + bcd2dec(rtc[6]) : 1900 + bcd2dec(rtc[6]); // year 0-99 + _rtc_tm.wday = bcd2dec(rtc[3]); // returns 1-7 - if (_tm.hour == 0) { - _tm.twelveHour = 0; - _tm.am = 1; - } else if (_tm.hour < 12) { - _tm.twelveHour = _tm.hour; - _tm.am = 1; + if (_rtc_tm.hour == 0) { + _rtc_tm.twelveHour = 0; + _rtc_tm.am = 1; + } else if (_rtc_tm.hour < 12) { + _rtc_tm.twelveHour = _rtc_tm.hour; + _rtc_tm.am = 1; } else { - _tm.twelveHour = _tm.hour - 12; - _tm.am = 0; + _rtc_tm.twelveHour = _rtc_tm.hour - 12; + _rtc_tm.am = 0; } - return &_tm; + return &_rtc_tm; } void rtc_get_time_s(uint8_t* hour, uint8_t* min, uint8_t* sec) @@ -216,7 +216,7 @@ void rtc_get_time_s(uint8_t* hour, uint8_t* min, uint8_t* sec) } // fixme: support 12-hour mode for setting time -void rtc_set_time(struct tm* tm_) +void rtc_set_time(struct rtc_tm* tm_) { twi_begin_transmission(RTC_ADDR); twi_send_byte(0x0); @@ -550,7 +550,7 @@ void rtc_set_alarm_s(uint8_t hour, uint8_t min, uint8_t sec) } } -void rtc_set_alarm(struct tm* tm_) +void rtc_set_alarm(struct rtc_tm* tm_) { if (!tm_) return; rtc_set_alarm_s(tm_->hour, tm_->min, tm_->sec); @@ -570,15 +570,15 @@ void rtc_get_alarm_s(uint8_t* hour, uint8_t* min, uint8_t* sec) } } -struct tm* rtc_get_alarm(void) +struct rtc_tm* rtc_get_alarm(void) { uint8_t hour, min, sec; rtc_get_alarm_s(&hour, &min, &sec); - _tm.hour = hour; - _tm.min = min; - _tm.sec = sec; - return &_tm; + _rtc_tm.hour = hour; + _rtc_tm.min = min; + _rtc_tm.sec = sec; + return &_rtc_tm; } bool rtc_check_alarm(void) diff --git a/ds3231/rtc.h b/ds3231/rtc.h index 08e0994..da0424e 100644 --- a/ds3231/rtc.h +++ b/ds3231/rtc.h @@ -38,7 +38,7 @@ * and translation has to be done manually (you can call rtc_24h_to_12h to perform the calculation) * */ -struct tm { +struct rtc_tm { int sec; // 0 to 59 int min; // 0 to 59 int hour; // 0 to 23 @@ -53,7 +53,7 @@ struct tm { }; // statically allocated -extern struct tm _tm; +extern struct rtc_tm _rtc_tm; // Initialize the RTC and autodetect type (DS1307 or DS3231) void rtc_init(void); @@ -67,11 +67,11 @@ void rtc_set_ds3231(void); // Get/set time // Gets the time: Supports both 24-hour and 12-hour mode -struct tm* rtc_get_time(void); +struct rtc_tm* rtc_get_time(void); // Gets the time: 24-hour mode only void rtc_get_time_s(uint8_t* hour, uint8_t* min, uint8_t* sec); // Sets the time: Supports both 24-hour and 12-hour mode -void rtc_set_time(struct tm* tm_); +void rtc_set_time(struct rtc_tm* tm_); // Sets the time: Supports 12-hour mode only void rtc_set_time_s(uint8_t hour, uint8_t min, uint8_t sec); @@ -98,9 +98,9 @@ void rtc_osc32kHz_enable(bool enable); // Alarm functionality void rtc_reset_alarm(void); -void rtc_set_alarm(struct tm* tm_); +void rtc_set_alarm(struct rtc_tm* tm_); void rtc_set_alarm_s(uint8_t hour, uint8_t min, uint8_t sec); -struct tm* rtc_get_alarm(void); +struct rtc_tm* rtc_get_alarm(void); void rtc_get_alarm_s(uint8_t* hour, uint8_t* min, uint8_t* sec); bool rtc_check_alarm(void);