;PROGRAM: MidKck.src M.Whitco, CET 02-07-98 ; Routine for PIC 16C56 based midi trigger unit, to play a kick drum note on a tone ;generator or synth (selectable note value, midi channel 10, with variable velocity). ; Accumulates a byte of information (to become 3rd byte transmitted), which is inversely ;proportional to the length of time that a SPDT switch is between contacts (ie velocity). ; Timing begins with switch leaving initial contacts, and ends when final contacts are ;closed. Transmission then begins. ; Transmits a 3-byte string of serial (midi) data at 31.25 Kbaud (Asynchronous 8-N-1), and ;using inverted logic levels (output current on = logic 0, per midi specs).. Baud rate ;determined by bit_K and the clock rate of the PIC. ;Constants & input/output assignments bit_K = 13 ;For 31,250-baud operation @ 8 MHz clock rate serial_out = ra.2 ;Serial data output line (pin 1) switch_up = ra.0 ;Start of switch travel (pin 17 to NC contacts) switch_dn = ra.1 ;End of switch travel (pin 18 to NO contacts) note = rb ;Input for note selection (via DIP switch) ;Storage space for variables above special-purpose file registers ("define space") org 8 ;Start assigning at register 08 delay_cntr ds 1 ;Register for serial delay routine (holds bit_K) bit_cntr ds 1 ;Number of transmitted bits msg_cntr ds 1 ;Byte pointer, increment after each byte sent xmt_byte ds 1 ;The transmitted byte is stored here vel_byte ds 1 ;Register for storing velocity value accumulated pause ds 1 ;Delay time for switch debouncing (also used to ;slow decrementing rate of velocity value) ;Org 0 starts program at the top of ROM. org 0 device pic16c56,hs_osc,wdt_off,protect_off reset start start mov !ra,#00000011b ;Assign pins 17 & 18 as inputs, pin 1 output mov !rb,#11111111b ;set up as input for DIP switch mov vel_byte,#127 ;Start with highest velocity, for 0 time mov msg_cntr,#0 ;Message string initialized to 1st byte of 3 ;**************************************************************************** ;PROCESS SENSOR SWITCH call debounce :loop jb switch_up,timer ;If switch is logic high, continue jmp :loop timer mov pause,#255 ;This line sets delay time :loop nop djnz pause,:loop ;Remain in loop until zero jnb switch_dn,send ;or switch reaches bottom djnz vel_byte,timer ;Decrement & re-check if not 0 ;*************************************************************************** ;TRANSMISSION BEGINS, now that the velocity byte is collected send :again mov bit_cntr,#8 ;Eight bits in a byte call datastor ;Get the next byte from storage setb serial_out ;Send start_bit call bit_delay ;Wait 1 bit period (32 uSec) :xmit rr xmt_byte ;Rotate bits of byte being sent, into carry movb serial_out,/c ;Send a bit out call bit_delay ;Wait 1 bit period (32 uSec) djnz bit_cntr,:xmit ;Not 8 bits yet? Send next bit clrb serial_out ;Send stop bit call bit_delay ;Wait 1 bit period (32 uSec) inc msg_cntr ;Add 1 to byte pointer(next byte) cjbe msg_cntr,#2,:again ;More bytes to send? Then repeat. :loop jnb switch_up,over jmp :loop ;Stay here until pedal is up over jmp start ;Restart the program (next kick) ;*************************************************************************** ;SUBROUTINES ;TRANSMISSION BIT DURATION bit_delay mov delay_cntr,#bit_K ;Put the baud rate constant into :loop nop ;the register, to prepare for djnz delay_cntr,:loop ;midi data transmission ret ;BYTE VALUES TO BE TRANSMITTED datastor cje msg_cntr,#0,byte1 ;Check counter, to see which cje msg_cntr,#1,byte2 ;byte is needed next. Then jump cje msg_cntr,#2,byte3 ;below, to store that byte. byte1 mov xmt_byte,#99h ;Note on, midi channel 10 ret byte2 mov xmt_byte,note ;Note value = DIP switch setting ret byte3 mov xmt_byte,vel_byte ;Velocity variable ret ;DEBOUNCE ROUTINE debounce mov pause,#64 ;Create delay for intermittent :loop nop ;contacts to become fully djnz pause,:loop ;debounced ret