Shop OBEX P1 Docs P2 Docs Learn Events
Send number of pulses with delay time using propeller hardware counter — Parallax Forums

Send number of pulses with delay time using propeller hardware counter

propcogpropcog Posts: 4
edited 2014-10-01 07:32 in Propeller 1
Hi,

I'm a newbie propeller user and a want to use the P8X32A for pulse generation.
When I run my code a counter is producing a number of PWM pulses with adjustable frequency and duty-cycle and waits a couple of mSec and starts again.

Problem is when it's restarting the counter it generates a pulse, after the count has reached max number of pulses and then waits... why is this happing?

Is it possible to insert a delay-time between the PWM hardware counter generator?

Thanks for your time,
Regards!
CON _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000             ' CHECK THIS!!!

    pwm1pin  = 16
    pwm2pin  = 17
    
VAR long parameter
  

OBJ
  pwm1  :  "pwmasm"
  
PUB go | x

  pwm1.start(pwm1pin)
  pwm1.SetFreq(2)
  pwm1.SetDuty(50)
  pwm1.SetGatePulses(2)
  pwm1.SetGatePeriodms(1000)

-------------------
{
 usage

 OBJ
        pwm : pwmAsm

  ....

  pwm.start( Pin)               ' start pwm
  pwm.SetPeriod( period )       ' set pwm period in clock cycles
  pwm.SetFreq( freq )           ' set pwm frequency in Hz
  pwm.SetDuty( duty )           ' set duty in %                               
  pwm.SetGatePulses( pulses )   ' set number of pulses
  pwm.SetGatePeriod( period )   ' set waittime next start of pulses after mSec
  pwm.Stop

}
VAR
  long  cogon, cog  
  long sDuty                     ' order important (the variables are read from memory in this order)  
  long sPinOut 
  long sCtraVal
  long sPeriod
  long sGatePulses
  long sGatePeriod

  
PUB Start( Pin) : okay
'start pwm on Pin
  longfill(@sDuty, 0, 4)       
  sDuty := 50                   ' default duty
  sPinOut := |< Pin   
  sCtraVal := %00100 << 26 + Pin
  sPeriod := 1000
  sGatePulses := 2
  sGatePeriod := 40000000
  
  okay := cogon := (cog := cognew(@entry,@sDuty)) > 0    
  
PUB stop

'' Stop object - frees a cog

  if cogon~
    cogstop(cog)
  longfill(@sDuty, 0, 4) 

PUB SetPeriod(counts)
' set pwm period in clock cycles, frequency = (_clkfreq / period)
   sPeriod := counts

PUB SetFreq( freq )
sPeriod := clkfreq / freq * sDuty  / 100

PUB SetDuty(counts)
   if (counts < 0)
     counts := 0
   if (counts > 100)
     counts := 100
   sDuty :=counts*sPeriod/100

PUB SetGatePulses(counts)
' set pwm period in clock cycles, frequency = (_clkfreq / period)
   sGatePulses := counts
   
PUB SetGatePeriod(counts)
' set pwm period in clock cycles, frequency = (_clkfreq / period)
   sGatePeriod := counts

PUB SetGatePeriodms(msec)
   sGatePeriod := 80_000_000 / 1000 * msec
      
DAT
        org

entry   mov     t1,par          'get first parameter
        rdlong  value, t1
         
        add     t1,#4                 
        rdlong  pinOut, t1
        or      dira, pinOut    ' set pinOut to output      

        add     t1, #4
        rdlong  ctraval, t1
        mov ctra, ctraval       'establish counter A mode and APIN

        add     t1, #4
        rdlong  period, t1

        add     t1, #4
        rdlong  gpulses, t1

        add     t1, #4
        rdlong  gperiod, t1        

        mov frqa, #1            'set counter to increment 1 each cycle

        mov time, cnt           'record current time
        add time, period        'establish next period
        mov tmp, #0
        mov ctra, ctraval
        
