;******************************************************************************
;  MSP430FG5438 - Real Time Clock Workaround
;
;  Description: This program demonstrates the RTC Workaround for the RTC
;  Errata deailed in the XMS '5438 Errata under RTC3
;  Assembly functions for the RTC workaround
;  Allows safe access to the RTC registers that potentially have a write issue
;  Code is aligned so that the lower 5 bits of the address of the instruction
;  fetch following the RTC register write are equal
;  Do not change the code in the ASM file (.s43) all nops in there are needed.
;
;  Texas Instruments Inc.
;  October 2008
;  Built with CCE version 3.2.2
;
;*******************************************************************************
; !!!!!! Do not change the code. Every nop has a function !!!!!!
;*******************************************************************************

            .cdecls C,LIST,"msp430x54x.h"   ; Include device header file

;-------------------------------------------------------------------------------
            .text                           ; Progam Start
;-------------------------------------------------------------------------------
            .align  32
;-------------------------------------------------------------------------------
            .global SetRTCYEAR
; int SetRTCYEAR(int year)
; year will be set in the RTCYEAR register
; return value is read back from the RTCYEAR register
; Works only in calendar mode (RTCMODE = 1)
; argument year is in R12
; return value is in R12
SetRTCYEAR: nop
            nop
            nop
            nop
            dint
            nop
            nop
            nop
            mov.w   R12,&RTCYEAR            ; Set RTCYEAR to year 		
            nop
            nop
            mov.w   &RTCYEAR,R12            ; Return value
            nop
            eint
            nop
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif
            
            
;-------------------------------------------------------------------------------
			.global	SetRTCMON
; int SetRTCMON(int month)
; month will be set in the RTCMON register
; Workaround requires to write 16 bits into RTCDATE
; return value is read back from the RTCMON register
; argument month is in R12
; return value is in R12
SetRTCMON:  push.w  R5                      ; push R5
            mov.b   &RTCDAY,R5              ; read RTCDAY into R5
            swpb    R12                     ; R12 holds month - swap lower and upper byte
            bis.w   R12,R5                  ; combine read RTCDAY and new RTCMON
            dint
            nop
            mov.w   R5,&RTCDATE             ; write to RTCDATE		
            nop
            nop
            nop
            nop
            eint
            nop
            mov.b   &RTCMON,R12             ; Read RTCMON register
            pop.w   R5                      ; pop R5
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif
;-------------------------------------------------------------------------------
			.global	SetRTCDAY
; int SetRTCDAY(int day)
; day will be set in the RTCDAY register
; Workaround requires to write 16 bits into RTCDATE
; return value is read back from the RTCDAY register
; argument day is in R12
; return value is in R12
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
SetRTCDAY:                                  ; R12 holds day in lower byte
            push.w  R5                      ; push R5
            mov.b   &RTCMON,R5              ; read RTCMON into lower byte of R5
            swpb    R5                      ; month is now in higher byte of R5
            bic.w   #00FFh,R5               ; clear lower byte of R5
            bis.w   R12,R5                  ; combine read RTCDAY and new RTCMON
            dint
            nop
            mov.w   R5,&RTCDATE             ; write to RTCDATE		
            nop
            eint
            nop
            mov.b   &RTCDAY,R12             ; Read RTCDAY register
            pop.w   R5                      ; pop R5
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif
;-------------------------------------------------------------------------------
            .global	SetRTCDOW
; int SetRTCDOW(int dow)
; dow will be set in the RTCDOW register
; Workaround requires to write 16 bits into RTCTIM1
; return value is read back from the RTCDOW register
; argument dow is in R12
; return value is in R12
SetRTCDOW:  push.w  R5                      ; push R5
            mov.b   &RTCHOUR,R5             ; read RTCHOUR into R5
            swpb    R12                     ; R12 holds dow - swap lower and upper byte
            bis.w   R12, R5                 ; combine read RTCHOUR and new RTCDOW
            dint
            nop
            mov.w   R5,&RTCTIM1             ; write to RTCTIM1		
            nop
            eint
            nop
            mov.b   &RTCDOW,R12             ; Read RTCDOW register
            pop.w   R5                      ; pop R5
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif
;-------------------------------------------------------------------------------
            .global	SetRTCHOUR
