       ; WRITTEN BY:           TOM SCARFF
       ; DATE:                 29/09/2002
       ; ITERATION:            1.1
       ; FILE SAVED AS:        mid_chan.ASM
       ; MODIFICATION: 		
	;			
       ; FOR:                  PIC16F877
       ; CLOCK:                4.00 MHz CRYSTAL                                        
       ; INSTRUCTION CLOCK:    1.00 MHz  T= luS
       ; PROGRAMME FUNCTION:   To read MIDI in and change all to specific channel
       ;                       and to transmit it out.


	list p=16F877           ; tells the assembler which PIC
	#include "p16F877.inc"  ; general register file



	__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _WRT_ENABLE_OFF & _LVP_OFF & _DEBUG_OFF & _CPD_OFF 



; '__CONFIG' directive is used to embed configuration data within .asm file.
; The lables following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.


;********************************
;  Variable Assignment Addresses
;   ( from 20h) for PIC16F877
;********************************


rcvreg    equ       20h
midich    equ       21h

	;************************************
       	;       PROGRAMME Reset Point
       	;************************************
              org     00               ; reset vector
              goto    init

;******************************************
;       Receive Data  subroutine
;******************************************

rxdata         btfss   PIR1,RCIF   ; test for incoming data
               goto     $-1
               movf    RCREG,W
	       movwf   rcvreg
               return

;******************************************
;       transmission complete subroutine
;***************+**************************

txchar   bsf       STATUS,RP0
                   btfss TXSTA,1   ; test for end of transmission
                   goto  $-1
                   bcf   STATUS,RP0
                   return


 
;******************************************
;       initalise software
;******************************************
    
init    bcf     STATUS,RP0      ;page 0
        clrf    PORTA
        clrf    PORTB
        clrf    PORTC
        clrf    PORTD
	clrf	PORTE
	
	
 	  bsf STATUS,RP0
	  MOVLW 6             
          MOVWF ADCON1        ;set port A as digital
          CLRF TRISA         ;all pins outputs
	  CLRF TRISB	     ;all pins outputs
          CLRF TRISD         ;all pins outputs   
	movlw	04h	; 0000 0100
        movwf    TRISE	; bit 2 i/p                   
          
	


        bcf STATUS,RP0          ; return to page 0
   
        
   
   ; Set up USART
   
           bsf     STATUS,RP0      ; goto page 1
           movlw   b'10001111'     ; RC7 is RX input
           movwf   TRISC	   ; RC0-3 i/p MIDI Ch.
           movlw   01h             ; 31250 baud for MIDI
           movwf   SPBRG
           movlw   b'00100000'     ; async tx 8 bit
           movwf   TXSTA
           bcf     STATUS,RP0              ; return to page 0
           movlw   b'10010000'     ; async rx 8 bit
           movwf   RCSTA
   
            clrw
	movwf midich

	clrf    PORTA ; set all outputs to '0000 0000'
        clrf    PORTB        
        clrf    PORTD
	movlw	04h	; 0000 0100
        movwf    PORTE	
	

	goto start

;************************************************



start     movf PORTC,W ; read midich. switches
          andlw 0Fh
          movwf midich	   

	  call rxdata ; is it status?
	  movf rcvreg,W
          andlw 80h
          sublw 80h
          btfss STATUS,Z
          goto start	; no

system?	  movf rcvreg,W ; is it System Message?
          andlw 0F0h
          sublw 0F0h
          btfss STATUS,Z ; 
          goto cont1	; no

	movf rcvreg,W	; yes, so
	sublw 0F0h
	btfsc STATUS,Z ; is it System Exclusive
	goto sys_excl

	movf rcvreg,W	; yes, so
	sublw 0F3h
	btfsc STATUS,Z ; is it Song Select
	goto midi_3byte

	movf rcvreg,W	; yes, so
	sublw 0F2h
	btfsc STATUS,Z ; is it Song Position Pointer
	goto midi_2byte

	movf rcvreg,W	; yes, so
	sublw 0F1h
	btfsc STATUS,Z ; is it MIDI Time Code
	goto midi_2byte

	movf rcvreg,W
	movwf TXREG	; no, so transmit 
	call txchar
	goto start

sys_excl
	movf rcvreg,W	
	movwf TXREG	
	call txchar

	call rxdata ; is it End of System Exclusive
	movf rcvreg,W        
        sublw 0F7h
        btfss STATUS,Z
	goto sys_excl ; no, keep outputting data

	movf rcvreg,W ; yes, so o/p 0F7h and re-start	
	movwf TXREG	
	call txchar
	goto start


cont1	movf rcvreg,W
	andlw 0F0h	; set midi channel = 0
	addwf midich,W	; add pre-set midich
	
	
	movwf TXREG	; transmit 
	call txchar
;-----------------------------

	  movf rcvreg,W
          andlw 80h
          sublw 80h
          btfss STATUS,Z
          goto midi_3byte

	  movf rcvreg,W
          andlw 90h
          sublw 90h
          btfss STATUS,Z
          goto midi_3byte

	  movf rcvreg,W
          andlw 0A0h
          sublw 0A0h
          btfss STATUS,Z
          goto midi_3byte


	  movf rcvreg,W
          andlw 0B0h
          sublw 0B0h
          btfss STATUS,Z
          goto midi_3byte

	  movf rcvreg,W
          andlw 0C0h
          sublw 0C0h
          btfss STATUS,Z
          goto midi_2byte


	  movf rcvreg,W
          andlw 0D0h
          sublw 0D0h
          btfss STATUS,Z
          goto midi_2byte


	  movf rcvreg,W
          andlw 0E0h
          sublw 0E0h
          btfss STATUS,Z
          goto midi_3byte
	
	goto start
;------------------------------------------------


midi_3byte
	  call rxdata  ; check 2nd value
range1    movf rcvreg,W
	 
	movwf TXREG	; transmit 
	call txchar


	call rxdata  ; check 3rd value
	movf rcvreg,W
	 
	movwf TXREG	; transmit 
	call txchar

	
	  call rxdata ; status or note?
          movf rcvreg,W
          andlw 80h
          sublw 80h
          btfss STATUS,Z
          goto range1 ; if in running status
          goto system?


;-------------------------------------------------


midi_2byte
	  call rxdata  ; check 2nd value
range2    movf rcvreg,W
	 
	movwf TXREG	; transmit 
	call txchar
	
	  call rxdata ; status or note?
          movf rcvreg,W
          andlw 80h
          sublw 80h
          btfss STATUS,Z
          goto range2 ; if in running status
          goto system?
;---------------------------------------------------


	end
