Shop OBEX P1 Docs P2 Docs Learn Events
yet another counter thread - clever idea, execution not so good... — Parallax Forums

yet another counter thread - clever idea, execution not so good...

agsags Posts: 386
edited 2013-08-07 08:40 in Propeller 1
I'm trying a new approach to using counters to drive IOs. For this discussion I'll focus on just one signal, the clock.

It occurred to me that I could setup a counter for the clock line in NCO mode (%00100), let it "run" all the time, and use frqx to "enable" it. If frqx is set to $40_00_00_00, that will drive a clock at 1/4 the Propeller clock. When I set frqx, the clock starts, when I clear frqx it stops. I propose that I don't ever need to care about phsx (with this particular frqx value) since when frqx is cleared, phsx will always be 0 - or the starting state.

This looks great in theory. In practice, I'm seeing entirely different behavior (using a logic analyzer). So I'm wondering what incorrect assumption(s) I've made about how this should work. Specific code (assuming cog just started, e.g. all special registers cleared) :
movi ctra, #%0_00100_000    'set NCO mode
movs ctra, clkPinNum        'set APIN that clock will drive
...other stuff
movi frqa, #%0_1000_0000    'turn clock "on" at 1/4 Propeller clock speed
...do more stuff with clock running
movi frqa, #0                   'turn clock "off"

I have reviewed the detailed discussions of the timing of counter actions, when the registers are set (which clock cycle in the instruction), etc. I seem to have missed something important.

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-08-06 11:29
    phsx will pick up from where it left off. Clearing frqx does not reset phsx.

    -Phil
  • agsags Posts: 386
    edited 2013-08-06 12:20
    Right - and if my understanding is accurate, with this approach (only allowing frqx be $40000000 or 0) phsx will always be left off with a value of 0 when the clock is stopped (by setting frqx = 0).
  • tonyp12tonyp12 Posts: 1,951
    edited 2013-08-06 12:45
    >phsx will always be left off with a value of 0
    So you planning to only use 1/4 and as most cog opcodes use 4 clocks,
    when you stop counter from adding you will always be at a known pin state.

    Should work, but set phsa to initial value as even after a reboot it does not reset.
    Or maybe it's just CNT that keeps it's value after a reboot?
  • agsags Posts: 386
    edited 2013-08-06 14:29
    tonyp12 wrote: »
    Should work, but set phsa to initial value as even after a reboot it does not reset.

    After I picked myself up off the floor, I did some research. I have always assumed (and coded - and have lots of inline comments reminding me of this) that all 16 special cog registers are cleared at coginit (PAR and CNT being immediately written with a valid value). From the Propeller P8X32A Datasheed v1.4.0 page 16 section 5.2:
    When a cog is booted up, locations 0 ($000) through 495($1EF) are loaded sequentially from Main RAM / ROMand its special purpose locations, 496 ($1F0) through 511($1FF), are cleared to zero.

    I also looked at the Propeller Manual. That seems to support your statement (by omission). It clearly states that dirx and outx are cleared, but no mention of clearing ctrx, freqx, phsx or vcfg vscl registers.

    Hard to imagine how my functioning code works - I rarely set phsx registers, assuming they are cleared at startup (which is typically what I want)

    Thinking this through further - is it just phsx that is not cleared, or ctrx and frqx also? (they are each specified as being cleared in the datasheet, but no mention of them being cleared in the Manual). If none were cleared, then whenever a cog was (re)started, there would be a possibility that a pin would start toggling away as soon as its direction was set to output (if ctrx value was also persistent from a previous cog launch). This seems odd. And it seems odd that only phsx would not be cleared if all other special registers were.

    Have you tested and verified that phsx is not cleared? I will have to wait until I have access to a prop to test directly.
  • AribaAriba Posts: 2,690
    edited 2013-08-06 22:24
    The special purpose registers are all cleared at a coginit/cognew. Also PHSA and PHSB.
    But in your first post you wrote:
    ags wrote: »
    ...do more stuff with clock running
    The question is what instructions are used in this "more stuff" - not all instructions take 4 cycles or a multiple of 4 cycles.
    After any waitxxx instruction the synchronisation between PHSx and instruction cycles is anyway unknown.

    Another possible problem: If the write to FRQx from the MOVI and the change of PHSx by the counter happens at the same time it may be that sometimes FRQx is added before cleared, sometimes not. In this case you can try to initalize PHSx with $4000_0000 before the first movi frqa, #%0_1000_0000. The change of PHSx should then happen in another cycle then the write to FRQx.

    Andy
  • agsags Posts: 386
    edited 2013-08-07 08:40
    So it appears that phsx is cleared during cog initialization. I haven't run exhaustive tests though. If anyone can provide a definitive answer that would be appreciated. As noted above, the datasheet specifically states all 16 cog special registers are cleared - but the manual only explicitly states this for dirx and outx.

    @Ariba you are correct that all the "more stuff with clock running" must be multiples of 4 clocks for this to work. So any hubop or wait is likely to throw that off. I don't allow such things in this section of code. Outside the bounds of setting and clearing the frqx register I'm free to do whatever I want without problems.

    From many detailed exchanges with kuroneko, and my direct experience, I'm pretty confident that writing to phsx always "overrides" the current value, even if fhsx is being accumulated at the time. That gets into details of when registers are sampled, when results are written, etc. See this thread if interested: http://forums.parallax.com/showthread.php/134383-(PASM)-waitcnt-and-odd-clocks

    As for the problems I had - they are gone. I can't say exactly what fixed things (or if they are really fixed or still fragile but working with the current specific snapshot of code) because I changed too many things at once. One may have been yet another power supply problem. I am now using a larger supply, as I'm running several peripherals from the same supply. I also simplified some of my code with the intention of optimizing for speed after it's functional.

    But I would still really like to hear the definitive answer on clearing (or not) of the "other" cog special registers (other than dirx and outx).
Sign In or Register to comment.