Maxim DS1305 clock module

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Post Reply

Did you find this useful?

Poll ended at Wed Feb 08, 2012 7:57 pm

Yes, thank you.
6
100%
No, why would I?
0
No votes
 
Total votes: 6

User avatar
Senacharim
Posts: 139
Joined: Tue Aug 10, 2010 5:19 pm
Location: Ventura, CA

Maxim DS1305 clock module

Post by Senacharim » Tue Feb 08, 2011 7:57 pm

Hi all!
Decided to share one of the module's I've hand-coded for interfacing with hardware.

It might work for you right out-of-the-box, but more likely you'll need to tweak it just a bit for your own needs.

That being said, here's my module for interfacing with Maxim's DS1305 (which I've been using on pretty much ALL my PIC projects for a few years now.)


Code: Select all

{
****************************************************************
*  Name    : EM_Clock.bas                                      *
*  Author  : Senacharim                               *
*  Date    : 02/08/2011                                        *
*  Version : 1.2                                               *
*  Notes   : Written for interfacing a PIC18 w/ Maxim DS1305   *
*          :                                                   *
****************************************************************
}
' - - - - - - - - - - - - - SOF - - - - - - - - - - - - - 
Module DS1305
#ifndef _program 'Put a #define _program into your main program...
    #error _program, "Hey, thou shalt not compile modules."
#endif
#define DS1305

#option SHIFT_CLOCK = 1
#option SHIFT_MAX = 8
Include "shift.bas"
Include "convert.bas"

  Dim 
    Alarm0Buff(4),
    Alarm1Buff(4),
    ClockBuff(7),
    ControlRegister,
    Err_Condition,
    oldSeconds,
    oldMinutes,
    TimeFlags As Byte,
    Clock_Error As Boolean,
    TMR0ON As T0Con.Booleans(7),
    T08BIT As T0Con.Booleans(6),
    T0CS As T0Con.5,
    ToSE As T0Con.4,
    PSA As T0Con.3,
    T0PS2 As T0Con.2,
    T0PS1 As T0Con.1,
    T0PS0 As T0Con.0,
    TMR_OverFlow As INTCON.Booleans(2),
    Timer0 As TMR0L.AsWord,
    FlagSeconds As TimeFlags.Booleans(0),
    FlagMinutes As TimeFlags.Booleans(1),
    ConReg_EOSC As ControlRegister.7,
    ConReg_WP As ControlRegister.6,
    ConReg_INTCN As ControlRegister.2,
    ConReg_AIE1 As ControlRegister.1,
    ConReg_AIE0 As ControlRegister.0
  Public Dim
    Yesterday_Year,
    Yesterday_Month,
    Yesterday_Date,
    Willbe_Year,
    Willbe_Month,
    Willbe_Date As Byte
  Const
    Alarm0ReadAddressStart = $07,
    Alarm1ReadAddressStart = $0B
  Public Const
    Clock_Err_NotRunning = -1,
    Clock_Err_AllGood = 0

    Const FOSC = _clock * 1000000
    Const One_Second_Load = 65536 - ((1 * (FOSC / 4)) / 256)

#if One_Second_Load > 65535
    #warning "Invalid Timer1 pre-load value!"
#endif


    Dim Clk_CS As PORTC.5

'----------------------------------=-=-----------------------------------------
Public Function Control_Register() As Byte
'----------------------------------=-=-----------------------------------------
    Result = ControlRegister
End Function

'----------------------------------=-=-----------------------------------------
Public Function Alarm0_Enabled() As Boolean
'----------------------------------=-=-----------------------------------------
    Result = Boolean(ConReg_AIE0)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Alarm1_Enabled() As Boolean
'----------------------------------=-=-----------------------------------------
    Result = Boolean(ConReg_AIE1)
End Function

'----------------------------------=-=-----------------------------------------
Public Function DayofMonth() As Byte
'----------------------------------=-=-----------------------------------------
    Result = ClockBuff(4)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Seconds() As Byte
'----------------------------------=-=-----------------------------------------
    Result = ClockBuff(0)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Minutes() As Byte
'----------------------------------=-=-----------------------------------------
    Result = ClockBuff(1)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Hours() As Byte
'----------------------------------=-=-----------------------------------------
    Result = ClockBuff(2)
End Function

'----------------------------------=-=-----------------------------------------
Public Function DayofWeek() As Byte
'----------------------------------=-=-----------------------------------------
    Result = ClockBuff(3)
End Function

'----------------------------------=-=-----------------------------------------
Public Function DayofWeekString() As String
'----------------------------------=-=-----------------------------------------
    Select DayofWeek
        Case 1
            Result = "Sunday"
        Case 2
            Result = "Monday"
        Case 3
            Result = "Tuesday"
        Case 4
            Result = "Wednesday"
        Case 5
            Result = "Thursday"
        Case 6
            Result = "Friday"
        Case 7
            Result = "Saturday"
    End Select
End Function

'----------------------------------=-=-----------------------------------------
Public Function Month() As Byte
'----------------------------------=-=-----------------------------------------
    Result = ClockBuff(5)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Year2() As Byte
'----------------------------------=-=-----------------------------------------
    Result = ClockBuff(6)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Year() As Word
'----------------------------------=-=-----------------------------------------
    Result = 2000 + ClockBuff(6)
End Function

'----------------------------------=-=-----------------------------------------
Function toByte(pValue As Byte) As Byte 'from faux hex!
'----------------------------------=-=-----------------------------------------
  Dim
    Mini,
    Maxm As Byte
'---------------=-=---------------
    Mini = 0
    Maxm = 0
    Mini.0 = pValue.0
    Mini.1 = pValue.1
    Mini.2 = pValue.2
    Mini.3 = pValue.3
    Maxm.0 = pValue.4
    Maxm.1 = pValue.5
    Maxm.2 = pValue.6
    Maxm.3 = pValue.7
    Result = (Maxm * 10) + Mini
End Function

'----------------------------------=-=-----------------------------------------
Function Clock_IN() As Byte
'----------------------------------=-=-----------------------------------------
(* public const  //Shift.In Modes
   MSB_PRE = $00,       // MSB first, sample before clock
   MSB_POST = $02,      // MSB first, sample after clock
   LSB_PRE = $01,       // LSB first, sample before clock
   LSB_POST = $03       // LSB first, sample after clock *)
'---------------=-=---------------
    Result = Shift.In(LSB_PRE, 8)
End Function

'----------------------------------=-=-----------------------------------------
Function toHex(pValue As Byte) As Byte 'teh faux hexer!
'----------------------------------=-=-----------------------------------------
  Dim
    Mini,
    Maxm As Byte,
    Number As String
'---------------=-=---------------
    Number = DecToStr(pValue,2)
    Maxm = Byte(Number(0)) - 48
    Mini = Byte(Number(1)) - 48
    Result = (Maxm << 4) + Mini
End Function

'----------------------------------=-=-----------------------------------------
Sub Clock_OUT(pValue As Byte)
'----------------------------------=-=-----------------------------------------
(* public const // shiftout modes...
   LSB_FIRST = $00,     // LSB first
   MSB_FIRST = $01      // MSB first   *)
'---------------=-=---------------
    Shift.Out(LSB_FIRST,pValue ,8)
End Sub

'----------------------------------=-=-----------------------------------------
Function Clock_IO(pAddress As Byte, pValue As Byte = 0) As Byte
'----------------------------------=-=-----------------------------------------
  Dim
    pRes As Byte
'---------------=-=---------------
    High(Clk_CS)
    DelayUS(1)
    Clock_OUT(pAddress)
    If pAddress > 127 Then
        pRes = pValue
        Clock_OUT(pRes)
        Result = 0
    Else
        pRes = Clock_IN
        Result = pRes
    EndIf
    Low(Clk_CS)
    DelayUS(1)
End Function

'----------------------------------=-=-----------------------------------------
Sub Reset_Timer()
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    Timer0 = One_Second_Load
    TMR_OverFlow = false
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub Read_Alarm0()
'----------------------------------=-=-----------------------------------------
  Dim
    Index As Byte
'---------------=-=---------------
    High(Clk_CS)
    Clock_OUT(toHex(Alarm0ReadAddressStart))
    For index = 0 To Bound(Alarm0Buff)
        Alarm0Buff(index) = Clock_IN()
    Next
    Low(Clk_CS)
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub Read_Alarm1()
'----------------------------------=-=-----------------------------------------
  Dim
    Index As Byte
'---------------=-=---------------
    High(Clk_CS)
    Clock_OUT(toHex(Alarm1ReadAddressStart))
    For index = 0 To Bound(Alarm1Buff)
        Alarm1Buff(index) = Clock_IN()
    Next
    Low(Clk_CS)
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub Alarm0_Off()
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    Clock_IO(Alarm0ReadAddressStart)
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub Alarm1_Off()
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    Clock_IO(Alarm1ReadAddressStart)
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub Read_Clock(pBypassTimer As Boolean = false)
'----------------------------------=-=-----------------------------------------
  Dim
    Index,
    FailCount As Byte
'---------------=-=---------------
    If (TMR_OverFlow = true Or pBypassTimer = true) Then
        FailCount = 0
            ReadAgain:
            High(Clk_CS)
            Clock_OUT(0)
            For index = 0 To Bound(ClockBuff)
                ClockBuff(index) = toByte(Clock_IN())
            Next
            Low(Clk_CS)
           
            If (FailCount < 255) Then
                If Hours > 23 Or
                   Minutes > 59 Or
                   Seconds > 59 Or
                   Month = 0 Or
                   Month > 12 Or
                   DayofWeek > 7 Or
                   DayofWeek = 0 Or
                   Year2 > 99 Then
                    DelayMS(10)
                    Inc(FailCount)
                    GoTo ReadAgain
                EndIf
            EndIf
        Reset_Timer()
    EndIf
   
    If oldSeconds <> ClockBuff(0) Then
        FlagSeconds = true
        oldSeconds = ClockBuff(0)
    Else
        FlagSeconds = false
    EndIf
    
    If oldMinutes <> ClockBuff(1) Then
        FlagMinutes = true
        oldMinutes = ClockBuff(1)
    Else
        FlagMinutes = false
    EndIf
    
	If Willbe_Date <> DayofMonth Then
		Yesterday_Year = Willbe_Year
		Yesterday_Month = Willbe_Month
		Yesterday_Date = Willbe_Date
		Willbe_Year = Year
		Willbe_Month = Month
		Willbe_Date = DayofMonth
	EndIf    
End Sub

'----------------------------------=-=-----------------------------------------
Public Function SecondsFlag() As Boolean
'----------------------------------=-=-----------------------------------------
    Result = FlagSeconds
End Function

'----------------------------------=-=-----------------------------------------
Public Function MinutesFlag() As Boolean
'----------------------------------=-=-----------------------------------------
    Result = FlagMinutes
End Function

Const
    pTS_Month = 0,
    pTS_Date = 1,
    pTS_Year = 2,
    pTS_Hour = 3,
    pTS_Minute = 4,
    pTS_Weekday = 5,
    TimeWriteAddress() As Byte = ($85,$84,$86,$82,$81,$83)

'----------------------------------=-=-----------------------------------------
Public Sub SetMonth(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    pValue = toHex(pValue)
    Clock_IO(TimeWriteAddress(pTS_Month), pValue)
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub SetDate(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    pValue = toHex(pValue)
    Clock_IO(TimeWriteAddress(pTS_Date), pValue)
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub SetYear(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    pValue = toHex(pValue)
    Clock_IO(TimeWriteAddress(pTS_Year), pValue)
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub SetHour(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    pValue = toHex(pValue)
    pValue.6 = 0 'Set to 24h time.
    Clock_IO(TimeWriteAddress(pTS_Hour), pValue)
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub SetMinute(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    pValue = toHex(pValue)
    Clock_IO(TimeWriteAddress(pTS_Minute), pValue)
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub SetWeekday(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    pValue = toHex(pValue)
    Clock_IO(TimeWriteAddress(pTS_Weekday), pValue)
End Sub

'************************ |/ Alarm 0 \/ ***************************************
Const
    Alarm_Second = 0,
    Alarm_Minute = 1,
    Alarm_Hour = 2,
    Alarm_Weekday = 3,
    Alarm0_WriteAddress() As Byte = ($87,$88,$89,$8A)
'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm0Seconds(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
    Clock_IO(
        Alarm0_WriteAddress(Alarm_Second),
        pValue
        )
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm0Minute(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
    Clock_IO(
        Alarm0_WriteAddress(Alarm_Minute),
        pValue
        )
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm0Hour(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
    Clock_IO(
        Alarm0_WriteAddress(Alarm_Hour),
        pValue
        )
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm0Weekday(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
    Clock_IO(
        Alarm0_WriteAddress(Alarm_Weekday),
        pValue
        )
End Sub

'----------------------------------=-=-----------------------------------------
Public Function Alarm0Seconds() As Byte
'----------------------------------=-=-----------------------------------------
    Result = Alarm0Buff(0)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Alarm0Minutes() As Byte
'----------------------------------=-=-----------------------------------------
    Result = Alarm0Buff(1)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Alarm0Hours() As Byte
'----------------------------------=-=-----------------------------------------
    Result = Alarm0Buff(2)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Alarm0DayofWeek() As Byte
'----------------------------------=-=-----------------------------------------
    Result = Alarm0Buff(3)
End Function

'************************ |/ Alarm 1 \/ ***************************************
Const
    Alarm1_WriteAddress() As Byte = ($8B,$8C,$8D,$8E)
'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm1Seconds(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
    Clock_IO(
        Alarm1_WriteAddress(Alarm_Second),
        pValue
        )
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm1Minute(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
    Clock_IO(
        Alarm1_WriteAddress(Alarm_Minute),
        pValue
        )
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm1Hour(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
    Clock_IO(
        Alarm1_WriteAddress(Alarm_Hour),
        pValue
        )
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm1Weekday(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
    Clock_IO(
        Alarm1_WriteAddress(Alarm_Weekday),
        pValue
        )
End Sub

'----------------------------------=-=-----------------------------------------
Public Function Alarm1Seconds() As Byte
'----------------------------------=-=-----------------------------------------
    Result = Alarm1Buff(0)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Alarm1Minutes() As Byte
'----------------------------------=-=-----------------------------------------
    Result = Alarm1Buff(1)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Alarm1Hours() As Byte
'----------------------------------=-=-----------------------------------------
    Result = Alarm1Buff(2)
End Function

'----------------------------------=-=-----------------------------------------
Public Function Alarm1DayofWeek() As Byte
'----------------------------------=-=-----------------------------------------
    Result = Alarm1Buff(3)
End Function

'******************************************************************************

'----------------------------------=-=-----------------------------------------
Function SetControlRegister(pSetValue As Byte) As Boolean
'----------------------------------=-=-----------------------------------------
  Dim
    ErrCountup As Byte
'---------------=-=---------------
    ErrCountup = 0
    Result = false
    '1 Read ControlRegister value.
    ControlRegister = Clock_IO($0F)
    While (ErrCountup < 255)
        If ControlRegister <> pSetValue Then
            Clock_IO($8F, pSetValue)
            DelayMS(1)
            ControlRegister = Clock_IO($0F)
            DelayMS(1)
        Else 'they equal!  We're good.
            Result = true
            Break
        EndIf
        Inc(ErrCountup)
    Wend
End Function

'----------------------------------=-=-----------------------------------------
Public Sub INTCN_EN(pEnabled As Boolean)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    ControlRegister = Clock_IO($0F) 'Get clock control register value.;
    If ConReg_INTCN <> Bit(pEnabled) Then
        ConReg_INTCN = Bit(pEnabled)
        SetControlRegister(ControlRegister)
    EndIf
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub Alarm0_EN(pEnabled As Boolean)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    ControlRegister = Clock_IO($0F)
    If ConReg_AIE0 <> Bit(pEnabled) Then
        ConReg_AIE0 = Bit(pEnabled) ' 1
        SetControlRegister(ControlRegister)
    EndIf
End Sub

'----------------------------------=-=-----------------------------------------
Public Sub Alarm1_EN(pEnabled As Boolean)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
    ControlRegister = Clock_IO($0F)
    If ConReg_AIE1 <> Bit(pEnabled) Then
        ConReg_AIE1 = Bit(pEnabled) ' 1
        SetControlRegister(ControlRegister)
    EndIf
End Sub

' *****************************************************************************

'----------------------------------=-=-----------------------------------------
Public Sub Clock_Init(pEnableTimer As Boolean = true)
    'the vaunted, all important clock initialization.
    'a routine which must not fail if accurate timing is to be achieved.
'----------------------------------=-=-----------------------------------------
  Dim
    CountUp As Byte
'---------------=-=---------------
    CountUp = 0
    ControlRegister = Clock_IO($0F) 'Read control register.
    ConReg_WP = 0
    SetControlRegister(ControlRegister) 'Write Protect Off.
    If ConReg_EOSC <> 0 Then
        ConReg_EOSC = 0
        SetControlRegister(ControlRegister)
    EndIf
    
    If pEnableTimer Then
        TMR0ON = false
        T08BIT = false  '16 bit counter
        T0CS = 0        'internal clock
        PSA = 0         'prescaler assigned.
        
        T0PS2 = 1
        T0PS1 = 1
        T0PS0 = 1 ' 1:256 Scaler.
        
        Timer0 = One_Second_Load
        TMR0ON = true
    Else
        TMR0ON = false
        Timer0 = 0
    EndIf
    
    TMR_OverFlow = false
'    Read_Clock(true)
    While
     (Hours = 0 And Minutes = 0 And Seconds = 0
      And Year2 = 0 And Month = 0 And DayofMonth = 0
      And CountUp < 255)
        Inc(CountUp)
        DelayMS(10)
        Read_Clock(true)
    Wend
    
    'Assuming the system clock is correct, then at least 2.5 seconds will have
    'gone by betwixt initialization and the last loop's reading.
    
    'A 0 in the seconds place, given that situation, indicates a definite err.
    
    If (CountUp = 255) Then
        Clock_Error = true
        Err_Condition = Clock_Err_NotRunning
    Else
        Err_Condition = Clock_Err_AllGood
    EndIf
    ControlRegister = Clock_IO($0F) 'Read control register. Again.
End Sub

//TimerEvent = Clock_Increment()

//Initialise Module
Err_Condition = 255

    Shift.SetInput(PORTB.0)
    Shift.SetOutput(PORTB.0)
    Shift.SetClock(PORTC.4)

    Clear(ClockBuff)
    Clock_Error = false
    FlagSeconds = false
    oldSeconds = 255
    oldMinutes = 255
    Yesterday_Year = 0
    Yesterday_Month = 0
    Yesterday_Date = 0
    Willbe_Year = 0
    Willbe_Month = 0
    Willbe_Date = 0

    Clock_Init() 'auto-init with timer.  Perhaps to change this later...

' - - - - - - - - - - - - - EOF - - - - - - - - - - - - - 
End Module
Surviving Member
Bermuda Triangle Battalion
from 2026 to 1992

Voted "Most likely to time travel"--Class of 2024.

ta1dr
Registered User
Registered User
Posts: 15
Joined: Tue Aug 18, 2009 8:14 am
Location: istanbul TURKEY

Post by ta1dr » Wed Feb 09, 2011 7:24 am

thanks for this modul if you add sample code it will be very nice :D

User avatar
Senacharim
Posts: 139
Joined: Tue Aug 10, 2010 5:19 pm
Location: Ventura, CA

Post by Senacharim » Wed Feb 09, 2011 9:07 pm

It's pretty straightforward, or so I'd thought...

1st, read the spec for the DS1305.

Then, read the spec again.

A little example code:

Code: Select all

Include "EM_Clock.bas"

Clock_Init()
While(true)
    Read_Clock()
{note the use of Timer1 to insure we only read the clock once per second... }
    If DS1305.SecondsFlag = true then 'it's a new second!
         LCD.Write(DecToStr(DS1305.Hours,2) + ":")
         LCD.Write(DecToStr(DS1305.Minutes,2) + ":")
         LCD.Write(DecToStr(DS1305.Seconds,2) )
    Endif
Wend
Read the code.

Also, that line near that top should be

Code: Select all

Clock_Err_NotRunning = 1,
instead of

Code: Select all

Clock_Err_NotRunning = -1,
Surviving Member
Bermuda Triangle Battalion
from 2026 to 1992

Voted "Most likely to time travel"--Class of 2024.

Post Reply