1////////////////////////////////////////////////////////////////////////////////
2// //
3// This software is supplied under the terms of a license agreement or //
4// nondisclosure agreement with Mitov Software and may not be copied //
5// or disclosed except in accordance with the terms of that agreement. //
6// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. //
7// //
8////////////////////////////////////////////////////////////////////////////////
9
10#ifndef _MITOV_RTC_DS3231_h
11#define _MITOV_RTC_DS3231_h
12
13#include <Mitov.h>
14#include <Mitov_Basic_RTC.h>
15
16namespace Mitov
17{
18//---------------------------------------------------------------------------
19// enum DS3231ClockFrequency { rtc3231fDisabled, rtc3231f1Hz, rtc3231f1024Hz, rtc3231f4096Hz, rtc3231f8192Hz };
20//---------------------------------------------------------------------------
21 class RTC_DS3231 : public BasicHaltRTC
22 {
23 typedef BasicHaltRTC inherited;
24
25 enum Register
26 {
27 kSecondReg = 0,
28 kMinuteReg = 1,
29 kHourReg = 2,
30 kDayReg = 3,
31 kDateReg = 4,
32 kMonthReg = 5,
33 kYearReg = 6,
34 kControlReg = 0xE
35// kClockReg = 7,
36
37 // The RAM register space follows the clock register space.
38// kRamAddress0 = 8
39 };
40
41 const uint8_t DS3231_ADDRESS = 0x68;
42
43 protected:
44 Mitov::TDateTime FLastDateTime;
45
46 protected:
47 uint8_t readRegister(const uint8_t reg)
48 {
49 Wire.beginTransmission(DS3231_ADDRESS);
50 Wire.write( reg );
51 Wire.endTransmission();
52
53 Wire.requestFrom(DS3231_ADDRESS, (uint8_t)1 );
54
55 return Wire.read();
56 }
57
58 void writeRegister( const uint8_t reg, const uint8_t value )
59 {
60 Wire.beginTransmission(DS3231_ADDRESS);
61 Wire.write( reg );
62 Wire.write( value );
63 Wire.endTransmission();
64 }
65
66 uint8_t hourFromRegisterValue(const uint8_t value)
67 {
68 uint8_t adj;
69 if (value & 128) // 12-hour mode
70 adj = 12 * ((value & 32) >> 5);
71
72 else // 24-hour mode
73 adj = 10 * ((value & (32 + 16)) >> 4);
74
75 return (value & 15) + adj;
76 }
77
78 virtual void ReadTime()
79 {
80 if( ! OutputPin.IsConnected() )
81 return;
82
83 Wire.beginTransmission(DS3231_ADDRESS);
84 Wire.write((byte)0);
85 Wire.endTransmission();
86
87 Wire.requestFrom(DS3231_ADDRESS, (byte)7);
88 uint16_t ASecond = FromBcdToDec(Wire.read() & 0x7F);
89 uint16_t AMinute = FromBcdToDec(Wire.read());
90 uint16_t AHour = hourFromRegisterValue( Wire.read() );
91 uint16_t ADay = Wire.read();
92 uint16_t ADate = FromBcdToDec(Wire.read());
93 uint16_t AMonth = FromBcdToDec(Wire.read());
94 uint16_t AYear = FromBcdToDec(Wire.read()) + 2000;
95
96 Mitov::TDateTime ADateTime;
97
98 if( ADateTime.TryEncodeDateTime( AYear, AMonth, ADate, AHour, AMinute, ASecond, 0 ))
99 {
100 if( FLastDateTime != ADateTime )
101 {
102 FLastDateTime = ADateTime;
103 OutputPin.Notify( &ADateTime );
104 }
105 }
106
107 }
108
109 virtual void UpdateHalt()
110 {
111 uint8_t sec = readRegister( kSecondReg );
112
113 sec &= ~(1 << 7);
114 sec |= ( ( Halt & 1 ) << 7 );
115 writeRegister( kSecondReg, sec );
116 }
117
118/*
119 void UpdateClockFrequency()
120 {
121 const uint8_t CValues [] = { 0x00, 0x80, 0x40, 0x41, 0x42, 0x43 };
122
123 uint8_t AValue = readRegister( kControlReg );
124
125 sec &= ~(1 << 7);
126 sec |= ( ( Halt & 1 ) << 7 );
127 writeRegister( kSecondReg, sec );
128
129 writeRegister( kControlReg, CValues[ ClockFrequency ] );
130 }
131*/
132 protected:
133 virtual void DoSetReceive( void *_Data )
134 {
135 Mitov::TDateTime &ADateTime = *(Mitov::TDateTime *)_Data;
136
137 uint16_t AYear;
138 uint16_t AMonth;
139 uint16_t ADay;
140 uint16_t AWeekDay;
141 uint16_t AHour;
142 uint16_t AMinute;
143 uint16_t ASecond;
144 uint16_t AMilliSecond;
145 ADateTime.DecodeDateTime( AYear, AMonth, ADay, AWeekDay, AHour, AMinute, ASecond, AMilliSecond );
146
147 Wire.beginTransmission(DS3231_ADDRESS);
148 Wire.write((byte)0); // start at location 0
149
150 Wire.write( ( ( Halt & 1 ) << 7 ) | FromDecToBcd( ASecond ));
151 Wire.write(FromDecToBcd( AMinute ));
152 Wire.write(FromDecToBcd( AHour ));
153 Wire.write(FromDecToBcd( AWeekDay ));
154 Wire.write(FromDecToBcd( ADay ));
155 Wire.write(FromDecToBcd( AMonth ));
156 Wire.write(FromDecToBcd( AYear - 2000));
157
158 Wire.endTransmission();
159 }
160
161 protected:
162 virtual void SystemInit()
163 {
164 UpdateHalt();
165// UpdateClockFrequency();
166 inherited::SystemInit();
167 }
168
169 public:
170 RTC_DS3231()// :
171// ClockFrequency( rtc3231fDisabled )
172 {
173 }
174 };
175}
176
177#endif