From e72e3439086ca16d376d939a60bafa95f7da6748 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 23 Jan 2017 14:37:10 +1100 Subject: docs: Add documentation for lcd160cr module. --- docs/library/index.rst | 1 + docs/library/lcd160cr.rst | 376 ++++++++++++++++++++++++++++++++++++++++ docs/pyboard/hardware/index.rst | 1 + 3 files changed, 378 insertions(+) create mode 100644 docs/library/lcd160cr.rst (limited to 'docs') 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..c31dd6d2f --- /dev/null +++ b/docs/library/lcd160cr.rst @@ -0,0 +1,376 @@ +: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 `_ (100KiB PDF) +* `LCD160CRv1.0 schematics `_ (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")`` + +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 255. + +.. 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/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 `_ (194KiB PDF) * `AMPv1.0 schematics `_ (209KiB PDF) +* LCD160CRv1.0: see :mod:`lcd160cr` Datasheets for the components on the pyboard ============================================ -- cgit v1.2.3 From 7d08bc27e23251b74f4b41f6ecbc0a565e67dbb4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 23 Jan 2017 15:50:37 +1100 Subject: docs/pyboard/tutorial: Add tutorial for LCD160CR. --- docs/pyboard/tutorial/index.rst | 1 + docs/pyboard/tutorial/lcd160cr_skin.rst | 132 ++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 docs/pyboard/tutorial/lcd160cr_skin.rst (limited to 'docs') 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..f0bc34e1e --- /dev/null +++ b/docs/pyboard/tutorial/lcd160cr_skin.rst @@ -0,0 +1,132 @@ +The LCD160CR skin +================= + +This tutorial shows how to get started using the LCD160CR skin. + +.. image:: http://micropython.org/resources/LCD160CRv10-persp.jpg + :alt: LCD160CRv1.0 picture + :width: 640px + +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. + +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 `__). You +can also find the driver in the GitHub repository +`here `__, 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 `__. + +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_touched() + +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. -- cgit v1.2.3 From c707668d9e84f4b27b9d306f6cf2687e83f4425d Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 24 Jan 2017 00:17:39 +1100 Subject: docs/library/lcd160cr: Fix set_brightness range, should be 0..31. --- docs/library/lcd160cr.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/library/lcd160cr.rst b/docs/library/lcd160cr.rst index c31dd6d2f..bb5a9b9f9 100644 --- a/docs/library/lcd160cr.rst +++ b/docs/library/lcd160cr.rst @@ -109,7 +109,7 @@ Setup commands .. method:: LCD160CR.set_brightness(value) - Set the brightness of the display, between 0 and 255. + Set the brightness of the display, between 0 and 31. .. method:: LCD160CR.set_i2c_addr(addr) -- cgit v1.2.3 From 56e7ebf07af8d570aadfe53b4686d014af574bf3 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 28 Jan 2017 11:55:48 +0300 Subject: docs/machine.Timer: Move WiPy adhoc parts to its documentation. --- docs/library/machine.Timer.rst | 95 ++++++++---------------------------------- docs/wipy/quickref.rst | 3 +- docs/wipy/tutorial/index.rst | 1 + docs/wipy/tutorial/timer.rst | 70 +++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 78 deletions(-) create mode 100644 docs/wipy/tutorial/timer.rst (limited to 'docs') diff --git a/docs/library/machine.Timer.rst b/docs/library/machine.Timer.rst index 12db58d5c..318443348 100644 --- a/docs/library/machine.Timer.rst +++ b/docs/library/machine.Timer.rst @@ -1,53 +1,14 @@ .. 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 - - 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 +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). .. note:: @@ -61,10 +22,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 +53,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 +96,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 +152,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/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 `. :: Timers ------ -See :ref:`machine.Timer ` and :ref:`machine.Pin `. :: +See :ref:`machine.Timer ` and :ref:`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 `. 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. -- cgit v1.2.3 From 0aa83142a42f07675a21f8d223dc97b7da0194e4 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 28 Jan 2017 12:08:25 +0300 Subject: docs/machine: Add explicit note on machine module level and scope. It's very low, hardware level, with associated constraints on operations and callbacks. --- docs/library/machine.Timer.rst | 3 +++ docs/library/machine.rst | 23 ++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/library/machine.Timer.rst b/docs/library/machine.Timer.rst index 318443348..eddb2ce78 100644 --- a/docs/library/machine.Timer.rst +++ b/docs/library/machine.Timer.rst @@ -10,6 +10,9 @@ 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). +See discussion of :ref:`important constraints ` on +Timer callbacks. + .. note:: Memory can't be allocated inside irq handlers (an interrupt) and so diff --git a/docs/library/machine.rst b/docs/library/machine.rst index 7870da2ff..753f6b417 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 - -The ``machine`` module contains specific functions related to the board. + :synopsis: functions related to the hardware + +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 ----------------------- -- cgit v1.2.3 From 59540dccf125452a8cf4e55f260788a46f7838dc Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 28 Jan 2017 13:55:51 +0300 Subject: docs/usocket: Clarify exceptions used. --- docs/library/usocket.rst | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'docs') diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst index c46e8f4c5..64afa6f59 100644 --- a/docs/library/usocket.rst +++ b/docs/library/usocket.rst @@ -10,6 +10,12 @@ This module provides access to the BSD socket interface. See corresponding `CPython module `_ 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. + Socket address format(s) ------------------------ @@ -51,13 +57,18 @@ Functions s = socket.socket() s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1]) -.. only:: port_wipy - - Exceptions - ---------- - - .. data:: socket.error - .. data:: socket.timeout + .. admonition:: Difference to CPython + :class: attention + + 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 --------- -- cgit v1.2.3 From 74fcb122f0afa8be19b691e720c35f5730175f96 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 28 Jan 2017 14:46:58 +0300 Subject: docs/usocket: Elaborate "Constants" section. --- docs/library/usocket.rst | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'docs') diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst index 64afa6f59..16ba66c2b 100644 --- a/docs/library/usocket.rst +++ b/docs/library/usocket.rst @@ -74,21 +74,33 @@ 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 - .. data:: socket.IPPROTO_SEC + IP protocol numbers. - protocol numbers +.. data:: socket.SOL_* + + Socket option levels (an argument to ``setsockopt()``). The exact inventory depends on a board. + +.. 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 ============ -- cgit v1.2.3 From f23c47fea701d1adb778092f9f53532d057acffd Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 28 Jan 2017 15:39:18 +0300 Subject: docs/usocket: Clarify description of various methods. --- docs/library/usocket.rst | 55 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 14 deletions(-) (limited to 'docs') diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst index 16ba66c2b..a75049727 100644 --- a/docs/library/usocket.rst +++ b/docs/library/usocket.rst @@ -7,8 +7,8 @@ This module provides access to the BSD socket interface. -See corresponding `CPython module `_ for -comparison. +See the corresponding `CPython module `_ +for comparison. .. admonition:: Difference to CPython :class: attention @@ -16,10 +16,19 @@ comparison. 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 @@ -141,10 +150,19 @@ Methods .. method:: socket.send(bytes) 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.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. + + 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. .. method:: socket.recv(bufsize) @@ -189,19 +207,22 @@ Methods 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.0) + * ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)`` + * ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0)`` - .. method:: socket.makefile(mode='rb') + .. method:: socket.makefile(mode='rb', buffering=0) 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'). + 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. - 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. + .. admonition:: Difference to CPython + :class: attention + + 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 @@ -213,12 +234,15 @@ Methods 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. + 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]) Read bytes into the ``buf``. If ``nbytes`` is specified then read at most - that many bytes. Otherwise, read at most ``len(buf)`` bytes. + 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``. @@ -230,6 +254,9 @@ Methods .. 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. -- cgit v1.2.3 From 6947a7f6a975dd9ebf1af6ea7ddf21c364339078 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 28 Jan 2017 15:49:54 +0300 Subject: docs/usocket: Dedent Methods section. This was apparently of an ::only directive which was later removed. --- docs/library/usocket.rst | 190 +++++++++++++++++++++++------------------------ 1 file changed, 95 insertions(+), 95 deletions(-) (limited to 'docs') diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst index a75049727..dd0f5708b 100644 --- a/docs/library/usocket.rst +++ b/docs/library/usocket.rst @@ -117,146 +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). + 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. + 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. - .. method:: socket.bind(address) +.. method:: socket.bind(address) - Bind the socket to address. The socket must not already be bound. + Bind the socket to address. The socket must not already be bound. - .. method:: socket.listen([backlog]) +.. method:: socket.listen([backlog]) - 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. + 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.accept() +.. method:: socket.accept() - 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. + 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.connect(address) +.. method:: socket.connect(address) - Connect to a remote socket at address. + Connect to a remote socket at address. - .. method:: socket.send(bytes) +.. method:: socket.send(bytes) - 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"). + 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.sendall(bytes) +.. method:: socket.sendall(bytes) - 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. + 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. - 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. + 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. - .. 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)`` - .. method:: socket.makefile(mode='rb', buffering=0) +.. method:: socket.makefile(mode='rb', buffering=0) - 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', 'wb', and 'rwb'). + CPython's arguments: ``encoding``, ``errors`` and ``newline`` are not supported. - .. admonition:: Difference to CPython - :class: attention + .. admonition:: Difference to CPython + :class: attention - As MicroPython doesn't support buffered streams, values of ``buffering`` - parameter is ignored and treated as if it was 0 (unbuffered). + 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. 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. + 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. Just as - ``read()``, this method follows "no short reads" policy. + 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. 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``. + 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. -- cgit v1.2.3 From ef6fb66d2323d5c60fffdc77886a2ce170fa5e20 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 28 Jan 2017 16:35:40 +0300 Subject: docs/uio: Describe differences between uPy an CPy stream hierarchy. --- docs/library/uio.rst | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) (limited to 'docs') diff --git a/docs/library/uio.rst b/docs/library/uio.rst index 9b4c87df8..352939932 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 later of buffering is counter- +productive (an issue known as "bufferbloat") and spends 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 traits, 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, blockedness vs non-blockedness 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 asynchronuous 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 --------- -- cgit v1.2.3 From bdb0d22fe2619393e2d8cd591dd14cd4081f8fc5 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 28 Jan 2017 12:57:08 +0300 Subject: docs/conf.py: Add myself as a copyright holder on the docs. Based on the following statistics: $ git log docs |grep Author | sort | uniq -c | sort -n -r 175 Author: Paul Sokolovsky 135 Author: Damien George 31 Author: Daniel Campora 26 Author: danicampora 14 Author: Peter Hinch git blame stats script from http://stackoverflow.com/a/13687302/496009: $ sh git-authors docs 9977 author Damien George 2679 author Paul Sokolovsky 1699 author Daniel Campora 1580 author danicampora 1286 author Peter Hinch 282 author Shuning Bian 249 author Dave Hylands Total lines per this script: 18417, my contribution is 14.5%. --- docs/conf.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/conf.py b/docs/conf.py index 6026aee56..1a552be2e 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 @@ -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'), ] -- cgit v1.2.3 From 0ddeedfc733b8a5c2f4e1939d0dd31c77e38e39d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 29 Jan 2017 16:18:33 +0300 Subject: docs/uio: Typo fixes/lexical improvements. --- docs/library/uio.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/library/uio.rst b/docs/library/uio.rst index 352939932..1239c6394 100644 --- a/docs/library/uio.rst +++ b/docs/library/uio.rst @@ -24,8 +24,8 @@ 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 later of buffering is counter- -productive (an issue known as "bufferbloat") and spends precious memory. +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. @@ -34,7 +34,7 @@ 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 traits, as it allows to develop +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 @@ -47,7 +47,7 @@ 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, blockedness vs non-blockedness being another CPython dichotomy, +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 @@ -56,7 +56,7 @@ 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 asynchronuous operations, so this property prevails on +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 -- cgit v1.2.3 From 5ec5bfb0d31c04b3d44e109dd5dca779c3a070e0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 30 Jan 2017 18:19:29 +1100 Subject: docs/pyboard/tutorial/lcd160cr_skin: Fix typo, get_touched->get_touch. --- docs/pyboard/tutorial/lcd160cr_skin.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/pyboard/tutorial/lcd160cr_skin.rst b/docs/pyboard/tutorial/lcd160cr_skin.rst index f0bc34e1e..11ebad9a6 100644 --- a/docs/pyboard/tutorial/lcd160cr_skin.rst +++ b/docs/pyboard/tutorial/lcd160cr_skin.rst @@ -95,7 +95,7 @@ the screen to see the result. To get the location of the touch you can use the method:: - >>> lcd.get_touched() + >>> 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 -- cgit v1.2.3 From 50a9dd59f5848d536d2057498671d8fe90c76ef1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 Feb 2017 12:48:54 +1100 Subject: docs: For LCD160CR driver and tutorial, add link to positioning image. --- docs/library/lcd160cr.rst | 3 +++ docs/pyboard/tutorial/lcd160cr_skin.rst | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/library/lcd160cr.rst b/docs/library/lcd160cr.rst index bb5a9b9f9..39f492fc4 100644 --- a/docs/library/lcd160cr.rst +++ b/docs/library/lcd160cr.rst @@ -69,6 +69,9 @@ Constructors - "YX" is for the left-side and uses: ``pwr=Pin("Y4")``, ``i2c=I2C("X")``, ``spi=SPI("Y")`` + See `this image `_ + for how the display can be connected to the pyboard. + Static methods -------------- diff --git a/docs/pyboard/tutorial/lcd160cr_skin.rst b/docs/pyboard/tutorial/lcd160cr_skin.rst index 11ebad9a6..fc9d63538 100644 --- a/docs/pyboard/tutorial/lcd160cr_skin.rst +++ b/docs/pyboard/tutorial/lcd160cr_skin.rst @@ -3,9 +3,9 @@ The LCD160CR skin This tutorial shows how to get started using the LCD160CR skin. -.. image:: http://micropython.org/resources/LCD160CRv10-persp.jpg +.. image:: http://micropython.org/resources/LCD160CRv10-positions.jpg :alt: LCD160CRv1.0 picture - :width: 640px + :width: 800px For detailed documentation of the driver for the display see the :mod:`lcd160cr` module. @@ -16,6 +16,8 @@ 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 ------------------ -- cgit v1.2.3 From d5e9ab6e61729f533dbed5c2b6b27307ce6c3b55 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 5 Feb 2017 14:20:17 +0300 Subject: extmod/machine_pulse: Make time_pulse_us() not throw exceptions. machine.time_pulse_us() is intended to provide very fine timing, including while working with signal bursts, where each transition is tracked in row. Throwing and handling an exception may take too much time and "signal loss". So instead, in case of a timeout, just return negative value. Cases of timeout while waiting for initial signal stabilization, and during actual timing, are recognized. The documentation is updated accordingly, and rewritten somewhat to clarify the function behavior. --- docs/library/machine.rst | 11 +++++++---- drivers/dht/dht.c | 4 ++-- extmod/machine_pulse.c | 6 ++---- tests/extmod/machine_pulse.py | 11 ++--------- tests/extmod/machine_pulse.py.exp | 4 ++-- 5 files changed, 15 insertions(+), 21 deletions(-) (limited to 'docs') diff --git a/docs/library/machine.rst b/docs/library/machine.rst index 753f6b417..c6da71585 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -118,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/drivers/dht/dht.c b/drivers/dht/dht.c index 1f0cffc6f..6bdda44b4 100644 --- a/drivers/dht/dht.c +++ b/drivers/dht/dht.c @@ -65,7 +65,7 @@ STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) { // time pulse, should be 80us ticks = machine_time_pulse_us(pin, 1, 150); - if (ticks == (mp_uint_t)-1) { + if ((mp_int_t)ticks < 0) { goto timeout; } @@ -73,7 +73,7 @@ STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) { uint8_t *buf = bufinfo.buf; for (int i = 0; i < 40; ++i) { ticks = machine_time_pulse_us(pin, 1, 100); - if (ticks == (mp_uint_t)-1) { + if ((mp_int_t)ticks < 0) { goto timeout; } buf[i / 8] = (buf[i / 8] << 1) | (ticks > 48); diff --git a/extmod/machine_pulse.c b/extmod/machine_pulse.c index b2a78d72e..5f837479d 100644 --- a/extmod/machine_pulse.c +++ b/extmod/machine_pulse.c @@ -34,7 +34,7 @@ mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t mp_uint_t start = mp_hal_ticks_us(); while (mp_hal_pin_read(pin) != pulse_level) { if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) { - return (mp_uint_t)-1; + return (mp_uint_t)-2; } } start = mp_hal_ticks_us(); @@ -57,9 +57,7 @@ STATIC mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) { timeout_us = mp_obj_get_int(args[2]); } mp_uint_t us = machine_time_pulse_us(pin, level, timeout_us); - if (us == (mp_uint_t)-1) { - mp_raise_OSError(MP_ETIMEDOUT); - } + // May return -1 or -2 in case of timeout return mp_obj_new_int(us); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj, 2, 3, machine_time_pulse_us_); diff --git a/tests/extmod/machine_pulse.py b/tests/extmod/machine_pulse.py index b6e126435..6491b5409 100644 --- a/tests/extmod/machine_pulse.py +++ b/tests/extmod/machine_pulse.py @@ -43,12 +43,5 @@ t = machine.time_pulse_us(p, 0) print(type(t)) p = ConstPin(0) -try: - machine.time_pulse_us(p, 1, 10) -except OSError: - print("OSError") - -try: - machine.time_pulse_us(p, 0, 10) -except OSError: - print("OSError") +print(machine.time_pulse_us(p, 1, 10)) +print(machine.time_pulse_us(p, 0, 10)) diff --git a/tests/extmod/machine_pulse.py.exp b/tests/extmod/machine_pulse.py.exp index f9a474218..20d4c1043 100644 --- a/tests/extmod/machine_pulse.py.exp +++ b/tests/extmod/machine_pulse.py.exp @@ -5,5 +5,5 @@ value: 1 value: 0 value: 1 -OSError -OSError +-2 +-1 -- cgit v1.2.3 From 27c149efe030b6fd24c0cc1475ea509da1a72821 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 6 Feb 2017 13:19:52 +1100 Subject: stmhal: Add pyb.fault_debug() function, to control hard-fault behaviour. This new function controls what happens on a hard-fault: - debugging disabled: board will do a reset - debugging enabled: board will print registers and stack and flash LEDs The default is disabled, ie to do a reset. This is different to previous behaviour which flashed the LEDs and waited indefinitely. --- docs/library/pyb.rst | 13 +++++++++++++ stmhal/modpyb.c | 9 +++++++++ stmhal/stm32_it.c | 20 +++++++------------- stmhal/stm32_it.h | 2 ++ tests/pyb/pyb1.py | 3 +++ 5 files changed, 34 insertions(+), 13 deletions(-) (limited to 'docs') 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/stmhal/modpyb.c b/stmhal/modpyb.c index 53b4335e7..93ae5d40b 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -38,6 +38,7 @@ #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "gccollect.h" +#include "stm32_it.h" #include "irq.h" #include "systick.h" #include "led.h" @@ -64,6 +65,12 @@ #include "extmod/vfs.h" #include "extmod/utime_mphal.h" +STATIC mp_obj_t pyb_fault_debug(mp_obj_t value) { + pyb_hard_fault_debug = mp_obj_is_true(value); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_fault_debug_obj, pyb_fault_debug); + /// \function millis() /// Returns the number of milliseconds since the board was last reset. /// @@ -131,6 +138,8 @@ MP_DECLARE_CONST_FUN_OBJ_KW(pyb_main_obj); // defined in main.c STATIC const mp_map_elem_t pyb_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_fault_debug), (mp_obj_t)&pyb_fault_debug_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_bootloader), (mp_obj_t)&machine_bootloader_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_hard_reset), (mp_obj_t)&machine_reset_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&machine_info_obj }, diff --git a/stmhal/stm32_it.c b/stmhal/stm32_it.c index 245b2ade4..4152050a9 100644 --- a/stmhal/stm32_it.c +++ b/stmhal/stm32_it.c @@ -71,6 +71,7 @@ #include STM32_HAL_H #include "py/obj.h" +#include "py/mphal.h" #include "pendsv.h" #include "irq.h" #include "pybthread.h" @@ -95,11 +96,6 @@ extern PCD_HandleTypeDef pcd_hs_handle; // Set the following to 1 to get some more information on the Hard Fault // More information about decoding the fault registers can be found here: // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0646a/Cihdjcfc.html -#define REPORT_HARD_FAULT_REGS 0 - -#if REPORT_HARD_FAULT_REGS - -#include "py/mphal.h" STATIC char *fmt_hex(uint32_t val, char *buf) { const char *hexDig = "0123456789abcdef"; @@ -142,7 +138,13 @@ typedef struct { uint32_t r0, r1, r2, r3, r12, lr, pc, xpsr; } ExceptionRegisters_t; +int pyb_hard_fault_debug = 0; + void HardFault_C_Handler(ExceptionRegisters_t *regs) { + if (!pyb_hard_fault_debug) { + NVIC_SystemReset(); + } + // We need to disable the USB so it doesn't try to write data out on // the VCP and then block indefinitely waiting for the buffer to drain. pyb_usb_flags = 0; @@ -209,14 +211,6 @@ void HardFault_Handler(void) { " b HardFault_C_Handler \n" // Off to C land ); } -#else -void HardFault_Handler(void) { - /* Go to infinite loop when Hard Fault exception occurs */ - while (1) { - __fatal_error("HardFault"); - } -} -#endif // REPORT_HARD_FAULT_REGS /** * @brief This function handles NMI exception. diff --git a/stmhal/stm32_it.h b/stmhal/stm32_it.h index fc61d57be..a168cda83 100644 --- a/stmhal/stm32_it.h +++ b/stmhal/stm32_it.h @@ -63,6 +63,8 @@ ****************************************************************************** */ +extern int pyb_hard_fault_debug; + void NMI_Handler(void); void HardFault_Handler(void); void MemManage_Handler(void); diff --git a/tests/pyb/pyb1.py b/tests/pyb/pyb1.py index 0087ec050..00adc8553 100644 --- a/tests/pyb/pyb1.py +++ b/tests/pyb/pyb1.py @@ -40,3 +40,6 @@ pyb.sync() print(len(pyb.unique_id())) pyb.wfi() + +pyb.fault_debug(True) +pyb.fault_debug(False) -- cgit v1.2.3 From 9779c99317f229435c07f11fd18223956de77b41 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 7 Feb 2017 12:35:39 +1100 Subject: stmhal: Add ability to skip booting from SD card via /flash/SKIPSD file. --- docs/pyboard/general.rst | 5 +++++ stmhal/main.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'docs') 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/stmhal/main.c b/stmhal/main.c index 7bf6f6a3a..7bfdc52c3 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -568,7 +568,10 @@ soft_reset: #if MICROPY_HW_HAS_SDCARD // if an SD card is present then mount it on /sd/ if (sdcard_is_present()) { - mounted_sdcard = init_sdcard_fs(first_soft_reset); + // if there is a file in the flash called "SKIPSD", then we don't mount the SD card + if (!mounted_flash || f_stat(&fs_user_mount_flash.fatfs, "/SKIPSD", NULL) != FR_OK) { + mounted_sdcard = init_sdcard_fs(first_soft_reset); + } } #endif -- cgit v1.2.3 From 3217bbe4910416b9084691ea5ff1ec1530e15ee4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 7 Feb 2017 16:58:43 +1100 Subject: docs/esp8266/tutorial: Specify the baudrate in picocom example command. --- docs/esp8266/tutorial/repl.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') 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, -- cgit v1.2.3 From 21f08524baf11e62384814b7cb8fcd2b5a8998fb Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 7 Feb 2017 20:04:40 +1100 Subject: docs: Add M-logo as favicon. --- docs/conf.py | 2 +- docs/static/favicon.ico | Bin 0 -> 1406 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/static/favicon.ico (limited to 'docs') diff --git a/docs/conf.py b/docs/conf.py index 1a552be2e..66ea325e9 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -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, diff --git a/docs/static/favicon.ico b/docs/static/favicon.ico new file mode 100644 index 000000000..49c615414 Binary files /dev/null and b/docs/static/favicon.ico differ -- cgit v1.2.3