;-------------------------------------------------------------------------
; MSP430-1121STK - MSP430F1121 STARTER KIT DEVELOPMENT BOARD
;-------------------------------------------------------------------------
; http://www.olimex.com/dev
;
; Hardware:   MSP430-1121STK-PCB-A
;             POWER 3V/2xAA BATTERIES, MCU MSP430F1121 / 32768 Hz crystall
;             2 pcs LEDs, 2 pcs BUTTONs, BUZZER, FREQUENCY INPUT
;             DALLAS INPUT, RS232 TX,RX
;             
; Date:       14.04.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  "msp430x11x1.h"

;-------------------------------------------
; PORT definitions
;-------------------------------------------
#define     FREQ_IN     BIT0                /* FREQUENCY       P1.0     */
#define     RS232TX     BIT1                /* RS232 Tx        P1.1     */
#define     B_RIGHT     BIT2,&P1IN          /* RIGHT BUTTON    P1.2     */
#define     DALLAS      BIT3                /* DALLAS          P1.3     */
#define     BUZ_1       BIT0,&P2OUT         /* BUZZER 1        P2.0     */
#define     B_LEFT      BIT1,&P2IN          /* LEFT BUTTON     P2.1     */
#define     RS232RX     BIT2                /* RS232 Rx        P2.2     */
#define     LED_LEFT    BIT3,&P2OUT         /* LEFT LED        P2.3     */
#define     LED_RIGHT   BIT4,&P2OUT         /* RIGHT LED       P2.4     */
#define     BUZ_2       BIT5,&P2OUT         /* BUZZER 2        P2.5     */

#define     P1DEF       00000010b           /* P1.x definitions         */
#define     P2DEF       00111001b           /* P2.x definitions         */

;-------------------------------------------
; Program constants
;-------------------------------------------
#define     Delta     150                   /* DCO 150*32768/4            */
#define     Bitime_5  64                    /* 9600 bps half bit          */
#define     Bitime    128                   /* 104 us bit time            */
#define     CR        0Dh                   /* ASCII CR                   */
#define     LF        0Ah                   /* ASCII LF                   */
#define     RXWAIT    0FFFFh                /* Host RX wait time constant */                                  
#define     w600us    00F3h                 /* 600 us delay               */
#define     w15us     0003h                 /* 15 us delay                */
#define     w60us     0008h                 /* 60 us delay                */
#define     w240us    0021h                 /* 240 us delay               */
;--------------------------------------------
; Register variables
;--------------------------------------------
#define     DSCNTR    R8                    /* Dallas routines counter      */
#define     FREQUENCY R9                    /* Beep frequency               */
#define     RXData    R10                   /* ISR RS232 buffer             */
#define     TXData    R11                   /* ISR RS232 buffer             */
#define     BitCnt    R12                   /* ISR RS232 bit counter        */
#define     SPTR      R13                   /* String RS232 send ptr        */
#define     TEMP      R14                   /* buzzer temp variable         */
#define     DCO_TR0   R14                   /* temprary registers for DCO   */
#define     CNTR      R15                   /* buzzer temp variable         */
#define     DCO_TR1   R15                   /* calibration                  */
                                            
;--------------------------------------------
; Code memory
;--------------------------------------------
            org     0F000h                  ;
            
RESET       mov.w   #0300h,SP               ;Initialize stackpointer
SetupWDT    mov.w   #WDT_ADLY_250,&WDTCTL   ;init WDT
SetupTA     mov.w   #TASSEL1+TACLR,&TACTL   ;Clear TAR & set TAR source = SMCLK
SetupBC     mov.b   #XT2OFF+DIVA1+RSEL2+RSEL0,&BCSCTL1   ; ACLK/4  RSEL=5
SetupC0     mov.w   #OUT,&CCTL0             ;TXD idle as mark 
                        
            bis.b   #RS232TX,&P1SEL         ;P1.1 to output TA0 for TXD to PC
            bis.b   #RS232RX,&P2SEL         ;P2.2 to input TA0 for RXD from PC
            mov.b   #P1DEF,&P1DIR           ;
            mov.b   #P2DEF,&P2DIR           ;
            mov.b   #BIT3+BIT4,&P2OUT       ;
                       
            bis.w   #MC1,&TACTL             ;Start Timer_A in continous mode
            call    #Delay                  ;Delay for crystal stabalization                  
            call    #Set_DCO                ;Calibrate DCO to 1228800 hz 
            eint                            ;General interrupt enable

            mov.w   #GREET,SPTR             ;MSP430-1121STK string display
            call    #TX_String              ;
            mov.w   #COPYR,SPTR             ;copyright(c) display
            call    #TX_String              ;
            mov.w   #WEB,SPTR               ;web address display
            call    #TX_String              ;            
            call    #RXSetup                ;setup RS232 receive            
