IntRTCC

SwordfishUser.IntRTCC History

Show minor edits - Show changes to output

Deleted line 319:
' Include "UTCDateTime.bas"
Deleted line 320:
Include "usbcdc.bas"
Added lines 1-768:
!!! PIC18 RTCC Module

This module allows you to use the on-board internal RTCC of many of the newer PIC18F devices.

From the datasheet:

The key features of the Real-Time Clock and Calendar (RTCC) module are:
• Time: hours, minutes and seconds
• 24-hour format (military time)
• Calendar: weekday, date, month and year
• Alarm configurable
• Year range: 2000 to 2099
• Leap year correction
• BCD format for compact firmware
• Optimized for low-power operation
• User calibration with auto-adjust
• Calibration range: ?2.64 seconds error per month
• Requirements: external 32.768 kHz clock crystal
• Alarm pulse or seconds clock output on RTCC pin

The RTCC module is intended for applications, where accurate time must be maintained for an extended period with minimum to no intervention from the CPU. The module is optimized for low-power usage in order to provide extended battery life while keeping track of time. The module is a 100-year clock and calendar with automatic leap year detection. The range of the clock is from 00:00:00 (midnight) on January 1, 2000 to 23:59:59 on December 31, 2099. Hours are measured in 24-hour (military time) format. The clock provides a granularity of one second with half-second visibility to the user.

The main limitation of the internal RTCC over an external solution is there is no independant battery backup for the module (Hint! hint! Microchip. A BATVCC input would be useful!) When the PIC power goes, the RTCC stops and loses its time. The module is unaffected by all other reset conditions however.

The module can be configured to run off an external 32.768 kHz crystal on the Timer1 input (SOSC) or from the internal RC oscillator (if present).

!!Usage

!Structures
These two structures are provided to simplify access to the various registers.

'''TTime'''
Second as byte
Minute as byte
Hour as byte

'''TDate'''
Day as byte
Month as byte
Year as byte
DayOfWeek as byte

!Subroutines

The following subroutines are provided to control the module.

'''sub RTCEnable(pState as boolean)'''
pState - State. Can be TRUE (run RTCC) or FALSE (stop RTCC).
Starts or Stops the RTCC module running (if an appropriate clock is present).

'''sub AlarmEnable(pState as boolean)'''
pState - State. Can be TRUE (Alarm Enabled) or FALSE (Alarm Disabled).
Enables or Disables the Alarm function of the module.

'''compound sub Read(ReadItem)'''
ReadItem - Item to Read.
Reads realtime clock registers. Readitem can be a TTime Structure or TDate Structure, in which the current values are updated.

'''compound sub Write(ReadItem)'''
WriteItem - Item to Write.
Writes realtime clock registers. Writeitem can be a TTime Structure or TDate Structure, from which the updated values are written.

'''compound sub GetAlarm(ReadItem)'''
ReadItem - Item to Read.
Reads Alarm value registers. Readitem can be a TTime Structure or TDate Structure, in which the current values are updated.

'''compound sub Write(ReadItem)'''
WriteItem - Item to Write.
Writes Alarm value registers. Writeitem can be a TTime Structure or TDate Structure, from which the updated values are written.

'''sub SetAlarmMode(pMask As Byte, pChime As Boolean = false, pRepeat As Byte = $00)'''
pMask - Sets the Alarm trigger mask. Can be:

EveryHalfSec
EverySecond
Every10Secs
EveryMinute
Every10Mins
EveryHour
EveryDay
EveryWeek
EveryMonth
EveryYear

pChime - Sets whether the Alarm should repeat indefinately, ignoring the pRepeat value.
pRepeat - Sets a limited number of times the Alarm should repeat (up to 255).
Configures the Alarm settings.

'''sub OutputEnable(pState As Boolean, pMode As Byte = OUTAlarm)'''
pState - State. Can be TRUE (OE pin is enabled) or FALSE (OE Pin is disabled).
pMode - Output mode. Can be:
OUTClock - Source clock (INTRC or EXT32).
OUTSecond - Toggles at 1 Hz (as per RTCC).
OUTAlarm - Toggles on Alarm event.
Sets whether the RTCC Output PIN is enabled, and if so, which mode the Pin operates in.

