#include  "msp430x11x1.h"
;******************************************************************************
;   MSP-FET430x110 Demo - Timer_A Ultra-low Power 1800hz detect, SMCLK +/- 1%
;
;   Description; Using Timer_A capture capability.  At 128ms intervals,
;   CCR0 is enabled on P2.2  to detect presence or absence of 1800Hz. If 
;   1800Hz is present, P1.0 is set, if not, reset.  Software FLL is use to set 
;   DCO (SMCLK)to 1MHz.  WDT is used for 128ms second wake-up to hunt for
;   tone. System runs normally in LPM3.  Watch crystal is required for ACLK.
;
;      921600kHz = SMCLK = DCOCLK
;        1800Hz  = 512 SMCLK clocks
;        1814Hz  = 508 SMCLK clocks 
;        1786Hz  = 516 SMCLK clock
;
;                 MSP430F1121
;             -----------------
;         /|\|              XIN|-  
;          | |                 | 32k
;          --|RST          XOUT|-
;            |                 |
;    Signal->|P2.2/CCR0    P1.0|-->LED
;            |                 |			 
;
;
;            CPU registers used
#define      Period R15
#define      OldCap R14
;
;            User definitions
Delta        equ    225                     ; Target DCO Clock/(32768/8)
;
;   M.Buccini
;   Texas Instruments, Inc
;   January 2002
;******************************************************************************
;------------------------------------------------------------------------------ 
            ORG     0F000h                  ; Program Start
;------------------------------------------------------------------------------ 
RESET       mov.w   #300h,SP		    ; Initialize stackpointer
SetupBC     bis.b   #DIVA1+DIVA0,&BCSCTL1   ; ACLK=LFXT1CLK/8 
SetupWDT    mov.w   #WDT_ADLY_16,&WDTCTL    ; WDT 16ms*8 Interval Timer 
            bis.b   #WDTIE,&IE1             ; Enable WDT Interrupt 
SetupP1     mov.b   #0FFh,&P1DIR            ; All P1.x Outputs
            clr.b   &P1OUT                  ; All P1.x Reset
SetupP2     mov.b   #0FBh,&P2DIR            ; P2.2 Input / All P2.x Output
            bis.b   #004h,&P2SEL            ; P2.2 CCR0 input
            clr.b   &P2OUT                  ; All P2.x Reset
            call    #Delay                  ; Time for crystal to stabilize								  ze
            call    #Set_DCO                ; St DCO to target frequency
            eint                            ; Enable Interrupts
                                            ;													  
Mainloop    bis.w   #LPM3,SR                ; Enter LPM3
            call    #Get_CCR0               ; Capture CCR0 on P2.2 
            cmp.w   #0516,Period            ;
            jhs     OFF                     ;
            cmp.w   #0508,Period            ;
            jlo     OFF                     ;
                                            ;
ON          bis.b   #001h,&P1OUT            ; P1.0 = 1
            jmp     Mainloop                ;  
OFF         bic.b   #001h,&P1OUT            ; P1.0 = 0
            jmp     Mainloop                ;  
                                            ;
;------------------------------------------------------------------------------ 
Get_CCR0; Subroutine to get CCR0 Capture
;------------------------------------------------------------------------------ 
            clr.w   Period                  ;
            clr.w   OldCap                  ;
            mov.w   #TASSEL1+TACLR,&TACTL   ; SMCLK, TAR cleared
SetupC0     mov.w   #CCIS0+CM0+CAP+CCIE+SCS,&CCTL0  ; CCI0B, CAP, interrupt
            bis.w   #MC1,&TACTL             ; Start timer in Ccntinous mode
Test_1      cmp.w   #02048,&TAR             ; Timeout
            jlo     Test_1                  ; jump if 02048 > &TAR
            clr.w   &TACTL                  ; Stop Timer_A
            clr.w   &CCTL0                  ; Stop CCTL0
            ret                             ;
                                            ;
;------------------------------------------------------------------------------ 
Delay;       Software delay
;------------------------------------------------------------------------------ 
            push.w  #0FFFFh                 ; Delay to TOS
L1          dec.w   0(SP)                   ; Decrement TOS
            jnz     L1                      ; Delay over?
            incd.w  SP                      ; Clean TOS
            ret                             ;
                                            ;
;------------------------------------------------------------------------------ 
Set_DCO;    Subroutine: Sets DCO to selected frequency based on Delta.
;           R14 and R15 are used, ACLK= 32768/8 Timer_A clocked by DCOCLK
;------------------------------------------------------------------------------ 
            clr.w   R15                     ;							
Setup_TA    mov.w   #TASSEL1+TACLR,&TACTL   ; SMCLK
Setup_CC2   mov.w   #CCIS0+CM0+CAP,&CCTL2   ; Define CCR2,CAP,ACLK									
            bis.w   #MC1,&TACTL             ; Start timer_A: Continous Mode
Test_DCO    bit.w   #CCIFG,&CCTL2           ; Test capture flag
            jz      Test_DCO                ;
            bic.w   #CCIFG,&CCTL2           ; Clear capture flag
                                            ;
AdjDCO      mov.w   &CCR2,R14               ; R14 = captured SMCLK
            sub.w   R15,R14                 ; R14 = capture difference
            mov.w   &CCR2,R15               ; R15 = captured SMCLK
            cmp.w   #Delta,R14              ; Delta = SMCLK/(32768/8)
            jlo     IncDCO                  ;
            jeq     DoneDCO                 ;
DecDCO      dec.b   &DCOCTL                 ; Slow DCO with DCO and MOD
            jnz     Test_DCO                ; Slower?
            bit.b   #07h,&BCSCTL1           ; Can RSEL.x be decremented?
            jz      DoneDCO                 ; jmp>DCO at slowest setting
            dec.b   &BCSCTL1                ; Decrement RSEL.x 
            jmp     Test_DCO                ;
IncDCO      inc.b   &DCOCTL                 ; Speed DCO with DCO and MOD
            jnc     Test_DCO                ; Faster?
            cmp.b   #07h,&BCSCTL1           ; Can RSEL.x be increased?
            jz      DoneDCO                 ; jmp> DCO at fastest settting
            inc.b   &BCSCTL1                ; Increment RSEL.x
            jmp     Test_DCO                ;
DoneDCO     clr.w   &CCTL2                  ; Stop CCR2
            clr.w   &TACTL                  ; Stop timer_A
            ret                             ; Return from subroutine
                                            ;                                            ;
;----------------------------------------------------------------------------- 
TA0_ISR;    Timer_A C0 ISR
;----------------------------------------------------------------------------- 
            push.w  &CCR0                   ; Captured TAR, rising edge
            mov.w   @SP,Period              ;
            sub.w   OldCap,Period           ; New - old = period
            pop.w   OldCap                  ; For next calculation
            reti                            ;
                                            ; 
;------------------------------------------------------------------------------ 
WDT_ISR;    Exit LPM3 on reti
;------------------------------------------------------------------------------ 
            bic.w    #LPM3,0(SP)            ; Clear LPM3 from TOS
            reti                            ;		 
                                            ; 
;------------------------------------------------------------------------------ 
;           Interrupt Vectors Used MSP430x11x1         
;------------------------------------------------------------------------------ 
            ORG     0FFFEh                  ; MSP430 RESET Vector
            DW      RESET                   ; 
            ORG     0FFF4h                  ; WDT Vector
            DW      WDT_ISR                 ; 
            ORG     0FFF2h                  ; Timer_A0 Vector
            DW      TA0_ISR                 ; 
            END