:loop   rdlong value, par       'get an up to date pulse width
        waitcnt time, period    'wait until next period
        cmp tmp, gpulses wz
   if_e mov ctra, #0
   if_e mov tmp, #0
   if_e waitcnt time, gperiod
   if_e or outa,#0
   if_e mov ctra, ctraval        
        neg phsa, value         'back up phsa so that it  trips "value" cycles from now
        add tmp, #1
        jmp #:loop              'loop for next cycle

period  res 1                    
time    res 1
value   res 1
t1      res 1
pinOut  res 1
ctraval res 1
ctraoff res 1
gpulses res 1
gperiod res 1
tmp     long 0

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2014-09-30 05:12
    What are the calling parameters, i.e. can you post your SPIN part as well? Also, could you elaborate on restart and then waits?
  • propcogpropcog Posts: 4
    edited 2014-09-30 05:27
    kuroneko wrote: »
    What are the calling parameters, i.e. can you post your SPIN part as well? Also, could you elaborate on restart and then waits?
    Hi kuroneko,

    When the number of pulses are done I stop the counter and wait a couple of mSec, the I restart the counter. Don't know if this is the right approach??

    Regards!
    CON _clkmode = xtal1 + pll16x
        _xinfreq = 5_000_000             ' CHECK THIS!!!
    
        pwm1pin  = 16
        pwm2pin  = 17
        
    VAR long parameter
      
    
    OBJ
      pwm1  :  "pwmasm"
      
    PUB go | x
    
      pwm1.start(pwm1pin)
      pwm1.SetFreq(2)
      pwm1.SetDuty(50)
      pwm1.SetGatePulses(2)
      pwm1.SetGatePeriodms(1000)
    
    {
     usage
    
     OBJ
            pwm : pwmAsm
    
      ....
    
      pwm.start( Pin)               ' start pwm
      pwm.SetPeriod( period )       ' set pwm period in clock cycles
      pwm.SetFreq( freq )           ' set pwm frequency in Hz
      pwm.SetDuty( duty )           ' set duty in %                               
      pwm.SetGatePulses( pulses )   ' set number of pulses
      pwm.SetGatePeriod( period )   ' set waittime next start of pulses after mSec
      pwm.Stop
    
    }
    VAR
      long  cogon, cog  
      long sDuty                     ' order important (the variables are read from memory in this order)  
      long sPinOut 
      long sCtraVal
      long sPeriod
      long sGatePulses
      long sGatePeriod
    
      
    PUB Start( Pin) : okay
    'start pwm on Pin
      longfill(@sDuty, 0, 4)       
      sDuty := 50                   ' default duty
      sPinOut := |< Pin   
      sCtraVal := %00100 << 26 + Pin
      sPeriod := 1000
      sGatePulses := 2
      sGatePeriod := 40000000
      
      okay := cogon := (cog := cognew(@entry,@sDuty)) > 0    
      
    PUB stop
    
    '' Stop object - frees a cog
    
      if cogon~
        cogstop(cog)
      longfill(@sDuty, 0, 4) 
    
    PUB SetPeriod(counts)
    ' set pwm period in clock cycles, frequency = (_clkfreq / period)
       sPeriod := counts
    
    PUB SetFreq( freq )
    sPeriod := clkfreq / freq * sDuty  / 100
    
    PUB SetDuty(counts)
       if (counts < 0)
         counts := 0
       if (counts > 100)
         counts := 100
       sDuty :=counts*sPeriod/100
    
    PUB SetGatePulses(counts)
    ' set pwm period in clock cycles, frequency = (_clkfreq / period)
       sGatePulses := counts
       
    PUB SetGatePeriod(counts)
    ' set pwm period in clock cycles, frequency = (_clkfreq / period)
       sGatePeriod := counts
    
    PUB SetGatePeriodms(msec)
       sGatePeriod := 80_000_000 / 1000 * msec
          
    DAT
            org
    
    entry   mov     t1,par          'get first parameter
            rdlong  value, t1
             
            add     t1,#4                 
            rdlong  pinOut, t1
            or      dira, pinOut    ' set pinOut to output      
    
            add     t1, #4
            rdlong  ctraval, t1
            mov ctra, ctraval       'establish counter A mode and APIN
    
            add     t1, #4
            rdlong  period, t1
    
            add     t1, #4
            rdlong  gpulses, t1
    
            add     t1, #4
            rdlong  gperiod, t1        
    
            mov frqa, #1            'set counter to increment 1 each cycle
    
            mov time, cnt           'record current time
            add time, period        'establish next period
            mov tmp, #0
            mov ctra, ctraval
            
    :loop   rdlong value, par       'get an up to date pulse width
            waitcnt time, period    'wait until next period
            cmp tmp, gpulses wz
       if_e mov ctra, #0
       if_e mov tmp, #0
       if_e waitcnt time, gperiod
       if_e or outa,#0
       if_e mov ctra, ctraval        
            neg phsa, value         'back up phsa so that it  trips "value" cycles from now
            add tmp, #1
            jmp #:loop              'loop for next cycle
    
    period  res 1                    
    time    res 1
    value   res 1
    t1      res 1
    pinOut  res 1
    ctraval res 1
    ctraoff res 1
    gpulses res 1
    gperiod res 1
    tmp     long 0
    
  • propcogpropcog Posts: 4
    edited 2014-09-30 06:08
    Hi,

    Don't know what happened but my first post is gone?
    My calling parameters are these:
    pwm.start( Pin)               ' start pwm
      pwm.SetPeriod( period )       ' set pwm period in clock cycles
      pwm.SetFreq( freq )           ' set pwm frequency in Hz
      pwm.SetDuty( duty )           ' set duty in %                               
      pwm.SetGatePulses( gpulses )   ' set number of pulses
      pwm.SetGatePeriod( gperiod )   ' set waittime next start of pulses after mSec
      pwm.Stop
    

    The PASM code is attached.

    When the number of pulses are generated I stop the counter and wait for a few mSec. Then I restart the counter. But it generates an extra pulse?

    Regards!
  • kuronekokuroneko Posts: 3,623
    edited 2014-09-30 07:42
    propcog wrote: »
    When the number of pulses are generated I stop the counter and wait for a few mSec. Then I restart the counter. But it generates an extra pulse?
    I can see an extra pulse at the beginning, from then on it generates the right amount of pulses though with slightly odd timing.
    tmp = 0, waitcnt, gpulse == 0?, rewind phsa, [COLOR="#FF8C00"]wait remainder of period[/COLOR]
    tmp = 1, waitcnt, gpulse == 1?, rewind phsa, [COLOR="#FF8C00"]wait remainder of period[/COLOR]
    tmp = 2, waitcnt, gpulse == 2?, rewind phsa, [COLOR="#020FC0"]wait remainder of period[/COLOR]
    tmp = 3, waitcnt, gpulse == 3?, tmp = 0, [COLOR="#020FC0"]wait remainder of period[/COLOR], waitcnt, rewind phsa, [COLOR="#FF0000"]wait remainder of gperiod[/COLOR], tmp++
    tmp = 1, waitcnt, gpulse == 1?, rewind phsa, ...
    
    The above is for gpulses == 3. It starts with 2 normal pulses followed by one with a double period followed by the last one which is part of the pause between pulse groups. As tmp is reset to 0 and incremented before the next check the extra pulse is then missing and the loop generates the right amount of pulses. This may look confusing but just look at the cycle wait count between phsa rewinds.

    Note that PASM waitcnt target, delta waits first for target then adds delta to target.
  • kuronekokuroneko Posts: 3,623
    edited 2014-09-30 19:05
    Note also, any Set* method which doesn't affect sDuty won't have an effect on the running cog as only this location is continuously sampled (rdlong value, par). All other parameters retain the values present when the cog was reading them.

    Looks like your first post has been restored.
  • propcogpropcog Posts: 4
    edited 2014-10-01 07:32
    kuroneko wrote: »
    Note also, any Set* method which doesn't affect sDuty won't have an effect on the running cog as only this location is continuously sampled (rdlong value, par). All other parameters retain the values present when the cog was reading them.

    Looks like your first post has been restored.
    Thanks for your reply kuroneko!
    Looks like I have lots more to learn :nerd: Timing the output of the gated pulses etc. And I also want to update the values from the main SPIN code and adjust the counter on demand.

    Regards!
Sign In or Register to comment.