Shop Learn P1 Docs P2 Docs Events
P1 to P2 Migration — Parallax Forums

P1 to P2 Migration

I was very adept at P1 in Spin and Pro C.
Since many of you are "professionals" in coding at a very high level. It was easy for you to over the years of the inception of the P2 to create wonderful code. Now this leaves the others who are novices so to speak to jump right in or migrate over. The P2 is so powerful that it can be overwhelming. Kudos to @cgracey.
Now I would like to start a thread where we can take simple code from the P1 and migrate to the P2.
@JonnyMac wrote a thread that started a P1 to P2

I followed the code instrctions but the code did not work. Not his fault. I will post later.
I think that it would be benificial to all if we can and as I will attemp to do, follow the PE kit documentation and move forward with a manual for the newbies.
I will be using the from the beginning code and moving forward, one the issues is the counters from the P1. I know that the P2 does not have cogs that we can program. Alas as we say in French, tampi pour nous, they were easy to use.
I will move slowley though the code and will need some assistance.
I would like to stay in SPIN to start then move to P2asm slowly to really teach the two. I was able to get through the basics of P1asm as assembly language is really not taught in the colleges any more.
We are on our own.

So I wish that we can start with the first chapter that I will post shortly with my P1 code and the direct translation of P2 code and ad later the P2 pins in a manner that we can all underatand.
Comments are pleased welcome.


  • BTW
    I would like to re write the PE manual with your help.

  • JonnyMacJonnyMac Posts: 8,612

    Suggestion: One-by-one, put up examples from the PE book and ask others to contribute their P2 version. You will get different approaches that will be successful. From those, you can synthesize what you think is best and then document that code for beginners.

    Personally, I have found moving to the P2 very easy, with the exception of losing the cog timers; I have many P1 projects that use simple timers and those take a little more effort to deal with in the P2. If you thought P1 PASM was easy, boy are you going to love P2 PASM. Yes, a lot more instructions, but many of them replace two or more instructions that were needed in the P1. And with inline PASM in the P2, it's really easy to learn by testing little snippets of code -- no additional cog required.

    Basics of P1 --> P2

    • save the file with .spin2 extension
    • add empty () to methods that don't take parameters
    • explicitly name the return variable for any method that returns a value (empty returns don't need this)
    • look for opportunities to replace P1 libraries with new P2 features (e.g., I have jm_io.spin and jm_time.spin for P1; Spin2 covers the most used features of these libraries).

    I wrote a Python program that will scan a P1 listing and give me suggestions on things to fix and a hint on how to do it. I have posted that in the forums. Some of the work is grunt work. I tend to use Propeller Tool so I press F9 to compile fix and error and move on. If using Spin Tools (from @macca) it does a constant compile process so you can click on the yellow and red tags to fix as you go. In the end, there's no magic bullet, you just have to slog through. You also have to prepare for going back later and realizing that you've learned something new about the P2 that will make your code better. Always be willing to update your code.

  • JonnyMacJonnyMac Posts: 8,612
    edited 2023-05-20 16:36

    Okay, I'll start. This is how I would translate the first program which changes the flashing rate of LEDs based on the state of a button.

    I'm a a bit of a stickler for clean, professional programming style -- even for simple test programs like this. The problem I have with the author's approach in the PE Kit is -- in his words -- much of it is quick and dirty. My contention is that it's never quick, and it's nothing but dirty. The PE Kit teaches bad habits that can cause problems, especially as programs grow more complex.

    My rules

    • Start with a template
    • Define IO pins and IO states (no magic numbers!)
    • Keep code neat and tidy
    • Add comments for clarity (do not state the obvious)
  • RaymanRayman Posts: 13,154

    The good news is that Spin2 seems stable now. Been hard to deal with code that is constantly changing…

  • I was working with the outa.[ ], the pin toggle and other combinations.
    Noted that using pintoggle(0..1) toggles all of the lower 32 pins.
    Tried pinhigh and pinlow got the same.
    dira and outa with the period and only get the second pin.
    Ref: Page 56 in the PE manual and page 10 of the Spin two documentation.
    What is the correct syntax.
    Thank you in advance.

  • RaymanRayman Posts: 13,154

    It's easy to mess up with pinfield and bitfields in Spin2.
    your problem might be having the lower number first.
    Think needs to be pintoggle(1..0)

  • JonnyMacJonnyMac Posts: 8,612
    edited 2023-05-31 02:01

    Attempting a direct/rote translation of P1 to P2 code is 1) not going to work in many cases, and 2) fails to take advantage of P2 features. We are forced to use outa[] and dira[] in the P1 because there are no high-level IO commands in Spin1. This is not true of Spin2, which also has two sets of IO registers to deal with (a group and b group) which can make things confusing unless the high-level commands are employed. The P2 outa[] and outb[] registers don't allow ranges like in Spin1 (this may be something for Chip to flag as an error). The only way I was able to get that syntax to work is like this:

      outa := %100001 << 4
      dira := %111111 << 4

    This writes to the pins but clears everything else (no isolation of LED group without more code). Why do this to a newbie when the P2 has nice, pin-centric IO functions?

    This is how I would merge those to programs while keeping with my persnickety rules about writing clean code from the jump.

    con { app io pins }
      LED06    = 09  { O }
      LED05    = 08  { O }
      LED04    = 07  { O }
      LED03    = 06  { O }
      LED02    = 05  { O }
      LED01    = 04  { O }
      LEDS     = LED01 addpins 5                                    ' use LED01..LED06  
    pub main()
    pub blink_v1()
      pinwrite(LEDS, %100001)
      pinwrite(LEDS, %011110)
    pub blink_v2()
      repeat 2

    Bear in mind, there are a few areas where the P1 has advantages (like the ranges in [] brackets), but overall, Spin2 is cleaner. Reverse engineering is not about copying, it's about applying intent in a new system.


    • If you see outa[x..y] := in a P1 program, replace it with pinwrite(x addpins z) in the P2
    • If you see !outa[x..y] in a P1 program, replace it with pintoggle(x addpins z) in the P2

    z = MSBpin - LSBpin - 1. Again, the P1 has a bit of an advantage here because P2 pin groups are always from the LSB upward. To reverse output bits in the P1 we can do this:

       outa[LSB..MSB] := value

    To reverse the bit order in the P2 we would have to do this:

      pinwrite(pingroup, value rev width)

    pingroup = LSB addpins (MSB - LSB - 1)
    width := MSB - LSB + 1

  • JonnyMacJonnyMac Posts: 8,612
    edited 2023-05-31 13:17

    I had a coffee break and found this is as close to rote as I could get the program -- but this is STUPIDLY UNFRIELDLY (as is the original P1 code). Note that in the P2 syntax you must use dot notation for the bit group, and the order of the bit group must be MSB..LSB (as Ray suggested).

    pub main()
        outa.[9..4] := %100001                                      
        waitct(clkfreq/4 + getct())                                 
        outa.[9..4] := %011110
        waitct(clkfreq/4 + getct())

    In the P2, using the ! (bang) syntax works like this:

    pub main()
      outa.[9..4] := %100001     
        != outa.[9..4]                              
        waitct(clkfreq/4 + getct()) 

    These programs work, but make the P2 and Spin2 look scary -- and that's not necessary given the Spin2 pinxxx() and waitxx() functions.

  • RaymanRayman Posts: 13,154

    The other interesting mistake is in Jon's thread:

    Where @Ariba pointed out that outb.[56] does not do what you might expect.

  • JonnyMacJonnyMac Posts: 8,612
    edited 2023-06-01 04:00

    That was a good catch by Andy -- as he so often does. It also demonstrates another reason not to use IO registers in Spin2 when simple IO commands are available. Pin groups and bit groups can be tricky.

    Note that thread is from the early days of Spin2 (but still a mistake on my part).

Sign In or Register to comment.