;-----------------------------------------------------------------------------------------------; ; Program: RS232 Speakjet ; ; Developed by David J. Brown ; ; Copyright (c) April 25, 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: (used with PhraseAlator program) ; ; Passes 2400 baud RS-232 data to SpeakJet ; note: 250 byte buffer eliminates need for flow control ; RS-232 data received on MIDI-In connector through adapter ; Adapter wiring: (converts +12 volts to 5 mA) ; DB-9 pin 3 to 1.5K resistor to diode to MIDI-In pin 4 ; note: cathode end connects to MIDI-In pin 4 ; DB-9 pin 5 to MIDI-In pin 5 (ground) ; DB-9 pin 7 to DB9 pin 8 (flow control loopback) ; DB-9 pin 1 to DB-9 pin 4 and pin 6 (status loopback) ; ; Stop led indicates RS-232 data received ; ; Auto-sets SpeakJet baud rate if Start switch pressed ; note: sends $55 and blinks Out-1 led (disabled) ; ; Run led blink indicates program health ; ; Written by David J. Brown ; Revision: 0.4 ; April 22, 2006 ; History: 0.4 Changed speakjet to i2c protocol ; 0.31 Converted to lower case, updated code ; 0.3 Added display of program name ; 0.2 Initialize AUX output low and SpeakJet pins ; 0.1 Modified pin definitions ; 0.0 Initial release of RS-232 SPEAKJET program ; Date: April 25, 2004 ; ; Uses the following PSIM template with modifications: ;***************************************************** ;* MIDI-In interrupt or polled (set by conditional) * ;* MIDI-Out polled * ;* Timer interrupts provide 1mS timestamp * ;***************************************************** ; ; Template developed by David J. Brown ; Based on code from Brice Hornback ; Revision: 0.1 ; Date: ; History: 0.1 Added DAC & led initialization, 1 mS timer ; functionality, stop led blinks when MIDI data ; received, run led blink at 0.5 seconds for ; health indicator ; 0.0 Initial release of MIDI input and output routines ; ;##################################################### ; ; ### CONDITIONAL COMPILING OPTION ### ; Set POLLED or INTERRUPT driven MIDI input ; ; Comment out next line for polled mode IM_FLAG CON 1 ;Define to enable MIDI In interrupts ; Comment to set polled MIDI In mode ; ;##################################################### ; ; ### CONDITIONAL COMPILING OPTION ### ; Set TIMER INTERRUPT mode ; note: Run led will blink if timer interrupts enabled ; ; Comment out next line to disable timer interrupts TM_FLAG CON 1 ;Define to enable timer interrupts ; Comment to disable timer interrupts ; ;##################################################### ; ;-----------------------------------------------------------------------------------------------; ; 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 spkj_full var in6 ;speakjet buffer half full spkj_sdata con p7 ;speakjet data aux_j con p8 ;aux jack (output mode) aux_in var in8 ;aux jack (input mode) stop_led con p9 ;stop led (red) stop_led_out var out9 ;stop led alias used for let statement run_led con p10 ;run led (green) run_led_out var out10 ;run led alias used for let statement load_dacs con p11 ;load dac pin ser_data con p12 ;dac serial data input pin clock con p13 ;dac clock pin midi_sdata con p15 ;midi data serial output ;i/o declarations in_j1 var word ;in-1 value: get_inputs in_j2 var word ;in-2 value: get_inputs in_j3 var word ;in-3 value: get_inputs in_j4 var word ;in-4 value: get_inputs 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 data declarations mididata var byte ;midi data variable for subroutines i_data var byte ;midi data variable for interrupt routine status var byte ;midi status data rptr_s var byte ;received data start pointer (first data in buffer) rptr_e var byte ;received data end pointer (last data in buffer+1) rbufnum var byte ;number of bytes in received data buffer rdataf var byte ;received data flag 1=data, 0=no data rbufl con 250 ;receive buffer length rbuf var byte(rbufl) ;receive buffer data ;timer declarations timecount var long ;1 ms timer count turnoff var long ;time to turn off stop led ;speakjet declarations spkdata var byte ;transmit data to speakjet ; ;***************************************************** ; ;initialize psim pins dirs=%0011111010000000 ;configure pin direction (1=output, 0=input) ;inputs: ; midi-in, aux, speakjet flow control, ; start, stop, in-4, in-3, in-2, in-1 ;outputs: ; load_dacs, ser_data, clock, stop led, ; run led, speakjet serial output ; note: setting midi out pin sends erroneous data high spkj_sdata ;set speakjet serial output to mark 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 serial hardware and ports ;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 ; ;setup timerw for 1 millisecond interupts let tmrw=%10001000 ;set timer mode register to enable count let tcrw=%10110000 ;set timer control register ; tcnt cleared by compare match ; /8 internal clock let tierw=%01110000 ;set timer interrupt register to disable overflow interrupt let tsrw=%01110000 ;set timer status register to default let tior0=%10001000 ;set timer i/o regiseter 0 to default let tior1=%10001000 ;set timer i/o register 1 to default let gra=2000 ;set general register a ; 16 mhz clock /8 = 2 mhz ; 2000 counts = 1 millisecond interrupt ; ;initialize variables let rptr_s=0 ;initialize receive start pointer let rptr_e=0 ;initialize receive end pointer let rbufnum=0 ;set receive buffer to empty let timecount=0 ;set real time counter to 0 let turnoff=0 ;set time to turn off to timecount ; ;display program name pause 250 ;let processors initialize let mididata=$f0 ;sysex gosub send_midi let mididata=$7d ;display id gosub send_midi let mididata=$0a ;clear display gosub send_midi let mididata=$18 ;overwrite gosub send_midi let mididata="r" gosub send_midi let mididata="s" gosub send_midi let mididata="2" gosub send_midi let mididata="3" gosub send_midi let mididata="2" gosub send_midi let mididata=" " gosub send_midi let mididata="t" gosub send_midi let mididata="o" gosub send_midi let mididata="s" gosub send_midi let mididata="p" gosub send_midi let mididata="e" gosub send_midi let mididata="a" gosub send_midi let mididata="k" gosub send_midi let mididata="j" gosub send_midi let mididata="e" gosub send_midi let mididata="t" gosub send_midi let mididata=$f7 ;end sysex gosub send_midi pause 1 let brr=207 ;set bit rate register for 2400 baud pause 1 ;wait for new baud rate ;initialize TTS256 i2cout p6,p7,$0,[($48<<1),"passthruon",$0d] ;turn pass through mode on ; #ifdef tm_flag oninterrupt timerwint_imiea, calctime enable timerwint_imiea ;enable timer interrupt #endif ; #ifdef im_flag oninterrupt sci3int_rdrf, midi_in_isr enable sci3int_rdrf ;enable midi in interrupt #endif ; main: ;send $55 to speakjet if start switch pressed ; if start_j = 1 then ;check for start ; let out_j1=1024 ;flash out1 led ; gosub load_outputs ; let spkdata=$55 ;send sync character to speakjet ; gosub speakjet ; pause 1000 ;allow time for switch release ; let out_j1=0 ; gosub load_outputs ; endif sendit: if rbufnum=0 then main ;check to see if any data received gosub get_rbuffer ;get data from received buffer let spkdata=mididata ;send it to speakjet gosub speakjet goto sendit ;loop until input buffer empty ; ;***************************************************** ; Subroutines ;***************************************************** ; ;send spkj_data via i2c speakjet: if spkdata="X" then ;X terminates pass through let spkdata=89 endif i2cout p6,p7,$0,[($48<<1),spkdata] ;send out i2c return ; ;subroutine to send mididata ;waits until transmitter ready send_midi: let status=ssr if status & %10000000 then ;check transmitter ready ;ready to transmit let tdr=mididata ;send data to TDR return else goto send_midi endif ; ;get mididata from receive buffer ;rdataf=1 if successful, rdataf=0 if no data in buffer get_rbuffer: #ifdef im_flag ;the interrupt service routine uses the same variables disable sci3int_rdrf #endif ;check to see if buffer empty if rbufnum=0 then ;buffer is empty rdataf=0 ;set empty flag else ;buffer has data let mididata=rbuf(rptr_s) let rbufnum=rbufnum-1 let rptr_s=rptr_s+1 if rptr_s=rbufl then let rptr_s=0 ;wrap pointer at max value endif let rdataf=1 ;set data returned flag endif #ifdef im_flag enable sci3int_rdrf #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,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 return ; ;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 ; ;***************************************************** ; Interrupt service routines ;***************************************************** ; #ifdef tm_flag ;interrupt service routine for timer ;increments timecount value ;turns off stop led at turnoff time value ;blinks run led at 0.512 second intervals calctime: let timecount=timecount+1 ;increment real time count if timecount=turnoff then ;value to turn off stop led low stop_led endif if (timecount&$000001ff)=$00000100 then toggle run_led ;blink run led at 0.512 second intervals endif resume #endif ; #ifdef im_flag ;interrupt service routine for received midi data ;puts data into input buffer and sets rbufnum to number of entries midi_in_isr: ;do not check ssr in interrupt mode let i_data=rdr ;read receiver data register ;check to see if buffer full if rbufnum=rbufl then ;buffer is full ;simply loose data else ;put data into buffer let rbuf(rptr_e)=i_data let rbufnum=rbufnum+1 ;set rbufnum to number of entries let rptr_e=rptr_e+1 ;increment pointer for next entry if rptr_e=rbufl then rptr_e=0 ;wrap pointer at max value endif endif resume #endif ; ;***************************************************** ; End of program ;*****************************************************