diff options
Diffstat (limited to 'docs/tutorial/switch.rst')
-rw-r--r-- | docs/tutorial/switch.rst | 101 |
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. |