;--------------------------------------------
mainloop                                    ;main loop
            bit.b   #B_RIGHT                ;right button pressed?
            jz      rbutton_pressed         ;
            bit.b   #B_LEFT                 ;left button pressed?
            jz      lbutton_pressed         ;
            bit     #CCIE,&CCTL0            ;received byte by RS232?
            jz      RX_complete             ;
            call    #DS_CHK                 ;Dallas iButton present
            jc      DS_present              ;
            jmp     mainloop                ;
;--------------------------------------------
DS_present                                  ;if Dallas iButton present
            bic.b   #LED_RIGHT              ;
            bic.b   #LED_LEFT               ;flash both LEDs & beep
            mov.b   #80h,FREQUENCY          ;
            mov.w   #0100h,CNTR             ;
            call    #Beep_0                 ;
            bis.b   #LED_RIGHT              ;
            bis.b   #LED_LEFT               ;
            jmp     mainloop                ;
;--------------------------------------------
rbutton_pressed                             ;right button pressed
            bic.b   #LED_RIGHT              ;
            call    #Beep_Hi                ;flash right LED & beep hi tone
            bis.b   #LED_RIGHT              ;
            mov.w   #RBPS,SPTR              ;
            call    #TX_String              ;
            call    #RXSetup                ;            
            jmp     mainloop                ;
;--------------------------------------------
lbutton_pressed                             ;left button pressed
            bic.b   #LED_LEFT               ;
            call    #Beep_Lo                ;flash left LED & beep lo tone
            bis.b   #LED_LEFT               ;
            mov.w   #LBPS,SPTR              ;
            call    #TX_String              ;
            call    #RXSetup                ;            
            jmp     mainloop                ;
;--------------------------------------------
RX_complete call    #Beep_rx                ;received char on RS232 port
            call    #RXSetup                ;convert ASCII code to sound
            jmp     mainloop                ;
;-------------------------------------------- 
Beep_rx     mov.w   RXData,FREQUENCY        ;Buzzer procedures
            rla.w   FREQUENCY               ;
            mov.w   #0100h,CNTR             ;
            jmp     Beep_0                  ;            
Beep_Hi     mov.w   #00E0h,FREQUENCY        ;
            mov.w   #0100h,CNTR             ;
            jmp     Beep_0                  ;
Beep_Lo     mov.w   #0120h,FREQUENCY        ;
            mov.w   #0100h,CNTR             ;            
Beep_0                                      ;
            bis.b   #BUZ_1                  ;
            bic.b   #BUZ_2                  ;
            mov.w   FREQUENCY,TEMP          ;
Beep_2                                      ;
            dec.w   TEMP                    ;
            jnz     Beep_2                  ;
            bis.b   #BUZ_2                  ;
            bic.b   #BUZ_1                  ;
            mov.w   FREQUENCY,TEMP          ;
Beep_3                                      ;
            dec.w   TEMP                    ;
            jnz     Beep_3                  ;            
            dec.w   CNTR                    ;
            jnz     Beep_0                  ;
            ret                             ;
;--------------------------------------------
; Dallas routines                           
;--------------------------------------------
DSdelay     dec.w   DSCNTR                  ;
            jnz     DSdelay                 ;
            ret                             ;
;--------------------------------------------
DS_CHK      bic.b   #DALLAS,&P1OUT          ;Dallas check present
            bis.b   #DALLAS,&P1DIR          ;            
            mov.w   #w600us,DSCNTR          ;
            call    #DSdelay                ;
            bic.b   #DALLAS,&P1DIR          ;
            mov.w   #w15us,DSCNTR           ;
            call    #DSdelay                ;
            bit.b   #DALLAS,&P1IN           ;
            jz      DS_CHK_0                ;
            mov.w   #w60us,DSCNTR           ;
DS_1        bit.b   #DALLAS,&P1IN           ;
            jz      DS_2                    ;
            dec.w   DSCNTR                  ;
            jnz     DS_1                    ;
            jmp     DS_CHK_0                ;
DS_2        mov.w   #w240us,DSCNTR          ;
DS_3        bit.b   #DALLAS,&P1IN           ;
            jnz     DS_CHK_1                ;
            dec.w   DSCNTR                  ;
            jnz     DS_3                    ;
DS_CHK_0    clrc                            ;
            ret                             ;
DS_CHK_1    setc                            ;
            ret                             ;            
;--------------------------------------------
; Calibrate DCO to 1228800 Hz (150*32768/4)
;--------------------------------------------
Delay       push    #0FFFFh                 ;
L1          dec     0(SP)                   ;
            jnz     L1                      ;
            incd    SP                      ;
            ret                             ;
