summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorGlenn Ruben Bakke <glennbakke@gmail.com>2017-02-07 22:26:13 +0100
committerGlenn Ruben Bakke <glennbakke@gmail.com>2017-02-07 22:26:13 +0100
commit4cf7fd151e98a3d842eb5c9428545cb67ddd57ee (patch)
tree947f265a2d498f4879bab3c7d19591133c56c1a0 /docs
parent9397583f6c99533fc4c0a2753126120a8552ba4c (diff)
parent21f08524baf11e62384814b7cb8fcd2b5a8998fb (diff)
Merge branch 'master' into nrf52
Diffstat (limited to 'docs')
-rwxr-xr-xdocs/conf.py10
-rw-r--r--docs/esp8266/tutorial/repl.rst2
-rw-r--r--docs/library/index.rst1
-rw-r--r--docs/library/lcd160cr.rst379
-rw-r--r--docs/library/machine.Timer.rst96
-rw-r--r--docs/library/machine.rst32
-rw-r--r--docs/library/pyb.rst13
-rw-r--r--docs/library/uio.rst65
-rw-r--r--docs/library/usocket.rst240
-rw-r--r--docs/pyboard/general.rst5
-rw-r--r--docs/pyboard/hardware/index.rst1
-rw-r--r--docs/pyboard/tutorial/index.rst1
-rw-r--r--docs/pyboard/tutorial/lcd160cr_skin.rst134
-rw-r--r--docs/static/favicon.icobin0 -> 1406 bytes
-rw-r--r--docs/wipy/quickref.rst3
-rw-r--r--docs/wipy/tutorial/index.rst1
-rw-r--r--docs/wipy/tutorial/timer.rst70
17 files changed, 867 insertions, 186 deletions
diff --git a/docs/conf.py b/docs/conf.py
index 6026aee56..66ea325e9 100755
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -90,7 +90,7 @@ source_suffix = '.rst'
# General information about the project.
project = 'MicroPython'
-copyright = '2014-2016, Damien P. George and contributors'
+copyright = '2014-2017, Damien P. George, Paul Sokolovsky, and contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -178,7 +178,7 @@ else:
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
-#html_favicon = None
+html_favicon = 'favicon.ico'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
@@ -253,7 +253,7 @@ latex_elements = {
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'MicroPython.tex', 'MicroPython Documentation',
- 'Damien P. George and contributors', 'manual'),
+ 'Damien P. George, Paul Sokolovsky, and contributors', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
@@ -283,7 +283,7 @@ latex_documents = [
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'micropython', 'MicroPython Documentation',
- ['Damien P. George and contributors'], 1),
+ ['Damien P. George, Paul Sokolovsky, and contributors'], 1),
]
# If true, show URL addresses after external links.
@@ -297,7 +297,7 @@ man_pages = [
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'MicroPython', 'MicroPython Documentation',
- 'Damien P. George and contributors', 'MicroPython', 'One line description of project.',
+ 'Damien P. George, Paul Sokolovsky, and contributors', 'MicroPython', 'One line description of project.',
'Miscellaneous'),
]
diff --git a/docs/esp8266/tutorial/repl.rst b/docs/esp8266/tutorial/repl.rst
index 1922da128..21e889c9a 100644
--- a/docs/esp8266/tutorial/repl.rst
+++ b/docs/esp8266/tutorial/repl.rst
@@ -24,7 +24,7 @@ terminal programs that will work, so pick your favourite!
For example, on Linux you can try running::
- picocom /dev/ttyUSB0
+ picocom /dev/ttyUSB0 -b115200
Once you have made the connection over the serial port you can test if it is
working by hitting enter a few times. You should see the Python REPL prompt,
diff --git a/docs/library/index.rst b/docs/library/index.rst
index 3621f9d88..a110ef0d2 100644
--- a/docs/library/index.rst
+++ b/docs/library/index.rst
@@ -170,6 +170,7 @@ the following libraries.
:maxdepth: 2
pyb.rst
+ lcd160cr.rst
.. only:: port_wipy
diff --git a/docs/library/lcd160cr.rst b/docs/library/lcd160cr.rst
new file mode 100644
index 000000000..39f492fc4
--- /dev/null
+++ b/docs/library/lcd160cr.rst
@@ -0,0 +1,379 @@
+:mod:`lcd160cr` --- control of LCD160CR display
+===============================================
+
+.. module:: lcd160cr
+ :synopsis: control of LCD160CR display
+
+This module provides control of the MicroPython LCD160CR display.
+
+.. image:: http://micropython.org/resources/LCD160CRv10-persp.jpg
+ :alt: LCD160CRv1.0 picture
+ :width: 640px
+
+Further resources are available via the following links:
+
+* `LCD160CRv1.0 reference manual <http://micropython.org/resources/LCD160CRv10-refmanual.pdf>`_ (100KiB PDF)
+* `LCD160CRv1.0 schematics <http://micropython.org/resources/LCD160CRv10-schematics.pdf>`_ (1.6MiB PDF)
+
+class LCD160CR
+--------------
+
+The LCD160CR class provides an interface to the display. Create an
+instance of this class and use its methods to draw to the LCD and get
+the status of the touch panel.
+
+For example::
+
+ import lcd160cr
+
+ lcd = lcd160cr.LCD160CR('X')
+ lcd.set_orient(lcd160cr.PORTRAIT)
+ lcd.set_pos(0, 0)
+ lcd.set_text_color(lcd.rgb(255, 0, 0), lcd.rgb(0, 0, 0))
+ lcd.set_font(1)
+ lcd.write('Hello MicroPython!')
+ print('touch:', lcd.get_touch())
+
+Constructors
+------------
+
+.. class:: LCD160CR(connect=None, \*, pwr=None, i2c=None, spi=None, i2c_addr=98)
+
+ Construct an LCD160CR object. The parameters are:
+
+ - `connect` is a string specifying the physical connection of the LCD
+ display to the board; valid values are "X", "Y", "XY", "YX".
+ Use "X" when the display is connected to a pyboard in the X-skin
+ position, and "Y" when connected in the Y-skin position. "XY"
+ and "YX" are used when the display is connected to the right or
+ left side of the pyboard, respectively.
+ - `pwr` is a Pin object connected to the LCD's power/enabled pin.
+ - `i2c` is an I2C object connected to the LCD's I2C interface.
+ - `spi` is an SPI object connected to the LCD's SPI interface.
+ - `i2c_addr` is the I2C address of the display.
+
+ One must specify either a valid `connect` or all of `pwr`, `i2c` and `spi`.
+ If a valid `connect` is given then any of `pwr`, `i2c` or `spi` which are
+ not passed as parameters (ie they are `None`) will be created based on the
+ value of `connect`. This allows to override the default interface to the
+ display if needed.
+
+ The default values are:
+
+ - "X" is for the X-skin and uses:
+ ``pwr=Pin("X4")``, ``i2c=I2C("X")``, ``spi=SPI("X")``
+ - "Y" is for the Y-skin and uses:
+ ``pwr=Pin("Y4")``, ``i2c=I2C("Y")``, ``spi=SPI("Y")``
+ - "XY" is for the right-side and uses:
+ ``pwr=Pin("X4")``, ``i2c=I2C("Y")``, ``spi=SPI("X")``
+ - "YX" is for the left-side and uses:
+ ``pwr=Pin("Y4")``, ``i2c=I2C("X")``, ``spi=SPI("Y")``
+
+ See `this image <http://micropython.org/resources/LCD160CRv10-positions.jpg>`_
+ for how the display can be connected to the pyboard.
+
+Static methods
+--------------
+
+.. staticmethod:: LCD160CR.rgb(r, g, b)
+
+ Return a 16-bit integer representing the given rgb color values. The
+ 16-bit value can be used to set the font color (see
+ :meth:`LCD160CR.set_text_color`) pen color (see :meth:`LCD160CR.set_pen`)
+ and draw individual pixels.
+
+.. staticmethod:: LCD160CR.clip_line(data, w, h):
+
+ Clip the given line data. This is for internal use.
+
+Instance members
+----------------
+
+The following instance members are publicly accessible.
+
+.. data:: LCD160CR.w
+.. data:: LCD160CR.h
+
+ The width and height of the display, respectively, in pixels. These
+ members are updated when calling :meth:`LCD160CR.set_orient` and should
+ be considered read-only.
+
+Setup commands
+--------------
+
+.. method:: LCD160CR.set_power(on)
+
+ Turn the display on or off, depending on the given value.
+
+.. method:: LCD160CR.set_orient(orient)
+
+ Set the orientation of the display. The `orient` parameter can be one
+ of `PORTRAIT`, `LANDSCAPE`, `PORTRAIT_UPSIDEDOWN`, `LANDSCAPE_UPSIDEDOWN`.
+
+.. method:: LCD160CR.set_brightness(value)
+
+ Set the brightness of the display, between 0 and 31.
+
+.. method:: LCD160CR.set_i2c_addr(addr)
+
+ Set the I2C address of the display. The `addr` value must have the
+ lower 2 bits cleared.
+
+.. method:: LCD160CR.set_uart_baudrate(baudrate)
+
+ Set the baudrate of the UART interface.
+
+.. method:: LCD160CR.set_startup_deco(value)
+
+ Set the start-up decoration of the display. The `value` parameter can be a
+ logical or of `STARTUP_DECO_NONE`, `STARTUP_DECO_MLOGO`, `STARTUP_DECO_INFO`.
+
+.. method:: LCD160CR.save_to_flash()
+
+ Save the following parameters to flash so they persist on restart and power up:
+ initial decoration, orientation, brightness, UART baud rate, I2C address.
+
+Pixel access methods
+--------------------
+
+The following methods manipulate individual pixels on the display.
+
+.. method:: LCD160CR.set_pixel(x, y, c)
+
+ Set the specified pixel to the given color. The color should be a 16-bit
+ integer and can be created by :meth:`LCD160CR.rgb`.
+
+.. method:: LCD160CR.get_pixel(x, y)
+
+ Get the 16-bit value of the specified pixel.
+
+.. method:: LCD160CR.get_line(x, y, buf)
+
+ Get a line of pixels into the given buffer.
+
+.. method:: LCD160CR.screen_dump(buf)
+
+ Dump the entire screen to the given buffer.
+
+.. method:: LCD160CR.screen_load(buf)
+
+ Load the entire screen from the given buffer.
+
+Drawing text
+------------
+
+To draw text one sets the position, color and font, and then uses
+`write` to draw the text.
+
+.. method:: LCD160CR.set_pos(x, y)
+
+ Set the position for text output using :meth:`LCD160CR.write`. The position
+ is the upper-left corner of the text.
+
+.. method:: LCD160CR.set_text_color(fg, bg)
+
+ Set the foreground and background color of the text.
+
+.. method:: LCD160CR.set_font(font, scale=0, bold=0, trans=0, scroll=0)
+
+ Set the font for the text. Subsequent calls to `write` will use the newly
+ configured font. The parameters are:
+
+ - `font` is the font family to use, valid values are 0, 1, 2, 3.
+ - `scale` is a scaling value for each character pixel, where the pixels
+ are drawn as a square with side length equal to `scale + 1`. The value
+ can be between 0 and 63.
+ - `bold` controls the number of pixels to overdraw each character pixel,
+ making a bold effect. The lower 2 bits of `bold` are the number of
+ pixels to overdraw in the horizontal direction, and the next 2 bits are
+ for the vertical direction. For example, a `bold` value of 5 will
+ overdraw 1 pixel in both the horizontal and vertical directions.
+ - `trans` can be either 0 or 1 and if set to 1 the characters will be
+ drawn with a transparent background.
+ - `scroll` can be either 0 or 1 and if set to 1 the display will do a
+ soft scroll if the text moves to the next line.
+
+.. method:: LCD160CR.write(s)
+
+ Write text to the display, using the current position, color and font.
+ As text is written the position is automatically incremented. The
+ display supports basic VT100 control codes such as newline and backspace.
+
+Drawing primitive shapes
+------------------------
+
+Primitive drawing commands use a foreground and background color set by the
+`set_pen` method.
+
+.. method:: LCD160CR.set_pen(line, fill)
+
+ Set the line and fill color for primitive shapes.
+
+.. method:: LCD160CR.erase()
+
+ Erase the entire display to the pen fill color.
+
+.. method:: LCD160CR.dot(x, y)
+
+ Draw a single pixel at the given location using the pen line color.
+
+.. method:: LCD160CR.rect(x, y, w, h)
+.. method:: LCD160CR.rect_outline(x, y, w, h)
+.. method:: LCD160CR.rect_interior(x, y, w, h)
+
+ Draw a rectangle at the given location and size using the pen line
+ color for the outline, and the pen fill color for the interior.
+ The `rect` method draws the outline and interior, while the other methods
+ just draw one or the other.
+
+.. method:: LCD160CR.line(x1, y1, x2, y2)
+
+ Draw a line between the given coordinates using the pen line color.
+
+.. method:: LCD160CR.dot_no_clip(x, y)
+.. method:: LCD160CR.rect_no_clip(x, y, w, h)
+.. method:: LCD160CR.rect_outline_no_clip(x, y, w, h)
+.. method:: LCD160CR.rect_interior_no_clip(x, y, w, h)
+.. method:: LCD160CR.line_no_clip(x1, y1, x2, y2)
+
+ These methods are as above but don't do any clipping on the input
+ coordinates. They are faster than the clipping versions and can be
+ used when you know that the coordinates are within the display.
+
+.. method:: LCD160CR.poly_dot(data)
+
+ Draw a sequence of dots using the pen line color.
+ The `data` should be a buffer of bytes, with each successive pair of
+ bytes corresponding to coordinate pairs (x, y).
+
+.. method:: LCD160CR.poly_line(data)
+
+ Similar to :meth:`LCD160CR.poly_dot` but draws lines between the dots.
+
+Touch screen methods
+--------------------
+
+.. method:: LCD160CR.touch_config(calib=False, save=False, irq=None)
+
+ Configure the touch panel:
+
+ - If `calib` is `True` then the call will trigger a touch calibration of
+ the resistive touch sensor. This requires the user to touch various
+ parts of the screen.
+ - If `save` is `True` then the touch parameters will be saved to NVRAM
+ to persist across reset/power up.
+ - If `irq` is `True` then the display will be configured to pull the IRQ
+ line low when a touch force is detected. If `irq` is `False` then this
+ feature is disabled. If `irq` is `None` (the default value) then no
+ change is made to this setting.
+
+.. method:: LCD160CR.is_touched()
+
+ Returns a boolean: `True` if there is currently a touch force on the screen,
+ `False` otherwise.
+
+.. method:: LCD160CR.get_touch()
+
+ Returns a 3-tuple of: (active, x, y). If there is currently a touch force
+ on the screen then `active` is 1, otherwise it is 0. The `x` and `y` values
+ indicate the position of the current or most recent touch.
+
+Advanced commands
+-----------------
+
+.. method:: LCD160CR.set_spi_win(x, y, w, h)
+
+ Set the window that SPI data is written to.
+
+.. method:: LCD160CR.fast_spi(flush=True)
+
+ Ready the display to accept RGB pixel data on the SPI bus, resetting the location
+ of the first byte to go to the top-left corner of the window set by
+ :meth:`LCD160CR.set_spi_win`.
+ The method returns an SPI object which can be used to write the pixel data.
+
+ Pixels should be sent as 16-bit RGB values in the 5-6-5 format. The destination
+ counter will increase as data is sent, and data can be sent in arbitrary sized
+ chunks. Once the destination counter reaches the end of the window specified by
+ :meth:`LCD160CR.set_spi_win` it will wrap around to the top-left corner of that window.
+
+.. method:: LCD160CR.show_framebuf(buf)
+
+ Show the given buffer on the display. `buf` should be an array of bytes containing
+ the 16-bit RGB values for the pixels, and they will be written to the area
+ specified by :meth:`LCD160CR.set_spi_win`, starting from the top-left corner.
+
+.. method:: LCD160CR.set_scroll(on)
+
+ Turn scrolling on or off. This controls globally whether any window regions will
+ scroll.
+
+.. method:: LCD160CR.set_scroll_win(win, x=-1, y=0, w=0, h=0, vec=0, pat=0, fill=0x07e0, color=0)
+
+ Configure a window region for scrolling:
+
+ - `win` is the window id to configure. There are 0..7 standard windows for
+ general purpose use. Window 8 is the text scroll window (the ticker).
+ - `x`, `y`, `w`, `h` specify the location of the window in the display.
+ - `vec` specifies the direction and speed of scroll: it is a 16-bit value
+ of the form ``0bF.ddSSSSSSSSSSSS``. `dd` is 0, 1, 2, 3 for +x, +y, -x,
+ -y scrolling. `F` sets the speed format, with 0 meaning that the window
+ is shifted `S % 256` pixel every frame, and 1 meaning that the window
+ is shifted 1 pixel every `S` frames.
+ - `pat` is a 16-bit pattern mask for the background.
+ - `fill` is the fill color.
+ - `color` is the extra color, either of the text or pattern foreground.
+
+.. method:: LCD160CR.set_scroll_win_param(win, param, value)
+
+ Set a single parameter of a scrolling window region:
+
+ - `win` is the window id, 0..8.
+ - `param` is the parameter number to configure, 0..7, and corresponds
+ to the parameters in the `set_scroll_win` method.
+ - `value` is the value to set.
+
+.. method:: LCD160CR.set_scroll_buf(s)
+
+ Set the string for scrolling in window 8. The parameter `s` must be a string
+ with length 32 or less.
+
+.. method:: LCD160CR.jpeg(buf)
+
+ Display a JPEG. `buf` should contain the entire JPEG data.
+ The origin of the JPEG is set by :meth:`LCD160CR.set_pos`.
+
+.. method:: LCD160CR.jpeg_start(total_len)
+.. method:: LCD160CR.jpeg_data(buf)
+
+ Display a JPEG with the data split across multiple buffers. There must be
+ a single call to `jpeg_start` to begin with, specifying the total number of
+ bytes in the JPEG. Then this number of bytes must be transferred to the
+ display using one or more calls to the `jpeg_data` command.
+
+.. method:: LCD160CR.feed_wdt()
+
+ The first call to this method will start the display's internal watchdog
+ timer. Subsequent calls will feed the watchdog. The timeout is roughly 30
+ seconds.
+
+.. method:: LCD160CR.reset()
+
+ Reset the display.
+
+Constants
+---------
+
+.. data:: lcd160cr.PORTRAIT
+.. data:: lcd160cr.LANDSCAPE
+.. data:: lcd160cr.PORTRAIT_UPSIDEDOWN
+.. data:: lcd160cr.LANDSCAPE_UPSIDEDOWN
+
+ orientation of the display, used by :meth:`LCD160CR.set_orient`
+
+.. data:: lcd160cr.STARTUP_DECO_NONE
+.. data:: lcd160cr.STARTUP_DECO_MLOGO
+.. data:: lcd160cr.STARTUP_DECO_INFO
+
+ type of start-up decoration, can be or'd together, used by
+ :meth:`LCD160CR.set_startup_deco`
diff --git a/docs/library/machine.Timer.rst b/docs/library/machine.Timer.rst
index 12db58d5c..eddb2ce78 100644
--- a/docs/library/machine.Timer.rst
+++ b/docs/library/machine.Timer.rst
@@ -1,53 +1,17 @@
.. currentmodule:: machine
-class Timer -- control internal timers
+class Timer -- control hardware timers
======================================
-.. only:: port_wipy
-
- Timers can be used for a great variety of tasks, calling a function periodically,
- counting events, and generating a PWM signal are among the most common use cases.
- Each timer consists of two 16-bit channels and this channels can be tied together to
- form one 32-bit timer. The operating mode needs to be configured per timer, but then
- the period (or the frequency) can be independently configured on each channel.
- By using the callback method, the timer event can call a Python function.
-
- Example usage to toggle an LED at a fixed frequency::
-
- from machine import Timer
- from machine import Pin
- led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED
- tim = Timer(3) # create a timer object using timer 3
- tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode
- tim_ch = tim.channel(Timer.A, freq=5) # configure channel A at a frequency of 5Hz
- tim_ch.irq(handler=lambda t:led.toggle(), trigger=Timer.TIMEOUT) # toggle a LED on every cycle of the timer
-
- Example using named function for the callback::
-
- from machine import Timer
- from machine import Pin
- tim = Timer(1, mode=Timer.PERIODIC, width=32)
- tim_a = tim.channel(Timer.A | Timer.B, freq=1) # 1 Hz frequency requires a 32 bit timer
+Hardware timers deal with timing of periods and events. Timers are perhaps
+the most flexible and heterogeneous kind of hardware in MCUs and SoCs,
+differently greatly from a model to a model. MicroPython's Timer class
+defines a baseline operation of executing a callback with a given period
+(or once after some delay), and allow specific boards to define more
+non-standard behavior (which thus won't be portable to other boards).
- led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED
-
- def tick(timer): # we will receive the timer object when being called
- global led
- led.toggle() # toggle the LED
-
- tim_a.irq(handler=tick, trigger=Timer.TIMEOUT) # create the interrupt
-
- Further examples::
-
- from machine import Timer
- tim1 = Timer(1, mode=Timer.ONE_SHOT) # initialize it in one shot mode
- tim2 = Timer(2, mode=Timer.PWM) # initialize it in PWM mode
- tim1_ch = tim1.channel(Timer.A, freq=10, polarity=Timer.POSITIVE) # start the event counter with a frequency of 10Hz and triggered by positive edges
- tim2_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=5000) # start the PWM on channel B with a 50% duty cycle
- tim2_ch.freq(20) # set the frequency (can also get)
- tim2_ch.duty_cycle(3010) # set the duty cycle to 30.1% (can also get)
- tim2_ch.duty_cycle(3020, Timer.NEGATIVE) # set the duty cycle to 30.2% and change the polarity to negative
- tim2_ch.period(2000000) # change the period to 2 seconds
+See discussion of :ref:`important constraints <machine_callbacks>` on
+Timer callbacks.
.. note::
@@ -61,10 +25,8 @@ Constructors
.. class:: Timer(id, ...)
- .. only:: port_wipy
-
- Construct a new timer object of the given id. ``id`` can take values from 0 to 3.
-
+ Construct a new timer object of the given id. Id of -1 constructs a
+ virtual timer (if supported by a board).
Methods
-------
@@ -94,8 +56,7 @@ Methods
.. method:: Timer.deinit()
- Deinitialises the timer. Disables all channels and associated IRQs.
- Stops the timer, and disables the timer peripheral.
+ Deinitialises the timer. Stops the timer, and disables the timer peripheral.
.. only:: port_wipy
@@ -138,17 +99,17 @@ Methods
- ``GP10`` on Timer 3 channel A.
- ``GP11`` on Timer 3 channel B.
-class TimerChannel --- setup a channel for a timer
-==================================================
+.. only:: port_wipy
-Timer channels are used to generate/capture a signal using a timer.
+ class TimerChannel --- setup a channel for a timer
+ ==================================================
-TimerChannel objects are created using the Timer.channel() method.
+ Timer channels are used to generate/capture a signal using a timer.
-Methods
--------
+ TimerChannel objects are created using the Timer.channel() method.
-.. only:: port_wipy
+ Methods
+ -------
.. method:: timerchannel.irq(\*, trigger, priority=1, handler=None)
@@ -194,22 +155,5 @@ Constants
.. data:: Timer.ONE_SHOT
.. data:: Timer.PERIODIC
-.. data:: Timer.PWM
-
- Selects the timer operating mode.
-
-.. data:: Timer.A
-.. data:: Timer.B
-
- Selects the timer channel. Must be ORed (``Timer.A`` | ``Timer.B``) when
- using a 32-bit timer.
-
-.. data:: Timer.POSITIVE
-.. data:: Timer.NEGATIVE
-
- Timer channel polarity selection (only relevant in PWM mode).
-
-.. data:: Timer.TIMEOUT
-.. data:: Timer.MATCH
- Timer channel IRQ triggers.
+ Timer operating mode.
diff --git a/docs/library/machine.rst b/docs/library/machine.rst
index 7870da2ff..c6da71585 100644
--- a/docs/library/machine.rst
+++ b/docs/library/machine.rst
@@ -1,10 +1,23 @@
-:mod:`machine` --- functions related to the board
-=================================================
+:mod:`machine` --- functions related to the hardware
+====================================================
.. module:: machine
- :synopsis: functions related to the board
+ :synopsis: functions related to the hardware
-The ``machine`` module contains specific functions related to the board.
+The ``machine`` module contains specific functions related to the hardware
+on a particular board. Most functions in this module allow to achieve direct
+and unrestricted access to and control of hardware blocks on a system
+(like CPU, timers, buses, etc.). Used incorrectly, this can lead to
+malfunction, lockups, crashes of your board, and in extreme cases, hardware
+damage.
+
+.. _machine_callbacks:
+
+A note of callbacks used by functions and class methods of ``machine`` module:
+all these callbacks should be considered as executing in an interrupt context.
+This is true for both physical devices with IDs >= 0 and "virtual" devices
+with negative IDs like -1 (these "virtual" devices are still thin shims on
+top of real hardware and real hardware intrerrupts). See :ref:`isr_rules`.
Reset related functions
-----------------------
@@ -105,12 +118,15 @@ Miscellaneous functions
microseconds. The `pulse_level` argument should be 0 to time a low pulse
or 1 to time a high pulse.
- The function first waits while the pin input is different to the `pulse_level`
- parameter, then times the duration that the pin is equal to `pulse_level`.
+ If the current input value of the pin is different to `pulse_level`,
+ the function first (*) waits until the pin input becomes equal to `pulse_level`,
+ then (**) times the duration that the pin is equal to `pulse_level`.
If the pin is already equal to `pulse_level` then timing starts straight away.
- The function will raise an OSError with ETIMEDOUT if either of the waits is
- longer than the given timeout value (which is in microseconds).
+ The function will return -2 if there was timeout waiting for condition marked
+ (*) above, and -1 if there was timeout during the main measurement, marked (**)
+ above. The timeout is the same for both cases and given by `timeout_us` (which
+ is in microseconds).
.. _machine_constants:
diff --git a/docs/library/pyb.rst b/docs/library/pyb.rst
index 910b2f45b..9c4933808 100644
--- a/docs/library/pyb.rst
+++ b/docs/library/pyb.rst
@@ -80,6 +80,19 @@ Reset related functions
Activate the bootloader without BOOT\* pins.
+.. function:: fault_debug(value)
+
+ Enable or disable hard-fault debugging. A hard-fault is when there is a fatal
+ error in the underlying system, like an invalid memory access.
+
+ If the `value` argument is `False` then the board will automatically reset if
+ there is a hard fault.
+
+ If `value` is `True` then, when the board has a hard fault, it will print the
+ registers and the stack trace, and then cycle the LEDs indefinitely.
+
+ The default value is disabled, i.e. to automatically reset.
+
Interrupt related functions
---------------------------
diff --git a/docs/library/uio.rst b/docs/library/uio.rst
index 9b4c87df8..1239c6394 100644
--- a/docs/library/uio.rst
+++ b/docs/library/uio.rst
@@ -7,6 +7,71 @@
This module contains additional types of stream (file-like) objects
and helper functions.
+Conceptual hierarchy
+--------------------
+
+.. admonition:: Difference to CPython
+ :class: attention
+
+ Conceptual hierarchy of stream base classes is simplified in MicroPython,
+ as described in this section.
+
+(Abstract) base stream classes, which serve as a foundation for behavior
+of all the concrete classes, adhere to few dichotomies (pair-wise
+classifications) in CPython. In MicroPython, they are somewhat simplified
+and made implicit to achieve higher efficiencies and save resources.
+
+An important dichotomy in CPython is unbuffered vs buffered streams. In
+MicroPython, all streams are currently unbuffered. This is because all
+modern OSes, and even many RTOSes and filesystem drivers already perform
+buffering on their side. Adding another layer of buffering is counter-
+productive (an issue known as "bufferbloat") and takes precious memory.
+Note that there still cases where buffering may be useful, so we may
+introduce optional buffering support at a later time.
+
+But in CPython, another important dichotomy is tied with "bufferedness" -
+it's whether a stream may incur short read/writes or not. A short read
+is when a user asks e.g. 10 bytes from a stream, but gets less, similarly
+for writes. In CPython, unbuffered streams are automatically short
+operation susceptible, while buffered are guarantee against them. The
+no short read/writes is an important trait, as it allows to develop
+more concise and efficient programs - something which is highly desirable
+for MicroPython. So, while MicroPython doesn't support buffered streams,
+it still provides for no-short-operations streams. Whether there will
+be short operations or not depends on each particular class' needs, but
+developers are strongly advised to favor no-short-operations behavior
+for the reasons stated above. For example, MicroPython sockets are
+guaranteed to avoid short read/writes. Actually, at this time, there is
+no example of a short-operations stream class in the core, and one would
+be a port-specific class, where such a need is governed by hardware
+peculiarities.
+
+The no-short-operations behavior gets tricky in case of non-blocking
+streams, blocking vs non-blocking behavior being another CPython dichotomy,
+fully supported by MicroPython. Non-blocking streams never wait for
+data either to arrive or be written - they read/write whatever possible,
+or signal lack of data (or ability to write data). Clearly, this conflicts
+with "no-short-operations" policy, and indeed, a case of non-blocking
+buffered (and this no-short-ops) streams is convoluted in CPython - in
+some places, such combination is prohibited, in some it's undefined or
+just not documented, in some cases it raises verbose exceptions. The
+matter is much simpler in MicroPython: non-blocking stream are important
+for efficient asynchronous operations, so this property prevails on
+the "no-short-ops" one. So, while blocking streams will avoid short
+reads/writes whenever possible (the only case to get a short read is
+if end of file is reached, or in case of error (but errors don't
+return short data, but raise exceptions)), non-blocking streams may
+produce short data to avoid blocking the operation.
+
+The final dichotomy is binary vs text streams. MicroPython of course
+supports these, but while in CPython text streams are inherently
+buffered, they aren't in MicroPython. (Indeed, that's one of the cases
+for which we may introduce buffering support.)
+
+Note that for efficiency, MicroPython doesn't provide abstract base
+classes corresponding to the hierarchy above, and it's not possible
+to implement, or subclass, a stream class in pure Python.
+
Functions
---------
diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst
index c46e8f4c5..dd0f5708b 100644
--- a/docs/library/usocket.rst
+++ b/docs/library/usocket.rst
@@ -7,13 +7,28 @@
This module provides access to the BSD socket interface.
-See corresponding `CPython module <https://docs.python.org/3/library/socket.html>`_ for
-comparison.
+See the corresponding `CPython module <https://docs.python.org/3/library/socket.html>`_
+for comparison.
+
+.. admonition:: Difference to CPython
+ :class: attention
+
+ CPython used to have a ``socket.error`` exception which is now deprecated,
+ and is an alias of OSError. In MicroPython, use OSError directly.
+
+.. admonition:: Difference to CPython
+ :class: attention
+
+ For efficiency and consistency, socket objects in MicroPython implement a stream
+ (file-like) interface directly. In CPython, you need to convert a socket to
+ a file-like object using ``makefile()`` method. This method is still supported
+ by MicroPython (but is a no-op), so where compatibility with CPython matters,
+ be sure to use it.
Socket address format(s)
------------------------
-Functions below which expect a network address, accept it in the format of
+The functions below which expect a network address, accept it in the format of
`(ipv4_address, port)`, where `ipv4_address` is a string with dot-notation numeric
IPv4 address, e.g. ``"8.8.8.8"``, and port is integer port number in the range
1-65535. Note the domain names are not accepted as `ipv4_address`, they should be
@@ -51,33 +66,50 @@ Functions
s = socket.socket()
s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1])
-.. only:: port_wipy
+ .. admonition:: Difference to CPython
+ :class: attention
- Exceptions
- ----------
-
- .. data:: socket.error
- .. data:: socket.timeout
+ CPython raises a ``socket.gaierror`` exception (OSError subclass) in case
+ of error in this function. MicroPython doesn't have ``socket.gaierror``
+ and raises OSError directly. Note that error numbers of ``getaddrinfo()``
+ form a separate namespace and may not match error numbers from
+ ``uerrno`` module. To distinguish ``getaddrinfo()`` errors, they are
+ represented by negative numbers, whereas standard system errors are
+ positive numbers (error numbers are accessible using ``e.args[0]`` property
+ from an exception object). The use of negative values is a provisional
+ detail which may change in the future.
Constants
---------
.. data:: socket.AF_INET
+ socket.AF_INET6
- family types
+ Address family types. Availability depends on a particular board.
.. data:: socket.SOCK_STREAM
-.. data:: socket.SOCK_DGRAM
+ socket.SOCK_DGRAM
- socket types
+ Socket types.
.. data:: socket.IPPROTO_UDP
-.. data:: socket.IPPROTO_TCP
-.. only:: port_wipy
+ socket.IPPROTO_TCP
+
+ IP protocol numbers.
+
+.. data:: socket.SOL_*
- .. data:: socket.IPPROTO_SEC
+ Socket option levels (an argument to ``setsockopt()``). The exact inventory depends on a board.
- protocol numbers
+.. data:: socket.SO_*
+
+ Socket options (an argument to ``setsockopt()``). The exact inventory depends on a board.
+
+Constants specific to WiPy:
+
+.. data:: socket.IPPROTO_SEC
+
+ Special protocol value to create SSL-compatible socket.
class socket
============
@@ -85,128 +117,146 @@ class socket
Methods
-------
- .. method:: socket.close
+.. method:: socket.close
+
+ Mark the socket closed. Once that happens, all future operations on the socket
+ object will fail. The remote end will receive no more data (after queued data is flushed).
+
+ Sockets are automatically closed when they are garbage-collected, but it is recommended
+ to close() them explicitly, or to use a with statement around them.
- Mark the socket closed. Once that happens, all future operations on the socket
- object will fail. The remote end will receive no more data (after queued data is flushed).
+.. method:: socket.bind(address)
- Sockets are automatically closed when they are garbage-collected, but it is recommended
- to close() them explicitly, or to use a with statement around them.
+ Bind the socket to address. The socket must not already be bound.
- .. method:: socket.bind(address)
+.. method:: socket.listen([backlog])
- Bind the socket to address. The socket must not already be bound.
+ Enable a server to accept connections. If backlog is specified, it must be at least 0
+ (if it's lower, it will be set to 0); and specifies the number of unaccepted connections
+ that the system will allow before refusing new connections. If not specified, a default
+ reasonable value is chosen.
- .. method:: socket.listen([backlog])
+.. method:: socket.accept()
- Enable a server to accept connections. If backlog is specified, it must be at least 0
- (if it's lower, it will be set to 0); and specifies the number of unaccepted connections
- that the system will allow before refusing new connections. If not specified, a default
- reasonable value is chosen.
+ Accept a connection. The socket must be bound to an address and listening for connections.
+ The return value is a pair (conn, address) where conn is a new socket object usable to send
+ and receive data on the connection, and address is the address bound to the socket on the
+ other end of the connection.
- .. method:: socket.accept()
+.. method:: socket.connect(address)
- Accept a connection. The socket must be bound to an address and listening for connections.
- The return value is a pair (conn, address) where conn is a new socket object usable to send
- and receive data on the connection, and address is the address bound to the socket on the
- other end of the connection.
+ Connect to a remote socket at address.
- .. method:: socket.connect(address)
+.. method:: socket.send(bytes)
- Connect to a remote socket at address.
+ Send data to the socket. The socket must be connected to a remote socket.
+ Returns number of bytes sent, which may be smaller than the length of data
+ ("short write").
- .. method:: socket.send(bytes)
+.. method:: socket.sendall(bytes)
- Send data to the socket. The socket must be connected to a remote socket.
+ Send all data to the socket. The socket must be connected to a remote socket.
+ Unlike ``send()``, this method will try to send all of data, by sending data
+ chunk by chunk consecutively.
- .. method:: socket.sendall(bytes)
+ The behavior of this method on non-blocking sockets is undefined. Due to this,
+ on MicroPython, it's recommended to use ``write()`` method instead, which
+ has the same "no short writes" policy for blocking sockets, and will return
+ number of bytes sent on non-blocking sockets.
- Send data to the socket. The socket must be connected to a remote socket.
+.. method:: socket.recv(bufsize)
- .. method:: socket.recv(bufsize)
+ Receive data from the socket. The return value is a bytes object representing the data
+ received. The maximum amount of data to be received at once is specified by bufsize.
- Receive data from the socket. The return value is a bytes object representing the data
- received. The maximum amount of data to be received at once is specified by bufsize.
+.. method:: socket.sendto(bytes, address)
- .. method:: socket.sendto(bytes, address)
+ Send data to the socket. The socket should not be connected to a remote socket, since the
+ destination socket is specified by `address`.
- Send data to the socket. The socket should not be connected to a remote socket, since the
- destination socket is specified by `address`.
+.. method:: socket.recvfrom(bufsize)
- .. method:: socket.recvfrom(bufsize)
+ Receive data from the socket. The return value is a pair (bytes, address) where bytes is a
+ bytes object representing the data received and address is the address of the socket sending
+ the data.
- Receive data from the socket. The return value is a pair (bytes, address) where bytes is a
- bytes object representing the data received and address is the address of the socket sending
- the data.
+.. method:: socket.setsockopt(level, optname, value)
- .. method:: socket.setsockopt(level, optname, value)
+ Set the value of the given socket option. The needed symbolic constants are defined in the
+ socket module (SO_* etc.). The value can be an integer or a bytes-like object representing
+ a buffer.
- Set the value of the given socket option. The needed symbolic constants are defined in the
- socket module (SO_* etc.). The value can be an integer or a bytes-like object representing
- a buffer.
+.. method:: socket.settimeout(value)
- .. method:: socket.settimeout(value)
+ Set a timeout on blocking socket operations. The value argument can be a nonnegative floating
+ point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations
+ will raise an ``OSError`` exception if the timeout period value has elapsed before the operation has
+ completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket
+ is put in blocking mode.
- Set a timeout on blocking socket operations. The value argument can be a nonnegative floating
- point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations
- will raise an ``OSError`` exception if the timeout period value has elapsed before the operation has
- completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket
- is put in blocking mode.
+ .. admonition:: Difference to CPython
+ :class: attention
- .. admonition:: Difference to CPython
- :class: attention
+ CPython raises a ``socket.timeout`` exception in case of timeout,
+ which is an ``OSError`` subclass. MicroPython raises an OSError directly
+ instead. If you use ``except OSError:`` to catch the exception,
+ your code will work both in MicroPython and CPython.
- CPython raises a ``socket.timeout`` exception in case of timeout,
- which is an ``OSError`` subclass. MicroPython raises an OSError directly
- instead. If you use ``except OSError:`` to catch the exception,
- your code will work both in MicroPython and CPython.
+.. method:: socket.setblocking(flag)
- .. method:: socket.setblocking(flag)
+ Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking,
+ else to blocking mode.
- Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking,
- else to blocking mode.
+ This method is a shorthand for certain ``settimeout()`` calls:
- This method is a shorthand for certain ``settimeout()`` calls::
+ * ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)``
+ * ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0)``
- sock.setblocking(True) is equivalent to sock.settimeout(None)
- sock.setblocking(False) is equivalent to sock.settimeout(0.0)
+.. method:: socket.makefile(mode='rb', buffering=0)
- .. method:: socket.makefile(mode='rb')
+ Return a file object associated with the socket. The exact returned type depends on the arguments
+ given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb').
+ CPython's arguments: ``encoding``, ``errors`` and ``newline`` are not supported.
- Return a file object associated with the socket. The exact returned type depends on the arguments
- given to makefile(). The support is limited to binary modes only ('rb' and 'wb').
- CPython's arguments: ``encoding``, ``errors`` and ``newline`` are not supported.
+ .. admonition:: Difference to CPython
+ :class: attention
- The socket must be in blocking mode; it can have a timeout, but the file object’s internal buffer
- may end up in a inconsistent state if a timeout occurs.
+ As MicroPython doesn't support buffered streams, values of ``buffering``
+ parameter is ignored and treated as if it was 0 (unbuffered).
- .. admonition:: Difference to CPython
- :class: attention
+ .. admonition:: Difference to CPython
+ :class: attention
- Closing the file object returned by makefile() WILL close the
- original socket as well.
+ Closing the file object returned by makefile() WILL close the
+ original socket as well.
- .. method:: socket.read([size])
+.. method:: socket.read([size])
- Read up to size bytes from the socket. Return a bytes object. If ``size`` is not given, it
- reads all data available from the socket until ``EOF``; as such the method will not return until
- the socket is closed.
+ Read up to size bytes from the socket. Return a bytes object. If ``size`` is not given, it
+ reads all data available from the socket until ``EOF``; as such the method will not return until
+ the socket is closed. This function tries to read as much data as
+ requested (no "short reads"). This may be not possible with
+ non-blocking socket though, and then less data will be returned.
- .. method:: socket.readinto(buf[, nbytes])
+.. method:: socket.readinto(buf[, nbytes])
- Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
- that many bytes. Otherwise, read at most ``len(buf)`` bytes.
+ Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
+ that many bytes. Otherwise, read at most ``len(buf)`` bytes. Just as
+ ``read()``, this method follows "no short reads" policy.
- Return value: number of bytes read and stored into ``buf``.
+ Return value: number of bytes read and stored into ``buf``.
- .. method:: socket.readline()
+.. method:: socket.readline()
- Read a line, ending in a newline character.
+ Read a line, ending in a newline character.
- Return value: the line read.
+ Return value: the line read.
- .. method:: socket.write(buf)
+.. method:: socket.write(buf)
- Write the buffer of bytes to the socket.
+ Write the buffer of bytes to the socket. This function will try to
+ write all data to a socket (no "short writes"). This may be not possible
+ with a non-blocking socket though, and returned value will be less than
+ the length of ``buf``.
- Return value: number of bytes written.
+ Return value: number of bytes written.
diff --git a/docs/pyboard/general.rst b/docs/pyboard/general.rst
index 107bae69a..48e014644 100644
--- a/docs/pyboard/general.rst
+++ b/docs/pyboard/general.rst
@@ -11,6 +11,11 @@ is inserted into the slot, it is available as ``/sd``.
When the pyboard boots up, it needs to choose a filesystem to boot from. If
there is no SD card, then it uses the internal filesystem ``/flash`` as the boot
filesystem, otherwise, it uses the SD card ``/sd``.
+If needed, you can prevent the use of the SD card by creating an empty file
+called ``/flash/SKIPSD``. If this file exists when the pyboard boots
+up then the SD card will be skipped and the pyboard will always boot from the
+internal filesystem (in this case the SD card won't be mounted but you can still
+mount and use it later in your program using ``os.mount``).
(Note that on older versions of the board, ``/flash`` is called ``0:/`` and ``/sd``
is called ``1:/``).
diff --git a/docs/pyboard/hardware/index.rst b/docs/pyboard/hardware/index.rst
index b64908c56..bc4726ce2 100644
--- a/docs/pyboard/hardware/index.rst
+++ b/docs/pyboard/hardware/index.rst
@@ -13,6 +13,7 @@ For the official skin modules:
* `LCD32MKv1.0 schematics <http://micropython.org/resources/LCD32MKv10-schematics.pdf>`_ (194KiB PDF)
* `AMPv1.0 schematics <http://micropython.org/resources/AMPv10-schematics.pdf>`_ (209KiB PDF)
+* LCD160CRv1.0: see :mod:`lcd160cr`
Datasheets for the components on the pyboard
============================================
diff --git a/docs/pyboard/tutorial/index.rst b/docs/pyboard/tutorial/index.rst
index ae40f47b8..07f136c9b 100644
--- a/docs/pyboard/tutorial/index.rst
+++ b/docs/pyboard/tutorial/index.rst
@@ -35,6 +35,7 @@ Tutorials requiring extra components
fading_led.rst
lcd_skin.rst
amp_skin.rst
+ lcd160cr_skin.rst
Tips, tricks and useful things to know
--------------------------------------
diff --git a/docs/pyboard/tutorial/lcd160cr_skin.rst b/docs/pyboard/tutorial/lcd160cr_skin.rst
new file mode 100644
index 000000000..fc9d63538
--- /dev/null
+++ b/docs/pyboard/tutorial/lcd160cr_skin.rst
@@ -0,0 +1,134 @@
+The LCD160CR skin
+=================
+
+This tutorial shows how to get started using the LCD160CR skin.
+
+.. image:: http://micropython.org/resources/LCD160CRv10-positions.jpg
+ :alt: LCD160CRv1.0 picture
+ :width: 800px
+
+For detailed documentation of the driver for the display see the
+:mod:`lcd160cr` module.
+
+Plugging in the display
+-----------------------
+
+The display can be plugged directly into a pyboard (all pyboard versions
+are supported). You plug the display onto the top of the pyboard either
+in the X or Y positions. The display should cover half of the pyboard.
+See the picture above for how to achieve this; the left half of the picture
+shows the X position, and the right half shows the Y position.
+
+Getting the driver
+------------------
+
+You can control the display directly using a power/enable pin and an I2C
+bus, but it is much more convenient to use the driver provided by the
+:mod:`lcd160cr` module. This driver is included in recent version of the
+pyboard firmware (see `here <http://micropython.org/download>`__). You
+can also find the driver in the GitHub repository
+`here <https://github.com/micropython/micropython/blob/master/drivers/display/lcd160cr.py>`__, and to use this version you will need to copy the file to your
+board, into a directory that is searched by import (usually the lib/
+directory).
+
+Once you have the driver installed you need to import it to use it::
+
+ import lcd160cr
+
+Testing the display
+-------------------
+
+There is a test program which you can use to test the features of the display,
+and which also serves as a basis to start creating your own code that uses the
+LCD. This test program is included in recent versions of the pyboard firmware
+and is also available on GitHub
+`here <https://github.com/micropython/micropython/blob/master/drivers/display/lcd160cr_test.py>`__.
+
+To run the test from the MicroPython prompt do::
+
+ >>> import lcd160cr_test
+
+It will then print some brief instructions. You will need to know which
+position your display is connected to (X or Y) and then you can run (assuming
+you have the display on position X)::
+
+ >>> test_all('X')
+
+Drawing some graphics
+---------------------
+
+You must first create an LCD160CR object which will control the display. Do this
+using::
+
+ >>> import lcd160cr
+ >>> lcd = lcd160cr.LCD160CR('X')
+
+This assumes your display is connected in the X position. If it's in the Y
+position then use ``lcd = lcd160cr.LCD160CR('Y')`` instead.
+
+To erase the screen and draw a line, try::
+
+ >>> lcd.set_pen(lcd.rgb(255, 0, 0), lcd.rgb(64, 64, 128))
+ >>> lcd.erase()
+ >>> lcd.line(10, 10, 50, 80)
+
+The next example draws random rectangles on the screen. You can copy-and-paste it
+into the MicroPython prompt by first pressing "Ctrl-E" at the prompt, then "Ctrl-D"
+once you have pasted the text. ::
+
+ from random import randint
+ for i in range(1000):
+ fg = lcd.rgb(randint(128, 255), randint(128, 255), randint(128, 255))
+ bg = lcd.rgb(randint(0, 128), randint(0, 128), randint(0, 128))
+ lcd.set_pen(fg, bg)
+ lcd.rect(randint(0, lcd.w), randint(0, lcd.h), randint(10, 40), randint(10, 40))
+
+Using the touch sensor
+----------------------
+
+The display includes a resistive touch sensor that can report the position (in
+pixels) of a single force-based touch on the screen. To see if there is a touch
+on the screen use::
+
+ >>> lcd.is_touched()
+
+This will return either ``False`` or ``True``. Run the above command while touching
+the screen to see the result.
+
+To get the location of the touch you can use the method::
+
+ >>> lcd.get_touch()
+
+This will return a 3-tuple, with the first entry being 0 or 1 depending on whether
+there is currently anything touching the screen (1 if there is), and the second and
+third entries in the tuple being the x and y coordinates of the current (or most
+recent) touch.
+
+Directing the MicroPython output to the display
+-----------------------------------------------
+
+The display supports input from a UART and implements basic VT100 commands, which
+means it can be used as a simple, general purpose terminal. Let's set up the
+pyboard to redirect its output to the display.
+
+First you need to create a UART object::
+
+ >>> import pyb
+ >>> uart = pyb.UART('XA', 115200)
+
+This assumes your display is connected to position X. If it's on position Y then
+use ``uart = pyb.UART('YA', 115200)`` instead.
+
+Now, connect the REPL output to this UART::
+
+ >>> pyb.repl_uart(uart)
+
+From now on anything you type at the MicroPython prompt, and any output you
+receive, will appear on the display.
+
+No set-up commands are required for this mode to work and you can use the display
+to monitor the output of any UART, not just from the pyboard. All that is needed
+is for the display to have power, ground and the power/enable pin driven high.
+Then any characters on the display's UART input will be printed to the screen.
+You can adjust the UART baudrate from the default of 115200 using the
+`set_uart_baudrate` method.
diff --git a/docs/static/favicon.ico b/docs/static/favicon.ico
new file mode 100644
index 000000000..49c615414
--- /dev/null
+++ b/docs/static/favicon.ico
Binary files differ
diff --git a/docs/wipy/quickref.rst b/docs/wipy/quickref.rst
index 7a4ea7f7f..2505eb35f 100644
--- a/docs/wipy/quickref.rst
+++ b/docs/wipy/quickref.rst
@@ -44,7 +44,8 @@ See :ref:`machine.Pin <machine.Pin>`. ::
Timers
------
-See :ref:`machine.Timer <machine.Timer>` and :ref:`machine.Pin <machine.Pin>`. ::
+See :ref:`machine.Timer <machine.Timer>` and :ref:`machine.Pin <machine.Pin>`.
+Timer ``id``'s take values from 0 to 3.::
from machine import Timer
from machine import Pin
diff --git a/docs/wipy/tutorial/index.rst b/docs/wipy/tutorial/index.rst
index c3d51e2e5..816de27b5 100644
--- a/docs/wipy/tutorial/index.rst
+++ b/docs/wipy/tutorial/index.rst
@@ -14,4 +14,5 @@ for instructions see :ref:`OTA How-To <wipy_firmware_upgrade>`.
repl.rst
blynk.rst
wlan.rst
+ timer.rst
reset.rst
diff --git a/docs/wipy/tutorial/timer.rst b/docs/wipy/tutorial/timer.rst
new file mode 100644
index 000000000..c87ac4495
--- /dev/null
+++ b/docs/wipy/tutorial/timer.rst
@@ -0,0 +1,70 @@
+Hardware timers
+===============
+
+Timers can be used for a great variety of tasks, calling a function periodically,
+counting events, and generating a PWM signal are among the most common use cases.
+Each timer consists of two 16-bit channels and this channels can be tied together to
+form one 32-bit timer. The operating mode needs to be configured per timer, but then
+the period (or the frequency) can be independently configured on each channel.
+By using the callback method, the timer event can call a Python function.
+
+Example usage to toggle an LED at a fixed frequency::
+
+ from machine import Timer
+ from machine import Pin
+ led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED
+ tim = Timer(3) # create a timer object using timer 3
+ tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode
+ tim_ch = tim.channel(Timer.A, freq=5) # configure channel A at a frequency of 5Hz
+ tim_ch.irq(handler=lambda t:led.toggle(), trigger=Timer.TIMEOUT) # toggle a LED on every cycle of the timer
+
+Example using named function for the callback::
+
+ from machine import Timer
+ from machine import Pin
+ tim = Timer(1, mode=Timer.PERIODIC, width=32)
+ tim_a = tim.channel(Timer.A | Timer.B, freq=1) # 1 Hz frequency requires a 32 bit timer
+
+ led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED
+
+ def tick(timer): # we will receive the timer object when being called
+ global led
+ led.toggle() # toggle the LED
+
+ tim_a.irq(handler=tick, trigger=Timer.TIMEOUT) # create the interrupt
+
+Further examples::
+
+ from machine import Timer
+ tim1 = Timer(1, mode=Timer.ONE_SHOT) # initialize it in one shot mode
+ tim2 = Timer(2, mode=Timer.PWM) # initialize it in PWM mode
+ tim1_ch = tim1.channel(Timer.A, freq=10, polarity=Timer.POSITIVE) # start the event counter with a frequency of 10Hz and triggered by positive edges
+ tim2_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=5000) # start the PWM on channel B with a 50% duty cycle
+ tim2_ch.freq(20) # set the frequency (can also get)
+ tim2_ch.duty_cycle(3010) # set the duty cycle to 30.1% (can also get)
+ tim2_ch.duty_cycle(3020, Timer.NEGATIVE) # set the duty cycle to 30.2% and change the polarity to negative
+ tim2_ch.period(2000000) # change the period to 2 seconds
+
+
+Additional constants for Timer class
+------------------------------------
+
+.. data:: Timer.PWM
+
+ PWM timer operating mode.
+
+.. data:: Timer.A
+.. data:: Timer.B
+
+ Selects the timer channel. Must be ORed (``Timer.A`` | ``Timer.B``) when
+ using a 32-bit timer.
+
+.. data:: Timer.POSITIVE
+.. data:: Timer.NEGATIVE
+
+ Timer channel polarity selection (only relevant in PWM mode).
+
+.. data:: Timer.TIMEOUT
+.. data:: Timer.MATCH
+
+ Timer channel IRQ triggers.