Shop OBEX P1 Docs P2 Docs Learn Events
Creating an inter-propeller SPI interface, but having a weird issue.. — Parallax Forums

Creating an inter-propeller SPI interface, but having a weird issue..

laser-vectorlaser-vector Posts: 118
edited 2010-08-24 22:14 in Propeller 1
im trying to make something similar to a Serial Peripheral Interface Bus (like an A/D converter) that ultimately should eventually server as communication between two propellers.

it works under the principal that you call this method with three controls (datainput, datasize, waitint)

datainput is the data to send.
datasize is the maximum number of bits to send
dataint is the interval between transmissions

ive got it working somewhat but have an interesting issue that i cant seem to figure out.

to start explaining, heres the code:
CON
  
    _CLKMODE    = XTAL1 + PLL16X
    _XINFREQ    = 6_250_000

VAR

    byte cog
    long Stack[20]
        
PUB init

    cog := (cognew(datasend, @stack) + 1)
        
PUB stop

    if cog
      cogstop(cog~ - 1)
    
PUB datasend | datainput, datamask, cntr, l, datasize, waitint, datarate, datapin, clkpin

    datasize  := 32                                        'soon to be an input, this indicates if its a long (32), word (16) or byte (8).
    datainput := %00000100_00111000_00010000_00111010      'soon to be an input, this is the data to send.
    waitint   := 50000                                     'soon to be an input, interval between transmissions.
    datarate  := 5000                                      'soon to be an input, sets the clock speed.
    datapin   := 0                                         'soon to be an input, data output IO pin.
    clkpin    := 1                                         'soon to be an input, clock IO pin

    
    dira[datapin]~~                                        'sets pins to output.
    dira[clkpin]~~
    
    repeat                                                 'initial "reset loop" makes sure every thing is clear from last transmission.
      outa[clkpin]~~                                       'sets datapin low, no need for data at this point..
      outa[datapin]~                                       ''sets clkpin high so that receiving cog knows transmission is idle
                                                           ''Note: the receiving cog should wait for the next falling edge.
      datamask := 0                                        'clears the incrimenting bitwise mask.
      cntr := 0                                            'clears datamask's incrimenting counter.
      waitcnt(waitint + cnt)                               'wait interval between data transmissions.
      repeat l from 0 to datasize                          ''main loop for reading each consectuive bit in datainput
                                                           ''while outputting each bit on the falling edge of every clock.
        waitcnt((datarate / 2) + cnt)                      'waits for half the clock cycle, ultimently it waits for one full phase (high in this case).

        if datamask & datainput                            'main argument, if the incrimenting datamask and datainput are both 1, datapin = 1.
          outa[datapin]~~                                  'sets datapin to 1.
        else                                               'if the incrimenting datamask and datainput are not the same, datapin = 0.
          outa[datapin]~                                   'sets datapin to 0. 
                  
        outa[clkpin]~                                      'sets clkpin to low phase.
          
        waitcnt((datarate / 2) + cnt)                      'waits for half the clock cycle, ultimently it waits for one full phase (low in this case).

        cntr++                                             'just adds 1 to cntr
        datamask := |< cntr                                'bitwise decode to incriment the datamask by cntr (or +1 every pass).
          
        if cntr => (datasize - 1)                          'makes sure the cntr never goes higer than the datasize limit.
           cntr := 0                                       'if it does then obviously it resets it to zero.
           
        outa[clkpin]~~                                     'sets clkpin to high phase.
                                                           'loop end...

The problem is that the LSB and MSB are not being sent correctly. which also makes me worried that the rest of the data might be out of sync as well (but it seems to be okay) but i havnt counted the clock pulses on my scope to see if they are in the right position yet...

anyways heres and example:

when i set datainput's MSB to 1 and all others to 0:
    datasize  := 32                                         'soon to be an input, this indicates if its a long (32), word (16) or byte (8).
    datainput := %10000000_00000000_00000000_00000000      'soon to be an input, this is the data to send.
    waitint   := 50000                                     'soon to be an input, interval between transmissions.
    datarate  := 5000                                      'soon to be an input, sets the clock speed.
    datapin   := 0                                         'soon to be an input, data output IO pin.
    clkpin    := 1                                         'soon to be an input, clock IO pin

after the clock has gone through 31 cycles it arrives at the last 32nd cycle, on the falling edge of clock cycle 32 the MSB is flipped to "on", the clock rises and data transmission should end, however there is still one erroneous falling edge (clock cycle) preceding it (which would indicate a 33rd bit equaling 0). see the picture of the actual output:
DSC04394.jpg

When i set datainput's LSB to 1 and all others to 0:
    datasize  := 32                                         'soon to be an input, this indicates if its a long (32), word (16) or byte (8).
    datainput := %00000000_00000000_00000000_00000001      'soon to be an input, this is the data to send.
    waitint   := 50000                                     'soon to be an input, interval between transmissions.
    datarate  := 5000                                      'soon to be an input, sets the clock speed.
    datapin   := 0                                         'soon to be an input, data output IO pin.
    clkpin    := 1                                         'soon to be an input, clock IO pin

There is nothing there...
DSC04396.jpg

If i set datainput to some random value:
    datasize  := 32                                         'soon to be an input, this indicates if its a long (32), word (16) or byte (8).
    datainput := %00000100_00111000_00010000_00111010      'soon to be an input, this is the data to send.
    waitint   := 50000                                     'soon to be an input, interval between transmissions.
    datarate  := 5000                                      'soon to be an input, sets the clock speed.
    datapin   := 0                                         'soon to be an input, data output IO pin.
    clkpin    := 1                                         'soon to be an input, clock IO pin

All looks good, except that there is an erroneous bit in the absolute last position, greater than the MSB from the first example..
DSC04397.jpg

anyone see anything wrong in this code that i dont??

i apologize for the crappy scope pictures, its an old school scope and i cant figure out how the trigger exactly works, i have a nice digital scope at work that i can use and take much better pictures with tomorrow.

ThAnKS!!! :D

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2010-08-24 22:14
    Your loop is supposed to have datasize+1 cycles (0..datasize)? Also, datamask starts as 0, not |< 0. Meaning bit 0 is never sampled.
Sign In or Register to comment.