Shop OBEX P1 Docs P2 Docs Learn Events
Can SpinBasic provide microsecond accuracy? - Page 2 — Parallax Forums

Can SpinBasic provide microsecond accuracy?

2»

Comments

  • AribaAriba Posts: 2,690
    edited 2013-08-03 17:39
    You can get even more precision in Spin with the use of a counter (every cog has two of them).
    The Spin code is smaller, but you need to know how the counter works to understand the code:
    CON
       _clkmode        = xtal1 + pll16x
       _xinfreq        = 5_000_000
       us120 = 80*120           'cnt clocks for 120us and 20us
       us20  = 80*20
       pin = 0                  'pin number to use
    
    PUB Main : now
     ctra := %00100<<26 + pin   'ctra in NCO mode
     frqa := 1                  'count up
     phsa := 0                  'output Low
     dira[pin] := 1             'pin = output
    
     repeat
       now := cnt               'reference point for exact timing
       phsa := -us20            'high for 20us
       waitcnt(now += us120)    'wait until exactly 120us from reference point
       phsa := -us20            'high for 20us
    
       waitcnt(clkfreq/100+cnt) 'wait ~10ms before next loop
    '
    
    The pulses are now precise to 12.5ns, only the pause between the two pulses suffer still from the hub sync timing and can vary about 200ns. The minimal pulse time is now 12.5ns !!

    Andy
  • JonnyMacJonnyMac Posts: 9,191
    edited 2013-08-03 18:21
    So, if I have to mess with assembler anyway, than why should I choose "8 cores" instead of at least 5x cheaper solution, if I have to deal with ASM ?

    As Mike pointed out, the Propeller instruction set is very nice, especially when it comes to fast, complex timing -- no cycle counting.

    Based on your description, you desire to generate two pulses that could overlap, so it will be cleaner to use the counters to generate pulses. Using a counter in NCO mode is easy and gives you 12.5ns resolution at 80MHz. I wrote the code below (compiles, but I didn't bother testing -- you can do that) that allows you to call a .start() method with the parameters you want to use (pins and timing in microseconds); I'm not a fan of embedding pin #s in code as hardware designs frequently change. As you can see, after getting the parameters, io and counters setup, the code is quite simple.
    var
    
      long  cog
    
        
    pub start(in, out1, out2, pw, ho)
    
    '' Start sensor/pulse generator cog
    '' -- in, out1, and out2 are io pins
    '' -- pw is pulse width in microseconds
    '' -- ho is edge-to-edge hold-off in microseconds
    
      stop
    
      ' convert pw (pulse width) and ho (hold-off) to system ticks
    
      pw *= clkfreq / 1_000_000
      ho *= clkfreq / 1_000_000 
      
      cog := cognew(@curious, @in) + 1                              ' start the cog
    
      return cog
    
    
    pub stop
    
    '' Stops cog (if running)
    
      if (cog)
        cogstop(cog - 1)
        cog := 0
    
    
    dat
    
                            org     0
    
                            ' get parameters from hub
    
    curious                 mov     t1, par                         ' start of parameters
                            rdlong  sensepin, t1                    ' read input pin
    
                            add     t1, #4
                            rdlong  out1pin, t1                     ' read pulse output 1
    
                            add     t1, #4
                            rdlong  out2pin, t1                     ' read pulse output 2
    
                            add     t1, #4
                            rdlong  pulsetix, t1                    ' ticks in pulse width
    
                            add     t1, #4
                            rdlong  hotix, t1                       ' ticsk in hold-off period
    
                            ' setup io
    
                            mov     sensemask, #1
                            shl     sensemask, sensepin             ' convert pin to mask
    
                            mov     out1mask, #1
                            shl     out1mask, out1pin               ' convert pin to mask
                            mov     frqa, #1                        ' setup ctra for hi-res pulse
                            mov     phsa, #0
                            mov     ctra, NCO_SE                    ' use NCO mode
                            or      ctra, out1pin                   ' assign to out1
                            or      dira, out1mask                  ' make out1 an output
    
                            mov     out2mask, #1      
                            shl     out2mask, out2pin 
                            mov     frqb, #1          
                            mov     phsb, #0          
                            mov     ctrb, NCO_SE   
                            or      ctrb, out2pin      
                            or      dirb, out2mask    
    
    
    waitforinput            mov     phsa, #0                        ' prevent spurious pulse
                            mov     phsb, #0
                            test    sensemask, ina          wc      ' look for input
            if_nc           jmp     #waitforinput                   ' wait for high
    
                            mov     sync, cnt                       ' establish sync point
            
    pulse1                  neg     phsa, pulsetix                  ' pulse #1
    
                            add     sync, hotix
                            waitcnt sync, #0                        ' wait hold-off period
    
    pulse2                  neg     phsb, pulsetix                  ' pulse #2
                            nop                                     ' { may not be needed }
    
                            waitpne out2mask, out2mask              ' let pulse #2 finish
    
                            jmp     #waitforinput  
    
    
    ' --------------------------------------------------------------------------------------------------
    
    NCO_SE                  long    %00100 << 26                    ' for counters
    
    
    sensepin                res     1                               ' input pin #
    out1pin                 res     1                               ' pulse output #1 pin
    out2pin                 res     1                               ' pulse output #2 pin
    pulsetix                res     1                               ' ticks in pulse width
    hotix                   res     1                               ' ticks in hold-off period
    
    sensemask               res     1
    out1mask                res     1
    out2mask                res     1
    
    sync                    res     1
    
    t1                      res     1                               ' work vars
    t2                      res     1
    
                            fit     496
    


    [Edit 1] It looks like Andy posted while I was writing my own version that uses counters. WAITCNT works in Spin and PASM, though with PASM there is far less overhead. If you look through my code you'll find it very straightforward; setting up the counter, for example, is nearly one-for-one, Spin to PASM.

    [Edit 2] I've attached a ready-to-run demo that illustrates how the Propeller can be used for self-testing. This will allow you to connect nothing but a 'scope to verify the code is working. This is a simple example, but I do the same thing when writing new protocol drivers. THAT would be very hard to do on a small PIC.
  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-03 18:47
    Ah ... love it. One of the excellent reasons to use Parallax products rather than something a lot cheaper ... If you wait a bit, sometimes hours, sometimes a day or two, you'll get all sorts of diverse expert help.
  • CuriousOneCuriousOne Posts: 931
    edited 2013-08-03 22:39
    Yes, the support from parallax community is the best so far. Contrary to Melabs guys, where you ask, "why this does not works" and get answer like "cause you're an idiot" :D

    Thanks everyone for the code examples. Let's summarize:

    Currently, parallax IDE, does not cares or checks whenever timings you specify in your code will be executed as you declared, if we're talking about microsecond delays.
    Also, if your code requires parallel running of "cores", the compiler does not distributes the load across the cores, to get the high performance.

    Right?
  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-03 23:20
    Parallax's IDE, whether the Propeller Tool or the GCC toolchain along with a number of 3rd party tools, do not do any kind of timing analysis at all, whether microsecond or millisecond. None of the Propeller programming tools care or check execution timings. In fact, there's no mechanism to declare them. There's no automatic "distribution" of computing across the cores. Both execution timing and control of the cogs (cores) is done manually. These are easy to do, but there's nothing automatic. This is deliberate. It's very difficult to do automatically, particularly with free or low-cost tools since the development costs are so high and the development time so long. Would you be willing to pay several hundred dollars for a programming tool ($600-$800) with some of the timing features you seem to want?
  • CuriousOneCuriousOne Posts: 931
    edited 2013-08-04 00:01
    Well, I'm not arguing or asking for something for free. I'm just evaluating existing offers to select one that fits me most. Sorry if hurted anyone.
  • AribaAriba Posts: 2,690
    edited 2013-08-04 08:00
    I can not see how a timing analyzer tool should know what you want to get. If you need to program in all the rules and timing parameters, you can also do a little Spin code in a second cog which analyzes your output, totally independent of the cog that generates the output.

    A good example of a tool that does run an analyzer cog and show the output in a GUI on the PC is Hannos Viewport.

    I know you will also find a fly in the ointment for Viewport. But this hurts only yourself and then you should perhaps change your Nickname to: UnsatisfiableOne :smile:

    Andy
  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-04 08:18
    No name calling please. CuriousOne is looking for something specific that's not available for the Propeller nor for most microcontrollers on the market, certainly not as a free provided tool. There may be something done in academia as part of a thesis project. You might check out XMOS.
  • CuriousOneCuriousOne Posts: 931
    edited 2013-08-04 08:42
    Thank you very much!

    XMOS seems to have what I want:

    http://www.xmos.com/products/tools/xtimecomposer

    whilst our unique XTA static timing analyzer can be used to validate that all real-time requirements are met without the need for complex and time-consuming dynamic test suites

    LOL but no BASIC language, only C & ASM :)
  • CuriousOneCuriousOne Posts: 931
    edited 2013-08-04 08:49
    Their led flasher sample code:
    #include <xs1.h>
    #define FLASH_PERIOD 20000000
    out port led = XS1_PORT_4F;
    int main(void) {
    timer tmr;
    int t;
    tmr :> t;
    while (1) {
    led <: 0x1;
    t += FLASH_PERIOD;
    tmr when timerafter(t) :> void;
    led <: 0x0;
    t += FLASH_PERIOD;
    tmr when timerafter(t) :> void;
    }
    return 0;
    }
    
    

    I personally liked the resolution of FLASH_PERIOD variable, but why so many brackets and commas, points and so on in C? why they make such strange syntax? :)
  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-04 10:13
    Most of it is standard C. Obvious exceptions include ":>" and "<:" and the when statement. You'll have to consult their C documentation for their extensions.
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2013-08-04 14:11
    Basic was always intended to be a beginner's language.. that's why it was called Basic.
    Precise usecond timing is not a beginner's project.

    Why use 8 cores? Well if you have to have several events start and stop independent of each other, it is a lot easier than threaded code... may be the only good solution.

    Why Propeller assembly versus PIC assembly? Well every time you need something different you might change PICs and have to learn a different assembler code and a lot of tedious detail about the silicon's architecture.

    Why is Propller timing considered easier? For longer periods, a 32 bit counter makes it extremely easy to create long delays, where an 8 or 16 bit register structure might require a bit more complex code. And of course, for the smallest of delays, the Propeller generally runs faster than PICs. I am not sure that 12.5 nano-seconds is completely correct as instructions take 4 clocks. So 50.0 nano-seconds for most solutions is easily done. If you really need 12.5 nano-seconds, it may require something more sophisticated than I straight-forward one Cog solution.

    Trying to buy a solution may work for awhile. But it you learn to code a solution, you will get persistent returns on your investment. Sure, you can get a PIC for $2 versus a Propeller for $10. But over the long haul, you may spend many more man-hours getting the right PIC for the job.

    Seems XMOS has what you want. Good luck.
  • JonnyMacJonnyMac Posts: 9,191
    edited 2013-08-05 13:45
    A rather silly thread.

    Indeed. As did others, I took time out of my life to write practical demonstration code and it turns out he doesn't even own a Propeller! I kind of wish forum threads were like Amazon book reviews where the review indicates if the reviewer actually purchased the book.

    Also, if your code requires parallel running of "cores", the compiler does not distributes the load across the cores, to get the high performance.

    Oi vey. This reminds me of a story told to me by a director (who also does electronics) about new employees in the visual effects world. They come into the office, sit down at their computer, and then proceed to ask, "Where's the dinosaur plug-in?" At some point you just have to put on your big-boy pants and build the dinosaur yourself. Counting on the work of others to completely automate your life is a fool's errand in my opinion. They don't put automatic transmissions in F1 cars for a reason.

    XMOS seems to have what I want

    Good luck. Say "Hi" to Leon! ;)
  • mindrobotsmindrobots Posts: 6,506
    edited 2013-08-05 13:51
    I'm NOT a plugin!!!

    rex plugin.jpg


    Thanks, Jon!!
    1024 x 819 - 87K
Sign In or Register to comment.