![]() |
Forum Index : Microcontroller and PC projects : Frequency counter using PIO, work in progress for picomite
![]() ![]() |
|||||
Author | Message | ||||
Pluto Guru ![]() Joined: 09/06/2017 Location: FinlandPosts: 375 |
![]() Test set-up: The signal source (in the middle) is a Si5351A-based oscillator controlled by a 28pin MicroMite. Cheap Chinese frequency meter on the left. PicoMite with Volhout's newest PIO-based frequency meter on the right, outputting 89998399Hz. |
||||
Amnesie Guru ![]() Joined: 30/06/2020 Location: GermanyPosts: 530 |
Hi, I was trying Volhouts latest code but got Syntax error: ![]() ![]() This is the code (one page back <): pio_freq_measure.zip Has anyone some hints? - Daniel |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 4875 |
Hi Daniel. This is made for PicoMite V5.07.05RC3. Since then (i.e. V5.08.00) the format is corrected for PIO(execctrl a,b,c) Change the first "0" in "gp0": (example for PIO 1.0) e0 = Pio(execctrl 0,0,&h1f) to e0 = Pio(execctrl gp0,0,&h1f) Regards, Volhout Edited 2024-04-18 00:51 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
Amnesie Guru ![]() Joined: 30/06/2020 Location: GermanyPosts: 530 |
Hi thank you a lot, works fine now - impressive work! -Daniel |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 4875 |
Warning: below code is just a proof of concept for a new PIO core that allows for more accurate frequency measurement. It is by no means complete. The essence is to increase resolution, so a different method is used. Note that this method uses MMBasic to generate the gate pulse, not PIO itself. The gate pulse need not to be accurate now. Note that the final accuracy depends on the crystal on the pico. The crystal accuracy can be calibrated out when you know what it is. This code (as is) can only be assembled using the 6.00.02 PIO assembler. You need V6.00.02rc7 or newer to run the code. ' test for the RC7 new PIO CONFIGURE 'PIO Configure pio, sm, clock [,startaddress] '[,sidesetbase] [,sidesetno] [,sidesetout] '[,setbase] [,setno] [,setout] [,outbase] [,outno] [,outout] [,inbase] '[,jmppin] [,wraptarget] [,wrap] [,sideenable] '[,pushthreshold] [,pullthreshold] [,autopush] [,autopull] [,inshiftdir] [,outshiftdir] '[,joinrxfifo] [,jointxfifo] [,joinrxfifoget] [,joinrxfifoput] ' test for new assembler format ' requires picomite 6.00.02 beta 10 or newer because (PIO(NEXT LINE)) 'FC2 = frequency counter 2, OPTION CPUSPEED 252000 is accurate 'idea from Bert Lemmens to increase accuracy frequency measurement 'at start gate, wait for first edge, then start gate', and count pulses. 'at end gate, wait for next edge, then stop gate', and stop counting 'measure pulse width gate' 'frequency = count / gate' time 'period = gate' time / count 'this should not jitter 'current assignment 'gp0 = count input 'gp1 = gate pulse 'gp2 = gate'pulse '-------------------------- version history ------------------------------ 'v00 'gate pulse works 'v01 'pulse measurement from gate' pls works 'v02 'counter works (not calibrated) 'v03 'replace PIO gate generator with MMBasic pulse generator (free 1 SM)) 'v04 'implement pause measurement, new assembler directives in v6.00.02b10 debug=1'0 'do you want debug output ? '-------------------------- system setup -------------------------------- 'MMBasic generate gate pulse (active low) p = 1 'use PIO 1 'assign frequency counter pins if p=1 then setpin gp0,pio1 ' = input setpin gp2,pio1 ' = gate' else setpin gp0,pio0 ' = input setpin gp2,pio0 ' = gate' end if setpin gp1,dout : pin(gp1) = 1 ' = gate output from MMBasic, active low assemble p 'assemble the code in PIO p configPio p 'configure PIO p state machines 'defines puls_tick! = 2 / f0 ' pulse measurement tick 'memory allocation dim altgate%(4) ' to read gate' value from fifo dim cntr%(4) ' to read count value from fifo '----------------------------- main -------------------------------------- do 'gat epulse generation in MMBasic pulse gp1,200 'generate gate pulse pause 300 'this is the loop time, the pulse 200 is not blocking 'read what the PIO reads from gate' pio read 1,0,5,altgate%() 'read what the PIO reads from counter pio read 1,1,5,cntr%() if cntr%(4)=0 then inc cntr%(4) 'prevent divide by zero 'show period and frequency print altgate%(4)*puls_tick!/cntr%(4);" seconds period", print cntr%(4)/(altgate%(3)*puls_tick!);" Hz frequency" loop end '----------------------------- subs -------------------------------------- 'this configures the state machines for PIO n Sub configPio(p) 'stop all PIO's PIO stop p,0: PIO stop p,1': PIO stop p,2: PIO stop p,3 'PIO p.0 (measure pulse from GP2) f0=126e6 '126 MHz frequency e0=Pio(execctrl gp2,puls_target,puls_wrap) 'GP2 is jump pin p0=Pio(pinctrl 0,,,GP2,,,) 'GP2 is input pin 'PIO 1.1 (frequency A from GP0) f1=126e6 '126 MHz frequency e1=Pio(execctrl gp1,count_target,count_wrap,0,1) 'GP1 = cond jmp, side_set ena option p1=Pio(pinctrl 2,1,,gp0,gp2,GP2,) 'GP0 input, GP2 for SIDE SET and SET '2 = side enable + side set pins 'Start all PIO sequencers 'PIO init machine p,0,f0,p0,e0,0,puls_start PIO Configure p,0,f0,puls_start,GP2,2,,GP2,1,,,,,GP0,GP1,puls_target,puls_wrap PIO start p,0 'this will start pulse measurement from GP2 ' PIO init machine p,1,f1,p1,e1,0,count_start PIO Configure p,1,f1,count_start,,,,,,,,,,GP2,GP2,count_target,count_wrap,1 PIO start p,1 'start counter, count while GP1 low End Sub 'this sub assmebles the different PIO routines sub assemble (p) 'measure positive pulse, used for gate' time 'require IN and JMP pin to be set equal to the gate' pin puls_start=0 pio assemble p .program pulse .line 0 .wrap target mov x,!null 'x=ffffffff wait 1 pin 0 'wait for pin to go high .label cnt: 'label jmp x-- always 'decrement x, and always go to the next instruction .label always: 'label jmp pin cnt 'while 1 jmp to cnt: mov isr,!x 'copy inverted value to isr push noblock 'push in fifo .wrap .end program list puls_target=pio(.wrap target) puls_wrap=pio(.wrap) if debug then print puls_start,puls_target,puls_wrap ' 'count pulses 'uses side set 2 to control gate' and no-signal... gate' and no_count are same signal 'set and side set base must point to the same pins 'todo: add no-count via SET second bit count_start=pio(next line) pio assemble p .program count .line next 'continue assembling .side set 1 opt 'side set bits + option set pindirs,1 'gate' set output and low .wrap target 'return here mov x,!null side 0 'x=ffffffff, gate' low, no_count low .label wait: 'label jmp pin wait 'wait until gate opens (active low) .label countup: 'label wait 0 pin 0 'wait until count in low wait 1 pin 0 'wait until count in high jmp pin ready side 1 'set gate' and check if gate ready jmp x-- countup 'count down while not 0, gate high .label ready: 'label mov isr,!x side 0 'copy inverted value to isr, gate' low push noblock 'push in fifo .wrap 'endless loop .end program list count_target=pio(.wrap target) count_wrap=pio(.wrap) if debug then print count_start,count_target,count_wrap 'measure negative pulse, used for gate time 'require IN and JMP pin to be set equal to the gate pin pause_start=pio(next line) pio assemble p .program pause .line next .wrap target mov x,!null 'x=ffffffff wait 0 pin 0 'wait for pin to go low .label cnt: 'label jmp pin done 'when 1 jmp to done: jmp x-- cnt 'decrement x, and always go to the next instruction .label done: 'label mov isr,!x 'copy inverted value to isr push noblock 'push in fifo .wrap .end program list pause_target=pio(.wrap target) pause_wrap=pio(.wrap) if debug then print pause_start,pause_target,pause_wrap end sub I run the pico at 252MHz, so PIO can run at 126MHz, which is a full divider from 252MHz. This is needed for low jitter. Note above code still has the old "e0, e1, p0, p1" PIO helper variables, but these are not used, since the parameters are embedded in the new PIO CONFIGURE command (as listed in the comments at the top of the code). Volhout Edited 2025-05-14 16:43 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
pwillard Guru ![]() Joined: 07/06/2022 Location: United StatesPosts: 308 |
Just wanted to say... thanks for this effort. It might come in handy for one of my projects. |
||||
PhenixRising Guru ![]() Joined: 07/11/2023 Location: United KingdomPosts: 1170 |
Hi Harm, But the PIO can run at sysclock, no? |
||||
Pluto Guru ![]() Joined: 09/06/2017 Location: FinlandPosts: 375 |
Thanks Volhout! What would the max measurable frequency be? |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 4875 |
Hi Pluto, The counting code is the same as in the previous tests you have performed, so the achievable frequency would be the same if you set the same PIO clock. Volhout PicomiteVGA PETSCII ROBOTS |
||||
![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |