Shop OBEX P1 Docs P2 Docs Learn Events
PROPetual Commotion — Parallax Forums

PROPetual Commotion

Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
edited 2013-07-14 06:58 in Propeller 1
AKA self-referential timing:

attachment.php?attachmentid=102698&d=1373349634

I know this is weird, but I just had to try it. The idea is that you overdrive XIN, in XINPUT | PLLx? mode, forcing the system clock's VCO to run at its open-loop frequency. You do this by making one of the counters do the same and using its output to drive XIN. The program has to start in RCFAST mode first in order to get everything set up and the counter running. Then you can shift gears to XINPUT | PLLx? I started with PLLx16 and got a system clock frequency of about 250 MHz. The counters ran okay, but the program would not. By backing down to PLLx8, I was able to get a program running with a system clock frequency of 125 MHz -- all without any external clock sources or resonators. Here's the test program:
CON

  _clkmode      = rcfast
  CLKPIN        = 0
  MONPIN        = 1
  PRGPIN        = 2

PUB  start

  ctra := %00010 << 26 | %111 << 23 | CLKPIN
  frqa := $8000_0000
  dira := 1 << CLKPIN | 1 << MONPIN
  frqb := $8000_0000
  ctrb := %00100 << 26 | MONPIN
  waitcnt(cnt + clkfreq >> 3)
  clkset(%0110_0110, 0)
  cognew(@monitor, 0)
  repeat

DAT

monitor       mov       dira,pinmask

main_lp       mov       outa,pinmask
              nop
              mov       outa,#0
              jmp       #main_lp

pinmask       long      1 << PRGPIN              

Here's the scope output:

attachment.php?attachmentid=102699&d=1373349634

The top (yellow) trace is XIN (i.e. ctra); the middle {cyan} trace, the output of ctrb; the bottom (magenta) trace, the output of the PASM program.

Of course, this is not something you'd do if you need any kind of timing accuracy. :)

-Phil
320 x 282 - 13K
640 x 480 - 18K

