How can you check a specific pin number inside of a cogs ina register in PASM?
Hello,
With spin, I would write temp := ina[6]
With PASM, I'm able to view all of the pins with "mov pinsState, ina" and then writing pinsState but I'm not sure how to do a cmp to 1010111100000000000000000[size=+2]1[/size]000000 ?
I'd like to do:
cmp pinsState, #1 or cmp pinsState, #0
Is this possible?
With spin, I would write temp := ina[6]
With PASM, I'm able to view all of the pins with "mov pinsState, ina" and then writing pinsState but I'm not sure how to do a cmp to 1010111100000000000000000[size=+2]1[/size]000000 ?
I'd like to do:
cmp pinsState, #1 or cmp pinsState, #0
Is this possible?

Comments
try this:
mov ina,ina 'copy to shadow
and ina,_mypin wz
if_z ...
test my_pin,ina wz ... my_pin long 1 << pin_number-Phil
And if I wanted to check for that pin being low, then
mov ina, ina andn ina, camPwmMonitorPinMask WZ if_e mov highCycles, phsatest camPwmMonitorPinMask, ina wz if_z mov highCycles, phsaI've never used test before and am trying to wrap my head around it
in this case is the same as
How would this work with testing the pin being low?
-Phil
I'm sure I'm not the only one with many bit operation examples translated into binary.
Sorry, Brad and others for the OT (but not too much so) rant.
Explanation
TEST is similar to AND except it doesnt write a result to Value1; it performs a bitwise AND of the values in Value1 and Value2 and optionally stores the zero-result and parity of the result in the Z and C flags.
If the WZ effect is specified, the Z flag is set (1) if Value1 AND Value2 equals zero. If the WC effect is specified, the C flag is set (1) if the result contains an odd number of high (1) bits.
test against a low to then move high cycles
test 00000000000000000000000001000000, 10101111000000000000000000000000 WZ, WC
if_z mov highCycles, phsa ' if they AND to 0, Z is set to 1
I understand how this AND works, because the only one that is high in the pin mask is pin 6 and I guess test sets Z to 1 because no 1's are returned from the AND operation?
test against a high to then move low cycles
test 00000000000000000000000001000000, 10101111000000000000000001000000 WZ
if_nz mov lowCycles, phsb ' if they AND to 1, Z is set to 0
And with this one, if it is ANDed together, there is a single 1 from the AND operation, so test sets the Z flag to 0?
Do I have it?
odd bits/C=1
even bits/C=0
So if a bit from ina is high, all the bits below are ANDed together and 1 of them results in an odd number of bits (1)
0000000000000000000000000[size=+2]1[/size]000000 (pin mask)
ANDed
1010111100000000000000000[size=+2]1[/size]000000
=
0000000000000000000000000[size=+2]1[/size]000000
C=1
and if a bit is low, all the bits are ANDed together and 0 of them result in an odd number of bits (0)
0000000000000000000000000[size=+2]1[/size]000000 (pin mask)
ANDed
1010111100000000000000000[size=+2]0[/size]000000
=
0000000000000000000000000[size=+2]0[/size]000000
C=0
I take it this is best used when testing a single pin?
-Phil
I can't figure out what I'm doing wrong here?
The binary value of pinReadMask is 00000000000000000000001000000000
I can see pstPtr16 oscillating between 1 and 0 and I've set the counters up as shown below.
highCycles is always 0 and lowCycles is at least doing something, does the format at least look correct?
highCycles should read ~66500
lowCycles should read ~200000
test pinReadMask, ina WZ ' test if pin is high or low if_z mov highCycles, phsa if_z wrlong one, pstPtr16 if_z wrlong highCycles, pstPtr13 test pinReadMask, ina WC if_c mov lowCycles, phsb if_c mov phsb, #0 ' clear high phase counter if_c wrlong zero, pstPtr16 if_c wrlong lowCycles, pstPtr14mov ctra, POS_DETECT ' ctra measures high phase add ctra, pinReadMask mov frqa, #1 mov ctrb, NEG_DETECT ' ctrb measures low phase add ctrb, pinReadMask mov frqb, #1movs ctra, #pin movi ctra, #%0_01000_000 ' POS detect test mask, ina wc mask long |< pinpinRead is 22, pinReadMask is 00000000010000000000000000000000
pin is 26, pinMask is 00000100000000000000000000000000
POS_DETECT long %01000 << 26
NEG_DETECT long %01100 << 26
I would like to read the high cycles when the pin goes low, and the low cycles when the pin goes high, but without a wait command as well as then clear the high cycles when the pin is low and clear the low cycles when the pin is high, again without any wait commands.
I've reread what everyone has written a bunch of times and to me, the code below should work based on my understanding, and it is not.
initialize mov pinMask, #1 ' create mask from pin # rdlong pin, pinAddrPtr shl pinMask, pin mov dira, pinMask mov pinReadMask, #1 ' create mask from pin # rdlong pinRead, pinReadAddrPtr shl pinReadMask, pinRead mov ina, pinReadMask mov ctra, pinRead mov ctra, POS_DETECT ' ctra measures high phase mov frqa, #1 mov ctrb, pinRead mov ctrb, NEG_DETECT ' ctrb measures low phase mov frqb, #1 mov phaseState, phaseOnetest pinReadMask, ina WC ' test for low if_nc mov highCycles, phsa if_nc mov phsb, #0 if_nc wrlong one, pstPtr16 if_nc wrlong highCycles, pstPtr14 test pinReadMask, ina WC ' test for high if_c mov lowCycles, phsb if_c mov phsa, #0 ' clear high phase counter if_c wrlong zero, pstPtr16 if_c wrlong lowCycles, pstPtr15Thanks for the reply and pointing out that I'm clearing on the wrong 1/2 of the cycle, I've changed that to what is reflected below but it still isn't working? I've also changed the initialize code to reflect the following.
I have my full object with lots of pasm and lots of debugging/commenting. Would you rather me create something simple?
What I would like to do is:
when pin == 1, copy phsb to lowCycles, then clear phsb
when pin == 0, copy phsa to highCycles, then clear phsa
Does my code look close if I switch to
test pinReadMask, ina WC ' test for low if_nc mov highCycles, phsa if_nc mov phsa, #0 if_nc wrlong one, pstPtr16 if_nc wrlong highCycles, pstPtr14 test pinReadMask, ina WC ' test for high if_c mov lowCycles, phsb if_c mov phsb, #0 ' clear high phase counter if_c wrlong zero, pstPtr16 if_c wrlong lowCycles, pstPtr15Let me know if you'd like me to try to build some simple object. Thanks!
Here is the object itself, if you need the entire project, please let me know.
Thank you again.
Here is what the pst is seeing (as a general example, the numbers are changing with each refresh)
cmp pinReadState, waitForLow WC, WZ if_e jmp #low cmp pinReadState, waitForHigh WC, WZ if_e jmp #high low test pinReadMask, ina WC, WZ ' test for low if_z mov highCycles, phsa if_z mov phsa, #0 if_z wrlong one, pstPtr16 if_z wrlong highCycles, pstPtr14 if_z mov pinReadState, waitForHigh high test pinReadMask, ina WC, WZ ' test for high if_c mov lowCycles, phsb if_c mov phsb, #0 ' clear high phase counter if_c wrlong zero, pstPtr16 if_c wrlong lowCycles, pstPtr15 if_c mov pinReadState, waitForLowCON _clkmode = XTAL1|PLL16X _xinfreq = 5_000_000 pin = 16 OBJ serial: "FullDuplexSerial" VAR long storage[2] long stack[32] PUB null serial.start(31, 30, %0000, 115200) cognew(pulse, @stack{0}) cognew(@entry, @storage{0}) waitcnt(clkfreq*3 + cnt) serial.tx(0) repeat serial.hex(storage{0}, 8) serial.tx(32) serial.hex(storage[1], 8) serial.tx(13) waitcnt(clkfreq/2 + cnt) PRI pulse dira[pin]~~ ctra := constant(%0_00100_000 << 23 | pin) repeat frqa := $00000100 waitcnt(clkfreq*2 + cnt) frqa := $00000080 waitcnt(clkfreq*2 + cnt) DAT org 0 entry add pulse_h, par add pulse_l, par movs ctra, #pin movi ctra, #%0_01000_000 ' POS movs ctrb, ctra movi ctrb, #%0_01100_000 ' NEG mov frqa, #1 mov frqb, #1 loop [COLOR="blue"]cmp edge, #1 wz[/COLOR] ' rising edge test? [COLOR="blue"]if_z[/COLOR] [COLOR="orange"]test mask, ina wc[/COLOR] ' Y [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_c[/COLOR] mov phsb, phsb ' sample [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_c[/COLOR] wrlong phsb, pulse_l ' report [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_c[/COLOR] mov phsb, #0 ' clear [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_c[/COLOR] xor edge, #1 ' next is falling edge [COLOR="blue"]cmp edge, #0 wz[/COLOR] ' falling edge test? [COLOR="blue"]if_z[/COLOR] [COLOR="#FFA500"]test mask, ina wc[/COLOR] ' Y [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_nc[/COLOR] mov phsa, phsa ' sample [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_nc[/COLOR] wrlong phsa, pulse_h ' report [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_nc[/COLOR] mov phsa, #0 ' clear [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_nc[/COLOR] xor edge, #1 ' next is rising edge ' other in-loop code jmp #loop edge long 0 mask long |< pin pulse_h long 0 pulse_l long 4 fit DATGenerated output. Note that there are occasional transitions visible because the frequency change doesn't happen in sync with the square wave.I was able to get this to work a few minutes ago, but it was discovered through attrition. I'll be using your code to learn more about this, as I obviously have a huge gaping hole in my PASM knowledge when it comes to checking a pins input state. I want to make sure my head is completely wrapped around this, before moving to the next code that I have to write. Believe it or not, I'm pretty much an ADC/DAC away from testing this out in the car!
I was told that you could not do a conditional condition, such as
cmp x, y
if_e cmp, x, z
Is that incorrect? I see that you've done that with cmp/test, is it special with the test operation or can you do as I've written above?
Thank you again for the help.
cmp pinReadState, waitForLow WC, WZ if_e jmp #low cmp pinReadState, waitForHigh WC, WZ if_e jmp #high low test pinReadMask, ina WC, WZ ' test for low, and if low if_z mov highCycles, phsa if_z mov phsa, #0 if_z wrlong one, pstPtr16 if_z wrlong highCycles, pstPtr14 if_z mov pinReadState, waitForHigh if_nz jmp #phases high test pinReadMask, ina WC, WZ ' test for high, and if high if_c mov lowCycles, phsb if_c mov phsb, #0 ' clear high phase counter if_c wrlong zero, pstPtr16 if_c wrlong lowCycles, pstPtr15 if_c mov pinReadState, waitForLow phasesWhat's the branch condition in this case?
if_z_and_c mov [COLOR="blue"]phsb[/COLOR], phsb ' sample if_z_and_c wrlong [COLOR="blue"]phsb[/COLOR], pulse_l ' report if_z_and_c mov phsb, #0 ' clearThe counter is considered inactive at this point. The phase register can't be written directly to hub (shadow/counter) so we have to copy it first to a location which can be used in the destination slot (shadow or regular register). The final move affects both, counter and shadow register. An equivalent sequence would be:if_z_and_c mov [COLOR="orange"]temp[/COLOR], phsb ' sample if_z_and_c wrlong [COLOR="orange"]temp[/COLOR], pulse_l ' report if_z_and_c mov phsb, #0 ' clearOk, so in PASM you can do if && if, or if || if? I did not know that, but that will be handy.
I like puzzles! I believe it would be if x=y but x!=z, jump to #label? My question is, if x!=y, does it satisfy the if_ne also? If that is true, how would you handle that, with a jump, or is there something a little cleaner/universal like a break?
You mean x == y AND x <> z? If so, not quite (one out of three). Just take it one step at a time. You have 4 input conditions (x <> y, x == y, x <> z, x == z) what happens for each pairing?
Ok, I'm not sure yet if I'm looking at this correctly, because I'm still unclear if these are always evaluated conditionally/together, or they can be evaluated separately line by line? If the second comparison is always evaluated only if the first comparison is equal, then I believe I have the below correct. It's like a 2 digit binary equation : )
x==y / x!=z := true
x==y / x==z := false
x!=y / x!=z := false
x!=y / x==z := false