Shop OBEX P1 Docs P2 Docs Learn Events
SPI_Asm vs. SPI_Spin — Parallax Forums

SPI_Asm vs. SPI_Spin

kolyurkolyur Posts: 43
edited 2011-12-23 07:04 in Propeller 1
Are these objects designed to be interchangeable? One runs in a new cog and the other doesn't, but they both have Start, Shiftin, and Shiftout functions with the same parameters. The reason I ask is that SPI_Spin works for me but SPI_Asm doesn't.

I'm communicating with an AD7705 analog-to-digital converter. My basic data transfer functions are:
PRI WriteToReg(Value)
  spi.shiftout(TXpin, Cpin, SPI#MSBFIRST, 8, value)

PRI ReadResult : Value
  value := spi.shiftin(RXpin, Cpin, SPI#MSBPOST, 16)

Basically I write an 8-bit command value, then read in a 16-bit data value (no simultaneous transfers). Using SPI_Spin, everything works great. But if I just change the object definition to SPI_Asm, my readback value becomes some seemingly random number that doesn't change with the signal. I'd really like to figure out how to use the Assembly code here because a clock pulse with Spin code seems to be limited to about 10 us. The AD7705 is capable of much faster transfers so I'd like to use a clock pulse around 1us (which equates to a Delay value of 15 in SPI_Asm).

Are there any modifications I need to make to my code when switching to the Assembly version?

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2011-12-22 18:49
    Just some random thoughts here. Have you tried slowing down the PASM object to SPIN speed? Also, is chip select for the ADC permanently on? How is your clock line wired (pull-up/down)? Reason I'm asking this is that the object(s) only start driving the clock line immediately prior to the first transfer call. How did you configure the initial clock state (datasheet seems to suggest idle high)?
  • kolyurkolyur Posts: 43
    edited 2011-12-22 20:52
    Thanks for the suggestions. I tried setting the Delay parameter of SPI_Asm to 200, which should produce a clock pulse around 10us which simulates what I had with SPI_Spin. Did not fix problem.

    I don't have a pull-up/down on the clock line. I realize there is the possibility of stray data at startup before the Prop sets the pin directions, but my first action afterwards is to reset the chip by sending logic high for 32 pulses (see p.16 of datasheet).

    I have the initial clock state set as high (State=1).
  • kuronekokuroneko Posts: 3,623
    edited 2011-12-23 00:32
    kolyur wrote: »
    ... but my first action afterwards is to reset the chip by sending logic high for 32 pulses (see p.16 of datasheet).
    Do you - by any chance - use spi.shiftout(TXpin, Cpin, SPI#MSBFIRST, 32, -1) to do this? If so then the ADC will never see the reset.
    MSBFIRST_                                               ''     Send Data MSBFIRST
                  mov     t3,             arg4              ''          Load t3 with DataValue
                  mov     t5,             #%1               ''          Create MSB mask     ;     load t5 with "1"
                  [COLOR="orange"]shl     t5,             arg3[/COLOR]              ''          Shift "1" N number of bits to the left.
                  [COLOR="red"]shr     t5,             #1[/COLOR]                ''          Shifting the number of bits left actually puts
                                                            ''          us one more place to the left than we want. To
                                                            ''          compensate we'll shift one position right.              
    
    The shl will leave t5 untouched (32 behaves like 0) and the shr will effectively kill the mask. Meaning instead of 32 one-bits you'll get 32 zero-bits. This can be fixed by using ror instead of shr.
  • kolyurkolyur Posts: 43
    edited 2011-12-23 05:42
    Wow you nailed it kuroneko, I am using that exact code to reset the chip and the problem was fixed once I changed shr to ror as you suggested. Thanks for lending me your keen eye on this.

    But now I have another issue. It seems that when using SPI_Asm, the clock delay value has no effect. I'm referring to the first parameter in the Start method, which I assume to be the length of a clock pulse. In SPI_Spin, the clock delay is in units of microseconds, and of course I can see a noticeable change in my update rate when I change that value. (I'm averaging a fixed number of samples together and then updating my VFD display.)

    But with SPI_Asm, that delay seems fixed at about 10-15 us. I estimated that value by comparing the apparent update rate to what I get from SPI_Spin. I scoured my program looking for anything that might be introducing a delay, but it's pretty simple. I don't know enough about assembly to do the same with SPI_Asm.

    I'm using a 5Mhz crystal on the Prop if that makes a difference, and I have _clkmode = xtal1 + pll16x, _xinfreq = 5_000_000.
  • kuronekokuroneko Posts: 3,623
    edited 2011-12-23 06:40
    From the looks of it it is in 50ns steps for a half-cycle (i.e. you specify the delay for the low cycle of the clock). For visibility tests I used 10_000_000 which gives me 0.5 sec half-cycle, i.e. 1Hz. Which values did you try?
  • kolyurkolyur Posts: 43
    edited 2011-12-23 07:04
    I feel kind of silly now because I just realized that the problem is not with the SPI object, but rather a limitation of the ADC chip. Because of how I have the hardware filtering set up, one conversion takes 20 msec. So, if I average five samples, my VFD update rate should be about 10 Hz. That is about what I am seeing with either SPI object.

    So, there isn't much to be gained by using SPI_Asm and that's why it appeared [to me] to not be working correctly. With the Spin version and a clock pulse of 10us, it takes about 0.5 ms for one data transfer cycle. That's a pretty small fraction of 20 ms so I'll probably stick with SPI_Spin.

    Thanks for all your help with this.
Sign In or Register to comment.