;-------------------------------------------
; UART SUBROUTINES
;
; LAST MODIFIED: 13.04.2002
;
; DISCLAIMER:
; 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
;-------------------------------------------------------------------------

;--------------------------------------------
; UART routines                    
;--------------------------------------------
RX          mov.b   #0,RXTXData             ;clear RXTXData
            call    #RX_Ready               ;Setup UART to receive
RX_LOOP     bit     #CCIE,&CCTL0            ;All bits RXed?, = interrupt disabled
                                            ;in RX_Comp routine 
            jz      RX_done                 ;Yes, then loop
            dec.w   INDEX                   ;
            jnz     RX_LOOP                 ;
RX_done     ret                             ;
;--------------------------------------------
TX_String                                   ;Send ASCII strings, SPTR used as pointer
                                            ;terminated with null character = 0
TX_S1       mov.b   @SPTR+,RXTXData         ;Move string start to data buffer
            call    #TX_Byte                ;Set up to send string
            tst.b   0(SPTR)                 ;Test if next character in string = 0,
                                            ;SPTR autoincremented above
            jnz    TX_S1                    ;If not "0" then loop again
            ret                             ;String complete, return 
;--------------------------------------------
TX_Byte_ASCII                               ;Convert and TX byte from DataConv 
                                            ;in two ASCII bytes
            push    DataConv                ;Save current value to stack
            call    #NUM_ASCIR              ;Convert value to ASCII
            push    DataConv                ;Save value again, cleaned off below
            call    #NUM_ASCIA              ;
            ret                             ;
NUM_ASCIR                                   ;Convert Numbers 0 to f into ASCII 
            rrc     2(SP)                   ;left aligned  @ 2(SP) 
            rrc     2(SP)                   ;hi nibble
            rrc     2(SP)                   ;
            rrc     2(SP)                   ;
NUM_ASCIA
            and     #0fh,2(SP)              ;clear high nibble
            add     #030h,2(SP)             ;convert to ASCII (0-9)
            cmp     #03ah,2(SP)             ;Value = 0 to 9 decimal? 
            jlo     NUM_End                 ;Yes, jump next instruction
            add     #039,2(SP)              ;No, adjust for hex values A to F 
NUM_End     mov     2(SP),RXTXData          ;load TX buffer, sent in TX_Byte below
            mov     @SP+,0(SP)              ;Clean up top of stack                                          
;--------------------------------------------
; Set up CCR0 to send byte via UART
; Program loops until all bits sent via TA0_ISR
;--------------------------------------------
TX_Byte     mov     #TX_Count,BitCnt        ;Routine labels (in TX_Count)->Pointer
            push    &TAR                    ;Save current Timer_A count to stack
            add     #Bitime,0(SP)           ;Add next bit offset to value on stack
            pop     &CCR0                   ;Load adjusted next bit offset to CCR0
            mov     #OUTMOD2+OUTMOD0+CCIE,&CCTL0  ;Set up mode and interrupt,
                                            ;TX space = start bit 
TX_Wait     bit     #CCIE,&CCTL0            ;TX complete? CCIE cleared in TA0_ISR
            jnz     TX_Wait                 ;No, loop again 
            ret                             ;
;--------------------------------------------
RX_Ready                                    ;Subroutine that readies UART to RX byte 
                                            ;into RXTXData buffer.
            mov     #RX_Count,BitCnt        ;Routine labels (in RX_Count)->Pointer
            mov     #CCIS0+CM1+CCIE+CAP+OUT,&CCTL0  ; Set up mode and interrupt
            ret 

;--------------------------------------------
; CCR0/UART interrupt service routine
; each interrupt transmits or receives one bit 
; from the PC until all 8 bits are complete
;--------------------------------------------
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  RXTXData                 ;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  RXTXData                 ;Store received bit
            reti                            ;
RX_Comp     bic    #CCIE,&CCTL0             ;All bits RX, disable interrupt 
            reti                            ;


;--------------------------------------------
; TIMER A ISR bit read/write table
;--------------------------------------------
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 

