Shop OBEX P1 Docs P2 Docs Learn Events
Help with converting a single ended "pwmAsm" oblect to Differential mode — Parallax Forums

Help with converting a single ended "pwmAsm" oblect to Differential mode

SiriSiri Posts: 220
edited 2010-04-28 14:31 in Propeller 1
I am trying to modify - Jev Kuznetsov - "pwmAsm: oblect to work in the diffential mode.

Attached are the original object and my modification of the code and a test code that Iam using.

With the present modified code it only works like a single ended moe and not as a differential mode.

Please help me figure out what I am doing wrong.

Thanks.

Siri

Comments

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2010-04-15 00:10
    Did you shift sPinOutB left by 9 places and OR it into Ctra?

    sCtraVal := %00101 << 26 + PinA ' Differretial mode

    Where is PinB?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    *Peter*
  • SiriSiri Posts: 220
    edited 2010-04-15 14:27
    Peter,

    I am trying to set BPIN- tried the way you suggested and also tried using MOVD as suggested prop manual page 205.Still
    I am not able to set the the BPIN.

    I am still a very green at PASM - so please pont out to me where I am making the error.

    I have attached the modified "object" and the test code.

    Thanks for all your help.

    Siri
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2010-04-15 23:22
    Five parameters are passed to the PASM cog:
      long sDuty                     ' order important (the variables are read from memory in this order)
      long sCtraVal  
      long sPinOutA
      long sPinOutB
      long sPeriod
    
    



    Isn't all you need to do is to OR in PinB into the 9th bit position in sCtraVal? This also implies that sPinOutA and sPinOutB are redundant for the PASM function as those values can be ascertained from sCtraVal.
    sCtraVal :=  %00101 << 26 + PinA + PinB << 9  ' Differretial mode
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    *Peter*
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-16 00:16
    At the moment you're mixing up pin numbers and pin masks in PASM. You setup bPinOut as a mask which means it can only be applied to dira. In that form it can't be used for counter setup, shifted or otherwise. So change the counter setup as Peter suggested and merge aPinOut and bPinOut into a single mask (or extract that info from the counter setup).

    Post Edited (kuroneko) : 4/26/2010 7:49:45 AM GMT
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2010-04-16 00:57
    Sori Siri, I didn't look at your latest code when I replied earlier but looking at it now that our black cat friend has pointed it out then I concur with him. Don't mix up masks which are used for logical operations such as ORing etc while a bit index (or whatever you call it) can only specify a single bit and is normally used as a human friendly way of referring to that particular bit. In this case CTRA takes that bit index directly into it's S and D fields, so take care.

    As pointed out you have redundant information which you can optimize out later when you understand what is going on. For the moment, just get it working.

    4Fs: Functional first, fancy final.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    *Peter*
  • SiriSiri Posts: 220
    edited 2010-04-16 02:05
    Thank you very much - both of you helping me.

    Siri
  • SiriSiri Posts: 220
    edited 2010-04-24 23:09
    I was trying to write PASM codein the "pwmasmdiff" object to include the setting of the pwm differential mode in th PASM.
    I did that by Initializing the " ctraval long %00101 << 26 + pinOutA + pinOutB << 9".

    The object code now is:

    {{'' Pwm differential mode PASM
    
        usage : Object : "pwmDiff"
    
         pwm.start( PinA,PinB)               ' start pwm
         pwm.SetPeriod( period )       ' set pwm period in clock cycles
         pwm.SetDuty( duty)            ' set duty in %                               
         pwm.Stop
         
        CON
         
            _clkmode = xtal1 + pll16x                       ' clock &#8594; 80 MHz
            _xinfreq = 5_000_000
        
      
    }}
    
    Var
          long     cogon, cog
          long     aDuty
          long     abcd
          long     aApin 
          long     aBpin
          long     aPeriod
    
    
    
    
    
    PUB Start(Apin,Bpin): okay
    'start pwm on Pin @ 80 kHz
      longfill(@aDuty, 0, 5)       
      aDuty := 50                  'Default duty
      aApin := |< Apin
      aBpin := |< Bpin
      
      aPeriod := 1000               'default period
      
      okay := cogon := (cog := cognew(@entry,@aDuty)) > 0
    
    
    PUB stop
    
    '' Stop object - frees a cog
    
      if cogon~
        cogstop(cog)
      longfill(@aDuty, 0, 5) 
    
    PUB SetPeriod(counts)
    ' set pwm period in clock cycles, frequency = (_clkfreq / period)
       aPeriod := counts
    
    
    PUB SetDuty(counts)
       if (counts < 0)
         counts := 0
       if (counts > 100)
         counts := 100
       aDuty :=counts* aPeriod/100
    
    DAT
    'assembly cog which updates the PWM cycle on APIN
    
            org
    
    entry   mov     t1,par                'get first parameter
            rdlong  value, t1
    
             add    t1,#4
             mov  ctra, ctraval
             
            add     t1, #4
            rdlong  PinOutA, t1
            or      dira,pinoutA
    
            
            
            add     t1, #4
            rdlong  pinOutB,t1 
            or      dira ,pinOutB                'set BPIN to output
    
            
               
             add    t1,#4
             rdlong period,t1
    
            mov frqa, #1                   'set counter to increment 1 each cycle
    
            mov time, cnt                  'record current time
            add time, period               'establish next period
    
    :loop   rdlong value, par              'get an up to date pulse width
            waitcnt time, period           'wait until next period
            neg phsa, value                'back up phsa so that it  trips "value" cycles from now
            jmp #:loop                     'loop for next cycle
    
    '------------- [noparse][[/noparse] Initialized variables] -------------------------------------------
    
    ctraval     long   %00101 <<  26 + pinOutA + pinOutB << 9
    
    
    '-------------------------------------[noparse][[/noparse] Vaiables } ----------------------------------
    period    res 1                    
    time      res 1
    value     res 1
    t1        res 1
    pinOutA   res 1
    pinOutB   res 1
    
    
    




    The test code is :


    ''    Testing the "pwmAsmdif" object
    
    ''    *****   WORKING   ****** 04/22/10
    
    
    CON _clkmode = xtal1 + pll16x
        _xinfreq = 6_000_000          
        
        max_duty = 100
        pwmApin  = 24
        pwmBpin  = 25
    
    VAR '
         long parameter
      
    
    OBJ
      pwm  :  "pwmDiff"
      
    
    PUB go | x
      
      pwm.start(pwmApin,pwmBpin)
      
      repeat
        
        repeat x from 0 to max_duty 'linearly advance parameter from 0 to 100
          pwm.SetDuty(x)
          
          waitcnt(clkfreq/50 + cnt)   'wait a little while before next update
    
    



    In the object code I had to include a dummy variable " long adcd" and also this to the PASM code " add t1,#4
    mov ctra, ctraval"

    for it to work correctly.

    I have attempted to remove the variable -abcde and removing "add t1,#4 from PASM - then the code does not work. also changing the PASM code after deleting addt1,#4
    and changing the next code line to "add t1,#8" and this too does not work.

    From all the changes I came to the conclusion that the PASM declared /Initialized are read in specific order and which I cannot figure out.

    I am trying to learn PASM by looking and playing with PASM code others have written and trying yo understand.


    Please can you help me with this.

    Thanks

    siri

    The actual code is also attached.
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-25 00:36
    Siri said...
    I did that by Initializing the " ctraval long %00101 << 26 + pinOutA + pinOutB << 9".
    This doesn't do what you think it does. You are just really lucky that it worked at all in the first place. This expression uses the register index (not their values, which are masks, not pin numbers) for pinOutA and pinOutB in the equation. As mentioned before - by pure luck they happen to be 24 and 25, the same values you use in the demo.

    As a quick fix, change your code like this:
    • in VAR change long abcd to long ctraval (remove it from DAT)
    • in the start method add ctraval := %0_00101_000 << 23 | Bpin << 9 | Apin
    • change the 4th line in PASM to rdlong ctra, t1
  • SiriSiri Posts: 220
    edited 2010-04-25 15:10
    kuroneko,
    Thanks you very much for your help.You explanation helped me to better understand PASM and your suggestions worked well.

    I would like to write specially the PASM code to 1.set ctra register to differetial mode
    2.set APIN and BPIN - using MOVS and MOVD - this will teach how to set registers with PASM.

    Thanks

    Siri
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-26 01:04
    Siri said...
    I would like to write specially the PASM code to
    1.set ctra register to differetial mode
    2.set APIN and BPIN - using MOVS and MOVD - this will teach how to set registers with PASM.
    Have a look at the following code fragment. It should give you an idea about how to handle pin numbers and pin masks. There are usually several ways to reduce the size of the code later depending on how parameters are defined (CON vs VAR). But that's something you have to decide for yourself.

    VAR
          long     aDuty
          long     aApin 
          long     aBpin
          long     aPeriod
          
    PUB Start(Apin,Bpin): okay
    
      aDuty   := 50                 ' default duty
      aApin   := Apin               ' pin number
      aBpin   := Bpin               ' pin number
      aPeriod := 1000               ' default period
      
    DAT             org     0
    
    entry           mov     t1, par                 ' get r/w copy of parameter address
                    rdlong  value, t1               ' read aDuty
    
                    add     t1, #4                  ' address of aApin
                    rdlong  PinOutA, t1
            
                    add     t1, #4                  ' address of aBpin
                    rdlong  pinOutB, t1        
               
                    add     t1, #4                  ' address of period
                    rdlong  period,t1
    
    ' now setup the counter
    
                    movi    ctra, #%0_00101_000     ' NCO differential
                    movd    ctra, PinOutB           '
                    movs    ctra, PinOutA           ' insert pin numbers
    
    ' enable the outputs in dira (converts pin numbers to pin masks)
    
                    mov     t1, #1
                    shl     t1, PinOutB             ' 1 << aBpin (pin mask)
                    or      dira, t1                ' activate
    
                    mov     t1, #1
                    shl     t1, PinOutA             ' 1 << aApin (pin mask)
                    or      dira, t1                ' activate
    
    ' enable counter
    
                    mov     frqa, #1                ' set counter to increment 1 each cycle
    
    ' remaining code
    
    t1              res     1
    PinOutA         res     1
    PinOutB         res     1
    
    value           res     1
    period          res     1
    
                    fit
    
  • SiriSiri Posts: 220
    edited 2010-04-26 17:16
    Kuroneko,

    Thank you very much for your help.

    I do not understand the following code lines.

    '·enable·the·outputs·in·dira·(converts·pin·numbers·to·pin·masks)

    ··············"·"·mov·····t1,·#1""
    ················shl·····t1,·PinOutB·············'·1·<<·aBpin·(pin·mask)
    ················or······dira,·t1················'·activate

    ···············""·mov·····t1,·#1""
    ················shl·····t1,·PinOutA·············'·1·<<·aApin·(pin·mask)
    ················or······dira,·t1················'·activate



    t1 was initially used to write PAR register followed by adding #4 to grt the address of Duty then Apin,Bpin etc. and since last code t1 was used to get period.Does t1 at this point has some value or does it has no value or is it only the pointer which does not retain any value at any time.

    ·I do uderstand "shl and or " in the code.

    So if you can explain to me "mov t1,#1" this code line - the logic behind it.

    Thanks for your patience and help.

    Siri
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-27 01:01
    Siri said...
    t1 was initially used to write PAR register followed by adding #4 to grt the address of Duty then Apin,Bpin etc. and since last code t1 was used to get period.Does t1 at this point has some value or does it has no value or is it only the pointer which does not retain any value at any time.

    I do uderstand "shl and or " in the code.

    So if you can explain to me "mov t1,#1" this code line - the logic behind it.
    You are correct, t1 was last used to get the period parameter/argument. It therefore holds the hub address of period at this point. Once we read the value from the hub we don't need the address anymore, which means t1 can be used for something else. Note that registers in the cog can't not have a value. There is always something in there, you could say that they are undefined or unintialised though.

    So what's with that funny mov t1, #1? So far we got the pin numbers (e.g. 24 and 25) from the hub and inserted them into ctra. Now we still need the bit mask to enable those bits in dira. This is done by shifting a 1 left by the required number of bits, i.e. 1 << 24 and 1 << 25. The shl instruction takes the value to be shifted in the destination slot, the amount in the source slot. So

    shl t1, PinOutB
    


    will take whatever is in t1 and shift it left by the amount specified in the lower 5 bits of PinOutB. The destination slot can't take immediate values like #1, meaning shl #1, PinOutB doesn't work. So we have to preload a temporary register - in this case t1 - with 1, which is where the mov t1, #1 comes in. Let's have a look at the content of t1:

    '                                                                            content of t1
    '                                                                            hub address of period
                    mov     t1, #1                                               1
                    shl     t1, PinOutB             ' 1 << aBpin (pin mask)      1 << aBpin
                    or      dira, t1                ' activate                   1 << aBpin
    
                    mov     t1, #1                                               1
                    shl     t1, PinOutA             ' 1 << aApin (pin mask)      1 << aApin
                    or      dira, t1                ' activate                   1 << aApin
    
    


    So let's say for a moment we remove both mov t1, #1 instructions. What happens is that hub address of period which is still held in t1 is shifted left by aBpin, e.g. $3C8 << 25 which is $9000_0000 (as we only have 32 bits the overflow disappears). Which means bits 31 and 28 get set in dira. Subsequently this value is shifted left by aApin, e.g. $9000_0000 << 24 which results in $0000_0000. No further change to dira. Whatever the resulting value is, it's not what we wanted. We need bits 25 and 24 set. Let's re-introduce the move instructions. The first shift will then perform 1 << 25 ($0200_0000), the second one 1 << 24 ($0100_0000). Both get OR'd into dira which - as it starts empty - will then hold $0300_0000 (i.e. bits 24 and 25 set as outputs).

    Basically, the only reason for the move instructions is to get the required 1 (value to be shifted) into a register.
  • SiriSiri Posts: 220
    edited 2010-04-27 15:02
    Kuroneko,

    Thank you very much.Now it is crystal clear to me except for this explaination :

    "The first shift will then perform 1 << 25 ($0200_0000) and 1<< 24 ($0100_0000)

    In my mind "t1" would be - % 00000000_00000000_0000000_00000001 --> prior to shift

    % 00000010_00000000_00000000_00000000 -->after shift (1 <<25)

    % 00000001_00000000_00000000_00000000 ---> after sfhift (1 <<24)

    Dira register
    > % 00000000_00000000_00000000_00000000 --- prior to "OR"

    after first OR dira ---> %00000010_00000000_00000000_00000000

    after 2nd OR dira ---> % 00000011_00000000_00000000_00000000 ----> pin 24 nad 25 set "Out-put"

    Where did $ 0200_0000 and $ 0100_0000 come from?

    Siri

    p.s - You are a good teacher.

    Post Edited (Siri) : 4/27/2010 10:33:41 PM GMT
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-28 00:40
    Siri said...
    Where did $0200_0000 and $0100_0000 come from?
    Both are the same as your binary numbers just that the $ notation is hexadecimal. Each digit represents a 4 bit number (0..9, A..F). So $0200_0000 is just another way of saying %00000010_00000000_00000000_00000000. Also, have a look in the manual, SPIN Language elements, Value Representations (p.45).

    $0200_0000
     |||| ++++---------+
     |||+---------+    |
     ||+------+   |    |
     |+--+    |   |    |
     |   |    |   |    |
     +--++--+ +--++--+ +---------------+
    %00000010_00000000_00000000_00000000
    
  • SiriSiri Posts: 220
    edited 2010-04-28 14:31
    Kuroneko,

    Thank you very much.

    I did look at your Hex notations and tried converting them to Binary using the conversion tables

    and they did not make any sense.That was the reason to I posted that again.

    I learned some basic facts I need to know.

    Thank you very much.

    Siri
Sign In or Register to comment.