;--------------------------------------------
Set_DCO     clr     DCO_TR0                 ;
Setup_CC2   mov     #CCIS0+CM0+CAP,&CCTL2   ;Define CCR2=ACLK,CAP mode,pos. edge
Test_DCO    bit     #CCIFG,&CCTL2           ;capture occured?
            jz      Test_DCO                ;
            bic     #CCIFG,&CCTL2           ;Yes, clear interrupt flag
AdjDCO      mov     &CCR2,DCO_TR0           ;
            sub     DCO_TR1,DCO_TR0         ;
            mov     &CCR2,DCO_TR1           ;
            cmp     #Delta,DCO_TR0          ;Delta = SMCLK/(32768/4)?
            jlo     IncDCO                  ;if lower increment DCO
            jeq     DoneDCO                 ;
DecDCO      dec.b   &DCOCTL                 ;if higher decrement DCO 
            jmp     Test_DCO                ;
IncDCO      inc.b   &DCOCTL                 ;
            jmp     Test_DCO                ;
DoneDCO     clr     &CCTL2                  ;
            ret                             ;
;--------------------------------------------
; UART routines                    
;--------------------------------------------
RXSetup     mov.b   #0,RXData               ;Setup for receiving from RS232
            mov     #RX_Count,BitCnt        ;
            mov     #CCIS0+CM1+CCIE+CAP+OUT,&CCTL0  ;Set up mode and interrupt
            ret                             ;
;--------------------------------------------
TX_String                                   ;Send ASCII strings, SPTR used as pointer
TX_S1       mov.b   @SPTR+,TXData           ;terminated with null character = 0
            call    #TX_Byte                ;
            tst.b   0(SPTR)                 ;
            jnz    TX_S1                    ;
            ret                             ;
;--------------------------------------------
TX_Byte     mov     #TX_Count,BitCnt        ;Transmit TXData character to RS232
            push    &TAR                    ;
            add     #Bitime,0(SP)           ;
            pop     &CCR0                   ;
            mov     #OUTMOD2+OUTMOD0+CCIE,&CCTL0  ;Set up mode and interrupt,
TX_Wait     bit     #CCIE,&CCTL0            ;TX complete? CCIE cleared in TA0_ISR
            jnz     TX_Wait                 ;
            ret                             ;
;--------------------------------------------
TA0_ISR     add    #Bitime,&CCR0            ;Add offset for next bit
            br     @BitCnt+                 ;Branch to next routine in 
                                            ;RX_count or TX_count table, set above
TX_Bit      rra.b  TXData                   ;LSB is shifted to carry
            jc     TX_Mark                  ;Jump if bit = 1
TX_Space    bis    #OUTMOD2,&CCTL0          ;TX space to PC 
            reti                            ;   
TX_Comp     bic    #CCIE,&CCTL0             ;All Bits TX, disable interrupt 
TX_Mark     bic    #OUTMOD2,&CCTL0          ;TX mark to PC 
            reti                            ;
RX_Edge     bic    #CAP,&CCTL0              ;Switch to compare mode
            add    #Bitime_5,&CCR0          ;First databit 1.5 bits from edge
            reti                            ;on stack. Use LPM0 since need DCO on  
RX_Bit      bit    #SCCI,&CCTL0             ;Get bit waiting in SCCI
            rrc.b  RXData                   ;Store received bit
            reti                            ;
RX_Comp     bic    #CCIE,&CCTL0             ;All bits RX, disable interrupt 
            reti                            ;
;--------------------------------------------
RX_Count    DW     RX_Edge                  ;Set up Timer_A for RX
            DW     RX_Bit                   ;RX first data bit
            DW     RX_Bit                   ;    second
            DW     RX_Bit                   ;    third
            DW     RX_Bit                   ;    fourth
            DW     RX_Bit                   ;    fifth
            DW     RX_Bit                   ;    sixth
            DW     RX_Bit                   ;    seventh
            DW     RX_Bit                   ; RX eighth (last) data bit
            DW     RX_Comp                  ; RX complete, process RX data
TX_Count    DW     TX_Bit                   ; TX first data bit
            DW     TX_Bit                   ;    second
            DW     TX_Bit                   ;    third
            DW     TX_Bit                   ;    fourth
            DW     TX_Bit                   ;    fifth
            DW     TX_Bit                   ;    sixth
            DW     TX_Bit                   ;    seventh
            DW     TX_Bit                   ; TX eighth (last) data bit
            DW     TX_Mark                  ; TX stop bit = mark
TX_End      DW     TX_Comp                  ; TX complete 
;--------------------------------------------
GREET       db      CR,LF,LF,"MSP430-1121 Starter kit"
COPYR       db      CR,LF,"Copyright(C) 2002, OLIMEX Ltd."
WEB         db      CR,LF,"http://www.olimex.com/dev"
RBPS        db      CR,LF,LF,"RIGHT button pressed!"
LBPS        db      CR,LF,LF,"LEFT  button pressed!"

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