;-----------------------------------------------------------------------------------------------; ; Program: CVS Klee Sequencer ; ; 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 implements a partial Klee sequencer. It can be set to a single 16 bit shift ; register or two 8 bit registers. If set to 8 bit registers, the lower shift register clocks ; at half the rate. ; ; The input and offset controls adjust the control voltage based on the attenuation of the bit ; in the shift register corresponding to that control. The level is auto-ranged so that the ; full 10 volt range is used. The output is then quantized, ranged and offset for a smaller span. ; ; MIDI notes are sent corresponding to the control voltage with a program change corresponding ; to the lower 6 bits of the upper byte of the shift register. ; ; Menus are used to input and set various program parameters: ; Gate1 register set for comparison with the shift register (saved in nv memory) ; Offset in semitones to add to midi note value (saved in nv memory) ; ; The program will detect the external control module. The external control ; will be used for variable input if present; otherwise Offset8 will be ; used. * and # will operate as Start and Stop in most menus. ; ; Inputs: ; Start = Various menu selection input ; Stop = Various menu selection input ; In-1 = Bit 16 level ; In-2 = Bit 15 level ; In-3 = Bit 14 level ; In-4 = Bit 13 level ; In-5 = Bit 12 level ; In-6 = Bit 11 level ; In-7 = Bit 10 level ; In-8 = Bit 9 level ; Off1 = Bit 8 level ; Off2 = Bit 7 level ; Off3 = Bit 6 level ; Off4 = Bit 5 level ; Off5 = Bit 4 level ; Off6 = Bit 3 level ; Off7 = Bit 2 level ; Off8 = Bit 1 level and menu values (if external controls not used) ; Aux = Clock In ; Midi-In = ; ; Outputs: ; Out-1 = 16 bit CV Out, 0 to 10 volts ; Out-2 = High 8 bit CV Out, 0 to 10 volts ; Out-3 = Low 8 bit CV Out, 0 to 10 volts ; Out-4 = 16 bit Gate1 Out, 0 to 5 volts ; Out-5 = High 8 bit Gate Out, 5 volts ; Out-6 = Low 8 bit Gate Out, 5 volts ; Out-7 = Trigger, 5 Volts, 5 mS ; Out-8 = Alternate Trigger, 5 Volts, 5 mS ; Aux = ; Midi-Out= Notes (offset by midi_offset) ; Speakjet= ; ; Display = Menu selection or step and note number ; Run led = Toggles @ 0.5 S (timer interrupts enabled) ; Stop led= Indicates setup mode ; ; Revision: 0.1 ; Date April 11, 2010 ; History: 0.1 changed running, send_all_off, hex2ascii, display_in, ; and display_out to eliminiate push/pop, added pin ; modifications for IDE8.0.1.7 ; 0.0 initial release of program ; Written: January 18, 2009 ; ;---------PSIM OR CVS CONDITIONAL COMPILE OPTION------------------------------------------------; ; ; ; COMMENT OUT NEXT LINE FOR PSIM CONFIGURATION ; cvs con 1 ;define for CVS configuration ; ;-----------------------------------------------------------------------------------------------; ;---------ENABLE AUX_IN RISING EDGE INTERRUPT CONDITIONAL COMPILE OPTION------------------------; ; ; ; COMMENT OUT NEXT LINE TO DISABLE AUX INPUT RISING EDGE INTERRUPTS ; ;aux_int_en con 1 ;define to enable aux_in rising edge interrupts ; ; ;comment to disable aux_in rising edge interrupts ; ;-----------------------------------------------------------------------------------------------; ;---------ENABLE TIMER INTERRUPT CONDITIONAL COMPILE OPTION-------------------------------------; ; Notes: run led will blink to verify timer operation ; ; ; ; 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 IN 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 ; ; ; ;-----------------------------------------------------------------------------------------; ; ; ; ; ;------ENABLE RISING EDGE DETECT IN TIMER INTERRUPT CONDITIONAL COMPILE OPTION------------; ; ; ; Note: requires timer_int_en to be defined ; ; ; ; pulse must be > 1 mS and > 8 mS period (7 timer clocks low / 1 timer clock high) ; ; ; ; ; ; ; ; COMMENT OUT NEXT LINE TO DISABLE RISING EDGE DETECT IN TIMER INTERRUPTS ; ; ;edge_int_en con 1 ;define to enable rising edge detect mode ; ; ; ; ;comment to disable rising edge detect mode ; ; ; ; UNCOMMENT ONE OF NEXT THREE LINES TO SELECT INPUT FOR RISING EDGE DETECT ; ; ;edge_in var in4 ;use start jack for rising edge detect input ; ; ;edge_in var in5 ;use stop jack for rising edge detect input ; ; ;edge_in var in8 ;use aux jack for rising edge detect input ; ; ; ;-----------------------------------------------------------------------------------------; ; ; ; ;-----------------------------------------------------------------------------------------------; ; Program: PSIM-CVS Template ; Developed by David J. Brown ; Revision: 1.0 ; Date: August 19, 2006 ; History: 1.0 added CVS configuration and midi processor code, ; changed hex2ascii from byte to word conversion ; 0.8 removed conditionals for MIDI interrupts, deleted ; polled routines check_midi and get_rcx_bfr, deleted ; obsolete debug_led and hex_console routines, optimized ; midi command subroutines ; 0.7 converted speakjet to i2c protocol, modified speakjet ; phrase definitions and recoded hex_speakjet ; 0.66 added edge_flg to detect rising edges in timer isr, ; added aux_cnt for aux_in rising edge interrupts, added ; display command summary ; 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 ; ;-----------------------------------------------------------------------------------------------; ; BasicMicro AtomPro2X PSIM / CVS ; ;-----------------------------------------------------------------------------------------------; ; P0 - digital in/out, analog in-1 ; ; P1 - digital in/out, analog in-2 ; ; P2 - digital in/out, analog in-3 ; ; P3 - digital in/out, analog in-4 ; ; P4 - start button (no input/default=0/low, pressed=1/hi) ; ; P5 - stop button (no input/default=0/low, pressed=1/hi) ; ; P6 - i2c data ; ; P7 - i2c clock ; ; P8 - aux in/out (PSIM: no input/default=1/hi, CVS: no input/default=0/low) ; ; P9 - stop led (low=off, hi=on) ; ; P10 - run led (low=off hi=on) ; ; P11 - dac load_dacs ; ; P12 - dac ser_data ; ; P13 - dac clock ; ; P14 - midi-in ; ; P15 - midi-out ; ;-----------------------------------------------------------------------------------------------; ; BasicMicro AtomPro28 CVS pins ; ;-----------------------------------------------------------------------------------------------; ; P16 - digital in/out, analog in-7 ; ; P17 - digital in/out, analog in-6 ; ; P18 - digital in/out, analog in-5 ; ; P19 - digital in/out, analog in-4 ; ;-----------------------------------------------------------------------------------------------; ; DJB-LCD commands ; ;-----------------------------------------------------------------------------------------------; ; $08 - (backspace) moves the active display position one backwards ; ; $09 - (tab) moves the active display position one forward ; ; $0a - (line feed) clears the display & sets active display position to beginning of line 1 ; ; $0b - (vertical tab) sets the active display position to beginning of line 2 ; ; $0c - (form feed) clears the display & sets active display position to beginning of line 2 ; ; $0d - (carriage return) Sets the active display position to beginning of line 1 ; ; $0e - (shift out) selects the lower characters set for display ; ; $0f - (shift in) selects the upper characters set for display ; ; $10 - program character0 row7, row6 ... row0 (bottom) ; ; $11 - program character1 row7, row6 ... row0 (bottom) ; ; $12 - program character2 row7, row6 ... row0 (bottom) ; ; $13 - program character3 row7, row6 ... row0 (bottom) ; ; $14 - program character4 row7, row6 ... row0 (bottom) ; ; $15 - program character5 row7, row6 ... row0 (bottom) ; ; $16 - program character6 row7, row6 ... row0 (bottom) ; ; $17 - program character7 row7, row6 ... row0 (bottom) ; ; $18 - sets the display mode to overwrite; new characters overwrite previous ; ; $19 - sets the display mode to scroll; display scrolls for new characters ; ; ; ; CVS implements these six commands: ; ; $1a - sets absolute position data ; ; $1b - sets relative position data ; ; $1c - reserved ; ; $1d - reserved ; ; $1e - reserved ; ; $1f - writes new default message character 1, character 2 ... character 32 ; ; ; ; DJB-PSIM implements these six commands: ; ; $1a - reserved ; ; $1b - reserved ; ; $1c - set Out1 data (0=no change, 1=reset to low, 2=set to high, 3=toggle) ; ; $1d - set Out2 data (0=no change, 1=reset to low, 2=set to high, 3=toggle) ; ; $1e - set Out3 data (0=no change, 1=reset to low, 2=set to high, 3=toggle) ; ; $1f - set Out4 data (0=no change, 1=reset to low, 2=set to high, 3=toggle) ; ;-----------------------------------------------------------------------------------------------; ; TTS-256 / SpeakJet commands ; ;-----------------------------------------------------------------------------------------------; ; enable TTS256 pass through: i2cout i2c_data,i2c_clk,$0,[($48<<1),"passthruon",$0d] ; ; terminate TTS256 pass through: i2cout i2c_data,i2c_clk,$0,[($48<<1),"X"] ; ; $00 - pause 0 mS ; ; $01 - pause 100 mS ; ; $02 - pause 200 mS ; ; $03 - pause 700 mS ; ; $04 - pause 30 mS ; ; $05 - pause 60 mS ; ; $06 - pause 90 mS ; ; $07 - play next sound fast ; ; $08 - play next sound slow ; ; $0e - play next sound high tone ; ; $0f - play next sound low tone ; ; $15 - speed ; ; $16 - pitch ; ; $17 - pitch ; ; $c8 to $d1 - robot sounds ; ; $d2 to $db - alarm sounds ; ; $dc to $e5 - beep sounds ; ; $e6 to $ef - biological sounds ; ; $f0 to $fb - DTMF sounds (0 1 2 3 4 5 6 7 8 9 * #) ; ; $fc - sonar ping ; ; $fd - pistol shot ; ; $fe - wow ; ;-----------------------------------------------------------------------------------------------; ; ;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 #ifdef cvs ;these pin definitions changed between IDE 8.0.1.0 and 8.0.1.7 ;uncomment the correct definitions for the version of IDE ;-----------------------------------------------------------------------------------------------; ;IDE 8.0.1.0 and previous ; ; pin_j5 con p16 ;in-5 pin ; ; pin_j6 con p17 ;in-6 pin ; ; pin_j7 con p18 ;in-7 pin ; ; pin_j8 con p19 ;in-8 pin ; ;-----------------------------------------------------------------------------------------------; ;IDE 8.0.1.7 ; pin_j5 con p18 ;in-5 pin ; pin_j6 con p19 ;in-6 pin ; pin_j7 con p17 ;in-7 pin ; pin_j8 con p16 ;in-8 pin ; ;-----------------------------------------------------------------------------------------------; #endif start_j var in4 ;start jack and switch stop_j var in5 ;stop jack and switch i2c_data con p6 ;i2c data pin i2c_clk con p7 ;i2c clock pin aux_j con p8 ;aux jack pin (used with high/low/toggle) aux_in var in8 ;aux jack (used for input) stop_led con p9 ;stop led (used with high/low/toggle) stop_led_out var out9 ;stop led alias (used with let) run_led con p10 ;run led (used with high/low/toggle) run_led_out var out10 ;run led alias (used with let) 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 #ifdef cvs in_j5 var word ;in-5 value: get_inputs, get_inputs_avg, avg1 in_j6 var word ;in-6 value: get_inputs, get_inputs_avg, avc2 in_j7 var word ;in-7 value: get_inputs, get_inputs_avg, avg3 in_j8 var word ;in-8 value: get_inputs, get_inputs_avg, avg4 in_j9 var word ;in-9 value in_j10 var word ;in-10 value in_j11 var word ;in-11 value in_j12 var word ;in-12 value in_j13 var word ;in-13 value in_j14 var word ;in-14 value in_j15 var word ;in-15 value in_j16 var word ;in-16 value #endif 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 #ifdef cvs out_j5 var word ;out-5 value: load_outputs out_j6 var word ;out-6 value: load_outputs out_j7 var word ;out-7 value: load_outputs out_j8 var word ;out-8 value: load_outputs olat var byte ;output latch: load_outputs ; bit7=dac2 select (high=enable) ; bit6=dac1 select (high=enable) ; bit5=reserved ; bit4=reserved ; bit3=reserved ; bit2=offset level (high=5 volts, low=10 volts) ; bit1=offset voltage enable (high=enable) ; bit0=control voltage enable (high=enable) #endif ;midi variable declarations allup con $7b ;midi all notes-off command keyup con $80 ;midi note-off command keydn con $90 ;midi note-on command conctrl con $b0 ;midi continuous controller command pgmchg con $c0 ;midi program change command chnprs con $d0 ;midi channel pressure command pitchb con $e0 ;midi pitch bend command midi_chan var nib ;midi channel: send_note_on, send_note_off, send_cc, send_prog_change 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 trans_chan var byte ;midi in channel transpose (added to midi channel) trans_note var byte ;midi in note tranpose (added to note value) 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 midi_data var byte ;variable: 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 ;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 ;edge detect declarations #ifdef edge_int_en edge_state var byte ;eight samples of edge input: tm_isr edge_flg var byte ;edge flag (1=rising edge, 0=no rising edge): tm_isr #endif #ifdef aux_int_en aux_cnt var word ;aux interrupt count: aux_isr #endif ;input buffer declarations in_j1_ptr var byte ;in-1 buffer pointer: avgx, get_inputs_avg isr_cnt var nib ;timer pass counter: tm_isr (always define due to conditionals) #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 in_j5_ptr var byte ;in-5 buffer pointer: avgx in_j6_ptr var byte ;in-6 buffer pointer: avgx in_j7_ptr var byte ;in-7 buffer pointer: avgx in_j8_ptr var byte ;in-8 buffer pointer: avgx #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 #ifdef cvs in_j5_tmp var long ;in-5 temporary variable: avgx, get_inputs_avg in_j6_tmp var long ;in-6 temporary variable: avgx, get_inputs_avg in_j7_tmp var long ;in-7 temporary variable: avgx, get_inputs_avg in_j8_tmp var long ;in-8 temporary variable: avgx, get_inputs_avg in_j9_tmp var long ;in-9 temporary variable in_j10_tmp var long ;in-10 temporary variable in_j11_tmp var long ;in-11 temporary variable in_j12_tmp var long ;in-12 temporary variable in_j13_tmp var long ;in-13 temporary variable in_j14_tmp var long ;in-14 temporary variable in_j15_tmp var long ;in-15 temporary variable in_j16_tmp var long ;in-16 temporary variable #endif 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 #ifdef cvs in_j5_bfr var long(2) ;in-5 last 4 samples buffer: avgx, get_inputs_avg in_j6_bfr var long(2) ;in-6 last 4 samples buffer: avgx, get_inputs_avg in_j7_bfr var long(2) ;in-7 last 4 samples buffer: avgx, get_inputs_avg in_j8_bfr var long(2) ;in-8 last 4 samples buffer: avgx, get_inputs_avg in_j9_bfr var long(2) ;in-9 last 4 samples buffer in_j10_bfr var long(2) ;in-10 last 4 samples buffer in_j11_bfr var long(2) ;in-11 last 4 samples buffer in_j12_bfr var long(2) ;in-12 last 4 samples buffer in_j13_bfr var long(2) ;in-13 last 4 samples buffer in_j14_bfr var long(2) ;in-14 last 4 samples buffer in_j15_bfr var long(2) ;in-15 last 4 samples buffer in_j16_bfr var long(2) ;in-16 last 4 samples buffer #endif hys con 2 ;hysteresis +/- value in_j1_low var word ;in-1 low value: get_inputs_hy in_j1_high var word ;in-1 high value: get_inputs_hy in_j2_low var word ;in-2 low value: get_inputs_hy in_j2_high var word ;in-2 high value: get_inputs_hy in_j3_low var word ;in-3 low value: get_inputs_hy in_j3_high var word ;in-3 high value: get_inputs_hy in_j4_low var word ;in-4 low value: get_inputs_hy in_j4_high var word ;in-4 high value: get_inputs_hy #ifdef cvs in_j5_low var word ;in-5 low value: get_inputs_hy in_j5_high var word ;in-5 high value: get_inputs_hy in_j6_low var word ;in-6 low value: get_inputs_hy in_j6_high var word ;in-6 high value: get_inputs_hy in_j7_low var word ;in-7 low value: get_inputs_hy in_j7_high var word ;in-7 high value: get_inputs_hy in_j8_low var word ;in-8 low value: get_inputs_hy in_j8_high var word ;in-8 high value: get_inputs_hy in_j9_low var word ;in-9 low value: get_inputs_hy in_j9_high var word ;in-9 high value: get_inputs_hy in_j10_low var word ;in-10 low value: get_inputs_hy in_j10_high var word ;in-10 high value: get_inputs_hy in_j11_low var word ;in-11 low value: get_inputs_hy in_j11_high var word ;in-11 high value: get_inputs_hy in_j12_low var word ;in-12 low value: get_inputs_hy in_j12_high var word ;in-12 high value: get_inputs_hy in_j13_low var word ;in-13 low value: get_inputs_hy in_j13_high var word ;in-13 high value: get_inputs_hy in_j14_low var word ;in-14 low value: get_inputs_hy in_j14_high var word ;in-14 high value: get_inputs_hy in_j15_low var word ;in-15 low value: get_inputs_hy in_j15_high var word ;in-15 high value: get_inputs_hy in_j16_low var word ;in-16 low value: get_inputs_hy in_j16_high var word ;in-16 high value: get_inputs_hy #endif ;display declarations num_data var word ;data for ascii conversion: hex2ascii tths var byte ;ten thousands digit: hex2ascii thos var byte ;thousands digit: 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 ;misc declarations tempb var byte ;temp byte tempb2 var byte ;temp byte tempw var word ;temp word spkj_data var byte ;variable: send_speakjet phrase1 var byte ;variable: hex_speakjet phrase2 var byte ;variable: hex_speakjet data_hex var byte ;variable: hex_speakjet fivevolts con 1920 ;5 volt output value #ifdef cvs ;external controls declarations ext_ctrl var byte ;external control flag (1=present, 0=not present):check_ext key_data var byte ;keypad data: key_keynum key_prev var byte ;previous keypad data: key_keynum key_temp var byte ;temp keypad: key_keynum key_entry var word ;0-999 keypad entry: get_keyentry #endif ;program declarations temp1 var word ;temporary local variable ; seq_mode var byte ;sequence mode: 0=up, 1=down, 2=up/down, 3=random ; step_dir var byte ;step direction: 0=up, 1=down clk_cnt var byte ;counter for clock divider rnd_num var long ;random number sel_flg var byte ;selection flag: select midi_flg var byte ;note sent flag: clk_h midi_offset var word ;midi offset in semitones gate1 var word ;gate1 ; gate2 var word ;gate2 mask var word ;mask for bit indexing ; ctrl_v var word(16) ;input control values bit_num var word ;mask bit count ; last_step var byte ;last sequencer step: in_val ; step_max var word ;maximum steps out_v var word ;output value note_oct var byte ;note octave note_num var byte ;note number within octave note_asc var byte ;note ascii value note_sh var byte ;note sharp or space last_patch var byte ;last program change patch patch var byte(8) ;step program change patchs max_value var word ;maximum value of input controls shift_reg var word ;shift register - input at bit 0 scale_fac var float ;scale factor for auto level out_cv var float ;output cv ; ;-----------------------------------------------------------------------------------------------; ; Tables ; ;-----------------------------------------------------------------------------------------------; ; phrase bytetable "0123456789ABCDEF" ;tts256 digit phrases for hex output step_tbl bytetable 256,128,86,64,52,43,37,32,29,26,24,22,20,19,18,17 ;byte to step max divisors note_tbl bytetable "C C",$02,"D D",$02,"E F F",$02,"G G",$02,"A A",$02,"B ";semitone number to note conversion gate_tbl bytetable "0123456789ABCDEF" ;gate hex value conversion patch_tbl bytetable | ;GM instrument patch names "AcouGrnd", | ; 1 "BrightAc", | ; 2 "ElecGrnd", | ; 3 "HonkyTnk", | ; 4 "ElPiano1", | ; 5 "ElPiano2", | ; 6 "Harpscrd", | ; 7 "Clavinet", | ; 8 "Celesta ", | ; 9 "Glcknspl", | ;10 "MusicBox", | ;11 "Vibraphn", | ;12 "Marimba ", | ;13 "Xylophon", | ;14 "TubBells", | ;15 "Dulcimer", | ;16 "Drawbar ", | ;17 "Perc Org", | ;18 "Rock Org", | ;19 "Church ", | ;20 "Reed Org", | ;21 "Acordian", | ;22 "Harmnica", | ;23 "TangoAcc", | ;24 "NylonGtr", | ;25 "SteelGtr", | ;26 "Jazz Gtr", | ;27 "CleanGtr", | ;28 "MutedGtr", | ;29 "OverDriv", | ;30 "Distortn", | ;31 "Harmonic", | ;32 "AcouBass", | ;33 "FingerAc", | ;34 "PickBass", | ;35 "Fretless", | ;36 "Slp1Bass", | ;37 "Slp2Bass", | ;38 "SynBass1", | ;39 "SynBass2", | ;40 "Violin ", | ;41 "Viola ", | ;42 "Cello ", | ;43 "Contra ", | ;44 "Trem Str", | ;45 "Pizicato", | ;46 "Orchestl", | ;47 "Timpani ", | ;48 "StrEnsm1", | ;49 "StrEnsm2", | ;50 "SynStr1 ", | ;51 "SynStr2 ", | ;52 "ChoirAhs", | ;53 "VoiceOhs", | ;54 "SynthVoc", | ;55 "OrchHits", | ;56 "Trumpet ", | ;57 "Trombone", | ;58 "Tuba ", | ;59 "MuteTrmp", | ;60 "FrnchHrn", | ;61 "BrassSec", | ;62 "SynBrss1", | ;63 "SynBrss2", | ;64 "SoprnSax", | ;65 "Alto Sax", | ;66 "TenorSax", | ;67 "Baritone", | ;68 "Oboe ", | ;69 "English ", | ;70 "Bassoon ", | ;71 "Clarinet", | ;72 "Piccolo ", | ;73 "Flute ", | ;74 "Recorder", | ;75 "PanFlute", | ;76 "BlownBtl", | ;77 "Shakuhac", | ;78 "Whistle ", | ;79 "Ocarina ", | ;80 "SquareWv", | ;81 "Sawtooth", | ;82 "Calliope", | ;83 "Chiff Ld", | ;84 "Charang ", | ;85 "Voice Ld", | ;86 "5thsLead", | ;87 "BassLead", | ;88 "New Age ", | ;89 "Warm Syn", | ;90 "Poly Syn", | ;91 "ChoirPad", | ;92 "BowedPad", | ;93 "Metallic", | ;94 "Halo Pad", | ;95 "SweepPad", | ;96 "Rain Fx ", | ;97 "Soundtrk", | ;98 "Crystal ", | ;99 "Atmosphr", | ;100 "Britness", | ;101 "Goblins ", | ;102 "EchoesFx", | ;103 "SciFi Fx", | ;104 "Sitar ", | ;105 "Banjo ", | ;106 "Shamisen", | ;107 "Koto ", | ;108 "Kalimba ", | ;109 "Bag Pipe", | ;110 "Fiddle ", | ;111 "Shanai ", | ;112 "TinklBel", | ;113 "Agogo ", | ;114 "SteelDrm", | ;115 "Woodblok", | ;116 "TaikoDrm", | ;117 "Melodic ", | ;118 "Syn Drum", | ;119 "RevCymbl", | ;120 "Gtr Fret", | ;121 "Breath ", | ;122 "Seashore", | ;123 "BrdTweet", | ;124 "Tel Ring", | ;125 "Helicptr", | ;126 "Applause", | ;127 "Gunshot " ;128 ; ;-----------------------------------------------------------------------------------------------; ; NV Memory ; ;-----------------------------------------------------------------------------------------------; ; address variable ; ------- -------- nv_step_max con 0 ;adr000 step_max nv_midi_offset con 1 ;adr001 midi_offset nv_gate1_lo con 2 ;adr002 gate1.byte0 nv_gate1_hi con 3 ;adr003 gate1.byte1 nv_gate2_lo con 4 ;adr004 gate2.byte0 nv_gate2_hi con 5 ;adr005 gate2.byte1 nv_patch con 6 ;adr006 step 1 patch ;nv_patch(1) con 7 ;adr007 step 2 patch ;nv_patch(2) con 8 ;adr008 step 3 patch ;nv_patch(3) con 9 ;adr009 step 4 patch ;nv_patch(4) con 10 ;adr010 step 5 patch ;nv_patch(5) con 11 ;adr011 step 6 patch ;nv_patch(6) con 12 ;adr012 step 7 patch ;nv_patch(7) con 13 ;adr013 step 8 patch ;nv_patch(8) con 14 ;adr014 step 9 patch ;nv_patch(9) con 15 ;adr015 step 10 patch ;nv_patch(10) con 16 ;adr016 step 11 patch ;nv_patch(11) con 17 ;adr017 step 12 patch ;nv_patch(12) con 18 ;adr018 step 13 patch ;nv_patch(13) con 19 ;adr019 step 14 patch ;nv_patch(14) con 20 ;adr020 step 15 patch ;nv_patch(15) con 21 ;adr021 step 16 patch nv_seq_mode con 22 ;adr022 seq_mode ; ;-----------------------------------------------------------------------------------------------; ; Program ; ;-----------------------------------------------------------------------------------------------; ; ;initialize pins #ifdef cvs dires=%0000000000000000 ;configure pin direction (1=output, 0=input) ;inputs: in-7, in-6, in-5, in-4 #endif dirs=%0001011000000000 ;configure pin direction (1=output, 0=input) ;note: setting midi-out, i2c_clock, i2c_data, and load_dacs to outputs can glitch so initialize as inputs ;inputs: midi-in, aux, start, stop, in-4, in-3, in-2, in-1 ;initialize as inputs: midi-out, clock, load_dacs, ic2_data, ic2_clk ;outputs: ser_data, stop led, run led high load_dacs ;set dac load high high clock ;set dac clock high so cs can not advance low run_led ;reset run led low stop_led ;reset stop led ;initialize control hardware #ifdef cvs let olat=$ff ;set olat i2cout i2c_data,i2c_clk,$0,[($20<<1),$0a,olat];set outputs high i2cout i2c_data,i2c_clk,$0,[($20<<1),$00,$00] ;set iodir to output #endif ;initialize outputs 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 #ifdef cvs let out_j5=0 ;set out-5 low let out_j6=0 ;set out-6 low let out_j7=0 ;set out-7 low let out_j8=0 ;set out-8 low #endif gosub load_outputs ;initialize input variables let in_j1_ptr=0 ;reset in-1 pointer #ifdef input_int_en let in_j2_ptr=0 ;reset in-2 pointer let in_j3_ptr=0 ;reset in-3 pointer let in_j4_ptr=0 ;reset in-4 pointer let isr_cnt=0 ;reset isr pass counter #endif let in_j1_bfr(0)=0 ;reset in-1 buffer data let in_j1_bfr(1)=0 let in_j2_bfr(0)=0 ;reset in-2 buffer data let in_j2_bfr(1)=0 let in_j3_bfr(0)=0 ;reset in-3 buffer data let in_j3_bfr(1)=0 let in_j4_bfr(0)=0 ;reset in-4 buffer data let in_j4_bfr(1)=0 #ifdef cvs let in_j5_bfr(0)=0 ;reset in-5 buffer data let in_j5_bfr(1)=0 let in_j6_bfr(0)=0 ;reset in-6 buffer data let in_j6_bfr(1)=0 let in_j7_bfr(0)=0 ;reset in-7 buffer data let in_j7_bfr(1)=0 let in_j8_bfr(0)=0 ;reset in-8 buffer data let in_j8_bfr(1)=0 #endif let in_j1_low=0 ;initialize in-1 hysteresis values let in_j1_high=2*hys let in_j2_low=0 ;initialize in-2 hysteresis values let in_j2_high=2*hys let in_j3_low=0 ;initialize in-3 hysteresis values let in_j3_high=2*hys let in_j4_low=0 ;initialize in-4 hysteresis values let in_j4_high=2*hys #ifdef cvs let in_j5_low=0 ;initialize in-5 hysteresis values let in_j5_high=2*hys let in_j6_low=0 ;initialize in-6 hysteresis values let in_j6_high=2*hys let in_j7_low=0 ;initialize in-7 hysteresis values let in_j7_high=2*hys let in_j8_low=0 ;initialize in-8 hysteresis values let in_j8_high=2*hys let in_j9_low=0 ;initialize in-9 hysteresis values let in_j9_high=2*hys let in_j10_low=0 ;initialize in-10 hysteresis values let in_j10_high=2*hys let in_j11_low=0 ;initialize in-11 hysteresis values let in_j11_high=2*hys let in_j12_low=0 ;initialize in-12 hysteresis values let in_j12_high=2*hys let in_j13_low=0 ;initialize in-13 hysteresis values let in_j13_high=2*hys let in_j14_low=0 ;initialize in-14 hysteresis values let in_j14_high=2*hys let in_j15_low=0 ;initialize in-15 hysteresis values let in_j15_high=2*hys let in_j16_low=0 ;initialize in-16 hysteresis values let in_j16_high=2*hys #endif ;initialize midi variables let midi_chan=0 ;set midi channel let midi_note=0 ;set midi note let midi_vel=64 ;set default velocity let midi_cmd=$0f ;set last midi command (invalid) let trans_note=0 ;set transpose note to none let trans_chan=0 ;set transpose channel to none ;initialize edge interrupts #ifdef edge_int_en let edge_state=0 ;reset current state let edge_flg=0 ;reset edge flag #endif ;enable aux_in rising edge interrupts #ifdef aux_int_en let aux_cnt=0 ;reset count let pmr1=pmr1|%00100000 ;set Port Mode Register to enable irq1 let iegr1=iegr1|%00000010 ;set irq1 to rising edge let irr1=irr1&%11111101 ;clear any pending interrupt oninterrupt irq1int,aux_isr enable irq1int ;enable rising edge interrupts #endif ;initialize timerW hardware for 1 mS #ifdef timer_int_en 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=2000 ;2 MHz / 2000 = 1 mS ;enable timerW interrupts let time_count=0 ;reset real time count let turn_off=0 ;reset turn off time oninterrupt timerwint_imiea, tm_isr enable timerwint_imiea ;enable timer interrupt #endif ;enable midi interrupts enablehserial sethserial h31200,h8databits,hnoparity,h1stopbits #ifdef cvs pause 50 ;let display initialize hserout [$f0,$7d,$10,$01,$7f,$09,$00,$0b,$11,$0e,$f7] ;character0 G1 (sideways) hserout [$f0,$7d,$11,$09,$15,$13,$00,$0b,$11,$0e,$f7] ;character1 G2 (sideways) ;character2 default sharp hserout [$f0,$7d,$13,$07,$04,$04,$04,$04,$04,$1c,$f7] ;character3 rising edge hserout [$f0,$7d,$14,$1f,$00,$00,$00,$00,$00,$00,$f7] ;character4 high level hserout [$f0,$7d,$15,$1c,$04,$04,$04,$04,$04,$07,$f7] ;character5 falling edge hserout [$f0,$7d,$16,$00,$00,$00,$00,$00,$00,$1f,$f7] ;character6 low level hserout [$f0,$7d,$17,$00,$00,$0a,$00,$11,$0e,$00,$f7] ;character7 smiley face hserout [$f0,$7d,$0a,$18,"Klee Sequencer-8ModularSynthesis",$f7] ;clear, overwrite, name #else pause 250 ;let display initialize hserout [$f0,$7d,$0a,$18,"DJB-PSIMprogram ",$f7] ;clear, overwrite, name #endif gosub send_all_off ;ensure no stuck notes ; ;-----------------------------------------------------------------------------------------------; ; Main Program ; ;-----------------------------------------------------------------------------------------------; ; pause 2000 ;display program name let rnd_num=1 ;start with non-zero number let midi_flg=0 ;indicate no notes on let last_patch=255 ;set last patch invalid let ext_ctrl=0 ;assume internal controls i2cin i2c_data,i2c_clk,no_controls,($4c<<1),$00,[ext_ctrl,ext_ctrl] ;check to see if external controls present let ext_ctrl=1 ;no error so set for external control input no_controls: ;get non-volatile parameters ;these will be valid after first program execution ; read nv_step_max,step_max ;get number of steps read nv_gate1_hi,gate1.byte1 ;get gate1 read nv_gate1_lo,gate1.byte0 ; read nv_gate2_hi,gate2.byte1 ;get gate2 ; read nv_gate2_lo,gate2.byte0 read nv_midi_offset,midi_offset ;get midi_offset ; for temp1=0 to 15 ;get patchs ; read nv_patch+temp1,patch(temp1) ; next ; read nv_seq_mode,seq_mode ;get seq_mode ; ;menu choice to sequence or setup start: gosub nmlv_0 ;set normal to 0 gosub refv_10 ;set offset to 10 ; let last_step=15 ;set to off8 high stop_led ;indicate setup mode hserout [$f0,$7d,$0a,"Start? Sequence Stop? Setup ",$f7] ;display choice gosub select ;get input if sel_flg=1 then sequence ; ;old sequencer code ;menu choice to set number of steps ; let num_data=step_max ; gosub hex2ascii ; hserout [$f0,$7d,$0a,"Start? Steps ",tens,ones," Stop? Modify ",$f7] ;display choice ; gosub select ;get input ; if sel_flg=1 then set_mode ; if ext_ctrl=1 then ; hserout [$f0,$7d,$0a,"ExtIO? Steps Start? Select ",$f7] ;display choice ; else ; hserout [$f0,$7d,$0a,"Off8? Steps Start? Select ",$f7] ;display choice ; endif ;set_step: ; pause 20 ; if ext_ctrl=1 then ; i2cin i2c_data,i2c_clk,($4c<<1),$00,[step_max,step_max] ;read previous/start conversion cycle then read ain0 ; let step_max=(step_max/16)+1 ;allow 1-16 ; else ; adin pin_j8,in_j16 ; let in_j16=in_j16+hys ;offset for compare at zero ; if in_j16>in_j16_low then ;check lower range ; if in_j16255 then set_step2 ;wait for release ;set_step3: ; write nv_step_max,step_max ;nv save step_max ;menu choice sequence direction mode ;set_mode: ; hserout [$f0,$7d,$0a,"Start? Dir "] ;display choice ; if seq_mode=0 then ;up ; hserout ["Up "] ; elseif seq_mode=1 ;down ; hserout ["Down "] ; elseif seq_mode=2 ;up/down ; hserout ["Up/Dn"] ; else ;random ; hserout ["Rndm "] ; endif ; hserout ["Stop? Modify ",$f7] ; gosub select ;get input ; if sel_flg=1 then set1_gate ;set_mode1: ; let seq_mode=seq_mode+1 ;increment to next mode ; if seq_mode=4 then ;check for wrap around ; let seq_mode=0 ; endif ; if seq_mode=0 then ;up ; hserout [$f0,$7d,$1a,$0b,"Up ",$f7] ; elseif seq_mode=1 ;down ; hserout [$f0,$7d,$1a,$0b,"Down ",$f7] ; elseif seq_mode=2 ;up/down ; hserout [$f0,$7d,$1a,$0b,"Up/Dn",$f7] ; else ;random ; hserout [$f0,$7d,$1a,$0b,"Rndm ",$f7] ; endif ; gosub select ;get input ; if sel_flg=0 then set_mode1 ; write nv_seq_mode,seq_mode ;nv save seq_mode ;menu choice to set gate1 set1_gate: let bit_num=15 ;start at the high bit hserout [$f0,$7d,$0a,"Start? Gt1 "] ;display choice hserout [gate_tbl(gate1.nib3),gate_tbl(gate1.nib2),gate_tbl(gate1.nib1),gate_tbl(gate1.nib0)] hserout [" Stop? Modify ",$f7] gosub select ;get input if sel_flg=1 then set2_gate set1_gate1: let mask=dcd bit_num ;calculate bit index let num_data=bit_num gosub hex2ascii hserout [$f0,$7d,$0a,"Start? Bit ",tens,ones," Stop? Rev Gt1 ",$f7] ;display choice set1_gate2: if (gate1&mask)<>0 then ;check gate1 level hserout [$f0,$7d,$1a,$1e,$03,$04,$f7] ;display level hi else hserout [$f0,$7d,$1a,$1e,$05,$06,$f7] ;display level lo endif gosub select ;get input if sel_flg=0 then ;toggle gate1 level let gate1=gate1^mask goto set1_gate2 ;display new level endif let bit_num=bit_num-1 ;increment step if bit_num<>-1 then set1_gate1 ;check if done write nv_gate1_hi,gate1.byte1 ;nv save gate1 write nv_gate1_lo,gate1.byte0 goto set1_gate ;do next step ; ;menu choice to set gate2 set2_gate: ; let step_num=0 ;start at the beginning ; hserout [$f0,$7d,$0a,"Start? Gt2 "] ;display choice ; hserout [gate_tbl(gate2.nib0),gate_tbl(gate2.nib1),gate_tbl(gate2.nib2),gate_tbl(gate2.nib3)] ; hserout [" Stop? Modify ",$f7] ; gosub select ;get input ; if sel_flg=1 then set_midi ;set2_gate1: ; let mask=dcd (step_num+1) ;calculate bit index ; let num_data=step_num+1 ; gosub hex2ascii ; hserout [$f0,$7d,$0a,"Start? Step ",tens,ones," Stop? Rev Gt2 ",$f7] ;display choice ;set2_gate2: ; if (gate2&mask)<>0 then ;check gate2 level ; hserout [$f0,$7d,$1a,$1e,$03,$04,$f7] ;display level hi ; else ; hserout [$f0,$7d,$1a,$1e,$05,$06,$f7] ;display level lo ; endif ; gosub select ;get input ; if sel_flg=0 then ;toggle gate2 level ; let gate2=gate2^mask ; goto set2_gate2 ;display new level ; endif ; let step_num=step_num+1 ;increment step ; if step_num<>step_max then set2_gate1 ;check if done ; write nv_gate2_hi,gate2.byte1 ;nv save gate2 ; write nv_gate2_lo,gate2.byte0 ; goto set2_gate ;do next step ; ;menu choice to set midi program change ;set_midi: ; let step_num=0 ;initialize step number ; hserout [$f0,$7d,$0a,"Start? NextMenu Stop? SetPatch ",$f7] ;display choice ; gosub select ;get input ; if sel_flg=1 then set_offset ;set_midi1: ; hserout [$f0,$7d,$0a,"Step",$0b,"Stop? Modify ",$f7] ;initialize display ; hserout [$f0,$7d,$1a,$05,dec step_num+1," ",$f7] ;display step number and space ; let midi_pgm=patch(step_num) ;get program change patch ; hserout [$f0,$7d,$1a,$08] ;set LCD position ; for temp1=0 to 7 ;get characters of patch name ; hserout [patch_tbl((midi_pgm*8)+temp1)] ;display patch name ; next ; hserout [$f7] ;complete lcd message ; gosub select ;get input ; if sel_flg=1 then set_midi5 ;check if done with this step ; if ext_ctrl=1 then ; hserout [$f0,$7d,$0a,"ExtIO?",$0b,"Start? Select ",$f7] ;display choice ; else ; hserout [$f0,$7d,$0a,"Off8?",$0b,"Start? Select ",$f7] ;display choice ; endif ;set_midi2: ; pause 20 ; if ext_ctrl=1 then ; i2cin i2c_data,i2c_clk,($4c<<1),$00,[midi_pgm,midi_pgm] ;read previous/start conversion cycle then read ain0 ; let midi_pgm=(midi_pgm/2) ;allow 0 - 127 ; else ; adin pin_j8,in_j16 ; let in_j16=in_j16+hys ;offset for compare at zero ; if in_j16>in_j16_low then ;check lower range ; if in_j16255 then set_midi4 ;wait for release ;set_midi5: ; write nv_patch+step_num,patch(step_num) ;nv save patch ; let step_num=step_num+1 ;go to next step ; if step_num=step_max then set_midi ;check for end ; goto set_midi1 ;continue with next step ; ;menu choice for midi offset set_offset: let num_data=midi_offset gosub hex2ascii hserout [$f0,$7d,$0a,"Start? Midi+N ",tens,ones,"Stop? Modify ",$f7] ;display choice gosub select ;get input if sel_flg=1 then adj_step if ext_ctrl=1 then hserout [$f0,$7d,$0a,"ExtIO? Midi+N Start? Select ",$f7] ;display choice else hserout [$f0,$7d,$0a,"Off8? Midi+N Start? Select ",$f7] ;display choice endif set_offset1: pause 20 if ext_ctrl=1 then i2cin i2c_data,i2c_clk,($4c<<1),$00,[midi_offset,midi_offset] ;read previous/start conversion cycle then read ain0 let midi_offset=((midi_offset*10)/53) ;allow 0 - 48 else adin pin_j8,in_j16 let in_j16=in_j16+hys ;offset for compare at zero if in_j16>in_j16_low then ;check lower range if in_j16255 then set_offset3 ;wait for release set_offset4: write nv_midi_offset,midi_offset ;nv save midi_offset ;menu choice to set levels adj_step: goto start ; let step_num=0 ;initialize step number ; hserout [$f0,$7d,$0a,"Start? NextMenu Stop? SetLevels",$f7] ;display choice ; gosub select ;get input ; if sel_flg=1 then start ; hserout [$f0,$7d,$0a,"Step",$0b,"Note Start?",$f7] ;initialize display ;adj_step1: ; hserout [$f0,$7d,$1a,$05,dec step_num+1," ",$f7] ;display step number and space ; let midi_pgm=patch(step_num) ;get program change patch ; hserout [$f0,$7d,$1a,$08] ;set LCD position ; for temp1=0 to 7 ;get characters of patch name ; hserout [patch_tbl((midi_pgm*8)+temp1)] ;display patch name ; next ; hserout [$f7] ;complete lcd message ; gosub in_val ;get input ; gosub out_val ;output and display value ; if start_j=0 then adj_step3 ;check forward select ;adj_step2: ; pause 20 ;debounce switch ; if start_j=1 then adj_step2 ;wait for release ; let let step_num=step_num+1 ;increment step number ; if step_num<>step_max then adj_step1 ;check for end ; goto adj_step ;decide if sequence or adjust ; ;adj_step3: ; if stop_j=0 then adj_step1 ;check backward select ;adj_step4: ; pause 20 ;debounce switch ; if stop_j=1 then adj_step4 ;wait for release ; let let step_num=step_num-1 ;decrement step number ; if step_num=255 then ;check for beginning ; let step_num=step_max-1 ;reset to end of sequence ; endif ; goto adj_step1 ;continue ; ;sequence sequence: hserout [$f0,$7d,$0a,"Rg=3 Of=1 Nt=",$f7] let shift_reg=$3578 ;use some initial seed for registers let clk_cnt=0 ;initialize clock divider low stop_led ;indicate sequence mode let last_patch=255 ;set last patch invalid to send program change on first note ; hserout [$f0,$7d,$0a] ;initialize sequence display ; if seq_mode=0 then ;up ; hserout ["Up"] ; let step_num=step_max-1 ;setup for step 1 ; elseif seq_mode=1 ;down ; hserout ["Down"] ; let step_num=0 ;setup for top step ; elseif seq_mode=2 ;up/down ; hserout ["UpDn"] ; let step_num=255 ;setup for step 1 ; let step_dir=1 ; else ;random ; hserout ["Rndm"] ; let step_num=step_max-1 ;setup for step 1 ; endif ; hserout [$0b,"Note ",$00," ",$01," ",$f7] ;and finish display initialization goto clk_l ;wait for clock low to prevent short first cycle ; clk_h: pause 20 ;debounce switch if stop_j=1 then restart ;check stop if aux_in=0 then clk_h ;check for clock high transition gosub in_val ;get input values let scale_fac=tofloat(in_j16+in_j15+in_j14+in_j13+in_j12+in_j11+in_j10+in_j9+in_j8+in_j7+in_j6+in_j5+in_j4+in_j3+in_j2+in_j1) let scale_fac=scale_fac/3840.0 ;scale to max value of 10.0 volts ;this implements a single 16 bit shift register ;use this or the next code segment ; let shift_reg=(shift_reg+shift_reg) ;shift bits ; let rnd_num=random(rnd_num) ; let shift_reg=shift_reg+rnd_num.bit0 ;add in random lower bit ; let out_j7=fivevolts ;set trigger high ; let out_j8=fivevolts ;set trigger high ; goto out_bits ;this implements a double 8 bit shift register with low shift register clock/2 ;use this or the previous code segment let rnd_num=random(rnd_num) if clk_cnt<>0 then let shift_reg.lowbyte=(shift_reg.lowbyte+shift_reg.lowbyte) ;shift bits for low byte let shift_reg.bit0=rnd_num.bit0 ;add in random lower bit let clk_cnt=0 let out_j8=fivevolts ;set trigger high else let clk_cnt=1 endif let shift_reg.highbyte=(shift_reg.highbyte+shift_reg.highbyte) ;shift bits for high byte let shift_reg.bit8=rnd_num.bit0 ;add in random lower bit let out_j7=fivevolts ;set trigger high ;end of double 8 bit shift register ;this code creates the cv outputs ;out1 is all 16 bits ;out2 is high byte ;out3 is low byte out_bits: let out_cv=tofloat((shift_reg.bit15*in_j1)+(shift_reg.bit14*in_j2)+(shift_reg.bit13*in_j3)+(shift_reg.bit12*in_j4)+| (shift_reg.bit11*in_j5)+(shift_reg.bit10*in_j6)+(shift_reg.bit9*in_j7)+(shift_reg.bit8*in_j8)+| (shift_reg.bit7*in_j9)+(shift_reg.bit6*in_j10)+(shift_reg.bit5*in_j11)+(shift_reg.bit4*in_j12)+| (shift_reg.bit3*in_j13)+(shift_reg.bit2*in_j14)+(shift_reg.bit1*in_j15)+(shift_reg.bit1*in_j16)) let out_cv=((out_cv/scale_fac)/3.33)+384.0 let out_j1=(toint(out_cv))&$ffe0 ;convert and quantize let out_cv=tofloat((shift_reg.bit15*in_j1)+(shift_reg.bit14*in_j2)+(shift_reg.bit13*in_j3)+(shift_reg.bit12*in_j4)+| (shift_reg.bit11*in_j5)+(shift_reg.bit10*in_j6)+(shift_reg.bit9*in_j7)+(shift_reg.bit8*in_j8)) let out_cv=((out_cv/scale_fac)/2.5)+384.0 let out_j2=(toint(out_cv))&$ffe0 ;convert and quantize let out_cv=tofloat((shift_reg.bit7*in_j9)+(shift_reg.bit6*in_j10)+(shift_reg.bit5*in_j11)+(shift_reg.bit4*in_j12)+| (shift_reg.bit3*in_j13)+(shift_reg.bit2*in_j14)+(shift_reg.bit1*in_j15)+(shift_reg.bit1*in_j16)) let out_cv=((out_cv/scale_fac)/3.33)+768.0 let out_j3=(toint(out_cv))&$ffe0 ;convert and quantize ;generate gates ;out4 is all 16 bits ;out5 is high byte ;out6 is low byte let temp1=shift_reg&gate1 ;and gate bits if temp1=0 then ;compare bits let out_j4=0 ;no match else let out_j4=fivevolts ;match endif if temp1.highbyte=0 then ;compare bits let out_j5=0 ;no match else let out_j5=fivevolts ;match endif if temp1.lowbyte=0 then ;compare bits let out_j6=0 ;no match else let out_j6=fivevolts ;match endif gosub load_outputs ;display the note and shift register bits let out_j1=out_j1>>5 ;reduce output to semitone number let note_oct=out_j1/12 ;calulate octave let note_num=(out_j1-(note_oct*12))*2 ;calculate note number within octave (X2 for lookup) let note_asc=note_tbl(note_num) ;calculate note ascii value let note_sh=note_tbl(note_num+1) ;get # or space let note_oct=note_oct+$30 ;convert octave to ascii hserout [$f0,$7d,$1a,$0d,note_asc,note_oct,note_sh,| $30+shift_reg.bit15,$30+shift_reg.bit14,$30+shift_reg.bit13,$30+shift_reg.bit12,| $30+shift_reg.bit11,$30+shift_reg.bit10,$30+shift_reg.bit9,$30+shift_reg.bit8,| $30+shift_reg.bit7,$30+shift_reg.bit6,$30+shift_reg.bit5,$30+shift_reg.bit4,| $30+shift_reg.bit3,$30+shift_reg.bit2,$30+shift_reg.bit1,$30+shift_reg.bit0,$f7] ;display note and shift registers ; ; let num_data=step_num+1 ; gosub hex2ascii ; hserout [$f0,$7d,$1a,$05,tens,ones,$f7] ;display step number ; let midi_pgm=patch(step_num) ;get patch ; hserout [$f0,$7d,$1a,$08] ;set LCD position ; for temp1=0 to 7 ;get characters of patch name ; hserout [patch_tbl((midi_pgm*8)+temp1)] ;display patch name ; next ; hserout [$f7] ;complete lcd message ; let out_j2=fivevolts ;set trigger ; if (gate1&mask)<>0 then ;check gate1 levels ; let out_j3=fivevolts ;set gate1 high ; hserout [$f0,$7d,$1a,$1a,$03,$04,$f7] ;display step level hi ; else ; let out_j3=0 ;set gate1 low ; hserout [$f0,$7d,$1a,$1a,$05,$06,$f7] ;display step level lo ; endif ; if (gate2&mask)<>0 then ;check gate2 levels ; let out_j4=fivevolts ;set gate2 high ; hserout [$f0,$7d,$1a,$1e,$03,$04,$f7] ;display step level hi ; else ; let out_j4=0 ;set gate2 low ; hserout [$f0,$7d,$1a,$1e,$05,$06,$f7] ;display step level lo ; endif ; gosub in_val ;get input ; gosub out_val ;set output value and display value ; if step_max>1 then ;check if more than 1 step ; let out_j5=((step_num)*fivevolts)/(step_max-1) ;step cv out 0 to 5 volts ; let out_j6=fivevolts-out_j5 ;inverse step cv out 5 to 0 volts ; else ; let out_j5=0 ;step cv out 0 volts ; let out_j6=fivevolts ;inverse step cv out 5 volts ; endif ; if step_num=0 then ;set first gate ; let out_j7=fivevolts ; else ; let out_j7=0 ; endif ; if step_num=step_max-1 then ;set last gate ; let out_j8=fivevolts ; else ; let out_j8=0 ; endif ; gosub load_outputs ; if midi_pgm<>last_patch then ;check if different ; let last_patch=midi_pgm ;yes so save new patch ; gosub send_prog_change ;send program change ; endif if midi_flg=1 then ;check if sent note on gosub send_note_off ;yes so send note off endif let midi_pgm=shift_reg.highbyte&$3f ;keep to bottom 64 programs gosub send_prog_change let midi_note=out_j1+midi_offset ;offset gosub send_note_on let midi_flg=1 ;set flag to indicate note on pause 5 ;trigger width let out_j7=0 ;reset triggers let out_j8=0 ;dac2 is already selected shiftout ser_data,clock,4,[(out_j7|$4000)\16] pulsout load_dacs,1 ;clock loaddacs shiftout ser_data,clock,4,[out_j8\16] pulsout load_dacs,1 ;clock loaddacs clk_l: pause 20 ;debounce switch if stop_j=1 then restart ;check stop if aux_in=1 then clk_l ;wait for clock low transition goto clk_h ; ;old sequencer code ; if seq_mode=0 then ;up ; let step_num=step_num+1 ; if step_num=step_max then ;check for end of sequence ; step_num=0 ; endif ; elseif seq_mode=1 ;down ; let step_num=step_num-1 ; if step_num=255 then ;check for end of sequence ; step_num=step_max-1 ; endif ; elseif seq_mode=2 ;up/down ; if step_dir=1 then ;check for up ; let step_num=step_num+1 ; if step_num=step_max then ;check for end of up sequence ; let step_dir=0 ;reverse direction ; if step_max=1 then ;check for minimum sequence ; let step_num=step_num-1 ;repeat last step ; else ; let step_num=step_num-2 ;do not repeat last step ; endif ; endif ; else ; let step_num=step_num-1 ; if step_num=255 then ;check for end of down sequence ; let step_dir=1 ;reverse direction ; if step_max=1 then ;check for minimum sequence ; let step_num=step_num+1 ;repeat last step ; else ; let step_num=step_num+2 ;do not repeat last step ; endif ; endif ; endif ; else ;random ; let rnd_num=random(rnd_num) ; let step_num=(rnd_num.byte0^rnd_num.byte1^rnd_num.byte2^rnd_num.byte3) ; let step_num=step_num/(step_tbl(step_max-1)) ;keep to proper number of bits ; endif ; let mask=dcd (step_num+1) ;calculate bit index ; goto clk_h ; restart: pause 20 if stop_j=1 then restart let out_j1=0 ;reset all outputs let out_j2=0 let out_j3=0 let out_j4=0 let out_j5=0 let out_j6=0 let out_j7=0 let out_j8=0 gosub load_outputs if midi_flg=1 then ;check if sent note on gosub send_note_off ;yes so send note off let midi_flg=0 ;indicate no notes on endif goto start ; ;get external input values with hysteresis ;written by David J. Brown in_val: gosub nmlv_10 ;set normal to 10 gosub refv_0 ;set offset to 0 pause 10 ;let inputs settle adin pin_j1,in_j1 let in_j1=in_j1+hys ;offset for compare at zero if in_j1>in_j1_low then ;check lower range if in_j1in_j2_low then ;check lower range if in_j2in_j3_low then ;check lower range if in_j3in_j4_low then ;check lower range if in_j4in_j5_low then ;check lower range if in_j5in_j6_low then ;check lower range if in_j6in_j7_low then ;check lower range if in_j7in_j8_low then ;check lower range if in_j8in_j9_low then ;check lower range if in_j9in_j10_low then ;check lower range if in_j10in_j11_low then ;check lower range if in_j11in_j12_low then ;check lower range if in_j12in_j13_low then ;check lower range if in_j13in_j14_low then ;check lower range if in_j14in_j15_low then ;check lower range if in_j15in_j16_low then ;check lower range if in_j16>5 ;reduce output to semitone number ; let note_oct=out_v/12 ;calulate octave ; let note_num=(out_v-(note_oct*12))*2 ;calculate note number within octave (X2 for lookup) ; let note_asc=note_tbl(note_num) ;calculate note ascii value ; let note_sh=note_tbl(note_num+1) ;get # or space ; let note_oct=note_oct+$30 ;convert octave to ascii ; hserout [$f0,$7d,$1a,$15,note_asc,note_oct,note_sh,$f7] ;display note ; return ; ;wait for selection ;sel_data_flg=1 if start or *, 0 if stop or # select: let rnd_num=rnd_num+1 ;vary random seed pause 20 ;debounce switch if ext_ctrl=1 then ;check if external controls gosub get_keynum if key_data=10 then ;check for * let sel_flg=1 ;indicate start goto sel4 ;wait for release endif if key_data=11 then ;check for # let sel_flg=0 ;indicate stop goto sel4 ;wait for release endif endif if start_j=1 then sel3 ;check start if stop_j=0 then select ;check stop sel2: pause 20 ;debounce switch if stop_j=1 then sel2 ;wait for stop release let sel_flg=0 ;indicate stop return sel3: pause 20 ;debounce switch if start_j=1 then sel3 ;wait for start release let sel_flg=1 ;indicate start return sel4: pause 20 gosub get_keynum if key_data<>255 then sel4 ;wait for release return ; ;-----------------------------------------------------------------------------------------------; ; MIDI Protocol Subroutine ; ;-----------------------------------------------------------------------------------------------; ; ;process midi commands ;passes all midi in to midi out ;note: transposes note to midi note+trans_note ; transposes channel to midi channel+trans_chan ;written by David J. Brown proc_midi: hserin 0,proc_none,[midi_data] if midi_data=$fe then proc_midi ;ignore active status high stop_led #ifdef timer_int_en disable timerwint_imiea let turn_off=time_count+20 ;set led time enable timerwint_imiea #endif if midi_data>$f7 then real_time ;check for real time if midi_data.bit7=0 then running ;check to see if running status let last_cmd=midi_data ;save command to expand running let midi_cmd=(midi_data>>4)&$07 ;strip midi channel for branch branch midi_cmd,[mkey_up,mkey_dn,key_prs,ctrl_chg,prgm_chg,chan_prs,ptch_bnd,sys_com] ; proc_none: return ; ;running status running: let tempb=midi_data ;save second byte let midi_data=(last_cmd&$f0)|((last_cmd+trans_chan)&$0f) ;expand to non-running and transpose midi channel hserout [midi_data] let midi_data=tempb ;restore second byte branch midi_cmd,[mkey_upr,mkey_dnr,key_prsr,ctrl_chgr,prgm_chgr,chan_prsr,ptch_bndr,proc_none] ; ;note off command mkey_up: let midi_data=keyup|((midi_data+trans_chan)&$0f) ;transpose midi channel hserout [midi_data] gosub get_next_byte ;get data from received buffer mkey_upr: let midi_data=midi_data+trans_note ;transpose midi note hserout [midi_data] gosub get_next_byte ;get data from received buffer hserout [midi_data] return ; ;note on command mkey_dn: let midi_data=keydn|((midi_data+trans_chan)&$0f) ;transpose midi channel hserout [midi_data] gosub get_next_byte ;get data from received buffer mkey_dnr: let midi_data=midi_data+trans_note ;transpose midi note hserout [midi_data] gosub get_next_byte ;get data from received buffer hserout [midi_data] return ; ;key pressure command key_prs: let midi_data=chnprs|((midi_data+trans_chan)&$0f) ;transpose 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] return ; ;control change command ctrl_chg: let midi_data=conctrl|((midi_data+trans_chan)&$0f) ;transpose 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] return ; ;program change command prgm_chg: let midi_data=pgmchg|((midi_data+trans_chan)&$0f) ;transpose midi channel hserout [midi_data] gosub get_next_byte ;get data from received buffer prgm_chgr: hserout [midi_data] return ; ;channel pressure command chan_prs: let midi_data=chnprs|((midi_data+trans_chan)&$0f) ;transpose midi channel hserout [midi_data] gosub get_next_byte ;get data from received buffer chan_prsr: hserout [midi_data] return ; ;pitch bend command ptch_bnd: let midi_data=pitchb|((midi_data+trans_chan)&$0f) ;transpose 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] return ; ;system common command sys_com: let sys_cmd=midi_data&$07 ;get system common command branch sys_cmd,[sys_ex,proc_none,song_ptr,song_sel,proc_none,proc_none,tune_req,proc_none] ; ;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 return ; ;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] return ; ;song select command song_sel: hserout [midi_data] gosub get_next_byte ;get data from received buffer hserout [midi_data] return ; ;tune_request command tune_req: hserout [midi_data] return ; ;real time commands real_time: let sys_cmd=midi_data&$07 ;strip high bits for branch branch sys_cmd,[time_clk,proc_none,start_cmd,cont_cmd,stop_cmd,proc_none,proc_none,reset_cmd] return ; ;timing clock command time_clk: hserout [midi_data] return ; ;start command start_cmd: hserout [midi_data] return ; ;start command cont_cmd: hserout [midi_data] return ; ;start command stop_cmd: hserout [midi_data] return ; ;start command reset_cmd: hserout [midi_data] return ; ;wait for data and check for real time data get_next_byte: hserin 0,get_next_byte,[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 ; ;-----------------------------------------------------------------------------------------------; ; Subroutines ; ;-----------------------------------------------------------------------------------------------; ; ;send midi note-on command ;midi_chan is channel 0 - 15 ;midi_note is note ;midi_vel is velocity send_note_on: hserout [keydn|midi_chan,midi_note,midi_vel] return ; ;send midi note-off command ;midi_chan is channel 0 - 15 ;midi_note is note send_note_off: hserout [keyup|midi_chan,midi_note,0] return ; ;send midi all notes off command on all channels send_all_off: let tempb=midi_chan for midi_chan=0 to 15 ;send on all channels hserout [conctrl|midi_chan,allup,0] ;send all notes off next let midi_chan=tempb return ; ;send midi program change command ;midi_chan is channel 0 - 15 ;midi_pgm is program change send_prog_change: hserout [pgmchg|midi_chan,midi_pgm] return ; ;send midi continuous controller command ;midi_cc is controller number ;midi_data is controller data send_cc: hserout [conctrl|midi_chan,midi_cc,midi_data] return ; ;get midi_data from buffer ;rcx_data_flg=1 if successful, rcx_data_flg=0 if no data in buffer get_rcx_bfr: let rcx_data_flg=0 ;set empty flag get_rcx_bfr1: hserin 0,get_rcx_bfr2,[midi_data] if midi_data=$fe then get_rcx_bfr1 ;ignore active status let rcx_data_flg=1 ;set data returned flag get_rcx_bfr2: return ; ;send midi_data send_midi: hserout [midi_data] ;put data in transmit buffer return ; ;send spkj_data via i2c ;retransmit on error for flow control send_speakjet: i2cout i2c_data,i2c_clk,send_speakjet,$0,[($48<<1),spkj_data] ;send to TTS256 return ; ;convert num_data to ascii digits ;updates tths, thos, huns, tens, ones variables ;use to generate leading zeros for fixed column display ;written by David J. Brown hex2ascii: let tempw=num_data ;save data let tths=num_data/10000 ;get ten thousands let num_data=num_data//10000 ;get thousands remainder let tths=tths+$30 ;convert to ascii let thos=num_data/1000 ;get thousands let num_data=num_data//1000 ;get hundreds remainder let thos=thos+$30 ;convert to ascii let huns=num_data/100 ;get hundreds let num_data=num_data//100 ;get tens remainder let huns=huns+$30 ;convert to ascii let tens=num_data/10 ;get tens let num_data=num_data//10 ;get ones remainder let tens=tens+$30 ;convert to ascii let ones=num_data+$30 ;convert to ascii let num_data=tempw ;restore data return ; ;update display with four input voltages in_jx ;note: 10 displays as "A" (e.g. A.0 volts) ;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 if ones=10 then let ones=$11 ;convert 10 to A endif let tens=((in_j1-((ones*1023)/10))*100)/1023 hserout [$f0,$7d,$0d,$00,ones+$30,".",dec tens] ;home1 and display in_j1 voltage let ones=(in_j2*10)/1023 ;convert to integer digits if ones=10 then let ones=$11 ;convert 10 to A endif let tens=((in_j2-((ones*1023)/10))*100)/1023 hserout [$01,ones+$30,".",dec tens] ;display in_j2 voltage let ones=(in_j3*10)/1023 ;convert to integer digits if ones=10 then let ones=$11 ;convert 10 to A endif let tens=((in_j3-((ones*1023)/10))*100)/1023 hserout [$02,ones+$30,".",dec tens] ;display in_j3 voltage let ones=(in_j4*10)/1023 ;convert to integer digits if ones=10 then let ones=$11 ;convert 10 to A endif let tens=((in_j4-((ones*1023)/10))*100)/1023 hserout [$03,ones+$30,".",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 for PSIM ;300 uS execution time for CVS get_inputs: adin pin_j1,in_j1 adin pin_j2,in_j2 adin pin_j3,in_j3 adin pin_j4,in_j4 #endif #ifdef cvs adin pin_j5,in_j5 adin pin_j6,in_j6 adin pin_j7,in_j7 adin pin_j8,in_j8 #endif return ; ;sample and average in-1 to in-x ;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 for PSIM ;1.2 mS execution time for CVS ;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 #ifdef cvs adin pin_j5,in_j5_bfr.word1(in_j1_ptr) ;get in-5 into buffer let in_j5_tmp=in_j5_bfr(0)+in_j5_bfr(1) ;add two high words together and low words together let in_j5=(in_j5_tmp.word1+in_j5_tmp.word0)/4 adin pin_j6,in_j6_bfr.word1(in_j1_ptr) ;get in-6 into buffer let in_j6_tmp=in_j6_bfr(0)+in_j6_bfr(1) ;add two high words together and low words together let in_j6=(in_j6_tmp.word1+in_j6_tmp.word0)/4 adin pin_j7,in_j7_bfr.word1(in_j1_ptr) ;get in-7 into buffer let in_j7_tmp=in_j7_bfr(0)+in_j7_bfr(1) ;add two high words together and low words together let in_j7=(in_j7_tmp.word1+in_j7_tmp.word0)/4 adin pin_j8,in_j8_bfr.word1(in_j1_ptr) ;get in-8 into buffer let in_j8_tmp=in_j8_bfr(0)+in_j8_bfr(1) ;add two high words together and low words together let in_j8=(in_j8_tmp.word1+in_j8_tmp.word0)/4 #endif let in_j1_ptr=(in_j1_ptr+1)&$03 ;increment pointer and wrap at 3 return ; ;send data_hex to speakjet ;pause 100 mS before first nibble and 60 mS before second nibble ;written by David J. Brown hex_speakjet let phrase1=data_hex>>4 ;get high nibble let phrase1=phrase(phrase1) ;get first byte let phrase2=data_hex&$0f ;get bottom nibble let phrase2=phrase(phrase2) ;get first byte hex_error: i2cout i2c_data,i2c_clk,hex_error,$0,[($48<<1),$01,phrase1,$05,phrase2,$0d] ;send to TTS256 return ; ;output out_jx values to dacs ;750 uS execution time for PSIM ;2.6 mS execution time for CVS load_outputs: #ifdef cvs let olat.bit6=1 ;select dac1 let olat.bit7=0 ;deselect dac2 i2cout i2c_data,i2c_clk,$0,[($20<<1),$0a,olat] ;set olat #endif ;add dac address to out_jx values and shift 16 bits using mode 4 shiftout ser_data,clock,4,[(out_j1|$c000)\16] pulsout load_dacs,1 ;clock loaddacs shiftout ser_data,clock,4,[(out_j2|$8000)\16] pulsout load_dacs,1 ;clock loaddacs shiftout ser_data,clock,4,[(out_j3|$4000)\16] pulsout load_dacs,1 ;clock loaddacs shiftout ser_data,clock,4,[out_j4\16] pulsout load_dacs,1 ;clock loaddacs #ifdef cvs let olat.bit6=0 ;deselect dac1 let olat.bit7=1 ;select dac2 i2cout i2c_data,i2c_clk,$0,[($20<<1),$0a,olat] ;set olat shiftout ser_data,clock,4,[(out_j5|$c000)\16] pulsout load_dacs,1 ;clock loaddacs shiftout ser_data,clock,4,[(out_j6|$8000)\16] pulsout load_dacs,1 ;clock loaddacs shiftout ser_data,clock,4,[(out_j7|$4000)\16] pulsout load_dacs,1 ;clock loaddacs shiftout ser_data,clock,4,[out_j8\16] pulsout load_dacs,1 ;clock loaddacs #endif return ; #ifdef cvs ;set input normal voltage to 10 volts nmlv_10: let olat.bit0=1 ;set for input normal voltage to +10 i2cout i2c_data,i2c_clk,$0,[($20<<1),$0a,olat] ;set olat return ; ;set input normal voltage to 0 nmlv_0: let olat.bit0=0 ;reset for input normal voltage to 0 i2cout i2c_data,i2c_clk,$0,[($20<<1),$0a,olat] ;set olat return ; ;set input reference voltage to 10 volts refv_10: let olat.bit1=1 ;set to enable input reference voltage let olat.bit2=0 ;reset for input reference voltage to +10 i2cout i2c_data,i2c_clk,$0,[($20<<1),$0a,olat] ;set olat return ; ;set input reference voltage to 5 volts refv_5: let olat.bit1=1 ;set to enable input reference voltage let olat.bit2=1 ;set for input reference voltage to +5 i2cout i2c_data,i2c_clk,$0,[($20<<1),$0a,olat] ;set olat return ; ;set input reference voltage to 0 refv_0: let olat.bit1=0 ;reset for input reference voltage to 0 i2cout i2c_data,i2c_clk,$0,[($20<<1),$0a,olat] ;set olat return #endif ; ;scans keypad and returns key_data ;key_data=0 to 9, 10=*, 11=#, and 255=no keys pressed ;written by David J. Brown get_keynum: i2cin i2c_data,i2c_clk,($4c<<1),$02,[key_temp,key_temp] ;read previous/start conversion cycle then read ain2 if key_temp>242 then let key_data=255 ;no keys down elseif key_temp>221 let key_data=10 ;* key elseif key_temp>201 let key_data=7 ;7 key elseif key_temp>180 let key_data=4 ;4 key elseif key_temp>158 let key_data=1 ;1 key elseif key_temp>137 let key_data=0 ;0 key elseif key_temp>116 let key_data=8 ;8 key elseif key_temp>95 let key_data=5 ;5 key elseif key_temp>74 let key_data=2 ;2 key elseif key_temp>54 let key_data=11 ;# key elseif key_temp>33 let key_data=9 ;9 key elseif key_temp>10 let key_data=6 ;6 key else let key_data=3 ;3 key endif if key_data=key_prev then ;check if state change return ;two scans same so have key value endif let key_prev=key_data ;save state pause 20 ;let keys settle goto get_keynum ;scan again ; ;-----------------------------------------------------------------------------------------------; ; Interrupt Service Routines ; ;-----------------------------------------------------------------------------------------------; ; #ifdef aux_int_en ;interrupt service routine for aux input rising edge aux_isr: let aux_cnt=aux_cnt+1 ;count number of aux interrupts resume ;ignore overflow #endif ; #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 #ifdef edge_int_en ;check for trigger rising edge ;pulse width must be > 1 ms timer let edge_state=edge_state<<1 ;shift previous state left let edge_state.bit0=edge_in ;set low bit to current input state if edge_state=$01 then ;edge detect requires 7 previous lows and current high let edge_flg=1 ;set edge flag endif #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 #endif #ifdef cvs ;change the following table to modify the scan rate for each CVS input ;175 uS execution time so maximum of one sample and average per interrupt ;currently set for: in-1 to 8 @ 8 mS branch isr_cnt, [avg1,avg2,avg3,avg4,avg5,avg6,avg7,avg8,avg1,avg2,avg3,avg4,avg5,avg6,avg7,avg8] #else ;change the following table to modify the scan rate for each PSIM 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] #endif ;sample in-1 avg1: #ifdef input_int_en 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 #endif ;sample in-2 avg2: #ifdef input_int_en 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 #endif ;sample in-3 avg3: #ifdef input_int_en 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 #endif ;sample in-4 avg4: #ifdef input_int_en 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 ;sample in-5 avg5: #ifdef input_int_en adin pin_j5,in_j5_bfr.word1(in_j5_ptr) ;get in-5 into buffer let in_j5_tmp=in_j5_bfr(0)+in_j5_bfr(1) ;add two high words together and low words together let in_j5=(in_j5_tmp.word1+in_j5_tmp.word0)/4 let in_j5_ptr=(in_j5_ptr+1)&$03 ;increment pointer and wrap at 3 resume #endif ;sample in-6 avg6: #ifdef input_int_en adin pin_j6,in_j2_bfr.word1(in_j6_ptr) ;get in-6 into buffer let in_j6_tmp=in_j6_bfr(0)+in_j6_bfr(1) ;add two high words together and low words together let in_j6=(in_j2_tmp.word1+in_j6_tmp.word0)/4 let in_j6_ptr=(in_j6_ptr+1)&$03 ;increment pointer and wrap at 3 resume #endif ;sample in-7 avg7: #ifdef input_int_en adin pin_j7,in_j7_bfr.word1(in_j7_ptr) ;get in-7 into buffer let in_j7_tmp=in_j7_bfr(0)+in_j7_bfr(1) ;add two high words together and low words together let in_j7=(in_j7_tmp.word1+in_j7_tmp.word0)/4 let in_j7_ptr=(in_j7_ptr+1)&$03 ;increment pointer and wrap at 3 resume #endif ;sample in-8 avg8: #ifdef input_int_en adin pin_j8,in_j8_bfr.word1(in_j8_ptr) ;get in-8 into buffer let in_j8_tmp=in_j8_bfr(0)+in_j8_bfr(1) ;add two high words together and low words together let in_j8=(in_j8_tmp.word1+in_j8_tmp.word0)/4 let in_j8_ptr=(in_j8_ptr+1)&$03 ;increment pointer and wrap at 3 resume #endif ; ;-----------------------------------------------------------------------------------------------; ; End Of Program ; ;-----------------------------------------------------------------------------------------------;