Shop Learn P1 Docs P2 Docs
Chip Select — Parallax Forums

Chip Select

How would I program a cs function, using smart pins, that wouöd count fhe pulses from an NCO clock and then. turn off. CS low then 16 counts later goes high again?
Jim

Comments

  • JonnyMacJonnyMac Posts: 8,309
    edited 2022-01-06 05:04

    If you setup a smart pin (pulse mode) to create your clock pulses no counting is required; the just tell the smart pin to output 16 pulses and toggle the start of CS when it's done. Easy-peasy.

    Setup pin for pulse mode (1 MHz):

      m := P_PULSE | P_OE                                           ' spi clock mode
      x.word[0] := 2 #> (clkfreq / (1_000_000)) <# $FFFF            ' ticks in period
      x.word[1] := x.word[0] >> 1                                   ' ticks in low cycle (50%)
      pinstart(SCLK, m, x, 0)
    

    Test loop:

      repeat
        pintoggle(CS)
        wypin(SCLK, 16)
        repeat until pinr(SCLK)
    

    I dropped that code into a little test app and got the attached output.

    1920 x 1040 - 41K
  • JonnyMacJonnyMac Posts: 8,309
    edited 2022-01-06 05:42

    If you need a continous clock stream with the CS toggling every 16th bit, you can drop a small bit of simple PASM into another cog.

    con
    
      SCLK     = 17  { O }
      CS       = 16  { O }
    
      QTIX     = ((CLK_FREQ / 1_000_000) >> 2) - 2
    
    
    dat
    
                    org
    
    cs_sclk         drvh      #CS
                    rep       #6, #16
                     waitx    #QTIX
                     drvh     #SCLK
                     waitx    #QTIX  
                     waitx    #QTIX  
                     drvl     #SCLK
                     waitx    #(QTIX-2)  
    
                    drvl      #CS
                    rep       #6, #16
                     waitx    #QTIX  
                     drvh     #SCLK
                     waitx    #QTIX  
                     waitx    #QTIX  
                     drvl     #SCLK
                     waitx    #(QTIX-2)  
    
                    jmp       #cs_sclk
    

  • MicksterMickster Posts: 2,301

    Too darned 😎👍

  • RS_JimRS_Jim Posts: 1,616

    Thanks Jon. I will down load this into my PC and give it a whirl.
    Jim

  • RS_JimRS_Jim Posts: 1,616

    @JonnyMac
    OK, so I am getting old and understanding comes very slowly. if I start by driving cs high, and then do a pin toggle then will I get only the negitive going pulse on the cs pin and the clock out on the sclk pin? i don't see the pin assignments happening so I am still somewhat in the dark. I will need to feed the clock signal out to my chip and to the clock input of my sync seral rx clk in. sync serial rcv data will be coming in-from the chip. I assume that I can the take the Z register of the ssr
    pin, and by properly shifting it turn from MSB first to LSB first. The chip (AS5040) uses cs high as a signal to prepare its position information for output.
    Jon, thanks for your assistance in helping me to understand, The documentation often leaves me banging my head on rhe desk.
    Jim

  • JonnyMacJonnyMac Posts: 8,309
    edited 2022-01-10 00:21

    You kind of buried the lead -- starting out with the fact that you're attempting to interface with the AS5040 would have streamlined the responses.

    I looked up the data sheet and searched for existing (usually Schmarschmino) libraries. This device looks pretty easy, and you may be working too hard. Just because we have smart pins doesn't mean we have to use them. I wouldn't in this case -- the setup and use of smart pins takes more code than simple bit-banging.

    Here's the data sheet I looked at, specifically Figure 21

    I found this library which seems -- if a bit clumsy -- to match the data sheet.

    The attached starter Spin2 object matches that library pretty closely -- though I think my variation is a bit cleaner, and it's certainly faster. For some reason the other programmer put in obnoxious delays. I don't have a chip so there's no activity on the MISO (data) pin, but the capture of CS and SCLK shows that the timing is well within the device parameters. It could be made a little faster, but that would require inline PASM to enforce bit timing at any clkfreq value. I don't think it's necessary as the transaction takes less than 75 microseconds.

    I hope this helps.

  • JonnyMacJonnyMac Posts: 8,309
    edited 2022-01-10 00:57

    It could me made faster, but that would require inline PASM to enforce bit timing at any clkfreq setting.

    As an exercise, I went ahead and coded the read() method in PASM2 to run at ~1MHz.

    pri fast_read() : result, sbits | half, _cs, _mosi, _sclk
    
      half := (clkfreq / 1_000_000) >> 1
    
      longmove(@_cs, @cs, 3)
    
      org
                    drvl      _cs
                    waitx     half
    
                    rep       #7, #16
                     drvl     _sclk
                     waitx    half
                     drvh     _sclk
                     waitx    half
                     shl      result, #1
                     testp    _mosi                         wc
                     muxc     result, #1
    
                    mov       sbits, result
                    and       sbits, #$3F
    
                    shr       result, #6
    
                    drvh      _cs
      end
    
      laststatus := sbits
    
    1920 x 431 - 47K
  • MicksterMickster Posts: 2,301

    obnoxious delays

    :D

  • pik33pik33 Posts: 1,809
    edited 2022-01-12 11:51

    @Mickster said:

    obnoxious delays

    :D

    I had to add an obnoxious delay for my robot control program. The robot board controls power supply for several Raspberries. While developing it is connected via PropPlug/USB to the computer - PC/Windows

    Every time I insert anything (eg. pendrive) in any USB in this PC, the connected Propeller is resetted 6-7 times, making short power supply pulses for these Pis. The SD cards fail is imminent in such an environment. So... at the very start of the program...

    pinl(pi_power)
    waitms(2000)
    pinh(pi_power)
    ' the rest of the code
    

    I don't know if there is any solution to this problem and if it is Windows only or not.

  • evanhevanh Posts: 13,837

    I learnt about that rather slowly myself. In fact it required some hints, from Von I think it was, before I woke up.

    USB resets are frequently due to weak cabling. It's something like the device reports low supply volts so the bus controller, or OS, will power cycle the whole bus in an attempt to clear the fault. Of course, a crappy cable can't be resolved that way so it becomes a recurring effect that appears as if the system is unreliable. And can progress to driver/controller lock-ups.

    Fix is get a heavier cable or mains powered hub.

  • evanhevanh Posts: 13,837
    edited 2022-01-12 12:09

    Maybe there is a significant RF noise source near by, which will induce the same resetting effect. This requires some greater effort to resolve - Nominally shielding of the noise source, like replacing an unshielded cable with a shielded one.

    Or maybe it's a static problem. Then earthing of equipment and providing discharge paths for static build up. Maybe adding moisture to the air to bleed off the static.

    On the whole, USB lacks robustness. It needs cuddles.

  • RS_JimRS_Jim Posts: 1,616

    @JonnyMac
    Jon, just as a sanity check for me, what do you see in the Degrees output with AS5040 hardware not connected?
    Jim

  • JonnyMacJonnyMac Posts: 8,309
    edited 2022-01-12 14:52

    I never bothered checking because I didn't have hardware connected, hence any values would be invalid.

    I just connected an EVAL board and without anything connected the degrees() method returns 359. This is not a surprise; I have found that unloaded P2 pins in input mode often return as 1. If this bothers you, change the start method to this:

    pub start(cspin, misopin, sclkpin)
    
    '' Configure interface pins for AS5040
    
      longmove(@cs, @cspin, 3)                                      ' copy pins
    
      pinh(cs)                                                      ' deselect
    
      wrpin(miso, P_LOW_15K)                                        ' use 15K pull-down
      pinl(miso)                                                    ' enable p/d
    
      pinh(sclk)                                                    ' set clock idle
    

    Now the MISO pin is pulled to ground through 15K and without anything connected, all methods read back 0.

    Others: By obnoxious delays, I was talking about bit timing in the bit-banged SPI routine -- here it is:

    uint32_t AS5040::read_chip(void)
    {
      uint32_t raw_value = 0;
      uint16_t inputstream = 0;
      uint16_t c;
      digitalWrite(_cs, HIGH);
      digitalWrite(_clock, HIGH);
      delay(100);
      digitalWrite(_cs, LOW);
      delay(10);
      digitalWrite(_clock, LOW);
      delay(10);
      for (c = 0; c < 16; c++)
      {
        digitalWrite(_clock, HIGH);
        delay(10);
        inputstream = digitalRead(_data);
        raw_value = ((raw_value << 1) + inputstream);
        digitalWrite(_clock, LOW);
        delay(10);
      }
     return raw_value;
    }
    

    The delays in that routine add up to 440ms (with ~50Hz clock). The device is spec'd for a 1MHz clock. In Spin2 at 200MHz, the clock is ~210kHz (see trace above).

  • RS_JimRS_Jim Posts: 1,616

    Jon,just ckng to see if I was getting same.
    Jim

  • RS_JimRS_Jim Posts: 1,616
    edited 2022-01-18 14:30

    Further update:
    I have tried both the spin code and the spin/PASM2 code to no avail. I suspect that my issue is hardware related. All of the error bits come back as %1 and no response for any angle request. I have a hand tremor that makes it impossible for me to solder smt components. I bought 16pin smt break out boards from sparkfun and had a friend with steadier hands assemble them for me. when I look at the boards they are a bit messy so i may have some solder bridges etc. At this point I believe I may abandon the as5040 for an as5055(?) which has 2 more bits of resolution and uses a standard SPI Interface. If I cn't find a breakout board, I may tray to design my own and send it off to one of the board fab houses. A single sided board would work just fine and I could provide for the bypass cap (100nf) to be board mounted and not interfere with the magnetic field. Jon, I do appreciate the assistance. I will try the ohm-meter to see if a I spot any obvious problems that I might be able to fix. I think I have somewhere a probe that will make that easy.
    Edit: Got out the ohm meter and did some testing. Found the AS5040 rotated by 180 degrees on the breakout board. I am afraid that I am screwed! So back to the drawing board so to speak. renumbered the pins and reconnected and tested. Errors still present.
    Jim

  • JonnyMacJonnyMac Posts: 8,309

    I ordered one of these: https://www.digikey.com/en/products/detail/ams/AS5040-SS-EK-AB/2339617. When it arrives I'll finish the basic driver and post it.

  • RS_JimRS_Jim Posts: 1,616

    cool,, let me know how it works.
    Jim

  • RS_JimRS_Jim Posts: 1,616

    @JonnyMac
    Jon,
    Did you ever get a chance to get the AS5040 demo package working?
    Jim

  • JonnyMacJonnyMac Posts: 8,309

    I did. It works fine.

  • RS_JimRS_Jim Posts: 1,616

    OK
    I guess I need to follow your example and get the demo board from Digi
    Thanks for checking.
    Jim

  • JonnyMacJonnyMac Posts: 8,309
    edited 2022-02-08 21:04

    Here's my current code. I decided to use an inline PASM routine to read the chip because it's easy and allows the programmer to set the clock speed (up to 1MHz).

Sign In or Register to comment.