Shop OBEX P1 Docs P2 Docs Learn Events
Weekend PASM puzzle: — Parallax Forums

Weekend PASM puzzle:

Beau SchwabeBeau Schwabe Posts: 6,568
edited 2011-01-05 10:41 in Propeller 1
jazzed posted something yesterday here that got me thinking. His original code was a way to throttle a clock pulse without using a counter... the bare bones code looks something like this...

CON
  _CLKMODE = XTAL1 + PLL16X
  _XINFREQ = 5_000_000

PUB start|ptr
    ptr := 1
    cognew(@PASM, @ptr)

DAT
PASM    org 0
        mov   dira, #1
:loop
  rdlong   val,  par wz
  xor      outa, #1
  if_nz    jmp   #:loop

val     res




...If the value in ptr is a non zero, then basically the tight loop generates a 2.5MHz clock, otherwise there is no clock.


I thought well for sure you can get at least 5MHz out of this and still be able to throttle the clock. So the code I came up with looks something like this...

CON
  _CLKMODE = XTAL1 + PLL16X
  _XINFREQ = 5_000_000

PUB start|ptr
    ptr := 3
    cognew(@PASM, @ptr)

DAT

PASM    org 0
        mov   dira, #1

'5MHz clock
:loop          rdlong    outa,   par wz
               nop
         if_nz djnz      outa,   #:loop

NoEnd          jmp #NoEnd        




This will allow you to generate a 5MHz square wave. The only thing is, is that you can't use any other I/O's during this
loop, and it will only work on P0.

The function of the 'ptr' value expands to something that could be very useful for data transmission

if ptr = 0, then the 5MHz is off
if ptr = 1, then only 1 pulse (100ns wide) is sent
if ptr = 2,4,6,8, etc., then 5MHz is ON starting out LOW
if ptr = 3,5,7,9, etc., then 5MHz is ON starting out HIGH

.... In other words you could toggle the ptr between 2 and 3 and you could flip the phase by 180 Deg could be interesting
for data transmission.


If you remove the nop instruction, the frequency is still 5MHz, but now ...

if ptr = 0, then the 5MHz is off
if ptr = 1, then only 1 pulse (50ns wide) is sent
if ptr = 2,4,6,8, etc., then 5MHz is ON starting out LOW with a 75% duty cycle
if ptr = 3,5,7,9, etc., then 5MHz is ON starting out HIGH with a 25% duty cycle

.... In this case you could toggle the ptr between 2 and 3 transmitting data by altering the duty cycle.


Now, I think that 5MHz is the limit based on the rdlong function requiring 16 clock cycles, however if you expand your options to use an I/O pin for control I can "almost" get 10MHz. What I mean by almost, is that when P0 is HIGH P1 will output 10MHz, and when P0 is LOW P1 will output a 25% duty cycle 5MHz frequency for a little while, before it drops out and doesn't produce any signal at all.

The challenge if it is possible, is to throttle the 10MHz without the 25% duty 5MHz, without using a counter.
If someone wants to show how to do it with a counter that would be fine, I believe you can go back to using the pointer variable to control it this way. I just thought this would be a good exercise to get back on topic of programming.

CON
  _CLKMODE = XTAL1 + PLL16X
  _XINFREQ = 5_000_000

PUB start
    cognew(@PASM, 0)

DAT

PASM    org 0
        mov   dira, #%10        'Set Pin directions P0 = input P1 = output
        mov   outa,  ina
{{
If P0 is HIGH, then P1 will output a 10MHz clock
If P0 is LOW,  then P1 will output a 5MHz clock before dropping off to no clock output
}}

'5MHz/10MHz clock
:loop1        andn  outa, ina
              djnz  outa,   #:loop1
 
NoEnd         jmp #NoEnd


▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe

IC Layout Engineer
Parallax, Inc.