'''sub Initialize()'''
Initializes the module to a default time and starts the module running.

!Sample code
The sample code presented demonstrates most of the basic functionality of the module. It has been tested on a 18F27J53 device in both External and Internal Oscillator modes.

=code [=
Device = 18F27J53
Clock = 48

Public Config
  OSC = INTOSCPLLO,                  ' internal osc 8MHz
  PLLDIV = 2,                        ' usb 48MHz
  CPUDIV = OSC1,                    ' 48MHz cpu clock
  FCMEN = OFF,
  IESO = OFF,
  WDTEN = OFF,
  WDTPS = 2048,
  STVREN = ON,
  XINST = OFF
  'DEBUG = OFF

'#option OSCSOURCE = EXT32 // set to EXT32 for external 32.768 kHz Crystal on Timer1
#option OSCSOURCE = INTRC // set to INTRC for internal 32.768 kHz Oscillator

// Enable this option to use with the Microchip USB HID bootloader
'#option org_reset = $1000

Include "system.bas"
Include "IntRTCC.bas" // Needs to be near top as it has a config line?
Include "usbcdc.bas"
Include "convert.bas"
Include "string.bas"

Dim Timer As TTime
Dim Time As TTime
Dim Date As TDate
Dim ResponseString As String
Dim OutputMode As Byte

Sub MenuDisplay()
CDC.Write("D: Set Date", 13, 10)
CDC.Write("T: Set Time", 13, 10)
CDC.Write("I: Initalise RTCC", 13, 10)
CDC.Write("P: Set Output pin mode", 13, 10)
CDC.Write("A: Set One-off Alarm Time", 13, 10)
CDC.Write("M: Set Minute Chime",13, 10)
CDC.Write("S: Stop Alarm", 13, 10)
End Sub

Sub Menu(pMenuOption As String)

If pMenuOption <> " " Then
CDC.Write(">: Option: " + pMenuOption, 13, 10)
EndIf 

Select pMenuOption
Case " "  // Menu
MenuDisplay()
Case "D" 
    CDC.Write("Set Day (1-31): ") // Get Day
CDC.Read(ResponseString)
Date.Day = StrToDec(ResponseString) // Put it into the Date Structure
CDC.Write(DecToStr(Date.Day), 13, 10)

CDC.Write("Set Month (1-12): ") // Get Month
CDC.Read(ResponseString)
Date.Month = StrToDec(ResponseString) // Put it into the Date Structure
CDC.Write(DecToStr(Date.Month), 13, 10)

CDC.Write("Set Year (0-99): ") // Get year
CDC.Read(ResponseString)
Date.Year = StrToDec(ResponseString) // Put it into the Date Structure
CDC.Write(DecToStr(Date.Year), 13, 10)

CDC.Write("Set Day of week (0-Sun, 1-Mon, 2-Tues, 3-Weds, 4-Thurs, 5-Fri, 6-Sat): ")
CDC.Read(ResponseString)
Date.DayOfWeek = StrToDec(ResponseString) // Put it into the Date Structure
CDC.Write(DecToStr(Date.DayOfWeek), 13, 10)

IntRTCC.Write(Date) // Set the Date parameters using the Date Structure

Case "T"
            CDC.Write("Set 24 Hour (0-23): ") // Get Hours
CDC.Read(ResponseString)
Time.Hour = StrToDec(ResponseString) // Put it into the Time Structure
CDC.Write(DecToStr(Time.Hour), 13, 10)

CDC.Write("Set Minutes (0-59): ") // Get Hours
CDC.Read(ResponseString)
Time.Minute = StrToDec(ResponseString) // Put it into the Time Structure
CDC.Write(DecToStr(Time.Minute), 13, 10)

CDC.Write("Set Seconds (0-59): ") // Get Hours
CDC.Read(ResponseString)
Time.Second = StrToDec(ResponseString) // Put it into the Time Structure
CDC.Write(DecToStr(Time.Second), 13, 10)

IntRTCC.Write(Time) // Set the Time parameters using the Time Structure

Case "I"
IntRTCC.Initialize() // Initialise to module defaults

Case "P"
CDC.Write("Set Output Pin (0-Off, 1-Output Clock, 2-Output Seconds, 3-OutputAlarm): ")
CDC.Read(ResponseString)
Select StrToDec(ResponseString)
Case 0
OutputEnable(false) // Get Hours
CDC.Write("Output Off", 13, 10)
Case 1
OutputEnable(true, OUTClock) // Output the source clock (intRC or T0)
CDC.Write("Output Clock", 13, 10)
Case 2
OutputEnable(true, OUTSecond) // Output seconds (toggle every second)
CDC.Write("Output Seconds", 13, 10)
Case 3
OutputEnable(true, OUTAlarm) // Output the Alarm
CDC.Write("Output Alarm", 13, 10)
End Select

Case "A"
  CDC.Write("Set 24 Hour (0-23): ") // Get Hours
CDC.Read(ResponseString)
Time.Hour = StrToDec(ResponseString) // Put it into the Time Structure
CDC.Write(DecToStr(Time.Hour), 13, 10)

CDC.Write("Set Minutes (0-59): ") // Get Minutes
CDC.Read(ResponseString)
Time.Minute = StrToDec(ResponseString) // Put it into the Time Structure
CDC.Write(DecToStr(Time.Minute), 13, 10)

CDC.Write("Set Seconds (0-59): ") // Get Seconds
CDC.Read(ResponseString)
Time.Second = StrToDec(ResponseString) // Put it into the Time Structure
CDC.Write(DecToStr(Time.Second), 13, 10)

IntRTCC.SetAlarm(Time)                      // Set the Alarm parameters using the Time Structure
SetAlarmMode(EveryDay) // Will trigger once at the set time of day
OutputEnable(true, OUTAlarm)                // Set the output pin to Output the alarm signal
AlarmEnable(true)                          // Enable the alarm

Case "M"
CDC.Write("Set Seconds (0-59): ")          // Get time
CDC.Read(ResponseString)
Time.Second = StrToDec(ResponseString)      // Put it into the Time Structure
CDC.Write(DecToStr(Time.Second), 13, 10)

IntRTCC.SetAlarm(Time)                      // Set the Alarm parameters using the Time Structure
SetAlarmMode(EveryMinute, true) // Will trigger repeatedly each minute (Pin should toggle every minute at seconds set)
OutputEnable(true, OUTAlarm)                // Set the output pin to Output the alarm signal
AlarmEnable(true)                          // Enable the alarm

Case "S"
AlarmEnable(false) // Disable the Alarm

End Select
End Sub

#if OSCSOURCE = EXT32
// Start up the timer1 Oscillator if using it
T1CON.3 = 1

#endif
   
ReadTerminator = #13
OutputMode = OUTAlarm

Clear(Timer)
Output(PORTB.4) // RTCC output pin

// wait for connection...
Repeat
Until Attached

IntRTCC.RTCEnable(true) // Enable the RTCC

While true

  If DataAvailable Then // Get responses from CDC terminal
        CDC.Read(ResponseString)
Menu(Str.Uppercase(ResponseString))
  EndIf

  IntRTCC.Read(Time, Date) // Read the RTCC into the Time & Date structures
 
  If Time <> Timer Then // Displays updated time every second when the second field changes
Timer = Time
CDC.Write(DecToStr(Time.Hour, 2),":",DecToStr(Time.Minute,2),":",DecToStr(Time.Second,2), " ")
CDC.Write(DaysOfWeek(Date.DayOfWeek), " ", DecToStr(Date.Day,2),"/",DecToStr(Date.Month,2),"/",DecToStr(Date.Year,2), 13, 10)
EndIf

Wend
=]
!!! IntRTCC Module
=code [=
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                  *
*  Author  : Nathan Herbert                                                *
*  Notice  : Copyright (c) 2012                 *
*          : All Rights Reserved                                            *
*  Date    : 27/09/2012                                                    *
*  Version : 1.0                                                            *
*  Notes  :                                                                *
*          :                                                                *
*****************************************************************************
}
Module IntRTCC

