Browse Source

first commit

pi3rrot 6 years ago
commit
7938385ae0

+ 0 - 0
lib/.holder


BIN
lib/DS3231/.DS3231.h.swp


+ 485 - 0
lib/DS3231/DS3231.cpp

@@ -0,0 +1,485 @@
+/*
+  DS3231.cpp - Arduino/chipKit library support for the DS3231 I2C Real-Time Clock
+  Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
+  
+  This library has been made to easily interface and use the DS3231 RTC with
+  an Arduino or chipKit.
+
+  You can find the latest version of the library at 
+  http://www.RinkyDinkElectronics.com/
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the CC BY-NC-SA 3.0 license.
+  Please see the included documents for further information.
+
+  Commercial use of this library requires you to buy a license that
+  will allow commercial use. This includes using the library,
+  modified or not, as a tool to sell products.
+
+  The license applies to all part of the library including the 
+  examples and tools supplied with the library.
+*/
+#include "DS3231.h"
+
+// Include hardware-specific functions for the correct MCU
+#if defined(__AVR__)
+	#include "hardware/avr/HW_AVR.h"
+#elif defined(__PIC32MX__)
+  #include "hardware/pic32/HW_PIC32.h"
+#elif defined(__arm__)
+	#include "hardware/arm/HW_ARM.h"
+#endif
+
+#define REG_SEC		0x00
+#define REG_MIN		0x01
+#define REG_HOUR	0x02
+#define REG_DOW		0x03
+#define REG_DATE	0x04
+#define REG_MON		0x05
+#define REG_YEAR	0x06
+
+#define REG_ALARM1_SEC	0x07
+#define REG_ALARM1_MIN	0x08
+#define REG_ALARM1_HOUR	0x09
+#define REG_ALARM1_DAY	0xA0
+
+#define REG_ALARM2_MIN	0xB0
+#define REG_ALARM2_HOUR	0xC0
+#define REG_ALARM2_DAY	0xD0
+
+#define REG_CON		0x0e
+#define REG_STATUS	0x0f
+#define REG_AGING	0x10
+#define REG_TEMPM	0x11
+#define REG_TEMPL	0x12
+
+#define SEC_1970_TO_2000 946684800
+
+static const uint8_t dim[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
+
+/* Public */
+
+Time::Time()
+{
+	this->year = 2014;
+	this->mon  = 1;
+	this->date = 1;
+	this->hour = 0;
+	this->min  = 0;
+	this->sec  = 0;
+	this->dow  = 3;
+}
+
+DS3231::DS3231(uint8_t data_pin, uint8_t sclk_pin)
+{
+	_sda_pin = data_pin;
+	_scl_pin = sclk_pin;
+}
+
+Time DS3231::getTime()
+{
+	Time t;
+	_burstRead();
+	t.sec	= _decode(_burstArray[0]);
+	t.min	= _decode(_burstArray[1]);
+	t.hour	= _decodeH(_burstArray[2]);
+	t.dow	= _burstArray[3];
+	t.date	= _decode(_burstArray[4]);
+	t.mon	= _decode(_burstArray[5]);
+	t.year	= _decodeY(_burstArray[6])+2000;
+	return t;
+}
+
+void DS3231::setTime(uint8_t hour, uint8_t min, uint8_t sec)
+{
+	if (((hour>=0) && (hour<24)) && ((min>=0) && (min<60)) && ((sec>=0) && (sec<60)))
+	{
+		_writeRegister(REG_HOUR, _encode(hour));
+		_writeRegister(REG_MIN, _encode(min));
+		_writeRegister(REG_SEC, _encode(sec));
+	}
+}
+
+void DS3231::setDate(uint8_t date, uint8_t mon, uint16_t year)
+{
+	if (((date>0) && (date<=31)) && ((mon>0) && (mon<=12)) && ((year>=2000) && (year<3000)))
+	{
+		year -= 2000;
+		_writeRegister(REG_YEAR, _encode(year));
+		_writeRegister(REG_MON, _encode(mon));
+		_writeRegister(REG_DATE, _encode(date));
+	}
+}
+
+void DS3231::setDOW()
+{
+	int dow;
+	byte mArr[12] = {6,2,2,5,0,3,5,1,4,6,2,4};
+	Time _t = getTime();
+  
+	dow = (_t.year % 100);
+	dow = dow*1.25;
+	dow += _t.date;
+	dow += mArr[_t.mon-1];
+	if (((_t.year % 4)==0) && (_t.mon<3))
+		dow -= 1;
+	while (dow>7)
+		dow -= 7;
+	_writeRegister(REG_DOW, dow);
+}
+
+void DS3231::setDOW(uint8_t dow)
+{
+	if ((dow>0) && (dow<8))
+		_writeRegister(REG_DOW, dow);
+}
+
+char *DS3231::getTimeStr(uint8_t format)
+{
+	static char output[] = "xxxxxxxx";
+	Time t;
+	t=getTime();
+	if (t.hour<10)
+		output[0]=48;
+	else
+		output[0]=char((t.hour / 10)+48);
+	output[1]=char((t.hour % 10)+48);
+	output[2]=58;
+	if (t.min<10)
+		output[3]=48;
+	else
+		output[3]=char((t.min / 10)+48);
+	output[4]=char((t.min % 10)+48);
+	output[5]=58;
+	if (format==FORMAT_SHORT)
+		output[5]=0;
+	else
+	{
+	if (t.sec<10)
+		output[6]=48;
+	else
+		output[6]=char((t.sec / 10)+48);
+	output[7]=char((t.sec % 10)+48);
+	output[8]=0;
+	}
+	return (char*)&output;
+}
+
+char *DS3231::getDateStr(uint8_t slformat, uint8_t eformat, char divider)
+{
+	static char output[] = "xxxxxxxxxx";
+	int yr, offset;
+	Time t;
+	t=getTime();
+	switch (eformat)
+	{
+		case FORMAT_LITTLEENDIAN:
+			if (t.date<10)
+				output[0]=48;
+			else
+				output[0]=char((t.date / 10)+48);
+			output[1]=char((t.date % 10)+48);
+			output[2]=divider;
+			if (t.mon<10)
+				output[3]=48;
+			else
+				output[3]=char((t.mon / 10)+48);
+			output[4]=char((t.mon % 10)+48);
+			output[5]=divider;
+			if (slformat==FORMAT_SHORT)
+			{
+				yr=t.year-2000;
+				if (yr<10)
+					output[6]=48;
+				else
+					output[6]=char((yr / 10)+48);
+				output[7]=char((yr % 10)+48);
+				output[8]=0;
+			}
+			else
+			{
+				yr=t.year;
+				output[6]=char((yr / 1000)+48);
+				output[7]=char(((yr % 1000) / 100)+48);
+				output[8]=char(((yr % 100) / 10)+48);
+				output[9]=char((yr % 10)+48);
+				output[10]=0;
+			}
+			break;
+		case FORMAT_BIGENDIAN:
+			if (slformat==FORMAT_SHORT)
+				offset=0;
+			else
+				offset=2;
+			if (slformat==FORMAT_SHORT)
+			{
+				yr=t.year-2000;
+				if (yr<10)
+					output[0]=48;
+				else
+					output[0]=char((yr / 10)+48);
+				output[1]=char((yr % 10)+48);
+				output[2]=divider;
+			}
+			else
+			{
+				yr=t.year;
+				output[0]=char((yr / 1000)+48);
+				output[1]=char(((yr % 1000) / 100)+48);
+				output[2]=char(((yr % 100) / 10)+48);
+				output[3]=char((yr % 10)+48);
+				output[4]=divider;
+			}
+			if (t.mon<10)
+				output[3+offset]=48;
+			else
+				output[3+offset]=char((t.mon / 10)+48);
+			output[4+offset]=char((t.mon % 10)+48);
+			output[5+offset]=divider;
+			if (t.date<10)
+				output[6+offset]=48;
+			else
+				output[6+offset]=char((t.date / 10)+48);
+			output[7+offset]=char((t.date % 10)+48);
+			output[8+offset]=0;
+			break;
+		case FORMAT_MIDDLEENDIAN:
+			if (t.mon<10)
+				output[0]=48;
+			else
+				output[0]=char((t.mon / 10)+48);
+			output[1]=char((t.mon % 10)+48);
+			output[2]=divider;
+			if (t.date<10)
+				output[3]=48;
+			else
+				output[3]=char((t.date / 10)+48);
+			output[4]=char((t.date % 10)+48);
+			output[5]=divider;
+			if (slformat==FORMAT_SHORT)
+			{
+				yr=t.year-2000;
+				if (yr<10)
+					output[6]=48;
+				else
+					output[6]=char((yr / 10)+48);
+				output[7]=char((yr % 10)+48);
+				output[8]=0;
+			}
+			else
+			{
+				yr=t.year;
+				output[6]=char((yr / 1000)+48);
+				output[7]=char(((yr % 1000) / 100)+48);
+				output[8]=char(((yr % 100) / 10)+48);
+				output[9]=char((yr % 10)+48);
+				output[10]=0;
+			}
+			break;
+	}
+	return (char*)&output;
+}
+
+char *DS3231::getDOWStr(uint8_t format)
+{
+	char *output = "xxxxxxxxxx";
+	char *daysLong[]  = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
+	char *daysShort[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
+	Time t;
+	t=getTime();
+	if (format == FORMAT_SHORT)
+		output = daysShort[t.dow-1];
+	else
+		output = daysLong[t.dow-1];
+	return output;
+}
+
+char *DS3231::getMonthStr(uint8_t format)
+{
+	char *output= "xxxxxxxxx";
+	char *monthLong[]  = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
+	char *monthShort[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+	Time t;
+	t=getTime();
+	if (format == FORMAT_SHORT)
+		output = monthShort[t.mon-1];
+	else
+		output = monthLong[t.mon-1];
+	return output;
+}
+
+long DS3231::getUnixTime(Time t)
+{
+	uint16_t	dc;
+
+	dc = t.date;
+	for (uint8_t i = 0; i<(t.mon-1); i++)
+		dc += dim[i];
+	if ((t.mon > 2) && (((t.year-2000) % 4) == 0))
+		++dc;
+	dc = dc + (365 * (t.year-2000)) + (((t.year-2000) + 3) / 4) - 1;
+
+	return ((((((dc * 24L) + t.hour) * 60) + t.min) * 60) + t.sec) + SEC_1970_TO_2000;
+
+}
+
+void DS3231::enable32KHz(bool enable)
+{
+  uint8_t _reg = _readRegister(REG_STATUS);
+  _reg &= ~(1 << 3);
+  _reg |= (enable << 3);
+  _writeRegister(REG_STATUS, _reg);
+}
+
+void DS3231::setOutput(byte enable)
+{
+  uint8_t _reg = _readRegister(REG_CON);
+  _reg &= ~(1 << 2);
+  _reg |= (enable << 2);
+  _writeRegister(REG_CON, _reg);
+}
+
+void DS3231::setSQWRate(int rate)
+{
+  uint8_t _reg = _readRegister(REG_CON);
+  _reg &= ~(3 << 3);
+  _reg |= (rate << 3);
+  _writeRegister(REG_CON, _reg);
+}
+
+float DS3231::getTemp()
+{
+	uint8_t _msb = _readRegister(REG_TEMPM);
+	uint8_t _lsb = _readRegister(REG_TEMPL);
+	return (float)_msb + ((_lsb >> 6) * 0.25f);
+}
+
+/* Private */
+
+void	DS3231::_sendStart(byte addr)
+{
+	pinMode(_sda_pin, OUTPUT);
+	digitalWrite(_sda_pin, HIGH);
+	digitalWrite(_scl_pin, HIGH);
+	digitalWrite(_sda_pin, LOW);
+	digitalWrite(_scl_pin, LOW);
+	shiftOut(_sda_pin, _scl_pin, MSBFIRST, addr);
+}
+
+void	DS3231::_sendStop()
+{
+	pinMode(_sda_pin, OUTPUT);
+	digitalWrite(_sda_pin, LOW);
+	digitalWrite(_scl_pin, HIGH);
+	digitalWrite(_sda_pin, HIGH);
+	pinMode(_sda_pin, INPUT);
+}
+
+void	DS3231::_sendNack()
+{
+	pinMode(_sda_pin, OUTPUT);
+	digitalWrite(_scl_pin, LOW);
+	digitalWrite(_sda_pin, HIGH);
+	digitalWrite(_scl_pin, HIGH);
+	digitalWrite(_scl_pin, LOW);
+	pinMode(_sda_pin, INPUT);
+}
+
+void	DS3231::_sendAck()
+{
+	pinMode(_sda_pin, OUTPUT);
+	digitalWrite(_scl_pin, LOW);
+	digitalWrite(_sda_pin, LOW);
+	digitalWrite(_scl_pin, HIGH);
+	digitalWrite(_scl_pin, LOW);
+	pinMode(_sda_pin, INPUT);
+}
+
+void	DS3231::_waitForAck()
+{
+	pinMode(_sda_pin, INPUT);
+	digitalWrite(_scl_pin, HIGH);
+	while (digitalRead(_sda_pin)==HIGH) {}
+	digitalWrite(_scl_pin, LOW);
+}
+
+uint8_t DS3231::_readByte()
+{
+	pinMode(_sda_pin, INPUT);
+
+	uint8_t value = 0;
+	uint8_t currentBit = 0;
+
+	for (int i = 0; i < 8; ++i)
+	{
+		digitalWrite(_scl_pin, HIGH);
+		currentBit = digitalRead(_sda_pin);
+		value |= (currentBit << 7-i);
+		delayMicroseconds(1);
+		digitalWrite(_scl_pin, LOW);
+	}
+	return value;
+}
+
+void DS3231::_writeByte(uint8_t value)
+{
+	pinMode(_sda_pin, OUTPUT);
+	shiftOut(_sda_pin, _scl_pin, MSBFIRST, value);
+}
+
+uint8_t	DS3231::_decode(uint8_t value)
+{
+	uint8_t decoded = value & 127;
+	decoded = (decoded & 15) + 10 * ((decoded & (15 << 4)) >> 4);
+	return decoded;
+}
+
+uint8_t DS3231::_decodeH(uint8_t value)
+{
+  if (value & 128)
+    value = (value & 15) + (12 * ((value & 32) >> 5));
+  else
+    value = (value & 15) + (10 * ((value & 48) >> 4));
+  return value;
+}
+
+uint8_t	DS3231::_decodeY(uint8_t value)
+{
+	uint8_t decoded = (value & 15) + 10 * ((value & (15 << 4)) >> 4);
+	return decoded;
+}
+
+uint8_t DS3231::_encode(uint8_t value)
+{
+	uint8_t encoded = ((value / 10) << 4) + (value % 10);
+	return encoded;
+}
+
+
+
+
+
+
+
+void DS3231::setAlarm1Time(uint8_t hour, uint8_t min, uint8_t sec)
+{
+	if (((hour>=0) && (hour<24)) && ((min>=0) && (min<60)) && ((sec>=0) && (sec<60)))
+	{
+		_writeRegister(REG_ALARM1_HOUR, _encode(hour));
+		_writeRegister(REG_ALARM1_MIN, _encode(min));
+		_writeRegister(REG_ALARM1_SEC, _encode(sec));
+	}
+}
+
+
+
+void DS3231::setAlarm2Time(uint8_t hour, uint8_t min, uint8_t sec)
+{
+	if (((hour>=0) && (hour<24)) && ((min>=0) && (min<60)) && ((sec>=0) && (sec<60)))
+	{
+		_writeRegister(REG_ALARM2_HOUR, _encode(hour));
+		_writeRegister(REG_ALARM2_MIN, _encode(min));
+		_writeRegister(REG_ALARM2_SEC, _encode(sec));
+	}
+}
+

+ 128 - 0
lib/DS3231/DS3231.h

@@ -0,0 +1,128 @@
+/*
+  DS3231.cpp - Arduino/chipKit library support for the DS3231 I2C Real-Time Clock
+  Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
+  
+  This library has been made to easily interface and use the DS3231 RTC with
+  an Arduino or chipKit.
+
+  You can find the latest version of the library at 
+  http://www.RinkyDinkElectronics.com/
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the CC BY-NC-SA 3.0 license.
+  Please see the included documents for further information.
+
+  Commercial use of this library requires you to buy a license that
+  will allow commercial use. This includes using the library,
+  modified or not, as a tool to sell products.
+
+  The license applies to all part of the library including the 
+  examples and tools supplied with the library.
+*/
+#ifndef DS3231_h
+#define DS3231_h
+
+#if defined(__AVR__)
+	#include "Arduino.h"
+	#include "hardware/avr/HW_AVR_defines.h"
+#elif defined(__PIC32MX__)
+	#include "WProgram.h"
+	#include "hardware/pic32/HW_PIC32_defines.h"
+#elif defined(__arm__)
+	#include "Arduino.h"
+	#include "hardware/arm/HW_ARM_defines.h"
+#endif
+
+#define DS3231_ADDR_R	0xD1
+#define DS3231_ADDR_W	0xD0
+#define DS3231_ADDR		0x68
+
+#define FORMAT_SHORT	1
+#define FORMAT_LONG		2
+
+#define FORMAT_LITTLEENDIAN	1
+#define FORMAT_BIGENDIAN	2
+#define FORMAT_MIDDLEENDIAN	3
+
+#define MONDAY		1
+#define TUESDAY		2
+#define WEDNESDAY	3
+#define THURSDAY	4
+#define FRIDAY		5
+#define SATURDAY	6
+#define SUNDAY		7
+
+#define SQW_RATE_1		0
+#define SQW_RATE_1K		1
+#define SQW_RATE_4K		2
+#define SQW_RATE_8K		3
+
+#define OUTPUT_SQW		0
+#define OUTPUT_INT		1
+
+class Time
+{
+public:
+	uint8_t		hour;
+	uint8_t		min;
+	uint8_t		sec;
+	uint8_t		date;
+	uint8_t		mon;
+	uint16_t	year;
+	uint8_t		dow;
+
+	Time();
+};
+
+class DS3231
+{
+	public:
+		DS3231(uint8_t data_pin, uint8_t sclk_pin);
+		void	begin();
+		Time	getTime();
+		void	setTime(uint8_t hour, uint8_t min, uint8_t sec);
+
+		void	setAlarm1Time(uint8_t hour, uint8_t min, uint8_t sec);
+		void	setAlarm2Time(uint8_t hour, uint8_t min, uint8_t sec);
+
+
+		void	setDate(uint8_t date, uint8_t mon, uint16_t year);
+		void	setDOW();
+		void	setDOW(uint8_t dow);
+
+		char	*getTimeStr(uint8_t format=FORMAT_LONG);
+		char	*getDateStr(uint8_t slformat=FORMAT_LONG, uint8_t eformat=FORMAT_LITTLEENDIAN, char divider='.');
+		char	*getDOWStr(uint8_t format=FORMAT_LONG);
+		char	*getMonthStr(uint8_t format=FORMAT_LONG);
+		long	getUnixTime(Time t);
+
+		void	enable32KHz(bool enable);
+		void	setOutput(byte enable);
+		void	setSQWRate(int rate);
+		float	getTemp();
+
+	private:
+		uint8_t _scl_pin;
+		uint8_t _sda_pin;
+		uint8_t _burstArray[7];
+		boolean	_use_hw;
+
+		void	_sendStart(byte addr);
+		void	_sendStop();
+		void	_sendAck();
+		void	_sendNack();
+		void	_waitForAck();
+		uint8_t	_readByte();
+		void	_writeByte(uint8_t value);
+		void	_burstRead();
+		uint8_t	_readRegister(uint8_t reg);
+		void 	_writeRegister(uint8_t reg, uint8_t value);
+		uint8_t	_decode(uint8_t value);
+		uint8_t	_decodeH(uint8_t value);
+		uint8_t	_decodeY(uint8_t value);
+		uint8_t	_encode(uint8_t vaule);
+#if defined(__arm__)
+		Twi		*twi;
+#endif
+};
+#endif

BIN
lib/DS3231/Documentation/DS3231.pdf


+ 3 - 0
lib/DS3231/Documentation/version.txt

@@ -0,0 +1,3 @@
+Version:
+	1.0	17 Aug 2014  -  initial release
+	1.01	25 Aug 2014  -  small bugfix

BIN
lib/DS3231/License/License - CC BY-NC-SA 3.0 - Legal.pdf


BIN
lib/DS3231/License/License - CC BY-NC-SA 3.0 - Summary.pdf


+ 77 - 0
lib/DS3231/examples/Arduino/DS3231_Serial_Easy/DS3231_Serial_Easy.ino

@@ -0,0 +1,77 @@
+// DS3231_Serial_Easy
+// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
+// web: http://www.RinkyDinkElectronics.com/
+//
+// A quick demo of how to use my DS3231-library to 
+// quickly send time and date information over a serial link
+//
+// To use the hardware I2C (TWI) interface of the Arduino you must connect
+// the pins as follows:
+//
+// Arduino Uno/2009:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Analog 4 or the dedicated SDA pin
+//          SCL pin   -> Arduino Analog 5 or the dedicated SCL pin
+//
+// Arduino Leonardo:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 2 or the dedicated SDA pin
+//          SCL pin   -> Arduino Digital 3 or the dedicated SCL pin
+//
+// Arduino Mega:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA pin
+//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL pin
+//
+// Arduino Due:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA1 (Digital 70) pin
+//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL1 (Digital 71) pin
+//
+// The internal pull-up resistors will be activated when using the 
+// hardware I2C interfaces.
+//
+// You can connect the DS3231 to any available pin but if you use any
+// other than what is described above the library will fall back to
+// a software-based, TWI-like protocol which will require exclusive access 
+// to the pins used, and you will also have to use appropriate, external
+// pull-up resistors on the data and clock signals.
+//
+
+#include <DS3231.h>
+
+// Init the DS3231 using the hardware interface
+DS3231  rtc(SDA, SCL);
+
+void setup()
+{
+  // Setup Serial connection
+  Serial.begin(115200);
+  // Uncomment the next line if you are using an Arduino Leonardo
+  //while (!Serial) {}
+  
+  // Initialize the rtc object
+  rtc.begin();
+  
+  // The following lines can be uncommented to set the date and time
+  //rtc.setDOW(WEDNESDAY);     // Set Day-of-Week to SUNDAY
+  //rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
+  //rtc.setDate(1, 1, 2014);   // Set the date to January 1st, 2014
+}
+
+void loop()
+{
+  // Send Day-of-Week
+  Serial.print(rtc.getDOWStr());
+  Serial.print(" ");
+  
+  // Send date
+  Serial.print(rtc.getDateStr());
+  Serial.print(" -- ");
+
+  // Send time
+  Serial.println(rtc.getTimeStr());
+  
+  // Wait one second before repeating :)
+  delay (1000);
+}

+ 95 - 0
lib/DS3231/examples/Arduino/DS3231_Serial_Hard/DS3231_Serial_Hard.ino

@@ -0,0 +1,95 @@
+// DS3231_Serial_Hard
+// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
+// web: http://www.RinkyDinkElectronics.com/
+//
+// A quick demo of how to use my DS3231-library to 
+// retrieve time- and date-data for you to manipulate.
+//
+// To use the hardware I2C (TWI) interface of the Arduino you must connect
+// the pins as follows:
+//
+// Arduino Uno/2009:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Analog 4 or the dedicated SDA pin
+//          SCL pin   -> Arduino Analog 5 or the dedicated SCL pin
+//
+// Arduino Leonardo:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 2 or the dedicated SDA pin
+//          SCL pin   -> Arduino Digital 3 or the dedicated SCL pin
+//
+// Arduino Mega:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA pin
+//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL pin
+//
+// Arduino Due:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA1 (Digital 70) pin
+//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL1 (Digital 71) pin
+//
+// The internal pull-up resistors will be activated when using the 
+// hardware I2C interfaces.
+//
+// You can connect the DS3231 to any available pin but if you use any
+// other than what is described above the library will fall back to
+// a software-based, TWI-like protocol which will require exclusive access 
+// to the pins used, and you will also have to use appropriate, external
+// pull-up resistors on the data and clock signals.
+//
+
+#include <DS3231.h>
+
+// Init the DS3231 using the hardware interface
+DS3231  rtc(SDA, SCL);
+
+// Init a Time-data structure
+Time  t;
+
+void setup()
+{
+  // Setup Serial connection
+  Serial.begin(115200);
+  // Uncomment the next line if you are using an Arduino Leonardo
+  //while (!Serial) {}
+
+  // Initialize the rtc object
+  rtc.begin();
+  
+  // The following lines can be uncommented to set the date and time
+  //rtc.setDOW(WEDNESDAY);     // Set Day-of-Week to SUNDAY
+  //rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
+  //rtc.setDate(1, 1, 2014);   // Set the date to January 1st, 2014
+}
+
+void loop()
+{
+  // Get data from the DS3231
+  t = rtc.getTime();
+  
+  // Send date over serial connection
+  Serial.print("Today is the ");
+  Serial.print(t.date, DEC);
+  Serial.print(". day of ");
+  Serial.print(rtc.getMonthStr());
+  Serial.print(" in the year ");
+  Serial.print(t.year, DEC);
+  Serial.println(".");
+  
+  // Send Day-of-Week and time
+  Serial.print("It is the ");
+  Serial.print(t.dow, DEC);
+  Serial.print(". day of the week (counting monday as the 1th), and it has passed ");
+  Serial.print(t.hour, DEC);
+  Serial.print(" hour(s), ");
+  Serial.print(t.min, DEC);
+  Serial.print(" minute(s) and ");
+  Serial.print(t.sec, DEC);
+  Serial.println(" second(s) since midnight.");
+
+  // Send a divider for readability
+  Serial.println("  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -");
+  
+  // Wait one second before repeating :)
+  delay (1000);
+}

+ 64 - 0
lib/DS3231/examples/Arduino/DS3231_Temperature/DS3231_Temperature.ino

@@ -0,0 +1,64 @@
+// DS3231_Temperature
+// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
+// web: http://www.RinkyDinkElectronics.com/
+//
+// A quick demo of how to use my DS3231-library to 
+// quickly send the current temperature over a serial link
+//
+// To use the hardware I2C (TWI) interface of the Arduino you must connect
+// the pins as follows:
+//
+// Arduino Uno/2009:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Analog 4 or the dedicated SDA pin
+//          SCL pin   -> Arduino Analog 5 or the dedicated SCL pin
+//
+// Arduino Leonardo:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 2 or the dedicated SDA pin
+//          SCL pin   -> Arduino Digital 3 or the dedicated SCL pin
+//
+// Arduino Mega:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA pin
+//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL pin
+//
+// Arduino Due:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA1 (Digital 70) pin
+//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL1 (Digital 71) pin
+//
+// The internal pull-up resistors will be activated when using the 
+// hardware I2C interfaces.
+//
+// You can connect the DS3231 to any available pin but if you use any
+// other than what is described above the library will fall back to
+// a software-based, TWI-like protocol which will require exclusive access 
+// to the pins used, and you will also have to use appropriate, external
+// pull-up resistors on the data and clock signals.
+//
+
+#include <DS3231.h>
+
+// Init the DS3231 using the hardware interface
+DS3231  rtc(SDA, SCL);
+
+void setup()
+{
+  // Setup Serial connection
+  Serial.begin(115200);
+  // Uncomment the next line if you are using an Arduino Leonardo
+  //while (!Serial) {}
+
+  // Initialize the rtc object
+  rtc.begin();
+}
+
+void loop()
+{
+  // Send current temperature
+  Serial.print("Temperature: ");
+  Serial.print(rtc.getTemp());
+  Serial.println(" C");
+  delay (1000);
+}

+ 87 - 0
lib/DS3231/examples/Arduino/DS3231_UnixTime/DS3231_UnixTime.ino

@@ -0,0 +1,87 @@
+// DS3231_UnixTime
+// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
+// web: http://www.RinkyDinkElectronics.com/
+//
+// A quick demo of how to use my DS3231-library to 
+// convert date and time to UnixTime
+//
+// To use the hardware I2C (TWI) interface of the Arduino you must connect
+// the pins as follows:
+//
+// Arduino Uno/2009:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Analog 4 or the dedicated SDA pin
+//          SCL pin   -> Arduino Analog 5 or the dedicated SCL pin
+//
+// Arduino Leonardo:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 2 or the dedicated SDA pin
+//          SCL pin   -> Arduino Digital 3 or the dedicated SCL pin
+//
+// Arduino Mega:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA pin
+//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL pin
+//
+// Arduino Due:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA1 (Digital 70) pin
+//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL1 (Digital 71) pin
+//
+// The internal pull-up resistors will be activated when using the 
+// hardware I2C interfaces.
+//
+// You can connect the DS3231 to any available pin but if you use any
+// other than what is described above the library will fall back to
+// a software-based, TWI-like protocol which will require exclusive access 
+// to the pins used, and you will also have to use appropriate, external
+// pull-up resistors on the data and clock signals.
+//
+
+#include <DS3231.h>
+
+// Init the DS3231 using the hardware interface
+DS3231  rtc(SDA, SCL);
+
+Time t;
+
+void setup()
+{
+  // Setup Serial connection
+  Serial.begin(115200);
+  // Uncomment the next line if you are using an Arduino Leonardo
+  //while (!Serial) {}
+
+  // Initialize the rtc object
+  rtc.begin();
+}
+
+void loop()
+{
+  // Send Current time
+  Serial.print("Current Time.............................: ");
+  Serial.print(rtc.getDOWStr());
+  Serial.print(" ");
+  Serial.print(rtc.getDateStr());
+  Serial.print(" -- ");
+  Serial.println(rtc.getTimeStr());
+
+  // Send Unixtime
+  // ** Note that there may be a one second difference between the current time **
+  // ** and current unixtime show if the second changes between the two calls   **
+  Serial.print("Current Unixtime.........................: ");
+  Serial.println(rtc.getUnixTime(rtc.getTime()));
+  
+  // Send Unixtime for 00:00:00 on January 1th 2014
+  Serial.print("Unixtime for 00:00:00 on January 1th 2014: ");
+  t.hour = 0;
+  t.min = 0;
+  t.sec = 0;
+  t.year = 2014;
+  t.mon = 1;
+  t.date = 1;
+  Serial.println(rtc.getUnixTime(t));
+
+  // Wait indefinitely
+  while (1) {};
+}

+ 65 - 0
lib/DS3231/examples/chipKit/DS3231_Serial_Easy/DS3231_Serial_Easy.pde

@@ -0,0 +1,65 @@
+// DS3231_Serial_Easy
+// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
+// web: http://www.RinkyDinkElectronics.com/
+//
+// A quick demo of how to use my DS3231-library to 
+// quickly send time and date information over a serial link
+//
+// To use the hardware I2C (TWI) interface of the chipKit you must connect
+// the pins as follows:
+//
+// chipKit Uno32/uC32:
+// ----------------------
+// DS3231:  SDA pin   -> Analog 4
+//          SCL pin   -> Analog 5
+// *** Please note that JP6 and JP8 must be in the I2C position (closest to the analog pins)
+//
+// chipKit Max32:
+// ----------------------
+// DS3231:  SDA pin   -> Digital 20 (the pin labeled SDA)
+//          SCL pin   -> Digital 21 (the pin labeled SCL)
+//
+// The chipKit boards does not have pull-up resistors on the hardware I2C interface
+// so external pull-up resistors on the data and clock signals are required.
+//
+// You can connect the DS3231 to any available pin but if you use any
+// other than what is described above the library will fall back to
+// a software-based, TWI-like protocol which will require exclusive access 
+// to the pins used.
+//
+
+#include <DS3231.h>
+
+// Init the DS3231 using the hardware interface
+DS3231  rtc(SDA, SCL);
+
+void setup()
+{
+  // Setup Serial connection
+  Serial.begin(115200);
+  
+  // Initialize the rtc object
+  rtc.begin();
+  
+  // The following lines can be uncommented to set the date and time
+  //rtc.setDOW(WEDNESDAY);     // Set Day-of-Week to SUNDAY
+  //rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
+  //rtc.setDate(1, 1, 2014);   // Set the date to January 1st, 2014
+}
+
+void loop()
+{
+  // Send Day-of-Week
+  Serial.print(rtc.getDOWStr());
+  Serial.print(" ");
+  
+  // Send date
+  Serial.print(rtc.getDateStr());
+  Serial.print(" -- ");
+
+  // Send time
+  Serial.println(rtc.getTimeStr());
+  
+  // Wait one second before repeating :)
+  delay (1000);
+}

+ 83 - 0
lib/DS3231/examples/chipKit/DS3231_Serial_Hard/DS3231_Serial_Hard.pde

@@ -0,0 +1,83 @@
+// DS3231_Serial_Hard
+// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
+// web: http://www.RinkyDinkElectronics.com/
+//
+// A quick demo of how to use my DS3231-library to 
+// retrieve time- and date-data for you to manipulate.
+//
+// To use the hardware I2C (TWI) interface of the chipKit you must connect
+// the pins as follows:
+//
+// chipKit Uno32/uC32:
+// ----------------------
+// DS3231:  SDA pin   -> Analog 4
+//          SCL pin   -> Analog 5
+// *** Please note that JP6 and JP8 must be in the I2C position (closest to the analog pins)
+//
+// chipKit Max32:
+// ----------------------
+// DS3231:  SDA pin   -> Digital 20 (the pin labeled SDA)
+//          SCL pin   -> Digital 21 (the pin labeled SCL)
+//
+// The chipKit boards does not have pull-up resistors on the hardware I2C interface
+// so external pull-up resistors on the data and clock signals are required.
+//
+// You can connect the DS3231 to any available pin but if you use any
+// other than what is described above the library will fall back to
+// a software-based, TWI-like protocol which will require exclusive access 
+// to the pins used.
+//
+
+#include <DS3231.h>
+
+// Init the DS3231 using the hardware interface
+DS3231  rtc(SDA, SCL);
+
+// Init a Time-data structure
+Time  t;
+
+void setup()
+{
+  // Setup Serial connection
+  Serial.begin(115200);
+
+  // Initialize the rtc object
+  rtc.begin();
+  
+  // The following lines can be uncommented to set the date and time
+  //rtc.setDOW(WEDNESDAY);     // Set Day-of-Week to SUNDAY
+  //rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
+  //rtc.setDate(1, 1, 2014);   // Set the date to January 1st, 2014
+}
+
+void loop()
+{
+  // Get data from the DS3231
+  t = rtc.getTime();
+  
+  // Send date over serial connection
+  Serial.print("Today is the ");
+  Serial.print(t.date, DEC);
+  Serial.print(". day of ");
+  Serial.print(rtc.getMonthStr());
+  Serial.print(" in the year ");
+  Serial.print(t.year, DEC);
+  Serial.println(".");
+  
+  // Send Day-of-Week and time
+  Serial.print("It is the ");
+  Serial.print(t.dow, DEC);
+  Serial.print(". day of the week (counting monday as the 1th), and it has passed ");
+  Serial.print(t.hour, DEC);
+  Serial.print(" hour(s), ");
+  Serial.print(t.min, DEC);
+  Serial.print(" minute(s) and ");
+  Serial.print(t.sec, DEC);
+  Serial.println(" second(s) since midnight.");
+
+  // Send a divider for readability
+  Serial.println("  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -");
+  
+  // Wait one second before repeating :)
+  delay (1000);
+}

+ 52 - 0
lib/DS3231/examples/chipKit/DS3231_Temperature/DS3231_Temperature.pde

@@ -0,0 +1,52 @@
+// DS3231_Temperature
+// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
+// web: http://www.RinkyDinkElectronics.com/
+//
+// A quick demo of how to use my DS3231-library to 
+// quickly send the current temperature over a serial link
+//
+// To use the hardware I2C (TWI) interface of the chipKit you must connect
+// the pins as follows:
+//
+// chipKit Uno32/uC32:
+// ----------------------
+// DS3231:  SDA pin   -> Analog 4
+//          SCL pin   -> Analog 5
+// *** Please note that JP6 and JP8 must be in the I2C position (closest to the analog pins)
+//
+// chipKit Max32:
+// ----------------------
+// DS3231:  SDA pin   -> Digital 20 (the pin labeled SDA)
+//          SCL pin   -> Digital 21 (the pin labeled SCL)
+//
+// The chipKit boards does not have pull-up resistors on the hardware I2C interface
+// so external pull-up resistors on the data and clock signals are required.
+//
+// You can connect the DS3231 to any available pin but if you use any
+// other than what is described above the library will fall back to
+// a software-based, TWI-like protocol which will require exclusive access 
+// to the pins used.
+//
+
+#include <DS3231.h>
+
+// Init the DS3231 using the hardware interface
+DS3231  rtc(SDA, SCL);
+
+void setup()
+{
+  // Setup Serial connection
+  Serial.begin(115200);
+
+  // Initialize the rtc object
+  rtc.begin();
+}
+
+void loop()
+{
+  // Send current temperature
+  Serial.print("Temperature: ");
+  Serial.print(rtc.getTemp());
+  Serial.println(" C");
+  delay (1000);
+}

+ 75 - 0
lib/DS3231/examples/chipKit/DS3231_UnixTime/DS3231_UnixTime.pde

@@ -0,0 +1,75 @@
+// DS3231_UnixTime
+// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
+// web: http://www.RinkyDinkElectronics.com/
+//
+// A quick demo of how to use my DS3231-library to 
+// convert date and time to UnixTime
+//
+// To use the hardware I2C (TWI) interface of the chipKit you must connect
+// the pins as follows:
+//
+// chipKit Uno32/uC32:
+// ----------------------
+// DS3231:  SDA pin   -> Analog 4
+//          SCL pin   -> Analog 5
+// *** Please note that JP6 and JP8 must be in the I2C position (closest to the analog pins)
+//
+// chipKit Max32:
+// ----------------------
+// DS3231:  SDA pin   -> Digital 20 (the pin labeled SDA)
+//          SCL pin   -> Digital 21 (the pin labeled SCL)
+//
+// The chipKit boards does not have pull-up resistors on the hardware I2C interface
+// so external pull-up resistors on the data and clock signals are required.
+//
+// You can connect the DS3231 to any available pin but if you use any
+// other than what is described above the library will fall back to
+// a software-based, TWI-like protocol which will require exclusive access 
+// to the pins used.
+//
+
+#include <DS3231.h>
+
+// Init the DS3231 using the hardware interface
+DS3231  rtc(SDA, SCL);
+
+Time t;
+
+void setup()
+{
+  // Setup Serial connection
+  Serial.begin(115200);
+
+  // Initialize the rtc object
+  rtc.begin();
+}
+
+void loop()
+{
+  // Send Current time
+  Serial.print("Current Time.............................: ");
+  Serial.print(rtc.getDOWStr());
+  Serial.print(" ");
+  Serial.print(rtc.getDateStr());
+  Serial.print(" -- ");
+  Serial.println(rtc.getTimeStr());
+
+  // Send Unixtime
+  // ** Note that there may be a one second difference between the current time **
+  // ** and current unixtime show if the second changes between the two calls   **
+  Serial.print("Current Unixtime.........................: ");
+  Serial.println(rtc.getUnixTime(rtc.getTime()));
+  
+  // Send Unixtime for 00:00:00 on January 1th 2014
+  Serial.print("Unixtime for 00:00:00 on January 1th 2014: ");
+  t.hour = 0;
+  t.min = 0;
+  t.sec = 0;
+  t.year = 2014;
+  t.mon = 1;
+  t.date = 1;
+  Serial.println(rtc.getUnixTime(t));
+
+  // Wait indefinitely
+  while (1) {};
+}

+ 154 - 0
lib/DS3231/hardware/arm/HW_ARM.h

@@ -0,0 +1,154 @@
+void DS3231::begin()
+{
+	_use_hw = false;
+	if ((_sda_pin == SDA) and (_scl_pin == SCL))
+	{
+		_use_hw = true;
+		twi = TWI1;
+		pmc_enable_periph_clk(WIRE_INTERFACE_ID);
+		PIO_Configure(g_APinDescription[PIN_WIRE_SDA].pPort, g_APinDescription[PIN_WIRE_SDA].ulPinType, g_APinDescription[PIN_WIRE_SDA].ulPin, g_APinDescription[PIN_WIRE_SDA].ulPinConfiguration);
+		PIO_Configure(g_APinDescription[PIN_WIRE_SCL].pPort, g_APinDescription[PIN_WIRE_SCL].ulPinType, g_APinDescription[PIN_WIRE_SCL].ulPin, g_APinDescription[PIN_WIRE_SCL].ulPinConfiguration);
+		NVIC_DisableIRQ(TWI1_IRQn);
+		NVIC_ClearPendingIRQ(TWI1_IRQn);
+		NVIC_SetPriority(TWI1_IRQn, 0);
+		NVIC_EnableIRQ(TWI1_IRQn);
+
+	}
+	else if ((_sda_pin == SDA1) and (_scl_pin == SCL1))
+	{
+		_use_hw = true;
+		twi = TWI0;
+		pmc_enable_periph_clk(WIRE1_INTERFACE_ID);
+		PIO_Configure(g_APinDescription[PIN_WIRE1_SDA].pPort, g_APinDescription[PIN_WIRE1_SDA].ulPinType, g_APinDescription[PIN_WIRE1_SDA].ulPin, g_APinDescription[PIN_WIRE1_SDA].ulPinConfiguration);
+		PIO_Configure(g_APinDescription[PIN_WIRE1_SCL].pPort, g_APinDescription[PIN_WIRE1_SCL].ulPinType, g_APinDescription[PIN_WIRE1_SCL].ulPin, g_APinDescription[PIN_WIRE1_SCL].ulPinConfiguration);
+		NVIC_DisableIRQ(TWI0_IRQn);
+		NVIC_ClearPendingIRQ(TWI0_IRQn);
+		NVIC_SetPriority(TWI0_IRQn, 0);
+		NVIC_EnableIRQ(TWI0_IRQn);
+	}
+
+	if (_use_hw)
+	{
+		// activate internal pullups for twi.
+		digitalWrite(SDA, 1);
+		digitalWrite(SCL, 1);
+
+		// Reset the TWI
+		twi->TWI_CR = TWI_CR_SWRST;
+		// TWI Slave Mode Disabled, TWI Master Mode Disabled.
+		twi->TWI_CR = TWI_CR_SVDIS;
+		twi->TWI_CR = TWI_CR_MSDIS;
+		// Set TWI Speed
+		twi->TWI_CWGR = (TWI_DIV << 16) | (TWI_SPEED << 8) | TWI_SPEED;
+		// Set master mode
+		twi->TWI_CR = TWI_CR_MSEN;
+	}
+	else
+	{
+		pinMode(_scl_pin, OUTPUT);
+	}
+}
+
+void DS3231::_burstRead()
+{
+	if (_use_hw)
+	{
+		// Set slave address and number of internal address bytes.
+		twi->TWI_MMR = (1 << 8) | TWI_MMR_MREAD | (DS3231_ADDR << 16);
+		// Set internal address bytes
+		twi->TWI_IADR = 0;
+		// Send START condition
+		twi->TWI_CR = TWI_CR_START;
+
+		for (int i=0; i<6; i++)
+		{
+			while ((twi->TWI_SR & TWI_SR_RXRDY) != TWI_SR_RXRDY)
+			{
+			};
+			_burstArray[i] = twi->TWI_RHR;
+		}
+
+		twi->TWI_CR = TWI_CR_STOP;
+		while ((twi->TWI_SR & TWI_SR_RXRDY) != TWI_SR_RXRDY) {};
+		_burstArray[6] = twi->TWI_RHR;
+		while ((twi->TWI_SR & TWI_SR_TXCOMP) != TWI_SR_TXCOMP) {};
+	}
+	else
+	{
+		_sendStart(DS3231_ADDR_W);
+		_waitForAck();
+		_writeByte(0);
+		_waitForAck();
+		_sendStart(DS3231_ADDR_R);
+		_waitForAck();
+
+		for (int i=0; i<7; i++)
+		{
+			_burstArray[i] = _readByte();
+			if (i<6)
+				_sendAck();
+			else
+				_sendNack();
+		}
+		_sendStop();
+	}
+}
+
+uint8_t DS3231::_readRegister(uint8_t reg)
+{
+	uint8_t	readValue=0;
+
+	if (_use_hw)
+	{
+		// Set slave address and number of internal address bytes.
+		twi->TWI_MMR = (1 << 8) | TWI_MMR_MREAD | (DS3231_ADDR << 16);
+		// Set internal address bytes
+		twi->TWI_IADR = reg;
+		// Send START and STOP condition to read a single byte
+		twi->TWI_CR = TWI_CR_START | TWI_CR_STOP;
+		while ((twi->TWI_SR & TWI_SR_RXRDY) != TWI_SR_RXRDY) {};
+		readValue = twi->TWI_RHR;
+		while ((twi->TWI_SR & TWI_SR_TXCOMP) != TWI_SR_TXCOMP) {};
+	}
+	else
+	{
+		_sendStart(DS3231_ADDR_W);
+		_waitForAck();
+		_writeByte(reg);
+		_waitForAck();
+		_sendStart(DS3231_ADDR_R);
+		_waitForAck();
+		readValue = _readByte();
+		_sendNack();
+		_sendStop();
+	}
+	return readValue;
+}
+
+void DS3231::_writeRegister(uint8_t reg, uint8_t value)
+{
+	if (_use_hw)
+	{
+		// Set slave address and number of internal address bytes.
+		twi->TWI_MMR = (1 << 8) | (DS3231_ADDR << 16);
+		// Set internal address bytes
+		twi->TWI_IADR = reg;
+		// Send a single byte to start transfer
+		twi->TWI_THR = value;
+		while ((twi->TWI_SR & TWI_SR_TXRDY) != TWI_SR_TXRDY) {};
+		// Send STOP condition
+		twi->TWI_CR = TWI_CR_STOP;
+		while ((twi->TWI_SR & TWI_SR_TXCOMP) != TWI_SR_TXCOMP) {};
+	}
+	else
+	{
+		_sendStart(DS3231_ADDR_W);
+		_waitForAck();
+		_writeByte(reg);
+		_waitForAck();
+		_writeByte(value);
+		_waitForAck();
+		_sendStop();
+	}
+}
+

+ 13 - 0
lib/DS3231/hardware/arm/HW_ARM_defines.h

@@ -0,0 +1,13 @@
+// *** Hardwarespecific defines ***
+#define SDA		20
+#define SCL		21
+#define SDA1	70
+#define SCL1	71
+
+#define TWI_SPEED		TWI_SPEED_400k	// Set default TWI Speed
+#define TWI_SPEED_100k	208
+#define TWI_SPEED_400k	101
+
+#define TWI_DIV			TWI_DIV_400k	// Set divider for TWI Speed (must match TWI_SPEED setting)
+#define TWI_DIV_100k	1
+#define TWI_DIV_400k	0

+ 153 - 0
lib/DS3231/hardware/avr/HW_AVR.h

@@ -0,0 +1,153 @@
+void DS3231::begin()
+{
+	if ((_sda_pin == SDA) and (_scl_pin == SCL))
+	{
+		_use_hw = true;
+		// activate internal pullups for twi.
+		digitalWrite(SDA, HIGH);
+		digitalWrite(SCL, HIGH);
+		//delay(1);  // Workaround for a linker bug
+
+		// initialize twi prescaler and bit rate
+		cbi(TWSR, TWPS0);
+		cbi(TWSR, TWPS1);
+		TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
+
+		// enable twi module, acks, and twi interrupt
+		TWCR = _BV(TWEN) | _BV(TWIE)/* | _BV(TWEA)*/;
+	}
+	else
+	{
+		_use_hw = false;
+		pinMode(_scl_pin, OUTPUT);
+	}
+}
+
+void DS3231::_burstRead()
+{
+	if (_use_hw)
+	{
+		// Send start address
+		TWCR = _BV(TWEN) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);						// Send START
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		TWDR = DS3231_ADDR_W;
+		TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA);									// Clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		TWDR = 0;
+		TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA);									// Clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+
+		// Read data starting from start address
+		TWCR = _BV(TWEN) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);						// Send rep. START
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		TWDR = DS3231_ADDR_R;
+		TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA);									// Clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		for (int i=0; i<7; i++)
+		{
+			TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA);								// Send ACK and clear TWINT to proceed
+			while ((TWCR & _BV(TWINT)) == 0) {};									// Wait for TWI to be ready
+			_burstArray[i] = TWDR;
+		}
+		TWCR = _BV(TWEN) | _BV(TWINT);												// Send NACK and clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+
+		TWCR = _BV(TWEN)| _BV(TWINT) | _BV(TWSTO);									// Send STOP
+	}
+	else
+	{
+		_sendStart(DS3231_ADDR_W);
+		_waitForAck();
+		_writeByte(0);
+		_waitForAck();
+		_sendStart(DS3231_ADDR_R);
+		_waitForAck();
+
+		for (int i=0; i<7; i++)
+		{
+			_burstArray[i] = _readByte();
+			if (i<6)
+				_sendAck();
+			else
+				_sendNack();
+		}
+		_sendStop();
+	}
+}
+
+uint8_t DS3231::_readRegister(uint8_t reg)
+{
+	uint8_t	readValue=0;
+
+	if (_use_hw)
+	{
+		// Send start address
+		TWCR = _BV(TWEN) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);						// Send START
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		TWDR = DS3231_ADDR_W;
+		TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA);									// Clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		TWDR = reg;
+		TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA);									// Clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+
+		// Read data starting from start address
+		TWCR = _BV(TWEN) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);						// Send rep. START
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		TWDR = DS3231_ADDR_R;
+		TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA);									// Clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA);									// Send ACK and clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		readValue = TWDR;
+		TWCR = _BV(TWEN) | _BV(TWINT);												// Send NACK and clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+
+		TWCR = _BV(TWEN)| _BV(TWINT) | _BV(TWSTO);									// Send STOP
+	}
+	else
+	{
+		_sendStart(DS3231_ADDR_W);
+		_waitForAck();
+		_writeByte(reg);
+		_waitForAck();
+		_sendStart(DS3231_ADDR_R);
+		_waitForAck();
+		readValue = _readByte();
+		_sendNack();
+		_sendStop();
+	}
+	return readValue;
+}
+
+void DS3231::_writeRegister(uint8_t reg, uint8_t value)
+{
+	if (_use_hw)
+	{
+		// Send start address
+		TWCR = _BV(TWEN) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);						// Send START
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		TWDR = DS3231_ADDR_W;
+		TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA);									// Clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		TWDR = reg;
+		TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA);									// Clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+		TWDR = value;
+		TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA);									// Clear TWINT to proceed
+		while ((TWCR & _BV(TWINT)) == 0) {};										// Wait for TWI to be ready
+
+		TWCR = _BV(TWEN)| _BV(TWINT) | _BV(TWSTO);									// Send STOP
+	}
+	else
+	{
+		_sendStart(DS3231_ADDR_W);
+		_waitForAck();
+		_writeByte(reg);
+		_waitForAck();
+		_writeByte(value);
+		_waitForAck();
+		_sendStop();
+	}
+}
+

