Skip to content

Commit 11db028

Browse files
authored
Ds1302 real-time clock library (#547)
* Added separate Ds1302 solution * Fixed magic numbers * nuspec fixes * fix stylecop issues * pr comments resolving * PR comments resolving * PR comments resolving * Fix for communication enabled pin * Added missing files * Update version.json * PR fixes Co-authored-by: Rafał <Kałwak>
1 parent 2b7a635 commit 11db028

19 files changed

+686
-7
lines changed

Diff for: devices/Ds1302/Ds1302.cs

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Device;
6+
using System.Device.Gpio;
7+
using System.Device.Model;
8+
using Iot.Device.Common;
9+
10+
namespace Iot.Device.Rtc
11+
{
12+
/// <summary>
13+
/// Realtime Clock Ds1302.
14+
/// </summary>
15+
[Interface("Realtime Clock Ds1302")]
16+
public class Ds1302 : RtcBase
17+
{
18+
private readonly GpioPin _clockPin;
19+
private readonly GpioPin _communicationEnabledPin;
20+
private readonly GpioPin _dataPin;
21+
private readonly byte enableWrite = 0b1000_0000;
22+
private readonly byte disableWrite = 0b0000_0000;
23+
private readonly byte enableWriteOrRead = 0b1000_0001;
24+
private readonly bool _shouldDispose;
25+
private PinMode _currentDataPinDirection;
26+
private GpioController _controller;
27+
28+
/// <summary>
29+
/// Initializes a new instance of the <see cref="Ds1302"/> class.
30+
/// </summary>
31+
/// <param name="clockPin">Clock pin number.</param>
32+
/// <param name="dataPin">Data pin number.</param>
33+
/// <param name="communicationEnabledPin">Communication enabled pin number.</param>
34+
/// <param name="controller">Gpio controller.</param>
35+
/// <param name="shouldDispose">True to dispose the Gpio Controller.</param>
36+
/// <exception cref="ArgumentNullException">When pin numbers are not valid.</exception>
37+
public Ds1302(int clockPin, int dataPin, int communicationEnabledPin, GpioController? controller = null, bool shouldDispose = true)
38+
{
39+
_controller = controller ?? new GpioController();
40+
_shouldDispose = shouldDispose || controller is null;
41+
42+
if (clockPin < 0 || dataPin < 0 || communicationEnabledPin < 0)
43+
{
44+
throw new ArgumentOutOfRangeException();
45+
}
46+
47+
_clockPin = _controller.OpenPin(clockPin, PinMode.Output);
48+
_communicationEnabledPin = _controller.OpenPin(communicationEnabledPin, PinMode.Output);
49+
_dataPin = _controller.OpenPin(dataPin, PinMode.Input);
50+
51+
_communicationEnabledPin.Write(PinValue.Low);
52+
_clockPin.Write(PinValue.Low);
53+
}
54+
55+
/// <summary>
56+
/// Checks if the clock is halted.
57+
/// </summary>
58+
/// <returns><b>true</b> when clock is halted, else <b>false</b></returns>
59+
public bool IsHalted()
60+
{
61+
PrepareRead(Ds1302Registers.REG_SECONDS);
62+
byte seconds = ReadByte();
63+
EndTransmission();
64+
return (byte)(seconds & enableWrite) > 0;
65+
}
66+
67+
/// <summary>
68+
/// Halts the clock.
69+
/// </summary>
70+
public void Halt()
71+
{
72+
PrepareWrite(Ds1302Registers.REG_SECONDS);
73+
WriteByte(enableWrite);
74+
EndTransmission();
75+
}
76+
77+
/// <summary>
78+
/// Read time from the device.
79+
/// </summary>
80+
/// <returns>Time from the device.</returns>
81+
protected override DateTime ReadTime()
82+
{
83+
PrepareRead(Ds1302Registers.REG_BURST);
84+
var seconds = NumberHelper.Bcd2Dec((byte)(ReadByte() & 0b0111_1111));
85+
var minutes = NumberHelper.Bcd2Dec((byte)(ReadByte() & 0b0111_1111));
86+
var hours = NumberHelper.Bcd2Dec((byte)(ReadByte() & 0b0011_1111));
87+
var days = NumberHelper.Bcd2Dec((byte)(ReadByte() & 0b0011_1111));
88+
var months = NumberHelper.Bcd2Dec((byte)(ReadByte() & 0b0001_1111));
89+
var dayOfWeek = NumberHelper.Bcd2Dec((byte)(ReadByte() & 0b0000_0111));
90+
var years = NumberHelper.Bcd2Dec((byte)(ReadByte() & 0b0111_1111));
91+
92+
EndTransmission();
93+
94+
return new DateTime(2000 + years, months, days, hours, minutes, seconds, 0);
95+
}
96+
97+
/// <summary>
98+
/// Sets date and time.
99+
/// </summary>
100+
/// <param name="time">Date and time.</param>
101+
protected override void SetTime(DateTime time)
102+
{
103+
PrepareWrite(Ds1302Registers.REG_WP);
104+
WriteByte(disableWrite);
105+
EndTransmission();
106+
107+
PrepareWrite(Ds1302Registers.REG_BURST);
108+
WriteByte(NumberHelper.Dec2Bcd(time.Second));
109+
WriteByte(NumberHelper.Dec2Bcd(time.Minute));
110+
WriteByte(NumberHelper.Dec2Bcd(time.Hour));
111+
WriteByte(NumberHelper.Dec2Bcd(time.Day));
112+
WriteByte(NumberHelper.Dec2Bcd(time.Month));
113+
WriteByte(NumberHelper.Dec2Bcd((int)time.DayOfWeek));
114+
WriteByte(NumberHelper.Dec2Bcd(time.Year - 2000));
115+
116+
WriteByte(enableWrite);
117+
EndTransmission();
118+
}
119+
120+
/// <summary>
121+
/// <inheritdoc/>
122+
/// </summary>
123+
/// <param name="disposing">True to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
124+
protected override void Dispose(bool disposing)
125+
{
126+
_dataPin?.Dispose();
127+
_clockPin?.Dispose();
128+
_communicationEnabledPin?.Dispose();
129+
if (_shouldDispose)
130+
{
131+
_controller?.Dispose();
132+
_controller = null;
133+
}
134+
}
135+
136+
private byte ReadByte()
137+
{
138+
byte readValue = 0;
139+
for (byte i = 0; i < 8; i++)
140+
{
141+
if (_dataPin.Read() == PinValue.High)
142+
{
143+
readValue |= (byte)(0x01 << i);
144+
}
145+
146+
MoveToNextBit();
147+
}
148+
149+
return readValue;
150+
}
151+
152+
private void PrepareRead(Ds1302Registers ds1302Register)
153+
{
154+
SetDirectionOfDataPin(PinMode.Output);
155+
_communicationEnabledPin.Write(PinValue.High);
156+
WriteByte((byte)(enableWriteOrRead | (byte)ds1302Register));
157+
SetDirectionOfDataPin(PinMode.Input);
158+
}
159+
160+
private void PrepareWrite(Ds1302Registers ds1302Register)
161+
{
162+
SetDirectionOfDataPin(PinMode.Output);
163+
_communicationEnabledPin.Write(PinValue.High);
164+
WriteByte((byte)(enableWrite | (byte)ds1302Register));
165+
}
166+
167+
private void EndTransmission()
168+
{
169+
_communicationEnabledPin.Write(PinValue.Low);
170+
}
171+
172+
private void SetDirectionOfDataPin(PinMode direction)
173+
{
174+
if (_currentDataPinDirection != direction)
175+
{
176+
_currentDataPinDirection = direction;
177+
_dataPin.SetPinMode(_currentDataPinDirection);
178+
}
179+
}
180+
181+
private void WriteByte(byte register)
182+
{
183+
for (int i = 0; i < 8; i++)
184+
{
185+
_dataPin.Write((register & 0x01) > 0 ? PinValue.High : PinValue.Low);
186+
MoveToNextBit();
187+
register >>= 1;
188+
}
189+
}
190+
191+
private void MoveToNextBit()
192+
{
193+
_clockPin.Write(PinValue.High);
194+
DelayHelper.DelayMicroseconds(1, true);
195+
_clockPin.Write(PinValue.Low);
196+
DelayHelper.DelayMicroseconds(1, true);
197+
}
198+
}
199+
}

Diff for: devices/Ds1302/Ds1302.fzz

61.2 KB
Binary file not shown.

Diff for: devices/Ds1302/Ds1302.nfproj

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup Label="Globals">
4+
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
5+
</PropertyGroup>
6+
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
7+
<PropertyGroup>
8+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
9+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
10+
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
11+
<ProjectGuid>9bea4579-66fb-46ba-8d55-7301af9af9d6</ProjectGuid>
12+
<OutputType>Library</OutputType>
13+
<AppDesignerFolder>Properties</AppDesignerFolder>
14+
<FileAlignment>512</FileAlignment>
15+
<RootNamespace>Iot.Device.Ds1302</RootNamespace>
16+
<AssemblyName>Iot.Device.Ds1302</AssemblyName>
17+
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
18+
<DocumentationFile>bin\$(Configuration)\Iot.Device.Ds1302.xml</DocumentationFile>
19+
<LangVersion>9.0</LangVersion>
20+
<StyleCopTreatErrorsAsWarnings>false</StyleCopTreatErrorsAsWarnings>
21+
</PropertyGroup>
22+
<PropertyGroup>
23+
<SignAssembly>true</SignAssembly>
24+
</PropertyGroup>
25+
<PropertyGroup>
26+
<AssemblyOriginatorKeyFile>..\key.snk</AssemblyOriginatorKeyFile>
27+
</PropertyGroup>
28+
<PropertyGroup>
29+
<DelaySign>false</DelaySign>
30+
</PropertyGroup>
31+
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
32+
<ItemGroup>
33+
<Compile Include="..\Rtc\RtcBase.cs">
34+
<Link>RtcBase.cs</Link>
35+
</Compile>
36+
<Compile Include="Ds1302.cs" />
37+
<Compile Include="Ds1302Registers.cs" />
38+
</ItemGroup>
39+
<ItemGroup>
40+
<Reference Include="Iot.Device.Common.NumberHelper">
41+
<HintPath>packages\nanoFramework.Iot.Device.Common.NumberHelper.1.1.113.2032\lib\Iot.Device.Common.NumberHelper.dll</HintPath>
42+
</Reference>
43+
<Reference Include="mscorlib">
44+
<HintPath>packages\nanoFramework.CoreLibrary.1.12.0\lib\mscorlib.dll</HintPath>
45+
</Reference>
46+
<Reference Include="nanoFramework.Runtime.Events">
47+
<HintPath>packages\nanoFramework.Runtime.Events.1.10.0\lib\nanoFramework.Runtime.Events.dll</HintPath>
48+
</Reference>
49+
<Reference Include="nanoFramework.Runtime.Native">
50+
<HintPath>packages\nanoFramework.Runtime.Native.1.5.4\lib\nanoFramework.Runtime.Native.dll</HintPath>
51+
</Reference>
52+
<Reference Include="System.Device.Gpio">
53+
<HintPath>packages\nanoFramework.System.Device.Gpio.1.0.4\lib\System.Device.Gpio.dll</HintPath>
54+
</Reference>
55+
<Reference Include="System.Device.Model">
56+
<HintPath>packages\nanoFramework.System.Device.Model.1.1.113.2032\lib\System.Device.Model.dll</HintPath>
57+
</Reference>
58+
<Reference Include="System.Diagnostics.Stopwatch">
59+
<HintPath>packages\nanoFramework.System.Diagnostics.Stopwatch.1.1.113.2032\lib\System.Diagnostics.Stopwatch.dll</HintPath>
60+
</Reference>
61+
</ItemGroup>
62+
<ItemGroup>
63+
<None Include="packages.config" />
64+
<None Include="README.md" />
65+
</ItemGroup>
66+
<ItemGroup>
67+
<Compile Include="Properties\AssemblyInfo.cs" />
68+
<None Include="*.md" />
69+
</ItemGroup>
70+
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
71+
<ProjectExtensions>
72+
<ProjectCapabilities>
73+
<ProjectConfigurationsDeclaredAsItems />
74+
</ProjectCapabilities>
75+
</ProjectExtensions>
76+
<Import Project="packages\Nerdbank.GitVersioning.3.5.107\build\Nerdbank.GitVersioning.targets" Condition="Exists('packages\Nerdbank.GitVersioning.3.5.107\build\Nerdbank.GitVersioning.targets')" />
77+
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
78+
<PropertyGroup>
79+
<ErrorText> This project references NuGet package(s) that are missing on this computer.Enable NuGet Package Restore to download them.For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
80+
</PropertyGroup>
81+
<Error Condition="!Exists('packages\Nerdbank.GitVersioning.3.5.107\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Nerdbank.GitVersioning.3.5.107\build\Nerdbank.GitVersioning.targets'))" />
82+
</Target>
83+
<Import Project="packages\StyleCop.MSBuild.6.2.0\build\StyleCop.MSBuild.targets" Condition="Exists('packages\StyleCop.MSBuild.6.2.0\build\StyleCop.MSBuild.targets')" />
84+
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
85+
<PropertyGroup>
86+
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
87+
</PropertyGroup>
88+
<Error Condition="!Exists('packages\StyleCop.MSBuild.6.2.0\build\StyleCop.MSBuild.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\StyleCop.MSBuild.6.2.0\build\StyleCop.MSBuild.targets'))" />
89+
</Target>
90+
</Project>

Diff for: devices/Ds1302/Ds1302.nuspec

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
3+
<metadata>
4+
<id>nanoFramework.Iot.Device.Ds1302</id>
5+
<version>$version$</version>
6+
<title>nanoFramework.Iot.Device.Ds1302</title>
7+
<authors>nanoFramework project contributors</authors>
8+
<owners>nanoFramework,dotnetfoundation</owners>
9+
<requireLicenseAcceptance>false</requireLicenseAcceptance>
10+
<license type="file">LICENSE.md</license>
11+
<releaseNotes>
12+
</releaseNotes>
13+
<readme>docs\README.md</readme>
14+
<developmentDependency>false</developmentDependency>
15+
<projectUrl>https://github.com/nanoframework/nanoFramework.IoT.Device</projectUrl>
16+
<icon>images\nf-logo.png</icon>
17+
<repository type="git" url="https://github.com/nanoframework/nanoFramework.IoT.Device" commit="$commit$" />
18+
<copyright>Copyright (c) .NET Foundation and Contributors</copyright>
19+
<description>This package includes the .NET IoT Core binding Iot.Device.Ds1302 for .NET nanoFramework C# projects.</description>
20+
<summary>Iot.Device.Ds1302 assembly for .NET nanoFramework C# projects</summary>
21+
<tags>nanoFramework C# csharp netmf netnf Iot.Device.Ds1302</tags>
22+
<dependencies>
23+
<dependency id="nanoFramework.CoreLibrary" version="1.12.0" />
24+
<dependency id="nanoFramework.Iot.Device.Common.NumberHelper" version="1.1.113.2032" />
25+
<dependency id="nanoFramework.Runtime.Events" version="1.10.0" />
26+
<dependency id="nanoFramework.System.Device.Model" version="1.1.113.2032" />
27+
<dependency id="nanoFramework.System.Runtime.Native" version="1.5.4" />
28+
<dependency id="nanoFramework.System.Device.Gpio" version="1.0.4" />
29+
<dependency id="nanoFramework.System.Diagnostics.Stopwatch" version="1.1.113.2032" />
30+
</dependencies>
31+
</metadata>
32+
<files>
33+
<file src="bin\Release\Iot.Device.Ds1302.dll" target="lib\Iot.Device.Ds1302.dll" />
34+
<file src="bin\Release\Iot.Device.Ds1302.pdb" target="lib\Iot.Device.Ds1302.pdb" />
35+
<file src="bin\Release\Iot.Device.Ds1302.pdbx" target="lib\Iot.Device.Ds1302.pdbx" />
36+
<file src="bin\Release\Iot.Device.Ds1302.pe" target="lib\Iot.Device.Ds1302.pe" />
37+
<file src="bin\Release\Iot.Device.Ds1302.xml" target="lib\Iot.Device.Ds1302.xml" />
38+
<file src="README.md" target="docs\" />
39+
<file src="..\..\assets\nf-logo.png" target="images" />
40+
<file src="..\..\LICENSE.md" target="" />
41+
</files>
42+
</package>

Diff for: devices/Ds1302/Ds1302.png

113 KB
Loading

Diff for: devices/Ds1302/Ds1302.sln

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.3.32811.315
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "Ds1302", "Ds1302.nfproj", "{9BEA4579-66FB-46BA-8D55-7301AF9AF9D6}"
7+
EndProject
8+
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "Ds1302.Samples", "samples\Ds1302.Samples.nfproj", "{A1386D57-5216-4968-8BDE-646C662F5C4D}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{9BEA4579-66FB-46BA-8D55-7301AF9AF9D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17+
{9BEA4579-66FB-46BA-8D55-7301AF9AF9D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
18+
{9BEA4579-66FB-46BA-8D55-7301AF9AF9D6}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
19+
{9BEA4579-66FB-46BA-8D55-7301AF9AF9D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
20+
{9BEA4579-66FB-46BA-8D55-7301AF9AF9D6}.Release|Any CPU.Build.0 = Release|Any CPU
21+
{9BEA4579-66FB-46BA-8D55-7301AF9AF9D6}.Release|Any CPU.Deploy.0 = Release|Any CPU
22+
{A1386D57-5216-4968-8BDE-646C662F5C4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{A1386D57-5216-4968-8BDE-646C662F5C4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{A1386D57-5216-4968-8BDE-646C662F5C4D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
25+
{A1386D57-5216-4968-8BDE-646C662F5C4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
26+
{A1386D57-5216-4968-8BDE-646C662F5C4D}.Release|Any CPU.Build.0 = Release|Any CPU
27+
{A1386D57-5216-4968-8BDE-646C662F5C4D}.Release|Any CPU.Deploy.0 = Release|Any CPU
28+
EndGlobalSection
29+
GlobalSection(SolutionProperties) = preSolution
30+
HideSolutionNode = FALSE
31+
EndGlobalSection
32+
GlobalSection(ExtensibilityGlobals) = postSolution
33+
SolutionGuid = {BE615A65-F60F-4FFC-9D0F-761C2D616D22}
34+
EndGlobalSection
35+
EndGlobal

Diff for: devices/Ds1302/Ds1302Registers.cs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Iot.Device.Rtc
5+
{
6+
/// <summary>
7+
/// Register of Ds1302.
8+
/// </summary>
9+
internal enum Ds1302Registers : byte
10+
{
11+
REG_SECONDS = 0x80,
12+
REG_WP = 0x8E,
13+
REG_BURST = 0xBE,
14+
}
15+
}

0 commit comments

Comments
 (0)