Comments

  • BeanBean Posts: 8,129
    edited 2013-07-09 04:53
    Phil,
    Where to you get these ideas ???
    I assume you must connect P0 to XIN for this to work ?
    This could be really useful where you need more speed than RCFAST and don't need accuracy.

    P.S. I wonder what the low end clock speed of the VCO is ?

    Bean
  • prof_brainoprof_braino Posts: 4,313
    edited 2013-07-09 07:05
    Would the clock be consistent if the temperature were stable? That is, could the temp be monitored with say a thermistor and the clock adjusted accordingly?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-07-09 08:11
    Bean wrote:
    I assume you must connect P0 to XIN for this to work ?
    Yes.
    ... could the temp be monitored with say a thermistor and the clock adjusted accordingly?
    I doubt that there's any way to adjust the clock speed, since you're relying solely upon the open-loop frequency of the VCO. Assuming that were dependent only upon temperature, a thermistor might provide a clue as to what the actual speed is. Realistically, it's probably also device-dependent and who-knows-what-else-dependent. The phase of the moon, perhaps?

    -Phil
  • Beau SchwabeBeau Schwabe Posts: 6,566
    edited 2013-07-09 08:25
    That's pretty slick Phil !

    I have thought of using external environmental influences to affect the clock, but haven't really implemented anything. Basically a reverse method of timing something. Normally you would have a fixed clock frequency monitoring an I/O pin and timing the event on the pin. The reverse method would be to have a 'fixed' clock frequency or event on an I/O pin to monitor the system clock timing.

    As far as "could the temp be monitored with say a thermistor and the clock adjusted accordingly" - A thermistor tied to a VCO supplying the clock input would do that.
  • HumanoidoHumanoido Posts: 5,770
    edited 2013-07-09 11:37
    What is the most simple code example, with RC clock speed at 125 MHz, to count a number range and flash an LED when finished?
  • Cluso99Cluso99 Posts: 18,069
    edited 2013-07-09 18:52
    Very interesting find Phil.

    If only you could do this with power too... Like the perpetual power idea of inserting the power plug of a plugboard into the first socket ;)
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-09 22:16
    Very nice. I agree with Bean, there are likely lots of applications for this.

    Humanoido brings up a good point about making a demo which doesn't require an oscilloscope to monitor the speed change.

    This demo doesn't "count a number range" but it does use a waitcnt to wait a predetermined number of clock cycles.
    CON
    
      _clkmode      = rcfast
      CLKPIN        = 0
    
    
      LED_PIN       = 16
      
      ESTIMATED_HZ  = 125_000_000
      TOGGLE_WAIT   = ESTIMATED_HZ / 4                      ' to flash LED at approximately 2 Hz
      SLOW_TOGGLES  = 10                                    ' five flashes
      FAST_TOGGLES  = SLOW_TOGGLES
    
    
    PUB Start
    
    
      dira[LED_PIN] := 1
    
    
     Toggle(SLOW_TOGGLES)
    
    
      ctra := %00010 << 26 | %111 << 23 | CLKPIN
      frqa := $8000_0000
      dira[CLKPIN] := 1
      waitcnt(cnt + clkfreq >> 3)
      clkset(%0110_0110, 0)
     
      Toggle(FAST_TOGGLES)
    
    
      reboot                        ' go back to rcfast mode
      
    PUB Toggle(timesToToggle) | timer
    
    
      timer := cnt + TOGGLE_WAIT
      repeat timesToToggle
        !outa[LED_PIN]
        waitcnt(timer)
        timer += TOGGLE_WAIT
    
    
    

    The above demo flashes a LED five times at the rcfast clock speed and then five more times at the approximate 125MHz clock speed. It's kind of fun to see how dramatic the difference is between the two clock settings.

    I removed the PASM code and extra pins to simplify the program.

    I'm attaching this demo and the original code as Spin files.

    My original cut and paste left out some characters because of the percent signs. Hopefully this Spin code will make it easier for other to try out this cool new trick.
  • lonesocklonesock Posts: 917
    edited 2013-07-10 10:42
    This is awesome!

    I'm wondering since pin P23 is physically so much closer to XIN, do you think there would be any issues with the whole "Cog and I/O Pin Relationship" delays? It looks like using cog 7 would be ideal in this case, possibly forcing even purists to start off with a COGINIT? [8^)

    Jonathan
  • HumanoidoHumanoido Posts: 5,770
    edited 2013-07-11 08:08
    The programs are really great and work well.
    Can the code be made more simple?

    1) Turn on high speed rc clock (first section of the code)
    2) Run program below (other section of the code)
    dira[15]~~                     ' LED on pin 15, set to true
    repeat                         ' Loop below
     !outa[15]                     ' Toggle pin 15 /true/false/
      waitcnt(clkfreq/2 + cnt)     ' Delay
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-11 11:19
    Humanoido wrote: »
    The programs are really great and work well.
    Can the code be made more simple?

    Yes, of course. Though technically the timing isn't as exact since the setup isn't included in the delay (I doubt the difference would be noticed).

    I also thought it would be interesting to compare the rcfast speed vs the PROPetual speed Prop so I make the flashing part of the code a method which may be called while the Prop is operating at the two different speeds.

    Edit: See Phil's note below about clkfreq. I wasn't sure what the value of clkfreq would be which is one reason I didn't use it in my LED demo.
  • HumanoidoHumanoido Posts: 5,770
    edited 2013-07-11 17:27
    The program turns on the LED and appears to blink very slow.
    How to fix the delay for faster blinking?
    CON                                          ' Constants
      CLKPIN        = 0                          ' connect clock pin P0 to XIN
      LED_PIN       = 15                         ' put LED on pin 15
    
    PUB Start                                    ' Block to start PROPetual Speed
      ctra := 010 << 26 | 1 << 23 | CLKPIN       '
      frqa := $8000_0000                         ' frequency
      dira[CLKPIN] := 1                          ' make CLKPIN output to XIN
      waitcnt(cnt + clkfreq >> 3)                ' Pause
      clkset(10_0110, 0)                         '
      Toggle                                     ' Run Toggle
      
    PUB Toggle                                   ' Block to Toggle LED
      dira[LED_PIN] := 1                         ' Set LED pin 16 to output
      repeat                                     ' Loop below
       !outa[LED_PIN]                            ' Toggle pin 15 /true/false/
        waitcnt(clkfreq + cnt)                   ' Delay
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-07-11 17:59
    The secoind argument to the clkset command is the value subsequently used for clkfreq. I set it to zero in my example, since the actual value of clkfreq is indeterminate. That may explain the very slow pin toggling -- at about 53 sec. per change perhaps? You could set it to 125_000_000 and see what happens.

    -Phil
  • HumanoidoHumanoido Posts: 5,770
    edited 2013-07-11 19:04
    The second argument to the clkset command is the value subsequently used for clkfreq. I set it to zero in my example, since the actual value of clkfreq is indeterminate. That may explain the very slow pin toggling -- at about 53 sec. per change perhaps? You could set it to 125_000_000 and see what happens. -Phil

    Wow - that worked! Yes it was about 53 seconds.

    Could you explain what's happening here?
    ctra := 010 << 26 | 1 << 23 | CLKPIN
    
  • prof_brainoprof_braino Posts: 4,313
    edited 2013-07-11 19:25
    Could a set up like this be stable enough for serial communication to an external system?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-07-11 19:29
    Could a set up like this be stable enough for serial communication to an external system?
    Sure, if you use a self-clocking protocol like the one employed by the boot loader. But asynchronous NRZ? No.

    -Phil
  • HumanoidoHumanoido Posts: 5,770
    edited 2013-07-11 21:13
    The first program does not blink faster than the second program. How to fix?
    CON                                          ' Constants
      CLKPIN        = 0                          ' connect clock pin P0 to XIN
      LED_PIN       = 15                         ' put LED on pin 15
    
    PUB Start                                    ' Block to start PROPetual Speed
      ctra := 010 << 26 | 1 << 23 | CLKPIN       ' Counter A register setup
      frqa := $8000_0000                         ' frequency
      dira[CLKPIN] := 1                          ' make CLKPIN output
      waitcnt(cnt + clkfreq >> 3)                ' Pause
      clkset(10_0110, 125_000_000)               ' PLL8X, clkfreq
      Toggle                                     ' Run Toggle
      
    PUB Toggle                                   ' Block to Toggle LED
      dira[LED_PIN] := 1                         ' Set LED pin 16 to output
      repeat                                     ' Loop below
       !outa[LED_PIN]                            ' Toggle pin 15 /true/false/
       waitcnt(clkfreq/8 + cnt)                  ' Delay
    
    CON
      _clkmode      = rcfast
      LED_PIN       = 15        ' put LED on pin 15
    
    PUB Toggle                  ' Block to Toggle LED
      dira[LED_PIN] := 1        ' Set LED pin 16 to output
      repeat                    ' Loop below
       !outa[LED_PIN]           ' Toggle pin 15 /true/false/
       waitcnt(clkfreq/8 + cnt) ' Delay
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-11 21:15
    Use a constant number instead of clkfreq.
  • HumanoidoHumanoido Posts: 5,770
    edited 2013-07-11 21:26
    Duane Degn wrote: »
    Use a constant number instead of clkfreq.
    Can you suggest a number that will work?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-11 22:28
    Humanoido wrote: »
    Can you suggest a number that will work?

    I thought I had in post #8.
    CON                                          ' Constants    
      ESTIMATED_HZ  = 125_000_000
      TOGGLE_WAIT   = ESTIMATED_HZ / 8           ' to flash LED at approximately 4 Hz
      CLKPIN        = 0                          ' connect clock pin P0 to XIN
      LED_PIN       = 15                         ' put LED on pin 15
    
    PUB Start                                    ' Block to start PROPetual Speed
      ctra := %00010 << 26 | %111 << 23 | CLKPIN ' Counter A control register setup
      frqa := $8000_0000                         ' Counter A frequency register setup (not actual Hz)
      dira[CLKPIN] := 1                          ' make CLKPIN output
      waitcnt(cnt + clkfreq >> 3)                ' Pause
      clkset(%0110_0110, 0)                      ' PLL8X
      Toggle                                     ' Run Toggle
      
    PUB Toggle                                   ' Block to Toggle LED
      dira[LED_PIN] := 1                         ' Set LED pin 15 to output
      repeat                                     ' Loop below
       !outa[LED_PIN]                            ' Toggle pin 15 /true/false/
       waitcnt(TOGGLE_WAIT + cnt)                ' Delay
    

    Watch out about the percent sign causing trouble with cut and paste.
  • BeanBean Posts: 8,129
    edited 2013-07-12 04:35
    Could a set up like this be stable enough for serial communication to an external system?

    I might work if you use an "auto-baud" type setup. Where the other device sends data first. Then the propeller can time that data and use that timing to send data back.

    Bean
  • HumanoidoHumanoido Posts: 5,770
    edited 2013-07-12 06:42
    Duane: Thanks, I really appreciate this example and oops I had missed the point in post 8. I'm just a student learning Spin and I have a really long way to go. Sometimes when I look at another person's program, it appears like magic, even though I read the Propeller book sections for understanding. You're right, there was some trouble with the percent sign values when code was moved over to the IDE.
  • prof_brainoprof_braino Posts: 4,313
    edited 2013-07-12 06:56
    Sure, if you use a self-clocking protocol like the one employed by the boot loader. But asynchronous NRZ? No.

    How about autosynch the self reference clock to the external source clock? And then make it an external synchronous?

    We did have an autobaud (on the Harris RTX2000) that could sync in one character. I have a gut feeling about this. Maybe too much coffee.
  • HumanoidoHumanoido Posts: 5,770
    edited 2013-07-13 08:00
    AKA self-referential timing: I know this is weird, but I just had to try it. The idea is that you overdrive XIN, in XINPUT | PLLx? mode, forcing the system clock's VCO to run at its open-loop frequency. You do this by making one of the counters do the same and using its output to drive XIN. The program has to start in RCFAST mode first in order to get everything set up and the counter running. Then you can shift gears to XINPUT | PLLx? I started with PLLx16 and got a system clock frequency of about 250 MHz. The counters ran okay, but the program would not. By backing down to PLLx8, I was able to get a program running with a system clock frequency of 125 MHz -- all without any external clock sources or resonators. -Phil

    Why wouldn't a program run at 250MHz and are there any mods that could make it run that fast? Maybe another weird thing?
  • Bill HenningBill Henning Posts: 6,445
    edited 2013-07-14 06:58
    Phil,

    This is seriously cool!

    Thanks for the link in the other thread, I missed this thread somehow.
Sign In or Register to comment.