Yes the block diagram and maths are simple.
Chip added support in the smart pins to make the hardware details simple too..
(it can get tricky to ensure the two captures of time and cycles are made on the same edge, and ideally, you want lossless/gapless capture too, so 10 or 100 captures of time and cycles can be summed to give higher precisions )
I think it should actually be called "period counter".
I guess they mean "reciprocal of frequency" counter.
But "reciprocal of frequency" == period.
I think that would make usage more clear.
But, when you google "period counter" you get other stuff, which is maybe why the chose this name...
I think it should actually be called "period counter".
I guess they mean "reciprocal of frequency" counter.
But "reciprocal of frequency" == period.
I think that would make usage more clear.
But, when you google "period counter" you get other stuff, which is maybe why the chose this name...
I think it started as a simple one-word prefix so 'Frequency Counter' became 'Reciprocal Frequency Counter'.
If you wanted to create a new name, 'period counter' infers it measures a single periods, which is inaccurate.
'whole periods timer' is clearer, in that now includes key elements of measuring the time over N Whole Periods, and then calculates N/Time to give Cycles/Second units.
- however, because the final units are Hz, including Frequency in the name seems important. - Instrument users care less about the how, than what they ultimately measure.
On that note, the thread tile would be better as Reciprocal Frequency Counter Demo
Hey guys been a while. I have been working at home teaching aircraft mechanics teaching our academic side without lab. Each 24 days is a new class. Took three classes to get all dialed in.
I am now back learning this P2 asm and asm stuff.
Much thanks to @cgracy for the reciprocal counter demo and much thanks to @evanh for his help.
I stripped out the counter demo code to get to the asm code to print to the serial terminal.
Think because of now starting from the basics I am getting a much better understanding. Thanks to evanh I think I am getting it. I looked up the pop command on youtube and get it.
I have a couple of questions that I commented in the attached code. If either of you or anybody else have a minute would you please answer them.
Much thanks.
Martin
Not sure if Pilot is still around but I'll have a shot at answering his questions now anyway:
tx_string pop x 'pop return address and make byte ptr
'DOES THIS TAKE WHAT EVER X IS AT THE TOP OF THE STACK (THE LAST VALUE OF X)
Not the last value of x, but takes the last value off the stack and puts it into the x variable (register). Overwriting the old value of x.
'QUESTION: is x the last address of the caller????????????
Almost. This is architecture dependant but the common (propeller2) behaviour is when a routine is CALLed the program counter of the calling routine is pushed to the stack for later retrieval by a RET instruction. At the CALL time, the program counter holds the address of the subsequent instruction after the CALL ... so that is the address that gets pushed on to the stack.
shl x,#2
'I looked up altgb what is it doing to x and getbyte?
.loop altgb x 'get character
getbyte y
The SHL is multiplying x by 4. This is typical when rescaling an index or pointer. In this case x contains a cogRAM address so is longword scaled. But to use GETBYTE requires byte scaling, hence the times 4.
ALTGB is a prefixing instruction. A prefixing instruction means it modifies the behaviour of the subsequent instruction. The ALTxx instructions in general are a little hard to get and keep your head wrapped around. They provide what's called indirect addressing, or referencing in loose C speak. The trick is remembering that the variable holds an address, as opposed to holding the data.
ALTGB is tailored for prefixing GETBYTE, it won't correctly prefix any other instruction. There is other prefixes that are generic and function with many or most other instructions. ALTGB has two forms, the above form is simply copy a byte from location x and place it in y. x can address anywhere in cogRAM.
@Ramon said:
How can I convert this PASM code to SPIN2 with the minimal lines of code?
While not an answer to your Spin2 code conversion question, take a look at the TSL235R Quick Byte that I wrote. I converted Chip's standalone Reciprocal Counter PASM2 code to inline PASM2 and placed it into two driver routines:
fb_measfreq2P.spin2 <-- Read frequency, periods using 2 P2 smart pins.
Ramon,
You won't be able to JMP between assembly blocks like that. Each Pasm block is handled one at a time with just what is defined for it, not unlike Spin methods. Any branching will have to be within a block.
Francis, many thank for your help. I will take a look to that code, I am yet a little scared by PASM and try to use the most simple SPIN keywords. Nice that you can reduce the number of smart pins used. I was about to ask if it could be possible to just use one smart pin to detect frequency.
Evanh, yes I thought that the loop would not execute but in fact was repeating the code. Those ASM instructions I am not sure how to correctly convert into SPIN.
@Ramon said:
How can I convert this PASM code to SPIN2 with the minimal lines of code?
Here is a simple version in Spin2. I use P40 as input and output a test-frequency at P39, which is connected to pin 40 with a wire. It only measures the frequency, not the duty.
CON
_clkfreq = 200_000_000
MSR_PIN = 40 {connected to pin 39}
PUB main() | ticks, periods, freq, mintime
pinstart(39, P_NCO_FREQ+P_OE, 1, 1_000_150 frac clkfreq) 'test freq
mintime := clkfreq / 1_000 '1ms min measure time
pinstart(MSR_PIN+0, P_COUNTER_TICKS, mintime, %00)
pinstart(MSR_PIN+1, P_MINUS1_A + P_MINUS1_B + P_COUNTER_PERIODS, mintime, %00)
repeat
akpin(MSR_PIN addpins 1) 'start next measurement
repeat until pinr(MSR_PIN) 'wait until done
ticks := rqpin(MSR_PIN+0) 'read measured values
periods := rqpin(MSR_PIN+1)
freq := muldiv64(clkfreq, periods, ticks-1) 'calc frequency
debug(udec(ticks), udec(periods), udec(freq))
waitms(300)
I got it working, but I think you have some typo on lines 4 and 7.
Line 4 : should be -> MSR_PIN = 39
Line 7 : should be -> pinstart(MSR_PIN, P_NCO_FREQ+P_OE, 1, 1_000_150 frac clkfreq) 'test freq
Also the last parameter (1_000_150 frac clkfreq) seems to result zero always in (%00).
According to SPIN docs, the frac equivalent should be:
1_000_150 frac clkfreq = (1_000_150<<32) / clkfreq ' Result is Zero
Is that some mistake, or copy&paste from another code?
I am able to run the code with good results when I change the '1_000_150 frac clkfreq' with '%00'.
I have made a Flexprop version (for Retroblade2) here (Flexprop doesn't allow addpins, frac, or debug instructions)
By the way, what is a TICK? rise or fall?
And what are periods? Is a 'period' according to our system clock, or a full cycle (period) detected while reading the pin?
These are the kind of examples that I will never understand until some nice diagrams or drawings are made.
I output a test frequency on Pin 39 which I can vary to test the Frequency counter. For this is the pinstart on the first line in main(), it just starts an NCO. If you don't need that you can delete this line.
The counter input is on the MSR_PIN and the MSR_PIN + 1, which is pin 40 and pin 41 in my code (you seem to use pin 0 and 1).
My code works also with Flexprop without any modification. Flexprop knows FRAC, ADDPINS and DEBUG (in this simple form). Maybe you have a very old version.
By the way, what is a TICK? rise or fall?
And what are periods? Is a 'period' according to our system clock, or a full cycle (period) detected while reading the pin?
A tick is one single sysclock clock. Raise or fall defines if the positive or the negative edges of the input frequency are use to measure the periods. A period is the time from one positive edge to the next positive edge of the input signal.
One smartpin (41) measures the number of periodes that fit into the 1ms window, and the other smartpin (40) measures the time that all these periods take. They don't stop instantly after the 1ms time window, like a simple frequency counter. No they both finish the last periode that goes over the 1ms window, that's the trick of this reciprocal counter.
If you know the time that a certain number of periods take, you can calculate the frequency from that.
@evanh said:
How is debug supported? I presume not via loadp2 -t.
It is exactly via loadp2 -t . debug statements just get translated into the equivalent of BASIC "print" statements. The backtick kinds of debug (for graphics) just print the backtick strings, no graphics. debug() statements in PASM code are ignored.
@evanh : DEBUG() statements are optional (as they are in PNut). In order to enable debug() flexspin needs the -g flag on the command line. We should probably continue this on the flexspin thread if you have more questions.
@Ramon said:
I have made a Flexprop version (for Retroblade2) here (Flexprop doesn't allow addpins, frac, or debug instructions)
I think you need to update your flexprop. addpins, frac, and debug have been supported for some time now.
I was using 5.2.0. I just downloaded 5.3.2, and looks that it is the same error I had before.
error: syntax error, unexpected identifier `frac', expecting ')' or ','
error: syntax error, unexpected identifier `addpins', expecting ')' or ','
error: unknown identifier debug used in function call
error: unknown identifier udec used in function call
error: unknown identifier udec used in function call
error: unknown identifier udec used in function call
Ariba, Thank you for explaining all the details. Now I understand.
Never occurred to me that something like that was possible !!
Being able to configure the (smart)pin for output to create a test frequency and at the same time configure the same pin with counter function for input is like having two smartpins on each pin.
That could be great to make a simple test program that can check all pin input/ouputs. (with a wire between each pin pair:
Frequency test output (pin 0, 2, 4, 6, 8, 10 ... 62) with NCO.
'Loopback' cable between 0+1, 2+1, 4+1 ... 62+1.
And configure frequency counters on 0+1, 2+1 .. 62+1.
I think you need to update your flexprop. addpins, frac, and debug have been supported for some time now.
I was using 5.2.0. I just downloaded 5.3.2, and looks that it is the same error I had before.
Ah, I see the problem, your file is named .spin (for Spin 1) instead of .spin2 (for Spin 2). The two languages are slightly different, unfortunately. To use Spin2 operators like addpin or frac you need to name the file with a .spin2 extension.
@Ramon said:
Ariba, Thank you for explaining all the details. Now I understand.
Never occurred to me that something like that was possible !!
Being able to configure the (smart)pin for output to create a test frequency and at the same time configure the same pin with counter function for input is like having two smartpins on each pin.
That could be great to make a simple test program that can check all pin input/ouputs. (with a wire between each pin pair:
You can do all that and more without any wires at all. However, Ariba used smartpin's 39, 40 and 41. Three of them. Each pin has one smartpin. Each smartpin does only one job at a time.
Each pin input can be rerouted, by the mode bits, to up to six other nearby pin INs. This saves using any linking wires. Which is what Chip has done for two of the three smartpins in the original Reciprocal Counter Demo.
You only need the one active pin. The mode configurable re-routing works on physical pin inputs only. It doesn't shortcut anything. So, you can fully test each pin input and output without any loopback wires.
In my config above the pin under test is MSR_PIN. The fact that there is two extra smartpins involved doesn't detract from it being a real physical action on that pin - With both the output driver slewing times and the input threshold propagation times.
There is block diagram we put together that might help - https://forums.parallax.com/discussion/171420/smartpin-diagram/p1
The "Logic Input" block is where to select the routed inputs. Each is from another nearby pin input, just the same way as the immediate input is routed. In fact, for the odd pin, -1 is even shown coming from the even pin. And, for the even pin, +1 is coming from the odd pin.
Comments
Yes the block diagram and maths are simple.
Chip added support in the smart pins to make the hardware details simple too..
(it can get tricky to ensure the two captures of time and cycles are made on the same edge, and ideally, you want lossless/gapless capture too, so 10 or 100 captures of time and cycles can be summed to give higher precisions )
I guess they mean "reciprocal of frequency" counter.
But "reciprocal of frequency" == period.
I think that would make usage more clear.
But, when you google "period counter" you get other stuff, which is maybe why the chose this name...
I used it to do the other waves that you helped me with in the past.
I think it started as a simple one-word prefix so 'Frequency Counter' became 'Reciprocal Frequency Counter'.
If you wanted to create a new name, 'period counter' infers it measures a single periods, which is inaccurate.
'whole periods timer' is clearer, in that now includes key elements of measuring the time over N Whole Periods, and then calculates N/Time to give Cycles/Second units.
- however, because the final units are Hz, including Frequency in the name seems important. - Instrument users care less about the how, than what they ultimately measure.
On that note, the thread tile would be better as Reciprocal Frequency Counter Demo
@cgracey
Hey guys been a while. I have been working at home teaching aircraft mechanics teaching our academic side without lab. Each 24 days is a new class. Took three classes to get all dialed in.
I am now back learning this P2 asm and asm stuff.
Much thanks to @cgracy for the reciprocal counter demo and much thanks to @evanh for his help.
I stripped out the counter demo code to get to the asm code to print to the serial terminal.
Think because of now starting from the basics I am getting a much better understanding. Thanks to evanh I think I am getting it. I looked up the pop command on youtube and get it.
I have a couple of questions that I commented in the attached code. If either of you or anybody else have a minute would you please answer them.
Much thanks.
Martin
Many Thanks for the test code.
I have been testing it on recent FlexProp and PNUT and (Thanks to Ozpropdev!) have found a few thinks that I think it is worth mentioning.
For flexprop will need to add a LineFeed (10) : (otherwise, output will rewrite the current line)
For PNUT we can add this line (to avoid error message "DEBUG requires at least 10MHz of Crystal" when we use DEBUG, CTRL+F10):
I was able to check the frequency of my DP83848 Ethernet board 50MHz oscillator output pin (OSCIN)
IMPORTANT: If there is no signal present, then there will be not output at all on the serial terminal or debug terminal !
Not the last value of x, but takes the last value off the stack and puts it into the x variable (register). Overwriting the old value of x.
Almost. This is architecture dependant but the common (propeller2) behaviour is when a routine is CALLed the program counter of the calling routine is pushed to the stack for later retrieval by a RET instruction. At the CALL time, the program counter holds the address of the subsequent instruction after the CALL ... so that is the address that gets pushed on to the stack.
EDIT: Formatting
The SHL is multiplying x by 4. This is typical when rescaling an index or pointer. In this case x contains a cogRAM address so is longword scaled. But to use GETBYTE requires byte scaling, hence the times 4.
ALTGB is a prefixing instruction. A prefixing instruction means it modifies the behaviour of the subsequent instruction. The ALTxx instructions in general are a little hard to get and keep your head wrapped around. They provide what's called indirect addressing, or referencing in loose C speak. The trick is remembering that the variable holds an address, as opposed to holding the data.
ALTGB is tailored for prefixing GETBYTE, it won't correctly prefix any other instruction. There is other prefixes that are generic and function with many or most other instructions. ALTGB has two forms, the above form is simply copy a byte from location x and place it in y. x can address anywhere in cogRAM.
How can I convert this PASM code to SPIN2 with the minimal lines of code?
I tried in this way, but failed:
While not an answer to your Spin2 code conversion question, take a look at the TSL235R Quick Byte that I wrote. I converted Chip's standalone Reciprocal Counter PASM2 code to inline PASM2 and placed it into two driver routines:
Inline PASM2 code lets you have the best of both worlds, easier programming/integration in Spin, while still having speedy PASM2 routines.
Ramon,
You won't be able to JMP between assembly blocks like that. Each Pasm block is handled one at a time with just what is defined for it, not unlike Spin methods. Any branching will have to be within a block.
Francis, many thank for your help. I will take a look to that code, I am yet a little scared by PASM and try to use the most simple SPIN keywords. Nice that you can reduce the number of smart pins used. I was about to ask if it could be possible to just use one smart pin to detect frequency.
Evanh, yes I thought that the loop would not execute but in fact was repeating the code. Those ASM instructions I am not sure how to correctly convert into SPIN.
Here is a simple version in Spin2. I use P40 as input and output a test-frequency at P39, which is connected to pin 40 with a wire. It only measures the frequency, not the duty.
Andy
Thank you Ariba!
I got it working, but I think you have some typo on lines 4 and 7.
Also the last parameter (1_000_150 frac clkfreq) seems to result zero always in (%00).
According to SPIN docs, the frac equivalent should be:
Is that some mistake, or copy&paste from another code?
I am able to run the code with good results when I change the '1_000_150 frac clkfreq' with '%00'.
I have made a Flexprop version (for Retroblade2) here (Flexprop doesn't allow addpins, frac, or debug instructions)
It is working. But still have no idea how it works. why do we need two pinstarts (first NCO mode, and later ticks counter) for MSR_PIN?
pinstart(MSR_PIN, P_NCO_FREQ+P_OE, 1, (1_000_150<<32) / clkfreq) 'test freq
pinstart(MSR_PIN+0, P_COUNTER_TICKS, mintime, %00)
pinstart(MSR_PIN+1, P_MINUS1_A + P_MINUS1_B + P_COUNTER_PERIODS, mintime, %00)
By the way, what is a TICK? rise or fall?
And what are periods? Is a 'period' according to our system clock, or a full cycle (period) detected while reading the pin?
These are the kind of examples that I will never understand until some nice diagrams or drawings are made.
I output a test frequency on Pin 39 which I can vary to test the Frequency counter. For this is the pinstart on the first line in main(), it just starts an NCO. If you don't need that you can delete this line.
The counter input is on the MSR_PIN and the MSR_PIN + 1, which is pin 40 and pin 41 in my code (you seem to use pin 0 and 1).
My code works also with Flexprop without any modification. Flexprop knows FRAC, ADDPINS and DEBUG (in this simple form). Maybe you have a very old version.
A tick is one single sysclock clock. Raise or fall defines if the positive or the negative edges of the input frequency are use to measure the periods. A period is the time from one positive edge to the next positive edge of the input signal.
One smartpin (41) measures the number of periodes that fit into the 1ms window, and the other smartpin (40) measures the time that all these periods take. They don't stop instantly after the 1ms time window, like a simple frequency counter. No they both finish the last periode that goes over the 1ms window, that's the trick of this reciprocal counter.
If you know the time that a certain number of periods take, you can calculate the frequency from that.
Andy
I think you need to update your flexprop. addpins, frac, and debug have been supported for some time now.
How is debug supported? I presume not via loadp2 -t.
It is exactly via loadp2 -t . debug statements just get translated into the equivalent of BASIC "print" statements. The backtick kinds of debug (for graphics) just print the backtick strings, no graphics. debug() statements in PASM code are ignored.
Ah, no graphics makes sense. But still not getting anything reported with the simple demo from Pnut's .zip
PS: I'm not using Flexprop. Flexspin and Loadp2 are hand entered in the shell.
@evanh : DEBUG() statements are optional (as they are in PNut). In order to enable debug() flexspin needs the -g flag on the command line. We should probably continue this on the flexspin thread if you have more questions.
Thanks, that got it. The needed .c sources was a surprise.
I was using 5.2.0. I just downloaded 5.3.2, and looks that it is the same error I had before.
Ariba, Thank you for explaining all the details. Now I understand.
Never occurred to me that something like that was possible !!
Being able to configure the (smart)pin for output to create a test frequency and at the same time configure the same pin with counter function for input is like having two smartpins on each pin.
That could be great to make a simple test program that can check all pin input/ouputs. (with a wire between each pin pair:
Much cheaper than 64 resistors + LEDs.
Ah, I see the problem, your file is named .spin (for Spin 1) instead of .spin2 (for Spin 2). The two languages are slightly different, unfortunately. To use Spin2 operators like addpin or frac you need to name the file with a .spin2 extension.
Haha, Sorry !! At least, that time was not wasted. I have learned what those instructions were doing.
You can do all that and more without any wires at all. However, Ariba used smartpin's 39, 40 and 41. Three of them. Each pin has one smartpin. Each smartpin does only one job at a time.
Each pin input can be rerouted, by the mode bits, to up to six other nearby pin INs. This saves using any linking wires. Which is what Chip has done for two of the three smartpins in the original Reciprocal Counter Demo.
Here's Ariba's setup without any wires needed:
Is it possible to generate a test frequency and calculate its frequency, with just two pins?
I don't want to save any wire. The wire is a requirement, to be able to test the pins output and input.
You only need the one active pin. The mode configurable re-routing works on physical pin inputs only. It doesn't shortcut anything. So, you can fully test each pin input and output without any loopback wires.
In my config above the pin under test is MSR_PIN. The fact that there is two extra smartpins involved doesn't detract from it being a real physical action on that pin - With both the output driver slewing times and the input threshold propagation times.
There is block diagram we put together that might help - https://forums.parallax.com/discussion/171420/smartpin-diagram/p1
The "Logic Input" block is where to select the routed inputs. Each is from another nearby pin input, just the same way as the immediate input is routed. In fact, for the odd pin, -1 is even shown coming from the even pin. And, for the even pin, +1 is coming from the odd pin.