123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557 |
- /*
- 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_DATE 0x0a
- #define REG_ALARM2_MIN 0x0b
- #define REG_ALARM2_HOUR 0x0c
- #define REG_ALARM2_DATE 0x0d
- #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)
- {
- if (((hour>=0) && (hour<24)) && ((min>=0) && (min<60)))
- {
- min = _encode(min);
- hour = _encode(hour);
-
- uint8_t sec = 0x00;
- min = min &~ (1<<7);
- hour = hour &~ (1<<7);
- hour = hour &~ (1<<6);
- uint8_t date = 0x81;
- _writeRegister(REG_ALARM1_SEC, sec);
- _writeRegister(REG_ALARM1_MIN, min);
- _writeRegister(REG_ALARM1_HOUR, hour);
- _writeRegister(REG_ALARM1_DATE, date);
- }
- }
- char *DS3231::getAlarm1Str(uint8_t format)
- {
- static char output[] = "xx:xx:xx-xxxxxx";
- uint8_t sec = _readRegister(REG_ALARM1_SEC);
- uint8_t min = _readRegister(REG_ALARM1_MIN);
- uint8_t hour = _readRegister(REG_ALARM1_HOUR);
- uint8_t date = _readRegister(REG_ALARM1_DATE);
-
- // Formatage des bits de controle
- if((sec&(1<<7)) == 0)
- output[14] = 48;
- else
- output[14] = 49;
-
- if((min&(1<<7)) == 0)
- output[13] = 48;
- else
- output[13] = 49;
-
- if((hour&(1<<7)) == 0)
- output[12] = 48;
- else
- output[12] = 49;
-
- if((hour&(1<<6)) == 0)
- output[10] = 50;
- else
- output[10] = 49;
-
- if((date&(1<<7)) == 0)
- output[11] = 48;
- else
- output[11] = 49;
-
- if((date&(1<<6)) == 0)
- output[9] = 77;
- else
- output[9] = 87;
-
- //Fin formatage des bits de controle
-
-
- sec = _decode(sec);
- min = _decode(min);
- hour = _decode(hour);
-
- if (hour<10)
- output[0]=48; // "0" en ASCII
- else
- output[0]=char((hour / 10)+48);
-
-
- output[1]=char((hour % 10)+48);
-
- if (min<10)
- output[3]=48; // "0" en ASCII
- else
- output[3]=char((min / 10)+48);
-
- output[4]=char((min % 10)+48);
-
-
- output[6]=char((sec / 10)+48);
- output[7]=char((sec % 10)+48);
- output[16]=0;
-
- return (char*)&output;
- }
- void DS3231::setControl()
- {
- _writeRegister(REG_CON, 0x07);
- // Serial.print("set de la conf");
- }
- void DS3231::resetAlarm()
- {
- _writeRegister(REG_STATUS, 0x00);
- // Serial.print("reset de l'alarme");
- }
|