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_DS1307_h
11#define _MITOV_RTC_DS1307_h
12
13#include <Mitov.h>
14#include <Mitov_Basic_RTC.h>
15
16namespace Mitov
17{
18//---------------------------------------------------------------------------
19 enum DS1307ClockFrequency { rtc1307fDisabledLow, rtc1307fDisabledHigh, rtc1307f1Hz, rtc1307f4096Hz, rtc1307f8192Hz, rtc1307f32768Hz };
20//---------------------------------------------------------------------------
21 class RTC_DS1307 : 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 kClockReg = 7,
35
36 // The RAM register space follows the clock register space.
37 kRamAddress0 = 8
38 };
39
40 const uint8_t DS1307_ADDRESS = 0x68;
41
42 public:
43 DS1307ClockFrequency ClockFrequency : 3;
44
45 public:
46 void SetClockFrequency( DS1307ClockFrequency AValue )
47 {
48 if( ClockFrequency == AValue )
49 return;
50
51 ClockFrequency = AValue;
52 UpdateClockFrequency();
53 }
54
55 protected:
56 Mitov::TDateTime FLastDateTime;
57
58 protected:
59 uint8_t readRegister(const uint8_t reg)
60 {
61 Wire.beginTransmission(DS1307_ADDRESS);
62 Wire.write( reg );
63 Wire.endTransmission();
64
65 Wire.requestFrom(DS1307_ADDRESS, (uint8_t)1 );
66
67 return Wire.read();
68 }
69
70 void writeRegister( const uint8_t reg, const uint8_t value )
71 {
72 Wire.beginTransmission(DS1307_ADDRESS);
73 Wire.write( reg );
74 Wire.write( value );
75 Wire.endTransmission();
76 }
77
78 uint8_t hourFromRegisterValue(const uint8_t value)
79 {
80 uint8_t adj;
81 if (value & 128) // 12-hour mode
82 adj = 12 * ((value & 32) >> 5);
83
84 else // 24-hour mode
85 adj = 10 * ((value & (32 + 16)) >> 4);
86
87 return (value & 15) + adj;
88 }
89
90 void UpdateClockFrequency()
91 {
92 const uint8_t CValues [] = { 0x00, 0x80, 0x40, 0x41, 0x42, 0x43 };
93 writeRegister( kClockReg, CValues[ ClockFrequency ] );
94 }
95
96 virtual void ReadTime()
97 {
98 if( ! OutputPin.IsConnected() )
99 return;
100
101 Wire.beginTransmission(DS1307_ADDRESS);
102 Wire.write((byte)0);
103 Wire.endTransmission();
104
105 Wire.requestFrom(DS1307_ADDRESS, (byte)7);
106 uint16_t ASecond = FromBcdToDec(Wire.read() & 0x7F);
107 uint16_t AMinute = FromBcdToDec(Wire.read());
108 uint16_t AHour = hourFromRegisterValue( Wire.read() );
109 uint16_t ADay = Wire.read();
110 uint16_t ADate = FromBcdToDec(Wire.read());
111 uint16_t AMonth = FromBcdToDec(Wire.read());
112 uint16_t AYear = FromBcdToDec(Wire.read()) + 2000;
113
114 Mitov::TDateTime ADateTime;
115
116 if( ADateTime.TryEncodeDateTime( AYear, AMonth, ADate, AHour, AMinute, ASecond, 0 ))
117 {
118 if( FLastDateTime != ADateTime )
119 {
120 FLastDateTime = ADateTime;
121 OutputPin.Notify( &ADateTime );
122 }
123 }
124
125 }
126
127 virtual void UpdateHalt()
128 {
129 uint8_t sec = readRegister( kSecondReg );
130
131 sec &= ~(1 << 7);
132 sec |= ( ( Halt & 1 ) << 7 );
133 writeRegister( kSecondReg, sec );
134 }
135
136 protected:
137 virtual void DoSetReceive( void *_Data )
138 {
139// if( WriteProtect )
140// return;
141
142 Mitov::TDateTime &ADateTime = *(Mitov::TDateTime *)_Data;
143
144 uint16_t AYear;
145 uint16_t AMonth;
146 uint16_t ADay;
147 uint16_t AWeekDay;
148 uint16_t AHour;
149 uint16_t AMinute;
150 uint16_t ASecond;
151 uint16_t AMilliSecond;
152 ADateTime.DecodeDateTime( AYear, AMonth, ADay, AWeekDay, AHour, AMinute, ASecond, AMilliSecond );
153
154 Wire.beginTransmission(DS1307_ADDRESS);
155 Wire.write((byte)0); // start at location 0
156
157 Wire.write( ( ( Halt & 1 ) << 7 ) | FromDecToBcd( ASecond ));
158 Wire.write(FromDecToBcd( AMinute ));
159 Wire.write(FromDecToBcd( AHour ));
160 Wire.write(FromDecToBcd( AWeekDay ));
161 Wire.write(FromDecToBcd( ADay ));
162 Wire.write(FromDecToBcd( AMonth ));
163 Wire.write(FromDecToBcd( AYear - 2000));
164
165 Wire.endTransmission();
166 }
167
168 protected:
169 virtual void SystemInit()
170 {
171 UpdateHalt();
172 UpdateClockFrequency();
173 inherited::SystemInit();
174 }
175
176 public:
177 RTC_DS1307() :
178 ClockFrequency( rtc1307fDisabledLow )
179 {
180 }
181 };
182}
183
184#endif