;-----------------------------------------------------------------------------------------------; ; Program: Multi Phase LFO ; ; 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: ; ; Multiphased outputs at 0, 120, 240, and variable degrees ; Frequency range 0.3 hz to 4 hz ; ; Inputs: ; In1 = waveform selection (read at start) ; note: (calibrated to my control positions) ; position 0 - 2 pulse ; position 2 - 4 sine ; position 4 - 6 triangle ; position 6 - 8 ramp ; position 8 -10 saw ; In2 = frequency (no effect until end of current waveform cycle) ; In3 = square duty cycle ; In4 = variable phase for out4 ; ; Outputs: ; Out1 = lfo ; Out2 = lfo shifted 120 degrees ; Out3 = lfo shifted 240 degrees ; Out4 = lfo shifted in4 variable degrees ; ; Start: Generate waveform outputs. Run led indicates waveform mode ; Stop: Enter waveform select mode. Stop led indicates select mode ; Note: Stop must be held until end of current waveform cycle ; ; Written by David J. Brown ; Revision: 0.4S2 ; Sept 25, 2010 ; History: 0.4S2 changed serial for Studio ; 0.4X changed shiftout for Studio, removed serial speakjet ; 0.4 removed debug_led and send_cc,hex2ascii, display_in, ; display_out, and hex_speakjet to eliminiate push/pop ; 0.31 converted to psim template, integrated waveform ; generation into waveform select code ; 0.3 added display of program name, waveform, ; duty cycle (%), and phase (degrees), switched pulse and ; sine positions ; 0.2 changed if then else waveform selection ; 0.1 initialize aux output low and speakjet pins ; 0.0 initial release of multiphase lfo ; Date: April 25, 2004 ; ;---------ENABLE MIDI INTERRUPT CONDITIONAL COMPILE OPTION--------------------------------------; ; Note: speakjet and console serial output is not compatible with interrupts ; ; ; ; COMMENT OUT NEXT LINE TO DISABLE MIDI INTERRUPTS/ENABLE POLLED ; midi_int_en con 1 ;define to enable midi interrupts ; ; ;comment to set polled midi mode ; ;-----------------------------------------------------------------------------------------------; ;---------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 ; ; ; ;-----------------------------------------------------------------------------------------; ; ; ; ;-----------------------------------------------------------------------------------------------; ; Program: PSIM Template ; Developed by David J. Brown ; Contains portions written by Brice Hornback and Grant Richter ; Revision: 0.65 ; Date: January 29, 2006 ; History: 0.65 added display_in to display four input voltages, ; added display_out to display four output voltages, ; programmed voltage characters, updated sample code, ; added GPL ; 0.64 added hex2ascii for conversion with leading 0's, ; default display message, removed serial hex_led routine ; 0.63 removed ;high midi_sdata' command which limited ; TxD (P15) to V(ol)=1.5 volts ; 0.62 added hex_lcd routine, changed debug_data to ; data_hex, changed debug_speakjet to hex_speakjet, ; debug_led to hex_led, and debug_console to hex_console, ; added start message ; 0.61 change dirs command for MIDI out pin, changed ; load_outputs to 'or' instead of 'add' ; 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 ; Written: April 13, 2004 ; ;-----------------------------------------------------------------------------------------------; ; PSIM-1 module from SynthModules.com ; ; BasicMicro AtomPro24 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 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 ;display declarations num_data var byte ;data for ascii conversion: hex2ascii huns var byte ;hundreds digit: hex2ascii tens var byte ;tens digit: hex2ascii, display_in, display_out ones var byte ;ones digit: hex2ascii, display_in, display_out huns_p var byte ;phase hundreds digit tens_p var byte ;phase tens digit ones_p var byte ;phase ones digit tens_d var byte ;duty tens digit ones_d var byte ;duty ones digit ;misc declararation tempb var byte ;temp byte tempb2 var byte ;temp byte tempw var word ;temp word data_hex var byte ;variable: debug_led, debug_console fivevolts con 1920 ;5 volt output value round var byte ;used to convert 2's compliment sbyte to byte alpha var byte ;phase index counter index var byte ;table index pointer (wraps at 256) offset var byte ;variable phase offset offset_p var word ;variable phase offset in degrees duty var byte ;pulse duty cycle duty_d var word ;pulse duty cycle in percent freq var word ;frequency delay wave var word ;waveform select table var word(256) ;wave table of values ; ;-----------------------------------------------------------------------------------------------; ; 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 data_hex=0 ;set data_hex to 0 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 ; #ifndef midi_int_en ;initialize midi hardware ;these next 6 commands need to be in this order let scr3=%00000000 ;reset Serial Control Register let smr=%00000000 ;set Serial Mode Register ; asynchronous ; 8 bits ; parity disabled ; even parity (disabled) ; 1 stop bit ; multiprocessor mode disabled ; brr clock source direct let brr=15 ;set Bit Rate Register for 31500 baud pauseus 100 ;let brr settle for 50 uS let scr3=%00110000 ;set Serial Control Register ; transmit or receive interrupts disabled ; transmit and receive enabled ; multiprocessor interrupt disabled ; transmit end interrupt disabled ; internal baud rate generator let pmr1=%00001110 ;set Port Mode Register ; P17 general I/O port ; P16 general I/O port ; P15 general I/O port ; P14 general I/O port ; txd output ; P10 general I/O port #endif ; #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 ; 16 MHz clock /8 prescalar S = 2 MHz timer clock ; let gra=20023 ;2 MHz /20000 =10 mS (adjusted to measurement) let gra=2003 ;2 MHz / 2000 = 1 mS (adjusted to measurement) #endif ; ;enable timerW interrupt #ifdef timer_int_en 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 #ifdef midi_int_en sethserial1 h31200,h8databits,hnoparity,h1stopbits pause 250 ;assume display initializaton may take longer hserout [$f0,$7d,$0a,$18,$f7] ;clear display, overwrite #endif ; ;program voltage characters #ifdef midi_int_en hserout [$f0,$7d,$10,$01,$1f,$09,$00,$11,$1f,$11,$f7] ;character0 "I1" hserout [$f0,$7d,$11,$0d,$15,$17,$00,$11,$1f,$11,$f7] ;character1 "I2" hserout [$f0,$7d,$12,$0e,$15,$15,$00,$11,$1f,$11,$f7] ;character2 "I3" hserout [$f0,$7d,$13,$1f,$04,$1c,$00,$11,$1f,$11,$f7] ;character3 "I4" hserout [$f0,$7d,$14,$01,$1f,$09,$00,$0e,$11,$0e,$f7] ;character4 "O1" hserout [$f0,$7d,$15,$0d,$15,$17,$00,$0e,$11,$0e,$f7] ;character5 "O2" hserout [$f0,$7d,$16,$0e,$15,$15,$00,$0e,$11,$0e,$f7] ;character6 "O3" hserout [$f0,$7d,$17,$1f,$04,$1c,$00,$0e,$11,$0e,$f7] ;character7 "O4" #endif ; ;-----------------------------------------------------------------------------------------------; ; Main program ; ;-----------------------------------------------------------------------------------------------; ; select: ;display waveform and wait for start low run_led ;set run led off high stop_led ;set stop led on ;determine out4 offset gosub get_inputs let offset=in_j4/4 ;set range 0 - 255 let offset_p=(offset*45)/32 ;convert to degrees 0-360 let offset=offset^$ff ;invert so offsets to leading edge if offset_p >99 then let huns_p=offset_p/100 let offset_p=offset_p-(huns_p*100) let huns_p=huns_p+$30 else let huns_p=$20 endif if offset_p >9 then let tens_p=offset_p/10 let offset_p=offset_p-(tens_p*10) let tens_p=tens_p+$30 else let tens_p=$20 endif if huns_p<>0 then ;check if 10x, 20x or 30x if tens_p=$20 then let tens_p=$30 ;make middle digit 0 and not space endif endif let ones_p=offset_p+$30 ; ;determine duty cycle let duty=in_j3/4 ;set range 0 - 255 let duty=duty&$fe ;do not allow 255, must be at least 1 bit pulse let duty_d=(duty*25)/64 ;convert to %0-99 if duty_d >9 then let tens_d=duty_d/10 let duty_d=duty_d-(tens_d*10) let tens_d=tens_d+$30 else let tens_d=$20 endif let ones_d=duty_d+$30 ; ;determine waveform let wave=in_j1 if wave>760 then ;set for 8 - 10 postion hserout [$f0,$7d,"lfo out4saw ",huns_p,tens_p,ones_p,$0f,$df,$0e,$f7] ;create 256 long wave table of saw function for alpha=0 to 255 let table(alpha)=15*(255-alpha) ;scale from 256 to 3840 for 10+ volt output next elseif wave>495 ;set for 6 - 8 position hserout [$f0,$7d,"lfo out4rmp ",huns_p,tens_p,ones_p,$0f,$df,$0e,$f7] ;create 256 long wave table of ramp function for alpha=0 to 255 let table(alpha)=15*alpha ;scale from 256 to 3840 for 10+ volt output next elseif wave>325 ;set for 4 - 6 position hserout [$f0,$7d,"lfo out4tri ",huns_p,tens_p,ones_p,$0f,$df,$0e,$f7] ;create 256 long wave table of triangle function for alpha=0 to 255 if alpha <128 then let table(alpha)=30*alpha ;scale 2x for each half cycle to 3840 for 10+ volt output else let table(alpha)=30*(255-alpha) endif next elseif wave>140 ;set for 2 - 4 position hserout [$f0,$7d,"lfo out4sin ",huns_p,tens_p,ones_p,$0f,$df,$0e,$f7] ;create 256 long wave table of sine function for alpha=0 to 255 let round=128+sin(alpha) ;add 128 to convert from sbyte to byte table(alpha)=15*round ;scale from 256 to 3840 for 10+ volt output next else ;set for 0 - 2 position hserout [$f0,$7d,"lfo d",tens_d,ones_d,"%pul ",huns_p,tens_p,ones_p,$0f,$df,$0e,$f7] ;create 256 long wave table of pulse function for alpha=0 to 255 if alpha > duty then let table(alpha)=0 else let table(alpha)=3840 ;scale from 256 to 3840 for 10+ volt output endif next endif pause 50 if start_j=0 then select ; ;output waveform high run_led ;set run led on low stop_led ;set stop led off loop: ;determine frequency let adin pin_j2,in_j2 let freq=in_j2*16 ;set frequency range 0 - 16535 let freq=freq^$3fff ;reverse range so 16535 is fast let freq=freq|$0001 ;do not allow 0 ; ;output one cycle of waveform for alpha=0 to 255 let out_j1=table(alpha) let index=alpha+170 ;offset 120 degrees, wrap at 360 let out_j2=table(index) let index=alpha+85 ;offset 240 degrees, wrap at 360 let out_j3=table(index) let index=alpha+offset ;variable phase offset let out_j4=table(index) gosub load_outputs pauseus freq next ; ;check for stop if stop_j=0 then loop goto select ; ;-----------------------------------------------------------------------------------------------; ; 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 send_all_off: 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 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 tempb=midi_data let midi_data=cont_ctr+midi_chan gosub send_midi let midi_data=midi_cc gosub send_midi let midi_data=tempb gosub send_midi return ; #ifndef midi_int_en ;poll midi-in ;puts data into buffer and sets rcx_bfr_num to number of entries ;written by David J. Brown check_midi: let rcx_status=ssr if rcx_status&%01000000 then ;data has been received let rcx_data=rdr ;read Receiver Data Register if rcx_data<>$fe then ;ignore active status ;put midi_data into receive buffer ;check to see if buffer full if rcx_bfr_num=rcx_bfr_len then ;buffer is full ;simply loose data else ;buffer has space let rcx_bfr(rcx_ptr_end)=rcx_data let rcx_bfr_num=rcx_bfr_num+1 let rcx_ptr_end=rcx_ptr_end+1 if rcx_ptr_end=rcx_bfr_len then rcx_ptr_end=0 ;wrap pointer at max value endif endif endif else ;no data received ;check if error if rcx_status&%00111000 then ;error condition let rcx_status=rcx_status&%10000111 let ssr=rcx_status ;reset error bits endif endif return #endif ; ;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: #ifndef midi_int_en ;check to see if buffer empty if rcx_bfr_num=0 then ;buffer is empty let rcx_data_flg=0 ;set empty flag else ;buffer has data let midi_data=rcx_bfr(rcx_ptr_strt) let rcx_bfr_num=rcx_bfr_num-1 let rcx_ptr_strt=rcx_ptr_strt+1 if rcx_ptr_strt=rcx_bfr_len then let rcx_ptr_strt=0 ;wrap pointer at max value endif let rcx_data_flg=1 ;set data returned flag endif return #else 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 #endif ; ;send midi_data ;waits until transmitter ready if polled ;puts data in buffer if interrupt enabled ;written by David J. Brown send_midi: #ifndef midi_int_en ;enable midi-out on timer interrupts let tx_status=ssr ;poll midi-out if tx_status&%10000000 then ;check transmitter ready ;ready to transmit let tdr=midi_data ;send data to tdr return endif goto send_midi #else hserout [midi_data] ;put data in transmit buffer return #endif ; ;convert byte num_data to three ascii digits ;updates huns, tens, ones variables ;use to generate leading zeros for fixed column display ;written by David J. Brown hex2ascii: let tempb=num_data ;save data if num_data >99 then let huns=num_data/100 ;calculate hundreds let num_data=num_data-(huns*100) ;prepare for tens let huns=huns+$30 ;convert to ascii else let huns=$30 ;leading 0 in ascii endif if num_data >9 then let tens=num_data/10 ;calculate tens let num_data=num_data-(tens*10) ;prepare for ones let tens=tens+$30 ;convert to ascii else let tens=$30 ;leading 0 in ascii endif let ones=num_data+$30 ;convert to ascii let num_data=tempb ;restore data return ; ;update display with four input voltages in_jx ;written by David J. Brown display_in: let tempb=ones let tempb2=tens ;*100)/1023 is divide by 10.23 and *10)/1023 is divide by 102.3 let ones=(in_j1*10)/1023 ;convert to integer digits let tens=((in_j1-((ones*1023)/10))*100)/1023 hserout [$f0,$7d,$0d,$00,dec ones,".",dec tens] ;home1 and display in_j1 voltage let ones=(in_j2*10)/1023 ;convert to integer digits let tens=((in_j2-((ones*1023)/10))*100)/1023 hserout [$01,dec ones,".",dec tens] ;display in_j2 voltage let ones=(in_j3*10)/1023 ;convert to integer digits let tens=((in_j3-((ones*1023)/10))*100)/1023 hserout [$02,dec ones,".",dec tens] ;display in_j3 voltage let ones=(in_j4*10)/1023 ;convert to integer digits let tens=((in_j4-((ones*1023)/10))*100)/1023 hserout [$03,dec ones,".",dec tens,$f7] ;display in_j4 voltage and end sysex let tens=tempb2 let ones=tempb return ; ;update display with four output voltages out_jx ;note: 10 displays as "A" (e.g. A.6 volts) ;written by David J. Brown display_out: let tempb=ones let tempb2=tens ;/4)*25)/24 is divide by 3.84 to convert 4095 to 1066 (10.66 volts) let tempw=out_j1 let out_j1=((out_j1/4)*25)/24 ;convert to 4 digit voltage let ones=out_j1/100 ;convert to integer digits let tens=(out_j1-(ones*100))/10 if ones=10 then let ones=$11 ;convert 10 to A endif let out_j1=tempw hserout [$f0,$7d,$0d,$04,ones+$30,".",dec tens] ;home1 and display out_j1 voltage let tempw=out_j2 let out_j2=((out_j2/4)*25)/24 ;convert to 4 digit voltage let ones=out_j2/100 ;convert to integer digits let tens=(out_j2-(ones*100))/10 if ones=10 then let ones=$11 ;convert 10 to A endif let out_j2=tempw hserout [$05,ones+$30,".",dec tens] ;display out_j2 voltage let tempw=out_j3 let out_j3=((out_j3/4)*25)/24 ;convert to 4 digit voltage let ones=out_j3/100 ;convert to integer digits let tens=(out_j3-(ones*100))/10 if ones=10 then let ones=$11 ;convert 10 to A endif let out_j3=tempw hserout [$06,ones+$30,".",dec tens] ;display out_j3 let tempw=out_j4 let out_j4=((out_j4/4)*25)/24 ;convert to 4 digit voltage let ones=out_j4/100 ;convert to integer digits let tens=(out_j4-(ones*100))/10 if ones=10 then let ones=$11 ;convert 10 to A endif let out_j4=tempw hserout [$07,ones+$30,".",dec tens,$f7] ;display out_j4 voltage and end sysex let tens=tempb2 let ones=tempb 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 ; ;send data_hex to console ;written by David J. Brown hex_console: #ifdef midi_int_en ;interrupts must be off for correct timing disable #endif #ifdef timer_int_en disable timerwint_imiea #endif serout s_out,i38400,[hex data_hex,13] #ifdef timer_int_en enable timerwint_imiea #endif #ifdef midi_int_en enable #endif return ; ;output out_jx values to dacs ;750 uS execution time load_outputs: ;add dac address to out_jx values and shift 16 bits using mode 4 shiftout ser_data,clock,fastmsbpre,[(out_j1|$c000)\16] pulsout load_dacs,1 ;clock loaddacs shiftout ser_data,clock,fastmsbpre,[(out_j2|$8000)\16] pulsout load_dacs,1 ;clock loaddacs shiftout ser_data,clock,fastmsbpre,[(out_j3|$4000)\16] pulsout load_dacs,1 ;clock loaddacs shiftout ser_data,clock,fastmsbpre,[out_j4\16] pulsout load_dacs,1 ;clock loaddacs 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 ;written by David J. Brown 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 ; ;-----------------------------------------------------------------------------------------------;