; This code may not be used for commercial gain without prior agreement ; Copyright March 2000, Colin Fraser ; ; Modifications for Boss DR-110 by Benjamin Riggs 2004... cheers Colin :) ; ; revision history: ; ; 30/03/2004 - fixed a bug which could cause it to transmit midiclocks from ; poweron. just inserted a 1 second delay at poweron and it ; now seems to work fine. ; ; 08/03/2004 - modified code to sync a BOSS-DR110 to midi. ; now outputs 12PPM sync on pin 3(GP4), ; pin 2(GP5) goes high / pin6(GP1) goes high Z on start for 4ms, ; pin 6(GP1) goes high / pin2(GP5) goes high Z on stop for 4ms, ; ; modified code to send midi sync from Boss DR-110 internal clock ; now outputs 24 midi clocks per metronome from 12ppm internal DR-110 clock ; send midi start on rising edge of pulse on pin 2 (GP5) ; send midi stop on rising edge of pulse on pin 6 (GP1) ; ; 15/05/2003 - fixed config option for MCLRE - oops! ; ; 26/11/2001 - added sync to midi conversion ; ; 6/3/2000 - modified midi bit timing to fix rare sync problem when consecutive ; bytes were received with no gap ; ; ; ; PIC12C508 Midi to Boss DR-110 Sync ; ; This program uses Microchip assembler mnemonics and the Microchip ; MPASM assembler (http://www.microchip.com/). Default config options ; are set in the __CONFIG line below: MCLRE on, CP off, WDT off, OSC=INTRC. ; ; _______ _______ ; | \/ | ; (+5V) Vdd --+ 1 8 +-- Vss (GND) ; | | ; X1/CLKI/GP5 --+ 2 7 +-- GP0 ; (Sync Start) | | (Midi output) ; X2/CLKO/GP4 --+ 3 6 +-- GP1 ; (Sync Clock) | | (Sync Stop) ; GP3/!MCLR --+ 4 5 +-- GP2 ; (mode sel) | (PIC12C508) | (Midi input) ; +----------------+ ; ; This program converts incoming midi clock bytes ; to Boss DR-110 compatible sync pulses ; ; ; list p=12c508 list p=12C508a radix dec ; include "p12c508.inc" include "p12c508a.inc" __CONFIG _MCLRE_OFF & _CP_OFF & _WDT_OFF & 0xFFE ;Internal osc. cblock 0x07 ;Variables midi ;incoming byte din ;output status dinstat ;din input status x y z endc org 0x00 movwf OSCCAL movlw b'11000111' ;Turn off T0CKI, prescale for TMR0 = 1:256 option ;/ movlw 0xFE tris GPIO movlw b'00000001' ;Preset outputs movwf GPIO ;/ ; wait a second while powering up movlw 0x1F ;31 * 32ms= 992ms movwf y poweronloop ;1sec clrf TMR0 poweronloop1 ;32ms btfss TMR0,7 goto poweronloop1 decfsz y,F goto poweronloop ; ==================== ; midi to sync section ; ; din (written to GPIO for sync output) ; b0 MIDI Ouput ; b1 DIN stop. Always high as stop is triggered by selecting ; data direction on port. output for +5V, input for HIGH Z. ; b2 unused ; b3 unused ; b4 DIN Clock ; b5 DIN start. Always high as with DIN stop. ; b6 unused ; b7 Run Status ; ==================== m2s movlw b'00100011' movwf din ; if time elapsed write out din to clear clock/cont bits rescc movlw b'00101110' ;Set the I/O direction, start and stop pins high Z tris GPIO clrf TMR0 ; ; rx - receive midi byte at 31250 bps. ; rx btfss GPIO,3 ; Check mode select goto s2m btfsc TMR0,4 ; Check timer 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 Start movfw midi xorlw 0xFA btfsc STATUS,Z call clockstart ; Check for Clock pulse movfw midi xorlw 0xF8 btfsc STATUS,Z call clockpulse ; Check for Stop movfw midi xorlw 0xFC btfsc STATUS,Z call clockstop goto rx ; Set start pin high / stop pin high Z clockstart bsf din,7 ;set run status movlw b'00001110' ;Set the I/O direction tris GPIO movfw din ;pulse start pin movwf GPIO clrf TMR0 retlw 0x00 ; Set stop pin high / start pin high Z clockstop bcf din,7 ;clear run status bcf din,4 ;clear clock pin movlw b'00101100' ;Set the I/O direction tris GPIO movfw din ;pulse stop pin. movwf GPIO clrf TMR0 retlw 0x00 ; Toggle clock pin clockpulse btfss din,7 ;check run status retlw 0x00 ;continue if running movlw 0x10 xorwf din,1 ;toggle clock pin movfw din movwf GPIO retlw 0x00 ; ==================== ; sync to midi section ; ; dinstat ; b0 previous status of clock pin ; b1 previous status of start pin ; b2 previous status of start pin ; b4 current run status. set on start, reset on stop ; b5 initial clock status. used to ensure first midi clock on first rising edge only. ; b6 unused ; b7 unused ; ==================== s2m movlw b'00111110' ;Set the I/O direction tris GPIO clrw movwf dinstat starttest btfsc GPIO,3 ; check mode select goto m2s ; go back to midi to sync if required btfss GPIO,5 ; Check for DIN start = 1 goto lowstart ; branch if start = 0 goto highstart ; branch if start = 1 clktest btfss GPIO,4 ; Check DIN Clock goto lowclock ; branch if clock = 0 goto highclock ; branch if clock = 1 stoptest btfss GPIO,1 ; Check for DIN stop = 1 goto lowstop ; branch if stop = 0 goto highstop ; branch if stop = 1 lowstart btfss dinstat,1 ; was it already 0 ? goto clktest ; branch if start pin not changed bcf dinstat,1 ; start status = 0 goto clktest highstart btfsc dinstat,1 ; was it already 1 ? goto clktest ; branch if startpin not changed bsf dinstat,1 ; start status = 1 btfsc dinstat,3 ; are we already running? goto clktest ; skip midi tx if yes bsf dinstat,3 ; run status = 1 movlw 0xFA ; tx midi start byte call miditx goto clktest lowstop btfss dinstat,2 ; was it already 0 ? goto starttest ; branch if stop pin not changed bcf dinstat,2 ; stop status = 0 goto starttest highstop btfsc dinstat,2 ; was it already 0 ? goto starttest ; branch if stop pin not changed bsf dinstat,2 ; stop status = 1 btfss dinstat,3 ; are we already stopped? goto starttest ; skip midi tx if yes bcf dinstat,3 ; run status = 0 btfsc dinstat,4 bcf dinstat,4 ; clear initial clock status movlw 0xFC ; tx midi start byte call miditx goto starttest lowclock btfss dinstat,0 ; was previous clock 1 ? goto stoptest ; don't send midi if no bcf dinstat,0 ; clock status = 0 btfss dinstat,3 ; check run status goto stoptest ; don't send midi if not running btfss dinstat,4 ; have we had an initial rising edge clock ? goto stoptest ; don't send midi if no movlw 0xF8 ; tx midi clock byte call miditx goto stoptest highclock btfsc dinstat,0 ; was previous clock 0 ? goto stoptest ; don't send midi if no bsf dinstat,0 ; clock status = 1 btfss dinstat,3 ; check run status goto stoptest ; don't send midi if not running btfss dinstat,4 bsf dinstat,4 ; set initial clock status movlw 0xF8 ; tx midi clock byte call miditx goto starttest 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 retlw 0x00 end