Shop Learn
P2 Tricks, Traps & Differences between P1 (general discussion) - Page 9 — Parallax Forums

P2 Tricks, Traps & Differences between P1 (general discussion)

145679

Comments

  • jonabel1971jonabel1971 Posts: 184
    edited 2020-08-26 22:01
    I did that. I added a temp3 variable & listed with the other temp variables.

    Then I wrote this - but it didn't seem to fix my scope output.
    mov      temp3, temp
                  xor      temp3,    #UpdateTonToff wz',nr    ' Check Ton/Toff  
             if_z jmp      #_Update_TonToff
    
  • jonabel1971jonabel1971 Posts: 184
    edited 2020-08-26 22:35
    All my arrays appear to be holding good data, but whatever PWM_32 is doing with it, my scope doesn't show a signal.

    I will potentially have to pull out my old P1 board, and see if the original code works correctly. I've never actually tested it.
    1276 x 630 - 134K
  • Time to attach the assembly code, I guess.
    When called - it appears to be receiving good data from my arrays.

    I have tried a wide range of frequencies (60 to 78125 Hz) , but my scope doesn't get an output signal.
  • What is NOP used for in P1 code? Since there is no "real equivalent" for the P2, I am unsure what I can do to remove/replace this code.

  • Cluso99Cluso99 Posts: 17,970
    edited 2020-08-27 21:05
    There is a NOP in P2. It is in fact a ROL 0,0 ??? of all $00000000. You just cannot change the conditional cccc=%0000.

    BTW Be aware, nop in the P1 was often done to ensure the setting on bits in a following instruction with movs/movd/movi or other similar things needed a delay. This delay is longer in P2 so you will need more nop’s or a wait n instruction.
  • Cluso99 wrote: »
    There is a NOP in P2. It is in fact a ROL 0,0 ??? of all $00000000. You just cannot change the conditional cccc=%0000.

    BTW Be aware, nop in the P1 was often done to ensure the setting on bits in a following instruction with movs/movd/movi or other similar things needed a delay. This delay is longer in P2 so you will need more nop’s or a wait n instruction.

    So, if I create a dummy variable called temp, and add zero to it 2-3 times - is that equivalent to a NOP on the P2? I am converting P1 code, this is why I ask. How many dummy ADDS are equivalent to a P2 NOP?
  • Cluso99Cluso99 Posts: 17,970
    No. Just use the NOP instruction on the P2.

    Where you see a NOP on P2 you need to look at the code surrounding it to see why a NOP was used because you may need more than one NOP in P2,
  • But, I don't know what I am looking for.
  • I also noticed that I had to move the "org" call before the "PWM_Asm" symbol location in the assembly code.
    The following P1 code runs correctly, but gives the error "This directive cannot be proceeded by a symbol" when compiled for the P2.

    Would this change have an effect on the program?
    PWM_Asm       org
    
                  mov      temp, par
                  mov      cmd_address, temp        'Acquire command variable address
                  add      temp,    #4  
                  mov      ARG_0, temp              'Acquire ARG_0 variable address
                  add      temp,    #4  
                  mov      ARG_1, temp              'Acquire ARG_1 variable address
                  add      temp,    #4
                  mov      ARG_2, temp              'Acquire ARG_2 variable address
    
  • evanhevanh Posts: 11,856
    edited 2020-08-28 22:00
    That was probably a bug in the original prop1 source code. ORG, or ORG 0, as a pasm2 directive (presumably the same for pasm1) will reset the assembling referencing to zero at that point.

    When executing code, certain instructions use absolute addressing - either via "immediate" encoding into the instruction itself, or via "register direct" encoding in another general register. To make the encoding of these addresses suited to that, ORG is used to tell the assembler the origin you are wanting.

    So the next symbol, or instruction, after the ORG will be treated as address zero - this is the start of cogRAM. It's often used with COGINIT - which copies the binary code from somewhere in hubRAM to the start of cogRAM - so now the assembled code is suited to the actual use.

    PS: ORG on the propellers is specifically a cogRAM directive. ORGH is used for hubRAM and works in a slightly different manner.

  • Yeah, I don't really know enough to go that deep yet.

    I have been testing my P1 board with the old PWM_32.spin code.
    I am finding that my P1 is potentially capable of doing what I want the P2 to do.
    However, I have to call PhaseSync() extra times for every increase in frequency - otherwise it sweeps. I can't just call it once.
  • I might be overthinking this. If all my frequencies are 4x each other, all I need to do is make sure they are synchronized to start at the same time. Phasing by 0, 90, 180, and 270 will all give the same signal phase. It's the same shift at each point, since 1 frequency is 1/4 of the next.

    So, how do I synchronize my original P2 code frequencies? I potentially don't need to phase.

    The call I am making for each frequency is
    pinstart(pin, P_OE | P_NCO_FREQ | P_SYNC_IO, 1, fr01 frac clkfreq)
    
  • The math just looks different if using sine waves instead of pulses.
    To get sine waves to start at the same time:

    y1 = 1+ sin(x)
    y2 = 1- cos(4x)

    However, with a microcontroller, I just need to start the pulses at the same time.
    Is this possible?
  • Ah HA! You figured it out. You might note @Ariba gave you the answer a week ago on the closed thread:

    “ ...2) What do you mean by 'phasing' or by a phase of 270°. You can only have a phase shift between two signals with the same frequency. One can be shifted by 270° in respect to the other, but there is no absolute phase, or a certain phasehift for signals with different frequencies....”

    After this, we then we went another step and gave you fully working code. You might want to swallow your pride and download the code I posted. Its the answer you seek. Fully functional. Happy to give it to you. For free. The “crippled” part was only “crippled” because you simply cant phase-shift two signals not of the same frequency.

    When you are ready to run your Impenetrable Plasma Barrier, ask nicely and ye shall receive full source code. Its written in FlexBASIC. No assembly needed. IT IS READY TO MAKE A PLASMA BARRIER THE MOMENT YOU RUN IT. Nothing is “crippled”. You simply hadnt had your “AH HA!!!” moment yet.

    Btw: the next “ah ha!” moment is simply starting all the smart pins at once. You can do it with one command. And yes, they will stay phase-locked once started. See the demo...
  • jonabel1971jonabel1971 Posts: 184
    edited 2020-08-31 18:43
    1. I am looking for a SmartPin command allowing synchronization of pin frequency phases - due to an issue of sweeping phases between all channels. Does anyone know a Sync command that works with Smartpins?

    I have another issue that may benefit from it:

    P_PWM_SAWTOOTH does not generate frequencies lower than 20 Hz.

    With a Sync command - this might allow me to build in some a 1-20 Hz frequency generator without using cogs. But, potentially, I need more information.

    2. If a Sync command DOESN'T allow straight-forward frequency creation - then P_NCO_FREQ & P_NCO_DUTY are the only smartpin commands that mention storage of phase information in z[15..0]. But, there are no examples on the discussion threads - or P2 documentation that show how they work.

    3. Regardless, my attached code now has working DutyCycle for all 54 channels - using the PWM_SAWTOOTH command. All that is needed is syncing & some lower frequencies (1-20 Hz) at this point.

    The PWM_TRIANGLE command gave me half the frequency I wanted, but still kept sweeping the phase, so I didn't see the benefit.
    x.word[1] := 255
            
            x.word[0] := 1 #> ((clkfreq / 255) / FrequencyArray[temppin]) <# $FFFF
            pinstart(temppin, P_OE | P_PWM_SAWTOOTH | P_SYNC_IO, x, DutyCycles1[temppin] * 255 / 100)
    

  • jonabel1971jonabel1971 Posts: 184
    edited 2020-08-31 17:06
    I forgot to post the needed signal. It appears my frequencies CAN start at the same time (no phase needed either way), but this output is created after multiple frequencies travel through multiple coils.

    So, for now - I need a syncing command for SmartPins, and a way to create frequencies lower than 20 Hz. Phasing will be potentially be needed at some point, but I cannot see that far ahead yet - and examples of how to do it are not forthcoming.
    1008 x 630 - 129K
  • AribaAriba Posts: 2,524
    You can sync the outputs of some smartpins by starting them at the same clockcycle. A smartpin gets started when the DIR bit goes high, so you need to raise all the DIR bits of the group at the same time, and the frequencies must be an exact multiple of 4.

    Here is a new version of the methode that sets the smartpins. I have it not tested, but something like that may work.
    pub fillset(tempset) | i,x,y       
            
            tempchannel := 1
            temppin := (tempset - 1) * 6 + tempchannel
            
            repeat i from 0 to 5
               x := clkfreq / FrequencyArray[temppin+i]              'periode in ticks
               y := x>>16 + 1                                        'handle overflow ( > $FFFF)
               x := (x / y)<<16 + y                                  ' by adjusting base period
               y := x.word[1] * DutyCycles1[temppin+i] / 100         'pulswidth from % to ticks
               pinsetup(temppin+i, P_OE | P_PWM_SAWTOOTH, x, y)      'configure smartpin, but don't start it yet
            
            pinl[temppin addpins 5]                                  'start all smartpins of the group at the same time (synced)
    
    The lowest frequency a smartpin can generate is clkfreq / 2^32, which is 0.7 Hz at 300 MHz clock.

    Andy
  • jonabel1971jonabel1971 Posts: 184
    edited 2020-08-31 22:30
    [Removed]

  • jonabel1971jonabel1971 Posts: 184
    edited 2020-08-31 23:03
    I just tested this. Frequencies start at the same time, but phase sweeping is still occurring.

    What causes this sync code to only work for frequencies 4x from each other?
    That seems ironically coincidental, since that's what I ultimately needed.

    However, I would like the flexibility to change 1 frequency.
  • jmgjmg Posts: 14,820
    I just tested this. Frequencies start at the same time, but phase sweeping is still occurring.

    You need to give more info - what exactly does 'phase sweeping' mean - how quickly is the phase sweeping ?
    Keep in mind that NCO frequencies are approximations, and will only be precise when the adder values 'fit' exactly into 2^32.
  • That also fixed the 20 Hz limit. Now it appears to go down to at least 1 Hz.
    Thanks twice!

    Just the phase sweep left. Posting an update now, since I need to leave the library.
  • AribaAriba Posts: 2,524
    I just tested this. Frequencies start at the same time, but phase sweeping is still occurring.

    What causes this sync code to only work for frequencies 4x from each other?
    That seems ironically coincidental, since that's what I ultimately needed.

    However, I would like the flexibility to change 1 frequency.

    It does not only work at 4x frequencies, but I thought that's what you want. The value in the higher word of x defines the periode in (base-)clock cycles. If one period-value is 1000 and another 4000 then they stay in sync if they started together. The first will do 4 periodes while the second does one, but if there is an exact multiple the 2 frequencies don't drift.
    If you calculate it by frequency, there is always the possibility that rounding errors at division results not in a exact ratio for the resulting periodes.
    So it's best to calc the period for the highest frequency and then multiply this periode value with 4, 16, 64 or what you want, for lower frequencies.

    @jmg This is not NCO, it's PWM mode with a periode count.
  • I see.

    I will see if I can update to nanoseconds instead of microseconds - for storing periods.
    Maybe that will fix the issue.

    I also noticed that my 20 Mhz & 80 Mhz no longer worked (now they are displaying a sine wave?).
    Not sure why. I will work on my resolution issues.
  • ElectrodudeElectrodude Posts: 1,440
    edited 2020-09-01 16:58
    I will see if I can update to nanoseconds instead of microseconds - for storing periods.
    Maybe that will fix the issue.
    You have to do it in NCO units - not nanoseconds or microseconds or anything else convenient. Unless the NCO values are all precise powers of two, it won't work - you'll get the phase problems you've been having. Try some of the code others such as Ariba or JRoark have offered you.
  • I tried dividing down from the highest frequency (/4) instead of multiplying up x4.
    I also got my tick values correct now & periods down to nanoseconds.
    I have been testing with numbers that divide down evenly by 4 into whole numbers.

    However, this does not solve the phase sweeping issue. Code & Output is attached.
    if (channelprompt == 9)
              repeat Channel from 1 to n
                 PinValue1 := (((defaultset - 1) * 6) + (7-Channel))
                 Periods1[PinValue1] := (1000000000 / defaultfrequency)     ' 1 clocktick = 3125 picoseconds 
                 TotalTicksTemp := (_clkfreq / defaultfrequency)
    
                 FrequencyArray[Pinvalue1] := defaultfrequency             
                 DutyCycles1[Pinvalue1] := duty  
                 Phase[Pinvalue1] := phase1
                              
                 TotalTicks[Pinvalue1] := TotalTicksTemp        
                 TimeOn[PinValue1] := (Periods1[PinValue1] * duty) / 100              ' in nanoseconds
                 TimeOff[PinValue1] := (Periods1[PinValue1] * (100 - duty) / 100)     ' in nanoseconds
                 
                 OnTicks[Pinvalue1] := (TotalTicks[PinValue1] * duty) / 100              ' 1 clocktick = 3125 picoseconds
                 OffTicks[Pinvalue1] := (TotalTicks[PinValue1] * (100 - duty)) / 100
    
                 PhaseTime[PinValue1] := (Periods1[PinValue1] * Phase[PinValue1]) / 360     ' conversion from degrees to nanoseconds
                 PhaseTicks[PinValue1] := (TotalTicks[PinValue1] * Phase[PinValue1]) / 360 ' conversion from degrees to clockticks
    
                 FrequencyEnabled[Pinvalue1] := 1
                 defaultfrequency /= 4
                 TotalTicksTemp /= 4
    
              repeat Channel from 1 to n
                 PinValue1 := (((defaultset - 1) * 6) + Channel)
                 term.fstr5(string("Frequency: %d   Period: %d ns  TotalTicks: %d  TimeOn: %d ns TimeOff: %d ns\r"), FrequencyArray[PinValue1], Periods1[PinValue1], TotalTicks[PinValue1], TimeOn[PinValue1], TimeOff[PinValue1])
                 term.fstr5(string("OnTicks: %d   OffTicks: %d   PhaseTime: %d ns PhaseTicks: %d  Duty: %d\r"), OnTicks[PinValue1], OffTicks[PinValue1], PhaseTime[PinValue1], PhaseTicks[PinValue1],DutyCycles1[PinValue1])
                 term.fstr2(string("Pinvalue:  %d Phase: %d degrees\r"), PinValue1, Phase[PinValue1])
                 term.fstr5(string("Set: %d   Channel: %d   Frequency: %d Hz  DC: %d  Phase: %d degrees\r\r"), defaultset, Channel, FrequencyArray[PinValue1], DutyCycles1[PinValue1],Phase[PinValue1])
    
    
    1315 x 938 - 317K
  • AribaAriba Posts: 2,524
    Try this methode to set up the smartpins. The highest fequency must always be defined at channel 0 of the set, then the other frequencies will be calculated to have an exact ratio.
    pub fillset(tempset) | i,x,y,p       
            
            tempchannel := 1
            temppin := (tempset - 1) * 6 + tempchannel
            p := clkfreq / FrequencyArray[temppin]                   'periode in ticks for highest frequency (channel 0)
            
            repeat i from 0 to 5
               x := p * ((FrequencyArray[temppin] / FrequencyArray[temppin+i]) #> 1)     'periode in exact multiples of channel 0
               y := x>>16 + 1                                        'handle overflow ( > $FFFF)
               x := (x / y)<<16 + y                                  ' by adjusting base period
               y := x.word[1] * DutyCycles1[temppin+i] / 100         'pulswidth from % to ticks
               pinsetup(temppin+i, P_OE | P_PWM_SAWTOOTH, x, y)      'configure smartpin, but don't start it yet
            
            pinl[temppin addpins 5]                                  'start all smartpins of the group at the same time (synced)
    
  • This thread has run completely off the rails.
  • Thanks Ariba, I will try that.

    Alexander,
    If the moderators want me to move to a new thread (Publison or VonSzarvas)- then all they need to do is be willing to stop the abuse, baiting & tag-teaming from others on the threads (including JRoarke, JonnyMac, Phil Pilgrim, etc.)
  • Cluso99Cluso99 Posts: 17,970
    @jonabel1971,
    Please don’t hijack other threads to discuss your designs. You have your own threads for that.

    This thread, as indicated in the original post, is to discuss tricks and traps, and differences between P1 and P2.

    Thanks.
Sign In or Register to comment.