; WRITTEN BY: TOM SCARFF ; DATE: 18/03/2003 ; ITERATION: 1.1 ; FILE SAVED AS: prg_chx8.ASM ; MODIFICATION: ; ; FOR: PIC16F877 ; CLOCK: 4.00 MHz CRYSTAL ; INSTRUCTION CLOCK: 1.00 MHz T= luS ; PROGRAMME FUNCTION: To read MIDI in and detect Program Change ; and to transmit it to 8 (relay) outs. ; Record Mode reads switches and stores them with ; associated program change (to midi out and operates relays). list p=16F877 ; tells the assembler which PIC #include "p16F877.inc" ; general register file ;******************************** ; Constant Assignments ;******************************** RCIF equ 05h BORROW equ 0h ;******************************** ; Variable Assignment Addresses ;***t**************************** ; 20h Start of General purpose registers select EQU 21h output EQU 22h dlyreg2 equ 23h dlyreg3 equ 24h drum equ 25h val1 equ 26h val2 equ 27h rcvreg equ 28h midich equ 29h count equ 2Ah none_eq equ 2Bh eeprom_data equ 2Ch note equ 2Dh eeprom_addr equ 2Eh temp equ 2Fh prog_ch equ 30h switches equ 31h ; 7fh end of data area ;************************************ ; PROGRAMME Reset Point ;************************************ org 00 ; reset vector goto init ;************************************ ; Switch Debounce Delay 255mS ;************************************ sw_dbnc movlw .20 ; Delay routine variable movwf dlyreg2 debnce call delay3 decfsz dlyreg2 goto debnce return ;************************************* ; Delay Subroutine (1 mS) ;************************************* delay3 movlw .165 movwf dlyreg3 dly3 decfsz dlyreg3 goto dly3 movlw .165 movwf dlyreg3 dly4 decfsz dlyreg3 goto dly4 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 ;****************************************** ; Output Program Change ;****************************************** prog_ch_out movf midich,W addlw 0C0h ; Control Change ch. from midich movwf TXREG ; send character from W call txchar movf prog_ch,W andlw 07Fh movwf TXREG ; send character from W call txchar return ;************************************ ; EEPROM Read for 16F877 ; ENTRY: W=address ; RETURN: W=data ;************************************ ee_read bcf STATUS,RP0 bsf STATUS,RP1 ; bank 2 movwf EEADR bsf STATUS,RP0 bsf STATUS,RP1 ; bank 3 bcf EECON1,EEPGD bsf EECON1,RD r1 btfsc EECON1,RD ; Wait to finish read. goto r1 bcf STATUS,RP0 ; now bank 2 movf EEDATA,W ;;;;;;; andlw 07Fh ; prevent value >127 bcf STATUS,RP1 ; now bank 0 return ;************************************ ; EEPROM Write for 16F877 ; ENTRY: eeprom_addr=address, eeprom_data=data ; RETURN: ------- ;************************************ ee_write bsf STATUS,RP1 bsf STATUS,RP0 ;writing to eeprom, bank 3 btfsc EECON1,WR; is write finished? goto $-1 bcf STATUS,RP1 bcf STATUS,RP0 ; bank 0 movf eeprom_addr,W; start addr. EEPROM bsf STATUS,RP1 ; bank 2 movwf EEADR bcf STATUS,RP1 ; bank 0 movf eeprom_data,W ;;;;;; andlw 07Fh bsf STATUS,RP1 ; bank 2 movwf EEDATA bsf STATUS,RP0 ;writing to eeprom, bank 3 bcf EECON1,EEPGD bsf EECON1,WREN movlw 55h movwf EECON2 movlw 0AAh movwf EECON2 bsf EECON1,WR test_wr btfsc EECON1,WR; is write finished? goto test_wr bcf EECON1,WREN ; disable eeprom write! bcf STATUS,RP0 bcf STATUS,RP1 ; now bank 0 return ;****************************************** ; Read Value from RAM Program Change ; Entry: prog_ch, RAM address ; Exit: select, value for relays ;****************************************** RAM_rd btfss prog_ch,6 ; check if 0 to 63 goto rd_0_63 rd_64_127 bsf STATUS,IRP ; page 3 movfw prog_ch andlw 03Fh ; reduce value to 0-63 addlw 0A0h ; Set MSB of FSR + 20h base address movwf FSR movfw INDF ; Read value from RAM movwf select bcf STATUS,IRP ; page 0 return rd_0_63 bsf STATUS,IRP ; page 2 movfw prog_ch addlw 020h ; Clear MSB of FSR + 20h base address movwf FSR movfw INDF ; Read value from RAM movwf select bcf STATUS,IRP ; page 0 return ;****************************************** ; Write Program Change Value to RAM ; Entry: prog_ch, 0 to 127, RAM address ; switches x8, RAM data ; Exit: ---- ;****************************************** RAM_wr btfss prog_ch,6 ; check if 0 to 63 goto wr_0_63 wr_64_127 bsf STATUS,IRP ; page 3 movfw prog_ch andlw 03Fh ; reduce value to 0-63 addlw 0A0h ; Set MSB of FSR + 20h base address movwf FSR movfw switches ; x8 switches switch values movwf INDF ; Read value from RAM bcf STATUS,IRP ; page 0 return wr_0_63 bsf STATUS,IRP ; page 2 movfw prog_ch addlw 020h ; Clear MSB of FSR + 20h base address movwf FSR movfw switches ; x8 switches switch values movwf INDF ; Read value from RAM bcf STATUS,IRP ; page 0 return ;****************************************** ; Check for Program Change Command ;****************************************** chk_prog_ch call rxdata ; is it status? movf rcvreg,W andlw 80h sublw 80h btfss STATUS,Z goto chk_prog_ch midich? movf rcvreg,W ; correct MIDI Ch.? andlw 0Fh subwf midich,W btfss STATUS,Z goto chk_prog_ch prog_ch? movf rcvreg,W andlw 0F0h sublw 0C0h ; is it Program Change? btfss STATUS,Z goto chk_prog_ch call rxdata ; Program change value movf rcvreg,W andlw 07Fh movwf prog_ch call prog_ch_out ; Output Program Change return ;****************************************** ; EEPROM to RAM ;****************************************** ee_RAM clrf count ; start address LOOPIT movfw count call ee_read movwf switches movfw count movwf prog_ch call RAM_wr incf count movfw count XORLW .128 ; have we reached the end? BTFSS STATUS,Z GOTO LOOPIT ; no so next one please return ;+++++++++++++++++++++++++++++++++++++++++++++++++ ; Test Routine write 00 to 127 to EEPROM ;++++++++++++++++++++++++++++++++++++++++++++++++ ee_test clrf count loop movfw count movwf eeprom_addr movfw count movwf eeprom_data call ee_write incf count movfw count XORLW .128 ; have we reached the end? BTFSS STATUS,Z goto loop ; no so next one please 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 movlw 0FFh movwf TRISB ;all pins inputs 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 clrf PORTA ; set all outputs to '0000 0000' clrf PORTB clrf PORTD movlw 04h ; 0000 0100 movwf PORTE movf PORTC,W ; read midich. switches andlw 0Fh movwf midich goto start0 ;********************************************** ; Main ;*********************************************** start0 ;+++++++++++++++++++++++++++++++++++++++++++++++++ call ee_test ; test routine ;++++++++++++++++++++++++++++++++++++++++++++++++ call ee_RAM start btfss PORTE,2 ; read record mode switch goto record bcf PORTC,4 ; turn off record LED call chk_prog_ch ; returns prog_ch value call RAM_rd ; returns select value movfw select movwf PORTD ; relays ON/OFF goto start ;********************************************** ; Record Mode Operation ;********************************************** record call sw_dbnc bsf PORTC,4 ; turn on record LED call sw_dbnc ; wait for switches! x8 btfsc PORTE,2 ; read 'Learn' switch goto $-1 bsf PORTC,5 ; turn on Learn LED movfw PORTB ; Read PORTB switches movwf switches call chk_prog_ch call prog_ch_out ; Output Program Change movfw prog_ch movwf eeprom_addr movfw switches movwf eeprom_data call ee_write call RAM_wr record_on? bcf PORTC,5 ; Learn LED OFF call sw_dbnc btfss PORTE,2 goto record goto start ;+++++++++++++++++++++++++++++++++++++++++++++ end