;-------------------------------------------------------------------------
; MSP430-413STK - MSP430F413 STARTER KIT DEVELOPMENT BOARD
;-------------------------------------------------------------------------
; http://www.olimex.com/dev
;
; Hardware:   MSP430-413STK-PCB-B
;             POWER 3V/2xAA BATTERIES, MCU MSP430F413 / 32768 Hz crystall
;             LCD, 4 pcs BUTTONs, BUZZER, FREQUENCY INPUT
;             DALLAS INPUT, RS232 TX,RX
;             
; Date:       30.06.2002
;
; This software is provided "as is" for evaluation of our MSP430-1121STK
; development board. You are free to use this code in your projects, but 
; without warranty of any kind. If you can't understand how and what the 
; code does it's better to start by learning the MSP430 datasheets, and 
; assembly language, but don't call OLIMEX with questions regarding this 
; software. OLIMEX will not teach you how to write assembly language nor 
; how to use MSP430 peripherials, there is plenty of datasheets about them.
;
; (C) 2002 OLIMEX Ltd, All rights reserved
;-------------------------------------------------------------------------
#include  "include\msp430x41x.h"
;-------------------------------------------
; PORT definitions
;-------------------------------------------
#define     RS232TX     BIT0                /* RS232 Tx        P1.0     */
#define     RS232RX     BIT1                /* RS232 Rx        P1.1     */
#define     FREQ        BIT5                /* Frequency input P1.5     */

#define     P1DEF       00000001b

#define     DALLAS      BIT1                /* Dallas input    P2.1     */
#define     B4          BIT2,&P2IN          /* Button 4        P2.2     */
#define     B3          BIT3,&P2IN          /* Button 3        P2.3     */
#define     B2          BIT4,&P2IN          /* Button 2        P2.4     */
#define     B1          BIT5,&P2IN          /* Button 1        P2.5     */
#define     BUZ1        BIT6,&P2OUT         /* Buzzer line     P2.6     */
#define     BUZ2        BIT7,&P2OUT         /* Buzzer line     P2.7     */

#define     P2DEF       11000000b

;-------------------------------------------
; Program constants
;-------------------------------------------
#define     LCD_2D      0000000000000001b
#define     LCD_2E      0000000000000010b
#define     LCD_2DP     0000000000000100b
#define     LCD_3C      0000000000001000b
#define     LCD_3D      0000000000010000b
#define     LCD_3E      0000000000100000b
#define     LCD_3DP     0000000001000000b
#define     LCD_1_      0000000010000000b
#define     LCD_MINUS   0000000100000000b
#define     LCD_COM     0000001000000000b
#define     LCD_BAT     0000010000000000b
#define     LCD_PLUS    0000100100000000b
#define     LCD_ARR     0001000000000000b
#define     LCD_AC      0010000000000000b
#define     LCD_3G      0100000000000000b
#define     LCD_3F      1000000000000000b

#define     LCD_3A      0000000000000001b
#define     LCD_3B      0000000000000010b
#define     LCD_2C      0000000000000100b
#define     LCD_1DP     0000000000001000b
#define     LCD_1E      0000000000010000b
#define     LCD_1D      0000000000100000b
#define     LCD_1C      0000000001000000b
#define     LCD_1B      0000000010000000b
#define     LCD_1A      0000000100000000b
#define     LCD_1F      0000001000000000b
#define     LCD_1G      0000010000000000b
#define     LCD_2B      0000100000000000b
#define     LCD_2A      0001000000000000b
#define     LCD_2F      0010000000000000b
#define     LCD_2G      0100000000000000b
#define     LCD_L       1000000000000000b

#define     Bitime_5  128                   /* 9600 bps half bit          */
#define     Bitime    256                   /* 104 us bit time            */
#define     CR        0Dh                   /* ASCII CR                   */
#define     LF        0Ah                   /* ASCII LF                   */

;-------------------------------------------
; Register variables
;-------------------------------------------
#define     INDEX     R6                    /* INDEX EEPROM, RS232 RX       */
#define     BitCnt    R7                    /* ISR RS232                    */
#define     SPTR      R8                    /* String RS232 send ptr        */
#define     FREQUENCY R9                    /* Beep frequency               */
#define     HOURMIN   R10                   /* Hours : minutes              */
#define     SECONDS   R11                   /* Seconds RTC                  */
#define     TIME      R12                   /* 1 second counter             */
#define     LCD       R13                   /* LCD conversion register      */
 