+ 6 - 0
lib/DS3231/hardware/avr/HW_AVR_defines.h

@@ -0,0 +1,6 @@
+// *** Hardwarespecific defines ***
+#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
+
+#ifndef TWI_FREQ
+	#define TWI_FREQ 400000L
+#endif

+ 192 - 0
lib/DS3231/hardware/pic32/HW_PIC32.h

@@ -0,0 +1,192 @@
+inline void _waitForIdleBus() { while (I2C1CON & 0x1f) {} }
+
+void DS3231::begin()
+{
+	if ((_sda_pin == SDA) and (_scl_pin == SCL))
+	{
+		uint32_t	tpgd;
+
+		_use_hw = true;
+		pinMode(SDA, OUTPUT);
+		digitalWrite(SDA, HIGH);
+		IFS0CLR = 0xE0000000;									// Clear Interrupt Flag
+		IEC0CLR = 0xE0000000;									// Disable Interrupt
+		I2C1CONCLR = (1 << _I2CCON_ON);							// Disable I2C interface
+		tpgd = ((F_CPU / 8) * 104) / 125000000;
+		I2C1BRG = (F_CPU / (2 * TWI_FREQ) - tpgd) - 2;			// Set I2C Speed
+		I2C1ADD = DS3231_ADDR;									// Set I2C device address
+		I2C1CONSET = (1 << _I2CCON_ON) | (1 << _I2CCON_STREN);	// Enable I2C Interface
+	}
+	else
+	{
+		_use_hw = false;
+		pinMode(_scl_pin, OUTPUT);
+	}
+}
+
+void DS3231::_burstRead()
+{
+	if (_use_hw)
+	{
+		_waitForIdleBus();									// Wait for I2C bus to be Idle before starting
+		I2C1CONSET = (1 << _I2CCON_SEN);					// Send start condition
+		if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return; }		// Check if there is a bus collision
+		while (I2C1CON & (1 << _I2CCON_SEN)) {}				// Wait for start condition to finish
+		I2C1TRN = (DS3231_ADDR<<1);							// Send device Write address
+		while (I2C1STAT & (1 << _I2CSTAT_IWCOL))			// Check if there is a Write collision
+		{
+			I2C1STATCLR = (1 << _I2CSTAT_IWCOL);			// Clear Write collision flag
+			I2C1TRN = (DS3231_ADDR<<1);						// Retry send device Write address
+		}
+		while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {}		// Wait for transmit to finish
+		while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {}		// Wait for ACK
+		I2C1TRN = 0;										// Send the register address
+		while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {}		// Wait for transmit to finish
+		while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {}		// Wait for ACK
+		_waitForIdleBus();									// Wait for I2C bus to be Idle before starting
+		I2C1CONSET = (1 << _I2CCON_RSEN);					// Send start condition
+		if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return; }		// Check if there is a bus collision
+		while (I2C1CON & (1 << _I2CCON_RSEN)) {}			// Wait for start condition to finish
+		I2C1TRN = (DS3231_ADDR<<1) | 1;						// Send device Read address
+		while (I2C1STAT & (1 << _I2CSTAT_IWCOL))			// Check if there is a Write collision
+		{
+			I2C1STATCLR = (1 << _I2CSTAT_IWCOL);			// Clear Write collision flag
+			I2C1TRN = (DS3231_ADDR<<1) | 1;					// Retry send device Read address
+		}
+		while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {}		// Wait for transmit to finish
+		while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {}		// Wait for ACK
+		byte dummy = I2C1RCV;								// Clear _I2CSTAT_RBF (Receive Buffer Full)
+		for (int i=0; i<7; i++)
+		{
+			_waitForIdleBus();								// Wait for I2C bus to be Idle before continuing
+			I2C1CONSET = (1 << _I2CCON_RCEN);				// Set RCEN to start receive
+			while (I2C1CON & (1 << _I2CCON_RCEN)) {}		// Wait for Receive operation to finish
+			while (!(I2C1STAT & (1 << _I2CSTAT_RBF))) {}	// Wait for Receive Buffer Full
+			_burstArray[i] = I2C1RCV;						// Read data
+			if (i == 6)
+				I2C1CONSET = (1 << _I2CCON_ACKDT);			// Prepare to send NACK
+			else
+				I2C1CONCLR = (1 << _I2CCON_ACKDT);			// Prepare to send ACK
+			I2C1CONSET = (1 << _I2CCON_ACKEN);				// Send ACK/NACK
+			while (I2C1CON & (1 << _I2CCON_ACKEN)) {}		// Wait for ACK/NACK send to finish
+		}
+		I2C1CONSET = (1 << _I2CCON_PEN);					// Send stop condition
+		while (I2C1CON & (1 << _I2CCON_PEN)) {}				// Wait for stop condition to finish
+	}
+	else
+	{
+		_sendStart(DS3231_ADDR_W);
+		_waitForAck();
+		_writeByte(0);
+		_waitForAck();
+		_sendStart(DS3231_ADDR_R);
+		_waitForAck();
+
+		for (int i=0; i<7; i++)
+		{
+			_burstArray[i] = _readByte();
+			if (i<6)
+				_sendAck();
+			else
+				_sendNack();
+		}
+		_sendStop();
+	}
+}
+
+uint8_t DS3231::_readRegister(uint8_t reg)
+{
+	uint8_t	readValue=0;
+
+	if (_use_hw)
+	{
+		_waitForIdleBus();									// Wait for I2C bus to be Idle before starting
+		I2C1CONSET = (1 << _I2CCON_SEN);					// Send start condition
+		if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return 0xff; }// Check if there is a bus collision
+		while (I2C1CON & (1 << _I2CCON_SEN)) {}				// Wait for start condition to finish
+		I2C1TRN = (DS3231_ADDR<<1);							// Send device Write address
+		while (I2C1STAT & (1 << _I2CSTAT_IWCOL))			// Check if there is a Write collision
+		{
+			I2C1STATCLR = (1 << _I2CSTAT_IWCOL);			// Clear Write collision flag
+			I2C1TRN = (DS3231_ADDR<<1);						// Retry send device Write address
+		}
+		while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {}		// Wait for transmit to finish
+		while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {}		// Wait for ACK
+		I2C1TRN = reg;										// Send the register address
+		while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {}		// Wait for transmit to finish
+		while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {}		// Wait for ACK
+		_waitForIdleBus();									// Wait for I2C bus to be Idle before starting
+		I2C1CONSET = (1 << _I2CCON_RSEN);					// Send start condition
+		if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return 0xff; }// Check if there is a bus collision
+		while (I2C1CON & (1 << _I2CCON_RSEN)) {}			// Wait for start condition to finish
+		I2C1TRN = (DS3231_ADDR<<1) | 1;						// Send device Read address
+		while (I2C1STAT & (1 << _I2CSTAT_IWCOL))			// Check if there is a Write collision
+		{
+			I2C1STATCLR = (1 << _I2CSTAT_IWCOL);			// Clear Write collision flag
+			I2C1TRN = (DS3231_ADDR<<1) | 1;					// Retry send device Read address
+		}
+		while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {}		// Wait for transmit to finish
+		while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {}		// Wait for ACK
+		byte dummy = I2C1RCV;								// Clear _I2CSTAT_RBF (Receive Buffer Full)
+		_waitForIdleBus();									// Wait for I2C bus to be Idle before continuing
+		I2C1CONSET = (1 << _I2CCON_RCEN);					// Set RCEN to start receive
+		while (I2C1CON & (1 << _I2CCON_RCEN)) {}			// Wait for Receive operation to finish
+		while (!(I2C1STAT & (1 << _I2CSTAT_RBF))) {}		// Wait for Receive Buffer Full
+		readValue = I2C1RCV;								// Read data
+		I2C1CONSET = (1 << _I2CCON_ACKDT);					// Prepare to send NACK
+		I2C1CONSET = (1 << _I2CCON_ACKEN);					// Send NACK
+		while (I2C1CON & (1 << _I2CCON_ACKEN)) {}			// Wait for NACK send to finish
+		I2C1CONSET = (1 << _I2CCON_PEN);					// Send stop condition
+		while (I2C1CON & (1 << _I2CCON_PEN)) {}				// Wait for stop condition to finish
+	}
+	else
+	{
+		_sendStart(DS3231_ADDR_W);
+		_waitForAck();
+		_writeByte(reg);
+		_waitForAck();
+		_sendStart(DS3231_ADDR_R);
+		_waitForAck();
+		readValue = _readByte();
+		_sendNack();
+		_sendStop();
+	}
+	return readValue;
+}
+
+void DS3231::_writeRegister(uint8_t reg, uint8_t value)
+{
+	if (_use_hw)
+	{
+		_waitForIdleBus();									// Wait for I2C bus to be Idle before starting
+		I2C1CONSET = (1 << _I2CCON_SEN);					// Send start condition
+		if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return; }		// Check if there is a bus collision
+		while (I2C1CON & (1 << _I2CCON_SEN)) {}				// Wait for start condition to finish
+		I2C1TRN = (DS3231_ADDR<<1);							// Send device Write address
+		while (I2C1STAT & (1 << _I2CSTAT_IWCOL))			// Check if there is a Write collision
+		{
+			I2C1STATCLR = (1 << _I2CSTAT_IWCOL);			// Clear Write collision flag
+			I2C1TRN = (DS3231_ADDR<<1);						// Retry send device Write address
+		}
+		while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {}		// Wait for transmit to finish
+		while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {}		// Wait for ACK
+		I2C1TRN = reg;										// Send the 1st data byte
+		while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {}		// Wait for transmit to finish
+		while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {}		// Wait for ACK
+		I2C1TRN = value;									// Send the 2nd data byte
+		while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {}		// Wait for transmit to finish
+		while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {}		// Wait for ACK
+		I2C1CONSET = (1 << _I2CCON_PEN);					// Send stop condition
+		while (I2C1CON & (1 << _I2CCON_PEN)) {}				// Wait for stop condition to finish
+	}
+	else
+	{
+		_sendStart(DS3231_ADDR_W);
+		_waitForAck();
+		_writeByte(reg);
+		_waitForAck();
+		_writeByte(value);
+		_waitForAck();
+		_sendStop();
+	}
+}

