;   File:SAMPLE5.ASM
;    PIC: 16F877 @ 20Mhz
;   Date: 10-Feb-2003
; Author: Joe Farr
;---------------------------------------------------------------------
; Description:
; Sends 100 blocks of 258 bytes (256 data + 2 trailer) to the
; serial port.
; On receipt of a 'G' command from the PC, the PIC waits for 'B'
; command and then sends a 258 byte block. The PIC again waits for a 'B'
; command before sending the next block.
; The block being sent is reflected on the PORTB LEDS.
; Each block contains ASCII codes (0 to 255).
;
; The PIC waits for a character before sending back the ASCII block
;
;---------------------------------------------------------------------
; Config register bits from the TK3 Config PIC screen
; CP1  CP0  DBG  NIL  WRT  CPD  LVP  BOR  CP1 CP0  POR  WDT  OS1  OS0
;  1    1    1    1    1    1    0    0    1   1    0    0    1    0
; N.B. Logic 1/0 do NOT necessarily mean that the function is On/Off
; respectively - refer ro PIC '87 data sheet.
;---------------------------------------------------------------------
;
; I/O Port Usage Map
; PORT     Usage
;------------------------------------------
; A0 - A5  N/U
; B0       LED 0 (LSB)
; B1       LED 1
; B2       LED 2
; B3       LED 3
; B4       LED 4
; B5       LED 5
; B6       LED 6
; B7       LED 7 (MSB)
; C0 - C5  N/U
; C6 	   RS232 from PIC to Interface Card
; C7 	   RS232 from Interface Card to PIC
; D0 - D7  N/U
; E0 - E2  N/U
;---------------------------------------------------------------------

	LIST p=16f877,c=140,n=999
        errorlevel 1,-(305)
        include "p16f877.inc"

BLK  	equ     0x24            ; Stores the block number we are sending
BYT  	equ     0x25            ; Stores the byte number we are sending

	org 	0
        clrf 	STATUS
        goto 	BootStart
        org 	4
ISR     goto 	5            	; Setup Interupt Address
	org 	5


BootStart
  	clrf  	PORTB

        bsf 	STATUS,RP0  	; set RAM Page 1 for TRIS registers
        movlw 	b'00000000'
        movwf   TRISB           ; set PORTB for all outputs

;
; Configure the baud rate generator
;
        movlw   d'64'           ; 19.2K Baud with 20MHz XTAL (See PIC data sheet for these values)
	movwf   SPBRG           ; In bank 1
        movlw   b'00100100'     ; BRGH = 1(High speed) & ASYNC transmission
        movwf   TXSTA           ; In bank 1
        bcf 	STATUS,RP0  	; back to RAM page 0
        movlw   b'10010000'     ; ASYNC reception
        movwf   RCSTA           ; In bank 0
        call 	FlushRXBuffer   ; Flush the RX buffer in bank 0

LoopAgain
        movlw   0xFF
        movwf   PORTB           ; All PORTB bits on - Waiting for 'G'

WaitG 				; Wait for any character to be received
        call 	FlushRXBuffer   ; Make sure that the RX buffer is empty
        call    RecLoop         ; Wait and read from serial - character returned in W
        sublw   'G'             ; Is this a 'G'
        btfss   STATUS,Z
        goto    WaitG           ; Not a 'G'

;
; 'G' has been received - Confirm ready state back to PC
        movlw   'R'             ; Signal 'R'eady
        call    TxByte

;
; Start sending the blocks
;
	clrf    BLK            	; Reset the Block counter = 0

;
; First, wait for the PC to send us a 'B' command (Send block)
;
WaitB
	movlw   0x80
	movwf   PORTB           ; MSB PORTB Led ON - Waiting for a 'B' command

	call 	FlushRXBuffer   ; Make sure that the RX buffer is empty
        call    RecLoop         ; Wait and read from serial - character returned in W
        movwf   PORTB
        sublw   'B'             ; Is this a 'B'
        btfss   STATUS,Z
        goto    WaitB           ; Not a 'B'
;
; 'B' recevied, send a block
;
	movlw   0x00            ; Reset the byte counter
        movwf   BYT             ; BYT = W
SendNext
        movf    BLK,W           ; W = Block number being sent (this is the data we are going to send)
	movwf   PORTB           ; Display block number on PORTB LEDS
	call    TxByte          ; send W to serial port

        movf    BYT,W           ; W = BYT
        addlw 	B'1'            ; W = W + 1
        btfsc   STATUS,Z        ; Test Zero (Z) bit of STATUS - if 1 then we've reached zero and there are no more characters in this block to send
	goto    NextBlock       ; At 0, send next character
        movwf   BYT             ; BYT = W
        goto    SendNext
NextBlock
; Data portion of the block has been sent
; Now send the Block terminator
        movlw   0x0D            ; CR
        call    TxByte
        movlw   0x0A            ; LF
        call    TxByte

; Setup for the next Block
        incf    BLK,F           ; BLK = BLK + 1
        goto    WaitB


;
; Receive a character from RS232
; (This routine does not return until a character has been received)
; The received character is in the W register
;
RecLoop
        nop
        btfss   PIR1,RCIF       ; Check for any RX'd data
        goto 	RecLoop         ; Nothing RX'd
        movf    RCREG,W         ; Store the RX'd data in 'W'
        return

;
; Send a byte 'W' to the USART
;
TxByte
        nop
        btfss   PIR1,TXIF       ; TX Buffer empty yet ?
        goto    TxByte          ; No - Keep waiting
        movwf   TXREG           ; Now empty - send this character
        return

;
; Flush the contents of the RX Buffer
;
FlushRXBuffer
	movf    RCREG,W        	; Flush the RX buffer in bank 0
        movf    RCREG,W
	movf    RCREG,W
        return

        end                     ; end of program