PASM Waitneq, waitpeq, and spin parm passing for button pressed.
Hello,
I could use some help here
this is my code snippet and vars
'vars:
datamask_dira long %00000000_00000011_11011100_00000000
datamask_PUPD long %00000000_00000000_11010000_00000000
pin_status long 0
waiteq_test long %00000000_00000000_00100000_00000000
Pin13_Dsel1 long |< 13 ' pin 13
one long 1
'setup:
mov dira, datamask_dira ' %00000000_00000011_11011100_00000000
mov outa, datamask_PUPD ' %00000000_00000000_11010000_00000000
'code:
:button test waiteq_test,INA wc 'test pin 13 if high or low
rcl pin_status,#20 ' move wc flag to pin_status
cmp pin_status,one wz ' check pin status = 1 (high)
if_e jmp #:start ' jump to start code running
jmp #:button ' else keep waiting
:start mov loop_length, loop_reset 'start main code running
and when I press button (pin 13), I get the button high,

but for some reason the code never starts,
if I make cmp one,one wz the code runs, so it seems the test if not right

when I press the button, my logic analyzer shows the button is pressed
it seems the code is broken, I also tried
:button waitpeq Pin13_Dsel1,Pin13_Dsel1 ' pin 13 button to run code.
which had the same result,
thanks in advance
regards
Jeff

