The LED in a button is to be switched on and off safely.
The challenge is to give the user a sure feeling when switching. Nothing should flicker and there must be no doubt about the state of the switch.
In order to achieve this, bounce in the switch must be removed by software.
What Pseudo code is.
Function: init ( -- ) set all ports, values, variables ... Function: toggleLED ( -- ) \ Demo LOOP: IF: button was pressed, toggle LED halt testing button IF: button has been released stabel H enable testing again ENDLOOP if any key is pressed
\ Switch LED with button \ TI MSP430G2553 Launchpad with noForth mv 2553 240101 (* History 20250620 toggle LED in button 20250609 P1.7 digital input, some bounce tests addr acronym registername 020 P1IN Input 021 P1OUT Output 022 P1DIR Direction 023 P1IFG Interupt Flag 024 P1IES Interrupt Edge Select 025 P1IE Interrupt Enable 026 P1SEL Port Select 041 P1SEL2 Port Select2 027 P1REN Resistor Enable Pin1.7--<---R---Button---GND Pin1.0-->---R-----Led----GND R=47K *) \ tools\ ( include if it is your latest shield ) \ --- input --- hex 80 constant pin7 \ mask for pin7 of port : PININ ( mask -- ) \ make pin to input ( 020 ) \ P1IN Input, read only dup 021 *bis \ P1OUT Output, pullup resistor set dup 022 *bic \ P1DIR Direction to IN dup 023 *bic \ P1IFG Interupt Flag, cleared dup 024 *bic \ P1IES Interrupt Edge Select, falling \_ dup 025 *bic \ P1IE Interrupt Enable, off dup 026 *bic \ P1SEL Port Select, I/O dup 041 *bic \ P1SEL2 Port Select2, I/O 027 *bis \ P1REN Resistor Enable, set ; : CLAVIS? ( mask -- f ) \ Query button. >r r@ 023 bit* \ test for edge r@ = ( true ) \ button has been pressed r> 023 *bic \ clear edge detection flag. ; : TASTO? ( mask -- f ) \ Query button. debounced >r r@ 020 bit* 3 ms r@ 020 bit* 3 ms and r@ 020 bit* 3 ms and r@ 020 bit* 3 ms and r@ 020 bit* 3 ms and r> = ; \ --- output --- hex 01 constant pin0 : PINOUT ( mask -- ) \ Switch pin P1.0 as output dup 027 *bic \ ren off dup 025 *bic \ ie disable interrupt dup 026 *bic \ SEL I/0 dup 041 *bic \ SEL2 I/0 022 *bis \ set out for P1.0 ; : p1H pin0 021 *bis ; \ set P1.0 to H : p1L pin0 021 *bic ; \ set P1.0 to L \ --- Demo Application --- variable ILED \ LED integrated in button value sem \ semaphor: allows testing : +sem true to sem ; \ some syntactic sugar : -sem false to sem ; : init ( -- ) \ make the various settings at once. pin0 pinout pin7 pinin 0 iled ! +sem p1L ; : setled ( -- ) \ even number is led off iled @ 1 and 0= if p1L else p1H then ; : incled ( -- ) 1 iled +! ; : toggleLED ( -- ) \ toggle LED in button init begin sem if pin7 clavis? if \ if button pressed incled setled \ toggle LED 100 ms \ do some debouncing -sem \ don't test again then then pin7 tasto? if \ if button is released stabel pin7 023 *bic \ clear edgedetection bit to debounce loop +sem \ now allow retesting then \ when the routine gets too fast... 10 ms key? until ; shield nn\ freeze ( finis)
You can use it as follows:
toggleled <ret>
clavis?
and tasto?
are different methods for querying the button.
Clavis?
checks whether there has been a falling edge on the pin. The port pin remembers this in its interrupt flag bit, requiring no additional wiring on the MCU.
Tasto?
, on the other hand, monitors the logic level on the port pin several times in succession. Only when all queries have returned an H level is it assumed that the bouncing is over, i.e., the button has been released.
With these two routines, the state of the LED can be toggled back and forth.
Only when the button has been safely released does clavis?
fire on the next keypress.
The “smaller” Forth words in between are simply factored-out parts of the toggleLED
routine. These are useful during the interactive testing phase.
See clavis? and tasto? for more background information.
Here, clavis?
has been configured to immediately clear its interrupt flag after the query. This isn't really necessary, since it can only be queried again after tasto?
allows it and has cleared the flag.
None so far.
You have another approach?
Please add it at the end of this document.