Shop OBEX P1 Docs P2 Docs Learn Events
How can SPIN2 test an IN or Carry flag? — Parallax Forums

How can SPIN2 test an IN or Carry flag?

I need to set up a synchronous-serial transmit Smart Pin so a Spin2 program can detect whether or not the Smart Pin's buffer is empty. The instructions for that mode note:
Each time the buffer is advanced into the shifter, IN is raised, indicating that a new output word can be written via WYPIN.
So I know the IN flag should get raised. The Spin2 Language Documentation described the RQPIN as:
RQPIN(Pin) : Zval --- Read Pin smart pin without acknowledging, Zval[31] = C flag from RQPIN, other bits are RQPIN.
Now the Z[31] bit represents the state of the Carry bit/flag. Is that correct?
With code such as below, can I detect the IN flag in Spin2 this way? Or am I missing something about use of RQPIN? I know the synchronous-serial smart pin works properly.
repeat until alpha <> $8000_0000         'wait for alpha MSB = 1 
   alpha := RQPIN(21)  &  $8000_0000        '21 = Sync Ser Transmit pin, mask Z[31]

But when I run the following loop--within a larger program--the transmit and clock outputs work properly, but I never see the Z[31] set to a logic-1.
PINSTART (20, Transition_Mode, 7496, 0)         'Start Smart Pin 20
PINSTART (21, Sync_Tx_Mode, Sync_Ser_Xreg, 0)   'Start Smart Pin 21  
repeat                                          'Loop forever
   waitms (100)				        'Short delay
   wypin (20, Numb_Transitions)                 'Set clock transitions
   wypin (21, $82)				'Send $82, %10000010
   waitms (100)					'short delay
   alpha := RQPIN(21)				'Get Z-reg data
   debug (UHEX_Long(alpha))			'Display Z-reg data
Forum help always appreciated. --Jon

Comments

  • RaymanRayman Posts: 13,900
    I think you need to check the actual value of INA[pin] or INB[pin].
  • RaymanRayman Posts: 13,900
    Here's an assembly snippet from my wav player that waits for current sample to be done playing by testing IN with testp:
    WaitIn  'wait for smartpin to be done with current sample
                testp   pLeft   wc
        if_nc   jmp     #WaitIn
    
  • JonnyMacJonnyMac Posts: 8,929
    edited 2020-09-25 19:06
    If you're wanting to check the IN bit with Spin2, use pinread(). Here's a method from a Mode 0 Smart Pin SPI object I started
    pub shiftin(mode, bits) : value
    
    '' Shift data in from a synchronous serial device
    '' -- mode is bit order: LSBFIRST or MSBFIRST
    '' -- bits in the number of bits in the value
    
      pinf(sdi)                                                     ' reset di
      wxpin(sdi, %0_00000 | (bits-1))                               ' configure sampling/bits
      pinl(sdi)                                                     ' enable di
      wypin(sck, bits)                                              ' start clocking data
      repeat until pinr(sck)                                        ' wait until clocks finished
    
      value := rdpin(sdi)                                           ' get the value
    
      if (mode == LSBFIRST)
        value >>= (32-bits)                                         ' align lsb
      else
        value rev= 31                                               ' flip to align lsb
        if (bits < 32)                                              ' clear unused bits
          value zerox= (bits-1)
    

    FWIW, I've abandoned using smart pins for SPI -- it takes less effort to bit-bang and you have more flexibility.
  • Thanks, Jon. I agree with your assessment of bit banging for SPI. I'll use the sync-serial mode only as an illustration in a Smart-Pin tutorial that will introduce people to Smart Pins and how they work. My two other examples are a square-wave output and a quadrature-encoder input. I just wondered how to test flags like this in Spin2. Cheers. --Jon
  • May I suggest for your Spin examples that you use named constants for the pins, and the mode constants defined in Spin2 -- as in this code that is from that same experiment.
    pub start(sdipin, sdopin, sckpin, khz) : result | m, x, tix
    
      stop()
    
      if ((sdipin == sdopin) || (sckpin < 0))                       ' validate pins
        return false
    
      longmove(@sdi, @sdipin, 3)                                    ' save pins
    
      if (sdi >= 0)
        m := P_SYNC_RX                                              ' spi rx mode
        m |= ((sck-sdi) & %111) << 24                               ' add SCK offset (B pin)
        x := %0_00000 | (8-1)                                       ' sample ahead of b pin rise, 8 bits
        pinstart(sdi, m, x, 0)                                      ' configure smart pin
        pinf(sdi)                                                   ' disable until used
    
      if (sdo >= 0)
        m := P_OE | P_SYNC_TX                                       ' spi tx mode
        m |= ((sck-sdo) & %111) << 24                               ' add SCK offset (B pin)
        x := %1_00000 | (8-1)                                       ' start/stop mode, 8 bits
        pinstart(sdo, m, x, 0)                                      ' configure smart pin
        pinf(sdo)                                                   ' disable until used
    
      m := P_OE | P_PULSE                                           ' pulses for spi clock
      x.word[0] := 2 #> (clkfreq / (khz*1000)) <# $FFFF             ' ticks in period
      x.word[1] := x.word[0] >> 1                                   ' ticks in low cycle (50%)
      pinstart(sck, m, x, 0)                                        ' configure smart pin
    
      setup := true
    
      return setup
    
    Putting magic numbers for pins into examples leads newcomers down a bad-habit path -- in my opinion.
  • cgraceycgracey Posts: 14,133
    edited 2020-09-25 19:49
    You can test the value for being negative, in order to get C:

    busy := RDPIN(pin) < 0

    Could the transmit have been completing so quickly that you were never able to catch BUSY high?
  • Jon--Right you are, no magic numbers in the final versions. Thanks for the reminder.
    Chip--I'll check that. I see the flag bit now that I can use DEBUG.
    Suppose I want to check the flag for the asynchronous receiver mode and I expect 32-bit data. How does the IN flag get tested then in Spin2? Obviously the C flag can't go into bit Z[31]. Maybe resort to a short section of assembly-language?
    --Jon
  • cgraceycgracey Posts: 14,133
    To test the IN flag, just use PINREAD (pin).
  • RaymanRayman Posts: 13,900
    I was just looking at the docs and it's not 100% clear how to use PINREAD or what it does...

    I think I've decided that if it's a single pin it's the same as INA[pin] or INB[pin].

    Guessing that if it's multiple pins it's a bitfield with bit 0 being the starting pin...
  • cgraceycgracey Posts: 14,133
    Rayman wrote: »
    I was just looking at the docs and it's not 100% clear how to use PINREAD or what it does...

    I think I've decided that if it's a single pin it's the same as INA[pin] or INB[pin].

    Guessing that if it's multiple pins it's a bitfield with bit 0 being the starting pin...

    That right. The TESTP instruction in PASM can only read one pin, but to match all the output instruction in Spin2 which can work on fields of pins, the PINREAD command reads INA or INB and then LSB-justifies the first bit in the field, with any other bits above the LSB.
Sign In or Register to comment.