Comments
additional data:
just for sanity check I wrote this in spin
CON _clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 5_000_000 Pin13 = 13 'pin connected to a LED via a resistor VAR long symbol OBJ pst : "FullDuplexSerial" PUB test_pin pst.Start(31, 30, %0000, 115200) dira[Pin13] := 0 'set direction repeat 'forever if INA[13] == 1 pst.str(string("Pin13 is High:", 13)) 'set it high else pst.str(string("Pin13 is low",13)) 'one second waitcnt(clkfreq + cnt) 'one second PRI private_method_name DAT name byte "string_data",0`the output from this when I use the PST is, when pressing the key
Pin is low
Pin is low
Pin is low
Pin is low
Pin is High:
Pin is High:
Pin is High:
Pin is High:
Pin is High:
Pin is low
Pin is low
Pin is low
anyway, also don't get why this doesn't seem to work for me
:button test waiteq_test,INA wc if_c jmp #:start jmp #:buttonI thought maybe this helps
Jeff
If you're looking for a button press (or IO state) you can use waitpxx instructions. This bit of code will take the pin to monitor in the par register, and then write false (0) or true (-1) based on the state of the pin. I tested with an active-low button and it works (code is attached).
dat org 0 entry rdlong t1, par ' get pin # from par mov btnmask, #1 ' convert to mask shl btnmask, t1 btn_loop mov t1, #0 ' set button state = false wrlong t1, par waitpne btnmask, btnmask ' wait for press neg t1, #1 ' set button state = true wrlong t1, par waitpeq btnmask, btnmask ' wait for release jmp #btn_loop ' -------------------------------------------------------------------------------------------------- btnmask res 1 ' mask for input pin t1 res 1 ' work vars t2 res 1 t3 res 1 fit $1F0BTW, your code samples will be easier to read if you put three back-ticks (`) on the line above and the line after -- this will cause the forum to format it for you.
This shows that you can do it with test, but if there's no compelling reason not to use waitpxx, I'd do that.
ready mov t1, #0 ' set button state = false wrlong t1, par wait_press test btnmask, ina wc if_c jmp #wait_press neg t1, #1 ' set button state = true wrlong t1, par wait_release test btnmask, ina wc if_nc jmp #wait_release jmp #readyThis works, too. Again, I was using an active-low input, so 0 = pressed.
BTW, I think your problem may have been with
What you really want to do is put the C flag into bit0 of pin_status. With the RCL instruction, I don't think you'll ever get pin_status to be 1 which is your target value.
This update works with the style you're using -- but you're using four instructions where you could use one.
wait_press test btnmask, ina wc muxnc pinStatus, #(1<<0) ' !c --> pinStatus.bit0 cmp pinStatus, PRESSED wz if_ne jmp #wait_pressHello,
thank you for the code to test my button,
the good news is that it work(ish)
here is the code, I think yours was P2, so I trimmed it down a little, anyway, the button works, what I mean is that the button works when I press reset, if I press reset I get (on the PST), this output, I pressed reset button 4 times,
started button testing
Pressed
released
started button testing
Pressed
released
started button testing
Pressed
released
started button testing
Pressed
released
so it seems to be happy, except when I press my pin13 button, which is active high, vs active low in your code.
Here is my code, with ticks'
`{Object_Title_and_Purpose} CON _clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 5_000_000 Pin13 = 13 'pin connected to a LED via a resistor VAR long symbol long btnState long param1 long param2 OBJ pst : "FullDuplexSerial" PUB test_pin | last pst.Start(31, 30, %0000, 115200) pst.str(string("started button testing ", 13)) btnState := 2 cognew(@entry, @btnState) last := false repeat if btnState <> last last := btnState if last == false pst.str(string("released", 13)) 'set it high else pst.str(string("Pressed", 13)) waitcnt(clkfreq + cnt) 'one second PRI private_method_name DAT org 0 entry rdlong t1, par ' get pin # from par mov btnmask, #1 ' convert to mask shl btnmask, t1 btn_loop mov t1, #0 ' set button state = false wrlong t1, par waitpne btnmask, btnmask ' wait for press neg t1, #1 ' set button state = true wrlong t1, par waitpeq btnmask, btnmask ' wait for release jmp #btn_loop ' -------------------------------------------------------------------------------------------------- btnmask res 1 ' mask for input pin t1 res 1 ' work vars t2 res 1 t3 res 1 fit $1F0`so I don't get it, in spin it works fine, press the button all is good, normally I would think my button is broken, but the spin code works fine, and it matches my LA, also in my pasm code, i sent the and'ed INA data to the LA, and it also shows the pin going low to high when pressed, when the button is not pressed the INA shows nothing high, (button not pressed), I think I doing something dumb in my code, but the same thing happens when I use your code, but the button is simply wired to pin 13. and tied to 3.3 volt when the button is pressed, causing it to go active high. normally low.
I have to think about this for awhile
thanks for the code, I'll keep trying
regards
Jeff
I'll try switching it to active low,
regards
Jeff
Depending on the button type you might try a debounce time delay of 20 or 30 milliseconds because the contacts in a normally open push button will bounce between closed and open for some milliseconds before settling in the closed position. The value of the delay depends on the type of switch you’re using.
Something like this:
ok, but I'm not seeing bounce, but worth trying, here is the LA, of the low to high
I think I need some resistors, so I'll see Monday, button is in the lower left corner, goes to pin 13 on the mini prop board.
You're welcome.
It works. Period. I tested it.
Nope, it's P1 (I've been doing this a long time, I know the difference).
If you're hungry and a stranger hands you a meal, do you throw some of it away before trying it?
I know you need resistors. If you want your button to be active-high (1 when pressed), put a pull-down between the pin and ground. If you want your button to be active-low (0 when pressed), put a pull-up between the pin a Vcc (3.3v). For buttons 10K pull-down/pull-up is a bit of a standard.
I reconfigured my board and it runs fine using active-high -- I just had to exchange the waitpne and waitpeq instructions.
Sandy makes a good point. This is how I implemented it in the demo I posted earlier.
dat org 0 entry mov t1, par ' t1 is start of hub values (btnState) rdlong t2, t1 ' get pin # mov btnmask, #1 ' convert to mask shl btnmask, t2 add t1, #4 ' point to send long (param1) rdlong btnticks, t1 btn_loop mov t1, #0 ' set button state = false wrlong t1, par wait_press waitpeq btnmask, btnmask ' wait for press mov t1, cnt add t1, btnticks waitcnt t1, #0 test btnmask, ina wc ' re-scan if_nc jmp #wait_press ' if not pressed, wait again neg t1, #1 ' set button state = true wrlong t1, par waitpne btnmask, btnmask ' wait for release wait_release jmp #btn_loop ' -------------------------------------------------------------------------------------------------- PRESSED long 1 pinStatus long 0 btnmask res 1 ' mask for input pin btnticks res 1 ' debounce delay t1 res 1 ' work vars t2 res 1 t3 res 1 fit $1F0jon,
I appreciate you help, and yes, agreed to your comments, monday I will add the resistors, I know your code works, and I know you have been at this for awhile, I did try switching the waits, but just to test, but the button didn't work, so hardware issue.
by the way, so does spin do things differently internally when checking pins?
regards
Jeff
No. That said, the P1 and P2 interpreters are quite complex as the interleave multiple instructions in small sections of code.
Consider this line of code:
In Spin, we could have a single pin (as shown) or a pin range, and we could even swap the order of the pin range. For a single-pin input, the mechanism I showed you in the demo is the approach most people seem to take with a single pin (have a look in fullduplexserial which is one of the earliest P1 drivers released).
-- set pin mask to 1
-- shift mask left by pin #
then...
-- test against ina register; result is in C flag
Another approach:
-- read ina into temp variable
-- shift temp right by pin #
-- and temp with #1
For multiple simultaneous inputs there is more to the process
-- create pins mask from number of pins to scan
then...
-- read ina into temp variable
-- shift temp right by LSB pin number
-- and temp with group mask
This blurb takes two pins passed in the via par register, extracts them, creates a mask for the number of the pins in the range, then samples those inputs.
entry rdlong t1, par ' get packed pins mov lsbpin, t1 ' extract pins and lsbpin, #$1F mov msbpin, t1 shr msbpin, #8 and msbpin, #$1F mov t2, msbpin ' # pins sub t2, lsbpin add t2, #1 neg swmask, #1 ' mask = all 1s shl swmask, t2 ' create inverted mask neg swmask, swmask ' invert range mask sub swmask, #1 read_switch mov temp, ina ' sample inputs shr temp, lsbpin ' align for lsb and temp, swmask ' mask off other pinsThere are lots of assembly wizards (I'm not one of them, though I do write working code) that may have more thoughts. Listen to them.
That multiple pin reading would be quite handy, anyway Monday I'll do this (not sure about the 100 ohm), I'll go with the 10K first
and get back with the button test results
regards
Jeff
The 100-ohm resistor will protect the pin if it's made an output and low and the button is pressed. Most of us don't put those series resistors on production boards, but they are found on educational products, and for good reason.
Well, this now works. but I went a slightly different way, I never got the P13 working under asm for a waitpne or waitpeq, i think it is a board issues on my design, so I went back to spin and did it that way by passing parms
basically it is fairly simple.
in the spin code i did this:
in the asm code I did this:
and the spin parms list
and the asm parms list
what i did find was that starting the cogs, as far as accessability, you need to wait alittle bit
so this is the cog starts
comments are welcome, I will eventually go back to a better test of the button 13, It will work if you use a breadboard, so that will eventually happen
regards
Jeff
Forgot to show the button working, here is an example of when you press the button.
the flow is left to right, first the button is detected, then the program start executing
and as mentioned in thread, it needed a debounce routine, without it you get to many pulses.