#define     LCD_1REG  R14                   /* LCD register WDT_ISR         */
#define     LCD_2REG  R15                   /* LCD register WDT_ISR         */

;-------------------------------------------
; Data variables
;-------------------------------------------
            org     0200h                   ;RAM address

RXTXData          dw      1                 ;RS232 working word
DataConv          db      1                 ;HEX to ASCII converter variable
LCD_update_flag   db      1                 ;time to LCD update in main
Blink             db      1                 ;LCD blink sign

;-------------------------------------------
            org     0E000h                  ;Code memory
;-------------------------------------------
#include  "include\uart.h"

WDT_ISR                                     ;R14,R15 LCD registers
            xor.w   #0FFFFh,LCD_1REG        ;
            xor.w   #0FFFFh,LCD_2REG        ;
            mov.b   LCD_1REG,&P3OUT         ;
            push    LCD_1REG                ;
            swpb    LCD_1REG                ;
            mov.b   LCD_1REG,&P4OUT         ;
            pop     LCD_1REG                ;
            mov.b   LCD_2REG,&P5OUT         ;
            push    LCD_2REG                ;
            swpb    LCD_2REG                ;
            mov.b   LCD_2REG,&P6OUT         ;
            pop     LCD_2REG                ;
                     
            inc.w   TIME                    ;
            cmp.w   #040h,TIME              ;
            jz      RTC_CLOCK               ;
RTC_exit                                    ;
            reti                            ;

RTC_CLOCK   clr.w   TIME                    ;
            mov.b   #1,LCD_update_flag      ;
            clrc                            ;time update each second
            dadd.w  #0100h,SECONDS          ;
            cmp.w   #6000h,SECONDS          ;
            jne     RTC_exit                ;
            clrc                            ;
            dadd.w  #4000h,SECONDS          ;
            dadc.w  HOURMIN                 ;
            cmp.b   #60h,HOURMIN            ;
            jne     RTC_exit                ;
            clrc                            ;
            dadd.w  #0040h,HOURMIN          ;
            cmp.w   #1300h,HOURMIN          ;
            jne     RTC_exit                ;
            mov.w   #0100h,HOURMIN          ;
            jmp     RTC_exit                ;

LCD_update  bic.b   #WDTIE,&IE1             ;disable WDT
            clr.w   LCD_1REG                ;
            clr.w   LCD_2REG                ;
            push    LCD                     ;fisrt digit
            rlc.w   LCD                     ;
            and.w   #01Eh,LCD               ;
            bis.w   LCD_1(LCD),LCD_2REG     ;
            pop     LCD                     ;
            push    LCD                     ;second digit
            rrc.w   LCD                     ;
            rrc.w   LCD                     ;
            rrc.w   LCD                     ;
            and.w   #01Eh,LCD               ;
            bis.w   LCD_2a(LCD),LCD_2REG    ;
            bis.w   LCD_2b(LCD),LCD_1REG    ;
            pop     LCD                     ;
            push    LCD                     ;third digit
            rrc.w   LCD                     ;
            rrc.w   LCD                     ;
            rrc.w   LCD                     ;
            rrc.w   LCD                     ;
            rrc.w   LCD                     ;
            rrc.w   LCD                     ;
            rrc.w   LCD                     ;
            and.w   #01Eh,LCD               ;
            bis.w   LCD_3a(LCD),LCD_1REG    ;
            bis.w   LCD_3b(LCD),LCD_2REG    ;
            pop     LCD                     ;
            push    LCD                     ;forth digit
            and.w   #0F000h,LCD             ;
            cmp.w   #01000h,LCD             ;
            jnz      no1                    ;
            bis.w   #LCD_1_,LCD_1REG        ;
no1         pop     LCD                     ;
            tst.b   Blink                   ;
            jnz     noblink                 ;
            bis.w   #LCD_L,LCD_2REG         ;
noblink            
            bis.b   #WDTIE,&IE1             ;enable WDT
            ret                             ;

Delay       push    INDEX                   ;delay
            push    SPTR                    ;
            mov.w   #0,INDEX                ;