; int SetRTCHOUR(int hour)
; hour will be set in the RTCHOUR register
; Workaround requires to write 16 bits into RTCTIM1
; return value is read back from the RTCHOUR register
; argument hour is in R12
; return value is in R12
SetRTCHOUR:                                 ; R12 holds day in lower byte
            push.w  R5                      ; push R5
            mov.b   &RTCDOW,R5              ; read RTCDOW into lower byte of R5
            swpb    R5                      ; dow is now in higher byte of R5
            bis.w   R12,R5                  ; combine read RTCDOW and new RTCHOUR
            dint
            nop
            nop
            mov.w   R5,&RTCTIM1             ; write to RTCTIM1		
            nop
            eint
            nop
            mov.b   &RTCHOUR,R12            ; Read RTCHOUR register
            pop.w   R5                      ; pop R5
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif
;-------------------------------------------------------------------------------
            .global	SetRTCMIN
; int SetRTCMIN(int min)
; min will be set in the RTCMIN register
; Workaround requires to write 16 bits into RTCTIM0
; return value is read back from the RTCDOW register
; argument min is in R12
; return value is in R12
SetRTCMIN:  push.w  R5                      ; push R5
            mov.b   &RTCSEC, R5             ; read RTCSEC into R5
            swpb    R12                     ; R12 holds min - swap lower and upper byte
            bis.w   R12,R5                  ; combine read RTCMIN and new RTCSEC
            dint
            nop
            mov.w   R5,&RTCTIM0             ; write to RTCTIM0
            nop
            eint
            nop
            mov.b   &RTCMIN,R12             ; Read RTCDOW register
            pop.w   R5                      ; pop R5
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif
;-------------------------------------------------------------------------------
            .global	SetRTCSEC
; int SetRTCSEC(int sec)
; sec will be set in the RTCSEC register
; Workaround requires to write 16 bits into RTCTIM0
; return value is read back from the RTCSEC register
; argument sec is in R12
; return value is in R12
SetRTCSEC:                                  ; R12 holds day in lower byte
            push.w  R5                      ; push R5
            mov.b   &RTCMIN, R5             ; read RTCMIN into lower byte of R5
            swpb    R5                      ; min is now in higher byte of R5
            bis.w   R12, R5                 ; combine read RTCMIN and new RTCSEC
            dint
            nop
            nop
            mov.w   R5,&RTCTIM0             ; write to RTCTIM0		
            nop
            eint
            nop
            mov.b   &RTCSEC, R12            ; Read RTCSEC register
            pop.w   R5                      ; pop R5
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif
;-------------------------------------------------------------------------------	

            .global GetRTCTIM0
; Read the RTC registers RTCTIM0
; return the values 
GetRTCTIM0:
            mov.w   &RTCTIM0,R12
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif

            .global GetRTCTIM1
; Read the RTC register RTCTIM1
; return the values 
GetRTCTIM1:
            mov.w   &RTCTIM1,R12
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif

            .global GetRTCDATE
; Read the RTC register RTCDATE
; return the values 
GetRTCDATE:
            mov.w   &RTCDATE,R12
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif

            .global GetRTCYEAR
; Read the RTC registers RTCYEAR
; return the values 
GetRTCYEAR:
            mov.w   &RTCYEAR, R12
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif

            .global GetRTCMON
; Read the RTC register RTCMON
; return the values 
GetRTCMON:
            mov.b   &RTCMON, R12
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif

            .global GetRTCDOW
; Read the RTC register RTCDOW
; return the values 
GetRTCDOW:
            mov.b   &RTCDOW, R12
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif

            .global GetRTCDAY
; Read the RTC register RTCDOW
; return the values 
GetRTCDAY:
            mov.b   &RTCDAY, R12
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif

            .global GetRTCHOUR
; Read the RTC register RTCDOW
; return the values 
GetRTCHOUR:
            mov.b   &RTCHOUR, R12
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif

            .global GetRTCMIN
; Read the RTC register RTCDOW
; return the values 
GetRTCMIN:
            mov.b   &RTCMIN, R12
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif

            .global GetRTCSEC
; Read the RTC register RTCDOW
; return the values 
GetRTCSEC:
            mov.b   &RTCSEC, R12
            .if     $isdefed("__LARGE_CODE_MODEL__") = 0
            ret
            .else
            reta
            .endif

