Serial I/O Timing problem
Now I know that the cogs are supposed to run pretty much independantly of each other. But recently I'm not so sure. I'm working on a MIDI application. I can run this program
and all of my MIDI bytes show up on my laptop (via the PropStick serial port) just fine. But when I add two more cogs running my prototype MIDI app like so:
something strange happens. Occasional bytes start showing up on the laptop shifted left 1 bit - what should be x80 comes in as x00, and x90 comes in as x20. This is showing up in my app as stuck notes or as the whole thing just freezing up. Any ideas on why this is happening?? The code in FastShiftOut and MidiIn are doing hub reads and writes to the channel_notes array, but are not using any locks. MidiIn is reading the same midi signal, but off a different pin - the two pins are sharing the same signal from the MIDI interface.
CON
_clkmode = xtal1 + pll16x ' use external crystal * 16
_xinfreq = 5_000_000 ' 5 MHz external crystal (standard on PropStick)
OBJ
miditracein : "FullDuplexSerial"
miditraceout : "FullDuplexSerial"
PUB PipeOrgan
miditracein.start(5, 4, 0, 31_250)
miditraceout.start(31, 30, 0, 38_400)
repeat
miditraceout.tx(miditracein.rx)
return
and all of my MIDI bytes show up on my laptop (via the PropStick serial port) just fine. But when I add two more cogs running my prototype MIDI app like so:
CON
_clkmode = xtal1 + pll16x ' use external crystal * 16
_xinfreq = 5_000_000 ' 5 MHz external crystal (standard on PropStick)
Midi_in_pin = 7 ' input pin from MIDI IN
Pipes_1_data_pin = 8 ' data pin for pipe group 1
Pipes_1_clock_pin = 9 ' clock pin for pipe group 1
Pipes_1_latch_pin = 10 ' latch pin for pipe group 1
Pipes_1_size = 16 ' number of pipes in pipe group 1
VAR
byte channel_notes[noparse][[/noparse]2048]
OBJ
shout_1 : "FastShiftOut" ' output shifter for pipe group 1
midi : "MidiIn" ' serial driver for the MIDI interface
miditracein : "FullDuplexSerial"
miditraceout : "FullDuplexSerial"
PUB PipeOrgan
midi.start(Midi_in_pin, @channel_notes)
shout_1.start(Pipes_1_data_pin, Pipes_1_clock_pin, Pipes_1_latch_pin, Pipes_1_size, @channel_notes + 60)
miditracein.start(5, 4, 0, 31_250)
miditraceout.start(31, 30, 0, 38_400)
repeat
miditraceout.tx(miditracein.rx)
return
something strange happens. Occasional bytes start showing up on the laptop shifted left 1 bit - what should be x80 comes in as x00, and x90 comes in as x20. This is showing up in my app as stuck notes or as the whole thing just freezing up. Any ideas on why this is happening?? The code in FastShiftOut and MidiIn are doing hub reads and writes to the channel_notes array, but are not using any locks. MidiIn is reading the same midi signal, but off a different pin - the two pins are sharing the same signal from the MIDI interface.

Comments
Charlie
try adding _stack = 250 or so to your CON section in the main application, also make sure that your COGS are not using the same pins!
James
''*********************************************** ''* Fast shift out routine v1.1 * ''* * ''* This routine examines a sequence of bytes * ''* 'num_pipes' long, and sends a sequence of * ''* bits out to a shift register, based on * ''* whether the bytes are zero or not. * * ''*********************************************** VAR long cog ' cog flag/id long data_pin ' Five contiguous long clock_pin ' longs for long latch_pin ' the input long num_pipes ' parameters. long data_loc ' DO NOT CHANGE! PUB start(d_pin, c_pin, l_pin, num, data) : okay stop data_pin := d_pin ' Save the parameters clock_pin := c_pin ' into a contiguous latch_pin := l_pin ' data structure so num_pipes := num ' the cog can data_loc := data ' retrieve them. okay := cog := cognew(@entry, @data_pin) + 1 ' Start up the cog. PUB stop '' Stop shifter - frees a cog if cog cogstop(cog~ - 1) DAT '*********************************** '* Assembly language shifter * '*********************************** org entry mov t1,par ' Get the structure address. rdlong t2,t1 ' Get the data pin, mov dataMask,#1 ' create a shl dataMask,t2 ' mask for it or dira,dataMask ' and make it an output. add t1,#4 rdlong t2,t1 ' Get the clock pin, mov clockMask,#1 ' create a shl clockMask,t2 ' mask for it or dira,clockMask ' and make it an output. add t1,#4 rdlong t2,t1 ' Get the latch pin, mov latchMask,#1 ' create a shl latchMask,t2 ' mask for it or dira,latchMask ' and make it an output. add t1,#4 rdlong numPipes,t1 ' Get the number of pipes. add t1,#4 rdlong dataLoc,t1 ' Get the data location sub dataLoc,#1 ' and adjust it. mov timer,delay add timer,cnt ' ' Initial setup is finished, now start the shift out loop. ' :main mov count,numPipes ' Get the number of pipes andn outa,latchMask ' and turn off the latch bit. waitcnt timer,delay mov t1,dataLoc ' Compute location add t1,count ' of the last byte rdbyte t2,t1 ' and load it. :inner test t2,#$FF WZ ' Test the byte and IF_NZ or outa,dataMask ' set it on or IF_Z andn outa,dataMask ' off as appropriate. waitcnt timer,delay or outa,clockMask ' Clock the bit out. sub t1,#1 ' Read the next rdbyte t2,t1 ' byte from main memory. waitcnt timer,delay andn outa,clockmask ' Finish clocking the bit out waitcnt timer,delay djnz count,#:inner ' and loop until all bytes done. or outa,latchMask ' Latch the pipe data waitcnt timer,delay jmp #:main ' and go do it all again. delay long 2_000 ' ' Uninitialized data ' t1 res 1 t2 res 1 count res 1 timer res 1 dataMask res 1 clockMask res 1 latchMask res 1 numPipes res 1 dataLoc res 1