Shop OBEX P1 Docs P2 Docs Learn Events
Question regarding Dira and in/outa selecting pins — Parallax Forums

Question regarding Dira and in/outa selecting pins

Yeah, the subject line is rather lumpy, hard to say it in a short blurb.

In the Prop Ed manual and the Prop manual v1.2, there are examples of DIRA[3] or DIRA[9..11] etc, but there does not seem to be a way to set the pin range as a constant or otherwise in the Con block of the code. So, down in some object, there ends up being a line like

DIRA[0..3]~ ' set input pins for partx

but it would be nice to be able to have a Con block entry like

...
PartX_inp = something

and down in some part of the code a line like

DIRA[PartX_inp]~

INA[PartX_inp]

...

So, the question is did I miss something or is this not possible to do with the Prop1

Thanks

Comments

  • Cluso99Cluso99 Posts: 18,069
    try this
    con
      pinlow = 3
      pinhi  = 6
    
    pub setpins
      dira[pinlow..pinhi] := 1
    
  • JonnyMacJonnyMac Posts: 9,102
    edited 2021-01-24 02:23
    I do what Ray does, but I tend to use the constant names with MSB and LSB so I can do something like this
      selection := ina[SW1_MSB..SW1_LSB]
    

    Remember, too, that when writing to a group of outputs there is a binary transfer so it's usually best to be obvious. For example, if you have three pins that correspond to an RGB LED.
      outa[R_LED..B_LED] := %100
      dira[R_LED..B_LED] := %111
    
    The first line makes the red LED output high when the second line sets the RGB pins to output mode.

    Pin fields and bit fields exist in the P2 which simplify (in many cases) some of this stuff.
  • Thank you sirs, your help was, well, very helpful. If I recall, the P2 has a mechanism for setting the range of I/O pins. Not gotten around to playing with it. The prop tool works well enough under wine, but no serial connection to the props last time I tried it. Currently using BST. Here is the output from 8 MCP3201s, ~5V Vref, with string of 10k resistors for 8 voltage levels.

    Bit 0 11110000
    Bit 1 11101100
    Bit 2 11011111
    Bit 3 10001010
    Bit 4 10001010
    Bit 5 10001010 <====== from 8 MCP3201s into pins 1-8
    Bit 6 10001010
    Bit 7 10001010
    Bit 8 10001010
    Bit 9 10101010
    Bit 10 11101010
    Bit 11 11111110
    Channel 0 0200 631mV
    Channel 1 03FF 1261mV
    Channel 2 0601 1894mV
    Channel 3 07FF 2523mV
    Channel 4 0A01 3157mV <======== Bit Array rotated into channels results of hex values match values on AD2 SPI capture
    Channel 5 0C07 3796mV
    Channel 6 0E03 4422mV
    Channel 7 0FFF 5048mV
    Clock Counts = 608656 <== ballpark PC counts. ~7ms, AD2 shows conversion time of ~1.5ms CS* pulse width

    PUB ReadADCs  (DataArray, Bits, Lead, CS, CK, ChannelArray, ChanCnt, ChanBase )| ChanEnd, Selector, x, y
    
      Bits--                                           ' correct for loop bit count
      Lead--                                           ' correct for loop lead pulse count
      ChanCnt--                                        ' same for channel count for ch 0 - channel m-1
      ChanEnd := ChanBase+ChanCnt                      ' determine channel high pin. Pins must be contiguous
      dira[ChanBase..ChanEnd]~
    
      repeat x from 0 to bits                          ' clear bits array
        word[DataArray][x] := 0
      repeat x from 0 to ChanCnt                       ' clear channel array
        word[ChannelArray][x] := 0
    
       outa[CS..CK]~                                        ' start with clock low and
       dira[CS..CK]~~                                       ' set chip sel to output
       outa[CS]~                                        ' drop CS to start sequence
       waitcnt(clkfreq/90000 + cnt)
        repeat x from 0 to Lead                        ' waste 3 pulses for capture and hold time
          waitcnt(clkfreq/90000 + cnt)                 ' could have just dummped this section and captured all 15
          outa[CK]~~                                   ' counts here, but that would have made things more complex later
          waitcnt(clkfreq/90000 + cnt)                 ' this actually came out faster in the overall result
          outa[CK]~
        repeat y from 0 to Bits                        ' get data bits from MSB to LSB (because that is the order they read out)
          waitcnt(clkfreq/90000 + cnt)
          outa[CK]~~
          waitcnt(clkfreq/90000 + cnt)
          byte[DataArray][y] := ina[ChanBase..ChanEnd] ' get the data bit for all channels
          outa[CK]~
      outa[CS]~~                                       ' until all bits for all channels are in an array x bits deep and y channels wide
    
      repeat x from 0 to Bits                          ' Convert bits to channels starting with MSB
        repeat y from 0 to ChanCnt                     ' unwind the bits for each channel
          Selector :=  |< y                            ' Use bit selector to identify destination channel
          if ( Selector & byte[DataArray][x])          ' is bit 2^n set for channel m
              word[ChannelArray][y] ++                      ' if true +1 then
          word[ChannelArray][y] <<= 1                       ' shift word for next value
      repeat y from 0 to ChanCnt                       ' unwinding leaves one extra shift per channel
        word[ChannelArray][y] >>= 1                         ' shift word right to correct for extra shift
    
    
  • JonnyMacJonnyMac Posts: 9,102
    edited 2021-01-24 07:24
    I have a toothache, a headache, and I've been at my desk since 7AM. So, fair warning, I may not be understanding what you're doing.

    Assumptions
    -- you're accessing all ADCs at the same time (i.e., CS and CLK are tied to all devices)
    -- you have 8 MISO pins connected to the Propeller

    If that's the case, I think you can simplify your code. As we say in Hollywood.... for your consideration:
    pub read_adcs(bits, p_dest) | temp[8], ch
    
      outa[CS] := 0
    
      longfill(@temp, 0, 8)                                         ' clear temp 
    
      repeat 3                                                      ' lead pulses
        outa[CLK] := 1
        outa[CLK] := 0
    
      repeat bits                                                   ' read ADCs
        outa[CLK] := 1
        repeat ch from 0 to LAST_CH                                 ' loop through channels
          temp[ch] := (temp[ch] << 1) | ina[MISO+ch]                ' get bits, MSBFIRST
        outa[CLK] := 0
    
      outa[CS] := 1
    
      longmove(p_dest, @temp, work)                                 ' copy local array to target
    

    Notes:
    -- The CS and CLK pins should be defined using constants, and set to outputs (CLK low, CS high) at start-up
    -- The LAST_CH constant is the index of your last channel.
    -- ADCs are connected as a contiguous group in ascending order

    Advice:
    -- Don't use the ~~ and ~ operators; they are confusing and slower than straight assignments.
    -- You're adding delays that are probably not necessary; that device can run 800kHz and you'll never hit that with bytecode Spin
  • Thank you Jon, that is some nice work. Difference between master and (probably) apprentice. Hence my doing a bit more brute force coding and refinement once working. Still more to learn. Will try this. Did not think of reading all the bits in the clock period. Also didn't know that ~ and ~~ was slower.

    Your assumptions are spot on, I had a handful of this part to play with and even though this is on a mini, pin count isn't yet a problem.

Sign In or Register to comment.