#option OSCSOURCE = INTRC

#if IsOption(OSCSOURCE) And Not (OSCSOURCE in (INTRC, EXT32))
  #error OSCSOURCE, "Invalid option. OSCSOURCE type not recognized. INTRC or EXT32 Only."
#endif

#if OSCSOURCE = INTRC
Config RTCOSC = INTOSCREF
#warning "Internal RC Accuracy is poor, even when calibrated."
#else
Config RTCOSC =  T1OSCREF
#endif

' Include "UTCDateTime.bas"
Include "convert.bas"
Include "usbcdc.bas"

// time data structure...
Public Structure TTime
  Second As Byte        // Second (0..59)
  Minute As Byte        // Minute (0..59)
  Hour As Byte          // Hour  (0..11 or 0..23)
End Structure

// date data structure...
Public Structure TDate
  Day  As Byte        // Date  (0..31)
  Month As Byte        // Month (1..12)
  Year  As Byte        // Year  (0..99)
  DayOfWeek As Byte    // day of the week (0..6)
End Structure

Dim
RTCEn As RTCCFG.Booleans(7),
RTCWren As RTCCFG.Booleans(5),
RTCSync As RTCCFG.Booleans(4),
RTCOe As RTCCFG.Booleans(2),
RTCCalib As RTCCAL,
RTCPinConfig As PADCFG1,
RTCConfig As RTCCFG,
RTCValLow As RTCVALL,
RTCValHigh As RTCVALH,
MemControl As EECON2,
AlarmEn As ALRMCFG.booleans(7),
AlarmChime As ALRMCFG.booleans(6),
AlarmConfig As ALRMCFG,
AlarmRepeat As ALRMRPT,
AlarmValLow As ALRMVALL,
AlarmValHigh As ALRMVALH