+ 21 - 0
lib/DS3231/hardware/pic32/HW_PIC32_defines.h

@@ -0,0 +1,21 @@
+// *** Hardwarespecific defines ***
+
+#if !defined(_UP_MCU_)
+	#if defined(__32MX320F128H__)
+		#define SDA	18					// A4 (Remeber to set the jumper correctly)
+		#define SCL	19					// A5 (Remeber to set the jumper correctly)
+	#elif defined(__32MX340F512H__)
+		#define SDA	18					// A4 (Remeber to set the jumper correctly)
+		#define SCL	19					// A5 (Remeber to set the jumper correctly)
+	#elif defined(__32MX795F512L__)
+		#define SDA	20					// Digital 20
+		#define SCL	21					// Digital 21
+	#else
+		#error "Unsupported PIC32 MCU!"
+	#endif  
+#endif
+
+#ifndef TWI_FREQ
+	#define TWI_FREQ 400000L
+#endif
+

+ 53 - 0
lib/DS3231/keywords.txt

@@ -0,0 +1,53 @@
+DS3231	KEYWORD1
+Time	KEYWORD1
+
+begin	KEYWORD2
+getTime	KEYWORD2
+setTime	KEYWORD2
+setDate	KEYWORD2
+setDOW	KEYWORD2
+getTimeStr	KEYWORD2
+getDateStr	KEYWORD2
+getDOWStr	KEYWORD2
+getMonthStr	KEYWORD2
+getUnixTime	KEYWORD2
+enable32KHz	KEYWORD2
+setOutput	KEYWORD2
+setSQWRate	KEYWORD2
+getTemp	KEYWORD2
+
+hour	KEYWORD2
+min	KEYWORD2
+sec	KEYWORD2
+date	KEYWORD2
+mon	KEYWORD2
+year	KEYWORD2
+dow	KEYWORD2
+
+FORMAT_SHORT	LITERAL1
+FORMAT_LONG	LITERAL1
+
+FORMAT_LITTLEENDIAN	LITERAL1
+FORMAT_BIGENDIAN	LITERAL1
+FORMAT_MIDDLEENDIAN	LITERAL1
+
+MONDAY	LITERAL1
+TUESDAY	LITERAL1
+WEDNESDAY	LITERAL1
+THURSDAY	LITERAL1
+FRIDAY	LITERAL1
+SATURDAY	LITERAL1
+SUNDAY	LITERAL1
+
+SQW_RATE_1	LITERAL1
+SQW_RATE_1K	LITERAL1
+SQW_RATE_4K	LITERAL1
+SQW_RATE_8K	LITERAL1
+
+OUTPUT_SQW	LITERAL1
+OUTPUT_INT	LITERAL1
+
+SDA	LITERAL1
+SCL	LITERAL1
+SDA1	LITERAL1
+SCL1	LITERAL1

