[FYI] clkfreq/2n
kuroneko
Posts: 3,623
This post has been triggered by a [post=1021211]recent 8MHz requirement[/post] (serial transfer, clkfreq/10). It didn't really need the clock generation but I did it anyway. In general, dividing by powers of two is easily done with an NCO but sometimes you may need the odd (2n) divider but not the associated (counter) jitter. What are our options?
A As in not exercising your brain enough
- plain code
- waitcnt usage
- (mis)using an NCO as a monoflop
- waitvid usage (for the time being I consider that cheatingA and it's not everyone's cup of tea anyway despite being one of the most flexible solutions)
CON pin = 16 DAT org 0 [COLOR="blue"]entry[/COLOR][COLOR="orange"]_28[/COLOR] mov dira, :mask mov cnt, #5{14} +4 add cnt, cnt :loop xor outa, :mask ' toggle pin waitcnt cnt, [COLOR="orange"]#14[/COLOR] jmp #:loop :mask long |< pin fitWhich leaves range 8..26. Let's cover plain code examples first (there are less, 8/16/20/24). I'm aware that 8 and 16 are powers of two, they are included here for completeness.
CON pin = 16 DAT org 0 [COLOR="blue"]entry_08[/COLOR] mov dira, :mask neg outa, dira ' !dira +1 djnz outa, #$-1 ' outa -= 1 :mask long |< pin fit DAT org 0 [COLOR="blue"]entry_16[/COLOR] mov dira, :mask xor outa, :mask ' toggle pin jmp #$-1 :mask long |< pin fit DAT org 0 [COLOR="blue"]entry_20[/COLOR] mov dira, :mask :loop waitpne $, #0 neg outa, dira ' !dira +1 waitpne $, #0 djnz outa, #:loop ' outa -= 1 :mask long |< pin fit DAT org 0 [COLOR="blue"]entry_24[/COLOR] mov dira, :mask :loop xor outa, :mask ' toggle pin nop jmp #:loop :mask long |< pin fitAnd finally, an NCO based example (clkfreq/26, the remainder is listed in the attached SPIN file).
CON pin = 16 DAT org 0 [COLOR="blue"]entry_26[/COLOR] mov dira, :mask movs ctra, #pin movi ctra, #%0_00100_000 ' NCO movi frqa, #%0000_0001_0 ' SDeRSDwm-RSDwm-RSDwm-RSDeRSDeR :loop movi phsa, #%1111_0011_0 ' XXX# ___# waitpne $, #0 ' ###### waitpne $, #0 ' ###### waitpne $, #0 ' ______ jmp #:loop ' ____ :mask long |< pin fitBean's bean [thread=123170]frequency counter[/thread] has been used to verify the generated waveforms.
A As in not exercising your brain enough
Comments
-Phil
-Phil
-Phil
-Phil
-Phil
Impressive - can you generalise that, for other divisions ? and include cases where Hi counts can be 1 different from low counts ?
Yes, those small number frequencies that are not easily reached with a simple SW loop make the most sense.
If course, if a general form for higher divides exists that is still small, then > 28+ can still be useful.
No problem. CLKFREQ/3 :
The driver allows you to send custom wave forms with a period of 1..32 cycles. Required parameters are period, pin and bit pattern.
In the end it is the most flexible way of sending out (custom) wave forms for this frequency range.
- setup an NCO
- set the top 12bit of frqx to ($1000_0000/period) >> 16
- preset phsx with frqx
- close the loop after period*4 cycles
High time for 2n+1 dividers is n+1, if you need opposite polarity just use a differential NCO and swap the pins. HTH