Const
// RTCPTR and ALMPTR pointer values
// RTCVAL<15:8>
VALYear = %00100011,
VALDay = %00100010,
VALHours = %00100001,
VALSeconds = %00100000,
// RTCVAL<7:0>
VALMonth = %00100010,
VALWeekday = %00100001,
VALMinutes = %00100000

Public Const
  DaysOfWeek(7) As String = ("Sun","Mon","Tue","Wed","Thu","Fri","Sat"),

  // Output Configuration
OUTClock = %00000100,
OUTSecond = %00000010,
OUTAlarm = %00000000,

// Alarm settings DoW Month Day Hours Minutes Seconds (X = don't care)
EveryHalfSec = %00000000, // X X X X X X X X X X X
EverySecond = %00000100, // X X X X X X X X X X S
Every10Secs = %00001000, // X X X X X X X X X X S
EveryMinute = %00001100, // X X X X X X X X X S S
Every10Mins = %00010000, // X X X X X X X X M S S
EveryHour = %00010100, // X X X X X X X M M S S
EveryDay = %00011000, // X X X X X H H M M S S
EveryWeek = %00011100, // D X X X X H H M M S S
EveryMonth = %00100000, // X X X D D H H M M S S
EveryYear = %00100100 // X M M D D H H M M S S

{
****************************************************************************
* Name    : RTCWriteEnable (PRIVATE)                                    *
* Purpose : Enables or Disables writes to RTCC registers                  *
****************************************************************************
}
Sub RTCWriteEnable(pState As Boolean)
// The lock sequence seems to need to be ASM in order to
// ensure the commands occur in the time required.
// An interrupt occuring during the sequence would
// disrupt it. So rather than disable the interrupts,
// I prefer to just repeat the sequence until occurs
// uninterrupted.

