├── .gitignore ├── README.md ├── library.properties ├── library.json ├── examples ├── Due_RTC_Alarm_Sample │ └── Due_RTC_Alarm_Sample.ino ├── Due_RTC_Simple_Sample │ └── Due_RTC_Simple_Sample.ino ├── Due_RTC_Simple_test_of_date │ └── Due_RTC_Simple_test_of_date.ino ├── Due_RTC_Simple_Sample_oneline_time_and_date │ └── Due_RTC_Simple_Sample_oneline_time_and_date.ino ├── Due_RTC_Simple_Unixtime_Compilertime │ └── Due_RTC_Simple_Unixtime_Compilertime.ino ├── Due_RTC_Simple_Sample_german_summertime │ └── Due_RTC_Simple_Sample_german_summertime.ino ├── Due_RTC_Simple_Unixtime_timezone │ └── Due_RTC_Simple_Unixtime_timezone.ino ├── Due_RTC_Simple_Sample_NTP_ETHERNET │ └── Due_RTC_Simple_Sample_NTP_ETHERNET.ino └── Due_RTC_Simple_Sample_NTP_WIFI │ └── Due_RTC_Simple_Sample_NTP_WIFI.ino ├── keywords.txt ├── src ├── rtc_clock.h └── rtc_clock.cpp └── change.log /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | 15 | # Backups 16 | *.bak 17 | 18 | # Folder 19 | nppBackup -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Arduino-Due-RTC-Library 2 | ======================= 3 | 4 | RTC Library for the Arduino Due, now outdated use the new https://github.com/MarkusLange/RTCDue keep in mind the first day of the week has changed from Monday to Sunday as usual by other RTC librarys. 5 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Due RTC Library 2 | version=2.1 3 | author=Markus Lange 4 | maintainer=Markus Lange 5 | sentence=Use for the RTC inside the SAM3X8E from the Arduino DUE 6 | paragraph=The Due RTC Library feature: access to the RTC Modul from the DUE to set time and alarm functions. 7 | category=Timing 8 | url=https://github.com/MarkusLange/Arduino-Due-RTC-Library 9 | architectures=sam 10 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DueRTC", 3 | "version": "2.1", 4 | "keywords": "rtc, time, clock", 5 | "description": "Access to the RTC Module inside the SAM3X8E from the DUE to set time and alarm functions", 6 | "repository": 7 | { 8 | "type": "git", 9 | "url": "https://github.com/MarkusLange/Arduino-Due-RTC-Library.git" 10 | }, 11 | "frameworks": "arduino", 12 | "platforms": "atmelsam" 13 | } 14 | -------------------------------------------------------------------------------- /examples/Due_RTC_Alarm_Sample/Due_RTC_Alarm_Sample.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Select the Slowclock source 4 | //RTC_clock rtc_clock(RC); 5 | RTC_clock rtc_clock(XTAL); 6 | 7 | char* daynames[]={"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; 8 | 9 | void setup() { 10 | Serial.begin(9600); 11 | rtc_clock.init(); 12 | rtc_clock.set_time(10, 29, 49); 13 | 14 | rtc_clock.set_alarmtime(10, 30, 0); 15 | 16 | rtc_clock.attachalarm(announcement); 17 | // rtc_clock.disable_alarm(); 18 | } 19 | 20 | void loop() { 21 | Serial.print("At the third stroke, it will be "); 22 | Serial.print(rtc_clock.get_hours()); 23 | Serial.print(":"); 24 | Serial.print(rtc_clock.get_minutes()); 25 | Serial.print(":"); 26 | Serial.println(rtc_clock.get_seconds()); 27 | } 28 | 29 | void announcement() { 30 | Serial.println(); 31 | Serial.println("Get up and buy an Arduino Due."); 32 | } 33 | -------------------------------------------------------------------------------- /examples/Due_RTC_Simple_Sample/Due_RTC_Simple_Sample.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Select the Slowclock source 4 | //RTC_clock rtc_clock(RC); 5 | RTC_clock rtc_clock(XTAL); 6 | 7 | char* daynames[]={"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; 8 | 9 | void setup() { 10 | Serial.begin(9600); 11 | rtc_clock.init(); 12 | rtc_clock.set_time(10, 29, 9); 13 | rtc_clock.set_date(22, 10, 2012); 14 | } 15 | 16 | void loop() { 17 | Serial.print("At the third stroke, it will be "); 18 | Serial.print(rtc_clock.get_hours()); 19 | Serial.print(":"); 20 | Serial.print(rtc_clock.get_minutes()); 21 | Serial.print(":"); 22 | Serial.println(rtc_clock.get_seconds()); 23 | Serial.print(" "); 24 | Serial.print(daynames[rtc_clock.get_day_of_week()-1]); 25 | Serial.print(": "); 26 | Serial.print(rtc_clock.get_days()); 27 | Serial.print("."); 28 | Serial.print(rtc_clock.get_months()); 29 | Serial.print("."); 30 | Serial.println(rtc_clock.get_years()); 31 | } 32 | -------------------------------------------------------------------------------- /examples/Due_RTC_Simple_test_of_date/Due_RTC_Simple_test_of_date.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define START_VALUE "Jan 01 2007" 4 | 5 | // Select the Slowclock source 6 | //RTC_clock rtc_clock(RC); 7 | RTC_clock rtc_clock(XTAL); 8 | 9 | int counter = 0; 10 | 11 | void setup() { 12 | Serial.begin(9600); 13 | rtc_clock.init(); 14 | } 15 | 16 | void loop() { 17 | if (rtc_clock.date_already_set() == 0) { 18 | Serial.print("no "); 19 | } else { 20 | Serial.print("yes "); 21 | } 22 | digitprint(counter, 3, 1); 23 | Serial.println(); 24 | delay(125); 25 | if (counter == 50) { 26 | rtc_clock.set_date(__DATE__); 27 | } 28 | if (counter == 100) { 29 | counter = 0; 30 | // technical all the same 31 | //rtc_clock.set_date( 1, 1, 2007); 32 | //rtc_clock.set_date("Jan 01 2007"); 33 | rtc_clock.set_date(START_VALUE); 34 | } 35 | counter++; 36 | } 37 | 38 | void digitprint(int value, int lenght, int placeholder){ 39 | for (int i = 0; i < (lenght - numdigits(value)); i++){ 40 | if (placeholder == 0) 41 | Serial.print("0"); 42 | else 43 | Serial.print(" "); 44 | } 45 | Serial.print(value); 46 | } 47 | 48 | int numdigits(int i){ 49 | int digits; 50 | if (i < 10) 51 | digits = 1; 52 | else 53 | digits = (int)(log10((double)i)) + 1; 54 | return digits; 55 | } 56 | -------------------------------------------------------------------------------- /examples/Due_RTC_Simple_Sample_oneline_time_and_date/Due_RTC_Simple_Sample_oneline_time_and_date.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Select the Slowclock source 4 | //RTC_clock rtc_clock(RC); 5 | RTC_clock rtc_clock(XTAL); 6 | 7 | char* daynames[]={"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; 8 | int hh,mm,ss,dow,dd,mon,yyyy; 9 | 10 | void setup() { 11 | Serial.begin(9600); 12 | rtc_clock.init(); 13 | rtc_clock.set_clock(__DATE__, __TIME__); 14 | } 15 | 16 | void loop() { 17 | Serial.print("Time: "); 18 | rtc_clock.get_time(&hh,&mm,&ss); 19 | rtc_clock.get_date(&dow,&dd,&mon,&yyyy); 20 | digitprint(hh, 2); 21 | Serial.print(":"); 22 | digitprint(mm, 2); 23 | Serial.print(":"); 24 | digitprint(ss, 2); 25 | Serial.println(""); 26 | Serial.print("Date: "); 27 | Serial.print(daynames[dow-1]); 28 | Serial.print(" "); 29 | digitprint(dd, 2); 30 | Serial.print("."); 31 | digitprint(mon, 2); 32 | Serial.print("."); 33 | Serial.println(yyyy); 34 | Serial.println(""); 35 | } 36 | 37 | void digitprint(int value, int lenght){ 38 | for (int i = 0; i < (lenght - numdigits(value)); i++){ 39 | Serial.print("0"); 40 | } 41 | Serial.print(value); 42 | } 43 | 44 | int numdigits(int i){ 45 | int digits; 46 | if (i < 10) 47 | digits = 1; 48 | else 49 | digits = (int)(log10((double)i)) + 1; 50 | return digits; 51 | } 52 | -------------------------------------------------------------------------------- /examples/Due_RTC_Simple_Unixtime_Compilertime/Due_RTC_Simple_Unixtime_Compilertime.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Select the Slowclock source 4 | //RTC_clock rtc_clock(RC); 5 | RTC_clock rtc_clock(XTAL); 6 | 7 | char* daynames[]={"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; 8 | 9 | void setup() { 10 | Serial.begin(9600); 11 | rtc_clock.init(); 12 | rtc_clock.set_time(__TIME__); 13 | rtc_clock.set_date(__DATE__); 14 | } 15 | 16 | void loop() { 17 | Serial.print("Unixtime: "); 18 | Serial.println(rtc_clock.unixtime()); 19 | Serial.println("And in plain for everyone"); 20 | Serial.print("Time: "); 21 | digitprint(rtc_clock.get_hours(), 2); 22 | Serial.print(":"); 23 | digitprint(rtc_clock.get_minutes(), 2); 24 | Serial.print(":"); 25 | digitprint(rtc_clock.get_seconds(), 2); 26 | Serial.println(""); 27 | Serial.print("Date: "); 28 | Serial.print(daynames[rtc_clock.get_day_of_week()-1]); 29 | Serial.print(" "); 30 | digitprint(rtc_clock.get_days(), 2); 31 | Serial.print("."); 32 | digitprint(rtc_clock.get_months(), 2); 33 | Serial.print("."); 34 | Serial.println(rtc_clock.get_years()); 35 | Serial.println(""); 36 | } 37 | 38 | void digitprint(int value, int lenght){ 39 | for (int i = 0; i < (lenght - numdigits(value)); i++){ 40 | Serial.print("0"); 41 | } 42 | Serial.print(value); 43 | } 44 | 45 | int numdigits(int i){ 46 | int digits; 47 | if (i < 10) 48 | digits = 1; 49 | else 50 | digits = (int)(log10((double)i)) + 1; 51 | return digits; 52 | } -------------------------------------------------------------------------------- /examples/Due_RTC_Simple_Sample_german_summertime/Due_RTC_Simple_Sample_german_summertime.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Select the Slowclock source 4 | //RTC_clock rtc_clock(RC); 5 | RTC_clock rtc_clock(XTAL); 6 | 7 | char* daynames[]={"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; 8 | int hh,mm,ss,dow,dd,mon,yyyy; 9 | 10 | void setup() { 11 | Serial.begin(9600); 12 | rtc_clock.init(); 13 | rtc_clock.set_clock("Oct 25 2015", "02:59:58"); 14 | //rtc_clock.set_clock(__DATE__, __TIME__); 15 | } 16 | 17 | int ss_old = 0; 18 | 19 | void loop() { 20 | rtc_clock.dst_followup(); 21 | rtc_clock.get_time(&hh,&mm,&ss); 22 | rtc_clock.get_date(&dow,&dd,&mon,&yyyy); 23 | if (ss != ss_old) { 24 | ss_old = ss; 25 | Serial.print("Time: "); 26 | digitprint(hh, 2); 27 | Serial.print(":"); 28 | digitprint(mm, 2); 29 | Serial.print(":"); 30 | digitprint(ss, 2); 31 | Serial.println(""); 32 | Serial.print("Date: "); 33 | Serial.print(daynames[dow-1]); 34 | Serial.print(" "); 35 | digitprint(dd, 2); 36 | Serial.print("."); 37 | digitprint(mon, 2); 38 | Serial.print("."); 39 | Serial.println(yyyy); 40 | Serial.println(""); 41 | } 42 | if (ss == 2) 43 | rtc_clock.set_clock("Mar 29 2015", "01:59:58"); 44 | if (ss == 2 && mon == 3) 45 | rtc_clock.set_clock("Oct 25 2015", "02:59:58"); 46 | } 47 | 48 | void digitprint(int value, int lenght){ 49 | for (int i = 0; i < (lenght - numdigits(value)); i++){ 50 | Serial.print("0"); 51 | } 52 | Serial.print(value); 53 | } 54 | 55 | int numdigits(int i){ 56 | int digits; 57 | if (i < 10) 58 | digits = 1; 59 | else 60 | digits = (int)(log10((double)i)) + 1; 61 | return digits; 62 | } 63 | -------------------------------------------------------------------------------- /examples/Due_RTC_Simple_Unixtime_timezone/Due_RTC_Simple_Unixtime_timezone.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Select the Slowclock source 4 | //RTC_clock rtc_clock(RC); 5 | RTC_clock rtc_clock(XTAL); 6 | 7 | char* daynames[]={"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; 8 | 9 | void setup() { 10 | Serial.begin(9600); 11 | rtc_clock.init(); 12 | rtc_clock.set_time(__TIME__); 13 | rtc_clock.set_date(__DATE__); 14 | } 15 | 16 | void loop() { 17 | Serial.print("Unixtime: "); 18 | // All known Time-zones are supported set in this style "UTC+1" or "UTC-930" without colon 19 | // so if you add an Time-zone as parameter you get an unixtime that adopts the "local-time" time shift 20 | Serial.println(rtc_clock.unixtime(UTC-5)); 21 | Serial.println("And in plain for everyone"); 22 | Serial.print("Time: "); 23 | digitprint(rtc_clock.get_hours(), 2); 24 | Serial.print(":"); 25 | digitprint(rtc_clock.get_minutes(), 2); 26 | Serial.print(":"); 27 | digitprint(rtc_clock.get_seconds(), 2); 28 | Serial.println(""); 29 | Serial.print("Date: "); 30 | Serial.print(daynames[rtc_clock.get_day_of_week()-1]); 31 | Serial.print(" "); 32 | digitprint(rtc_clock.get_days(), 2); 33 | Serial.print("."); 34 | digitprint(rtc_clock.get_months(), 2); 35 | Serial.print("."); 36 | Serial.println(rtc_clock.get_years()); 37 | Serial.println(""); 38 | } 39 | 40 | void digitprint(int value, int lenght){ 41 | for (int i = 0; i < (lenght - numdigits(value)); i++){ 42 | Serial.print("0"); 43 | } 44 | Serial.print(value); 45 | } 46 | 47 | int numdigits(int i){ 48 | int digits; 49 | if (i < 10) 50 | digits = 1; 51 | else 52 | digits = (int)(log10((double)i)) + 1; 53 | return digits; 54 | } 55 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Due-RTC 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | RTC_clock KEYWORD1 10 | rtc_clock KEYWORD1 11 | 12 | ####################################### 13 | # Methods and Functions (KEYWORD2) 14 | ####################################### 15 | 16 | init KEYWORD2 17 | set_time KEYWORD2 18 | set_date KEYWORD2 19 | set_seconds KEYWORD2 20 | set_minutes KEYWORD2 21 | set_hours KEYWORD2 22 | set_days KEYWORD2 23 | set_months KEYWORD2 24 | set_years KEYWORD2 25 | set_alarmtime KEYWORD2 26 | set_alarmdate KEYWORD2 27 | get_seconds KEYWORD2 28 | get_minutes KEYWORD2 29 | get_hours KEYWORD2 30 | get_days KEYWORD2 31 | get_day_of_week KEYWORD2 32 | get_months KEYWORD2 33 | get_years KEYWORD2 34 | attachalarm KEYWORD2 35 | disable_alarm KEYWORD2 36 | unixtime KEYWORD2 37 | get_time KEYWORD2 38 | get_date KEYWORD2 39 | summertime KEYWORD2 40 | switch_years KEYWORD2 41 | timing KEYWORD2 42 | date_already_set KEYWORD2 43 | set_clock KEYWORD2 44 | UTC_abbreviation KEYWORD2 45 | dst_followup KEYWORD2 46 | 47 | ####################################### 48 | # Instances (KEYWORD2) 49 | ####################################### 50 | 51 | 52 | ####################################### 53 | # Mean Instances (KEYWORD3) 54 | ####################################### 55 | 56 | #rtc_clock KEYWORD3 57 | 58 | ####################################### 59 | # Constants (LITERAL1) 60 | ####################################### 61 | 62 | RC LITERAL1 63 | XTAL LITERAL1 64 | 65 | __TIME__ LITERAL1 66 | __DATE__ LITERAL1 67 | 68 | Germany LITERAL1 69 | 70 | CET LITERAL1 71 | CEST LITERAL1 -------------------------------------------------------------------------------- /src/rtc_clock.h: -------------------------------------------------------------------------------- 1 | #ifndef RTC_clock_h 2 | #define RTC_clock_h 3 | 4 | #include "Arduino.h" 5 | 6 | // Includes Atmel CMSIS 7 | #include 8 | 9 | #define SUPC_KEY 0xA5u 10 | #define RESET_VALUE 0x01210720 11 | 12 | #define RC 0 13 | #define XTAL 1 14 | /* 15 | // Unixtimeseconds from 1. Januar 1970 00:00:00 to 1. Januar 2000 00:00:00 UTC-0 16 | #define SECONDS_FROM_1970_TO_2000 946684800 17 | */ 18 | #define SECONDS_PER_HOUR 3600 19 | 20 | #define UTC 0 21 | #define Germany 2000 22 | 23 | #define CET 1 //MEZ 24 | #define CEST 2 //MESZ 25 | 26 | class RTC_clock 27 | { 28 | public: 29 | RTC_clock (int source); 30 | void init (); 31 | void set_time (int hour, int minute, int second); 32 | void set_time (char* time); 33 | int get_hours (); 34 | int get_minutes (); 35 | int get_seconds (); 36 | void set_date (int day, int month, uint16_t year); 37 | void set_date (char* date); 38 | void set_clock (char* date, char* time); 39 | void set_clock (unsigned long timestamp, int timezone = 0); 40 | uint16_t get_years (); 41 | int get_months (); 42 | int date_already_set (); 43 | int get_days (); 44 | int get_day_of_week (); 45 | uint32_t get_valid_entry (); 46 | int calculate_day_of_week (uint16_t _year, int _month, int _day); 47 | int set_hours (int _hour); 48 | int set_minutes (int minute); 49 | int set_seconds (int second); 50 | int set_days (int day); 51 | int set_months (int month); 52 | int set_years (uint16_t year); 53 | void set_alarmtime (int hour, int minute, int second); 54 | void set_alarmdate (int month, int day); 55 | 56 | void attachalarm (void (*)(void)); 57 | uint32_t unixtime (int timezone = 0); 58 | void get_time (int *hour, int *minute, int *second); 59 | void get_date (int *day_of_week, int *day, int *month, int *year); 60 | //int switch_years (uint16_t year); 61 | int summertime (); 62 | int UTC_abbreviation(); 63 | void dst_followup(); 64 | 65 | private: 66 | // int _source; 67 | int _hour; 68 | int _minute; 69 | int _second; 70 | int _day; 71 | int _month; 72 | uint16_t _year; 73 | int _day_of_week; 74 | int timezoneadjustment (int timezone); 75 | // int _abbreviation; 76 | uint32_t current_time (); 77 | uint32_t current_date (); 78 | uint32_t _current_time; 79 | uint32_t _current_date; 80 | uint32_t change_time (uint32_t _now); 81 | uint32_t change_date (uint32_t _now); 82 | uint32_t _now; 83 | uint32_t _changed; 84 | bool dst_winter_done = false; 85 | }; 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /change.log: -------------------------------------------------------------------------------- 1 | 2015/25/03 Due RTC Library v2.1 2 | added 3 | - New rewritten function for the German Summertime with example rtc_clock.dst_followup 4 | Due_RTC_Simple_Sample_german_summertime 5 | 6 | fixed 7 | - Minor cosmetic changes inside the examples 8 | 9 | 2015/25/03 Due RTC Library v2.0 10 | added 11 | - Function rtc_clock.set_clock() 12 | now supports set time from unix timestamp over udp 13 | - Sketch Due_RTC_Simple_Sample_NTP_ETHERNET 14 | for rtc_clock.set_clock() from timeserver over ethernet 15 | - Sketch Due_RTC_Simple_Sample_NTP_WIFI 16 | for rtc_clock.set_clock() from timeserver over wifi 17 | - Some really needed and long forgotten comments 18 | 19 | modify 20 | - Function switch_years rewritten 21 | - Split functions to that adjustment for timezone become an seperate function 22 | - Minor improvements and cosmetic changes 23 | 24 | fixed 25 | - Deleted unused field inside the library.properties file 26 | - Corrections on formel to calculate German summer- and wintertime 27 | 28 | 2015/19/03 Due RTC Library v1.9 29 | modify 30 | - Updated to new library style for Arduino IDE 1.5.6 and after (1.5.x library format rev. 2). 31 | based on https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification 32 | 33 | 2013/01/04 Due RTC Library v1.8 34 | added 35 | - Function rtc_clock.set_clock() 36 | function to set Time and Date from compliertime -/date in 1 line 37 | 38 | fixed 39 | - Bug in rtc_clock.unixtime() 40 | - Bug in rtc_clock.summertime() 41 | 42 | 2013/04/03 Due RTC Library v1.7 43 | added 44 | - Function rtc_clock.date_already_set() 45 | function to proof if date is already set 46 | - Sketch Due_RTC_Simple_test_of_date 47 | for rtc_clock.date_already_set() 48 | 49 | 2013/04/03 Due RTC Library v1.6 50 | added 51 | - Function rtc_clock.timing() 52 | function to test if time and date set in summer or not musst be done in the inital 53 | part when the clock is setup works in connection with rtc_clock.summertime() so 54 | thats if the clock is setup in the range of summertime the function 55 | rtc_clock.summertime() makes the right correct between the time changes 56 | for Germany usefull 57 | - Sketch Due_RTC_Simple_german_timing_summertime_sample 58 | for rtc_clock.timing() & rtc_clock.summertime() 59 | 60 | 2013/04/03 Due RTC Library v1.5 61 | modify 62 | - Sketch Due_RTC_Simple_Germay_Summertime 63 | some changes in the Sketch for an better Output on the Serialmonitor 64 | 65 | 2013/04/03 Due RTC Library v1.4 66 | added 67 | - Function rtc_clock.summertime() 68 | function to show if summertime or not returns 1 for summertime (for Germany only) 69 | - Sketch Due_RTC_Simple_Germay_Summertime 70 | for rtc_clock.summertime() 71 | - Function rtc_clock.switch_years() 72 | function returns 1 if year is an switch year 73 | 74 | modify 75 | - Function rtc_clock.unixtime() 76 | add support for timezone Germany now summer- wintertime automatic supported 77 | 78 | 2013/02/03 Due RTC Library v1.3 79 | modify 80 | - Function rtc_clock.unixtime() 81 | add support for timezones to change automatic the unixtime to the right value 82 | - Sketch Due_RTC_Simple_Unixtime_timezone 83 | for rtc_clock.unixtime() 84 | 85 | 2013/01/03 Due RTC Library v1.2 86 | added 87 | - Function rtc_clock.get_time() 88 | to get Time in one operation 89 | - Function rtc_clock.get_date() 90 | to get Date in one operation 91 | - Sketch Due_RTC_Simple_Sample_oneline_time_and_date 92 | for rtc_clock.get_time() & rtc_clock.get_date() 93 | - Changelog and versioning 94 | to get some overview for me and users 95 | 96 | modify 97 | - Function rtc_clock.unixtime() 98 | some changes in the codelines 99 | - Sketch Due_RTC_Simple_Unixtime_Compilertime 100 | some cosmetic changes in this Sketch 101 | 102 | fixed 103 | - Bug in rtc_clock.set_alarmdate function 104 | wrong value name 105 | 106 | 2013/28/02 Due RTC Library v1.1 107 | added 108 | - Function rtc_clock.unixtime() 109 | for unixtime support 110 | - Sample Due_RTC_Simple_Unixtime_Compilertime 111 | for unixtime and compilertime 112 | 113 | modify 114 | - Function rtc_clock.set_time() 115 | to support compilertime with the value __TIME__ 116 | - Function rtc_clock.set_date() 117 | to support compilertime with the value __DATE__ 118 | - Syntax Coloring 119 | set rtc_clock to KEYWORD3 now rtc_clock printed bold 120 | 121 | 2012/07/12 Due RTC Library v1.0 122 | Initial Release -------------------------------------------------------------------------------- /examples/Due_RTC_Simple_Sample_NTP_ETHERNET/Due_RTC_Simple_Sample_NTP_ETHERNET.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // Enter a MAC address for your controller below. 7 | // Newer Ethernet shields have a MAC address printed on a sticker on the shield 8 | byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; 9 | 10 | unsigned int localPort = 2390; // local port to listen for UDP packets 11 | 12 | IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server 13 | 14 | const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message 15 | 16 | byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 17 | 18 | // A UDP instance to let us send and receive packets over UDP 19 | EthernetUDP Udp; 20 | 21 | // Select the Slowclock source 22 | //RTC_clock rtc_clock(RC); 23 | RTC_clock rtc_clock(XTAL); 24 | 25 | char* daynames[]={"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; 26 | 27 | // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: 28 | const unsigned long seventyYears = 2208988800UL; 29 | unsigned long actual_unixtime; 30 | 31 | void setup() { 32 | Serial.begin(9600); 33 | while (!Serial) { 34 | ; // wait for serial port to connect. Needed for Leonardo only 35 | } 36 | 37 | // start Ethernet and UDP 38 | if (Ethernet.begin(mac) == 0) { 39 | Serial.println("Failed to configure Ethernet using DHCP"); 40 | // no point in carrying on, so do nothing forever more: 41 | while (1) { 42 | Serial.println("Failed to configure Ethernet using DHCP"); 43 | delay(10000); 44 | } 45 | } 46 | 47 | Serial.println("Connected to ethernet"); 48 | printEthernetStatus(); 49 | 50 | Serial.println("Starting connection to server..."); 51 | Udp.begin(localPort); 52 | recieveNTP(); 53 | 54 | rtc_clock.init(); 55 | rtc_clock.set_clock(actual_unixtime, Germany); 56 | } 57 | 58 | void loop() { 59 | Serial.print("At the third stroke, it will be "); 60 | digitprint(rtc_clock.get_hours(), 2); 61 | Serial.print(":"); 62 | digitprint(rtc_clock.get_minutes(), 2); 63 | Serial.print(":"); 64 | digitprint(rtc_clock.get_seconds(), 2); 65 | Serial.print(" "); 66 | Serial.print(daynames[rtc_clock.get_day_of_week()-1]); 67 | Serial.print(": "); 68 | digitprint(rtc_clock.get_days(), 2); 69 | Serial.print("."); 70 | digitprint(rtc_clock.get_months(), 2); 71 | Serial.print("."); 72 | Serial.println(rtc_clock.get_years()); 73 | Serial.println(""); 74 | } 75 | 76 | void recieveNTP(){ 77 | sendNTPpacket(timeServer); // send an NTP packet to a time server 78 | // wait to see if a reply is available 79 | delay(1000); 80 | Serial.println( Udp.parsePacket() ); 81 | if ( Udp.parsePacket() ) { 82 | Serial.println("packet received"); 83 | 84 | // We've received a packet, read the data from it 85 | Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer 86 | 87 | // the timestamp starts at byte 40 of the received packet and is four bytes, 88 | // or two words, long. First, extract the two words: 89 | unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); 90 | unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 91 | 92 | // combine the four bytes (two words) into a long integer 93 | // this is NTP time (seconds since Jan 1 1900): 94 | unsigned long secsSince1900 = highWord << 16 | lowWord; 95 | actual_unixtime = secsSince1900 - seventyYears; 96 | } 97 | } 98 | 99 | // send an NTP request to the time server at the given address 100 | unsigned long sendNTPpacket(IPAddress& address){ 101 | // set all bytes in the buffer to 0 102 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 103 | // Initialize values needed to form NTP request 104 | // (see URL above for details on the packets) 105 | packetBuffer[0] = 0b11100011; // LI, Version, Mode 106 | packetBuffer[1] = 0; // Stratum, or type of clock 107 | packetBuffer[2] = 6; // Polling Interval 108 | packetBuffer[3] = 0xEC; // Peer Clock Precision 109 | // 8 bytes of zero for Root Delay & Root Dispersion 110 | packetBuffer[12] = 49; 111 | packetBuffer[13] = 0x4E; 112 | packetBuffer[14] = 49; 113 | packetBuffer[15] = 52; 114 | 115 | // all NTP fields have been given values, now 116 | // you can send a packet requesting a timestamp: 117 | Udp.beginPacket(address, 123); //NTP requests are to port 123 118 | Udp.write(packetBuffer, NTP_PACKET_SIZE); 119 | Udp.endPacket(); 120 | } 121 | 122 | void digitprint(int value, int lenght){ 123 | for (int i = 0; i < (lenght - numdigits(value)); i++){ 124 | Serial.print("0"); 125 | } 126 | Serial.print(value); 127 | } 128 | 129 | int numdigits(int i){ 130 | int digits; 131 | if (i < 10) 132 | digits = 1; 133 | else 134 | digits = (int)(log10((double)i)) + 1; 135 | return digits; 136 | } 137 | 138 | void printEthernetStatus(){ 139 | // print your local IP address: 140 | Serial.print("My IP address: "); 141 | for (byte thisByte = 0; thisByte < 4; thisByte++) { 142 | // print the value of each byte of the IP address: 143 | Serial.print(Ethernet.localIP()[thisByte], DEC); 144 | Serial.print("."); 145 | } 146 | Serial.println(); 147 | } -------------------------------------------------------------------------------- /examples/Due_RTC_Simple_Sample_NTP_WIFI/Due_RTC_Simple_Sample_NTP_WIFI.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int status = WL_IDLE_STATUS; 7 | char ssid[] = "mynetwork"; // your network SSID (name) 8 | char pass[] = "mypassword"; // your network password 9 | int keyIndex = 0; // your network key Index number (needed only for WEP) 10 | 11 | unsigned int localPort = 2390; // local port to listen for UDP packets 12 | 13 | IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server 14 | 15 | const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message 16 | 17 | byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 18 | 19 | // A UDP instance to let us send and receive packets over UDP 20 | WiFiUDP Udp; 21 | 22 | // Select the Slowclock source 23 | //RTC_clock rtc_clock(RC); 24 | RTC_clock rtc_clock(XTAL); 25 | 26 | char* daynames[]={"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; 27 | 28 | // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: 29 | const unsigned long seventyYears = 2208988800UL; 30 | unsigned long actual_unixtime; 31 | 32 | void setup() { 33 | Serial.begin(9600); 34 | while (!Serial) { 35 | ; // wait for serial port to connect. Needed for Leonardo only 36 | } 37 | 38 | String fv = WiFi.firmwareVersion(); 39 | if ( fv != "1.1.0" ) 40 | Serial.println("Please upgrade the firmware"); 41 | 42 | // attempt to connect to Wifi network: 43 | while ( status != WL_CONNECTED) { 44 | Serial.print("Attempting to connect to SSID: "); 45 | Serial.println(ssid); 46 | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: 47 | status = WiFi.begin(ssid, pass); 48 | 49 | // wait 10 seconds for connection: 50 | delay(10000); 51 | } 52 | 53 | Serial.println("Connected to wifi"); 54 | printWifiStatus(); 55 | 56 | Serial.println("Starting connection to server..."); 57 | Udp.begin(localPort); 58 | recieveNTP(); 59 | 60 | rtc_clock.init(); 61 | rtc_clock.set_clock(actual_unixtime, Germany); 62 | } 63 | 64 | void loop() { 65 | Serial.print("At the third stroke, it will be "); 66 | digitprint(rtc_clock.get_hours(), 2); 67 | Serial.print(":"); 68 | digitprint(rtc_clock.get_minutes(), 2); 69 | Serial.print(":"); 70 | digitprint(rtc_clock.get_seconds(), 2); 71 | Serial.print(" "); 72 | Serial.print(daynames[rtc_clock.get_day_of_week()-1]); 73 | Serial.print(": "); 74 | digitprint(rtc_clock.get_days(), 2); 75 | Serial.print("."); 76 | digitprint(rtc_clock.get_months(), 2); 77 | Serial.print("."); 78 | Serial.println(rtc_clock.get_years()); 79 | Serial.println(""); 80 | } 81 | 82 | void recieveNTP(){ 83 | sendNTPpacket(timeServer); // send an NTP packet to a time server 84 | // wait to see if a reply is available 85 | delay(1000); 86 | Serial.println( Udp.parsePacket() ); 87 | if ( Udp.parsePacket() ) { 88 | Serial.println("packet received"); 89 | 90 | // We've received a packet, read the data from it 91 | Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer 92 | 93 | // the timestamp starts at byte 40 of the received packet and is four bytes, 94 | // or two words, long. First, extract the two words: 95 | 96 | unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); 97 | unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 98 | 99 | // combine the four bytes (two words) into a long integer 100 | // this is NTP time (seconds since Jan 1 1900): 101 | unsigned long secsSince1900 = highWord << 16 | lowWord; 102 | actual_unixtime = secsSince1900 - seventyYears; 103 | } 104 | } 105 | 106 | // send an NTP request to the time server at the given address 107 | unsigned long sendNTPpacket(IPAddress& address){ 108 | // set all bytes in the buffer to 0 109 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 110 | // Initialize values needed to form NTP request 111 | // (see URL above for details on the packets) 112 | packetBuffer[0] = 0b11100011; // LI, Version, Mode 113 | packetBuffer[1] = 0; // Stratum, or type of clock 114 | packetBuffer[2] = 6; // Polling Interval 115 | packetBuffer[3] = 0xEC; // Peer Clock Precision 116 | // 8 bytes of zero for Root Delay & Root Dispersion 117 | packetBuffer[12] = 49; 118 | packetBuffer[13] = 0x4E; 119 | packetBuffer[14] = 49; 120 | packetBuffer[15] = 52; 121 | 122 | // all NTP fields have been given values, now 123 | // you can send a packet requesting a timestamp: 124 | Udp.beginPacket(address, 123); //NTP requests are to port 123 125 | Udp.write(packetBuffer, NTP_PACKET_SIZE); 126 | Udp.endPacket(); 127 | } 128 | 129 | void digitprint(int value, int lenght){ 130 | for (int i = 0; i < (lenght - numdigits(value)); i++){ 131 | Serial.print("0"); 132 | } 133 | Serial.print(value); 134 | } 135 | 136 | int numdigits(int i){ 137 | int digits; 138 | if (i < 10) 139 | digits = 1; 140 | else 141 | digits = (int)(log10((double)i)) + 1; 142 | return digits; 143 | } 144 | 145 | void printWifiStatus() { 146 | // print the SSID of the network you're attached to: 147 | Serial.print("SSID: "); 148 | Serial.println(WiFi.SSID()); 149 | 150 | // print your WiFi shield's IP address: 151 | IPAddress ip = WiFi.localIP(); 152 | Serial.print("IP Address: "); 153 | Serial.println(ip); 154 | 155 | // print the received signal strength: 156 | long rssi = WiFi.RSSI(); 157 | Serial.print("signal strength (RSSI):"); 158 | Serial.print(rssi); 159 | Serial.println(" dBm"); 160 | } -------------------------------------------------------------------------------- /src/rtc_clock.cpp: -------------------------------------------------------------------------------- 1 | #include "rtc_clock.h" 2 | #include 3 | #include 4 | #include 5 | #include "Arduino.h" 6 | 7 | uint8_t daysInMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 8 | uint8_t meztime; 9 | 10 | // Based on https://github.com/PaulStoffregen/Time.cpp 11 | // for 4 digit years 12 | #define switch_years(Y) ( !(Y % 4) && ( (Y % 100) || !(Y % 400) ) ) 13 | 14 | RTC_clock::RTC_clock (int source) 15 | { 16 | // _source = source; 17 | if (source) { 18 | pmc_switch_sclk_to_32kxtal(0); 19 | 20 | while (!pmc_osc_is_ready_32kxtal()); 21 | } 22 | } 23 | 24 | void RTC_clock::init () 25 | { 26 | RTC_SetHourMode(RTC, 0); 27 | 28 | NVIC_DisableIRQ(RTC_IRQn); 29 | NVIC_ClearPendingIRQ(RTC_IRQn); 30 | NVIC_SetPriority(RTC_IRQn, 0); 31 | // NVIC_EnableIRQ(RTC_IRQn); 32 | // RTC_EnableIt(RTC, RTC_IER_SECEN | RTC_IER_ALREN); 33 | // RTC_EnableIt(RTC, RTC_IER_SECEN); 34 | } 35 | 36 | void RTC_clock::set_time (int hour, int minute, int second) 37 | { 38 | _hour = hour; 39 | _minute = minute; 40 | _second = second; 41 | 42 | RTC_SetTime (RTC, _hour, _minute, _second); 43 | } 44 | 45 | /* 46 | // Based on https://github.com/adafruit/RTClib/blob/master/RTClib.cpp 47 | int conv2d(char* p) 48 | { 49 | int v = 0; 50 | if ('0' <= *p && *p <= '9') 51 | v = *p - '0'; 52 | 53 | return 10 * v + *++p - '0'; 54 | } 55 | */ 56 | 57 | // Based on http://www.geeksforgeeks.org/write-your-own-atoi/ 58 | // Better version converts until none number shows up 59 | int conv2d(char* p) 60 | { 61 | int v = 0; // Initialize result 62 | 63 | // Iterate through all characters of input string and update result 64 | for (int i = 0; p[i] != '\0'; ++i) { 65 | if ('0' <= p[i] && p[i] <= '9') 66 | v = v*10 + p[i] - '0'; 67 | else 68 | break; 69 | } 70 | // return result. 71 | return v; 72 | } 73 | 74 | void RTC_clock::set_time (char* time) 75 | { 76 | _hour = conv2d(time); 77 | _minute = conv2d(time + 3); 78 | _second = conv2d(time + 6); 79 | 80 | RTC_SetTime (RTC, _hour, _minute, _second); 81 | } 82 | 83 | // Based on https://github.com/PaulStoffregen/Time.cpp 84 | void RTC_clock::set_clock (unsigned long timestamp, int timezone) 85 | { 86 | unsigned int monthLength; 87 | unsigned long time, days; 88 | 89 | // Sunday, 01-Jan-40 00:00:00 UTC 70 years after the beginning of the unix timestamp so 90 | // if the timestamp bigger than this the "offset" will automatic removed 91 | if (timestamp >= 2208988800UL) 92 | time -= 2208988800UL; 93 | 94 | time = timestamp + (unsigned long)timezoneadjustment(timezone); 95 | _second = time % 60; 96 | time /= 60; // now it is minutes 97 | _minute = time % 60; 98 | time /= 60; // now it is hours 99 | _hour = time % 24; 100 | time /= 24; // now it is days 101 | 102 | _year = 1970; 103 | days = 0; 104 | while(( days += (365 + switch_years(_year)) ) <= time) 105 | _year++; 106 | 107 | days -= (365 + switch_years(_year)); 108 | 109 | time -= days; // now it is days in this year, starting at 0 110 | 111 | days = 0; 112 | for (_month = 0; _month < 12; _month++) { 113 | if (_month == 1) // february 114 | monthLength = daysInMonth[_month] + switch_years(_year); 115 | else 116 | monthLength = daysInMonth[_month]; 117 | 118 | if (time >= monthLength) 119 | time -= monthLength; 120 | else 121 | break; 122 | } 123 | 124 | _month++; // jan is month 1 125 | _day = (int)time + 1; // day of month 126 | _day_of_week = calculate_day_of_week (_year, _month, _day); 127 | 128 | RTC_SetTime (RTC, _hour, _minute, _second); 129 | RTC_SetDate (RTC, (uint16_t)_year, (uint8_t)_month, (uint8_t)_day, (uint8_t)_day_of_week); 130 | } 131 | 132 | uint32_t RTC_clock::current_time () 133 | { 134 | uint32_t dwTime; 135 | 136 | /* Get current RTC time */ 137 | dwTime = RTC->RTC_TIMR ; 138 | while ( dwTime != RTC->RTC_TIMR ) { 139 | dwTime = RTC->RTC_TIMR ; 140 | } 141 | 142 | return (dwTime); 143 | } 144 | 145 | void RTC_clock::get_time (int *hour, int *minute, int *second) 146 | { 147 | RTC_GetTime(RTC, (uint8_t*)hour, (uint8_t*)minute, (uint8_t*)second); 148 | } 149 | 150 | int RTC_clock::get_hours () 151 | { 152 | _current_time = current_time(); 153 | 154 | return (((_current_time & 0x00300000) >> 20) * 10 + ((_current_time & 0x000F0000) >> 16)); 155 | // return RTC_TIMR_HOUR ( current_time() ); 156 | } 157 | 158 | int RTC_clock::get_minutes () 159 | { 160 | _current_time = current_time(); 161 | 162 | return (((_current_time & 0x00007000) >> 12) * 10 + ((_current_time & 0x00000F00) >> 8)); 163 | // return RTC_TIMR_MIN ( current_time() ); 164 | } 165 | 166 | int RTC_clock::get_seconds () 167 | { 168 | _current_time = current_time(); 169 | 170 | return (((_current_time & 0x00000070) >> 4) * 10 + ((_current_time & 0x0000000F))); 171 | // return RTC_TIMR_SEC ( current_time() ); 172 | } 173 | 174 | /** 175 | * \brief Calculate day_of_week from year, month, day. 176 | * Based on SAM3X rtc_example.c from Atmel Software Framework (Real-Time Clock (RTC) example for SAM) also available 177 | * https://github.com/eewiki/asf/blob/master/sam/drivers/rtc/example/rtc_example.c 178 | */ 179 | int RTC_clock::calculate_day_of_week (uint16_t _year, int _month, int _day) 180 | { 181 | int _week; 182 | 183 | if (_month == 1 || _month == 2) { 184 | _month += 12; 185 | --_year; 186 | } 187 | 188 | _week = (_day + 2 * _month + 3 * (_month + 1) / 5 + _year + _year / 4 - _year / 100 + _year / 400) % 7; 189 | 190 | ++_week; 191 | 192 | return _week; 193 | } 194 | 195 | void RTC_clock::set_date (int day, int month, uint16_t year) 196 | { 197 | _day = day; 198 | _month = month; 199 | _year = year; 200 | _day_of_week = calculate_day_of_week(_year, _month, _day); 201 | 202 | RTC_SetDate (RTC, (uint16_t)_year, (uint8_t)_month, (uint8_t)_day, (uint8_t)_day_of_week); 203 | } 204 | 205 | // Based on https://github.com/adafruit/RTClib/blob/master/RTClib.cpp 206 | void RTC_clock::set_date (char* date) 207 | { 208 | _day = conv2d(date + 4); 209 | 210 | //Month 211 | switch (date[0]) { 212 | case 'J': _month = date[1] == 'a' ? 1 : (_month = date[2] == 'n') ? 6 : 7; break; 213 | case 'F': _month = 2; break; 214 | case 'A': _month = date[2] == 'r' ? 4 : 8; break; 215 | case 'M': _month = date[2] == 'r' ? 3 : 5; break; 216 | case 'S': _month = 9; break; 217 | case 'O': _month = 10; break; 218 | case 'N': _month = 11; break; 219 | case 'D': _month = 12; break; 220 | } 221 | 222 | _year = conv2d(date + 9); 223 | _day_of_week = calculate_day_of_week(_year, _month, _day); 224 | 225 | RTC_SetDate (RTC, (uint16_t)_year, (uint8_t)_month, (uint8_t)_day, (uint8_t)_day_of_week); 226 | } 227 | 228 | uint32_t RTC_clock::current_date () 229 | { 230 | uint32_t dwTime; 231 | 232 | /* Get current RTC date */ 233 | dwTime = RTC->RTC_CALR ; 234 | while ( dwTime != RTC->RTC_CALR ) { 235 | dwTime = RTC->RTC_CALR ; 236 | } 237 | 238 | return (dwTime); 239 | } 240 | 241 | int RTC_clock::date_already_set () 242 | { 243 | uint32_t dateregister; 244 | 245 | /* Get current RTC date */ 246 | dateregister = current_date (); 247 | 248 | if ( RESET_VALUE != dateregister ) { 249 | return 1; 250 | } else { 251 | return 0; 252 | } 253 | } 254 | 255 | void RTC_clock::get_date (int *day_of_week, int *day, int *month, int *year) 256 | { 257 | RTC_GetDate(RTC, (uint16_t*)year, (uint8_t*)month, (uint8_t*)day, (uint8_t*)day_of_week); 258 | } 259 | 260 | uint16_t RTC_clock::get_years () 261 | { 262 | _current_date = current_date(); 263 | 264 | return ((((_current_date >> 4) & 0x7) * 1000) + ((_current_date & 0xF) * 100) 265 | + (((_current_date >> 12) & 0xF) * 10) + ((_current_date >> 8) & 0xF)); 266 | // return ( RTC_CALR_CENT ( current_date() ) * 100 + RTC_CALR_YEAR ( current_date() ) ); 267 | } 268 | 269 | int RTC_clock::get_months () 270 | { 271 | _current_date = current_date(); 272 | 273 | return ((((_current_date >> 20) & 1) * 10) + ((_current_date >> 16) & 0xF)); 274 | // return RTC_CALR_MONTH ( current_date() ); 275 | } 276 | 277 | int RTC_clock::get_days () 278 | { 279 | _current_date = current_date(); 280 | 281 | return ((((_current_date >> 28) & 0x3) * 10) + ((_current_date >> 24) & 0xF)); 282 | // return RTC_CALR_DATE ( current_date() ); 283 | } 284 | 285 | int RTC_clock::get_day_of_week () 286 | { 287 | _current_date = current_date(); 288 | 289 | return (((_current_date >> 21) & 0x7)); 290 | // return RTC_CALR_DAY ( current_date() ); 291 | } 292 | 293 | uint32_t RTC_clock::get_valid_entry () 294 | { 295 | return (RTC->RTC_VER); 296 | } 297 | 298 | int RTC_clock::set_hours (int hour) 299 | { 300 | _hour = hour; 301 | uint32_t _current_time = current_time(); 302 | uint32_t _changed; 303 | 304 | _changed = ((_hour%10) | ((_hour/10)<<4))<<16; 305 | 306 | _current_time = (_current_time & 0xFFC0FFFF) ^ _changed; 307 | 308 | return change_time(_current_time); 309 | } 310 | 311 | int RTC_clock::set_minutes (int minute) 312 | { 313 | _minute = minute; 314 | uint32_t _current_time = current_time(); 315 | uint32_t _changed; 316 | 317 | _changed = ((_minute%10) | ((_minute/10)<<4))<<8; 318 | 319 | _current_time = (_current_time & 0xFFFF80FF) ^ _changed; 320 | 321 | return change_time(_current_time); 322 | } 323 | 324 | int RTC_clock::set_seconds (int second) 325 | { 326 | _second = second; 327 | uint32_t _current_time = current_time(); 328 | uint32_t _changed; 329 | 330 | _changed = ((_second%10) | ((_second/10)<<4)); 331 | 332 | _current_time = (_current_time & 0xFFFFFF80) ^ _changed; 333 | 334 | return change_time(_current_time); 335 | } 336 | 337 | uint32_t RTC_clock::change_time (uint32_t now) 338 | { 339 | _now = now; 340 | 341 | RTC->RTC_CR |= RTC_CR_UPDTIM ; 342 | while ((RTC->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD); 343 | 344 | RTC->RTC_SCCR = RTC_SCCR_ACKCLR; 345 | RTC->RTC_TIMR = _now; 346 | RTC->RTC_CR &= (uint32_t)(~RTC_CR_UPDTIM); 347 | RTC->RTC_SCCR |= RTC_SCCR_SECCLR; 348 | 349 | return (int)(RTC->RTC_VER & RTC_VER_NVTIM); 350 | } 351 | 352 | int RTC_clock::set_days (int day) 353 | { 354 | _day = day; 355 | uint32_t _current_date = current_date(); 356 | uint32_t _changed; 357 | 358 | _day_of_week = calculate_day_of_week(get_years(), get_months(), _day); 359 | _day_of_week = ((_day_of_week%10) | (_day_of_week/10)<<4)<<21; 360 | 361 | _changed = ((_day%10) | (_day/10)<<4)<<24; 362 | 363 | _current_date = (_current_date & (0xC0FFFFFF & 0xFF1FFFFF) ) ^ ( _changed | _day_of_week ); 364 | 365 | return change_date(_current_date); 366 | } 367 | 368 | int RTC_clock::set_months (int month) 369 | { 370 | _month = month; 371 | uint32_t _current_date = current_date(); 372 | uint32_t _changed; 373 | 374 | _day_of_week = calculate_day_of_week(get_years(), _month, get_days()); 375 | _day_of_week = ((_day_of_week%10) | (_day_of_week/10)<<4)<<21; 376 | 377 | _changed = ((_month%10) | (_month/10)<<4)<<16; 378 | 379 | _current_date = (_current_date & (0xFFE0FFFF & 0xFF1FFFFF) ) ^ ( _changed | _day_of_week ); 380 | 381 | return change_date(_current_date); 382 | } 383 | 384 | int RTC_clock::set_years (uint16_t year) 385 | { 386 | _year = year; 387 | uint32_t _current_date = current_date(); 388 | uint32_t _changed; 389 | 390 | _day_of_week = calculate_day_of_week(_year, get_months(), get_days()); 391 | _day_of_week = ((_day_of_week%10) | (_day_of_week/10)<<4)<<21; 392 | 393 | _changed = (((_year/100)%10) | ((_year/1000)<<4)) | ((_year%10) | (((_year/10)%10))<<4)<<8; 394 | 395 | _current_date = (_current_date & (0xFFFF0080 & 0xFF1FFFFF) ) ^ ( _changed | _day_of_week ); 396 | 397 | return change_date(_current_date); 398 | } 399 | 400 | uint32_t RTC_clock::change_date (uint32_t now) 401 | { 402 | _now = now; 403 | 404 | RTC->RTC_CR |= RTC_CR_UPDCAL; 405 | while ((RTC->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD); 406 | 407 | RTC->RTC_SCCR = RTC_SCCR_ACKCLR; 408 | RTC->RTC_CALR = _now; 409 | RTC->RTC_CR &= (uint32_t)(~RTC_CR_UPDCAL); 410 | RTC->RTC_SCCR |= RTC_SCCR_SECCLR; 411 | 412 | return (int)(RTC->RTC_VER & RTC_VER_NVCAL); 413 | } 414 | 415 | // Based on https://github.com/adafruit/RTClib/blob/master/RTClib.cpp 416 | void RTC_clock::set_clock (char* date, char* time) 417 | { 418 | set_date(date); 419 | set_time(time); 420 | } 421 | 422 | int RTC_clock::UTC_abbreviation () 423 | { 424 | if ( summertime () ) 425 | return CEST; 426 | else 427 | return CET; 428 | } 429 | 430 | void (*useralarmFunc)(void); 431 | 432 | void RTC_clock::attachalarm(void (*userFunction)(void)) 433 | { 434 | useralarmFunc = userFunction; 435 | } 436 | 437 | void RTC_Handler(void) 438 | { 439 | uint32_t status = RTC->RTC_SR; 440 | 441 | /* Time or date alarm */ 442 | if ((status & RTC_SR_ALARM) == RTC_SR_ALARM) { 443 | /* Disable RTC interrupt */ 444 | RTC_DisableIt(RTC, RTC_IDR_ALRDIS); 445 | 446 | /* Execute function */ 447 | useralarmFunc(); 448 | 449 | /* Clear notification */ 450 | RTC_ClearSCCR(RTC, RTC_SCCR_ALRCLR); 451 | RTC_EnableIt(RTC, RTC_IER_ALREN); 452 | } 453 | } 454 | 455 | void RTC_clock::set_alarmtime (int hour, int minute, int second) 456 | { 457 | uint8_t _hour = hour; 458 | uint8_t _minute = minute; 459 | uint8_t _second = second; 460 | 461 | RTC_EnableIt(RTC, RTC_IER_ALREN); 462 | RTC_SetTimeAlarm(RTC, &_hour, &_minute, &_second); 463 | NVIC_EnableIRQ(RTC_IRQn); 464 | } 465 | 466 | void RTC_clock::set_alarmdate (int month, int day) 467 | { 468 | uint8_t _month = month; 469 | uint8_t _day = day; 470 | 471 | RTC_EnableIt(RTC, RTC_IER_ALREN); 472 | RTC_SetDateAlarm(RTC, &_month, &_day); 473 | NVIC_EnableIRQ(RTC_IRQn); 474 | } 475 | 476 | uint32_t RTC_clock::unixtime(int timezone) 477 | { 478 | uint32_t _ticks; 479 | uint16_t _days; 480 | _current_date = current_date(); 481 | _current_time = current_time(); 482 | 483 | _second = (((_current_time & 0x00000070) >> 4) * 10 + ((_current_time & 0x0000000F))); 484 | _minute = (((_current_time & 0x00007000) >> 12) * 10 + ((_current_time & 0x00000F00) >> 8)); 485 | _hour = (((_current_time & 0x00300000) >> 20) * 10 + ((_current_time & 0x000F0000) >> 16)); 486 | 487 | _day = ((((_current_date >> 28) & 0x3) * 10) + ((_current_date >> 24) & 0xF)); 488 | //_day_of_week = ((_current_date >> 21) & 0x7); 489 | _month = ((((_current_date >> 20) & 1) * 10) + ((_current_date >> 16) & 0xF)); 490 | 491 | //_year 4 digits 492 | _year = ((((_current_date >> 4) & 0x7) * 1000) + ((_current_date & 0xF) * 100) 493 | + (((_current_date >> 12) & 0xF) * 10) + ((_current_date >> 8) & 0xF)); 494 | 495 | //_year 2 digits 496 | //_year = (((_current_date >> 12) & 0xF) * 10) + ((_current_date >> 8) & 0xF); 497 | 498 | // Based on https://github.com/punkiller/workspace/blob/master/string2UnixTimeStamp.cpp 499 | // days of the years between start of unixtime and now 500 | _days = 365 * (_year - 1970); 501 | 502 | // add days from switch years in between except year from date 503 | for( int i = 1970; i < _year ; i++){ 504 | if( switch_years (i) ) { 505 | _days++; 506 | } 507 | } 508 | 509 | // Based on https://github.com/adafruit/RTClib/blob/master/RTClib.cpp 510 | for (int i = 1; i < _month; ++i) 511 | _days += daysInMonth[i - 1]; 512 | 513 | if ( _month > 2 && switch_years (_year) ) 514 | ++_days; 515 | 516 | _days += _day - 1; 517 | 518 | _ticks = ((_days * 24 + _hour) * 60 + _minute) * 60 + _second; 519 | 520 | _ticks = _ticks - (int)timezoneadjustment(timezone); 521 | 522 | return _ticks; 523 | } 524 | 525 | int RTC_clock::timezoneadjustment (int timezone) 526 | { 527 | float adjustment; 528 | 529 | if (timezone == Germany) 530 | timezone = 1 + summertime(); 531 | 532 | switch (timezone) { 533 | case -12: 534 | adjustment = -12 * SECONDS_PER_HOUR; break; 535 | case -11: 536 | adjustment = -11 * SECONDS_PER_HOUR; break; 537 | case -10: 538 | adjustment = -10 * SECONDS_PER_HOUR; break; 539 | case -930: 540 | adjustment = -9.5 * SECONDS_PER_HOUR; break; 541 | case -9: 542 | adjustment = -9 * SECONDS_PER_HOUR; break; 543 | case -8: 544 | adjustment = -8 * SECONDS_PER_HOUR; break; 545 | case -7: 546 | adjustment = -7 * SECONDS_PER_HOUR; break; 547 | case -6: 548 | adjustment = -6 * SECONDS_PER_HOUR; break; 549 | case -5: 550 | adjustment = -5 * SECONDS_PER_HOUR; break; 551 | case -4: 552 | adjustment = -4 * SECONDS_PER_HOUR; break; 553 | case -330: 554 | adjustment = -3.5 * SECONDS_PER_HOUR; break; 555 | case -3: 556 | adjustment = -3 * SECONDS_PER_HOUR; break; 557 | case -2: 558 | adjustment = -2 * SECONDS_PER_HOUR; break; 559 | case -1: 560 | adjustment = -1 * SECONDS_PER_HOUR; break; 561 | case 0: 562 | default: 563 | adjustment = 0; break; 564 | case 1: 565 | adjustment = 1 * SECONDS_PER_HOUR; break; 566 | case 2: 567 | adjustment = 2 * SECONDS_PER_HOUR; break; 568 | case 3: 569 | adjustment = 3 * SECONDS_PER_HOUR; break; 570 | case 330: 571 | adjustment = 3.5 * SECONDS_PER_HOUR; break; 572 | case 4: 573 | adjustment = 4 * SECONDS_PER_HOUR; break; 574 | case 430: 575 | adjustment = 4.5 * SECONDS_PER_HOUR; break; 576 | case 5: 577 | adjustment = 5 * SECONDS_PER_HOUR; break; 578 | case 530: 579 | adjustment = 5.5 * SECONDS_PER_HOUR; break; 580 | case 545: 581 | adjustment = 5.75 * SECONDS_PER_HOUR; break; 582 | case 6: 583 | adjustment = 6 * SECONDS_PER_HOUR; break; 584 | case 630: 585 | adjustment = 6.5 * SECONDS_PER_HOUR; break; 586 | case 7: 587 | adjustment = 7 * SECONDS_PER_HOUR; break; 588 | case 8: 589 | adjustment = 8 * SECONDS_PER_HOUR; break; 590 | case 845: 591 | adjustment = 8.75 * SECONDS_PER_HOUR; break; 592 | case 9: 593 | adjustment = 9 * SECONDS_PER_HOUR; break; 594 | case 930: 595 | adjustment = 9.5 * SECONDS_PER_HOUR; break; 596 | case 10: 597 | adjustment = 10 * SECONDS_PER_HOUR; break; 598 | case 1030: 599 | adjustment = 10.5 * SECONDS_PER_HOUR; break; 600 | case 11: 601 | adjustment = 11 * SECONDS_PER_HOUR; break; 602 | case 1130: 603 | adjustment = 11.5 * SECONDS_PER_HOUR; break; 604 | case 12: 605 | adjustment = 12 * SECONDS_PER_HOUR; break; 606 | case 1245: 607 | adjustment = 12.75 * SECONDS_PER_HOUR; break; 608 | case 13: 609 | adjustment = 13 * SECONDS_PER_HOUR; break; 610 | case 14: 611 | adjustment = 14 * SECONDS_PER_HOUR; break; 612 | } 613 | 614 | return adjustment; 615 | } 616 | 617 | /* 618 | int RTC_clock::switch_years (uint16_t year) 619 | { 620 | if ( ((year %4 == 0) && (year % 100 != 0)) || (year % 400 == 0) ) { 621 | return 1; 622 | } else { 623 | return 0; 624 | } 625 | } 626 | */ 627 | 628 | int RTC_clock::summertime () 629 | { 630 | int sundaysommertime, sundaywintertime, today, sundaysommertimehours, sundaywintertimehours, todayhours; 631 | 632 | _current_date = current_date(); 633 | _current_time = current_time(); 634 | 635 | _hour = (((_current_time & 0x00300000) >> 20) * 10 + ((_current_time & 0x000F0000) >> 16)); 636 | _day = ((((_current_date >> 28) & 0x3) * 10) + ((_current_date >> 24) & 0xF)); 637 | _month = ((((_current_date >> 20) & 1) * 10) + ((_current_date >> 16) & 0xF)); 638 | //_year 4 digits 639 | _year = ((((_current_date >> 4) & 0x7) * 1000) + ((_current_date & 0xF) * 100) 640 | + (((_current_date >> 12) & 0xF) * 10) + ((_current_date >> 8) & 0xF)); 641 | 642 | //_year 2 digits 643 | //_year = (((_current_date >> 12) & 0xF) * 10) + ((_current_date >> 8) & 0xF); 644 | 645 | // Based on http://www.webexhibits.org/daylightsaving/i.html 646 | // Equations by Wei-Hwa Huang (US), and Robert H. van Gent (EC) 647 | // Slightly modified for use in micro controller for integer use 648 | // also found there http://manfred.wilzeck.de/Datum_berechnen.html#Auch_mit_Osterdatum_berechnen 649 | // Number 5 (Works for the Years 2000 - 2099) 650 | sundaysommertime = 31 - ( 5 + _year * 5 / 4 ) % 7; 651 | sundaywintertime = 31 - ( 2 + _year * 5 / 4 ) % 7; 652 | today = _day; 653 | 654 | // Summertime begin in March 655 | for (int i = 1; i < 2; ++i) { 656 | if ( (i - 1) == 1) 657 | sundaysommertime += daysInMonth[i - 1] + switch_years(_year); 658 | else 659 | sundaysommertime += daysInMonth[i - 1]; 660 | } 661 | 662 | // Wintertime begin in October 663 | for (int i = 1; i < 9; ++i) { 664 | if ( (i - 1) == 1) 665 | sundaywintertime += daysInMonth[i - 1] + switch_years(_year); 666 | else 667 | sundaywintertime += daysInMonth[i - 1]; 668 | } 669 | 670 | // Total actually days 671 | for (int i = 1; i < (_month - 1); ++i) { 672 | if ( (i - 1) == 1) 673 | today += daysInMonth[i - 1] + switch_years(_year); 674 | else 675 | today += daysInMonth[i - 1]; 676 | } 677 | 678 | sundaysommertimehours = sundaysommertime * 24 + 2; 679 | sundaywintertimehours = sundaywintertime * 24 + 3; 680 | todayhours = today * 24 + _hour; 681 | 682 | if ( todayhours >= sundaysommertimehours && (todayhours + 1) < sundaywintertimehours ) 683 | return 1; 684 | else 685 | return 0; 686 | } 687 | 688 | void RTC_clock::dst_followup () 689 | { 690 | int sundaysommertime, sundaywintertime; 691 | 692 | _current_date = current_date(); 693 | 694 | //_year 4 digits 695 | _year = ((((_current_date >> 4) & 0x7) * 1000) + ((_current_date & 0xF) * 100) 696 | + (((_current_date >> 12) & 0xF) * 10) + ((_current_date >> 8) & 0xF)); 697 | 698 | //_year 2 digits 699 | //_year = (((_current_date >> 12) & 0xF) * 10) + ((_current_date >> 8) & 0xF); 700 | 701 | sundaysommertime = 31 - ( 5 + _year * 5 / 4 ) % 7; 702 | sundaywintertime = 31 - ( 2 + _year * 5 / 4 ) % 7; 703 | 704 | if (get_months () == 3 && get_days () == sundaysommertime) { 705 | if (get_hours () == 2 && get_minutes () == 0 && get_seconds () == 0) { 706 | set_hours (3); 707 | dst_winter_done = false; 708 | } 709 | } 710 | 711 | if (!dst_winter_done) { 712 | if (get_months () == 10 && get_days () == sundaywintertime ) { 713 | if (get_hours () == 3 && get_minutes () == 0 && get_seconds () == 0) { 714 | set_hours (2); 715 | dst_winter_done = true; 716 | } 717 | } 718 | } 719 | } 720 | --------------------------------------------------------------------------------