;-----------------------------------------------------------------------------------------------; ; Program: SC-7 Control ; ; Developed by David J. Brown ; ; Copyright (c) April 13, 2004 David J. Brown ; ; Email: davebr@earthlink.net ; ; Web site: http://modularsynthesis.com ; ;-----------------------------------------------------------------------------------------------; ; LICENSE AGREEMENT: ; ; This program is free software. You can redistribute it and/or modify it. ; ; ; ; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, ; ; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ; ;-----------------------------------------------------------------------------------------------; ; ; Description: ; ; This program adds midi program change and octave transpose to control ; a Roland SC-7. Family and voice selections are made on the last midi ; channel used and displayed on the LCD. Octave transpose is global and ; applies to all note up / down commands. ; ; inputs: ; start = ; stop = ; in-1 = family select 0 to 15 ; in-2 = voice select 1 to 8 ; in-3 = octave select -2 to +2 ; in-4 = ; aux = ; midi-in = midi input ; ; outputs: ; out-1 = led indicates -2 octaves ; out-2 = led indicates -1 octave ; out-3 = led indicates +1 octave ; out-4 = led indicates +2 octaves ; aux = ; midi-out= midi output ; speakjet= voice output ; ; run led = toggles @ 0.5 S (if timer interrupts enabled) ; stop led = flashes when midi data received ; ; written by David J. Brown ; revision: 0.1S2 ; Setp 23, 2010 ; history: 0.1S2 changed serial for Studio 2 ; 0.1X converted shiftout to Studio ; 0.1 converted to CVS display, removed speakjet code, ; removed push/pop ; 0.0 initial release of SC-7 program ; adapted from MIDI transpose program ; date: July 23, 2006 ; ;---------ENABLE TIMER INTERRUPT CONDITIONAL COMPILE OPTION-------------------------------------; ;notes: run led will blink to verify timer operation ; ; speakjet and console serial output is not compatible with interrupts ; ; ; ;COMMENT OUT NEXT LINE TO DISABLE TIMER INTERRUPTS ; timer_int_en con 1 ;define to enable timer interrupts ; ; ;comment to disable timer interrupts ; ; ; ; ;------ENABLE AVERAGED ANALOG-IN ON TIMER INTERRUPT CONDITIONAL COMPILE OPTION------------; ; ; ;note: requires timer_int_en to be defined. ; ; ; ; ; ; ; ;COMMENT OUT NEXT LINE TO DISABLE ANALOG-IN ON TIMER INTERRUPTS / ENABLE POLLED ANALOG-IN ; ; ;input_int_en con 1 ;define to enable input interrupt mode ; ; ; ; ;comment to set polled input mode ; ; ; ;-----------------------------------------------------------------------------------------; ; ; ; ;-----------------------------------------------------------------------------------------------; ; ;psim template written by David J. Brown ;contains portions written by Brice Hornback and Grant Richter ;revision: 0.6 ; May 14, 2005 ;history: 0.6 changed midi drivers to use hserial interrupt ; mechanism ; 0.51 changed midi-out during timer interrupt to use ; timerA on 512 uS ; 0.5 added midi-out during timer interrupt, added ; put_tx_bfr, modified send_midi routine, added ; conditional midi-out compile option, added send_cc ; 0.44 streamlined debug_speakjet routine, changed ; gra divisor from 2000 to 2001 for accurate time ; 0.43 corrected send_speakjet pin label error, changed ; display_led to debug_led, changed send_console to ; debug_console, added debug_speakjet routine, changed ; led_data and con_data to debug_data ; 0.42 renamed start_b to start_j, renamed stop_b to ; stop_j, added push/pop to display_led, changed ; comment delimiter to semicolon, added send_console ; routine, re-aliased input pins, sends midi all notes ; off during initialization, added midi program change ; 0.41 upper case conversion to lower, variables and ; labels renamed ; 0.4 added averaged input input driver (polled or ; interrupt mode), display_led driver (for debug), ; speakjet driver, renamed program to djb template ; 0.3 added program header information, modified ; pin initialization ; 0.2 initialize aux output low and speakjet pins ; 0.1 added DAC & led initialization, 1 mS timestamp, ; stop led blinks when midi data received, run ; led toggles @ 0.5 S for health indication ; 0.0 initial release of midi input & output program ;date: April 13, 2004 ; ;-----------------------------------------------------------------------------------------------; ; PSIM-1 module from SynthModules.com ; ; BasicMicro AtomPro24M ; ;-----------------------------------------------------------------------------------------------; ; ; BasicMicro AtomPro24M configuration ; P0 - in-1 ; P1 - in-2 ; P2 - in-3 ; P3 - in-4 ; P4 - start button (momentary normally open switch) ; P5 - stop button (momentary normally open switch) ; P6 - j3 pin 2 (speakjet buffer half full) ; P7 - j3 pin 1 ( serial data to speakjet ) ; P8 - aux digital I/O ; P9 - stop led ; P10 - run led ; P11 - load_dacs ; P12 - ser_data ; P13 - clock ; P14 - j5 pin 1 (midi-in ) ; P15 - j5 pin 2 (midi-out) ; ;-----------------------------------------------------------------------------------------------; ; ;pin declarations pin_j1 con p0 ;in-1 pin pin_j2 con p1 ;in-2 pin pin_j3 con p2 ;in-3 pin pin_j4 con p3 ;in-4 pin start_j var in4 ;start jack and switch stop_j var in5 ;stop jack and switch spkj_full var in6 ;speakjet buffer half full spkj_sdata con p7 ;speakjet data aux_j con p8 ;aux jack (output mode) aux_in var in8 ;aux jack (input mode) stop_led con p9 ;stop led (red) stop_led_out var out9 ;stop led alias used for let statement run_led con p10 ;run led (green) run_led_out var out10 ;run led alias used for let statement load_dacs con p11 ;load dac pin ser_data con p12 ;dac serial data input pin clock con p13 ;dac clock pin midi_sdata con p15 ;midi data serial output ;i/o declarations in_j1 var word ;in-1 value: get_inputs, get_inputs_avg, avg1 in_j2 var word ;in-2 value: get_inputs, get_inputs_avg, avc2 in_j3 var word ;in-3 value: get_inputs, get_inputs_avg, avg3 in_j4 var word ;in-4 value: get_inputs, get_inputs_avg, avg4 out_j1 var word ;out-1 value: load_outputs out_j2 var word ;out-2 value: load_outputs out_j3 var word ;out-3 value: load_outputs out_j4 var word ;out-4 value: load_outputs ;midi variable declarations note_off con $80 ;midi note-off command: send_note_on, send_note_off note_on con $90 ;midi note-on command: send_note_on, send_note_off cont_ctr con $b0 ;midi continuous controller; send_all_off, send_cc pgm_chg con $c0 ;midi program change command:send_prog_change midi_chan var nib ;midi channel (0 - 15): send_note_on, send_note_off midi_note var byte ;midi note value: send_note_on, send_note_off midi_vel var byte ;midi velocity value: send_note_on, send_note_off midi_pgm var byte ;midi program change value:send_prog_change midi_cc var byte ;midi continuous controller number: send_cc ;midi driver variable declarations midi_data var byte ;variable: check_midi, send_midi, get_rcx_bfr, send_note_on, send_note_off rcx_data_flg var bit ;received data flag (1=data, 0=no data): get_rcx_bfr #ifndef midi_int_en rcx_status var byte ;variable: check_midi, send_midi rcx_data var byte ;variable: check_midi rcx_ptr_strt var byte ;received data start pointer (first data in buffer): get_rcx_bfr rcx_ptr_end var byte ;received data end pointer (last data in buffer+1): check_midi, midi_in_isr rcx_bfr_num var byte ;number of bytes in data buffer: check_midi, get_rcx_bfr, midi_in_isr rcx_bfr_len con 128 ;midi-in buffer length: rcx_bfr rcx_bfr var byte(rcx_bfr_len) ;midi-in data buffer: check_midi, get_rcx_bfr, midi_in_isr tx_status var byte ;variable: send_midi #endif ;timer declarations #ifdef timer_int_en time_count var long ;1 mS timer count value: tm_isr turn_off var long ;time value to turn off stop led: tm_isr #endif ;input buffer declarations in_j1_ptr var byte ;in-1 buffer pointer: avgx, get_inputs_avg #ifdef input_int_en in_j2_ptr var byte ;in-2 buffer pointer: avgx in_j3_ptr var byte ;in-3 buffer pointer: avgx in_j4_ptr var byte ;in-4 buffer pointer: avgx isr_cnt var nib ;timer pass counter: tm_isr #endif in_j1_tmp var long ;in-1 temporary variable: avgx, get_inputs_avg in_j2_tmp var long ;in-2 temporary variable: avgx, get_inputs_avg in_j3_tmp var long ;in-3 temporary variable: avgx, get_inputs_avg in_j4_tmp var long ;in-4 temporary variable: avgx, get_inputs_avg in_j1_bfr var long(2) ;in-1 last 4 samples buffer: avgx, get_inputs_avg in_j2_bfr var long(2) ;in-2 last 4 samples buffer: avgx, get_inputs_avg in_j3_bfr var long(2) ;in-3 last 4 samples buffer: avgx, get_inputs_avg in_j4_bfr var long(2) ;in-4 last 4 samples buffer: avgx, get_inputs_avg ;misc declarations fivevolts con 1920 ;5 volt output value ;midi declarations rcx_chan var byte ;midi channel transpose (last midi channel used) rcx_note var byte ;midi in note tranpose last_cmd var byte ;last midi command for running status midi_cmd var byte ;branch address for running status sys_cmd var byte ;branch address for system commands t_midi var byte ;temporary variable ;program change declarations last_pm var byte ;last program change chr_cnt var byte ;character counter str_cnt var word ;string position counter str_data var byte ;string character key_cnt var byte ;key up/down counter ; ;GM family text family bytetable | "Piano ", | ;1-8 "ChrmPerc", | ;9-16 "Organ ", | ;17-24 "Guitar ", | ;25-32 "Bass ", | ;33-40 "Strings ", | ;41-48 "Ensemble", | ;49-56 "Brass ", | ;57-64 "Reed ", | ;65-72 "Pipe ", | ;73-80 "SynthLd ", | ;81-88 "SynthPad", | ;89-96 "SynthFx ", | ;97-104 "Ethnic ", | ;105-112 "Percussn", | ;113-120 "SoundFX " ;121-128 ; ;GM voice text voice bytetable | "AccGrand", | ; 1 "BrightAc", | ; 2 "ElecGnd ", | ; 3 "HonkyTnk", | ; 4 "Elec-1 ", | ; 5 "Elec-2 ", | ; 6 "Harpsicd", | ; 7 "Clavi ", | ; 8 "Celesta ", | ; 9 "Glcknspl", | ;10 "MusicBox", | ;11 "Vibraphn", | ;12 "Marimba ", | ;13 "Xylophon", | ;14 "TubBells", | ;15 "Dulcimer", | ;16 "Drawbar ", | ;17 "Percussv", | ;18 "Rock Org", | ;19 "Church ", | ;20 "Reed Org", | ;21 "Acordian", | ;22 "Harmnica", | ;23 "TangoAcc", | ;24 "Nylon ", | ;25 "Steel ", | ;26 "Jazz ", | ;27 "Clean ", | ;28 "Muted ", | ;29 "Overdriv", | ;30 "Distortn", | ;31 "Harmonic", | ;32 "Accoustc", | ;33 "FingerAc", | ;34 "PickBass", | ;35 "Fretless", | ;36 "Slap1 ", | ;37 "Slap2 ", | ;38 "Synth1 ", | ;39 "Synth2 ", | ;40 "Violin ", | ;41 "Viola ", | ;42 "Cello ", | ;43 "Contra ", | ;44 "Tremolo ", | ;45 "Pizicato", | ;46 "Orchestl", | ;47 "Timpani ", | ;48 "Ensembl1", | ;49 "Ensembl2", | ;50 "SynthSt1", | ;51 "SynthSt2", | ;52 "ChoirAhs", | ;53 "VoiceOhs", | ;54 "SynthVoc", | ;55 "OrchHits", | ;56 "Trumpet ", | ;57 "Trombone", | ;58 "Tuba ", | ;59 "MuteTrmp", | ;60 "FrenchHn", | ;61 "BrassSec", | ;62 "Synth1 ", | ;63 "Synth2 ", | ;64 "SopranSx", | ;65 "Alto Sax", | ;66 "TenorSax", | ;67 "Baritone", | ;68 "Oboe ", | ;69 "English ", | ;70 "Bassoon ", | ;71 "Clarinet", | ;72 "Piccolo ", | ;73 "Flute ", | ;74 "Recorder", | ;75 "PanFlute", | ;76 "BlownBot", | ;77 "Shakuhac", | ;78 "Whistle ", | ;79 "Ocarina ", | ;80 "Square ", | ;81 "Sawtooth", | ;82 "Calliope", | ;83 "Chiff ", | ;84 "Charang ", | ;85 "Voice ", | ;86 "Fifths ", | ;87 "BassLead", | ;88 "New Age ", | ;89 "Warm ", | ;90 "Poly ", | ;91 "Choir ", | ;92 "Bowed ", | ;93 "Metallic", | ;94 "Halo ", | ;95 "Sweep ", | ;96 "Rain ", | ;97 "Soundtrk", | ;98 "Crystal ", | ;99 "Atmosphr", | ;100 "Britness", | ;101 "Goblins ", | ;102 "Echoes ", | ;103 "Sci-Fi ", | ;104 "Sitar ", | ;105 "Banjo ", | ;106 "Shamisen", | ;107 "Koto ", | ;108 "Kalimba ", | ;109 "Bag Pipe", | ;110 "Fiddle ", | ;111 "Shanai ", | ;112 "TinklBel", | ;113 "Agogo ", | ;114 "SteelDrm", | ;115 "Woodblk ", | ;116 "TaikoDrm", | ;117 "Melodic ", | ;118 "SynthDrm", | ;119 "RevCymbl", | ;120 "GtrFretN", | ;121 "Breath ", | ;122 "Seashore", | ;123 "BrdTweet", | ;124 "Tel Ring", | ;125 "Helicopt", | ;126 "Applause", | ;127 "Gunshot " ;128 ; ;-----------------------------------------------------------------------------------------------; ;start of program ; ;-----------------------------------------------------------------------------------------------; ; ;initialize pins ;note: setting midi-out, i2c_clock, and i2c_data to outputs can send glitches so initialize as inputs dirs=%0011111000000000 ;configure pin direction (1=output, 0=input) ;inputs: midi-in, aux, start, stop, in-4, in-3, in-2, in-1 ;outputs: load_dacs, ser_data, clock, stop led, run led, i2c clock & data low run_led ;set run led off low stop_led ;set stop led off high load_dacs ;set dac load-0 high low ser_data ;set dac data low low clock ;set dac clock low let out_j1=0 ;set out-1 low let out_j2=0 ;set out-2 low let out_j3=0 ;set out-3 low let out_j4=0 ;set out-4 low gosub load_outputs ; ;initialize misc variables #ifndef midi_int_en let rcx_ptr_strt=0 ;set receive start pointer let rcx_ptr_end=0 ;set receive end pointer let rcx_bfr_num=0 ;set receive buffer to empty #endif let midi_chan=0 ;set midi channel to 0 let midi_note=0 ;set midi note to 0 let midi_vel=$40 ;set default velocity let midi_cmd=$0f ;set last MIDI command (invalid) let sys_cmd=$0f ;set last MIDI command (invalid) let rcx_note=0 ;set note transpose to 0 let rcx_chan=0 ;set default program change channel to 0 let key_cnt=0 ;reset key counter let in_j1_ptr=0 ;set in-1 pointer to 0 #ifdef input_int_en let in_j2_ptr=0 ;set in-2 pointer to 0 let in_j3_ptr=0 ;set in-3 pointer to 0 let in_j4_ptr=0 ;set in-4 pointer to 0 let isr_cnt=0 ;set isr pass counter to 0 #endif let in_j1_bfr(0)=0 ;set in-1 buffer data to 0 let in_j1_bfr(1)=0 let in_j2_bfr(0)=0 ;set in-2 buffer data to 0 let in_j2_bfr(1)=0 let in_j3_bfr(0)=0 ;set in-3 buffer data to 0 let in_j3_bfr(1)=0 let in_j4_bfr(0)=0 ;set in-4 buffer data to 0 let in_j4_bfr(1)=0 ; #ifdef timer_int_en ;initialize timerW hardware for 1 mS interrupts let tmrw=%10001000 ;set Timer Mode Register to enable count let tcrw=%10110000 ;set Timer Control Register ; clear on compare match A ; prescalar S /8 = 2 MHz clock ; let gra=2000 ;count to 2000 for 1 mS let gra=2001 ;measures 999.8 uS on system ;enable timerW interrupt let time_count=0 ;set real time counter to 0 let turn_off=0 ;set time to turn off to time_count oninterrupt timerwint_imiea, tm_isr enable timerwint_imiea ;enable timer interrupt #endif ; ;enable midi interrupts sethserial1 h31200,h8databits,hnoparity,h1stopbits pause 250 ;allow display initialize time hserout [$f0,$7d,$0a,$18,"SC-7 Controller ModularSynthesis",$f7] ;clear display, overwrite, program name ; ;-----------------------------------------------------------------------------------------------; ;main program ; ;-----------------------------------------------------------------------------------------------; ; gosub send_all_off ;send all notes off on all channels pause 500 ;let program name display gosub get_inputs let in_j1=in_j1>>6 ;keep family to 16 positions let in_j2=in_j2>>7 ;keep voice to 8 positions let last_pm=(in_j1<<3)+in_j2 ;set last program change to current hserout [$f0,$7d,$0b] ;display current program change on line 2 let str_cnt=in_j1*8 ;offset by family X 8 characters for chr_cnt=0 to 7 ;output 8 characters of family let str_data=family(str_cnt+chr_cnt) hserout [str_data] next let str_cnt=(in_j1*64)+(in_j2*8) ;offset by family X 64 and then by voice X 8 characters for chr_cnt=0 to 7 ;output 8 characters of voice let str_data=voice(str_cnt+chr_cnt) hserout [str_data] next hserout [$f7] ;end sysex ; ;parse midi data for command pass_thru: gosub proc_controls ;check controls during idle hserin pass_thru,0,[midi_data] if midi_data=$fe then pass_thru ;ignore active status high stop_led disable timerwint_imiea let turn_off=time_count+20 ;set led time enable timerwint_imiea if midi_data>$f7 then ;check to see if real time gosub real_time endif if midi_data.bit7=0 then running ;check to see if running status let last_cmd=midi_data ;save command to restore for running let midi_cmd=(midi_data>>4)&07 ;strip midi channel for branch and save for running branch midi_cmd,[mkey_up,mkey_dn,key_prs,ctrl_chg,prgm_chg,chan_prs,ptch_bnd,sys_com] ; ;running status running: let t_midi=midi_data ;need to send command byte so save midi_data let midi_data=last_cmd ;restore last midi command let rcx_chan=midi_data&$0f ;save current midi channel hserout [midi_data] let midi_data=t_midi ;restore midi_data branch midi_cmd,[mkey_upr,mkey_dnr,key_prsr,ctrl_chgr,prgm_chgr,chan_prsr,ptch_bndr,pass_thru] ; ;note off command mkey_up: let rcx_chan=midi_data&$0f ;save current midi channel hserout [midi_data] gosub get_next_byte ;get data from received buffer mkey_upr: let midi_data=midi_data+rcx_note ;transpose midi note hserout [midi_data] gosub get_next_byte ;get data from received buffer hserout [midi_data] let key_cnt=key_cnt-1 ;count keys down goto pass_thru ;check if more data in buffer ; ;note on command mkey_dn: let rcx_chan=midi_data&$0f ;save current midi channel hserout [midi_data] gosub get_next_byte ;get data from received buffer mkey_dnr: let midi_data=midi_data+rcx_note ;transpose midi note hserout [midi_data] gosub get_next_byte ;get data from received buffer hserout [midi_data] let key_cnt=key_cnt+1 ;count keys down goto pass_thru ;check if more data in buffer ; ;key pressure command key_prs: let rcx_chan=midi_data&$0f ;save current midi channel hserout [midi_data] gosub get_next_byte ;get data from received buffer key_prsr: hserout [midi_data] gosub get_next_byte ;get data from received buffer hserout [midi_data] goto pass_thru ;check if more data in buffer ; ;control change command ctrl_chg: let rcx_chan=midi_data&$0f ;save current midi channel hserout [midi_data] gosub get_next_byte ;get data from received buffer ctrl_chgr: hserout [midi_data] gosub get_next_byte ;get data from received buffer hserout [midi_data] goto pass_thru ;check if more data in buffer ; ;program change command prgm_chg: let rcx_chan=midi_data&$0f ;save current midi channel hserout [midi_data] gosub get_next_byte ;get data from received buffer prgm_chgr: hserout [midi_data] goto pass_thru ; ;channel pressure command chan_prs: let rcx_chan=midi_data&$0f ;save current midi channel hserout [midi_data] gosub get_next_byte ;get data from received buffer chan_prsr: hserout [midi_data] goto pass_thru ; ;pitch bend command ptch_bnd: let rcx_chan=midi_data&$0f ;save current midi channel hserout [midi_data] gosub get_next_byte ;get data from received buffer ptch_bndr: hserout [midi_data] gosub get_next_byte ;get data from received buffer hserout [midi_data] goto pass_thru ;check if more data in buffer ; ;system common command sys_com: let sys_cmd=midi_data&$07 ;get system common command branch sys_cmd,[sys_ex,pass_thru,song_ptr,song_sel,pass_thru,pass_thru,tune_req,pass_thru] ; ;system exclusive sys_ex: hserout [midi_data] sys_ex2: gosub get_next_byte ;get data from received buffer hserout [midi_data] ;send it if midi_data<>$f7 then sys_ex2 ;check for end of string goto pass_thru ; ;song pointer command song_ptr: hserout [midi_data] gosub get_next_byte ;get data from received buffer hserout [midi_data] gosub get_next_byte ;get data from received buffer hserout [midi_data] goto pass_thru ;check if more data in buffer ; ;song select command song_sel: hserout [midi_data] gosub get_next_byte ;get data from received buffer hserout [midi_data] goto pass_thru ;check if more data in buffer ; ;tune_request command tune_req: hserout [midi_data] goto pass_thru ; ;real time commands real_time: let sys_cmd=midi_data&07 ;strip high bits for branch branch sys_cmd,[time_clk,nul_cmd,start_cmd,cont_cmd,stop_cmd,nul_cmd,nul_cmd,reset_cmd] real_time2: hserin real_time2,0,[midi_data] ;get next command if midi_data>$f7 then real_time ;check for to see if real time return ; ;timing clock command time_clk: hserout [midi_data] goto real_time2 ; ;reserved command nul_cmd: ;do nothing goto real_time2 ; ;start command start_cmd: hserout [midi_data] goto real_time2 ; ;start command cont_cmd: hserout [midi_data] goto real_time2 ; ;start command stop_cmd: hserout [midi_data] goto real_time2 ; ;start command reset_cmd: exception pass_thru ;clear at least one level of stack and restart ; ;wait for data and check for real time data get_next_byte: hserin get_next_byte,0,[midi_data] if midi_data=$fe then get_next_byte ;ignore active status if midi_data>$f7 then ;check for real time gosub real_time goto get_next_byte endif return ; ;process input controls proc_controls: ;determine and display program change gosub get_inputs ;get inputs let in_j1=in_j1>>6 ;keep family to 16 positions let in_j2=in_j2>>7 ;keep voice to 8 positions let midi_pgm=(in_j1<<3)+in_j2 ;assemble to 7 bit program change if midi_pgm <> last_pm then ;check to see if program changed let last_pm=midi_pgm ;set last program change for next check hserout [$f0,$7d,$0b] let str_cnt=in_j1*8 ;offset by family X 8 characters for chr_cnt=0 to 7 ;output 8 characters of family let str_data=family(str_cnt+chr_cnt) hserout [str_data] next let str_cnt=(in_j1*64)+(in_j2*8) ;offset by family X 64 and then by voice X 8 characters for chr_cnt=0 to 7 ;output 8 characters of voice let str_data=voice(str_cnt+chr_cnt) hserout [str_data] next hserout [$f7] ;end sysex let midi_data=pgm_chg+rcx_chan ;send program change on last used MIDI channel gosub send_midi let midi_data=midi_pgm gosub send_midi endif ;determine and display octave transpose if key_cnt=0 then ;wait for all keys up let out_j1=0 ;reset all transpose indicators let out_j2=0 let out_j3=0 let out_j4=0 let in_j3=in_j3>>7 ;keep transpose to 8 positions if in_j3=0 then let rcx_note=-24 let out_j1=fivevolts ;indicate tranpose -2 octaves endif if in_j3=1 or in_j3=2 then let rcx_note=-12 let out_j2=fivevolts ;indicate tranpose -1 octave endif if in_j3=3 or in_j3=4 then let rcx_note=0 endif if in_j3=5 or in_j3=6 then let rcx_note=12 let out_j3=fivevolts ;indicate tranpose 1 octave endif if in_j3=7 then let rcx_note=24 let out_j4=fivevolts ;indicate tranpose 2 octaves endif gosub load_outputs ;set lights endif return ; ;-----------------------------------------------------------------------------------------------; ;subroutines ; ;-----------------------------------------------------------------------------------------------; ; ;output midi note-on command send_note_on: let midi_data=note_on+midi_chan gosub send_midi let midi_data=midi_note gosub send_midi let midi_data=midi_vel gosub send_midi return ; ;output midi note-off command send_note_off: let midi_data=note_off+midi_chan gosub send_midi let midi_data=midi_note gosub send_midi let midi_data=0 gosub send_midi return ; ;output midi all notes off command on all channels send_all_off: let t_midi=midi_chan for midi_chan=0 to 15 ;send on all channels let midi_data=cont_ctr+midi_chan ;send all notes off gosub send_midi let midi_data=$7b gosub send_midi let midi_data=0 gosub send_midi next let midi_chan=t_midi return ; ;output midi program change command send_prog_change: let midi_data=pgm_chg+midi_chan gosub send_midi let midi_data=midi_pgm gosub send_midi return ; ;output midi continuous controller command ;midi_cc is controller number ;midi_data is controller data send_cc: let t_midi=midi_data let midi_data=cont_ctr+midi_chan gosub send_midi let midi_data=midi_cc gosub send_midi let midi_data=t_midi gosub send_midi return ; ;gets midi_data from buffer ;rcx_data_flg=1 if successful, rcx_data_flg=0 if no data in buffer ;written by David J. Brown get_rcx_bfr: hserin get_rcx_bfr1,0,[midi_data] if midi_data=$fe then get_rcx_bfr ;ignore active status let rcx_data_flg=1 ;set data returned flag return get_rcx_bfr1: let rcx_data_flg=0 ;set empty flag return ; ;send midi_data ;waits until transmitter ready if polled ;puts data in buffer if interrupt enabled ;written by David J. Brown send_midi: hserout [midi_data] ;put data in transmit buffer return ; #ifndef input_int_en ;sample in-1 to in-4 ;in_jx is input value (0 - 1023) ;150 uS execution time get_inputs: adin pin_j1,in_j1 adin pin_j2,in_j2 adin pin_j3,in_j3 adin pin_j4,in_j4 return ; ;sample and average in-1 to in-4 ;in_jx is input value averaged over last four samples (0 - 1023) ;in_jx_bfr(0) & in_jx_bfr(1) are last four word samples ;600 uS execution time ;written by David J. Brown get_inputs_avg: adin pin_j1,in_j1_bfr.word1(in_j1_ptr) ;get in-1 into buffer let in_j1_tmp=in_j1_bfr(0)+in_j1_bfr(1) ;add two high words together and low words together let in_j1=(in_j1_tmp.word1+in_j1_tmp.word0)/4 adin pin_j2,in_j2_bfr.word1(in_j1_ptr) ;get in-2 into buffer let in_j2_tmp=in_j2_bfr(0)+in_j2_bfr(1) ;add two high words together and low words together let in_j2=(in_j2_tmp.word1+in_j2_tmp.word0)/4 adin pin_j3,in_j3_bfr.word1(in_j1_ptr) ;get in-3 into buffer let in_j3_tmp=in_j3_bfr(0)+in_j3_bfr(1) ;add two high words together and low words together let in_j3=(in_j3_tmp.word1+in_j3_tmp.word0)/4 adin pin_j4,in_j4_bfr.word1(in_j1_ptr) ;get in-4 into buffer let in_j4_tmp=in_j4_bfr(0)+in_j4_bfr(1) ;add two high words together and low words together let in_j4=(in_j4_tmp.word1+in_j4_tmp.word0)/4 let in_j1_ptr=(in_j1_ptr+1)&$03 ;increment pointer and wrap at 3 return #endif ; ;output out_jx values to dacs ;written by Grant Richter ;750 uS execution time load_outputs: ;add addresses to values ;shift out 16 bits mode 4 shiftout ser_data,clock,fastmsbpre,[(out_j1+49152)\16] pulsout load_dacs,1 ;pulse loaddacs for each channel shiftout ser_data,clock,fastmsbpre,[(out_j2+32768)\16] pulsout load_dacs,1 ;pulse loaddacs for each channel shiftout ser_data,clock,fastmsbpre,[(out_j3+16384)\16] pulsout load_dacs,1 ;pulse loaddacs for each channel shiftout ser_data,clock,fastmsbpre,[out_j4\16] pulsout load_dacs,1 ;pulse loaddacs for each channel return ; ;-----------------------------------------------------------------------------------------------; ;interrupt service routines ; ;-----------------------------------------------------------------------------------------------; ; #ifdef timer_int_en ;interrupt service routine for timer ;increments time_count value ;turn off stop led at turn_off value ;toggle run led at 512 mS intervals ;written by David J. Brown tm_isr: let time_count=time_count+1 ;increment real time count if time_count=turn_off then ;value to turn off stop led low stop_led endif let run_led_out=time_count.bit9 ;toggle run led at 512 mS intervals #endif #ifndef input_int_en resume ;resume if input polled mode #else ;sample in-1 - in-4 at specific intervals ;injx is input averaged over last 4 samples (0 - 1023) ;injx_bfr(0) & injx_bfr(1) are last 4 word samples let isr_cnt=isr_cnt+1 ;change the following table to modify the scan rate for each input ;175 uS execution time so maximum of one sample and average per interrupt ;currently set for: in-1 @ 2 mS, in-2 @ 4 mS, in-3 @ 8 mS, in-4 @ 8 mS branch isr_cnt, [avg1,avg2,avg1,avg3,avg1,avg2,avg1,avg4,avg1,avg2,avg1,avg3,avg1,avg2,avg1,avg4] ;sample in-1 avg1: adin pin_j1,in_j1_bfr.word1(in_j1_ptr) ;get in-1 into buffer let in_j1_tmp=in_j1_bfr(0)+in_j1_bfr(1) ;add two high words together and low words together let in_j1=(in_j1_tmp.word1+in_j1_tmp.word0)/4 let in_j1_ptr=(in_j1_ptr+1)&$03 ;increment pointer and wrap at 3 resume ;sample in-2 avg2: adin pin_j2,in_j2_bfr.word1(in_j2_ptr) ;get in-2 into buffer let in_j2_tmp=in_j2_bfr(0)+in_j2_bfr(1) ;add two high words together and low words together let in_j2=(in_j2_tmp.word1+in_j2_tmp.word0)/4 let in_j2_ptr=(in_j2_ptr+1)&$03 ;increment pointer and wrap at 3 resume ;sample in-3 avg3: adin pin_j3,in_j3_bfr.word1(in_j3_ptr) ;get in-3 into buffer let in_j3_tmp=in_j3_bfr(0)+in_j3_bfr(1) ;add two high words together and low words together let in_j3=(in_j3_tmp.word1+in_j3_tmp.word0)/4 let in_j3_ptr=(in_j3_ptr+1)&$03 ;increment pointer and wrap at 3 resume ;sample in-4 avg4: adin pin_j4,in_j4_bfr.word1(in_j4_ptr) ;get in-4 into buffer let in_j4_tmp=in_j4_bfr(0)+in_j4_bfr(1) ;add two high words together and low words together let in_j4=(in_j4_tmp.word1+in_j4_tmp.word0)/4 let in_j4_ptr=(in_j4_ptr+1)&$03 ;increment pointer and wrap at 3 resume #endif ; ;-----------------------------------------------------------------------------------------------; ;end of program ; ;-----------------------------------------------------------------------------------------------;