Repeat
If pState = true Then
Asm
movlb 0x0F          // Lock sequence
movlw 0x55               
movwf EECON2
movlw 0xAA
movwf EECON2
bsf RTCCFG,5
End Asm
    Else
    Asm
movlb 0x0F          // Unlock sequence
movlw 0x55               
movwf EECON2
movlw 0xAA
movwf EECON2
bcf RTCCFG,5
End Asm
EndIf
Until RTCWren = pState
End Sub

{
****************************************************************************
* Name    : SetConfig                                           *
* Purpose :                   *
****************************************************************************
}
Sub SetRTCPointer(pState As Byte)

RTCConfig = RTCConfig And %11111100 // Clear the PTR bits
RTCConfig = RTCConfig Or pState // Set PTR bits to required

End Sub

{
****************************************************************************
* Name    : SetConfig                                           *
* Purpose :                   *
****************************************************************************
}
Sub SetAlarmPointer(pState As Byte)

AlarmConfig = AlarmConfig And %11111100 // Clear the PTR bits
AlarmConfig = AlarmConfig Or pState // Set PTR bits to required

End Sub

{
****************************************************************************
* Name    : RTCEnable                                           *
* Purpose : Enables or Disables the RTCC                   *
****************************************************************************
}
Public Sub RTCEnable(pState As Boolean)
RTCWriteEnable(true)
RTCEn = pState
RTCWriteEnable(false)
End Sub

{
****************************************************************************
* Name    : AlarmEnable                                           *
* Purpose : Enables or Disables the Alarm                   *
****************************************************************************
}
Public Sub AlarmEnable(pState As Boolean)
AlarmEn = pState
End Sub

{
****************************************************************************
* Name    : ReadItem (OVERLOAD)                                            *
* Purpose : Returns Time in the referenced variable                        *
****************************************************************************
}       
Sub ReadItem(ByRef pTime As TTime)
Dim
dummy As Byte,
Temp As TTime,
Result As Boolean

// Read at least twice as per datasheet to ensure we did not read during a rollover
result = false
Repeat
SetRTCPointer(VALHours) // Set pointer to start position

Temp.Hour = BCDToDec(RTCValLow) // Read Hours
dummy = RTCValHigh // Read Dummy to decrement pointer
Temp.Second = BCDToDec(RTCValLow) // Read Seconds
Temp.Minute = BCDToDec(RTCValHigh) // Read Minutes

SetRTCPointer(VALHours) // Set pointer to start position

pTime.Hour = BCDToDec(RTCValLow) // Read Hours
dummy = RTCValHigh // Read Dummy to decrement pointer
pTime.Second = BCDToDec(RTCValLow) // Read Seconds
pTime.Minute = BCDToDec(RTCValHigh) // Read Minutes

// Do both reads match?
If Temp = pTime Then
result = true
  EndIf
 
Until result = true

End Sub
{
****************************************************************************
* Name    : ReadItem (OVERLOAD)                                            *
* Purpose : Returns Date in the referenced variable                        *
****************************************************************************
}
Sub ReadItem(ByRef pDate As TDate)
Dim
dummy As Byte,
Temp As TDate,
Result As Boolean

// Read twice as per datasheet to ensure we did not read during a rollover
result = false
Repeat
SetRTCPointer(VALYear) // Set pointer to start position

Temp.Year = BCDToDec(RTCValLow) // Read Year
dummy = RTCValHigh // Read Dummy to decrement pointer
Temp.Day = BCDToDec(RTCValLow) // Read Day
Temp.Month = BCDToDec(RTCValHigh) // Read month and decrement pointer
Temp.DayOfWeek = BCDToDec(RTCValHigh) // Read Day of Week

SetRTCPointer(VALYear) // Set pointer to start position

pDate.Year = BCDToDec(RTCValLow) // Read Year
dummy = RTCValHigh // Read Dummy to decrement pointer
pDate.Day = BCDToDec(RTCValLow) // Read Day
pDate.Month = BCDToDec(RTCValHigh) // Read month and decrement pointer
pDate.DayOfWeek = BCDToDec(RTCValHigh) // Read Day of Week

