Shop OBEX P1 Docs P2 Docs Learn Events
Simple Blinky — Parallax Forums

Simple Blinky

Here is a simple Eval blink, Seems

Comments

  • JonnyMacJonnyMac Posts: 9,104
    edited 2020-12-17 16:33
    As the say here in Hollywood... for your consideration.

    This program does exactly what yours does, but uses named constants to make the program easier to modify for different hardware. I'm a firm believer of not using pin #s in listings; this practice can lead to confusion and to bugs. Using a number in a waitms() instruction is not so problematic, but defining a constant for that value means only one edit to change the behavior.
  • JonnyMacJonnyMac Posts: 9,104
    edited 2020-12-17 16:32
    Once a new programmer understands that, you can show them how to look for redundancy and eliminate it while maintaining behavior.
  • I just made it simple, so a newbie can see that just a few simple lines of code can get them up and running. Anyway your basically the only one writing spin2 examples, and they all work. Thanks for your input. I wonder who Bob Sweaney is.
  • Sorry, Bob, did I confuse you with someone else? I will fix those listings with your forum handle. My apologies.

    On a serious note, I think it's very dangerous to show newcomers code with "magic numbers" (e.g. embedded pin #s) -- habits die hard, so it's better to teach newcomers good habits from the start.
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2020-12-17 17:29
    I was interested in working with a 4 to 8 bit bus, so I modified the
    Parallax minimal program to blink an 8 bit buss, and transmit serial
    data.

    Unfortunately my next 5 programs that I tried to control an 8 bit buss
    were not successful.


    Bill M.
  • You have a syntax error in this line, Bill.
      PINWRITE(7..0, GETRND())
    
    Writing to a contiguous pin group is different in the P2 -- we use the LSB with addpins and the number of pins past the LSB..
      pinwrite(0 addpins 7, getrnd())
    
    Again, though, I would caution against the use of "magic numbers" in the code (even test code -- been bitten by this or than once). You could create this constant
      BUS4X = 0 addpins 3
    
    ...and then update the code like this:
      pinwrite(BUS4X, getrnd())
    
    ...if you wanted to write to a 4-bit bus. I attached a working demo that uses the LEDs on the Eval board.
  • No problem, call me Bob, DigitalBob, just don't call me late for dinner. I understand your templates, with assigned pins in the Con for I2C, serial, etc., but might be overwhelming for the newcomer. Anyway keep up the hardwork, My library is full with JonnyMac spin objects in P1 and P2.
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2020-12-17 18:18
    Thank you Jon

    I have 6 other beginner programs that I tried to use "Magic Numbers"
    to initiate and control 8 pins. I attached all 5 because each program
    tried something different.

    I tried to use the P2 GitHub OBEX as a guide line for initializing pins,
    but there were almost no demo objects?

    Do we need to initialize the pins, I heard someone say that with the
    new Pin(functions) the pins are automatically set to outputs?

    All the different problems are in the comments. 4 out of 5 programs
    compiled but did not run?

    Are the old pin registers (dira, outa, ina) necessary?

    Is everything I did wrong, or are there compiler issues? Mainly I am
    curious why many pin initialization worked (or at least compiled)
    like outa[7] and outa.[7], and others did not.

    Also the difference on using ' or ' ' for comments. It worked on the
    P1, but I am not sure it works on the P2. The new ide displays those
    comments in 2 different shades?

    Thanks

    Bill M.

    One other question. In many other P1 programs the pin#'s were passed
    from the demo object. Is there any reason why I should not do this (pass
    the pins) with a P2 program? TY
  • JonnyMacJonnyMac Posts: 9,104
    edited 2020-12-17 20:20
    Do we need to initialize the pins, I heard someone say that with the new Pin(functions) the pins are automatically set to outputs?
    It may have been me during one of my prosthelyzing posts. The pinX() functions in Spin2 actually do three three things:
    1) Select the correct IO registers ( A or B )
    2) Make pin(s) inputs or outputs as required
    3) Write to or read from the desired pin(s).

    To make a pin high in the P1, we would do this:
      dira[pin] := 1
      outa[pin] := 1
    
    In the P2, this handles it:
      pinhigh(pin)
    
    We only have 32 pins on the P1, but 64 on the P2. While we *can* directly access the IO registers, I don't recommend it because programs change. When I used to design products for EFX-TEK, I would never connect external circuitry to the Propeller in my schematic. When the PCB layout guy was finished, he had decided the best pins to use for the layout -- all I had to do was update my pin constants in the listing to move test code to the final product. This happens all the time (pins moving), which is one (of many) reasons why embedding pin #s into our code is a bad idea.

    In the P1, we could do this:
      outa[MSB..LSB] := value
      dira[MSB..LSB] := %1111
    
    In the P2, we do it like this:
      pinwrite(LSB addpins (MSB-LSB), value)
    
    There is a caveat, however. In the P1, we can also do this:
      outa[LSB..MSB] := value
    
    ...which will reverse the output order of the lower four bits in value. How can we do this in the P2?
      pinwrite(LSB addpins (MSB-LSB), value rev (MSB-LSB))
    
    Okay, this is not quite as friendly as the P1 version, but -- thankfully -- is an infrequent requirement.
    It might be tempting to do this:
      outa.[LSB..MSB] := value
    
    ...but this doesn't work. The rightmost value in the .[ ] syntax is used as the LSB.
    Are the old pin registers (dira, outa, ina) necessary?
    In Spin2, I don't see any need for direct IO register access.
    Is everything I did wrong, or are there compiler issues? Mainly I am curious why many pin initialization worked (or at least compiled) like outa[7] and outa.[7], and others did not.
    Things have changed from the P1 to the P2. This syntax:
      outa[7]
    
    ...is actually referring to register $003 in the cog. Why? In P2 syntax, outa is just another register and anything in [ ] is an offset. The address of outa is $1FC. Add 7 and you get $203 which is an illegal address because the max is $1FF, hence it wraps around to $003.

    I think you see now why I have become a bit adamant about NOT using IO registers in Spin2 code -- let the Spin2 instructions do the work for you.
    Also the difference on using ' or ' ' for comments. It worked on the P1, but I am not sure it works on the P2. The new ide displays those comments in 2 different shades?
    Single and double apostrophes are both legal line-comment starters. The difference is in the view when using Propeller tool. There is a radio-button a the top marked Documentation. In this mode, only the comments with double apostrophes or double block comments {{ }} will be displayed.
    One other question. In many other P1 programs the pin#'s were passed from the demo object. Is there any reason why I should not do this (pass the pins) with a P2 program?
    It is my (very strong) opinion that one should always craft objects that accept pins from the calling applications. Again, pins move from application to application, and hard-wiring pins is a bad idea. The exceptions, of course, are the fixed pins for programming and application memory (EE or flash). This is why my code calls out fixed IO pins versus application IO pins.

    Code Reviews:
    -- Blink_v01 : The syntax you're using causes the IO registers to be treated as long arrays, not a single array of 32 bits. Again, use the pinX() functions.
    -- Blink_v02 : Mixed syntax with IO registers that Spin2 doesn't support.
    -- Blink_v03 : Same issue with registers in setup(). The main() method never runs because it is not called. Have a look at my template; setup() is called from main().
    -- Blink_v04 : Again, main() is never called. Note: Spin is not like C that looks for main(). In Spin, the first method runs (this is why I place main() at the top).
    -- Blink_v05 : Again, main() is never called.

    Important notes:
    -- It is best NOT to use IO registers directly in Spin2; the underlying code for the high-level instructions is very efficient and fast.
    -- In Spin, the first method in the listing runs and controls the program. The code does not care about its name, nor go looking for anything with a specific name.

    Side note. This blinker code works, but is tedious to write versus using the new Spin2 functions for IO.
      dirb.[56 & $1F] := 1
    
      repeat
        outb.[56 & $1F] ^= 1
        waitms(100)
    
    It's worse if you want to do multiple pins manually. Note the use of addbits versus addpins due to the nature of the syntax.
      dirb.[(56 & $1F) addbits 3] := %1111
    
      repeat
        outb.[(56 & $1F) addbits 3] := getrnd()
        waitms(100)
    
    To access bits with in a register we have to use the .[] notation. Registers are only 32 bits, so we have to use & $1F with the B IO registers. Again tedious. Don't do it.

    Final comment about pin groups. They only work within one register. What happens if you do this?
      BUS = 30 addpins 7
    
    The Propeller will create a group that will impact pins 30, 31, 0, 1, 2, 3, 4, 5 -- which is probably not what we want. I was just writing multi-channel LED driver for the P2 that looks for these boundary issues. It's something to be careful with.

    I've attached my P2 template for your examination and use if you choose.
  • BTW, if you haven't seen my intro article on the P2, you might find some of it helpful.
    -- https://www.nutsvolts.com/magazine/article/an-introduction-to-the-parallax-propeller-2
  • Here's my simple blinky with JM serial, If you use JM objects follow his format, they are well thought out
  • K2K2 Posts: 693
    edited 2020-12-17 20:47
    Fantastic article, JonnyMac! One complaint one hears, whether it's fair or not, is that Propeller information is spread hither and yon, and takes too much effort and time to piece together from a vast body of shaggy dog posts. Therefore any attempt to gather together relevant information for would-be newcomers would be a boon! But what you've written for N&V is far far better than just 'any' attempt. :) A place of prominence ought to be found for it!
  • Jon

    I don't code spin, but on the P1 if I have a data line that is bi-directional with a pullup, I will write a zero to that pin and then change the direction of the pin as required. To send a one, I change the direction to input, to send a zero I change the direction to output, but only for as long as that data bit is required. This helps avoid unintentional data collisions or bus conflicts. I just wondered how P2 spin does that?

    Dave
  • AribaAriba Posts: 2,690
    tritonium wrote: »
    Jon

    I don't code spin, but on the P1 if I have a data line that is bi-directional with a pullup, I will write a zero to that pin and then change the direction of the pin as required. To send a one, I change the direction to input, to send a zero I change the direction to output, but only for as long as that data bit is required. This helps avoid unintentional data collisions or bus conflicts. I just wondered how P2 spin does that?

    Dave

    With the P2 you don't need such tricks, you can configure the pin for open-drain with an internal pullup (or no pullup if you want an external).
    Then you use the same commands for output as you would use with a normal push-pull output.

    Andy
  • Ariba

    Thanks for that- makes sense.

    Dave
  • JonnyMacJonnyMac Posts: 9,104
    edited 2020-12-18 01:03
    Dave,

    Here's an example of what Andy was talking about. In my P2 I2C driver, the application can choose to have pull-ups on the bus or not. If not, the P_HIGH_FLOAT configuration is used which disconnects the output when the pin is written high -- this allows the external pull-up to have control. I'm doing it in PASM2 here, but it also works in Spin.
    pub setup(scl, sda, khz, pullup) | tix
    
    '' Define I2C SCL (clock) and SDA (data) pins
    '' -- khz is bus frequency: 100 (standard), 400 (full), 1000 (fast)
    ''    * circuit/connections will affect maximum bus speed
    '' -- pullup controls high level drive configuration of SCL and SDA
    
      longmove(@sclpin, @scl, 2)                                    ' copy pins
      clktix := tix := (clkfreq / (khz * 1_000)) >> 2               ' calculate ticks in 1/4 period
    
      case pullup
        PU_NONE : pullup := P_HIGH_FLOAT                            ' use external pull-up
        PU_1K5  : pullup := P_HIGH_1K5                              ' 1.5k
        PU_3K3  : pullup := P_HIGH_1MA                              ' acts like ~3.3k
        other   : pullup := P_HIGH_15K                              ' 15K
    
      org
                    fltl      scl                                   ' clear old smart pin setup
                    fltl      sda
                    wrpin     pullup, scl                           ' configure high drive
                    wrpin     pullup, sda
                    drvh      scl                                   ' both high
                    drvh      sda
                    waitx     tix
                    waitx     tix
    
                    rep       #8, #9                                ' bus clear (if SDA stuck low)
                     testp    sda                           wc      ' sample sda
        if_c         jmp      #.done                                ' abort loop if sda == 1
                     drvl     scl                                   ' scl low
                     waitx    tix
                     waitx    tix
                     drvh     scl                                   ' scl high
                     waitx    tix
                     waitx    tix
    .done
      end
    

    I did a quick check of the interpreter source; the pinread() function does not affect the dir register for the pin(s) read.
  • Thanks Jon

    Blink_v06.spin2 works as expected. Now I am going to apply that
    to one of my favorite P1 programs.

    The other P2 file is the comments using 4 different notations. There
    are 2 colors or shades of the comments depending on the notation.

    I did have an issue once with a ' ' but only once.


    Bill M.
  • Jon

    Oh I do like it.
    You do seem to be picking this P2 stuff up quickly.
    Ok, wrpin is an interesting command, it's available in flexbasic, so now I have to find what values
    P_HIGH_FLOAT
    P_HIGH_1K5
    P_HIGH_1MA
    P_HIGH_15K
    are.

    Thanks

    Dave
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2020-12-18 20:22
    In Blink_v08.spin2 I am working with returning binary numbers
    from random() : Rnd function, and using it to drive an 8 bit led bus
    and then print the binary data to Parallax Serial Monitor.

    My problem is that I am using too many "new line" commands and
    I thought there must be a better way to format my serial output.

    Possibly using a binary formatted string?

    fstr2(p_str, arg1, arg2)

    %[w[.p]]b print argument as binary

    -- w is field width
    * positive w causes right alignment in field
    * negative w causes left alignment in field
    -- %ws aligns s in field (may truncate)
    -- %wc prints w copies of c
    -- p is precision characters
    * number of characters to use, aligned in field
    -- prepends 0 if needed to match p
    -- for %w.pf, p is number of digits after decimal point

    ? -32 = 11111111_11111111_11111111_11100000

    Thanks

    Bill M.
  • tritonium wrote: »
    Jon

    Oh I do like it.
    You do seem to be picking this P2 stuff up quickly.
    Ok, wrpin is an interesting command, it's available in flexbasic, so now I have to find what values
    P_HIGH_FLOAT
    P_HIGH_1K5
    P_HIGH_1MA
    P_HIGH_15K
    are.

    Thanks

    Dave

    Those constants are built in to the compiler, and should work in flexbasic as well as Spin
  • @"Capt. Quirk": Have a look at this version -- I think it does what you want very cleanly.
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2020-12-20 20:09
    Thanks Jon, that was very helpful.

    I am in the process of building a list of P1 v P2 differences, or has
    someone already made one??

    I have questions in the code comments about (%) (.) and why the endless
    loop trap?

    TY

    Bill M.
    pub main() | rn          ' term.fstr1(string("LEDs = %.8b\r"), rn)
    
      setup()
    
      wait_for_terminal(true)
    
     '' Neat Trick
     '' I thought it was broken
    
      repeat
      
        rn := prng.xrandom()            ' get random number
    
                   
    
        pinwrite(LEDS, rn)                                          ' write to LEDs
        term.fstr1(string("Leds = %.8b\r"), rn)                     ' write to terminal
    
    '' I figured out the obvious stuff in the formatted strings
    '' ("Statement (%) (.) Bit field-width Base-Binary Ascii commands")
    ''  What does (%) and (.) represent?
    ''  When % or . is removed, the formatting falls apart.
    
    ''  Or are % or . just mandatory symbols to format a string?
    
        waitms(1000)
    
    
      repeat
    
    '' I assume this is an error trap, what can happen if
    '' there is no trap?
    
        waitct(0)
    
    
    con { formatted strings }
    
    '' Is this part of the BS2 Debug?
    
    {{
        Escaped characters
    
          \\          backslash char
          \%          percent char  '' thought it meant binary
          \q          double quote
          \b          backspace
          \t          tab (horizontal)
          \n          new line (vertical tab)
          \r          carriage return
          \nnn        arbitrary ASCII value (nnn is decimal)
    
        Formatted arguments   %.8b\r
    
          %w.pf       print argument as decimal width decimal point
          %[w[.p]]d   print argument as decimal
          %[w[.p]]x   print argument as hex
          %[w[.p]]o   print argument as octal
          %[w[.p]]q   print argument as quarternary
          %[w[.p]]b   print argument as binary
          %[w]s       print argument as string
          %[w]c       print argument as character (
    
                      -- w is field width
                         * positive w causes right alignment in field
                         * negative w causes left alignment in field
                      -- %ws aligns s in field (may truncate)
                      -- %wc prints w copies of c
                      -- p is precision characters
                         * number of characters to use, aligned in field
                           -- prepends 0 if needed to match p
                           -- for %w.pf, p is number of digits after decimal point
    }}
    
    
    
    
    
  • JonnyMacJonnyMac Posts: 9,104
    edited 2020-12-20 21:20
    I put this
      repeat
        waitct(0)
    
    ...at the end of main() to prevent the Propeller from rebooting and running what's in EE or flash.
    Is this part of the BS2 Debug?
    No. I did my best to match formatted string control as used in other languages -- am open to changes. See attached from demo of formatted strings. I was recently re-reading the K&R and may need to review and update that formatting code. I haven't had any problems with it, and a couple of users have found it very handy.
    What does (%) and (.) represent?
    That forces the number to be zero-padded. Again, see the attached demo. Note that the demo uses the format %0.width, but you can leave out the leading 0 due to the way get_nargs() (get numeric arguments) method works.
  • Cluso99Cluso99 Posts: 18,069
    JonnyMac wrote: »
    Is this part of the BS2 Debug?
    No. I did my best to match formatted string control as used in other languages -- am open to changes. See attached from demo of formatted strings. I was recently re-reading the K&R and may need to review and update that formatting code. I haven't had any problems with it, and a couple of users have found it very handy.
    I have found it very handy indeed so many thanks Jon.

Sign In or Register to comment.