===== Switch LED with button =====
==== Idea ====
The LED in a button is to be switched on and off safely.
==== Implementation ====
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.
==== Pseudo code for togglgeLED implementation ====
//What [[en:pfw:pseudocode|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
==== Forth implementation of toggleLED ====
\ 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
==== Glossary ====
''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.
==== Background information ====
See [[en:pfw:clavis|clavis?]] and [[en:pfw:tasto|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.
==== Possible Pitfalls ====
None so far.
==== Contributions ====
You have another approach?
Please add it at the end of this document.