Shop OBEX P1 Docs P2 Docs Learn Events
Serial I/O Timing problem — Parallax Forums

Serial I/O Timing problem

PyrotomPyrotom Posts: 84
edited 2007-05-15 21:17 in Propeller 1
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
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 JohnsonCharlie Johnson Posts: 147
    edited 2006-06-14 13:36
    I do not know the answer, but I bet when it gets solved it will also solve my RFID reader problem. This sounds very similar.

    Charlie
  • JavalinJavalin Posts: 892
    edited 2006-06-14 14:00
    What pins does your "FastShiftOut" object use? Just the 7-10 in the constant bits?

    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
  • PyrotomPyrotom Posts: 84
    edited 2006-06-14 14:16
    Yes FastShiftOut uses only the pins passed as the parameters, but it is definitely the cause of the problem. If I disable it, but leave the MidiIn object running, everything is OK. I'll post the entire code of FastShiftOut when I get home. It is definitely hitting a RDBYTE hub instruction very hard - about one out of every three or four rotations of the hub. If I put in some NOP's to slow down the inner loop, the frequency of errors definitely changes, but not in a way that makes much sense to me.
  • PyrotomPyrotom Posts: 84
    edited 2006-06-14 22:20
    OK, I put WAITCNT statements in my output shift routine, and when I put the delay at 2000 clock cnts, the jitter on the MIDI input seems to go away. Any smaller value on the delay and I start getting corruption of the MIDI input. Here's the code for the shifter - it is driving a string of 74HC595 serial-in parallel-out shift registers.
    ''***********************************************
    ''*  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
    
    
  • PyrotomPyrotom Posts: 84
    edited 2007-05-15 21:17
    I did finally solve this problem - it had nothing to do with the Propeller chip or the code. A friend who is an electronics person was over and I described my problem. He looked at my breadboard for a few seconds and said "Try a couple of .01uf de-glitching capacitors on your power supply lines". I plugged in the caps and the problems went away... Thank you, Larry!
Sign In or Register to comment.