// Do both reads match?
If Temp = pDate Then
result = true
  EndIf
 
Until result = true

End Sub

{
****************************************************************************
* Name    : Read                                                          *
* Purpose : Returns Time or Date in the referenced variable                *
****************************************************************************
}
Public Compound Sub Read(ReadItem)

{
****************************************************************************
* Name    : WriteItem (OVERLOAD)                                          *
* Purpose : Sets the Time in BCD format                                    *
****************************************************************************
}       
Sub WriteItem(pTime As TTime)
Dim RTCCurrent As Boolean

RTCCurrent = RTCEn                         // Save current state
RTCEnable(false) // Ensure the RTCC is not running
RTCWriteEnable(true) // Enable writes
SetRTCPointer(VALHours) // Set pointer to start position
RTCValLow = DecToBCD(pTime.Hour)            // Get Hours
SetRTCPointer(VALMinutes) // Set pointer to Minutes / Seconds
RTCValLow = DecToBCD(pTime.Second)          // Get Seconds
RTCValHigh = DecToBCD(pTime.Minute) // Get Minutes
RTCEnable(RTCCurrent) // Reset current state (Will disable writes)

End Sub 
{
****************************************************************************
* Name    : WriteItem (OVERLOAD)                                          *
* Purpose : Sets the Date in BCD format                                    *
****************************************************************************
}       
Sub WriteItem(pDate As TDate)
Dim RTCCurrent As Boolean

RTCCurrent = RTCEn // Save current state
RTCEnable(false) // Ensure the RTCC is not running
RTCWriteEnable(true)  // Enable writes
SetRTCPointer(VALYear) // Set pointer to start position
RTCValLow = DecToBCD(pDate.Year) // Get Year
SetRTCPointer(VALMonth) // Set pointer to Month / Day
RTCValLow = DecToBCD(pDate.Day)  // Get Day
RTCValHigh = DecToBCD(pDate.Month)  // Get Month & decrement
RTCValHigh = DecToBCD(pDate.DayOfWeek)  // Get Day of week
RTCEnable(RTCCurrent) // Reset current state (Will disable writes)

End Sub 
{
****************************************************************************
* Name    : Write                                                          *
* Purpose : Sets the Time or Date                                          *
****************************************************************************
}       
Public Compound Sub Write(WriteItem)

{
****************************************************************************
* Name    : ReadAlarm (OVERLOAD)                                          *
* Purpose : Returns Alarm Time in the referenced variable                  *
****************************************************************************
}       
Sub ReadAlarm(ByRef pTime As TTime)
Dim dummy As Byte

SetAlarmPointer(VALHours) // Set pointer to start position

pTime.Hour = BCDToDec(AlarmValLow) // Read Hours
dummy = AlarmValHigh // Read Dummy to decrement pointer
pTime.Second = BCDToDec(AlarmValLow) // Read Seconds
pTime.Minute = BCDToDec(AlarmValHigh) // Read Minutes

End Sub
{
****************************************************************************
* Name    : ReadAlarm (OVERLOAD)                                          *
* Purpose : Returns Alarm Date in the referenced variable                  *
****************************************************************************
}
Sub ReadAlarm(ByRef pDate As TDate)
Dim dummy As Byte

SetAlarmPointer(VALYear) // Set pointer to start position

pDate.Year = BCDToDec(AlarmValLow) // Read Year
dummy = AlarmValHigh // Read Dummy to decrement pointer
pDate.Day = BCDToDec(AlarmValLow) // Read Day
pDate.Month = BCDToDec(AlarmValHigh) // Read month and decrement pointer
pDate.DayOfWeek = BCDToDec(AlarmValHigh) // Read Day of Week

End Sub

{
****************************************************************************
* Name    : Read                                                          *
* Purpose : Returns Time or Date in the referenced variable                *
****************************************************************************
}
Public Compound Sub GetAlarm(ReadAlarm)

