; WRITTEN BY: TOM SCARFF ; DATE: 9/09/2002 ; ITERATION: 1.0 ; FILE SAVED AS: midimxr.ASM ; FOR: PIC16F877 ; CLOCK: 4.00 MHz CRYSTAL ; INSTRUCTION CLOCK: 1.00 MHz T= luS ; PROGRAMME FUNCTION: ; 8 analogue i/ps to MIDI out for volume and velocity list p=16F877 ; list directive to define processor #include "p16f877.inc" ; processor specific variable definitions __CONFIG _CP_ALL & _WDT_OFF & _BODEN_ON & _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. #DEFINE PAGE0 BCF 3,5 #DEFINE PAGE1 BSF 3,5 ;************************************************************* ; Constant Assignments ;************************************************************* CARRY EQU 0 ; CARRY BIT ;************************************************************** ; Variable Assignment Addresses ;************************************************************** ; rcvreg equ 20h count equ 21h vol equ 22h pot equ 23h midich equ 24h AD_DATA equ 25h dlyreg2 equ 26h dlyreg3 equ 27h ;************************************************************ ; PROGRAMME Reset Point ;************************************************************ org 00 ; reset vector goto init ;-------------------------------------------------------------------------- init PAGE1 movlw 0FFh movwf TRISB ;all pins inputs movwf TRISA ;all inputs clrf ADCON1 ; Set porta as analogue I/P's PAGE0 ; Set up USART PAGE1 bsf STATUS,RP0 ; goto page 1 movlw b'10001111' ; RC7 is RX input movwf TRISC 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 bsf STATUS,RP0 ; enable weak pull-up resistors movlw 07h ; rtcc/256 movwf OPTION_REG bcf STATUS,RP0 goto main ;------------------------------------------------------------------------- ;************************************ ; Switch Debounce Delay (100mS) ;************************************ sw_dbnc movlw 80h ; Delay routine movwf dlyreg2 debnce call delay3 decfsz dlyreg2,F goto debnce return ;************************************* ; Delay Subroutine (770uS) ;************************************* delay3 movlw .255 movwf dlyreg3 dly3 decfsz dlyreg3,F goto dly3 nop return ;****************************************** ; 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 ;********************************************* ; Start A/D conversion Subroutine ;********************************************* convert bsf ADCON0,2 ;set GO/DONE Bit btfsc ADCON0,2 goto $-1 rrf ADRESH,W andlw 07Fh movwf AD_DATA return ;************************************** ; Output MIDI Volume data ;************************************** vol_out movf pot,W addlw 0B0h ; Control Change ch. from midich movwf TXREG ; send character from W call txchar movlw 07h movwf TXREG ; send character from W call txchar movf vol,W movwf TXREG ; send character from W call txchar return ;*********************************************************************************************** ; Clear Fader Table ;*********************************************************************************************** clear_table MOVLW 60h ; MOVWF FSR ;first address CLRF INDF ;set to zero LOOPIT INCF FSR,F ; CLRF INDF ;set to zero MOVFW FSR ;copy position to w XORLW 06Fh ;have we reached the end BTFSS STATUS,Z ; 16 values 6f-60=0f=15 GOTO LOOPIT ;no so next one please ;yes job done RETURN ;************************************************************************ ; Check MIDI Channels 1-8 or 9-16 ;*********************************************************************** channels_chk btfss PORTB,5 ; is 1-8 sw. pressed? goto fad0_7 ; No, so go to goto fad8_15 fad0_7 bcf PORTC,4 ; switch LED off movlw 60h movwf FSR ; start of fader 0-7 data clrf pot return fad8_15 bsf PORTC,4 ; switch LED on movlw 68h movwf FSR ; start of fader 8-15 data movlw 08h movwf pot return ;**************************************************************** ; Main Programme ;**************************************************************** main call clear_table btfss PORTB,7 ; goto volume ; No, so go to goto velocity ;**************************************************************** ; Read Pots. ;**************************************************************** read_pots call convert call convert movf INDF,W subwf AD_DATA,W ; (f) - (W)--) (dest) btfsc STATUS,Z ; Skip if result not equal return movf AD_DATA,W andlw 07Fh movwf INDF ; move new value into table movwf vol ;;;; call sw_dbnc return ;**************************************************************** ; Volume Programme ;**************************************************************** volume bcf PORTC,5 call clear_table sw_chk1 call channels_chk movlw 08h movwf count rd_pots1 movlw .05 ; For address org 0500h movwf PCLATH movfw pot ; either 0 or 8 call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out movfw pot sublw 08h btfss STATUS,Z goto ch0_start goto ch8_start ;-------------------------------------------------------------------- ch0_start incf FSR,F ; 1 movlw 01h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 2 movlw 01h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 3 movlw 01h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 4 movlw 01h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 5 movlw 01h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 6 movlw 01h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 7 ch10 movlw 03h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;-------------------------------------------------------------------- ch8_start incf FSR,F ; 1 movlw 01h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 2 ch11 movlw 02h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 3 movlw 01h addwf pot,F movlw .05; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 4 movlw 01h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 5 movlw 01h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 6 movlw 01h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- incf FSR,F ; 7 ch16 movlw 01h addwf pot,F movlw .05 ; For address org 0500h movwf PCLATH call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call read_pots call vol_out ;------------------------- goto sw_chk1 ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ;**************************************************************** ; Velocity Programme ;**************************************************************** velocity bsf PORTC,5 start call channels_chk call rxdata ; is it status? movf rcvreg,W andlw 80h sublw 80h btfss STATUS,Z goto start midich? movf rcvreg,W ; Get MIDI Ch. andlw 0Fh movwf midich noteon? movf rcvreg,W andlw 0F0h sublw 90h btfsc STATUS,Z goto noteon noteoff? movf rcvreg,W andlw 0F0h sublw 80h btfsc STATUS,Z goto noteoff goto start ;------------------------------------------------ noteon movf rcvreg,W ; note-on + midich. movwf TXREG ; send character from W call txchar call rxdata ; Get note value range1 movf rcvreg,W movwf TXREG ; send character from W call txchar vel call rxdata; Get velocity byte movf rcvreg,W movlw .05 ; For address org 0500h movwf PCLATH movfw midich ; either 0 to 15 call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call convert call convert movf AD_DATA,W movwf TXREG ; send character from W call txchar runstat1 call rxdata ; status or note? movf rcvreg,W andlw 80h sublw 80h btfss STATUS,Z goto range1 ; if in running status goto start ;------------------------------------------------- noteoff movf rcvreg,W ; note-off + midich movwf TXREG ; send character from W call txchar call rxdata ; note-off value range2 movf rcvreg,W movwf TXREG ; send character from W call txchar offvel call rxdata ; vel-off value movf rcvreg,W movlw .05 ; For address org 0500h movwf PCLATH movfw midich ; either 0 to 15 call adc_tab ; selects A/D channel 0-7 movwf ADCON0 clrw movwf PCLATH call convert call convert movf AD_DATA,W movwf TXREG ; send character from W call txchar call rxdata ; status or note-off movf rcvreg,W andlw 80h sublw 80h btfss STATUS,Z goto range2 ; if in running status goto start ;------------------------------------------------ ;************************************** ; A/D Channel Table ;************************************** org 0500h adc_tab addwf PCL,F retlw B'01000001' ;0 adc0 retlw B'01001001' ;1 adc1 retlw B'01010001' ;2 adc2 retlw B'01011001' ;3 adc3 retlw B'01100001' ;4 adc4 retlw B'01101001' ;5 adc5 retlw B'01110001' ;6 adc6 retlw B'01000001' ;7 adc0 retlw B'01001001' ;8 adc1 retlw B'01111001' ;9 adc7 retlw B'01010001' ;10 adc2 retlw B'01011001' ;11 adc3 retlw B'01100001' ;12 adc4 retlw B'01101001' ;13 adc5 retlw B'01110001' ;14 adc6 retlw B'01111001' ;15 adc7 retlw 00 ;------------------------------ ;++++++++++++++++++++++++++++++++++++++++++++++++++++++ test1 call rxdata ; movf rcvreg,W movwf TXREG ; send character from W call txchar goto test1 ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++ end