yet another counter thread - clever idea, execution not so good...
ags
Posts: 386
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) :
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.
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
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?
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:
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.
But in your first post you wrote: 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
@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).