Post Edited (Beau Schwabe (Parallax)) : 9/12/2009 4:32:16 AM GMT

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-09-12 04:34
    Beau,

    I think this meets the minimum criteria — probably not what you had in mind, though, right?

    [b]CON[/b]
    
      [b]_clkmode[/b]      = [b]xtal1[/b] + [b]pll16x[/b]
      [b]_xinfreq[/b]      = 5_000_000
    
    [b]PUB[/b]  Start | time
    
      [b]dira[/b][noparse][[/noparse]*0]~~
      [b]cognew[/b](@clock, 0)
      time := [b]cnt[/b]
      [b]repeat[/b]
        [b]waitcnt[/b](time += clkfreq / 64)
        [b]outa[/b][noparse][[/noparse]*0]~~
        [b]waitcnt[/b](time += clkfreq / 128)
        [b]outa[/b][noparse][[/noparse]*0]~
    
    [b]DAT[/b]
    
                  [b]org[/b]       0
    
    clock         [b]mov[/b]       [b]dira[/b],#1
    
    :loop         [b]xor[/b]       [b]outa[/b],#1
                  [b]jmp[/b]       #:loop
    
    
    


    -Phil

    Post Edited (Phil Pilgrim (PhiPi)) : 9/12/2009 4:43:20 AM GMT
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2009-09-12 04:50
    Phil Pilgrim,

    The idea was more for a continuous pulse stream that you can break out of the "tight loop" from some external event and continue code execution within the same PASM cog after the tight loop.

    "runty pulses" - I liked that - [noparse]:o[/noparse]) - but Phil removed it [noparse]:o[/noparse](

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.

    Post Edited (Beau Schwabe (Parallax)) : 9/12/2009 5:07:46 AM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-09-12 04:58
    The "runty pulses" (the reference to which I deleted, BTW) were due to having my scope set to too long a time base. It's one of the downfalls of sampling oscilloscopes: you see a perfectly-formed waveform on the screen, which bears no resemblance to the signal you're actually monitoring, since it's being grotesquely undersampled. sad.gif In some ways, I miss my old analog scope.

    -Phil

    Post Edited (Phil Pilgrim (PhiPi)) : 9/12/2009 5:03:18 AM GMT
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2009-09-12 05:07
    Phil,

    Many times I've been tempted to dig out my old 20MHz from the garage ... I hear your screams! [noparse]:o[/noparse])

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • DroneDrone Posts: 433
    edited 2009-09-12 11:08
    Digital scopes for this kind of thing (at least affordable digital scopes) will lead you astray. Watch ebaY and get a 4-channel 400MHz analog Tektronix 2465B for around $400. Pick up a scope cart too, they're cheap.
  • kuronekokuroneko Posts: 3,623
    edited 2009-09-13 08:46
    Beau Schwabe (Parallax) said...
    The challenge if it is possible, is to throttle the 10MHz without the 25% duty 5MHz, without using a counter.
    The main issue with your (last) example is that outa will become undefined over time. So using flags etc is out of the question. If you can accept one extra 10MHz cycle then this fragment should do the trick. It brings outa into a known state before ina gets involved (P1 output, P0 input).

    :loop   mov     outa, #%00
            mov     outa, #%11
            andn    outa, ina
            djnz    outa, #:loop
    


    If P0 is high then the andn will apply -4 ($FFFF_FFFC) and pull P1 low while djnz forces outa to -1 (P1 high) and continues the loop. OTOH, if P0 is low at this stage, andn will apply -3 ($FFFF_FFFD). That leaves a convenient %01 in outa and djnz ends the loop.

    Something a bit more wasteful but workable (from a POC point of view):

    :loop   jmpret  outa, ina
            jmpret  outa, #:loop
    


    The lower 9bit of outa are set to PC+1 and PC+2 so it can be arranged that at least one bit is changing state. ina needs to be arranged so that its lower 9bit either point to :loop+1 or somewhere else to end clock generation.
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2009-09-13 13:40
    kuroneko,

    I really like option #1, and I don't think one extra 10MHz cycle would be an issue.




    Here is a method using one of the counters. The example is set to output 40MHz, but could certainly be adjusted to anything from DC to 128MHz. If ptr is equal to anything non Zero, then P0 will output a 40MHz signal.

    CON
      _CLKMODE = XTAL1 + PLL16X
      _XINFREQ = 5_000_000
    
    PUB start|ptr
        ptr := 1
        cognew(@PASM, @ptr)
    
        waitcnt(cnt+clkfreq*2)
        ptr := 0
    
    DAT
    
    PASM          org 0
    
    :mainloop     rdlong    val,    par  wz
            if_z  jmp       #:done  
    :mod          jmp       #:start_ctr
    :start_ctr    mov       ctra,   #1
                  shl       ctra,   #28
                  mov       frqa,   #1
                  ror       frqa,   #1
                  mov       dira,   #1
                  movs      :mod,   #:mainloop
                  jmp       #:mainloop
    :done         mov       ctra,   #0
                  mov       dira,   #0
                  
    NoEnd         jmp       #NoEnd
    
    val           res       1
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-05 10:41
    LOL You guys got to be kidding me. All I can say is WOW

    Bruce
Sign In or Register to comment.