;*******************************************************************************
;                                                                              *
;    Filename:            uart-test.asm                                        *
;    Date:                2016-10-09                                           *
;    File Version:        "$Revision: 1.6 $"                                                     *
;    Author:              Andy Fletcher                                        *
;    Description:         UART test in assembler                               *
;   
; String output based on http://www.phanderson.com/PIC/16C84/mult_string.html
    ; BCD routine from Microchip AN526
;                                                                              *
;*******************************************************************************

    LIST R=DEC
    INCLUDE "p16f887.inc"

#define DEBUG_LED PORTA, 4
#define PON_LED PORTA, 5

    __CONFIG _CONFIG1, _WDTE_OFF & _PWRTE_OFF & _CP_OFF & _BOREN_ON & _FCMEN_ON & _MCLRE_OFF & _CPD_OFF & _IESO_ON & _FOSC_INTRC_CLKOUT & _LVP_OFF
 
    extern B2_BCD, H_byte, L_byte, R0, R1, R2
    extern delay1s
 
    udata
count res 2
index res 1
str_num res 1

;*******************************************************************************
; Reset Vector
;*******************************************************************************

RES_VECT  CODE    0x0000            ; processor reset vector
    banksel START
    GOTO    START                   ; go to beginning of program

; No ISR

;*******************************************************************************
; MAIN PROGRAM
;*******************************************************************************
 
;MAIN_PROG CODE                      ; let linker place main program

START

    ;
    ;   configure i/o ports
    ;   configure all as digital unless needed otherwise
    ;
    banksel ANSEL
    clrf ANSEL & 0x7F
    banksel ANSELH
    clrf ANSELH & 0x7F

    banksel CM1CON0
    clrf CM1CON0 & 0x7F			; disable comparators
    banksel CM2CON0
    clrf CM2CON0 & 0x7F

    banksel PORTA
    clrf PORTA
    banksel TRISA
    movlw b'001111'			; all of PORTA are inputs 
    movwf TRISA	& 0x7F	; except RA5 (PON LED) and RA4 (DEBUG LED)

    banksel PORTA   
    bsf PON_LED				; turn on the power-on LED
    
    movlw 0xff				; all of PORTB are inputs
    movwf TRISB & 0x7F     

    banksel TRISC
    movlw b'10111111' 		; all of PORTC are inputs except EUSART TX
    movwf TRISC & 0x7F   

    movlw 0xff				; all of PORTD are inputs
    movwf TRISD & 0x7F     
   
    movlw 0xff				; all of PORTE are inputs
    movwf TRISB & 0x7F     

;   set clock to 8MHz
    movlw b'1110000'		; set IRCF0-2
    banksel OSCCON
    movwf OSCCON & 0x7F

;   and tune to around 8MHz
    clrf OSCTUNE & 0x7F

;   set EUSART baud rate to 19200, assuming a 8MHz clock
    banksel TXSTA
    bsf TXSTA & 0x7F, BRGH

    banksel BAUDCTL
    bcf BAUDCTL & 0x7F, BRG16

    banksel SPBRGH
    clrf SPBRGH & 0x7F

    movlw 25
    banksel SPBRG
    movwf SPBRG & 0x7F
;   
;   enable EUSART TX
;
    banksel TXSTA
    bsf TXSTA & 0x7F, TXEN

    bcf TXSTA & 0x7F, SYNC

    banksel RCSTA
    bsf RCSTA, SPEN
	
;   init the count
    clrf count
    clrf count + 1

;   
;   loop forever
;
loop:
    ; 
    ; print some characters
    ;
    ;   "UART Test"
    movlw 0		
    movwf str_num
    call out_str
;	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    movlw 1
    movwf str_num
    call out_str
    movlw 2
    movwf str_num
    call out_str
; 	 "abcdefghijklmnopqrstuvwxyz0123456789"
    movlw 3
    movwf str_num
    call out_str
    movlw 4
    movwf str_num
    call out_str
    movlw 5
    movwf str_num
    call out_str
; 	 convert count to BCD
    banksel count
    clrf H_byte
    movf count, w
    movwf L_byte
    call B2_BCD
; 	 print the count
    movf R0, w
    andlw 0x0F
    iorlw 0x30
    call uart_out
    swapf R1, w
    andlw 0x0F
    iorlw 0x30
    call uart_out
    movf R1, w
    andlw 0x0F
    iorlw 0x30
    call uart_out
    swapf R2, w
    andlw 0x0F
    iorlw 0x30
    call uart_out
    movf R2, w
    andlw 0x0F
    iorlw 0x30
    call uart_out
; 	 new line
    movlw 6
    movwf str_num
    call out_str

;   increment the count, allowing wraparound
    incf count, f
    
; 	turn on the debug LED
    banksel PORTA
    bsf DEBUG_LED
; 	wait a second
    call delay1s
; 	 turn off the debug LED
    banksel PORTA
    bcf DEBUG_LED
; 	wait a second 
    call delay1s

    goto loop
	
    ;
    ; string output routines
    ;
out_str:
    movf str_num, w
    call get_str_addr
    movwf index
	
out_str_char:
    movf index, w
    call get_str_char
    addlw 0			; perform an arithmetic function to set z flag
    banksel STATUS
    btfsc STATUS, Z
      return		; character was 00h

    call uart_out
    incf index, f
    goto out_str_char

get_str_addr:
    banksel PCL
    addwf PCL, f
    retlw uart_test - str_base
    retlw alpha_uc_1 - str_base
    retlw alpha_uc_2 - str_base 
    retlw alpha_1c_1 - str_base
    retlw alpha_1c_2 - str_base
    retlw digits - str_base
    retlw newline - str_base
	
uart_out:
    banksel PIR1
    btfss PIR1, TXIF
    goto uart_out 
    banksel TXREG
    movwf TXREG
    return

    ;
    ; strings table
    ;
get_str_char:
    addwf PCL, f
str_base:	
uart_test:
    dt 0aH, 0dH, "UART Test", 0dH, 0aH, 00H
alpha_uc_1:
    dt "ABCDEFGHIJKLM", 00H
alpha_uc_2:
    dt "NOPQRSTUVWXYZ", 0dH, 0aH, 00H
alpha_1c_1:
    dt "abcdefghijklm", 00H
alpha_1c_2:
    dt "nopqrstuvwxyz", 00H
digits:
    dt "0123456789", 0dH, 0aH, 00H
newline:
    dt 0dH, 0aH, 00H
	
    END