{
****************************************************************************
* Name    : WriteAlarm (OVERLOAD)                                          *
* Purpose : Sets the Alarm Time in BCD format                              *
****************************************************************************
}       
Sub WriteAlarm(pTime As TTime)
Dim AlarmCurrent As Boolean

AlarmCurrent = AlarmEn // Get current state
AlarmEnable(false) // Ensure alarm is disabled
RTCWriteEnable(true)  // Enable writes                   
SetAlarmPointer(VALHours) // Set pointer to start position
AlarmValLow = DecToBCD(pTime.Hour) // Get Hour
SetAlarmPointer(VALMinutes) // Set pointer to Minutes / Seconds
AlarmValLow = DecToBCD(pTime.Second) // Get Seconds
AlarmValHigh = DecToBCD(pTime.Minute) // Get Minutes
RTCWriteEnable(false) // Disable writes
AlarmEnable(AlarmCurrent) // Reset current alarm state

End Sub 
{
****************************************************************************
* Name    : WriteAlarm (OVERLOAD)                                          *
* Purpose : Sets the Alarm Date in BCD format                              *
****************************************************************************
}       
Sub WriteAlarm(pDate As TDate)
Dim AlarmCurrent As Boolean

AlarmCurrent = AlarmEn // Get current state
AlarmEnable(false)    // Ensure alarm is disabled
RTCWriteEnable(true)    // Enable writes
SetAlarmPointer(VALYear) // Set pointer to start position
AlarmValLow = DecToBCD(pDate.Year)  // Get Year
SetAlarmPointer(VALMonth) // Set pointer to Month / Day
AlarmValLow = DecToBCD(pDate.Day) // Get Day
AlarmValHigh = DecToBCD(pDate.Month) // Get Month & decrement
AlarmValHigh = DecToBCD(pDate.DayOfWeek) // Get Day of week
RTCWriteEnable(false) // Disable writes
AlarmEnable(AlarmCurrent) // Reset current alarm state

End Sub 
{
****************************************************************************
* Name    : SetAlarm                                           *
* Purpose : Sets the Alarm, with its options                       *
****************************************************************************
}         
Public Compound Sub SetAlarm(WriteAlarm)

{
****************************************************************************
* Name    : SetAlarmMode                                           *
* Purpose : Sets the Alarm to the desired mode                      *
****************************************************************************
}       
Public Sub SetAlarmMode(pMask As Byte, pChime As Boolean = false, pRepeat As Byte = $00)

// Datasheet says ALRMCFG, ALRMRPT and CHIME should only be changed when RTCSync = 0
Repeat
Until RTCSync = false

AlarmChime = pChime // Chime? (Repeat the alarm forever, ignores pRepeat)
AlarmRepeat = pRepeat  // Repeat a limited number of times? $00 = Alarm once.

// Set the Alarm mask (see constants above for logic)
AlarmConfig = AlarmConfig And %11000011 // Zero the mask bits
AlarmConfig = AlarmConfig Or pMask // Set the mask bits

End Sub

{
****************************************************************************
* Name    : OutputEnable                                           *
* Purpose : Sets the Output enable to the desired mode                    *
****************************************************************************
}       
Public Sub OutputEnable(pState As Boolean, pMode As Byte = OUTAlarm)

// Disable Pin to prevent glitching
RTCOe = false

// Set desired mode
RTCPinConfig = RTCPinConfig And %11111001
RTCPinConfig = RTCPinConfig Or pMode

// Set pin state
RTCOe = pState

End Sub

{
****************************************************************************
* Name    : Initialize                                           *
* Purpose : Initializes the module                                        *
****************************************************************************
}       
Public Sub Initialize()
Dim
pTime As TTime,
pDate As TDate
 
pDate.Day = 1        // 1st
pDate.Month = 1      // January
pDate.Year = 12      // 2012
pDate.DayOfWeek = 0 // Sunday
pTime.Hour = 0      // 12 midnight
pTime.Minute = 0
pTime.Second = 0

Write(pTime, pDate) // Write the defaults

RTCEnable(true) // Enable the Module
 
End Sub
=]