dly0        mov.w   #6,SPTR                ;
dly1        dec.w   SPTR                    ;
            jnz     dly1                    ;
            dec.w   INDEX                   ;
            jnz     dly0                    ;
            pop     SPTR                    ;
            pop     INDEX                   ;
            ret                             ;            

LCD_1    
            dw      LCD_1A+LCD_1B+LCD_1C+LCD_1D+LCD_1E+LCD_1F        ;0
            dw      LCD_1B+LCD_1C                                    ;1
            dw      LCD_1A+LCD_1B+LCD_1D+LCD_1E+LCD_1G               ;2
            dw      LCD_1A+LCD_1B+LCD_1C+LCD_1D+LCD_1G               ;3
            dw      LCD_1B+LCD_1C+LCD_1F+LCD_1G                      ;4
            dw      LCD_1A+LCD_1C+LCD_1D+LCD_1F+LCD_1G               ;5
            dw      LCD_1A+LCD_1C+LCD_1D+LCD_1E+LCD_1F+LCD_1G        ;6
            dw      LCD_1A+LCD_1B+LCD_1C                             ;7
            dw      LCD_1A+LCD_1B+LCD_1C+LCD_1D+LCD_1E+LCD_1F+LCD_1G ;8
            dw      LCD_1A+LCD_1B+LCD_1C+LCD_1D+LCD_1F+LCD_1G        ;9
            dw      LCD_1A+LCD_1B+LCD_1C+LCD_1E+LCD_1F+LCD_1G        ;A
            dw      LCD_1C+LCD_1D+LCD_1E+LCD_1F+LCD_1G               ;b
            dw      LCD_1A+LCD_1D+LCD_1E+LCD_1F                      ;C
            dw      LCD_1B+LCD_1C+LCD_1D+LCD_1E+LCD_1G               ;d
            dw      LCD_1A+LCD_1D+LCD_1E+LCD_1F+LCD_1G               ;E
            dw      LCD_1A+LCD_1E+LCD_1F+LCD_1G                      ;F
LCD_2a                                                  ;abcfg,LCD2_REG
            dw      LCD_2A+LCD_2B+LCD_2C+LCD_2F         ;0
            dw      LCD_2B+LCD_2C                       ;1
            dw      LCD_2A+LCD_2B+LCD_2G                ;2
            dw      LCD_2A+LCD_2B+LCD_2C+LCD_2G         ;3
            dw      LCD_2B+LCD_2C+LCD_2F+LCD_2G         ;4
            dw      LCD_2A+LCD_2C+LCD_2F+LCD_2G         ;5
            dw      LCD_2A+LCD_2C+LCD_2F+LCD_2G         ;6
            dw      LCD_2A+LCD_2B+LCD_2C                ;7
            dw      LCD_2A+LCD_2B+LCD_2C+LCD_2F+LCD_2G  ;8
            dw      LCD_2A+LCD_2B+LCD_2C+LCD_2F+LCD_2G  ;9
            dw      LCD_2A+LCD_2B+LCD_2C+LCD_2F+LCD_2G  ;A
            dw      LCD_2C+LCD_2F+LCD_2G                ;b
            dw      LCD_2A+LCD_2F                       ;C
            dw      LCD_2B+LCD_2C+LCD_2G                ;D
            dw      LCD_2A+LCD_2F+LCD_2G                ;E
            dw      LCD_2A+LCD_2F+LCD_2G                ;F
LCD_2b                                                  ;de,LCD1_REG
            dw      LCD_2D+LCD_2E                       ;0
            dw      0                                   ;1
            dw      LCD_2D+LCD_2E                       ;2
            dw      LCD_2D                              ;3
            dw      0                                   ;4
            dw      LCD_2D                              ;5
            dw      LCD_2D+LCD_2E                       ;6
            dw      0                                   ;7
            dw      LCD_2D+LCD_2E                       ;8
            dw      LCD_2D                              ;9
            dw      LCD_2E                              ;A
            dw      LCD_2D+LCD_2E                       ;b
            dw      LCD_2D+LCD_2E                       ;C            
            dw      LCD_2D+LCD_2E                       ;D
            dw      LCD_2D+LCD_2E                       ;E
            dw      LCD_2E                              ;F
            
