summaryrefslogtreecommitdiffstatshomepage
path: root/docs/tutorial/switch.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/tutorial/switch.rst')
-rw-r--r--docs/tutorial/switch.rst101
1 files changed, 101 insertions, 0 deletions
diff --git a/docs/tutorial/switch.rst b/docs/tutorial/switch.rst
new file mode 100644
index 0000000000..759fea8ffe
--- /dev/null
+++ b/docs/tutorial/switch.rst
@@ -0,0 +1,101 @@
+The Switch, callbacks and interrupts
+====================================
+
+The pyboard has 2 small switches, labelled USR and RST. The RST switch
+is a hard-reset switch, and if you press it then it restarts the pyboard
+from scratch, equivalent to turning the power off then back on.
+
+The USR switch is for general use, and is controlled via a Switch object.
+To make a switch object do::
+
+ >>> sw = pyb.Switch()
+
+Remember that you may need to type ``import pyb`` if you get an error that
+the name ``pyb`` does not exist.
+
+With the switch object you can get its status::
+
+ >>> sw()
+ False
+
+This will print ``False`` if the switch is not held, or ``True`` if it is held.
+Try holding the USR switch down while running the above command.
+
+Switch callbacks
+----------------
+
+The switch is a very simple object, but it does have one advanced feature:
+the ``sw.callback()`` function. The callback function sets up something to
+run when the switch is pressed, and uses an interrupt. It's probably best
+to start with an example before understanding how interrupts work. Try
+running the following at the prompt::
+
+ >>> sw.callback(lambda:print('press!'))
+
+This tells the switch to print ``press!`` each time the switch is pressed
+down. Go ahead and try it: press the USR switch and watch the output on
+your PC. Note that this print will interrupt anything you are typing, and
+is an example of an interrupt routine running asynchronously.
+
+As another example try::
+
+ >>> sw.callback(lambda:pyb.LED(1).toggle())
+
+This will toggle the red LED each time the switch is pressed. And it will
+even work while other code is running.
+
+To disable the switch callback, pass ``None`` to the callback function::
+
+ >>> sw.callback(None)
+
+You can pass any function (that takes zero arguments) to the switch callback.
+Above we used the ``lambda`` feature of Python to create an anonymous function
+on the fly. But we could equally do::
+
+ >>> def f():
+ ... pyb.LED(1).toggle()
+ ...
+ >>> sw.callback(f)
+
+This creates a function called ``f`` and assigns it to the switch callback.
+You can do things this way when your function is more complicated than a
+``lambda`` will allow.
+
+Note that your callback functions must not allocate any memory (for example
+they cannot create a tuple or list). Callback functions should be relatively
+simple. If you need to make a list, make it beforehand and store it in a
+global variable (or make it local and close over it). If you need to do
+a long, complicated calculation, then use the callback to set a flag which
+some other code then responds to.
+
+Technical details of interrupts
+-------------------------------
+
+Let's step through the details of what is happening with the switch
+callback. When you register a function with ``sw.callback()``, the switch
+sets up an external interrupt trigger (falling edge) on the pin that the
+switch is connected to. This means that the microcontroller will listen
+on the pin for any changes, and the following will occur:
+
+1. When the switch is pressed a change occurs on the pin (the pin goes
+ from low to high), and the microcontroller registers this change.
+2. The microcontroller finishes executing the current machine instruction,
+ stops execution, and saves its current state (pushes the registers on
+ the stack). This has the effect of pausing any code, for example your
+ running Python script.
+3. The microcontroller starts executing the special interrupt handler
+ associated with the switch's external trigger. This interrupt handler
+ get the function that you registered with ``sw.callback()`` and executes
+ it.
+4. Your callback function is executed until it finishes, returning control
+ to the switch interrupt handler.
+5. The switch interrupt handler returns, and the microcontroller is
+ notified that the interrupt has been dealt with.
+6. The microcontroller restores the state that it saved in step 2.
+7. Execution continues of the code that was running at the beginning. Apart
+ from the pause, this code does not notice that it was interrupted.
+
+The above sequence of events gets a bit more complicated when multiple
+interrupts occur at the same time. In that case, the interrupt with the
+highest priority goes first, then the others in order of their priority.
+The switch interrupt is set at the lowest priority.