+ 375 - 0
lib/calsol.h

@@ -0,0 +1,375 @@
+#ifndef CALSOL_H
+#define CALSOL_H
+/*
+ * Trouvé ici et exporté en CSV puis forgé par notepad++
+ * http://ptaff.ca/soleil/?l1pays=France&l1etat=Haute-Vienne&l1ville=Limoges&l2pays=&l2etat=&l1cityname=Limoges%2C+Haute-Vienne%2C+France&l1ltd=45&l1ltm=50&l1lts=07&l1ltx=N&l1lgd=1&l1lgm=15&l1lgs=45&l1lgx=E&l1tz=0.0&l1dst=&l2cityname=&l2ltd=&l2ltm=&l2lts=&l2ltx=N&l2lgd=&l2lgm=&l2lgs=&l2lgx=E&l2tz=0&l2dst=&year=2019&month=02&day=15&lang=fr_CA&go=Voir+le+graphe%21
+ * */
+const uint16_t DateSol_t[][9] ={
+    {2019, 1, 1, 7, 36, 16, 21, 8, 44},
+    {2019, 1, 2, 7, 36, 16, 22, 8, 45},
+    {2019, 1, 3, 7, 36, 16, 22, 8, 46},
+    {2019, 1, 4, 7, 36, 16, 23, 8, 47},
+    {2019, 1, 5, 7, 36, 16, 25, 8, 49},
+    {2019, 1, 6, 7, 36, 16, 26, 8, 50},
+    {2019, 1, 7, 7, 36, 16, 27, 8, 51},
+    {2019, 1, 8, 7, 35, 16, 28, 8, 52},
+    {2019, 1, 9, 7, 35, 16, 29, 8, 54},
+    {2019, 1, 10, 7, 35, 16, 30, 8, 55},
+    {2019, 1, 11, 7, 34, 16, 31, 8, 57},
+    {2019, 1, 12, 7, 34, 16, 32, 8, 59},
+    {2019, 1, 13, 7, 33, 16, 34, 9, 0},
+    {2019, 1, 14, 7, 33, 16, 35, 9, 2},
+    {2019, 1, 15, 7, 32, 16, 36, 9, 4},
+    {2019, 1, 16, 7, 32, 16, 37, 9, 6},
+    {2019, 1, 17, 7, 31, 16, 39, 9, 8},
+    {2019, 1, 18, 7, 30, 16, 40, 9, 10},
+    {2019, 1, 19, 7, 30, 16, 41, 9, 12},
+    {2019, 1, 20, 7, 29, 16, 43, 9, 14},
+    {2019, 1, 21, 7, 28, 16, 44, 9, 16},
+    {2019, 1, 22, 7, 27, 16, 46, 9, 18},
+    {2019, 1, 23, 7, 26, 16, 47, 9, 21},
+    {2019, 1, 24, 7, 25, 16, 48, 9, 23},
+    {2019, 1, 25, 7, 25, 16, 50, 9, 25},
+    {2019, 1, 26, 7, 24, 16, 51, 9, 28},
+    {2019, 1, 27, 7, 23, 16, 53, 9, 30},
+    {2019, 1, 28, 7, 21, 16, 54, 9, 33},
+    {2019, 1, 29, 7, 20, 16, 56, 9, 35},
+    {2019, 1, 30, 7, 19, 16, 57, 9, 38},
+    {2019, 1, 31, 7, 18, 16, 59, 9, 40},
+    {2019, 2, 1, 7, 17, 17, 0, 9, 43},
+    {2019, 2, 2, 7, 16, 17, 1, 9, 46},
+    {2019, 2, 3, 7, 14, 17, 3, 9, 48},
+    {2019, 2, 4, 7, 13, 17, 4, 9, 51},
+    {2019, 2, 5, 7, 12, 17, 6, 9, 54},
+    {2019, 2, 6, 7, 11, 17, 7, 9, 57},
+    {2019, 2, 7, 7, 9, 17, 9, 10, 0},
+    {2019, 2, 8, 7, 8, 17, 10, 10, 2},
+    {2019, 2, 9, 7, 6, 17, 12, 10, 5},
+    {2019, 2, 10, 7, 5, 17, 13, 10, 8},
+    {2019, 2, 11, 7, 4, 17, 15, 10, 11},
+    {2019, 2, 12, 7, 2, 17, 16, 10, 14},
+    {2019, 2, 13, 7, 1, 17, 18, 10, 17},
+    {2019, 2, 14, 6, 59, 17, 19, 10, 20},
+    {2019, 2, 15, 6, 57, 17, 21, 10, 23},
+    {2019, 2, 16, 6, 56, 17, 22, 10, 26},
+    {2019, 2, 17, 6, 54, 17, 24, 10, 29},
+    {2019, 2, 18, 6, 53, 17, 25, 10, 32},
+    {2019, 2, 19, 6, 51, 17, 26, 10, 35},
+    {2019, 2, 20, 6, 49, 17, 28, 10, 38},
+    {2019, 2, 21, 6, 48, 17, 29, 10, 42},
+    {2019, 2, 22, 6, 46, 17, 31, 10, 45},
+    {2019, 2, 23, 6, 44, 17, 32, 10, 48},
+    {2019, 2, 24, 6, 43, 17, 34, 10, 51},
+    {2019, 2, 25, 6, 41, 17, 35, 10, 54},
+    {2019, 2, 26, 6, 39, 17, 37, 10, 57},
+    {2019, 2, 27, 6, 37, 17, 38, 11, 0},
+    {2019, 2, 28, 6, 36, 17, 39, 11, 4},
+    {2019, 3, 1, 6, 34, 17, 41, 11, 7},
+    {2019, 3, 2, 6, 32, 17, 42, 11, 10},
+    {2019, 3, 3, 6, 30, 17, 44, 11, 13},
+    {2019, 3, 4, 6, 28, 17, 45, 11, 16},
+    {2019, 3, 5, 6, 27, 17, 46, 11, 20},
+    {2019, 3, 6, 6, 25, 17, 48, 11, 23},
+    {2019, 3, 7, 6, 23, 17, 49, 11, 26},
+    {2019, 3, 8, 6, 21, 17, 50, 11, 29},
+    {2019, 3, 9, 6, 19, 17, 52, 11, 33},
+    {2019, 3, 10, 6, 17, 17, 53, 11, 36},
+    {2019, 3, 11, 6, 15, 17, 55, 11, 39},
+    {2019, 3, 12, 6, 14, 17, 56, 11, 42},
+    {2019, 3, 13, 6, 12, 17, 57, 11, 46},
+    {2019, 3, 14, 6, 10, 17, 59, 11, 49},
+    {2019, 3, 15, 6, 8, 18, 0, 11, 52},
+    {2019, 3, 16, 6, 6, 18, 1, 11, 55},
+    {2019, 3, 17, 6, 4, 18, 3, 11, 59},
+    {2019, 3, 18, 6, 2, 18, 4, 12, 2},
+    {2019, 3, 19, 6, 0, 18, 5, 12, 5},
+    {2019, 3, 20, 5, 58, 18, 7, 12, 8},
+    {2019, 3, 21, 5, 56, 18, 8, 12, 12},
+    {2019, 3, 22, 5, 54, 18, 9, 12, 15},
+    {2019, 3, 23, 5, 52, 18, 11, 12, 18},
+    {2019, 3, 24, 5, 51, 18, 12, 12, 21},
+    {2019, 3, 25, 5, 49, 18, 13, 12, 25},
+    {2019, 3, 26, 5, 47, 18, 15, 12, 28},
+    {2019, 3, 27, 5, 45, 18, 16, 12, 31},
+    {2019, 3, 28, 5, 43, 18, 17, 12, 34},
+    {2019, 3, 29, 5, 41, 18, 19, 12, 38},
+    {2019, 3, 30, 5, 39, 18, 20, 12, 41},
+    {2019, 3, 31, 5, 37, 18, 21, 12, 44},
+    {2019, 4, 1, 5, 35, 18, 23, 12, 47},
+    {2019, 4, 2, 5, 33, 18, 24, 12, 51},
+    {2019, 4, 3, 5, 31, 18, 25, 12, 54},
+    {2019, 4, 4, 5, 30, 18, 26, 12, 57},
+    {2019, 4, 5, 5, 28, 18, 28, 13, 0},
+    {2019, 4, 6, 5, 26, 18, 29, 13, 3},
+    {2019, 4, 7, 5, 24, 18, 30, 13, 7},
+    {2019, 4, 8, 5, 22, 18, 32, 13, 10},
+    {2019, 4, 9, 5, 20, 18, 33, 13, 13},
+    {2019, 4, 10, 5, 18, 18, 34, 13, 16},
+    {2019, 4, 11, 5, 16, 18, 36, 13, 19},
+    {2019, 4, 12, 5, 15, 18, 37, 13, 22},
+    {2019, 4, 13, 5, 13, 18, 38, 13, 25},
+    {2019, 4, 14, 5, 11, 18, 40, 13, 29},
+    {2019, 4, 15, 5, 9, 18, 41, 13, 32},
+    {2019, 4, 16, 5, 7, 18, 42, 13, 35},
+    {2019, 4, 17, 5, 6, 18, 44, 13, 38},
+    {2019, 4, 18, 5, 4, 18, 45, 13, 41},
+    {2019, 4, 19, 5, 2, 18, 46, 13, 44},
+    {2019, 4, 20, 5, 0, 18, 47, 13, 47},
+    {2019, 4, 21, 4, 59, 18, 49, 13, 50},
+    {2019, 4, 22, 4, 57, 18, 50, 13, 53},
+    {2019, 4, 23, 4, 55, 18, 51, 13, 56},
+    {2019, 4, 24, 4, 54, 18, 53, 13, 59},
+    {2019, 4, 25, 4, 52, 18, 54, 14, 2},
+    {2019, 4, 26, 4, 50, 18, 55, 14, 5},
+    {2019, 4, 27, 4, 49, 18, 57, 14, 8},
+    {2019, 4, 28, 4, 47, 18, 58, 14, 11},
+    {2019, 4, 29, 4, 45, 18, 59, 14, 14},
+    {2019, 4, 30, 4, 44, 19, 0, 14, 16},
+    {2019, 5, 1, 4, 42, 19, 2, 14, 19},
+    {2019, 5, 2, 4, 41, 19, 3, 14, 22},
+    {2019, 5, 3, 4, 39, 19, 4, 14, 25},
+    {2019, 5, 4, 4, 38, 19, 6, 14, 28},
+    {2019, 5, 5, 4, 36, 19, 7, 14, 30},
+    {2019, 5, 6, 4, 35, 19, 8, 14, 33},
+    {2019, 5, 7, 4, 34, 19, 9, 14, 36},
+    {2019, 5, 8, 4, 32, 19, 11, 14, 38},
+    {2019, 5, 9, 4, 31, 19, 12, 14, 41},
+    {2019, 5, 10, 4, 30, 19, 13, 14, 44},
+    {2019, 5, 11, 4, 28, 19, 14, 14, 46},
+    {2019, 5, 12, 4, 27, 19, 16, 14, 49},
+    {2019, 5, 13, 4, 26, 19, 17, 14, 51},
+    {2019, 5, 14, 4, 25, 19, 18, 14, 53},
+    {2019, 5, 15, 4, 23, 19, 19, 14, 56},
+    {2019, 5, 16, 4, 22, 19, 20, 14, 58},
+    {2019, 5, 17, 4, 21, 19, 22, 15, 0},
+    {2019, 5, 18, 4, 20, 19, 23, 15, 3},
+    {2019, 5, 19, 4, 19, 19, 24, 15, 5},
+    {2019, 5, 20, 4, 18, 19, 25, 15, 7},
+    {2019, 5, 21, 4, 17, 19, 26, 15, 9},
+    {2019, 5, 22, 4, 16, 19, 27, 15, 11},
+    {2019, 5, 23, 4, 15, 19, 28, 15, 13},
+    {2019, 5, 24, 4, 14, 19, 29, 15, 15},
+    {2019, 5, 25, 4, 13, 19, 30, 15, 17},
+    {2019, 5, 26, 4, 12, 19, 31, 15, 19},
+    {2019, 5, 27, 4, 12, 19, 32, 15, 21},
+    {2019, 5, 28, 4, 11, 19, 33, 15, 22},
+    {2019, 5, 29, 4, 10, 19, 34, 15, 24},
+    {2019, 5, 30, 4, 10, 19, 35, 15, 26},
+    {2019, 5, 31, 4, 9, 19, 36, 15, 27},
+    {2019, 6, 1, 4, 8, 19, 37, 15, 29},
+    {2019, 6, 2, 4, 8, 19, 38, 15, 30},
+    {2019, 6, 3, 4, 7, 19, 39, 15, 32},
+    {2019, 6, 4, 4, 7, 19, 40, 15, 33},
+    {2019, 6, 5, 4, 6, 19, 40, 15, 34},
+    {2019, 6, 6, 4, 6, 19, 41, 15, 35},
+    {2019, 6, 7, 4, 6, 19, 42, 15, 36},
+    {2019, 6, 8, 4, 5, 19, 43, 15, 37},
+    {2019, 6, 9, 4, 5, 19, 43, 15, 38},
+    {2019, 6, 10, 4, 5, 19, 44, 15, 39},
+    {2019, 6, 11, 4, 5, 19, 45, 15, 40},
+    {2019, 6, 12, 4, 4, 19, 45, 15, 41},
+    {2019, 6, 13, 4, 4, 19, 46, 15, 41},
+    {2019, 6, 14, 4, 4, 19, 46, 15, 42},
+    {2019, 6, 15, 4, 4, 19, 47, 15, 43},
+    {2019, 6, 16, 4, 4, 19, 47, 15, 43},
+    {2019, 6, 17, 4, 4, 19, 47, 15, 43},
+    {2019, 6, 18, 4, 4, 19, 48, 15, 44},
+    {2019, 6, 19, 4, 4, 19, 48, 15, 44},
+    {2019, 6, 20, 4, 5, 19, 48, 15, 44},
+    {2019, 6, 21, 4, 5, 19, 49, 15, 44},
+    {2019, 6, 22, 4, 5, 19, 49, 15, 44},
+    {2019, 6, 23, 4, 5, 19, 49, 15, 44},
+    {2019, 6, 24, 4, 5, 19, 49, 15, 44},
+    {2019, 6, 25, 4, 6, 19, 49, 15, 43},
+    {2019, 6, 26, 4, 6, 19, 49, 15, 43},
+    {2019, 6, 27, 4, 7, 19, 49, 15, 43},
+    {2019, 6, 28, 4, 7, 19, 49, 15, 42},
+    {2019, 6, 29, 4, 8, 19, 49, 15, 42},
+    {2019, 6, 30, 4, 8, 19, 49, 15, 41},
+    {2019, 7, 1, 4, 9, 19, 49, 15, 40},
+    {2019, 7, 2, 4, 9, 19, 49, 15, 39},
+    {2019, 7, 3, 4, 10, 19, 48, 15, 39},
+    {2019, 7, 4, 4, 10, 19, 48, 15, 38},
+    {2019, 7, 5, 4, 11, 19, 48, 15, 37},
+    {2019, 7, 6, 4, 12, 19, 48, 15, 36},
+    {2019, 7, 7, 4, 13, 19, 47, 15, 35},
+    {2019, 7, 8, 4, 13, 19, 47, 15, 33},
+    {2019, 7, 9, 4, 14, 19, 46, 15, 32},
+    {2019, 7, 10, 4, 15, 19, 46, 15, 31},
+    {2019, 7, 11, 4, 16, 19, 45, 15, 29},
+    {2019, 7, 12, 4, 17, 19, 44, 15, 28},
+    {2019, 7, 13, 4, 18, 19, 44, 15, 26},
+    {2019, 7, 14, 4, 18, 19, 43, 15, 25},
+    {2019, 7, 15, 4, 19, 19, 42, 15, 23},
+    {2019, 7, 16, 4, 20, 19, 42, 15, 21},
+    {2019, 7, 17, 4, 21, 19, 41, 15, 20},
+    {2019, 7, 18, 4, 22, 19, 40, 15, 18},
+    {2019, 7, 19, 4, 23, 19, 39, 15, 16},
+    {2019, 7, 20, 4, 24, 19, 38, 15, 14},
+    {2019, 7, 21, 4, 25, 19, 37, 15, 12},
+    {2019, 7, 22, 4, 26, 19, 36, 15, 10},
+    {2019, 7, 23, 4, 27, 19, 35, 15, 8},
+    {2019, 7, 24, 4, 29, 19, 34, 15, 6},
+    {2019, 7, 25, 4, 30, 19, 33, 15, 4},
+    {2019, 7, 26, 4, 31, 19, 32, 15, 1},
+    {2019, 7, 27, 4, 32, 19, 31, 14, 59},
+    {2019, 7, 28, 4, 33, 19, 30, 14, 57},
+    {2019, 7, 29, 4, 34, 19, 29, 14, 55},
+    {2019, 7, 30, 4, 35, 19, 28, 14, 52},
+    {2019, 7, 31, 4, 36, 19, 26, 14, 50},
+    {2019, 8, 1, 4, 38, 19, 25, 14, 47},
+    {2019, 8, 2, 4, 39, 19, 24, 14, 45},
+    {2019, 8, 3, 4, 40, 19, 22, 14, 42},
+    {2019, 8, 4, 4, 41, 19, 21, 14, 40},
+    {2019, 8, 5, 4, 42, 19, 20, 14, 37},
+    {2019, 8, 6, 4, 44, 19, 18, 14, 35},
+    {2019, 8, 7, 4, 45, 19, 17, 14, 32},
+    {2019, 8, 8, 4, 46, 19, 15, 14, 29},
+    {2019, 8, 9, 4, 47, 19, 14, 14, 27},
+    {2019, 8, 10, 4, 48, 19, 12, 14, 24},
+    {2019, 8, 11, 4, 50, 19, 11, 14, 21},
+    {2019, 8, 12, 4, 51, 19, 9, 14, 18},
+    {2019, 8, 13, 4, 52, 19, 8, 14, 15},
+    {2019, 8, 14, 4, 53, 19, 6, 14, 13},
+    {2019, 8, 15, 4, 55, 19, 4, 14, 10},
+    {2019, 8, 16, 4, 56, 19, 3, 14, 7},
+    {2019, 8, 17, 4, 57, 19, 1, 14, 4},
+    {2019, 8, 18, 4, 58, 18, 59, 14, 1},
+    {2019, 8, 19, 5, 0, 18, 58, 13, 58},
+    {2019, 8, 20, 5, 1, 18, 56, 13, 55},
+    {2019, 8, 21, 5, 2, 18, 54, 13, 52},
+    {2019, 8, 22, 5, 3, 18, 53, 13, 49},
+    {2019, 8, 23, 5, 4, 18, 51, 13, 46},
+    {2019, 8, 24, 5, 6, 18, 49, 13, 43},
+    {2019, 8, 25, 5, 7, 18, 47, 13, 40},
+    {2019, 8, 26, 5, 8, 18, 45, 13, 37},
+    {2019, 8, 27, 5, 9, 18, 44, 13, 34},
+    {2019, 8, 28, 5, 11, 18, 42, 13, 31},
+    {2019, 8, 29, 5, 12, 18, 40, 13, 28},
+    {2019, 8, 30, 5, 13, 18, 38, 13, 25},
+    {2019, 8, 31, 5, 14, 18, 36, 13, 22},
+    {2019, 9, 1, 5, 16, 18, 34, 13, 19},
+    {2019, 9, 2, 5, 17, 18, 33, 13, 16},
+    {2019, 9, 3, 5, 18, 18, 31, 13, 13},
+    {2019, 9, 4, 5, 19, 18, 29, 13, 10},
+    {2019, 9, 5, 5, 21, 18, 27, 13, 6},
+    {2019, 9, 6, 5, 22, 18, 25, 13, 3},
+    {2019, 9, 7, 5, 23, 18, 23, 13, 0},
+    {2019, 9, 8, 5, 24, 18, 21, 12, 57},
+    {2019, 9, 9, 5, 25, 18, 19, 12, 54},
+    {2019, 9, 10, 5, 27, 18, 17, 12, 51},
+    {2019, 9, 11, 5, 28, 18, 15, 12, 47},
+    {2019, 9, 12, 5, 29, 18, 13, 12, 44},
+    {2019, 9, 13, 5, 30, 18, 12, 12, 41},
+    {2019, 9, 14, 5, 32, 18, 10, 12, 38},
+    {2019, 9, 15, 5, 33, 18, 8, 12, 35},
+    {2019, 9, 16, 5, 34, 18, 6, 12, 32},
+    {2019, 9, 17, 5, 35, 18, 4, 12, 28},
+    {2019, 9, 18, 5, 37, 18, 2, 12, 25},
+    {2019, 9, 19, 5, 38, 18, 0, 12, 22},
+    {2019, 9, 20, 5, 39, 17, 58, 12, 19},
+    {2019, 9, 21, 5, 40, 17, 56, 12, 16},
+    {2019, 9, 22, 5, 42, 17, 54, 12, 12},
+    {2019, 9, 23, 5, 43, 17, 52, 12, 9},
+    {2019, 9, 24, 5, 44, 17, 50, 12, 6},
+    {2019, 9, 25, 5, 45, 17, 48, 12, 3},
+    {2019, 9, 26, 5, 47, 17, 46, 12, 0},
+    {2019, 9, 27, 5, 48, 17, 44, 11, 56},
+    {2019, 9, 28, 5, 49, 17, 42, 11, 53},
+    {2019, 9, 29, 5, 50, 17, 40, 11, 50},
+    {2019, 9, 30, 5, 52, 17, 38, 11, 47},
+    {2019, 10, 1, 5, 53, 17, 36, 11, 43},
+    {2019, 10, 2, 5, 54, 17, 35, 11, 40},
+    {2019, 10, 3, 5, 55, 17, 33, 11, 37},
+    {2019, 10, 4, 5, 57, 17, 31, 11, 34},
+    {2019, 10, 5, 5, 58, 17, 29, 11, 31},
+    {2019, 10, 6, 5, 59, 17, 27, 11, 28},
+    {2019, 10, 7, 6, 1, 17, 25, 11, 24},
+    {2019, 10, 8, 6, 2, 17, 23, 11, 21},
+    {2019, 10, 9, 6, 3, 17, 21, 11, 18},
+    {2019, 10, 10, 6, 5, 17, 19, 11, 15},
+    {2019, 10, 11, 6, 6, 17, 18, 11, 12},
+    {2019, 10, 12, 6, 7, 17, 16, 11, 8},
+    {2019, 10, 13, 6, 9, 17, 14, 11, 5},
+    {2019, 10, 14, 6, 10, 17, 12, 11, 2},
+    {2019, 10, 15, 6, 11, 17, 10, 10, 59},
+    {2019, 10, 16, 6, 13, 17, 9, 10, 56},
+    {2019, 10, 17, 6, 14, 17, 7, 10, 53},
+    {2019, 10, 18, 6, 15, 17, 5, 10, 50},
+    {2019, 10, 19, 6, 17, 17, 3, 10, 47},
+    {2019, 10, 20, 6, 18, 17, 2, 10, 44},
+    {2019, 10, 21, 6, 19, 17, 0, 10, 40},
+    {2019, 10, 22, 6, 21, 16, 58, 10, 37},
+    {2019, 10, 23, 6, 22, 16, 56, 10, 34},
+    {2019, 10, 24, 6, 24, 16, 55, 10, 31},
+    {2019, 10, 25, 6, 25, 16, 53, 10, 28},
+    {2019, 10, 26, 6, 26, 16, 52, 10, 25},
+    {2019, 10, 27, 6, 28, 16, 50, 10, 22},
+    {2019, 10, 28, 6, 29, 16, 48, 10, 19},
+    {2019, 10, 29, 6, 30, 16, 47, 10, 16},
+    {2019, 10, 30, 6, 32, 16, 45, 10, 13},
+    {2019, 10, 31, 6, 33, 16, 44, 10, 10},
+    {2019, 11, 1, 6, 35, 16, 42, 10, 8},
+    {2019, 11, 2, 6, 36, 16, 41, 10, 5},
+    {2019, 11, 3, 6, 38, 16, 39, 10, 2},
+    {2019, 11, 4, 6, 39, 16, 38, 9, 59},
+    {2019, 11, 5, 6, 40, 16, 37, 9, 56},
+    {2019, 11, 6, 6, 42, 16, 35, 9, 53},
+    {2019, 11, 7, 6, 43, 16, 34, 9, 51},
+    {2019, 11, 8, 6, 45, 16, 33, 9, 48},
+    {2019, 11, 9, 6, 46, 16, 31, 9, 45},
+    {2019, 11, 10, 6, 47, 16, 30, 9, 43},
+    {2019, 11, 11, 6, 49, 16, 29, 9, 40},
+    {2019, 11, 12, 6, 50, 16, 28, 9, 37},
+    {2019, 11, 13, 6, 52, 16, 27, 9, 35},
+    {2019, 11, 14, 6, 53, 16, 26, 9, 32},
+    {2019, 11, 15, 6, 54, 16, 24, 9, 30},
+    {2019, 11, 16, 6, 56, 16, 23, 9, 28},
+    {2019, 11, 17, 6, 57, 16, 22, 9, 25},
+    {2019, 11, 18, 6, 59, 16, 21, 9, 23},
+    {2019, 11, 19, 7, 0, 16, 21, 9, 20},
+    {2019, 11, 20, 7, 1, 16, 20, 9, 18},
+    {2019, 11, 21, 7, 3, 16, 19, 9, 16},
+    {2019, 11, 22, 7, 4, 16, 18, 9, 14},
+    {2019, 11, 23, 7, 5, 16, 17, 9, 12},
+    {2019, 11, 24, 7, 7, 16, 16, 9, 10},
+    {2019, 11, 25, 7, 8, 16, 16, 9, 8},
+    {2019, 11, 26, 7, 9, 16, 15, 9, 6},
+    {2019, 11, 27, 7, 10, 16, 14, 9, 4},
+    {2019, 11, 28, 7, 12, 16, 14, 9, 2},
+    {2019, 11, 29, 7, 13, 16, 13, 9, 0},
+    {2019, 11, 30, 7, 14, 16, 13, 8, 59},
+    {2019, 12, 1, 7, 15, 16, 12, 8, 57},
+    {2019, 12, 2, 7, 17, 16, 12, 8, 55},
+    {2019, 12, 3, 7, 18, 16, 12, 8, 54},
+    {2019, 12, 4, 7, 19, 16, 11, 8, 52},
+    {2019, 12, 5, 7, 20, 16, 11, 8, 51},
+    {2019, 12, 6, 7, 21, 16, 11, 8, 50},
+    {2019, 12, 7, 7, 22, 16, 11, 8, 49},
+    {2019, 12, 8, 7, 23, 16, 10, 8, 47},
+    {2019, 12, 9, 7, 24, 16, 10, 8, 46},
+    {2019, 12, 10, 7, 25, 16, 10, 8, 45},
+    {2019, 12, 11, 7, 26, 16, 10, 8, 45},
+    {2019, 12, 12, 7, 27, 16, 10, 8, 44},
+    {2019, 12, 13, 7, 28, 16, 10, 8, 43},
+    {2019, 12, 14, 7, 28, 16, 11, 8, 42},
+    {2019, 12, 15, 7, 29, 16, 11, 8, 42},
+    {2019, 12, 16, 7, 30, 16, 11, 8, 41},
+    {2019, 12, 17, 7, 31, 16, 11, 8, 41},
+    {2019, 12, 18, 7, 31, 16, 12, 8, 40},
+    {2019, 12, 19, 7, 32, 16, 12, 8, 40},
+    {2019, 12, 20, 7, 32, 16, 12, 8, 40},
+    {2019, 12, 21, 7, 33, 16, 13, 8, 40},
+    {2019, 12, 22, 7, 33, 16, 13, 8, 40},
+    {2019, 12, 23, 7, 34, 16, 14, 8, 40},
+    {2019, 12, 24, 7, 34, 16, 14, 8, 40},
+    {2019, 12, 25, 7, 35, 16, 15, 8, 40},
+    {2019, 12, 26, 7, 35, 16, 16, 8, 41},
+    {2019, 12, 27, 7, 35, 16, 16, 8, 41},
+    {2019, 12, 28, 7, 36, 16, 17, 8, 41},
+    {2019, 12, 29, 7, 36, 16, 18, 8, 42},
+    {2019, 12, 30, 7, 36, 16, 19, 8, 43},
+    {2019, 12, 31, 7, 36, 16, 20, 8, 43}
+};
+
+#endif // CALSOL_H