LCD_3a                                                  ;cdefg,LCD_1REG
            dw      LCD_3C+LCD_3D+LCD_3E+LCD_3F         ;0
            dw      LCD_3C                              ;1
            dw      LCD_3D+LCD_3E+LCD_3G                ;2
            dw      LCD_3C+LCD_3D+LCD_3G                ;3
            dw      LCD_3C+LCD_3F+LCD_3G                ;4
            dw      LCD_3C+LCD_3D+LCD_3F+LCD_3G         ;5
            dw      LCD_3C+LCD_3D+LCD_3E+LCD_3F+LCD_3G  ;6
            dw      LCD_3C                              ;7
            dw      LCD_3C+LCD_3D+LCD_3E+LCD_3F+LCD_3G  ;8
            dw      LCD_3C+LCD_3D+LCD_3F+LCD_3G         ;9
            dw      LCD_3C+LCD_3E+LCD_3F+LCD_3G         ;A
            dw      LCD_3C+LCD_3D+LCD_3E+LCD_3F+LCD_3G  ;b
            dw      LCD_3D+LCD_3E+LCD_3F                ;C
            dw      LCD_3C+LCD_3D+LCD_3E+LCD_3G         ;D
            dw      LCD_3D+LCD_3E+LCD_3F+LCD_3G         ;E
            dw      LCD_3E+LCD_3F+LCD_3G                ;F
            
LCD_3b                                                  ;ab
            dw      LCD_3A+LCD_3B                       ;0
            dw      LCD_3B                              ;1
            dw      LCD_3A+LCD_3B                       ;2
            dw      LCD_3A+LCD_3B                       ;3
            dw      LCD_3B                              ;4
            dw      LCD_3A                              ;5
            dw      LCD_3A                              ;6
            dw      LCD_3A+LCD_3B                       ;7
            dw      LCD_3A+LCD_3B                       ;8
            dw      LCD_3A+LCD_3B                       ;9
            dw      LCD_3A+LCD_3B                       ;A
            dw      0                                   ;b            
            dw      LCD_3A                              ;C
            dw      LCD_3B                              ;D
            dw      LCD_3A                              ;E
            dw      LCD_3A                              ;F            
                        
           
;--------------------------------------------
; Code memory
;--------------------------------------------
RESET       mov.w   #0300h,SP               ;Initialize stackpointer
SetupWDT    mov.w   #WDT_ADLY_16,&WDTCTL    ;init WDT for 16ms
SetupTA     mov.w   #TASSEL1+TACLR,&TACTL   ;Clear TAR & set TAR source = SMCLK
            mov.b   #XCAP10PF,&FLL_CTL0     ;10 pf
            mov.b   #FLL_DIV_4,&FLL_CTL1    ;ACLK/4
            mov.b   #74,&SCFQCTL            ;fDCO=75*32768=2457600
            mov.w   #0FFFFh,INDEX           ;
wait0       dec.w   INDEX                   ;wait DCO to stabilize
            jnz     wait0                   ;
SetupC0     mov.w   #OUT,&CCTL0             ;TXD idle as mark 

            bis.b   #RS232TX+RS232RX,&P1SEL ;P1.0 to output TA0 for TXD to PC
                                            ;P1.1 to input TA0 for RXD from PC
            mov.b   #11111111b,&P1OUT       ;
            mov.b   #P1DEF,&P1DIR           ;
            bis.w   #MC1,&TACTL             ;Start Timer_A in continous mode
            mov.b   #P2DEF,&P2DIR           ;
            mov.b   #0FFh,P3DIR             ;P3-P6 outputs
            mov.b   #0FFh,P4DIR             ;
            mov.b   #0FFh,P5DIR             ;
            mov.b   #0FFh,P6DIR             ;
            mov.w   #LCD_COM,LCD_1REG       ;all segments ON
            mov.w   #0,LCD_2REG             ;

            mov.w   #0100h,HOURMIN          ;
            mov.w   #0,SECONDS              ;
            mov.b   #0,Blink                ;
            mov.w   #0,TIME                 ;
            mov.b   #0,LCD_update_flag      ;

            bis.b   #WDTIE,&IE1             ;enable WDT interrupts
            eint                            ;
            call    #LCD_update             ;update display            
mainloop                                    ;
            bit.b   #B2                     ;MINUTES++
            jnz     check_2                 ;
            bic.b   #WDTIE,&IE1             ;disable WDT            
            dadd.w  #01h,HOURMIN            ;
            cmp.b   #60h,HOURMIN            ;
            jne     chk1_exit               ;
            and.w   #0FF00h,HOURMIN         ;
