; This code may not be used for commercial gain without prior agreement ; Copyright April 2005, Colin Fraser ; ; revision history: ; ; 20/04/2005 - 12F629 version ; ; PIC12F629 Midi to Din / Din to Midi convertor ; ; This program uses Microchip assembler mnemonics and the Microchip ; MPASM assembler (http://www.microchip.com/). ; ; _______ _______ ; | \/ | ; (+5V) Vdd --+ 1 8 +-- Vss (GND) ; | | ; X1/CLKI/GP5 --+ 2 7 +-- GP0 ; (DIN Run) | | (Midi output) ; X2/CLKO/GP4 --+ 3 6 +-- GP1 ; (DIN Clock) | | (DIN Cont) ; GP3/!MCLR --+ 4 5 +-- GP2 ; (mode sel) | (PIC12F629) | (Midi input) ; +----------------+ ; ; ; list p=12F629 radix dec include "p12f629.inc" __CONFIG _MCLRE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT ;Internal osc. cblock 0x20 ;Variables midi ;incoming byte din ;output status dinstat ;din input status x y z endc org 0x00 ; bsf STATUS, RP0 ;Bank 1 call 3FFh ;Get the cal value movwf OSCCAL ;Calibrate movlw b'10000110' ;Turn off T0CKI, prescale for TMR0 = 1:128 movwf OPTION_REG bcf STATUS, RP0 ;Bank 0 movlw b'00000001' ;Preset outputs movwf GPIO ;/ ; ==================== ; midi to sync section ; ==================== m2s movlw b'00000001' movwf din movlw b'00001100' ;Set the I/O direction bsf STATUS, RP0 ;Bank 1 movwf TRISIO bcf STATUS, RP0 ;Bank 0 goto rx ; if time elapsed write out din to clear clock/cont bits rescc movfw din movwf GPIO clrf TMR0 btfss GPIO,3 goto s2m ; ; rx - receive midi byte at 31250 bps. ; rx btfsc TMR0,5 ; 4ms goto rescc btfsc GPIO,2 ; Detect start bit goto rx ; ; Wait to get to centre of start bit. ; nop ;1 nop ;2 nop ;3 nop ;4 nop ;5 nop ;6 nop ;7 nop ;8 movlw 8 ; Eight bits of data to get movwf x clrf midi ; ; Delay one bit-width (32 cycles) to get to center of LSB. ; Gather the bits into midi. ; mbin movlw 6 ;(1) movwf y ;(1) del1 nop ;\ decfsz y,F ;((5 x 4) + 3) = 23 goto del1 ;/ bcf STATUS,C ;(1) Default 0 rrf midi,F ;(1) Put 0 in MSB of recv, then btfsc GPIO,2 ;(1/2) sample the serial data and bsf midi,7 ;(1) set the bit if sample was=1 decfsz x,F ;((7 x 3) + 2) = 23, Do all bits goto mbin ;/ [total cycles = 32, MSB = 31] ; ; Time to first third of stop bit. (22 cycles) ; movlw 6 ;(1) movwf y ;(1) del2 decfsz y,F ;((6 x 3) + 2) = 20 goto del2 ;/ btfss GPIO,2 ;Stop bit showed up? goto rx ;If not, wait for another byte ; ; Do clock stuff ; midi reg now contains received midi byte ; ; Check for Clock pulse movfw midi xorlw 0xF8 btfsc STATUS,Z goto clockpulse ; Check for Start movfw midi xorlw 0xFA btfsc STATUS,Z goto clockstart ; Check for Continue movfw midi xorlw 0xFB btfsc STATUS,Z goto clockcont ; Check for Stop movfw midi xorlw 0xFC btfss STATUS,Z goto rx ; Set Run pin low bcf din,5 movfw din movwf GPIO goto rx ; Set Run pin high clockstart bsf din,5 movfw din movwf GPIO goto rx ; Set Run and Cont pin high clockcont bsf din,5 movfw din iorlw 0x02 movwf GPIO clrf TMR0 goto rx ; Set Clock pin high clockpulse movfw din iorlw 0x10 movwf GPIO clrf TMR0 goto rx ; ==================== ; sync to midi section ; ==================== s2m movlw b'00111110' ;Set the I/O direction bsf STATUS, RP0 ;Bank 1 movwf TRISIO bcf STATUS, RP0 ;Bank 0 clrw movwf dinstat clktest btfsc GPIO,3 ; check mode select goto m2s ; go back to midi to sync if required btfss GPIO,4 ; Check DIN Clock goto noclock ; branch if clock = 0 btfss dinstat,0 ; was previous clock 1 ? goto newclock ; branch if clock 0 -> 1 runtest btfss GPIO,5 ; Check for DIN Run = 1 goto norun ; branch if run = 0 btfss dinstat,1 ; was it already 1 ? goto newrun ; branch if clock 0 -> 1 goto clktest norun btfss dinstat,1 ; was it already 0 ? goto clktest ; branch if run not changed movfw dinstat andlw 0x1 movwf dinstat ; run status = 0 movlw 0xFC ; tx midi stop byte goto miditx newrun movfw dinstat iorlw 0x2 movwf dinstat ; run status = 1 movlw 0xFA ; tx midi start byte goto miditx noclock movfw dinstat andlw 0x2 movwf dinstat ; clock status = 0 goto runtest newclock movfw dinstat iorlw 0x1 movwf dinstat ; clock status = 1 movlw 0xF8 ; tx midi clock byte miditx movwf x ; store tx byte clrf GPIO ; start bit ;pause for one bit movlw 8 ;(1) movwf z ;(1) pause1 decfsz z ;(1/2) \ goto pause1 ;(2) / * z = 8 * 3 + 1 = 25 movlw 0x8 ;(1) movwf y ;(1) nop ;(1) mtxloop movfw x ;(1) movwf GPIO ;(1) lsb of tx byte to midi out ;pause for one bit movlw 7 ;(1) movwf z ;(1) pause2 decfsz z ;(1/2) \ goto pause2 ;(2) / * z = 7 * 3 + 1 = 22 bsf STATUS,C ;(1) rrf x,1 ;(1) nop ;(1) nop ;(1) decfsz y ;(1) goto mtxloop ;(2) nop goto clktest end