+ 76 - 0
src/sketch.ino

@@ -0,0 +1,76 @@
+// Arduino Uno/2009:
+// ----------------------
+// DS3231:  SDA pin   -> Arduino Digital 4 or the dedicated SDA pin
+//          SCL pin   -> Arduino Digital 5 or the dedicated SCL pin
+
+
+#include <Stepper.h>
+#include <DS3231.h>
+
+#include "../lib/calsol.h"
+
+// Pour steppers
+#define STEP_REV 400
+#define REV 10
+
+const int stepsPerRevolution = 400;
+// 360 / 0.9deg
+
+Stepper myStepper1(stepsPerRevolution, 6, 7, 8, 9);
+Stepper myStepper2(stepsPerRevolution, 2, 3, 4, 5);
+
+// Module DS3231 pour l'heure
+DS3231  rtc(4, 5);
+
+struct Date_t {
+        unsigned long annee;
+        unsigned long mois;
+        unsigned long jour;
+};
+
+
+void stepperOff() {
+  for(int i=2; i<=9; i++) {
+    digitalWrite(i, LOW);  
+  }
+}
+
+
+void setup() {
+  Serial.begin(115200);
+  rtc.begin();  
+  // The following lines can be uncommented to set the date and time
+
+  /*  rtc.setDOW(THURSDAY);     // Set Day-of-Week to SUNDAY
+      rtc.setTime(22, 14, 0);     // Set the time to 12:00:00 (24hr format)
+      rtc.setDate(4, 11, 2019);   // Set the date to January 1st, 2014 */
+
+}
+
+void loop() {
+  myStepper2.setSpeed(100);
+  for(int i=0; i<=STEP_REV*REV; i++) {
+      myStepper1.step(1);
+      myStepper2.step(-1);
+  }
+  for(int i=0; i<=STEP_REV*REV; i++) {
+      myStepper1.step(-1);
+      myStepper2.step(1);
+  }
+  stepperOff();
+  delay(3000);
+
+ // Send Day-of-Week
+  Serial.print(rtc.getDOWStr());
+  Serial.print(" ");
+  
+  // Send date
+  Serial.print(rtc.getDateStr());
+  Serial.print(" -- ");
+
+  // Send time
+  Serial.println(rtc.getTimeStr());
+  
+  // Wait one second before repeating :)
+  delay (1000);
+}