chk1_exit   mov.w   HOURMIN,LCD             ;
            call    #LCD_update             ;update display            
            mov.w   #B2S,SPTR               ;B2 string
            call    #TX_String              ;
            call    #Beep_B2                ;
check_2
            bit.b   #B1                     ;HOURS++
            jnz     check_3                 ;
            bic.b   #WDTIE,&IE1             ;disable WDT
            dadd.w  #00100h,HOURMIN         ;
            cmp.w   #01300h,HOURMIN         ;
            jlo     chk2_exit               ;
            and.w   #000FFh,HOURMIN         ;
            bis.w   #00100h,HOURMIN         ;
chk2_exit   mov.w   HOURMIN,LCD             ;
            call    #LCD_update             ;update display            
            mov.w   #B1S,SPTR               ;B1 string
            call    #TX_String              ;
            call    #Beep_B1                ;
check_3
            bit.b   #B3                     ;HOURS++
            jnz     check_4                 ;
            mov.w   #B3S,SPTR               ;B2 string
            call    #TX_String              ;
            call    #Beep_B3                ;
check_4
            bit.b   #B4                     ;HOURS++
            jnz     check_exit              ;
            mov.w   #B4S,SPTR               ;B2 string
            call    #TX_String              ;
            call    #Beep_B4                ;
check_exit
            tst.b   LCD_update_flag         ;
            jz     mainloop                 ;
            mov.w   HOURMIN,LCD             ;
            call    #LCD_update             ;
            clr.b   LCD_update_flag         ;
            xor.b   #1,Blink                ;
            jmp     mainloop                ;

ERRVEC                                      ;
            jmp     ERRVEC                  ;
            reti                            ;

Beep_B1     mov.w   #0100h,FREQUENCY        ;
            mov.w   #00200h,SPTR            ;
            jmp     Beep_0                  ;
Beep_B2     mov.w   #0150h,FREQUENCY        ;
            mov.w   #00200h,SPTR            ;
            jmp     Beep_0                  ;
Beep_B3     mov.w   #01A0h,FREQUENCY        ;
            mov.w   #00200h,SPTR            ;
            jmp     Beep_0                  ;
Beep_B4     mov.w   #0200h,FREQUENCY        ;
            mov.w   #00200h,SPTR            ;
Beep_0                                      ;
            bis.b   #BUZ1                   ;
            bic.b   #BUZ2                   ;
            mov.w   FREQUENCY,INDEX         ;
Beep_2                                      ;
            dec.w   INDEX                   ;
            jnz     Beep_2                  ;
            bis.b   #BUZ2                   ;
            bic.b   #BUZ1                   ;
            mov.w   FREQUENCY,INDEX         ;
Beep_3                                      ;
            dec.w   INDEX                   ;
            jnz     Beep_3                  ;            
            dec.w   SPTR                    ;
            jnz     Beep_0                  ;
            ret                             ;

B1S         db      CR,LF,"B1 pressed!"
B2S         db      CR,LF,"B2 pressed!"
B3S         db      CR,LF,"B3 pressed!"
B4S         db      CR,LF,"B4 pressed!"

;--------------------------------------------
; Interrupt Vectors MSP430F413
;--------------------------------------------
            rseg    INTVEC
            dw      ERRVEC                   ;0 reserved
            dw      ERRVEC                   ;1 reserved
            dw      ERRVEC                   ;2 port 1 Vector
            dw      ERRVEC                   ;3 port 2 Vector
            dw      ERRVEC                   ;4 reserved
            dw      ERRVEC                   ;5 reserved
            dw      TA0_ISR                  ;6 TIMER_A CC0 Vector
            dw      ERRVEC                   ;7 reserved
            dw      ERRVEC                   ;8 TIMER_A CC1-2 TA Vector
            dw      ERRVEC                   ;9 reserved
            dw      WDT_ISR                  ;10 WDT Vector
            dw      ERRVEC                   ;11 Comparator Vector
            dw      ERRVEC                   ;12 reserved            
            dw      ERRVEC                   ;13 reserved
            dw      ERRVEC                   ;14 NMI Vector
            dw      RESET                   ;15 RESET Vector            
            END