Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff8d0e071c | ||
|
|
0e3722137f | ||
|
|
8e701604d5 | ||
|
|
bc0bc764fc | ||
|
|
183ac71dc8 | ||
|
|
1e3fde0a10 | ||
|
|
72165c01f0 | ||
|
|
ff319dffad | ||
|
|
0344fa1ddf | ||
|
|
2cd79fa924 | ||
|
|
bfd11a35db | ||
|
|
f6e825b42e | ||
|
|
6e6dfdc56b | ||
|
|
1060baa2c2 | ||
|
|
38bd762121 | ||
|
|
039887a0ac | ||
|
|
a58713a899 | ||
|
|
c7da7838ba | ||
|
|
109c1de015 | ||
|
|
4029f51842 | ||
|
|
1559a97810 | ||
|
|
fa73c9cb25 | ||
|
|
88d3054ac0 | ||
|
|
7c4445afe1 | ||
|
|
1a8573ed0e | ||
|
|
47f349e7de | ||
|
|
c92ef361c7 | ||
|
|
4ef67d30f1 | ||
|
|
9a41b32b3f | ||
|
|
efc49c5591 | ||
|
|
6a15ac80dc | ||
|
|
504636815e | ||
|
|
0e557facb9 | ||
|
|
e62a0fe367 | ||
|
|
31619cc589 | ||
|
|
11aa91615e | ||
|
|
8bb71f0b06 | ||
|
|
66d08eb4fe | ||
|
|
6d287a6a02 | ||
|
|
2559e13957 | ||
|
|
b1422de12f | ||
|
|
49c47da804 | ||
|
|
4e54c876a7 |
@@ -17,6 +17,7 @@ script:
|
||||
- make -C bare-arm
|
||||
- make -C qemu-arm
|
||||
- make -C stmhal
|
||||
- make -C stmhal -B MICROPY_PY_WIZNET5K=1 MICROPY_PY_CC3K=1
|
||||
- make -C stmhal BOARD=STM32F4DISC
|
||||
- make -C teensy
|
||||
- make -C windows CROSS_COMPILE=i586-mingw32msvc-
|
||||
|
||||
10
docs/conf.py
@@ -60,7 +60,7 @@ copyright = '2014, Damien P. George'
|
||||
# The short X.Y version.
|
||||
version = '1.3'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.3.1'
|
||||
release = '1.3.6'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -113,7 +113,7 @@ html_theme = 'default'
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
html_theme_path = ['.']
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
@@ -124,7 +124,7 @@ html_theme = 'default'
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
#html_logo = '../logo/trans-logo.png'
|
||||
|
||||
# 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
|
||||
@@ -143,7 +143,7 @@ html_theme = 'default'
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
html_last_updated_fmt = '%d %b %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
@@ -154,7 +154,7 @@ html_theme = 'default'
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
html_additional_pages = {"index":"topindex.html"}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
11
docs/contents.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
Micro Python documentation contents
|
||||
===================================
|
||||
|
||||
.. toctree::
|
||||
|
||||
quickref.rst
|
||||
general.rst
|
||||
tutorial/index.rst
|
||||
library/index.rst
|
||||
hardware/index.rst
|
||||
license.rst
|
||||
20
docs/hardware/index.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
The pyboard hardware
|
||||
====================
|
||||
|
||||
* `PYBv1.0 schematics and layout <http://micropython.org/resources/PYBv10b.pdf>`_ (2.4MiB PDF)
|
||||
* `PYBv1.0 metric dimensions <http://micropython.org/resources/PYBv10b-metric-dimensions.pdf>`_ (360KiB PDF)
|
||||
* `PYBv1.0 imperial dimensions <http://micropython.org/resources/PYBv10b-imperial-dimensions.pdf>`_ (360KiB PDF)
|
||||
|
||||
Datasheets for the components on the pyboard
|
||||
============================================
|
||||
|
||||
* The microcontroller: `STM32F405RGT6 <http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1577/LN1035/PF252144>`_ (link to manufacturer's site)
|
||||
* The accelerometer: `Freescale MMA7660 <http://micropython.org/resources/datasheets/MMA7660FC.pdf>`_ (800kiB PDF)
|
||||
* The LDO voltage regulator: `Microchip MCP1802 <http://micropython.org/resources/datasheets/MCP1802-22053C.pdf>`_ (400kiB PDF)
|
||||
|
||||
Datasheets for other components
|
||||
===============================
|
||||
|
||||
* The LCD display on the LCD touch-sensor skin: `Newhaven Display NHD-C12832A1Z-FSW-FBW-3V3 <http://micropython.org/resources/datasheets/NHD-C12832A1Z-FSW-FBW-3V3.pdf>`_ (460KiB PDF)
|
||||
* The touch sensor chip on the LCD touch-sensor skin: `Freescale MPR121 <http://micropython.org/resources/datasheets/MPR121.pdf>`_ (280KiB PDF)
|
||||
* The digital potentiometer on the audio skin: `Microchip MCP4541 <http://micropython.org/resources/datasheets/MCP4541-22107B.pdf>`_ (2.7MiB PDF)
|
||||
@@ -1,43 +1,15 @@
|
||||
.. Micro Python documentation master file
|
||||
|
||||
Micro Python documentation and references
|
||||
=========================================
|
||||
|
||||
Here you can find documentation for Micro Python and the pyboard.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
quickref.rst
|
||||
|
||||
Software
|
||||
--------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
general.rst
|
||||
tutorial/index.rst
|
||||
|
||||
..
|
||||
.. - Reference for the [pyb module](module/pyb/ "pyb module").
|
||||
.. - Reference for [all modules](module/ "all modules").
|
||||
.. - [Guide for setting up the pyboard on Windows](/static/doc/Micro-Python-Windows-setup.pdf), including DFU programming (PDF).
|
||||
|
||||
The pyboard hardware
|
||||
--------------------
|
||||
|
||||
.. - PYBv1.0 [schematics and layout](/static/doc/PYBv10b.pdf "PYBv1.0") (2.4MiB PDF).
|
||||
.. - PYBv1.0 [metric dimensions](/static/doc/PYBv10b-metric-dimensions.pdf "metric dimensions") (360KiB PDF).
|
||||
.. - PYBv1.0 [imperial dimensions](/static/doc/PYBv10b-imperial-dimensions.pdf "imperial dimensions") (360KiB PDF).
|
||||
|
||||
Datasheets for the components on the pyboard
|
||||
--------------------------------------------
|
||||
|
||||
.. - The microcontroller: [STM32F405RGT6](http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1577/LN1035/PF252144) (external link).
|
||||
.. - The accelerometer: [Freescale MMA7660](/static/doc/MMA7660FC.pdf) (800kiB PDF).
|
||||
.. - The LDO voltage regulator: [Microchip MCP1802](/static/doc/MCP1802-22053C.pdf) (400kiB PDF).
|
||||
|
||||
library/index.rst
|
||||
hardware/index.rst
|
||||
license.rst
|
||||
contents.rst
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
@@ -45,4 +17,3 @@ Indices and tables
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
|
||||
58
docs/library/cmath.rst
Normal file
@@ -0,0 +1,58 @@
|
||||
:mod:`cmath` -- mathematical functions for complex numbers
|
||||
==========================================================
|
||||
|
||||
.. module:: cmath
|
||||
:synopsis: mathematical functions for complex numbers
|
||||
|
||||
The ``cmath`` module provides some basic mathematical funtions for
|
||||
working with complex numbers.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: cos(z)
|
||||
|
||||
Return the cosine of ``z``.
|
||||
|
||||
.. function:: exp(z)
|
||||
|
||||
Return the exponential of ``z``.
|
||||
|
||||
.. function:: log(z)
|
||||
|
||||
Return the natural logarithm of ``z``. The branch cut is along the negative real axis.
|
||||
|
||||
.. function:: log10(z)
|
||||
|
||||
Return the base-10 logarithm of ``z``. The branch cut is along the negative real axis.
|
||||
|
||||
.. function:: phase(z)
|
||||
|
||||
Returns the phase of the number ``z``, in the range (-pi, +pi].
|
||||
|
||||
.. function:: polar(z)
|
||||
|
||||
Returns, as a tuple, the polar form of ``z``.
|
||||
|
||||
.. function:: rect(r, phi)
|
||||
|
||||
Returns the complex number with modulus ``r`` and phase ``phi``.
|
||||
|
||||
.. function:: sin(z)
|
||||
|
||||
Return the sine of ``z``.
|
||||
|
||||
.. function:: sqrt(z)
|
||||
|
||||
Return the square-root of ``z``.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: e
|
||||
|
||||
base of the natural logarithm
|
||||
|
||||
.. data:: pi
|
||||
|
||||
the ratio of a circle's circumference to its diameter
|
||||
29
docs/library/gc.rst
Normal file
@@ -0,0 +1,29 @@
|
||||
:mod:`gc` -- control the garbage collector
|
||||
==========================================
|
||||
|
||||
.. module:: gc
|
||||
:synopsis: control the garbage collector
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: enable()
|
||||
|
||||
Enable automatic garbage collection.
|
||||
|
||||
.. function:: disable()
|
||||
|
||||
Disable automatic garbage collection. Heap memory can still be allocated,
|
||||
and garbage collection can still be initiated manually using :meth:`gc.collect`.
|
||||
|
||||
.. function:: collect()
|
||||
|
||||
Run a garbage collection.
|
||||
|
||||
.. function:: mem_alloc()
|
||||
|
||||
Return the number of bytes of heap RAM that are allocated.
|
||||
|
||||
.. function:: mem_free()
|
||||
|
||||
Return the number of bytes of available heap RAM.
|
||||
54
docs/library/index.rst
Normal file
@@ -0,0 +1,54 @@
|
||||
Micro Python libraries
|
||||
======================
|
||||
|
||||
Python standard libraries
|
||||
-------------------------
|
||||
|
||||
The following standard Python libraries are built in to Micro Python.
|
||||
|
||||
For additional libraries, please download them from the `micropython-lib repository
|
||||
<https://github.com/micropython/micropython-lib>`_.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
cmath.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
os.rst
|
||||
select.rst
|
||||
struct.rst
|
||||
sys.rst
|
||||
time.rst
|
||||
|
||||
Python micro-libraries
|
||||
----------------------
|
||||
|
||||
The following standard Python libraries have been "micro-ified" to fit in with
|
||||
the philosophy of Micro Python. They provide the core functionality of that
|
||||
module and are intended to be a drop-in replacement for the standard Python
|
||||
library.
|
||||
|
||||
The modules are available by their u-name, and also by their non-u-name. The
|
||||
non-u-name can be overridden by a file of that name in your package path.
|
||||
For example, ``import json`` will first search for a file ``json.py`` or
|
||||
directory ``json`` and load that package if it is found. If nothing is found,
|
||||
it will fallback to loading the built-in ``ujson`` module.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
usocket.rst
|
||||
uheapq.rst
|
||||
ujson.rst
|
||||
|
||||
Libraries specific to the pyboard
|
||||
---------------------------------
|
||||
|
||||
The following libraries are specific to the pyboard.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
pyb.rst
|
||||
network.rst
|
||||
177
docs/library/math.rst
Normal file
@@ -0,0 +1,177 @@
|
||||
:mod:`math` -- mathematical functions
|
||||
=====================================
|
||||
|
||||
.. module:: math
|
||||
:synopsis: mathematical functions
|
||||
|
||||
The ``math`` module provides some basic mathematical funtions for
|
||||
working with floating-point numbers.
|
||||
|
||||
*Note:* On the pyboard, floating-point numbers have 32-bit precision.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: acos(x)
|
||||
|
||||
Return the inverse cosine of ``x``.
|
||||
|
||||
.. function:: acosh(x)
|
||||
|
||||
Return the inverse hyperbolic cosine of ``x``.
|
||||
|
||||
.. function:: asin(x)
|
||||
|
||||
Return the inverse sine of ``x``.
|
||||
|
||||
.. function:: asinh(x)
|
||||
|
||||
Return the inverse hyperbolic sine of ``x``.
|
||||
|
||||
.. function:: atan(x)
|
||||
|
||||
Return the inverse tangent of ``x``.
|
||||
|
||||
.. function:: atan2(y, x)
|
||||
|
||||
Return the principal value of the inverse tangent of ``y/x``.
|
||||
|
||||
.. function:: atanh(x)
|
||||
|
||||
Return the inverse hyperbolic tangent of ``x``.
|
||||
|
||||
.. function:: ceil(x)
|
||||
|
||||
Return an integer, being ``x`` rounded towards positive infinity.
|
||||
|
||||
.. function:: copysign(x, y)
|
||||
|
||||
Return ``x`` with the sign of ``y``.
|
||||
|
||||
.. function:: cos(x)
|
||||
|
||||
Return the cosine of ``x``.
|
||||
|
||||
.. function:: cosh(x)
|
||||
|
||||
Return the hyperbolic cosine of ``x``.
|
||||
|
||||
.. function:: degrees(x)
|
||||
|
||||
Return radians ``x`` converted to degrees.
|
||||
|
||||
.. function:: erf(x)
|
||||
|
||||
Return the error function of ``x``.
|
||||
|
||||
.. function:: erfc(x)
|
||||
|
||||
Return the complementary error function of ``x``.
|
||||
|
||||
.. function:: exp(x)
|
||||
|
||||
Return the exponential of ``x``.
|
||||
|
||||
.. function:: expm1(x)
|
||||
|
||||
Return ``exp(x) - 1``.
|
||||
|
||||
.. function:: fabs(x)
|
||||
|
||||
Return the absolute value of ``x``.
|
||||
|
||||
.. function:: floor(x)
|
||||
|
||||
Return an integer, being ``x`` rounded towards negative infinity.
|
||||
|
||||
.. function:: fmod(x, y)
|
||||
|
||||
Return the remainder of ``x/y``.
|
||||
|
||||
.. function:: frexp(x)
|
||||
|
||||
Converts a floating-point number to fractional and integral components.
|
||||
|
||||
.. function:: gamma(x)
|
||||
|
||||
Return the gamma function of ``x``.
|
||||
|
||||
.. function:: isfinite(x)
|
||||
|
||||
Return ``True`` if ``x`` is finite.
|
||||
|
||||
.. function:: isinf(x)
|
||||
|
||||
Return ``True`` if ``x`` is infinite.
|
||||
|
||||
.. function:: isnan(x)
|
||||
|
||||
Return ``True`` if ``x`` is not-a-number
|
||||
|
||||
.. function:: ldexp(x, exp)
|
||||
|
||||
Return ``x * (2**exp)``.
|
||||
|
||||
.. function:: lgamma(x)
|
||||
|
||||
Return the natural logarithm of the gamma function of ``x``.
|
||||
|
||||
.. function:: log(x)
|
||||
|
||||
Return the natural logarithm of ``x``.
|
||||
|
||||
.. function:: log10(x)
|
||||
|
||||
Return the base-10 logarithm of ``x``.
|
||||
|
||||
.. function:: log2(x)
|
||||
|
||||
Return the base-2 logarithm of ``x``.
|
||||
|
||||
.. function:: modf(x)
|
||||
|
||||
Return a tuple of two floats, being the fractional and integral parts of
|
||||
``x``. Both return values have the same sign as ``x``.
|
||||
|
||||
.. function:: pow(x, y)
|
||||
|
||||
Returns ``x`` to the power of ``y``.
|
||||
|
||||
.. function:: radians(x)
|
||||
|
||||
Return degrees ``x`` converted to radians.
|
||||
|
||||
.. function:: sin(x)
|
||||
|
||||
Return the sine of ``x``.
|
||||
|
||||
.. function:: sinh(x)
|
||||
|
||||
Return the hyperbolic sine of ``x``.
|
||||
|
||||
.. function:: sqrt(x)
|
||||
|
||||
Return the square root of ``x``.
|
||||
|
||||
.. function:: tan(x)
|
||||
|
||||
Return the tangent of ``x``.
|
||||
|
||||
.. function:: tanh(x)
|
||||
|
||||
Return the hyperbolic tangent of ``x``.
|
||||
|
||||
.. function:: trunc(x)
|
||||
|
||||
Return an integer, being ``x`` rounded towards 0.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: e
|
||||
|
||||
base of the natural logarithm
|
||||
|
||||
.. data:: pi
|
||||
|
||||
the ratio of a circle's circumference to its diameter
|
||||
63
docs/library/network.rst
Normal file
@@ -0,0 +1,63 @@
|
||||
****************************************
|
||||
:mod:`network` --- network configuration
|
||||
****************************************
|
||||
|
||||
.. module:: network
|
||||
:synopsis: network configuration
|
||||
|
||||
This module provides network drivers and routing configuration.
|
||||
|
||||
|
||||
class CC3k
|
||||
==========
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: CC3k(spi, pin_cs, pin_en, pin_irq)
|
||||
|
||||
Initialise the CC3000 using the given SPI bus and pins and return a CC3k object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: cc3k.connect(ssid, key=None, \*, security=WPA2, bssid=None)
|
||||
|
||||
|
||||
class WIZnet5k
|
||||
==============
|
||||
|
||||
This class allows you to control WIZnet5x00 Ethernet adaptors based on
|
||||
the W5200 and W5500 chipsets (only W5200 tested).
|
||||
|
||||
Example usage::
|
||||
|
||||
import wiznet5k
|
||||
w = wiznet5k.WIZnet5k()
|
||||
print(w.ipaddr())
|
||||
w.gethostbyname('micropython.org')
|
||||
s = w.socket()
|
||||
s.connect(('192.168.0.2', 8080))
|
||||
s.send('hello')
|
||||
print(s.recv(10))
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: WIZnet5k(spi, pin_cs, pin_rst)
|
||||
|
||||
Create and return a WIZnet5k object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: wiznet5k.ipaddr([(ip, subnet, gateway, dns)])
|
||||
|
||||
Get/set IP address, subnet mask, gateway and DNS.
|
||||
|
||||
.. method:: wiznet5k.regs()
|
||||
|
||||
Dump WIZnet5k registers.
|
||||
67
docs/library/os.rst
Normal file
@@ -0,0 +1,67 @@
|
||||
:mod:`os` -- basic "operating system" services
|
||||
==============================================
|
||||
|
||||
.. module:: os
|
||||
:synopsis: basic "operating system" services
|
||||
|
||||
The ``os`` module contains functions for filesystem access and ``urandom``.
|
||||
|
||||
Pyboard specifics
|
||||
-----------------
|
||||
|
||||
The filesystem on the pyboard has ``/`` as the root directory and the
|
||||
available physical drives are accessible from here. They are currently:
|
||||
|
||||
``/flash`` -- the internal flash filesystem
|
||||
|
||||
``/sd`` -- the SD card (if it exists)
|
||||
|
||||
On boot up, the current directory is ``/flash`` if no SD card is inserted,
|
||||
otherwise it is ``/sd``.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: chdir(path)
|
||||
|
||||
Change current directory.
|
||||
|
||||
.. function:: getcwd()
|
||||
|
||||
Get the current directory.
|
||||
|
||||
.. function:: listdir([dir])
|
||||
|
||||
With no argument, list the current directory. Otherwise list the given directory.
|
||||
|
||||
.. function:: mkdir(path)
|
||||
|
||||
Create a new directory.
|
||||
|
||||
.. function:: remove(path)
|
||||
|
||||
Remove a file.
|
||||
|
||||
.. function:: rmdir(path)
|
||||
|
||||
Remove a directory.
|
||||
|
||||
.. function:: stat(path)
|
||||
|
||||
Get the status of a file or directory.
|
||||
|
||||
.. function:: sync()
|
||||
|
||||
Sync all filesystems.
|
||||
|
||||
.. function:: urandom(n)
|
||||
|
||||
Return a bytes object with n random bytes, generated by the hardware
|
||||
random number generator.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: sep
|
||||
|
||||
separation character used in paths
|
||||
52
docs/library/pyb.ADC.rst
Normal file
@@ -0,0 +1,52 @@
|
||||
.. _pyb.ADC:
|
||||
|
||||
class ADC -- analog to digital conversion: read analog values on a pin
|
||||
======================================================================
|
||||
|
||||
Usage::
|
||||
|
||||
import pyb
|
||||
|
||||
adc = pyb.ADC(pin) # create an analog object from a pin
|
||||
val = adc.read() # read an analog value
|
||||
|
||||
adc = pyb.ADCAll(resolution) # creale an ADCAll object
|
||||
val = adc.read_channel(channel) # read the given channel
|
||||
val = adc.read_core_temp() # read MCU temperature
|
||||
val = adc.read_core_vbat() # read MCU VBAT
|
||||
val = adc.read_core_vref() # read MCU VREF
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.ADC(pin)
|
||||
|
||||
Create an ADC object associated with the given pin.
|
||||
This allows you to then read analog values on that pin.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: adc.read()
|
||||
|
||||
Read the value on the analog pin and return it. The returned value
|
||||
will be between 0 and 4095.
|
||||
|
||||
.. method:: adc.read_timed(buf, freq)
|
||||
|
||||
Read analog values into the given buffer at the given frequency. Buffer
|
||||
can be bytearray or array.array for example. If a buffer with 8-bit elements
|
||||
is used, sample resolution will be reduced to 8 bits.
|
||||
|
||||
Example::
|
||||
|
||||
adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19
|
||||
buf = bytearray(100) # create a buffer of 100 bytes
|
||||
adc.read_timed(buf, 10) # read analog values into buf at 10Hz
|
||||
# this will take 10 seconds to finish
|
||||
for val in buf: # loop over all values
|
||||
print(val) # print the value out
|
||||
|
||||
This function does not allocate any memory.
|
||||
51
docs/library/pyb.Accel.rst
Normal file
@@ -0,0 +1,51 @@
|
||||
class Accel -- accelerometer control
|
||||
====================================
|
||||
|
||||
Accel is an object that controls the accelerometer. Example usage::
|
||||
|
||||
accel = pyb.Accel()
|
||||
for i in range(10):
|
||||
print(accel.x(), accel.y(), accel.z())
|
||||
|
||||
Raw values are between -32 and 31.
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.Accel()
|
||||
|
||||
Create and return an accelerometer object.
|
||||
|
||||
Note: if you read accelerometer values immediately after creating this object
|
||||
you will get 0. It takes around 20ms for the first sample to be ready, so,
|
||||
unless you have some other code between creating this object and reading its
|
||||
values, you should put a ``pyb.delay(20)`` after creating it. For example::
|
||||
|
||||
accel = pyb.Accel()
|
||||
pyb.delay(20)
|
||||
print(accel.x())
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: accel.filtered_xyz()
|
||||
|
||||
Get a 3-tuple of filtered x, y and z values.
|
||||
|
||||
.. method:: accel.tilt()
|
||||
|
||||
Get the tilt register.
|
||||
|
||||
.. method:: accel.x()
|
||||
|
||||
Get the x-axis value.
|
||||
|
||||
.. method:: accel.y()
|
||||
|
||||
Get the y-axis value.
|
||||
|
||||
.. method:: accel.z()
|
||||
|
||||
Get the z-axis value.
|
||||
87
docs/library/pyb.CAN.rst
Normal file
@@ -0,0 +1,87 @@
|
||||
class CAN -- controller area network communication bus
|
||||
======================================================
|
||||
|
||||
CAN implements the standard CAN communications protocol. At
|
||||
the physical level it consists of 2 lines: RX and TX. Note that
|
||||
to connect the pyboard to a CAN bus you must use a CAN transceiver
|
||||
to convert the CAN logic signals from the pyboard to the correct
|
||||
voltage levels on the bus.
|
||||
|
||||
Note that this driver does not yet support filter configuration
|
||||
(it defaults to a single filter that lets through all messages),
|
||||
or bus timing configuration (except for setting the prescaler).
|
||||
|
||||
Example usage (works without anything connected)::
|
||||
|
||||
from pyb import CAN
|
||||
can = pyb.CAN(1, pyb.CAN.LOOPBACK)
|
||||
can.send('message!', 123) # send message to id 123
|
||||
can.recv(0) # receive message on FIFO 0
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.CAN(bus, ...)
|
||||
|
||||
Construct a CAN object on the given bus. ``bus`` can be 1-2, or 'YA' or 'YB'.
|
||||
With no additional parameters, the CAN object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
The physical pins of the CAN busses are:
|
||||
|
||||
- ``CAN(1)`` is on ``YA``: ``(RX, TX) = (Y3, Y4) = (PB8, PB9)``
|
||||
- ``CAN(2)`` is on ``YB``: ``(RX, TX) = (Y5, Y6) = (PB12, PB13)``
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: can.init(mode, extframe=False, prescaler=100, \*, sjw=1, bs1=6, bs2=8)
|
||||
|
||||
Initialise the CAN bus with the given parameters:
|
||||
|
||||
- ``mode`` is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK
|
||||
|
||||
If ``extframe`` is True then the bus uses extended identifiers in the frames (29 bits).
|
||||
Otherwise it uses standard 11 bit identifiers.
|
||||
|
||||
.. method:: can.deinit()
|
||||
|
||||
Turn off the CAN bus.
|
||||
|
||||
.. method:: can.any(fifo)
|
||||
|
||||
Return ``True`` if any message waiting on the FIFO, else ``False``.
|
||||
|
||||
.. method:: can.recv(fifo, \*, timeout=5000)
|
||||
|
||||
Receive data on the bus:
|
||||
|
||||
- ``fifo`` is an integer, which is the FIFO to receive on
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive.
|
||||
|
||||
Return value: buffer of data bytes.
|
||||
|
||||
.. method:: can.send(send, addr, \*, timeout=5000)
|
||||
|
||||
Send a message on the bus:
|
||||
|
||||
- ``send`` is the data to send (an integer to send, or a buffer object).
|
||||
- ``addr`` is the address to send to
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the send.
|
||||
|
||||
Return value: ``None``.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: CAN.NORMAL
|
||||
.. data:: CAN.LOOPBACK
|
||||
.. data:: CAN.SILENT
|
||||
.. data:: CAN.SILENT_LOOPBACK
|
||||
|
||||
the mode of the CAN bus
|
||||
69
docs/library/pyb.DAC.rst
Normal file
@@ -0,0 +1,69 @@
|
||||
.. _pyb.DAC:
|
||||
|
||||
class DAC -- digital to analog conversion
|
||||
=========================================
|
||||
|
||||
The DAC is used to output analog values (a specific voltage) on pin X5 or pin X6.
|
||||
The voltage will be between 0 and 3.3V.
|
||||
|
||||
*This module will undergo changes to the API.*
|
||||
|
||||
Example usage::
|
||||
|
||||
from pyb import DAC
|
||||
|
||||
dac = DAC(1) # create DAC 1 on pin X5
|
||||
dac.write(128) # write a value to the DAC (makes X5 1.65V)
|
||||
|
||||
To output a continuous sine-wave::
|
||||
|
||||
import math
|
||||
from pyb import DAC
|
||||
|
||||
# create a buffer containing a sine-wave
|
||||
buf = bytearray(100)
|
||||
for i in range(len(buf)):
|
||||
buf[i] = 128 + int(127 \* math.sin(2 \* math.pi \* i / len(buf)))
|
||||
|
||||
# output the sine-wave at 400Hz
|
||||
dac = DAC(1)
|
||||
dac.write_timed(buf, 400 \* len(buf), mode=DAC.CIRCULAR)
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.DAC(port)
|
||||
|
||||
Construct a new DAC object.
|
||||
|
||||
``port`` can be a pin object, or an integer (1 or 2).
|
||||
DAC(1) is on pin X5 and DAC(2) is on pin X6.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: dac.noise(freq)
|
||||
|
||||
Generate a pseudo-random noise signal. A new random sample is written
|
||||
to the DAC output at the given frequency.
|
||||
|
||||
.. method:: dac.triangle(freq)
|
||||
|
||||
Generate a triangle wave. The value on the DAC output changes at
|
||||
the given frequency, and the frequence of the repeating triangle wave
|
||||
itself is 256 (or 1024, need to check) times smaller.
|
||||
|
||||
.. method:: dac.write(value)
|
||||
|
||||
Direct access to the DAC output (8 bit only at the moment).
|
||||
|
||||
.. method:: dac.write_timed(data, freq, \*, mode=DAC.NORMAL)
|
||||
|
||||
Initiates a burst of RAM to DAC using a DMA transfer.
|
||||
The input data is treated as an array of bytes (8 bit data).
|
||||
|
||||
``mode`` can be ``DAC.NORMAL`` or ``DAC.CIRCULAR``.
|
||||
|
||||
TIM6 is used to control the frequency of the transfer.
|
||||
113
docs/library/pyb.ExtInt.rst
Normal file
@@ -0,0 +1,113 @@
|
||||
.. _pyb.ExtInt:
|
||||
|
||||
class ExtInt -- configure I/O pins to interrupt on external events
|
||||
==================================================================
|
||||
|
||||
There are a total of 22 interrupt lines. 16 of these can come from GPIO pins
|
||||
and the remaining 6 are from internal sources.
|
||||
|
||||
For lines 0 thru 15, a given line can map to the corresponding line from an
|
||||
arbitrary port. So line 0 can map to Px0 where x is A, B, C, ... and
|
||||
line 1 can map to Px1 where x is A, B, C, ... ::
|
||||
|
||||
def callback(line):
|
||||
print("line =", line)
|
||||
|
||||
Note: ExtInt will automatically configure the gpio line as an input. ::
|
||||
|
||||
extint = pyb.ExtInt(pin, pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, callback)
|
||||
|
||||
Now every time a falling edge is seen on the X1 pin, the callback will be
|
||||
called. Caution: mechanical pushbuttons have "bounce" and pushing or
|
||||
releasing a switch will often generate multiple edges.
|
||||
See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed
|
||||
explanation, along with various techniques for debouncing.
|
||||
|
||||
Trying to register 2 callbacks onto the same pin will throw an exception.
|
||||
|
||||
If pin is passed as an integer, then it is assumed to map to one of the
|
||||
internal interrupt sources, and must be in the range 16 thru 22.
|
||||
|
||||
All other pin objects go through the pin mapper to come up with one of the
|
||||
gpio pins. ::
|
||||
|
||||
extint = pyb.ExtInt(pin, mode, pull, callback)
|
||||
|
||||
Valid modes are pyb.ExtInt.IRQ_RISING, pyb.ExtInt.IRQ_FALLING,
|
||||
pyb.ExtInt.IRQ_RISING_FALLING, pyb.ExtInt.EVT_RISING,
|
||||
pyb.ExtInt.EVT_FALLING, and pyb.ExtInt.EVT_RISING_FALLING.
|
||||
|
||||
Only the IRQ_xxx modes have been tested. The EVT_xxx modes have
|
||||
something to do with sleep mode and the WFE instruction.
|
||||
|
||||
Valid pull values are pyb.Pin.PULL_UP, pyb.Pin.PULL_DOWN, pyb.Pin.PULL_NONE.
|
||||
|
||||
There is also a C API, so that drivers which require EXTI interrupt lines
|
||||
can also use this code. See extint.h for the available functions and
|
||||
usrsw.h for an example of using this.
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.ExtInt(pin, mode, pull, callback)
|
||||
|
||||
Create an ExtInt object:
|
||||
|
||||
- ``pin`` is the pin on which to enable the interrupt (can be a pin object or any valid pin name).
|
||||
- ``mode`` can be one of:
|
||||
- ``ExtInt.IRQ_RISING`` - trigger on a rising edge;
|
||||
- ``ExtInt.IRQ_FALLING`` - trigger on a falling edge;
|
||||
- ``ExtInt.IRQ_RISING_FALLING`` - trigger on a rising or falling edge.
|
||||
- ``pull`` can be one of:
|
||||
- ``pyb.Pin.PULL_NONE`` - no pull up or down resistors;
|
||||
- ``pyb.Pin.PULL_UP`` - enable the pull-up resistor;
|
||||
- ``pyb.Pin.PULL_DOWN`` - enable the pull-down resistor.
|
||||
- ``callback`` is the function to call when the interrupt triggers. The
|
||||
callback function must accept exactly 1 argument, which is the line that
|
||||
triggered the interrupt.
|
||||
|
||||
|
||||
Class methods
|
||||
-------------
|
||||
|
||||
.. method:: ExtInt.regs()
|
||||
|
||||
Dump the values of the EXTI registers.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: extint.disable()
|
||||
|
||||
Disable the interrupt associated with the ExtInt object.
|
||||
This could be useful for debouncing.
|
||||
|
||||
.. method:: extint.enable()
|
||||
|
||||
Enable a disabled interrupt.
|
||||
|
||||
.. method:: extint.line()
|
||||
|
||||
Return the line number that the pin is mapped to.
|
||||
|
||||
.. method:: extint.swint()
|
||||
|
||||
Trigger the callback from software.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: ExtInt.IRQ_FALLING
|
||||
|
||||
interrupt on a falling edge
|
||||
|
||||
.. data:: ExtInt.IRQ_RISING
|
||||
|
||||
interrupt on a rising edge
|
||||
|
||||
.. data:: ExtInt.IRQ_RISING_FALLING
|
||||
|
||||
interrupt on a rising or falling edge
|
||||
153
docs/library/pyb.I2C.rst
Normal file
@@ -0,0 +1,153 @@
|
||||
.. _pyb.I2C:
|
||||
|
||||
class I2C -- a two-wire serial protocol
|
||||
=======================================
|
||||
|
||||
I2C is a two-wire protocol for communicating between devices. At the physical
|
||||
level it consists of 2 wires: SCL and SDA, the clock and data lines respectively.
|
||||
|
||||
I2C objects are created attached to a specific bus. They can be initialised
|
||||
when created, or initialised later on::
|
||||
|
||||
from pyb import I2C
|
||||
|
||||
i2c = I2C(1) # create on bus 1
|
||||
i2c = I2C(1, I2C.MASTER) # create and init as a master
|
||||
i2c.init(I2C.MASTER, baudrate=20000) # init as a master
|
||||
i2c.init(I2C.SLAVE, addr=0x42) # init as a slave with given address
|
||||
i2c.deinit() # turn off the peripheral
|
||||
|
||||
Printing the i2c object gives you information about its configuration.
|
||||
|
||||
Basic methods for slave are send and recv::
|
||||
|
||||
i2c.send('abc') # send 3 bytes
|
||||
i2c.send(0x42) # send a single byte, given by the number
|
||||
data = i2c.recv(3) # receive 3 bytes
|
||||
|
||||
To receive inplace, first create a bytearray::
|
||||
|
||||
data = bytearray(3) # create a buffer
|
||||
i2c.recv(data) # receive 3 bytes, writing them into data
|
||||
|
||||
You can specify a timeout (in ms)::
|
||||
|
||||
i2c.send(b'123', timeout=2000) # timout after 2 seconds
|
||||
|
||||
A master must specify the recipient's address::
|
||||
|
||||
i2c.init(I2C.MASTER)
|
||||
i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42
|
||||
i2c.send(b'456', addr=0x42) # keyword for address
|
||||
|
||||
Master also has other methods::
|
||||
|
||||
i2c.is_ready(0x42) # check if slave 0x42 is ready
|
||||
i2c.scan() # scan for slaves on the bus, returning
|
||||
# a list of valid addresses
|
||||
i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of slave 0x42,
|
||||
# starting at address 2 in the slave
|
||||
i2c.mem_write('abc', 0x42, 2, timeout=1000)
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.I2C(bus, ...)
|
||||
|
||||
Construct an I2C object on the given bus. ``bus`` can be 1 or 2.
|
||||
With no additional parameters, the I2C object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
The physical pins of the I2C busses are:
|
||||
|
||||
- ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)``
|
||||
- ``I2C(2)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PB10, PB11)``
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: i2c.deinit()
|
||||
|
||||
Turn off the I2C bus.
|
||||
|
||||
.. method:: i2c.init(mode, \*, addr=0x12, baudrate=400000, gencall=False)
|
||||
|
||||
Initialise the I2C bus with the given parameters:
|
||||
|
||||
- ``mode`` must be either ``I2C.MASTER`` or ``I2C.SLAVE``
|
||||
- ``addr`` is the 7-bit address (only sensible for a slave)
|
||||
- ``baudrate`` is the SCL clock rate (only sensible for a master)
|
||||
- ``gencall`` is whether to support general call mode
|
||||
|
||||
.. method:: i2c.is_ready(addr)
|
||||
|
||||
Check if an I2C device responds to the given address. Only valid when in master mode.
|
||||
|
||||
.. method:: i2c.mem_read(data, addr, memaddr, timeout=5000, addr_size=8)
|
||||
|
||||
Read from the memory of an I2C device:
|
||||
|
||||
- ``data`` can be an integer or a buffer to read into
|
||||
- ``addr`` is the I2C device address
|
||||
- ``memaddr`` is the memory location within the I2C device
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the read
|
||||
- ``addr_size`` selects width of memaddr: 8 or 16 bits
|
||||
|
||||
Returns the read data.
|
||||
This is only valid in master mode.
|
||||
|
||||
.. method:: i2c.mem_write(data, addr, memaddr, timeout=5000, addr_size=8)
|
||||
|
||||
Write to the memory of an I2C device:
|
||||
|
||||
- ``data`` can be an integer or a buffer to write from
|
||||
- ``addr`` is the I2C device address
|
||||
- ``memaddr`` is the memory location within the I2C device
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the write
|
||||
- ``addr_size`` selects width of memaddr: 8 or 16 bits
|
||||
|
||||
Returns ``None``.
|
||||
This is only valid in master mode.
|
||||
|
||||
.. method:: i2c.recv(recv, addr=0x00, timeout=5000)
|
||||
|
||||
Receive data on the bus:
|
||||
|
||||
- ``recv`` can be an integer, which is the number of bytes to receive,
|
||||
or a mutable buffer, which will be filled with received bytes
|
||||
- ``addr`` is the address to receive from (only required in master mode)
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive
|
||||
|
||||
Return value: if ``recv`` is an integer then a new buffer of the bytes received,
|
||||
otherwise the same buffer that was passed in to ``recv``.
|
||||
|
||||
.. method:: i2c.scan()
|
||||
|
||||
Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond.
|
||||
Only valid when in master mode.
|
||||
|
||||
.. method:: i2c.send(send, addr=0x00, timeout=5000)
|
||||
|
||||
Send data on the bus:
|
||||
|
||||
- ``send`` is the data to send (an integer to send, or a buffer object)
|
||||
- ``addr`` is the address to send to (only required in master mode)
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the send
|
||||
|
||||
Return value: ``None``.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: I2C.MASTER
|
||||
|
||||
for initialising the bus to master mode
|
||||
|
||||
.. data:: I2C.SLAVE
|
||||
|
||||
for initialising the bus to slave mode
|
||||
94
docs/library/pyb.LCD.rst
Normal file
@@ -0,0 +1,94 @@
|
||||
class LCD -- LCD control for the LCD touch-sensor pyskin
|
||||
========================================================
|
||||
|
||||
The LCD class is used to control the LCD on the LCD touch-sensor pyskin,
|
||||
LCD32MKv1.0. The LCD is a 128x32 pixel monochrome screen, part NHD-C12832A1Z.
|
||||
|
||||
The pyskin must be connected in either the X or Y positions, and then
|
||||
an LCD object is made using::
|
||||
|
||||
lcd = pyb.LCD('X') # if pyskin is in the X position
|
||||
lcd = pyb.LCD('Y') # if pyskin is in the Y position
|
||||
|
||||
Then you can use::
|
||||
|
||||
lcd.light(True) # turn the backlight on
|
||||
lcd.write('Hello world!\n') # print text to the screen
|
||||
|
||||
This driver implements a double buffer for setting/getting pixels.
|
||||
For example, to make a bouncing dot, try::
|
||||
|
||||
x = y = 0
|
||||
dx = dy = 1
|
||||
while True:
|
||||
# update the dot's position
|
||||
x += dx
|
||||
y += dy
|
||||
|
||||
# make the dot bounce of the edges of the screen
|
||||
if x <= 0 or x >= 127: dx = -dx
|
||||
if y <= 0 or y >= 31: dy = -dy
|
||||
|
||||
lcd.fill(0) # clear the buffer
|
||||
lcd.pixel(x, y, 1) # draw the dot
|
||||
lcd.show() # show the buffer
|
||||
pyb.delay(50) # pause for 50ms
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.LCD(skin_position)
|
||||
|
||||
Construct an LCD object in the given skin position. ``skin_position`` can be 'X' or 'Y', and
|
||||
should match the position where the LCD pyskin is plugged in.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: lcd.command(instr_data, buf)
|
||||
|
||||
Send an arbitrary command to the LCD. Pass 0 for ``instr_data`` to send an
|
||||
instruction, otherwise pass 1 to send data. ``buf`` is a buffer with the
|
||||
instructions/data to send.
|
||||
|
||||
.. method:: lcd.contrast(value)
|
||||
|
||||
Set the contrast of the LCD. Valid values are between 0 and 47.
|
||||
|
||||
.. method:: lcd.fill(colour)
|
||||
|
||||
Fill the screen with the given colour (0 or 1 for white or black).
|
||||
|
||||
This method writes to the hidden buffer. Use ``show()`` to show the buffer.
|
||||
|
||||
.. method:: lcd.get(x, y)
|
||||
|
||||
Get the pixel at the position ``(x, y)``. Returns 0 or 1.
|
||||
|
||||
This method reads from the visible buffer.
|
||||
|
||||
.. method:: lcd.light(value)
|
||||
|
||||
Turn the backlight on/off. True or 1 turns it on, False or 0 turns it off.
|
||||
|
||||
.. method:: lcd.pixel(x, y, colour)
|
||||
|
||||
Set the pixel at ``(x, y)`` to the given colour (0 or 1).
|
||||
|
||||
This method writes to the hidden buffer. Use ``show()`` to show the buffer.
|
||||
|
||||
.. method:: lcd.show()
|
||||
|
||||
Show the hidden buffer on the screen.
|
||||
|
||||
.. method:: lcd.text(str, x, y, colour)
|
||||
|
||||
Draw the given text to the position ``(x, y)`` using the given colour (0 or 1).
|
||||
|
||||
This method writes to the hidden buffer. Use ``show()`` to show the buffer.
|
||||
|
||||
.. method:: lcd.write(str)
|
||||
|
||||
Write the string ``str`` to the screen. It will appear immediately.
|
||||
38
docs/library/pyb.LED.rst
Normal file
@@ -0,0 +1,38 @@
|
||||
.. _pyb.LED:
|
||||
|
||||
class LED -- LED object
|
||||
=======================
|
||||
|
||||
The LED object controls an individual LED (Light Emitting Diode).
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.LED(id)
|
||||
|
||||
Create an LED object associated with the given LED:
|
||||
|
||||
- ``id`` is the LED number, 1-4.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: led.intensity([value])
|
||||
|
||||
Get or set the LED intensity. Intensity ranges between 0 (off) and 255 (full on).
|
||||
If no argument is given, return the LED intensity.
|
||||
If an argument is given, set the LED intensity and return ``None``.
|
||||
|
||||
.. method:: led.off()
|
||||
|
||||
Turn the LED off.
|
||||
|
||||
.. method:: led.on()
|
||||
|
||||
Turn the LED on.
|
||||
|
||||
.. method:: led.toggle()
|
||||
|
||||
Toggle the LED between on and off.
|
||||
266
docs/library/pyb.Pin.rst
Normal file
@@ -0,0 +1,266 @@
|
||||
.. _pyb.Pin:
|
||||
|
||||
class Pin -- control I/O pins
|
||||
=============================
|
||||
|
||||
A pin is the basic object to control I/O pins. It has methods to set
|
||||
the mode of the pin (input, output, etc) and methods to get and set the
|
||||
digital logic level. For analog control of a pin, see the ADC class.
|
||||
|
||||
Usage Model:
|
||||
|
||||
All Board Pins are predefined as pyb.Pin.board.Name ::
|
||||
|
||||
x1_pin = pyb.Pin.board.X1
|
||||
|
||||
g = pyb.Pin(pyb.Pin.board.X1, pyb.Pin.IN)
|
||||
|
||||
CPU pins which correspond to the board pins are available
|
||||
as ``pyb.cpu.Name``. For the CPU pins, the names are the port letter
|
||||
followed by the pin number. On the PYBv1.0, ``pyb.Pin.board.X1`` and
|
||||
``pyb.Pin.cpu.B6`` are the same pin.
|
||||
|
||||
You can also use strings::
|
||||
|
||||
g = pyb.Pin('X1', pyb.Pin.OUT_PP)
|
||||
|
||||
Users can add their own names::
|
||||
|
||||
MyMapperDict = { 'LeftMotorDir' : pyb.Pin.cpu.C12 }
|
||||
pyb.Pin.dict(MyMapperDict)
|
||||
g = pyb.Pin("LeftMotorDir", pyb.Pin.OUT_OD)
|
||||
|
||||
and can query mappings ::
|
||||
|
||||
pin = pyb.Pin("LeftMotorDir")
|
||||
|
||||
Users can also add their own mapping function::
|
||||
|
||||
def MyMapper(pin_name):
|
||||
if pin_name == "LeftMotorDir":
|
||||
return pyb.Pin.cpu.A0
|
||||
|
||||
pyb.Pin.mapper(MyMapper)
|
||||
|
||||
So, if you were to call: ``pyb.Pin("LeftMotorDir", pyb.Pin.OUT_PP)``
|
||||
then ``"LeftMotorDir"`` is passed directly to the mapper function.
|
||||
|
||||
To summarise, the following order determines how things get mapped into
|
||||
an ordinal pin number:
|
||||
|
||||
1. Directly specify a pin object
|
||||
2. User supplied mapping function
|
||||
3. User supplied mapping (object must be usable as a dictionary key)
|
||||
4. Supply a string which matches a board pin
|
||||
5. Supply a string which matches a CPU port/pin
|
||||
|
||||
You can set ``pyb.Pin.debug(True)`` to get some debug information about
|
||||
how a particular object gets mapped to a pin.
|
||||
|
||||
When a pin has the ``Pin.PULL_UP`` or ``Pin.PULL_DOWN`` pull-mode enabled,
|
||||
that pin has an effective 40k Ohm resistor pulling it to 3V3 or GND
|
||||
respectively (except pin Y5 which has 11k Ohm resistors).
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.Pin(id, ...)
|
||||
|
||||
Create a new Pin object associated with the id. If additional arguments are given,
|
||||
they are used to initialise the pin. See :meth:`pin.init`.
|
||||
|
||||
|
||||
Class methods
|
||||
-------------
|
||||
|
||||
.. method:: Pin.af_list()
|
||||
|
||||
Returns an array of alternate functions available for this pin.
|
||||
|
||||
.. method:: Pin.debug([state])
|
||||
|
||||
Get or set the debugging state (``True`` or ``False`` for on or off).
|
||||
|
||||
.. method:: Pin.dict([dict])
|
||||
|
||||
Get or set the pin mapper dictionary.
|
||||
|
||||
.. method:: Pin.mapper([fun])
|
||||
|
||||
Get or set the pin mapper function.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: pin.init(mode, pull=Pin.PULL_NONE, af=-1)
|
||||
|
||||
Initialise the pin:
|
||||
|
||||
- ``mode`` can be one of:
|
||||
- ``Pin.IN`` - configure the pin for input;
|
||||
- ``Pin.OUT_PP`` - configure the pin for output, with push-pull control;
|
||||
- ``Pin.OUT_OD`` - configure the pin for output, with open-drain control;
|
||||
- ``Pin.AF_PP`` - configure the pin for alternate function, pull-pull;
|
||||
- ``Pin.AF_OD`` - configure the pin for alternate function, open-drain;
|
||||
- ``Pin.ANALOG`` - configure the pin for analog.
|
||||
- ``pull`` can be one of:
|
||||
- ``Pin.PULL_NONE`` - no pull up or down resistors;
|
||||
- ``Pin.PULL_UP`` - enable the pull-up resistor;
|
||||
- ``Pin.PULL_DOWN`` - enable the pull-down resistor.
|
||||
- when mode is Pin.AF_PP or Pin.AF_OD, then af can be the index or name
|
||||
of one of the alternate functions associated with a pin.
|
||||
|
||||
Returns: ``None``.
|
||||
|
||||
.. method:: pin.high()
|
||||
|
||||
Set the pin to a high logic level.
|
||||
|
||||
.. method:: pin.low()
|
||||
|
||||
Set the pin to a low logic level.
|
||||
|
||||
.. method:: pin.value([value])
|
||||
|
||||
Get or set the digital logic level of the pin:
|
||||
|
||||
- With no argument, return 0 or 1 depending on the logic level of the pin.
|
||||
- With ``value`` given, set the logic level of the pin. ``value`` can be
|
||||
anything that converts to a boolean. If it converts to ``True``, the pin
|
||||
is set high, otherwise it is set low.
|
||||
|
||||
.. method:: pin.__str__()
|
||||
|
||||
Return a string describing the pin object.
|
||||
|
||||
.. method:: pin.af()
|
||||
|
||||
Returns the currently configured alternate-function of the pin. The
|
||||
integer returned will match one of the allowed constants for the af
|
||||
argument to the init function.
|
||||
|
||||
.. method:: pin.gpio()
|
||||
|
||||
Returns the base address of the GPIO block associated with this pin.
|
||||
|
||||
.. method:: pin.mode()
|
||||
|
||||
Returns the currently configured mode of the pin. The integer returned
|
||||
will match one of the allowed constants for the mode argument to the init
|
||||
function.
|
||||
|
||||
.. method:: pin.name()
|
||||
|
||||
Get the pin name.
|
||||
|
||||
.. method:: pin.names()
|
||||
|
||||
Returns the cpu and board names for this pin.
|
||||
|
||||
.. method:: pin.pin()
|
||||
|
||||
Get the pin number.
|
||||
|
||||
.. method:: pin.port()
|
||||
|
||||
Get the pin port.
|
||||
|
||||
.. method:: pin.pull()
|
||||
|
||||
Returns the currently configured pull of the pin. The integer returned
|
||||
will match one of the allowed constants for the pull argument to the init
|
||||
function.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: Pin.AF_OD
|
||||
|
||||
initialise the pin to alternate-function mode with an open-drain drive
|
||||
|
||||
.. data:: Pin.AF_PP
|
||||
|
||||
initialise the pin to alternate-function mode with a push-pull drive
|
||||
|
||||
.. data:: Pin.ANALOG
|
||||
|
||||
initialise the pin to analog mode
|
||||
|
||||
.. data:: Pin.IN
|
||||
|
||||
initialise the pin to input mode
|
||||
|
||||
.. data:: Pin.OUT_OD
|
||||
|
||||
initialise the pin to output mode with an open-drain drive
|
||||
|
||||
.. data:: Pin.OUT_PP
|
||||
|
||||
initialise the pin to output mode with a push-pull drive
|
||||
|
||||
.. data:: Pin.PULL_DOWN
|
||||
|
||||
enable the pull-down resistor on the pin
|
||||
|
||||
.. data:: Pin.PULL_NONE
|
||||
|
||||
don't enable any pull up or down resistors on the pin
|
||||
|
||||
.. data:: Pin.PULL_UP
|
||||
|
||||
enable the pull-up resistor on the pin
|
||||
|
||||
|
||||
class PinAF -- Pin Alternate Functions
|
||||
======================================
|
||||
|
||||
A Pin represents a physical pin on the microcprocessor. Each pin
|
||||
can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF
|
||||
object represents a particular function for a pin.
|
||||
|
||||
Usage Model::
|
||||
|
||||
x3 = pyb.Pin.board.X3
|
||||
x3_af = x3.af_list()
|
||||
|
||||
x3_af will now contain an array of PinAF objects which are availble on
|
||||
pin X3.
|
||||
|
||||
For the pyboard, x3_af would contain:
|
||||
[Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2]
|
||||
|
||||
Normally, each peripheral would configure the af automatically, but sometimes
|
||||
the same function is available on multiple pins, and having more control
|
||||
is desired.
|
||||
|
||||
To configure X3 to expose TIM2_CH3, you could use::
|
||||
|
||||
pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2)
|
||||
|
||||
or::
|
||||
|
||||
pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=1)
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: pinaf.__str__()
|
||||
|
||||
Return a string describing the alternate function.
|
||||
|
||||
.. method:: pinaf.index()
|
||||
|
||||
Return the alternate function index.
|
||||
|
||||
.. method:: pinaf.name()
|
||||
|
||||
Return the name of the alternate function.
|
||||
|
||||
.. method:: pinaf.reg()
|
||||
|
||||
Return the base register associated with the peripheral assigned to this
|
||||
alternate function. For example, if the alternate function were TIM2_CH3
|
||||
this would return stm.TIM2
|
||||
48
docs/library/pyb.RTC.rst
Normal file
@@ -0,0 +1,48 @@
|
||||
class RTC -- real time clock
|
||||
============================
|
||||
|
||||
The RTC is and independent clock that keeps track of the date
|
||||
and time.
|
||||
|
||||
Example usage::
|
||||
|
||||
rtc = pyb.RTC()
|
||||
rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0))
|
||||
print(rtc.datetime())
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.RTC()
|
||||
|
||||
Create an RTC object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: rtc.datetime([datetimetuple])
|
||||
|
||||
Get or set the date and time of the RTC.
|
||||
|
||||
With no arguments, this method returns an 8-tuple with the current
|
||||
date and time. With 1 argument (being an 8-tuple) it sets the date
|
||||
and time.
|
||||
|
||||
The 8-tuple has the following format:
|
||||
|
||||
(year, month, day, weekday, hours, minutes, seconds, subseconds)
|
||||
|
||||
``weekday`` is 1-7 for Monday through Sunday.
|
||||
|
||||
``subseconds`` counts down from 255 to 0
|
||||
|
||||
.. method:: rtc.info()
|
||||
|
||||
Get information about the startup time and reset source.
|
||||
|
||||
- The lower 0xffff are the number of milliseconds the RTC took to
|
||||
start up.
|
||||
- Bit 0x10000 is set if a power-on reset occurred.
|
||||
- Bit 0x20000 is set if an external reset occurred
|
||||
106
docs/library/pyb.SPI.rst
Normal file
@@ -0,0 +1,106 @@
|
||||
.. _pyb.SPI:
|
||||
|
||||
class SPI -- a master-driven serial protocol
|
||||
============================================
|
||||
|
||||
SPI is a serial protocol that is driven by a master. At the physical level
|
||||
there are 3 lines: SCK, MOSI, MISO.
|
||||
|
||||
See usage model of I2C; SPI is very similar. Main difference is
|
||||
parameters to init the SPI bus::
|
||||
|
||||
from pyb import SPI
|
||||
spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=0, crc=0x7)
|
||||
|
||||
Only required parameter is mode, SPI.MASTER or SPI.SLAVE. Polarity can be
|
||||
0 or 1, and is the level the idle clock line sits at. Phase can be 0 or 1
|
||||
to sample data on the first or second clock edge respectively. Crc can be
|
||||
None for no CRC, or a polynomial specifier.
|
||||
|
||||
Additional method for SPI::
|
||||
|
||||
data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes
|
||||
buf = bytearray(4)
|
||||
spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf
|
||||
spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.SPI(bus, ...)
|
||||
|
||||
Construct an SPI object on the given bus. ``bus`` can be 1 or 2.
|
||||
With no additional parameters, the SPI object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
The physical pins of the SPI busses are:
|
||||
|
||||
- ``SPI(1)`` is on the X position: ``(NSS, SCK, MISO, MOSI) = (X5, X6, X7, X8) = (PA4, PA5, PA6, PA7)``
|
||||
- ``SPI(2)`` is on the Y position: ``(NSS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8) = (PB12, PB13, PB14, PB15)``
|
||||
|
||||
At the moment, the NSS pin is not used by the SPI driver and is free
|
||||
for other use.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: spi.deinit()
|
||||
|
||||
Turn off the SPI bus.
|
||||
|
||||
.. method:: spi.init(mode, baudrate=328125, \*, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
|
||||
|
||||
Initialise the SPI bus with the given parameters:
|
||||
|
||||
- ``mode`` must be either ``SPI.MASTER`` or ``SPI.SLAVE``.
|
||||
- ``baudrate`` is the SCK clock rate (only sensible for a master).
|
||||
|
||||
.. method:: spi.recv(recv, \*, timeout=5000)
|
||||
|
||||
Receive data on the bus:
|
||||
|
||||
- ``recv`` can be an integer, which is the number of bytes to receive,
|
||||
or a mutable buffer, which will be filled with received bytes.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive.
|
||||
|
||||
Return value: if ``recv`` is an integer then a new buffer of the bytes received,
|
||||
otherwise the same buffer that was passed in to ``recv``.
|
||||
|
||||
.. method:: spi.send(send, \*, timeout=5000)
|
||||
|
||||
Send data on the bus:
|
||||
|
||||
- ``send`` is the data to send (an integer to send, or a buffer object).
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the send.
|
||||
|
||||
Return value: ``None``.
|
||||
|
||||
.. method:: spi.send_recv(send, recv=None, \*, timeout=5000)
|
||||
|
||||
Send and receive data on the bus at the same time:
|
||||
|
||||
- ``send`` is the data to send (an integer to send, or a buffer object).
|
||||
- ``recv`` is a mutable buffer which will be filled with received bytes.
|
||||
It can be the same as ``send``, or omitted. If omitted, a new buffer will
|
||||
be created.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive.
|
||||
|
||||
Return value: the buffer with the received bytes.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: SPI.MASTER
|
||||
.. data:: SPI.SLAVE
|
||||
|
||||
for initialising the SPI bus to master or slave mode
|
||||
|
||||
.. data:: SPI.LSB
|
||||
.. data:: SPI.MSB
|
||||
|
||||
set the first bit to be the least or most significant bit
|
||||
38
docs/library/pyb.Servo.rst
Normal file
@@ -0,0 +1,38 @@
|
||||
class Servo -- 3-wire hobby servo driver
|
||||
========================================
|
||||
|
||||
Servo controls standard hobby servos with 3-wires (ground, power, signal).
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.Servo(id)
|
||||
|
||||
Create a servo object. ``id`` is 1-4.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: servo.angle([angle, time=0])
|
||||
|
||||
Get or set the angle of the servo.
|
||||
|
||||
- ``angle`` is the angle to move to in degrees.
|
||||
- ``time`` is the number of milliseconds to take to get to the specified angle.
|
||||
|
||||
.. method:: servo.calibration([pulse_min, pulse_max, pulse_centre, [pulse_angle_90, pulse_speed_100]])
|
||||
|
||||
Get or set the calibration of the servo timing.
|
||||
|
||||
.. method:: servo.pulse_width([value])
|
||||
|
||||
Get or set the pulse width in milliseconds.
|
||||
|
||||
.. method:: servo.speed([speed, time=0])
|
||||
|
||||
Get or set the speed of a continuous rotation servo.
|
||||
|
||||
- ``speed`` is the speed to move to change to, between -100 and 100.
|
||||
- ``time`` is the number of milliseconds to take to get to the specified speed.
|
||||
37
docs/library/pyb.Switch.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
class Switch -- switch object
|
||||
=============================
|
||||
|
||||
A Switch object is used to control a push-button switch.
|
||||
|
||||
Usage::
|
||||
|
||||
sw = pyb.Switch() # create a switch object
|
||||
sw() # get state (True if pressed, False otherwise)
|
||||
sw.callback(f) # register a callback to be called when the
|
||||
# switch is pressed down
|
||||
sw.callback(None) # remove the callback
|
||||
|
||||
Example::
|
||||
|
||||
pyb.Switch().callback(lambda: pyb.LED(1).toggle())
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.Switch()
|
||||
|
||||
Create and return a switch object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: switch()
|
||||
|
||||
Return the switch state: ``True`` if pressed down, ``False`` otherwise.
|
||||
|
||||
.. method:: switch.callback(fun)
|
||||
|
||||
Register the given function to be called when the switch is pressed down.
|
||||
If ``fun`` is ``None``, then it disables the callback.
|
||||
234
docs/library/pyb.Timer.rst
Normal file
@@ -0,0 +1,234 @@
|
||||
.. _pyb.Timer:
|
||||
|
||||
class Timer -- control internal timers
|
||||
======================================
|
||||
|
||||
Timers can be used for a great variety of tasks. At the moment, only
|
||||
the simplest case is implemented: that of calling a function periodically.
|
||||
|
||||
Each timer consists of a counter that counts up at a certain rate. The rate
|
||||
at which it counts is the peripheral clock frequency (in Hz) divided by the
|
||||
timer prescaler. When the counter reaches the timer period it triggers an
|
||||
event, and the counter resets back to zero. By using the callback method,
|
||||
the timer event can call a Python function.
|
||||
|
||||
Example usage to toggle an LED at a fixed frequency::
|
||||
|
||||
tim = pyb.Timer(4) # create a timer object using timer 4
|
||||
tim.init(freq=2) # trigger at 2Hz
|
||||
tim.callback(lambda t:pyb.LED(1).toggle())
|
||||
|
||||
Further examples::
|
||||
|
||||
tim = pyb.Timer(4, freq=100) # freq in Hz
|
||||
tim = pyb.Timer(4, prescaler=0, period=99)
|
||||
tim.counter() # get counter (can also set)
|
||||
tim.prescaler(2) # set prescaler (can also get)
|
||||
tim.period(199) # set period (can also get)
|
||||
tim.callback(lambda t: ...) # set callback for update interrupt (t=tim instance)
|
||||
tim.callback(None) # clear callback
|
||||
|
||||
*Note:* Timer 3 is reserved for internal use. Timer 5 controls
|
||||
the servo driver, and Timer 6 is used for timed ADC/DAC reading/writing.
|
||||
It is recommended to use the other timers in your programs.
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.Timer(id, ...)
|
||||
|
||||
Construct a new timer object of the given id. If additional
|
||||
arguments are given, then the timer is initialised by ``init(...)``.
|
||||
``id`` can be 1 to 14, excluding 3.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: timer.callback(fun)
|
||||
|
||||
Set the function to be called when the timer triggers.
|
||||
``fun`` is passed 1 argument, the timer object.
|
||||
If ``fun`` is ``None`` then the callback will be disabled.
|
||||
|
||||
.. method:: timer.channel(channel, mode, ...)
|
||||
|
||||
If only a channel number is passed, then a previously initialized channel
|
||||
object is returned (or ``None`` if there is no previous channel).
|
||||
|
||||
Othwerwise, a TimerChannel object is initialized and returned.
|
||||
|
||||
Each channel can be configured to perform pwm, output compare, or
|
||||
input capture. All channels share the same underlying timer, which means
|
||||
that they share the same timer clock.
|
||||
|
||||
Keyword arguments:
|
||||
|
||||
- ``mode`` can be one of:
|
||||
|
||||
- ``Timer.PWM`` --- configure the timer in PWM mode (active high).
|
||||
- ``Timer.PWM_INVERTED`` --- configure the timer in PWM mode (active low).
|
||||
- ``Timer.OC_TIMING`` --- indicates that no pin is driven.
|
||||
- ``Timer.OC_ACTIVE`` --- the pin will be made active when a compare match occurs (active is determined by polarity)
|
||||
- ``Timer.OC_INACTIVE`` --- the pin will be made inactive when a compare match occurs.
|
||||
- ``Timer.OC_TOGGLE`` --- the pin will be toggled when an compare match occurs.
|
||||
- ``Timer.OC_FORCED_ACTIVE`` --- the pin is forced active (compare match is ignored).
|
||||
- ``Timer.OC_FORCED_INACTIVE`` --- the pin is forced inactive (compare match is ignored).
|
||||
- ``Timer.IC`` --- configure the timer in Input Capture mode.
|
||||
|
||||
- ``callback`` - as per TimerChannel.callback()
|
||||
|
||||
- ``pin`` None (the default) or a Pin object. If specified (and not None)
|
||||
this will cause the alternate function of the the indicated pin
|
||||
to be configured for this timer channel. An error will be raised if
|
||||
the pin doesn't support any alternate functions for this timer channel.
|
||||
|
||||
Keyword arguments for Timer.PWM modes:
|
||||
|
||||
- ``pulse_width`` - determines the initial pulse width value to use.
|
||||
- ``pulse_width_percent`` - determines the initial pulse width percentage to use.
|
||||
|
||||
Keyword arguments for Timer.OC modes:
|
||||
|
||||
- ``compare`` - determines the initial value of the compare register.
|
||||
|
||||
- ``polarity`` can be one of:
|
||||
- ``Timer.HIGH`` - output is active high
|
||||
- ``Timer.LOW`` - output is acive low
|
||||
|
||||
Optional keyword arguments for Timer.IC modes:
|
||||
|
||||
- ``polarity`` can be one of:
|
||||
- ``Timer.RISING`` - captures on rising edge.
|
||||
- ``Timer.FALLING`` - captures on falling edge.
|
||||
- ``Timer.BOTH`` - captures on both edges.
|
||||
|
||||
Note that capture only works on the primary channel, and not on the
|
||||
complimentary channels.
|
||||
|
||||
PWM Example::
|
||||
|
||||
timer = pyb.Timer(2, freq=1000)
|
||||
ch2 = timer.channel(2, pyb.Timer.PWM, pin=pyb.Pin.board.X2, pulse_width=210000)
|
||||
ch3 = timer.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.X3, pulse_width=420000)
|
||||
|
||||
.. method:: timer.counter([value])
|
||||
|
||||
Get or set the timer counter.
|
||||
|
||||
.. method:: timer.deinit()
|
||||
|
||||
Deinitialises the timer.
|
||||
|
||||
Disables the callback (and the associated irq).
|
||||
Disables any channel callbacks (and the associated irq).
|
||||
Stops the timer, and disables the timer peripheral.
|
||||
|
||||
.. method:: timer.freq([value])
|
||||
|
||||
Get or set the frequency for the timer (changes prescaler and period if set).
|
||||
|
||||
.. method:: timer.init(\*, freq, prescaler, period)
|
||||
|
||||
Initialise the timer. Initialisation must be either by frequency (in Hz)
|
||||
or by prescaler and period::
|
||||
|
||||
tim.init(freq=100) # set the timer to trigger at 100Hz
|
||||
tim.init(prescaler=83, period=999) # set the prescaler and period directly
|
||||
|
||||
Keyword arguments:
|
||||
|
||||
- ``freq`` --- specifies the periodic frequency of the timer. You migh also
|
||||
view this as the frequency with which the timer goes through one complete cycle.
|
||||
|
||||
- ``prescaler`` [0-0xffff] - specifies the value to be loaded into the
|
||||
timer's Prescaler Register (PSC). The timer clock source is divided by
|
||||
(``prescaler + 1``) to arrive at the timer clock. Timers 2-7 and 12-14
|
||||
have a clock source of 84 MHz (pyb.freq()[2] \* 2), and Timers 1, and 8-11
|
||||
have a clock source of 168 MHz (pyb.freq()[3] \* 2).
|
||||
|
||||
- ``period`` [0-0xffff] for timers 1, 3, 4, and 6-15. [0-0x3fffffff] for timers 2 & 5.
|
||||
Specifies the value to be loaded into the timer's AutoReload
|
||||
Register (ARR). This determines the period of the timer (i.e. when the
|
||||
counter cycles). The timer counter will roll-over after ``period + 1``
|
||||
timer clock cycles.
|
||||
|
||||
- ``mode`` can be one of:
|
||||
|
||||
- ``Timer.UP`` - configures the timer to count from 0 to ARR (default)
|
||||
- ``Timer.DOWN`` - configures the timer to count from ARR down to 0.
|
||||
- ``Timer.CENTER`` - confgures the timer to count from 0 to ARR and
|
||||
then back down to 0.
|
||||
|
||||
- ``div`` can be one of 1, 2, or 4. Divides the timer clock to determine
|
||||
the sampling clock used by the digital filters.
|
||||
|
||||
- ``callback`` - as per Timer.callback()
|
||||
|
||||
- ``deadtime`` - specifies the amount of "dead" or inactive time between
|
||||
transitions on complimentary channels (both channels will be inactive)
|
||||
for this time). ``deadtime`` may be an integer between 0 and 1008, with
|
||||
the following restrictions: 0-128 in steps of 1. 128-256 in steps of
|
||||
2, 256-512 in steps of 8, and 512-1008 in steps of 16. ``deadime``
|
||||
measures ticks of ``source_freq`` divided by ``div`` clock ticks.
|
||||
``deadtime`` is only available on timers 1 and 8.
|
||||
|
||||
You must either specify freq or both of period and prescaler.
|
||||
|
||||
.. method:: timer.period([value])
|
||||
|
||||
Get or set the period of the timer.
|
||||
|
||||
.. method:: timer.prescaler([value])
|
||||
|
||||
Get or set the prescaler for the timer.
|
||||
|
||||
.. method:: timer.source_freq()
|
||||
|
||||
Get the frequency of the source of the timer.
|
||||
|
||||
class TimerChannel --- setup a channel for a timer
|
||||
==================================================
|
||||
|
||||
Timer channels are used to generate/capture a signal using a timer.
|
||||
|
||||
TimerChannel objects are created using the Timer.channel() method.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: timerchannel.callback(fun)
|
||||
|
||||
Set the function to be called when the timer channel triggers.
|
||||
``fun`` is passed 1 argument, the timer object.
|
||||
If ``fun`` is ``None`` then the callback will be disabled.
|
||||
|
||||
.. method:: timerchannel.capture([value])
|
||||
|
||||
Get or set the capture value associated with a channel.
|
||||
capture, compare, and pulse_width are all aliases for the same function.
|
||||
capture is the logical name to use when the channel is in input capture mode.
|
||||
|
||||
.. method:: timerchannel.compare([value])
|
||||
|
||||
Get or set the compare value associated with a channel.
|
||||
capture, compare, and pulse_width are all aliases for the same function.
|
||||
compare is the logical name to use when the channel is in output compare mode.
|
||||
|
||||
.. method:: timerchannel.pulse_width([value])
|
||||
|
||||
Get or set the pulse width value associated with a channel.
|
||||
capture, compare, and pulse_width are all aliases for the same function.
|
||||
pulse_width is the logical name to use when the channel is in PWM mode.
|
||||
|
||||
In edge aligned mode, a pulse_width of ``period + 1`` corresponds to a duty cycle of 100%
|
||||
In center aligned mode, a pulse width of ``period`` corresponds to a duty cycle of 100%
|
||||
|
||||
.. method:: timerchannel.pulse_width_percent([value])
|
||||
|
||||
Get or set the pulse width percentage associated with a channel. The value
|
||||
is a number between 0 and 100 and sets the percentage of the timer period
|
||||
for which the pulse is active. The value can be an integer or
|
||||
floating-point number for more accuracy. For example, a value of 25 gives
|
||||
a duty cycle of 25%.
|
||||
136
docs/library/pyb.UART.rst
Normal file
@@ -0,0 +1,136 @@
|
||||
.. _pyb.UART:
|
||||
|
||||
class UART -- duplex serial communication bus
|
||||
=============================================
|
||||
|
||||
UART implements the standard UART/USART duplex serial communications protocol. At
|
||||
the physical level it consists of 2 lines: RX and TX. The unit of communication
|
||||
is a character (not to be confused with a string character) which can be 8 or 9
|
||||
bits wide.
|
||||
|
||||
UART objects can be created and initialised using::
|
||||
|
||||
from pyb import UART
|
||||
|
||||
uart = UART(1, 9600) # init with given baudrate
|
||||
uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters
|
||||
|
||||
Bits can be 7, 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2.
|
||||
|
||||
*Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled,
|
||||
only 7 and 8 bits are supported.
|
||||
|
||||
A UART object acts like a stream object and reading and writing is done
|
||||
using the standard stream methods::
|
||||
|
||||
uart.read(10) # read 10 characters, returns a bytes object
|
||||
uart.readall() # read all available characters
|
||||
uart.readline() # read a line
|
||||
uart.readinto(buf) # read and store into the given buffer
|
||||
uart.write('abc') # write the 3 characters
|
||||
|
||||
Individual characters can be read/written using::
|
||||
|
||||
uart.readchar() # read 1 character and returns it as an integer
|
||||
uart.writechar(42) # write 1 character
|
||||
|
||||
To check if there is anything to be read, use::
|
||||
|
||||
uart.any() # returns True if any characters waiting
|
||||
|
||||
*Note:* The stream functions ``read``, ``write`` etc Are new in Micro Python since v1.3.4.
|
||||
Earlier versions use ``uart.send`` and ``uart.recv``.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.UART(bus, ...)
|
||||
|
||||
Construct a UART object on the given bus. ``bus`` can be 1-6, or 'XA', 'XB', 'YA', or 'YB'.
|
||||
With no additional parameters, the UART object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
The physical pins of the UART busses are:
|
||||
|
||||
- ``UART(4)`` is on ``XA``: ``(TX, RX) = (X1, X2) = (PA0, PA1)``
|
||||
- ``UART(1)`` is on ``XB``: ``(TX, RX) = (X9, X10) = (PB6, PB7)``
|
||||
- ``UART(6)`` is on ``YA``: ``(TX, RX) = (Y1, Y2) = (PC6, PC7)``
|
||||
- ``UART(3)`` is on ``YB``: ``(TX, RX) = (Y9, Y10) = (PB10, PB11)``
|
||||
- ``UART(2)`` is on: ``(TX, RX) = (X3, X4) = (PA2, PA3)``
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: uart.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=1000, timeout_char=0, read_buf_len=64)
|
||||
|
||||
Initialise the UART bus with the given parameters:
|
||||
|
||||
- ``baudrate`` is the clock rate.
|
||||
- ``bits`` is the number of bits per character, 7, 8 or 9.
|
||||
- ``parity`` is the parity, ``None``, 0 (even) or 1 (odd).
|
||||
- ``stop`` is the number of stop bits, 1 or 2.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the first character.
|
||||
- ``timeout_char`` is the timeout in milliseconds to wait between characters.
|
||||
- ``read_buf_len`` is the character length of the read buffer (0 to disable).
|
||||
|
||||
*Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled,
|
||||
only 7 and 8 bits are supported.
|
||||
|
||||
.. method:: uart.deinit()
|
||||
|
||||
Turn off the UART bus.
|
||||
|
||||
.. method:: uart.any()
|
||||
|
||||
Return ``True`` if any characters waiting, else ``False``.
|
||||
|
||||
.. method:: uart.read([nbytes])
|
||||
|
||||
Read characters. If ``nbytes`` is specified then read at most that many bytes.
|
||||
|
||||
*Note:* for 9 bit characters each character takes two bytes, ``nbytes`` must
|
||||
be even, and the number of characters is ``nbytes/2``.
|
||||
|
||||
Return value: a bytes object containing the bytes read in. Returns ``b''``
|
||||
on timeout.
|
||||
|
||||
.. method:: uart.readall()
|
||||
|
||||
Read as much data as possible.
|
||||
|
||||
Return value: a bytes object.
|
||||
|
||||
.. method:: uart.readchar()
|
||||
|
||||
Receive a single character on the bus.
|
||||
|
||||
Return value: The character read, as an integer. Returns -1 on timeout.
|
||||
|
||||
.. method:: uart.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.
|
||||
|
||||
Return value: number of bytes read and stored into ``buf``.
|
||||
|
||||
.. method:: uart.readline()
|
||||
|
||||
Read a line, ending in a newline character.
|
||||
|
||||
Return value: the line read.
|
||||
|
||||
.. method:: uart.write(buf)
|
||||
|
||||
Write the buffer of bytes to the bus. If characters are 7 or 8 bits wide
|
||||
then each byte is one character. If characters are 9 bits wide then two
|
||||
bytes are used for each character (little endian), and ``buf`` must contain
|
||||
an even number of bytes.
|
||||
|
||||
Return value: number of bytes written.
|
||||
|
||||
.. method:: uart.writechar(char)
|
||||
|
||||
Write a single character on the bus. ``char`` is an integer to write.
|
||||
Return value: ``None``.
|
||||
57
docs/library/pyb.USB_VCP.rst
Normal file
@@ -0,0 +1,57 @@
|
||||
class USB_VCP -- USB virtual comm port
|
||||
======================================
|
||||
|
||||
The USB_VCP class allows creation of an object representing the USB
|
||||
virtual comm port. It can be used to read and write data over USB to
|
||||
the connected host.
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.USB_VCP()
|
||||
|
||||
Create a new USB_VCP object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: usb_vcp.any()
|
||||
|
||||
Return ``True`` if any characters waiting, else ``False``.
|
||||
|
||||
.. method:: usb_vcp.close()
|
||||
|
||||
|
||||
.. method:: usb_vcp.read([nbytes])
|
||||
|
||||
|
||||
.. method:: usb_vcp.readall()
|
||||
|
||||
|
||||
.. method:: usb_vcp.readline()
|
||||
|
||||
|
||||
.. method:: usb_vcp.recv(data, \*, timeout=5000)
|
||||
|
||||
Receive data on the bus:
|
||||
|
||||
- ``data`` can be an integer, which is the number of bytes to receive,
|
||||
or a mutable buffer, which will be filled with received bytes.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive.
|
||||
|
||||
Return value: if ``data`` is an integer then a new buffer of the bytes received,
|
||||
otherwise the number of bytes read into ``data`` is returned.
|
||||
|
||||
.. method:: usb_vcp.send(data, \*, timeout=5000)
|
||||
|
||||
Send data over the USB VCP:
|
||||
|
||||
- ``data`` is the data to send (an integer to send, or a buffer object).
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the send.
|
||||
|
||||
Return value: number of bytes sent.
|
||||
|
||||
.. method:: usb_vcp.write(buf)
|
||||
|
||||
182
docs/library/pyb.rst
Normal file
@@ -0,0 +1,182 @@
|
||||
:mod:`pyb` --- functions related to the pyboard
|
||||
===============================================
|
||||
|
||||
.. module:: pyb
|
||||
:synopsis: functions related to the pyboard
|
||||
|
||||
The ``pyb`` module contains specific functions related to the pyboard.
|
||||
|
||||
Time related functions
|
||||
----------------------
|
||||
|
||||
.. function:: delay(ms)
|
||||
|
||||
Delay for the given number of milliseconds.
|
||||
|
||||
.. function:: udelay(us)
|
||||
|
||||
Delay for the given number of microseconds.
|
||||
|
||||
.. function:: millis()
|
||||
|
||||
Returns the number of milliseconds since the board was last reset.
|
||||
|
||||
The result is always a micropython smallint (31-bit signed number), so
|
||||
after 2^30 milliseconds (about 12.4 days) this will start to return
|
||||
negative numbers.
|
||||
|
||||
.. function:: micros()
|
||||
|
||||
Returns the number of microseconds since the board was last reset.
|
||||
|
||||
The result is always a micropython smallint (31-bit signed number), so
|
||||
after 2^30 microseconds (about 17.8 minutes) this will start to return
|
||||
negative numbers.
|
||||
|
||||
.. function:: elapsed_millis(start)
|
||||
|
||||
Returns the number of milliseconds which have elapsed since ``start``.
|
||||
|
||||
This function takes care of counter wrap, and always returns a positive
|
||||
number. This means it can be used to measure periods upto about 12.4 days.
|
||||
|
||||
Example::
|
||||
|
||||
start = pyb.millis()
|
||||
while pyb.elapsed_millis(start) < 1000:
|
||||
# Perform some operation
|
||||
|
||||
.. function:: elapsed_micros(start)
|
||||
|
||||
Returns the number of microseconds which have elapsed since ``start``.
|
||||
|
||||
This function takes care of counter wrap, and always returns a positive
|
||||
number. This means it can be used to measure periods upto about 17.8 minutes.
|
||||
|
||||
Example::
|
||||
|
||||
start = pyb.micros()
|
||||
while pyb.elapsed_micros(start) < 1000:
|
||||
# Perform some operation
|
||||
pass
|
||||
|
||||
Reset related functions
|
||||
-----------------------
|
||||
|
||||
.. function:: hard_reset()
|
||||
|
||||
Resets the pyboard in a manner similar to pushing the external RESET
|
||||
button.
|
||||
|
||||
.. function:: bootloader()
|
||||
|
||||
Activate the bootloader without BOOT\* pins.
|
||||
|
||||
Interrupt related functions
|
||||
---------------------------
|
||||
|
||||
.. function:: disable_irq()
|
||||
|
||||
Disable interrupt requests.
|
||||
Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs
|
||||
respectively. This return value can be passed to enable_irq to restore
|
||||
the IRQ to its original state.
|
||||
|
||||
.. function:: enable_irq(state=True)
|
||||
|
||||
Enable interrupt requests.
|
||||
If ``state`` is ``True`` (the default value) then IRQs are enabled.
|
||||
If ``state`` is ``False`` then IRQs are disabled. The most common use of
|
||||
this function is to pass it the value returned by ``disable_irq`` to
|
||||
exit a critical section.
|
||||
|
||||
Power related functions
|
||||
-----------------------
|
||||
|
||||
.. function:: freq([sys_freq])
|
||||
|
||||
If given no arguments, returns a tuple of clock frequencies:
|
||||
(SYSCLK, HCLK, PCLK1, PCLK2).
|
||||
|
||||
If given an argument, sets the system frequency to that value in Hz.
|
||||
Eg freq(120000000) gives 120MHz. Note that not all values are
|
||||
supported and the largest supported frequency not greater than
|
||||
the given sys_freq will be selected.
|
||||
|
||||
Supported frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48,
|
||||
54, 56, 60, 64, 72, 84, 96, 108, 120, 144, 168.
|
||||
|
||||
8MHz uses the HSE (external crystal) directly and 16MHz uses the HSI
|
||||
(internal oscillator) directly. The higher frequencies use the HSE to
|
||||
drive the PLL (phase locked loop), and then use the output of the PLL.
|
||||
|
||||
Note that if you change the frequency while the USB is enabled then
|
||||
the USB may become unreliable. It is best to change the frequency
|
||||
in boot.py, before the USB peripheral is started. Also note that
|
||||
frequencies below 36MHz do not allow the USB to function correctly.
|
||||
|
||||
.. function:: wfi()
|
||||
|
||||
Wait for an interrupt.
|
||||
This executies a ``wfi`` instruction which reduces power consumption
|
||||
of the MCU until an interrupt occurs, at which point execution continues.
|
||||
|
||||
.. function:: standby()
|
||||
|
||||
|
||||
.. function:: stop()
|
||||
|
||||
Miscellaneous functions
|
||||
-----------------------
|
||||
|
||||
.. function:: have_cdc()
|
||||
|
||||
Return True if USB is connected as a serial device, False otherwise.
|
||||
|
||||
.. function:: hid((buttons, x, y, z))
|
||||
|
||||
Takes a 4-tuple (or list) and sends it to the USB host (the PC) to
|
||||
signal a HID mouse-motion event.
|
||||
|
||||
.. function:: info([dump_alloc_table])
|
||||
|
||||
Print out lots of information about the board.
|
||||
|
||||
.. function:: repl_uart(uart)
|
||||
|
||||
Get or set the UART object that the REPL is repeated on.
|
||||
|
||||
.. function:: rng()
|
||||
|
||||
Return a 30-bit hardware generated random number.
|
||||
|
||||
.. function:: sync()
|
||||
|
||||
Sync all file systems.
|
||||
|
||||
.. function:: unique_id()
|
||||
|
||||
Returns a string of 12 bytes (96 bits), which is the unique ID for the MCU.
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
pyb.Accel.rst
|
||||
pyb.ADC.rst
|
||||
pyb.CAN.rst
|
||||
pyb.DAC.rst
|
||||
pyb.ExtInt.rst
|
||||
pyb.I2C.rst
|
||||
pyb.LCD.rst
|
||||
pyb.LED.rst
|
||||
pyb.Pin.rst
|
||||
pyb.RTC.rst
|
||||
pyb.Servo.rst
|
||||
pyb.SPI.rst
|
||||
pyb.Switch.rst
|
||||
pyb.Timer.rst
|
||||
pyb.UART.rst
|
||||
pyb.USB_VCP.rst
|
||||
52
docs/library/select.rst
Normal file
@@ -0,0 +1,52 @@
|
||||
:mod:`select` -- Provides select function to wait for events on a stream
|
||||
========================================================================
|
||||
|
||||
.. module:: select
|
||||
:synopsis: Provides select function to wait for events on a stream
|
||||
|
||||
This module provides the select function.
|
||||
|
||||
Pyboard specifics
|
||||
-----------------
|
||||
|
||||
Polling is an efficient way of waiting for read/write activity on multiple
|
||||
objects. Current objects that support polling are: :class:`pyb.UART`,
|
||||
:class:`pyb.USB_VCP`.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: poll()
|
||||
|
||||
Create an instance of the Poll class.
|
||||
|
||||
.. function:: select(rlist, wlist, xlist[, timeout])
|
||||
|
||||
Wait for activity on a set of objects.
|
||||
|
||||
.. _class: Poll
|
||||
|
||||
class ``Poll``
|
||||
--------------
|
||||
|
||||
Methods
|
||||
~~~~~~~
|
||||
|
||||
.. method:: poll.register(obj[, eventmask])
|
||||
|
||||
Register ``obj`` for polling. ``eventmask`` is 1 for read, 2 for
|
||||
write, 3 for read-write.
|
||||
|
||||
.. method:: poll.unregister(obj)
|
||||
|
||||
Unregister ``obj`` from polling.
|
||||
|
||||
.. method:: poll.modify(obj, eventmask)
|
||||
|
||||
Modify the ``eventmask`` for ``obj``.
|
||||
|
||||
.. method:: poll.poll([timeout])
|
||||
|
||||
Wait for one of the registered objects to become ready.
|
||||
|
||||
Timeout is in milliseconds.
|
||||
25
docs/library/struct.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
:mod:`struct` -- pack and unpack primitive data types
|
||||
=====================================================
|
||||
|
||||
.. module:: struct
|
||||
:synopsis: pack and unpack primitive data types
|
||||
|
||||
See `Python struct <https://docs.python.org/3/library/struct.html>`_ for more
|
||||
information.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: calcsize(fmt)
|
||||
|
||||
Return the number of bytes needed to store the given ``fmt``.
|
||||
|
||||
.. function:: pack(fmt, v1, v2, ...)
|
||||
|
||||
Pack the values ``v1``, ``v2``, ... according to the format string ``fmt``.
|
||||
The return value is a bytes object encoding the values.
|
||||
|
||||
.. function:: unpack(fmt, data)
|
||||
|
||||
Unpack from the ``data`` according to the format string ``fmt``.
|
||||
The return value is a tuple of the unpacked values.
|
||||
52
docs/library/sys.rst
Normal file
@@ -0,0 +1,52 @@
|
||||
:mod:`sys` -- system specific functions
|
||||
=======================================
|
||||
|
||||
.. module:: sys
|
||||
:synopsis: system specific functions
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: exit([retval])
|
||||
|
||||
Raise a ``SystemExit`` exception. If an argument is given, it is the
|
||||
value given to ``SystemExit``.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: argv
|
||||
|
||||
a mutable list of arguments this program started with
|
||||
|
||||
.. data:: byteorder
|
||||
|
||||
the byte order of the system ("little" or "big")
|
||||
|
||||
.. data:: path
|
||||
|
||||
a mutable list of directories to search for imported modules
|
||||
|
||||
.. data:: platform
|
||||
|
||||
the platform that Micro Python is running on
|
||||
|
||||
.. data:: stderr
|
||||
|
||||
standard error (connected to USB VCP, and optional UART object)
|
||||
|
||||
.. data:: stdin
|
||||
|
||||
standard input (connected to USB VCP, and optional UART object)
|
||||
|
||||
.. data:: stdout
|
||||
|
||||
standard output (connected to USB VCP, and optional UART object)
|
||||
|
||||
.. data:: version
|
||||
|
||||
Python language version that this implementation conforms to, as a string
|
||||
|
||||
.. data:: version_info
|
||||
|
||||
Python language version that this implementation conforms to, as a tuple of ints
|
||||
41
docs/library/time.rst
Normal file
@@ -0,0 +1,41 @@
|
||||
:mod:`time` -- time related functions
|
||||
=====================================
|
||||
|
||||
.. module:: time
|
||||
:synopsis: time related functions
|
||||
|
||||
The ``time`` module provides functions for getting the current time and date,
|
||||
and for sleeping.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: localtime([secs])
|
||||
|
||||
Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
|
||||
contains: (year, month, mday, hour, minute, second, weekday, yearday)
|
||||
If secs is not provided or None, then the current time from the RTC is used.
|
||||
year includes the century (for example 2014).
|
||||
|
||||
* month is 1-12
|
||||
* mday is 1-31
|
||||
* hour is 0-23
|
||||
* minute is 0-59
|
||||
* second is 0-59
|
||||
* weekday is 0-6 for Mon-Sun
|
||||
* yearday is 1-366
|
||||
|
||||
.. function:: mktime()
|
||||
|
||||
This is inverse function of localtime. It's argument is a full 8-tuple
|
||||
which expresses a time as per localtime. It returns an integer which is
|
||||
the number of seconds since Jan 1, 2000.
|
||||
|
||||
.. function:: sleep(seconds)
|
||||
|
||||
Sleep for the given number of seconds. Seconds can be a floating-point number to
|
||||
sleep for a fractional number of seconds.
|
||||
|
||||
.. function:: time()
|
||||
|
||||
Returns the number of seconds, as an integer, since 1/1/2000.
|
||||
25
docs/library/uheapq.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
:mod:`uheapq` -- heap queue algorithm
|
||||
=====================================
|
||||
|
||||
.. module:: uheapq
|
||||
:synopsis: heap queue algorithm
|
||||
|
||||
This module implements the heap queue algorithm.
|
||||
|
||||
A heap queue is simply a list that has its elements stored in a certain way.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: heappush(heap, item)
|
||||
|
||||
Push the ``item`` onto the ``heap``.
|
||||
|
||||
.. function:: heappop(heap)
|
||||
|
||||
Pop the first item froh the ``heap``, and return it. Raises IndexError if
|
||||
heap is empty.
|
||||
|
||||
.. function:: heapify(x)
|
||||
|
||||
Convert the list ``x`` into a heap. This is an in-place operation.
|
||||
20
docs/library/ujson.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
:mod:`ujson` -- JSON encoding and decoding
|
||||
==========================================
|
||||
|
||||
.. module:: ujson
|
||||
:synopsis: JSON encoding and decoding
|
||||
|
||||
This modules allows to convert between Python objects and the JSON
|
||||
data format.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: dumps(obj)
|
||||
|
||||
Return ``obj`` represented as a JSON string.
|
||||
|
||||
.. function:: loads(str)
|
||||
|
||||
Parse the JSON ``str`` and return an object. Raises ValueError if the
|
||||
string is not correctly formed.
|
||||
17
docs/library/usocket.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
:mod:`usocket` -- socket module
|
||||
===============================
|
||||
|
||||
.. module:: usocket
|
||||
:synopsis: socket module
|
||||
|
||||
Socket functionality.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: getaddrinfo(host, port)
|
||||
|
||||
|
||||
.. function:: socket(family=AF_INET, type=SOCK_STREAM, fileno=-1)
|
||||
|
||||
Create a socket.
|
||||
24
docs/license.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
Micro Python license information
|
||||
================================
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013, 2014 Damien P. George, and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -1,13 +1,16 @@
|
||||
Quick reference for the pyboard
|
||||
=====================================
|
||||
.. _quickref:
|
||||
|
||||
.. image:: http://micropython.org/static/resources/pybv10-pinout.jpg
|
||||
:alt: AMP skin
|
||||
Quick reference for the pyboard
|
||||
===============================
|
||||
|
||||
.. image:: http://micropython.org/resources/pybv10-pinout.jpg
|
||||
:alt: PYBv1.0 pinout
|
||||
:width: 700px
|
||||
|
||||
General board control
|
||||
---------------------
|
||||
::
|
||||
|
||||
See :mod:`pyb`. ::
|
||||
|
||||
import pyb
|
||||
|
||||
@@ -21,7 +24,8 @@ General board control
|
||||
|
||||
LEDs
|
||||
----
|
||||
::
|
||||
|
||||
See :ref:`pyb.LED <pyb.LED>`. ::
|
||||
|
||||
from pyb import LED
|
||||
|
||||
@@ -32,7 +36,8 @@ LEDs
|
||||
|
||||
Pins and GPIO
|
||||
-------------
|
||||
::
|
||||
|
||||
See :ref:`pyb.Pin <pyb.Pin>`. ::
|
||||
|
||||
from pyb import Pin
|
||||
|
||||
@@ -45,7 +50,8 @@ Pins and GPIO
|
||||
|
||||
External interrupts
|
||||
-------------------
|
||||
::
|
||||
|
||||
See :ref:`pyb.ExtInt <pyb.ExtInt>`. ::
|
||||
|
||||
from pyb import Pin, ExtInt
|
||||
|
||||
@@ -54,7 +60,8 @@ External interrupts
|
||||
|
||||
Timers
|
||||
------
|
||||
::
|
||||
|
||||
See :ref:`pyb.Timer <pyb.Timer>`. ::
|
||||
|
||||
from pyb import Timer
|
||||
|
||||
@@ -65,7 +72,8 @@ Timers
|
||||
|
||||
PWM (pulse width modulation)
|
||||
----------------------------
|
||||
::
|
||||
|
||||
See :ref:`pyb.Pin <pyb.Pin>` and :ref:`pyb.Timer <pyb.Timer>`. ::
|
||||
|
||||
from pyb import Pin, Timer
|
||||
|
||||
@@ -76,7 +84,8 @@ PWM (pulse width modulation)
|
||||
|
||||
ADC (analog to digital conversion)
|
||||
----------------------------------
|
||||
::
|
||||
|
||||
See :ref:`pyb.Pin <pyb.Pin>` and :ref:`pyb.ADC <pyb.ADC>`. ::
|
||||
|
||||
from pyb import Pin, ADC
|
||||
|
||||
@@ -85,7 +94,8 @@ ADC (analog to digital conversion)
|
||||
|
||||
DAC (digital to analog conversion)
|
||||
----------------------------------
|
||||
::
|
||||
|
||||
See :ref:`pyb.Pin <pyb.Pin>` and :ref:`pyb.DAC <pyb.DAC>`. ::
|
||||
|
||||
from pyb import Pin, DAC
|
||||
|
||||
@@ -94,7 +104,8 @@ DAC (digital to analog conversion)
|
||||
|
||||
UART (serial bus)
|
||||
-----------------
|
||||
::
|
||||
|
||||
See :ref:`pyb.UART <pyb.UART>`. ::
|
||||
|
||||
from pyb import UART
|
||||
|
||||
@@ -104,7 +115,8 @@ UART (serial bus)
|
||||
|
||||
SPI bus
|
||||
-------
|
||||
::
|
||||
|
||||
See :ref:`pyb.SPI <pyb.SPI>`. ::
|
||||
|
||||
from pyb import SPI
|
||||
|
||||
@@ -115,7 +127,8 @@ SPI bus
|
||||
|
||||
I2C bus
|
||||
-------
|
||||
::
|
||||
|
||||
See :ref:`pyb.I2C <pyb.I2C>`. ::
|
||||
|
||||
from pyb import I2C
|
||||
|
||||
|
||||
93
docs/topindex.html
Normal file
@@ -0,0 +1,93 @@
|
||||
{% extends "defindex.html" %}
|
||||
{% block body %}
|
||||
|
||||
<h1>Micro Python documentation</h1>
|
||||
|
||||
<p>
|
||||
{{ _('Welcome! This is the documentation for Micro Python') }}
|
||||
v{{ release|e }}{% if last_updated %}, {{ _('last updated') }} {{ last_updated|e }}{% endif %}.
|
||||
</p>
|
||||
|
||||
<p><strong>Documentation for Micro Python and the pyboard:</strong></p>
|
||||
|
||||
<table class="contentstable"><tr>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("quickref") }}">Quick reference for the pyboard</a><br/>
|
||||
<span class="linkdescr">pinout for the pyboard and snippets of useful code</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("general") }}">General information about the pyboard</a><br/>
|
||||
<span class="linkdescr">read this first for a quick overview</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("tutorial/index") }}">Tutorials and code examples</a><br/>
|
||||
<span class="linkdescr">start here</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("library/index") }}">Library Reference</a><br/>
|
||||
<span class="linkdescr">Micro Python libraries, including the <a href="{{ pathto("library/pyb") }}">pyb module</a></span>
|
||||
</p>
|
||||
</td>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("hardware/index") }}">The pyboard hardware</a><br/>
|
||||
<span class="linkdescr">schematics, dimensions and component datasheets</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="http://micropython.org/resources/Micro-Python-Windows-setup.pdf">Guide for pyboard on Windows (PDF)</a><br/>
|
||||
<span class="linkdescr">including DFU programming</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("license") }}">License</a><br/>
|
||||
<span class="linkdescr">Micro Python license information</span>
|
||||
</p>
|
||||
</td>
|
||||
</tr></table>
|
||||
|
||||
<p><strong>Indices and tables:</strong></p>
|
||||
<table class="contentstable"><tr>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("py-modindex") }}">Module index</a><br/>
|
||||
<span class="linkdescr">quick access to all modules</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("genindex") }}">Full index</a><br/>
|
||||
<span class="linkdescr">all functions, classes, constants</span>
|
||||
</p>
|
||||
</td>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("contents") }}">Table of contents</a><br/>
|
||||
<span class="linkdescr">a list of all sections and subsections</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("search") }}">Search page</a><br/>
|
||||
<span class="linkdescr">search this documentation</span>
|
||||
</p>
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
<p><strong>External links:</strong></p>
|
||||
|
||||
<table class="contentstable"><tr>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="http://micropython.org">Micro Python homepage</a><br/>
|
||||
<span class="linkdescr">the official Micro Python site</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="http://forum.micropython.org">Micro Python forum</a><br/>
|
||||
<span class="linkdescr">community discussion for all things related to Micro Python</span>
|
||||
</p>
|
||||
</td>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="https://github.com/micropython">Micro Python on GitHub</a><br/>
|
||||
<span class="linkdescr">contribute to the source code on GitHub</span>
|
||||
</p>
|
||||
</td>
|
||||
</tr></table>
|
||||
|
||||
{% endblock %}
|
||||
@@ -3,11 +3,11 @@ The AMP audio skin
|
||||
|
||||
Soldering and using the AMP audio skin.
|
||||
|
||||
.. image:: http://micropython.org/static/doc/skin-amp-1.jpg
|
||||
.. image:: img/skin_amp_1.jpg
|
||||
:alt: AMP skin
|
||||
:width: 250px
|
||||
|
||||
.. image:: http://micropython.org/static/doc/skin-amp-3.jpg
|
||||
.. image:: img/skin_amp_2.jpg
|
||||
:alt: AMP skin
|
||||
:width: 250px
|
||||
|
||||
@@ -26,6 +26,7 @@ potentiometer, which is an I2C device with address 46 on the ``IC2(1)`` bus.
|
||||
|
||||
To set the volume, define the following function::
|
||||
|
||||
import pyb
|
||||
def volume(val):
|
||||
pyb.I2C(1, pyb.I2C.MASTER).mem_write(val, 46, 0)
|
||||
|
||||
@@ -50,11 +51,11 @@ For example::
|
||||
dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR)
|
||||
|
||||
You can also play WAV files using the Python ``wave`` module. You can get
|
||||
the wave module [here](/static/doc/examples/wave.py) and you will also need
|
||||
the chunk module available [here](/static/doc/examples/chunk.py). Put these
|
||||
the wave module `here <http://micropython.org/resources/examples/wave.py>`_ and you will also need
|
||||
the chunk module available `here <http://micropython.org/resources/examples/chunk.py>`_. Put these
|
||||
on your pyboard (either on the flash or the SD card in the top-level
|
||||
directory). You will need an 8-bit WAV file to play, such as
|
||||
[this one](/static/doc/examples/test.wav). Then you can do::
|
||||
`this one <http://micropython.org/resources/examples/test.wav>`_. Then you can do::
|
||||
|
||||
>>> import wave
|
||||
>>> from pyb import DAC
|
||||
|
||||
37
docs/tutorial/debounce.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
Debouncing a pin input
|
||||
======================
|
||||
|
||||
A pin used as input from a switch or other mechanical device can have a lot
|
||||
of noise on it, rapidly changing from low to high when the switch is first
|
||||
pressed or released. This noise can be eliminated using a capacitor (a
|
||||
debouncing circuit). It can also be eliminated using a simple function that
|
||||
makes sure the value on the pin is stable.
|
||||
|
||||
The following function does just this. It gets the current value of the given
|
||||
pin, and then waits for the value to change. The new pin value must be stable
|
||||
for a continuous 20ms for it to register the change. You can adjust this time
|
||||
(to say 50ms) if you still have noise. ::
|
||||
|
||||
import pyb
|
||||
|
||||
def wait_pin_change(pin):
|
||||
# wait for pin to change value
|
||||
# it needs to be stable for a continuous 20ms
|
||||
cur_value = pin.value()
|
||||
active = 0
|
||||
while active < 20:
|
||||
if pin.value() != cur_value:
|
||||
active += 1
|
||||
else:
|
||||
active = 0
|
||||
pyb.delay(1)
|
||||
|
||||
|
||||
Use it something like this::
|
||||
|
||||
import pyb
|
||||
|
||||
pin_x1 = pyb.Pin('X1', pyb.Pin.IN, pyb.Pin.PULL_DOWN)
|
||||
while True:
|
||||
wait_pin_change(pin_x1)
|
||||
pyb.LED(4).toggle()
|
||||
89
docs/tutorial/fading_led.rst
Normal file
@@ -0,0 +1,89 @@
|
||||
Fading LEDs
|
||||
===========
|
||||
|
||||
In addition to turning LEDs on and off, it is also possible to control the brightness of an LED using `Pulse-Width Modulation (PWM) <http://en.wikipedia.org/wiki/Pulse-width_modulation>`_, a common technique for obtaining variable output from a digital pin. This allows us to fade an LED:
|
||||
|
||||
.. image:: http://upload.wikimedia.org/wikipedia/commons/a/a9/Fade.gif
|
||||
|
||||
Components
|
||||
----------
|
||||
|
||||
You will need:
|
||||
|
||||
- Standard 5 or 3 mm LED
|
||||
- 100 Ohm resistor
|
||||
- Wires
|
||||
- `Breadboard <http://en.wikipedia.org/wiki/Breadboard>`_ (optional, but makes things easier)
|
||||
|
||||
Connecting Things Up
|
||||
--------------------
|
||||
|
||||
For this tutorial, we will use the ``X1`` pin. Connect one end of the resistor to ``X1``, and the other end to the **anode** of the LED, which is the longer leg. Connect the **cathode** of the LED to ground.
|
||||
|
||||
.. image:: img/fading_leds_breadboard_fritzing.png
|
||||
|
||||
Code
|
||||
----
|
||||
By examining the :ref:`quickref`, we see that ``X1`` is connected to channel 1 of timer 5 (``TIM5 CH1``). Therefore we will first create a ``Timer`` object for timer 5, then create a ``TimerChannel`` object for channel 1::
|
||||
|
||||
from pyb import Timer
|
||||
from time import sleep
|
||||
|
||||
# timer 5 will be created with a frequency of 100 Hz
|
||||
tim = pyb.Timer(5, freq=100)
|
||||
tchannel = tim.channel(1, Timer.PWM, pin=pyb.Pin.board.X1, pulse_width=0)
|
||||
|
||||
Brightness of the LED in PWM is controlled by controlling the pulse-width, that is the amount of time the LED is on every cycle. With a timer frequency of 100 Hz, each cycle takes 0.01 second, or 10 ms.
|
||||
|
||||
To achieve the fading effect shown at the beginning of this tutorial, we want to set the pulse-width to a small value, then slowly increase the pulse-width to brighten the LED, and start over when we reach some maximum brightness::
|
||||
|
||||
# maximum and minimum pulse-width, which corresponds to maximum
|
||||
# and minimum brightness
|
||||
max_width = 200000
|
||||
min_width = 20000
|
||||
|
||||
# how much to change the pulse-width by each step
|
||||
wstep = 1500
|
||||
cur_width = min_width
|
||||
|
||||
while True:
|
||||
tchannel.pulse_width(cur_width)
|
||||
|
||||
# this determines how often we change the pulse-width. It is
|
||||
# analogous to frames-per-second
|
||||
sleep(0.01)
|
||||
|
||||
cur_width += wstep
|
||||
|
||||
if cur_width > max_width:
|
||||
cur_width = min_width
|
||||
|
||||
Breathing Effect
|
||||
----------------
|
||||
|
||||
If we want to have a breathing effect, where the LED fades from dim to bright then bright to dim, then we simply need to reverse the sign of ``wstep`` when we reach maximum brightness, and reverse it again at minimum brightness. To do this we modify the ``while`` loop to be::
|
||||
|
||||
while True:
|
||||
tchannel.pulse_width(cur_width)
|
||||
|
||||
sleep(0.01)
|
||||
|
||||
cur_width += wstep
|
||||
|
||||
if cur_width > max_width:
|
||||
cur_width = max_width
|
||||
wstep *= -1
|
||||
elif cur_width < min_width:
|
||||
cur_width = min_width
|
||||
wstep *= -1
|
||||
|
||||
Advanced Exercise
|
||||
-----------------
|
||||
|
||||
You may have noticed that the LED brightness seems to fade slowly, but increases quickly. This is because our eyes interprets brightness logarithmically (`Weber's Law <http://www.telescope-optics.net/eye_intensity_response.htm>`_
|
||||
), while the LED's brightness changes linearly, that is by the same amount each time. How do you solve this problem? (Hint: what is the opposite of the logarithmic function?)
|
||||
|
||||
Addendum
|
||||
--------
|
||||
|
||||
We could have also used the digital-to-analog converter (DAC) to achieve the same effect. The PWM method has the advantage that it drives the LED with the same current each time, but for different lengths of time. This allows better control over the brightness, because LEDs do not necessarily exhibit a linear relationship between the driving current and brightness.
|
||||
BIN
docs/tutorial/img/fading_leds_breadboard_fritzing.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
docs/tutorial/img/pyboard_servo.jpg
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
docs/tutorial/img/pyboard_usb_micro.jpg
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
docs/tutorial/img/skin_amp_1.jpg
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
docs/tutorial/img/skin_amp_2.jpg
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
docs/tutorial/img/skin_lcd_1.jpg
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
docs/tutorial/img/skin_lcd_2.jpg
Normal file
|
After Width: | Height: | Size: 68 KiB |
@@ -22,6 +22,7 @@ the tutorial through in the order below.
|
||||
usb_mouse.rst
|
||||
timer.rst
|
||||
assembler.rst
|
||||
power_ctrl.rst
|
||||
|
||||
Tutorials requiring extra components
|
||||
------------------------------------
|
||||
@@ -31,5 +32,16 @@ Tutorials requiring extra components
|
||||
:numbered:
|
||||
|
||||
servo.rst
|
||||
fading_led.rst
|
||||
lcd_skin.rst
|
||||
amp_skin.rst
|
||||
|
||||
Tips, tricks and useful things to know
|
||||
--------------------------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:numbered:
|
||||
|
||||
debounce.rst
|
||||
pass_through.rst
|
||||
|
||||
@@ -3,11 +3,11 @@ The LCD and touch-sensor skin
|
||||
|
||||
Soldering and using the LCD and touch-sensor skin.
|
||||
|
||||
.. image:: http://micropython.org/static/doc/skin-lcd-3.jpg
|
||||
.. image:: img/skin_lcd_1.jpg
|
||||
:alt: pyboard with LCD skin
|
||||
:width: 250px
|
||||
|
||||
.. image:: http://micropython.org/static/doc/skin-lcd-1.jpg
|
||||
.. image:: img/skin_lcd_2.jpg
|
||||
:alt: pyboard with LCD skin
|
||||
:width: 250px
|
||||
|
||||
@@ -24,12 +24,14 @@ Using the LCD
|
||||
To get started using the LCD, try the following at the Micro Python prompt.
|
||||
Make sure the LCD skin is attached to the pyboard as pictured at the top of this page. ::
|
||||
|
||||
>>> import pyb
|
||||
>>> lcd = pyb.LCD('X')
|
||||
>>> lcd.light(True)
|
||||
>>> lcd.write('Hello uPy!\n')
|
||||
|
||||
You can make a simple animation using the code::
|
||||
|
||||
import pyb
|
||||
lcd = pyb.LCD('X')
|
||||
lcd.light(True)
|
||||
for x in range(-80, 128):
|
||||
@@ -46,6 +48,7 @@ MPR121 capacitive touch sensor has address 90.
|
||||
|
||||
To get started, try::
|
||||
|
||||
>>> import pyb
|
||||
>>> i2c = pyb.I2C(1, pyb.I2C.MASTER)
|
||||
>>> i2c.mem_write(4, 90, 0x5e)
|
||||
>>> touch = i2c.mem_read(1, 90, 0)[0]
|
||||
@@ -55,7 +58,7 @@ enables the 4 touch sensors. The third line reads the touch
|
||||
status and the ``touch`` variable holds the state of the 4 touch
|
||||
buttons (A, B, X, Y).
|
||||
|
||||
There is a simple driver [here](/static/doc/examples/mpr121.py)
|
||||
There is a simple driver `here <http://micropython.org/resources/examples/mpr121.py>`_
|
||||
which allows you to set the threshold and debounce parameters, and
|
||||
easily read the touch status and electrode voltage levels. Copy
|
||||
this script to your pyboard (either flash or SD card, in the top
|
||||
@@ -78,4 +81,4 @@ initialise the I2C bus using::
|
||||
>>> m = mpr121.MPR121(pyb.I2C(2, pyb.I2C.MASTER))
|
||||
|
||||
There is also a demo which uses the LCD and the touch sensors together,
|
||||
and can be found [here](/static/doc/examples/lcddemo.py).
|
||||
and can be found `here <http://micropython.org/resources/examples/lcddemo.py>`_.
|
||||
|
||||
17
docs/tutorial/pass_through.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
Making a UART - USB pass through
|
||||
================================
|
||||
|
||||
It's as simple as::
|
||||
|
||||
import pyb
|
||||
import select
|
||||
|
||||
def pass_through(usb, uart):
|
||||
while True:
|
||||
select.select([usb, uart], [], [])
|
||||
if usb.any():
|
||||
uart.write(usb.read(256))
|
||||
if uart.any():
|
||||
usb.write(uart.read(256))
|
||||
|
||||
pass_through(pyb.USB_VCP(), pyb.UART(1, 9600))
|
||||
13
docs/tutorial/power_ctrl.rst
Normal file
@@ -0,0 +1,13 @@
|
||||
Power control
|
||||
=============
|
||||
|
||||
:meth:`pyb.wfi` is used to reduce power consumption while waiting for an
|
||||
event such as an interrupt. You would use it in the following situation::
|
||||
|
||||
while True:
|
||||
do_some_processing()
|
||||
pyb.wfi()
|
||||
|
||||
Control the frequency using :meth:`pyb.freq`::
|
||||
|
||||
pyb.freq(30000000) # set CPU frequency to 30MHz
|
||||
@@ -26,7 +26,7 @@ and see which COM port it is (eg COM4).
|
||||
|
||||
You now need to run your terminal program. You can use HyperTerminal if you
|
||||
have it installed, or download the free program PuTTY:
|
||||
[`putty.exe`](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html).
|
||||
`putty.exe <http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html>`_.
|
||||
Using your serial program you must connect to the COM port that you found in the
|
||||
previous step. With PuTTY, click on "Session" in the left-hand panel, then click
|
||||
the "Serial" radio button on the right, then enter you COM port (eg COM4) in the
|
||||
@@ -39,7 +39,7 @@ Open a terminal and run::
|
||||
|
||||
screen /dev/tty.usbmodem*
|
||||
|
||||
When you are finishend and want to exit screen, type CTRL-A CTRL-\\.
|
||||
When you are finished and want to exit screen, type CTRL-A CTRL-\\.
|
||||
|
||||
Linux
|
||||
-----
|
||||
|
||||
@@ -10,7 +10,7 @@ Connecting your pyboard
|
||||
Connect your pyboard to your PC (Windows, Mac or Linux) with a micro USB cable.
|
||||
There is only one way that the cable will connect, so you can't get it wrong.
|
||||
|
||||
<img src="/static/doc/pyboard-usb-micro.jpg" alt="pyboard with USB micro cable" style="width:200px; border:1px solid black; display:inline-block;"/>
|
||||
.. image:: img/pyboard_usb_micro.jpg
|
||||
|
||||
When the pyboard is connected to your PC it will power on and enter the start up
|
||||
process (the boot process). The green LED should light up for half a second or
|
||||
@@ -46,16 +46,16 @@ a window (or command line) should be showing the files on the pyboard drive.
|
||||
The drive you are looking at is known as ``/flash`` by the pyboard, and should contain
|
||||
the following 4 files:
|
||||
|
||||
- [``boot.py``](/static/doc/fresh-pyboard/boot.py) -- this script is executed when the pyboard boots up. It sets
|
||||
* `boot.py <http://micropython.org/resources/fresh-pyboard/boot.py>`_ -- this script is executed when the pyboard boots up. It sets
|
||||
up various configuration options for the pyboard.
|
||||
|
||||
- [``main.py``](/static/doc/fresh-pyboard/main.py) -- this is the main script that will contain your Python program.
|
||||
* `main.py <http://micropython.org/resources/fresh-pyboard/main.py>`_ -- this is the main script that will contain your Python program.
|
||||
It is executed after ``boot.py``.
|
||||
|
||||
- [``README.txt``](/static/doc/fresh-pyboard/README.txt) -- this contains some very basic information about getting
|
||||
* `README.txt <http://micropython.org/resources/fresh-pyboard/README.txt>`_ -- this contains some very basic information about getting
|
||||
started with the pyboard.
|
||||
|
||||
- [``pybcdc.inf``](/static/doc/fresh-pyboard/pybcdc.inf) -- this is a Windows driver file to configure the serial USB
|
||||
* `pybcdc.inf <http://micropython.org/resources/fresh-pyboard/pybcdc.inf>`_ -- this is a Windows driver file to configure the serial USB
|
||||
device. More about this in the next tutorial.
|
||||
|
||||
Editing ``main.py``
|
||||
|
||||
@@ -8,7 +8,7 @@ These motors have 3 wires: ground, power and signal. On the pyboard you
|
||||
can connect them in the bottom right corner, with the signal pin on the
|
||||
far right. Pins X1, X2, X3 and X4 are the 4 dedicated servo signal pins.
|
||||
|
||||
<img src="/static/doc/pyboard-servo.jpg" alt="pyboard with servo motors" style="width:250px; border:1px solid black; display:inline-block;"/>
|
||||
.. image:: img/pyboard_servo.jpg
|
||||
|
||||
In this picture there are male-male double adaptors to connect the servos
|
||||
to the header pins on the pyboard.
|
||||
|
||||
@@ -101,11 +101,16 @@ enum {
|
||||
|
||||
// Here we need to set sign bit right
|
||||
#define TYPE2SMALLINT(x, nbits) ((((int)x) << (32 - nbits)) >> 1)
|
||||
#define GET_TYPE(x, nbits) (((x) >> (31 - nbits)) & ((1 << nbits) - 1));
|
||||
#define GET_TYPE(x, nbits) (((x) >> (31 - nbits)) & ((1 << nbits) - 1))
|
||||
// Bit 0 is "is_signed"
|
||||
#define GET_SCALAR_SIZE(val_type) (1 << ((val_type) >> 1))
|
||||
#define VALUE_MASK(type_nbits) ~((int)0x80000000 >> type_nbits)
|
||||
|
||||
#define IS_SCALAR_ARRAY(tuple_desc) ((tuple_desc)->len == 2)
|
||||
// We cannot apply the below to INT8, as their range [-128, 127]
|
||||
#define IS_SCALAR_ARRAY_OF_BYTES(tuple_desc) (GET_TYPE(MP_OBJ_SMALL_INT_VALUE((tuple_desc)->items[1]), VAL_TYPE_BITS) == UINT8)
|
||||
|
||||
// "struct" in uctypes context means "structural", i.e. aggregate, type.
|
||||
STATIC const mp_obj_type_t uctypes_struct_type;
|
||||
|
||||
typedef struct _mp_obj_uctypes_struct_t {
|
||||
@@ -153,6 +158,10 @@ STATIC void uctypes_struct_print(void (*print)(void *env, const char *fmt, ...),
|
||||
print(env, "<struct %s %p>", typen, self->addr);
|
||||
}
|
||||
|
||||
// Get size of any type descriptor
|
||||
STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size);
|
||||
|
||||
// Get size of scalar type descriptor
|
||||
static inline mp_uint_t uctypes_struct_scalar_size(int val_type) {
|
||||
if (val_type == FLOAT32) {
|
||||
return 4;
|
||||
@@ -161,11 +170,60 @@ static inline mp_uint_t uctypes_struct_scalar_size(int val_type) {
|
||||
}
|
||||
}
|
||||
|
||||
// Get size of aggregate type descriptor
|
||||
STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, mp_uint_t *max_field_size) {
|
||||
mp_uint_t total_size = 0;
|
||||
|
||||
mp_int_t offset_ = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
|
||||
mp_uint_t agg_type = GET_TYPE(offset_, AGG_TYPE_BITS);
|
||||
|
||||
switch (agg_type) {
|
||||
case STRUCT:
|
||||
return uctypes_struct_size(t->items[1], max_field_size);
|
||||
case PTR:
|
||||
if (sizeof(void*) > *max_field_size) {
|
||||
*max_field_size = sizeof(void*);
|
||||
}
|
||||
return sizeof(void*);
|
||||
case ARRAY: {
|
||||
mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]);
|
||||
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
|
||||
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
|
||||
mp_uint_t item_s;
|
||||
if (t->len == 2) {
|
||||
// Elements of array are scalar
|
||||
item_s = GET_SCALAR_SIZE(val_type);
|
||||
if (item_s > *max_field_size) {
|
||||
*max_field_size = item_s;
|
||||
}
|
||||
} else {
|
||||
// Elements of array are aggregates
|
||||
item_s = uctypes_struct_size(t->items[2], max_field_size);
|
||||
}
|
||||
|
||||
return item_s * arr_sz;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return total_size;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size) {
|
||||
mp_obj_dict_t *d = desc_in;
|
||||
mp_uint_t total_size = 0;
|
||||
|
||||
if (!MP_OBJ_IS_TYPE(desc_in, &mp_type_dict)) {
|
||||
if (MP_OBJ_IS_TYPE(desc_in, &mp_type_tuple)) {
|
||||
return uctypes_struct_agg_size((mp_obj_tuple_t*)desc_in, max_field_size);
|
||||
} else if (MP_OBJ_IS_SMALL_INT(desc_in)) {
|
||||
// We allow sizeof on both type definitions and structures/structure fields,
|
||||
// but scalar structure field is lowered into native Python int, so all
|
||||
// type info is lost. So, we cannot say if it's scalar type description,
|
||||
// or such lowered scalar.
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "Cannot unambiguously get sizeof scalar"));
|
||||
}
|
||||
syntax_error();
|
||||
}
|
||||
|
||||
@@ -189,48 +247,10 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size
|
||||
}
|
||||
mp_obj_tuple_t *t = (mp_obj_tuple_t*)v;
|
||||
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
|
||||
mp_uint_t agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
|
||||
offset &= VALUE_MASK(AGG_TYPE_BITS);
|
||||
|
||||
switch (agg_type) {
|
||||
case STRUCT: {
|
||||
mp_uint_t s = uctypes_struct_size(t->items[1], max_field_size);
|
||||
if (offset + s > total_size) {
|
||||
total_size = offset + s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTR: {
|
||||
if (offset + sizeof(void*) > total_size) {
|
||||
total_size = offset + sizeof(void*);
|
||||
}
|
||||
if (sizeof(void*) > *max_field_size) {
|
||||
*max_field_size = sizeof(void*);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARRAY: {
|
||||
mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]);
|
||||
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
|
||||
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
|
||||
mp_uint_t item_s;
|
||||
if (t->len == 2) {
|
||||
item_s = GET_SCALAR_SIZE(val_type);
|
||||
if (item_s > *max_field_size) {
|
||||
*max_field_size = item_s;
|
||||
}
|
||||
} else {
|
||||
item_s = uctypes_struct_size(t->items[2], max_field_size);
|
||||
}
|
||||
|
||||
mp_uint_t byte_sz = item_s * arr_sz;
|
||||
if (offset + byte_sz > total_size) {
|
||||
total_size = offset + byte_sz;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
mp_uint_t s = uctypes_struct_agg_size(t, max_field_size);
|
||||
if (offset + s > total_size) {
|
||||
total_size = offset + s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,7 +263,13 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size
|
||||
|
||||
STATIC mp_obj_t uctypes_struct_sizeof(mp_obj_t obj_in) {
|
||||
mp_uint_t max_field_size = 0;
|
||||
if (MP_OBJ_IS_TYPE(obj_in, &mp_type_bytearray)) {
|
||||
return mp_obj_len(obj_in);
|
||||
}
|
||||
// We can apply sizeof either to structure definition (a dict)
|
||||
// or to instantiated structure
|
||||
if (MP_OBJ_IS_TYPE(obj_in, &uctypes_struct_type)) {
|
||||
// Extract structure definition
|
||||
mp_obj_uctypes_struct_t *obj = obj_in;
|
||||
obj_in = obj->desc;
|
||||
}
|
||||
@@ -435,7 +461,14 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
|
||||
o->flags = self->flags;
|
||||
return o;
|
||||
}
|
||||
case PTR: case ARRAY: {
|
||||
case ARRAY: {
|
||||
mp_uint_t dummy;
|
||||
if (IS_SCALAR_ARRAY(sub) && IS_SCALAR_ARRAY_OF_BYTES(sub)) {
|
||||
return mp_obj_new_bytearray_by_ref(uctypes_struct_agg_size(sub, &dummy), self->addr + offset);
|
||||
}
|
||||
// Fall thru to return uctypes struct object
|
||||
}
|
||||
case PTR: {
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = &uctypes_struct_type;
|
||||
o->desc = sub;
|
||||
|
||||
33
lib/libm/roundf.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
// roundf from musl-0.9.15
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "libm.h"
|
||||
|
||||
float roundf(float x)
|
||||
{
|
||||
union {float f; uint32_t i;} u = {x};
|
||||
int e = u.i >> 23 & 0xff;
|
||||
float_t y;
|
||||
|
||||
if (e >= 0x7f+23)
|
||||
return x;
|
||||
if (u.i >> 31)
|
||||
x = -x;
|
||||
if (e < 0x7f-1) {
|
||||
FORCE_EVAL(x + 0x1p23f);
|
||||
return 0*u.f;
|
||||
}
|
||||
y = (float)(x + 0x1p23f) - 0x1p23f - x;
|
||||
if (y > 0.5f)
|
||||
y = y + x - 1;
|
||||
else if (y <= -0.5f)
|
||||
y = y + x + 1;
|
||||
else
|
||||
y = y + x;
|
||||
if (u.i >> 31)
|
||||
y = -y;
|
||||
return y;
|
||||
}
|
||||
23
py/builtin.c
@@ -448,9 +448,30 @@ STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) {
|
||||
vstr_free(vstr);
|
||||
return s;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_round(mp_obj_t o_in) {
|
||||
// TODO support second arg
|
||||
if (MP_OBJ_IS_INT(o_in)) {
|
||||
return o_in;
|
||||
}
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_float_t val = mp_obj_get_float(o_in);
|
||||
mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val);
|
||||
mp_int_t r = rounded;
|
||||
// make rounded value even if it was halfway between ints
|
||||
if (val - rounded == 0.5) {
|
||||
r = (r + 1) & (~1);
|
||||
} else if (val - rounded == -0.5) {
|
||||
r &= ~1;
|
||||
}
|
||||
#else
|
||||
mp_int_t r = mp_obj_get_int(o_in);
|
||||
#endif
|
||||
return mp_obj_new_int(r);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_round_obj, mp_builtin_round);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_sum(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
assert(1 <= n_args && n_args <= 2);
|
||||
mp_obj_t value;
|
||||
|
||||
@@ -61,6 +61,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_ord_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_pow_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_print_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_repr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_round_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sorted_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj);
|
||||
|
||||
|
||||
@@ -118,6 +118,7 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_pow), (mp_obj_t)&mp_builtin_pow_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_print), (mp_obj_t)&mp_builtin_print_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_repr), (mp_obj_t)&mp_builtin_repr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_round), (mp_obj_t)&mp_builtin_round_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sorted), (mp_obj_t)&mp_builtin_sorted_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sum), (mp_obj_t)&mp_builtin_sum_obj },
|
||||
|
||||
|
||||
@@ -233,6 +233,11 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
|
||||
}
|
||||
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
|
||||
// int >> int
|
||||
if (arg1 >= BITS_PER_WORD) {
|
||||
// Shifting to big amounts is underfined behavior
|
||||
// in C and is CPU-dependent; propagate sign bit.
|
||||
arg1 = BITS_PER_WORD - 1;
|
||||
}
|
||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
|
||||
} else {
|
||||
// shouldn't happen
|
||||
|
||||
9
py/gc.c
@@ -28,6 +28,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
@@ -68,7 +69,8 @@ STATIC mp_uint_t *gc_pool_end;
|
||||
STATIC int gc_stack_overflow;
|
||||
STATIC mp_uint_t gc_stack[STACK_SIZE];
|
||||
STATIC mp_uint_t *gc_sp;
|
||||
STATIC mp_uint_t gc_lock_depth;
|
||||
STATIC uint16_t gc_lock_depth;
|
||||
uint16_t gc_auto_collect_enabled;
|
||||
STATIC mp_uint_t gc_last_free_atb_index;
|
||||
|
||||
// ATB = allocation table byte
|
||||
@@ -163,6 +165,9 @@ void gc_init(void *start, void *end) {
|
||||
// unlock the GC
|
||||
gc_lock_depth = 0;
|
||||
|
||||
// allow auto collection
|
||||
gc_auto_collect_enabled = 1;
|
||||
|
||||
DEBUG_printf("GC layout:\n");
|
||||
DEBUG_printf(" alloc table at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", gc_alloc_table_start, gc_alloc_table_byte_len, gc_alloc_table_byte_len * BLOCKS_PER_ATB);
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
@@ -375,7 +380,7 @@ void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser) {
|
||||
mp_uint_t end_block;
|
||||
mp_uint_t start_block;
|
||||
mp_uint_t n_free = 0;
|
||||
int collected = 0;
|
||||
int collected = !gc_auto_collect_enabled;
|
||||
for (;;) {
|
||||
|
||||
// look for a run of n_blocks available blocks
|
||||
|
||||
5
py/gc.h
@@ -32,6 +32,11 @@ void gc_lock(void);
|
||||
void gc_unlock(void);
|
||||
bool gc_is_locked(void);
|
||||
|
||||
// This variable controls auto garbage collection. If set to 0 then the
|
||||
// GC won't automatically run when gc_alloc can't find enough blocks. But
|
||||
// you can still allocate/free memory and also explicitly call gc_collect.
|
||||
extern uint16_t gc_auto_collect_enabled;
|
||||
|
||||
// A given port must implement gc_collect by using the other collect functions.
|
||||
void gc_collect(void);
|
||||
void gc_collect_start(void);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
|
||||
16
py/modgc.c
@@ -24,15 +24,13 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
#include "runtime.h"
|
||||
#include "objlist.h"
|
||||
#include "objtuple.h"
|
||||
#include "objstr.h"
|
||||
#include "gc.h"
|
||||
|
||||
#if MICROPY_PY_GC && MICROPY_ENABLE_GC
|
||||
@@ -56,7 +54,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(gc_collect_obj, py_gc_collect);
|
||||
/// \function disable()
|
||||
/// Disable the garbage collector.
|
||||
STATIC mp_obj_t gc_disable(void) {
|
||||
gc_lock();
|
||||
gc_auto_collect_enabled = 0;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(gc_disable_obj, gc_disable);
|
||||
@@ -64,11 +62,16 @@ MP_DEFINE_CONST_FUN_OBJ_0(gc_disable_obj, gc_disable);
|
||||
/// \function enable()
|
||||
/// Enable the garbage collector.
|
||||
STATIC mp_obj_t gc_enable(void) {
|
||||
gc_unlock();
|
||||
gc_auto_collect_enabled = 1;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(gc_enable_obj, gc_enable);
|
||||
|
||||
STATIC mp_obj_t gc_isenabled(void) {
|
||||
return MP_BOOL(gc_auto_collect_enabled);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(gc_isenabled_obj, gc_isenabled);
|
||||
|
||||
/// \function mem_free()
|
||||
/// Return the number of bytes of available heap RAM.
|
||||
STATIC mp_obj_t gc_mem_free(void) {
|
||||
@@ -92,6 +95,7 @@ STATIC const mp_map_elem_t mp_module_gc_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_collect), (mp_obj_t)&gc_collect_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&gc_disable_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&gc_enable_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_isenabled), (mp_obj_t)&gc_isenabled_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_free), (mp_obj_t)&gc_mem_free_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_alloc), (mp_obj_t)&gc_mem_alloc_obj },
|
||||
};
|
||||
|
||||
@@ -25,10 +25,23 @@
|
||||
*/
|
||||
|
||||
// This file contains default configuration settings for MicroPython.
|
||||
// You can override any of these options using mpconfigport.h file located
|
||||
// in a directory of your port.
|
||||
// You can override any of the options below using mpconfigport.h file
|
||||
// located in a directory of your port.
|
||||
|
||||
// mpconfigport.h is a file containing configuration settings for a
|
||||
// particular port. mpconfigport.h is actually a default name for
|
||||
// such config, and it can be overriden using MP_CONFIGFILE preprocessor
|
||||
// define (you can do that by passing CFLAGS_EXTRA='-DMP_CONFIGFILE="<file.h>"'
|
||||
// argument to make when using standard MicroPython makefiles).
|
||||
// This is useful to have more than one config per port, for example,
|
||||
// release vs debug configs, etc. Note that if you switch from one config
|
||||
// to another, you must rebuild from scratch using "-B" switch to make.
|
||||
|
||||
#ifdef MP_CONFIGFILE
|
||||
#include MP_CONFIGFILE
|
||||
#else
|
||||
#include <mpconfigport.h>
|
||||
#endif
|
||||
|
||||
// Any options not explicitly set in mpconfigport.h will get default
|
||||
// values below.
|
||||
|
||||
6
py/mpz.c
@@ -37,9 +37,9 @@
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
|
||||
|
||||
#define DIG_SIZE (MPZ_DIG_SIZE)
|
||||
#define DIG_MASK ((1L << DIG_SIZE) - 1)
|
||||
#define DIG_MSB (1L << (DIG_SIZE - 1))
|
||||
#define DIG_BASE (1L << DIG_SIZE)
|
||||
#define DIG_MASK ((MPZ_LONG_1 << DIG_SIZE) - 1)
|
||||
#define DIG_MSB (MPZ_LONG_1 << (DIG_SIZE - 1))
|
||||
#define DIG_BASE (MPZ_LONG_1 << DIG_SIZE)
|
||||
|
||||
/*
|
||||
mpz is an arbitrary precision integer type with a public API.
|
||||
|
||||
8
py/mpz.h
@@ -36,7 +36,7 @@
|
||||
// depending on the machine, but it (and MPZ_DIG_SIZE) can be freely changed so
|
||||
// long as the constraints mentioned above are met.
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if defined(__x86_64__) || defined(_WIN64)
|
||||
// 64-bit machine, using 32-bit storage for digits
|
||||
typedef uint32_t mpz_dig_t;
|
||||
typedef uint64_t mpz_dbl_dig_t;
|
||||
@@ -50,6 +50,12 @@ typedef int32_t mpz_dbl_dig_signed_t;
|
||||
#define MPZ_DIG_SIZE (16)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
#define MPZ_LONG_1 1i64
|
||||
#else
|
||||
#define MPZ_LONG_1 1L
|
||||
#endif
|
||||
|
||||
#define MPZ_NUM_DIG_FOR_INT (sizeof(mp_int_t) * 8 / MPZ_DIG_SIZE + 1)
|
||||
#define MPZ_NUM_DIG_FOR_LL (sizeof(long long) * 8 / MPZ_DIG_SIZE + 1)
|
||||
|
||||
|
||||
7
py/obj.c
@@ -34,6 +34,7 @@
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "objtype.h"
|
||||
#include "mpz.h"
|
||||
#include "objint.h"
|
||||
#include "runtime0.h"
|
||||
@@ -145,7 +146,11 @@ bool mp_obj_is_true(mp_obj_t arg) {
|
||||
}
|
||||
|
||||
bool mp_obj_is_callable(mp_obj_t o_in) {
|
||||
return mp_obj_get_type(o_in)->call != NULL;
|
||||
mp_call_fun_t call = mp_obj_get_type(o_in)->call;
|
||||
if (call != mp_obj_instance_call) {
|
||||
return call != NULL;
|
||||
}
|
||||
return mp_obj_instance_is_callable(o_in);
|
||||
}
|
||||
|
||||
mp_int_t mp_obj_hash(mp_obj_t o_in) {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
@@ -292,7 +293,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
||||
#endif
|
||||
} else {
|
||||
res = array_new(o->typecode, slice.stop - slice.start);
|
||||
memcpy(res->items, o->items + slice.start * sz, (slice.stop - slice.start) * sz);
|
||||
memcpy(res->items, (uint8_t*)o->items + slice.start * sz, (slice.stop - slice.start) * sz);
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
@@ -331,7 +332,7 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui
|
||||
// read-only memoryview
|
||||
return 1;
|
||||
}
|
||||
bufinfo->buf += (mp_uint_t)o->free * sz;
|
||||
bufinfo->buf = (uint8_t*)bufinfo->buf + (mp_uint_t)o->free * sz;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
#if MICROPY_PY_SYS_MAXSIZE
|
||||
// Export value for sys.maxsize
|
||||
#define DIG_MASK ((1L << MPZ_DIG_SIZE) - 1)
|
||||
#define DIG_MASK ((MPZ_LONG_1 << MPZ_DIG_SIZE) - 1)
|
||||
STATIC const mpz_dig_t maxsize_dig[MPZ_NUM_DIG_FOR_INT] = {
|
||||
(MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) & DIG_MASK,
|
||||
#if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) > DIG_MASK
|
||||
|
||||
21
py/objstr.c
@@ -160,15 +160,18 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
|
||||
case 3:
|
||||
{
|
||||
// TODO: validate 2nd/3rd args
|
||||
if (!MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
|
||||
if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
|
||||
GET_STR_DATA_LEN(args[0], str_data, str_len);
|
||||
GET_STR_HASH(args[0], str_hash);
|
||||
mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
|
||||
o->data = str_data;
|
||||
o->hash = str_hash;
|
||||
return o;
|
||||
} else {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
|
||||
return mp_obj_new_str(bufinfo.buf, bufinfo.len, false);
|
||||
}
|
||||
GET_STR_DATA_LEN(args[0], str_data, str_len);
|
||||
GET_STR_HASH(args[0], str_hash);
|
||||
mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
|
||||
o->data = str_data;
|
||||
o->hash = str_hash;
|
||||
return o;
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -1895,7 +1898,7 @@ qstr mp_obj_str_get_qstr(mp_obj_t self_in) {
|
||||
// only use this function if you need the str data to be zero terminated
|
||||
// at the moment all strings are zero terminated to help with C ASCIIZ compatibility
|
||||
const char *mp_obj_str_get_str(mp_obj_t self_in) {
|
||||
if (MP_OBJ_IS_STR(self_in)) {
|
||||
if (MP_OBJ_IS_STR_OR_BYTES(self_in)) {
|
||||
GET_STR_DATA_LEN(self_in, s, l);
|
||||
(void)l; // len unused
|
||||
return (const char*)s;
|
||||
|
||||
@@ -142,15 +142,18 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
|
||||
case 3:
|
||||
{
|
||||
// TODO: validate 2nd/3rd args
|
||||
if (!MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
|
||||
if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
|
||||
GET_STR_DATA_LEN(args[0], str_data, str_len);
|
||||
GET_STR_HASH(args[0], str_hash);
|
||||
mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
|
||||
o->data = str_data;
|
||||
o->hash = str_hash;
|
||||
return o;
|
||||
} else {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
|
||||
return mp_obj_new_str(bufinfo.buf, bufinfo.len, false);
|
||||
}
|
||||
GET_STR_DATA_LEN(args[0], str_data, str_len);
|
||||
GET_STR_HASH(args[0], str_hash);
|
||||
mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
|
||||
o->data = str_data;
|
||||
o->hash = str_hash;
|
||||
return o;
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
28
py/objtype.c
@@ -204,6 +204,7 @@ STATIC void instance_print(void (*print)(void *env, const char *fmt, ...), void
|
||||
.attr = meth,
|
||||
.meth_offset = offsetof(mp_obj_type_t, print),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
if (member[0] == MP_OBJ_NULL && kind == PRINT_STR) {
|
||||
@@ -261,6 +262,7 @@ mp_obj_t instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, c
|
||||
.attr = MP_QSTR___new__,
|
||||
.meth_offset = offsetof(mp_obj_type_t, make_new),
|
||||
.dest = init_fn,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self);
|
||||
|
||||
@@ -341,6 +343,7 @@ STATIC mp_obj_t instance_unary_op(mp_uint_t op, mp_obj_t self_in) {
|
||||
.attr = op_name,
|
||||
.meth_offset = offsetof(mp_obj_type_t, unary_op),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
if (member[0] == MP_OBJ_SENTINEL) {
|
||||
@@ -437,6 +440,7 @@ STATIC mp_obj_t instance_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_i
|
||||
.attr = op_name,
|
||||
.meth_offset = offsetof(mp_obj_type_t, binary_op),
|
||||
.dest = dest,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, lhs->base.type);
|
||||
if (dest[0] == MP_OBJ_SENTINEL) {
|
||||
@@ -467,6 +471,7 @@ STATIC void instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
.attr = attr,
|
||||
.meth_offset = 0,
|
||||
.dest = dest,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
mp_obj_t member = dest[0];
|
||||
@@ -514,6 +519,7 @@ STATIC bool instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
|
||||
.attr = attr,
|
||||
.meth_offset = 0,
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
if (member[0] != MP_OBJ_NULL && MP_OBJ_IS_TYPE(member[0], &mp_type_property)) {
|
||||
@@ -549,6 +555,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
|
||||
.obj = self,
|
||||
.meth_offset = offsetof(mp_obj_type_t, subscr),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
uint meth_args;
|
||||
if (value == MP_OBJ_NULL) {
|
||||
@@ -583,7 +590,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t instance_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
bool mp_obj_instance_is_callable(mp_obj_t self_in) {
|
||||
mp_obj_instance_t *self = self_in;
|
||||
mp_obj_t member[2] = {MP_OBJ_NULL};
|
||||
struct class_lookup_data lookup = {
|
||||
@@ -591,6 +598,21 @@ STATIC mp_obj_t instance_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw
|
||||
.attr = MP_QSTR___call__,
|
||||
.meth_offset = offsetof(mp_obj_type_t, call),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
return member[0] != MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_instance_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
mp_obj_instance_t *self = self_in;
|
||||
mp_obj_t member[2] = {MP_OBJ_NULL, MP_OBJ_NULL};
|
||||
struct class_lookup_data lookup = {
|
||||
.obj = self,
|
||||
.attr = MP_QSTR___call__,
|
||||
.meth_offset = offsetof(mp_obj_type_t, call),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
if (member[0] == MP_OBJ_NULL) {
|
||||
@@ -611,6 +633,7 @@ STATIC mp_obj_t instance_getiter(mp_obj_t self_in) {
|
||||
.attr = MP_QSTR___iter__,
|
||||
.meth_offset = offsetof(mp_obj_type_t, getiter),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
if (member[0] == MP_OBJ_NULL) {
|
||||
@@ -777,7 +800,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
|
||||
o->load_attr = instance_load_attr;
|
||||
o->store_attr = instance_store_attr;
|
||||
o->subscr = instance_subscr;
|
||||
o->call = instance_call;
|
||||
o->call = mp_obj_instance_call;
|
||||
o->getiter = instance_getiter;
|
||||
o->bases_tuple = bases_tuple;
|
||||
o->locals_dict = locals_dict;
|
||||
@@ -850,6 +873,7 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
.attr = attr,
|
||||
.meth_offset = 0,
|
||||
.dest = dest,
|
||||
.is_type = false,
|
||||
};
|
||||
for (uint i = 0; i < len; i++) {
|
||||
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
|
||||
|
||||
@@ -32,3 +32,7 @@ typedef struct _mp_obj_instance_t {
|
||||
mp_obj_t subobj[];
|
||||
// TODO maybe cache __getattr__ and __setattr__ for efficient lookup of them
|
||||
} mp_obj_instance_t;
|
||||
|
||||
// these need to be exposed so mp_obj_is_callable can work correctly
|
||||
bool mp_obj_instance_is_callable(mp_obj_t self_in);
|
||||
mp_obj_t mp_obj_instance_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
|
||||
@@ -201,6 +201,7 @@ Q(range)
|
||||
Q(read)
|
||||
Q(repr)
|
||||
Q(reversed)
|
||||
Q(round)
|
||||
Q(sorted)
|
||||
Q(staticmethod)
|
||||
Q(sum)
|
||||
@@ -469,6 +470,7 @@ Q(gc)
|
||||
Q(collect)
|
||||
Q(disable)
|
||||
Q(enable)
|
||||
Q(isenabled)
|
||||
Q(mem_free)
|
||||
Q(mem_alloc)
|
||||
#endif
|
||||
|
||||
@@ -337,6 +337,11 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
|
||||
} else {
|
||||
// standard precision is enough for right-shift
|
||||
if (rhs_val >= BITS_PER_WORD) {
|
||||
// Shifting to big amounts is underfined behavior
|
||||
// in C and is CPU-dependent; propagate sign bit.
|
||||
rhs_val = BITS_PER_WORD - 1;
|
||||
}
|
||||
lhs_val >>= rhs_val;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -14,7 +14,7 @@ INC += -I$(PY_SRC)
|
||||
INC += -I$(BUILD)
|
||||
|
||||
CFLAGS_CORTEX_M3 = -mthumb -mcpu=cortex-m3
|
||||
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 $(CFLAGS_CORTEX_M3) $(COPT) \
|
||||
CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 $(CFLAGS_CORTEX_M3) $(COPT) \
|
||||
-flto -ffunction-sections -fdata-sections
|
||||
|
||||
#Debugging/Optimization
|
||||
|
||||
@@ -42,7 +42,7 @@ INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/cdc_msc_hid/inc
|
||||
INC += -I$(FATFS_DIR)/src
|
||||
|
||||
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
|
||||
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_CORTEX_M4) $(COPT)
|
||||
CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_CORTEX_M4) $(COPT)
|
||||
CFLAGS += -Iboards/$(BOARD)
|
||||
|
||||
LDFLAGS = -nostdlib -T stm32f405.ld -Map=$(@:.elf=.map) --cref
|
||||
@@ -68,6 +68,7 @@ SRC_LIB = $(addprefix lib/,\
|
||||
libm/atanf.c \
|
||||
libm/atan2f.c \
|
||||
libm/fmodf.c \
|
||||
libm/roundf.c \
|
||||
)
|
||||
|
||||
SRC_C = \
|
||||
|
||||
41
stmhal/can.c
@@ -60,13 +60,14 @@
|
||||
///
|
||||
/// from pyb import CAN
|
||||
/// can = pyb.CAN(1, pyb.CAN.LOOPBACK)
|
||||
/// can.send('message!', 123) # send message to id 123
|
||||
/// can.send('message!', 123) # send message with id 123
|
||||
/// can.recv(0) # receive message on FIFO 0
|
||||
|
||||
typedef struct _pyb_can_obj_t {
|
||||
mp_obj_base_t base;
|
||||
mp_uint_t can_id : 8;
|
||||
bool is_enabled : 1;
|
||||
bool extframe : 1;
|
||||
CAN_HandleTypeDef can;
|
||||
} pyb_can_obj_t;
|
||||
|
||||
@@ -143,7 +144,7 @@ STATIC void pyb_can_print(void (*print)(void *env, const char *fmt, ...), void *
|
||||
if (!self->is_enabled) {
|
||||
print(env, "CAN(%u)", self->can_id);
|
||||
} else {
|
||||
print(env, "CAN(%u, ", self->can_id);
|
||||
print(env, "CAN(%u, CAN.", self->can_id);
|
||||
qstr mode;
|
||||
switch (self->can.Init.Mode) {
|
||||
case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break;
|
||||
@@ -151,19 +152,26 @@ STATIC void pyb_can_print(void (*print)(void *env, const char *fmt, ...), void *
|
||||
case CAN_MODE_SILENT: mode = MP_QSTR_SILENT; break;
|
||||
case CAN_MODE_SILENT_LOOPBACK: default: mode = MP_QSTR_SILENT_LOOPBACK; break;
|
||||
}
|
||||
print(env, "%s, extframe=", qstr_str(mode));
|
||||
if (self->extframe) {
|
||||
mode = MP_QSTR_True;
|
||||
} else {
|
||||
mode = MP_QSTR_False;
|
||||
}
|
||||
print(env, "%s)", qstr_str(mode));
|
||||
}
|
||||
}
|
||||
|
||||
/// \method init(mode, prescaler=100, *, sjw=1, bs1=6, bs2=8)
|
||||
/// \method init(mode, extframe=False, prescaler=100, *, sjw=1, bs1=6, bs2=8)
|
||||
///
|
||||
/// Initialise the CAN bus with the given parameters:
|
||||
///
|
||||
/// - `mode` is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK
|
||||
STATIC mp_obj_t pyb_can_init_helper(pyb_can_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} },
|
||||
{ MP_QSTR_prescaler, MP_ARG_INT, {.u_int = 100} },
|
||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} },
|
||||
{ MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} },
|
||||
{ MP_QSTR_prescaler, MP_ARG_INT, {.u_int = 100} },
|
||||
/*
|
||||
{ MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 6} },
|
||||
@@ -175,11 +183,13 @@ STATIC mp_obj_t pyb_can_init_helper(pyb_can_obj_t *self, mp_uint_t n_args, const
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
self->extframe = args[1].u_bool;
|
||||
|
||||
// set the CAN configuration values
|
||||
memset(&self->can, 0, sizeof(self->can));
|
||||
CAN_InitTypeDef *init = &self->can.Init;
|
||||
init->Mode = args[0].u_int << 4; // shift-left so modes fit in a small-int
|
||||
init->Prescaler = args[1].u_int;
|
||||
init->Prescaler = args[2].u_int;
|
||||
init->SJW = CAN_SJW_1TQ; // TODO set from args
|
||||
init->BS1 = CAN_BS1_6TQ; // TODO set from args
|
||||
init->BS2 = CAN_BS2_8TQ; // TODO set from args
|
||||
@@ -317,13 +327,20 @@ STATIC mp_obj_t pyb_can_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
mp_buffer_info_t bufinfo;
|
||||
uint8_t data[1];
|
||||
pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data);
|
||||
// TODO check bufinfo.len <= 8
|
||||
|
||||
if (bufinfo.len > 8) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN data field too long"));
|
||||
}
|
||||
|
||||
// send the data
|
||||
CanTxMsgTypeDef tx_msg;
|
||||
tx_msg.StdId = args[1].u_int & 0x7ff;
|
||||
tx_msg.ExtId = 0; // TODO support extended ids
|
||||
tx_msg.IDE = CAN_ID_STD;
|
||||
if (self->extframe){
|
||||
tx_msg.ExtId = args[1].u_int & 0x1FFFFFFF;
|
||||
tx_msg.IDE = CAN_ID_EXT;
|
||||
} else {
|
||||
tx_msg.StdId = args[1].u_int & 0x7FF;
|
||||
tx_msg.IDE = CAN_ID_STD;
|
||||
}
|
||||
tx_msg.RTR = CAN_RTR_DATA;
|
||||
tx_msg.DLC = bufinfo.len;
|
||||
for (mp_uint_t i = 0; i < bufinfo.len; i++) {
|
||||
@@ -397,10 +414,6 @@ STATIC const mp_map_elem_t pyb_can_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_can_recv_obj },
|
||||
|
||||
// class constants
|
||||
/// \constant MASTER - for initialising the bus to master mode
|
||||
/// \constant SLAVE - for initialising the bus to slave mode
|
||||
/// \constant MSB - set the first bit to MSB
|
||||
/// \constant LSB - set the first bit to LSB
|
||||
// Note: we use the ST constants >> 4 so they fit in a small-int. The
|
||||
// right-shift is undone when the constants are used in the init function.
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_NORMAL), MP_OBJ_NEW_SMALL_INT(CAN_MODE_NORMAL >> 4) },
|
||||
|
||||
@@ -61,6 +61,8 @@
|
||||
#include "netapp.h"
|
||||
#include "patch_prog.h"
|
||||
|
||||
/// \moduleref network
|
||||
|
||||
int CC3000_EXPORT(errno); // for cc3000 driver
|
||||
|
||||
STATIC mp_obj_t cc3k_socket_new(mp_uint_t family, mp_uint_t type, mp_uint_t protocol, int *_errno);
|
||||
@@ -140,6 +142,8 @@ STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uin
|
||||
/******************************************************************************/
|
||||
// Micro Python bindings; CC3k class
|
||||
|
||||
/// \class CC3k - driver for CC3000 Wifi modules
|
||||
|
||||
typedef struct _cc3k_obj_t {
|
||||
mp_obj_base_t base;
|
||||
} cc3k_obj_t;
|
||||
@@ -381,7 +385,7 @@ STATIC mp_obj_t cc3k_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
|
||||
mp_int_t bytes = 0;
|
||||
while (bytes < bufinfo.len) {
|
||||
int n = MIN((bufinfo.len - bytes), MAX_TX_PACKET);
|
||||
n = CC3000_EXPORT(send)(self->fd, bufinfo.buf + bytes, n, 0);
|
||||
n = CC3000_EXPORT(send)(self->fd, (uint8_t*)bufinfo.buf + bytes, n, 0);
|
||||
if (n <= 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(CC3000_EXPORT(errno))));
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
#include "runtime.h"
|
||||
#include "modnetwork.h"
|
||||
|
||||
/// \module network - network configuration
|
||||
///
|
||||
/// This module provides network drivers and routing configuration.
|
||||
|
||||
mp_obj_list_t mod_network_nic_list;
|
||||
|
||||
void mod_network_init(void) {
|
||||
|
||||
169
stmhal/modpyb.c
@@ -195,80 +195,123 @@ STATIC mp_obj_t pyb_freq(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
} else {
|
||||
// set
|
||||
mp_int_t wanted_sysclk = mp_obj_get_int(args[0]) / 1000000;
|
||||
// search for a valid PLL configuration that keeps USB at 48MHz
|
||||
for (; wanted_sysclk > 0; wanted_sysclk--) {
|
||||
for (mp_uint_t p = 2; p <= 8; p += 2) {
|
||||
if (wanted_sysclk * p % 48 != 0) {
|
||||
continue;
|
||||
}
|
||||
mp_uint_t q = wanted_sysclk * p / 48;
|
||||
if (q < 2 || q > 15) {
|
||||
continue;
|
||||
}
|
||||
if (wanted_sysclk * p % (HSE_VALUE / 1000000) != 0) {
|
||||
continue;
|
||||
}
|
||||
mp_uint_t n_by_m = wanted_sysclk * p / (HSE_VALUE / 1000000);
|
||||
mp_uint_t m = 192 / n_by_m;
|
||||
while (m < (HSE_VALUE / 2000000) || n_by_m * m < 192) {
|
||||
m += 1;
|
||||
}
|
||||
if (m > (HSE_VALUE / 1000000)) {
|
||||
continue;
|
||||
}
|
||||
mp_uint_t n = n_by_m * m;
|
||||
if (n < 192 || n > 432) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// found values!
|
||||
// default PLL parameters that give 48MHz on PLL48CK
|
||||
uint32_t m = HSE_VALUE / 1000000, n = 336, p = 2, q = 7;
|
||||
uint32_t sysclk_source;
|
||||
|
||||
// let the USB CDC have a chance to process before we change the clock
|
||||
HAL_Delay(USBD_CDC_POLLING_INTERVAL + 2);
|
||||
// the following logic assumes HSE < HSI
|
||||
if (HSE_VALUE / 1000000 <= wanted_sysclk && wanted_sysclk < HSI_VALUE / 1000000) {
|
||||
// use HSE as SYSCLK
|
||||
sysclk_source = RCC_SYSCLKSOURCE_HSE;
|
||||
} else if (HSI_VALUE / 1000000 <= wanted_sysclk && wanted_sysclk < 24) {
|
||||
// use HSI as SYSCLK
|
||||
sysclk_source = RCC_SYSCLKSOURCE_HSI;
|
||||
} else {
|
||||
// search for a valid PLL configuration that keeps USB at 48MHz
|
||||
for (; wanted_sysclk > 0; wanted_sysclk--) {
|
||||
for (p = 2; p <= 8; p += 2) {
|
||||
// compute VCO_OUT
|
||||
mp_uint_t vco_out = wanted_sysclk * p;
|
||||
// make sure VCO_OUT is between 192MHz and 432MHz
|
||||
if (vco_out < 192 || vco_out > 432) {
|
||||
continue;
|
||||
}
|
||||
// make sure Q is an integer
|
||||
if (vco_out % 48 != 0) {
|
||||
continue;
|
||||
}
|
||||
// solve for Q to get PLL48CK at 48MHz
|
||||
q = vco_out / 48;
|
||||
// make sure Q is in range
|
||||
if (q < 2 || q > 15) {
|
||||
continue;
|
||||
}
|
||||
// make sure N/M is an integer
|
||||
if (vco_out % (HSE_VALUE / 1000000) != 0) {
|
||||
continue;
|
||||
}
|
||||
// solve for N/M
|
||||
mp_uint_t n_by_m = vco_out / (HSE_VALUE / 1000000);
|
||||
// solve for M, making sure VCO_IN (=HSE/M) is between 1MHz and 2MHz
|
||||
m = 192 / n_by_m;
|
||||
while (m < (HSE_VALUE / 2000000) || n_by_m * m < 192) {
|
||||
m += 1;
|
||||
}
|
||||
if (m > (HSE_VALUE / 1000000)) {
|
||||
continue;
|
||||
}
|
||||
// solve for N
|
||||
n = n_by_m * m;
|
||||
// make sure N is in range
|
||||
if (n < 192 || n > 432) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// set HSE as system clock source to allow modification of the PLL configuration
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct;
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
|
||||
goto fail;
|
||||
// found values!
|
||||
sysclk_source = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
goto set_clk;
|
||||
}
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "can't make valid freq"));
|
||||
}
|
||||
|
||||
// re-configure PLL
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct;
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = m;
|
||||
RCC_OscInitStruct.PLL.PLLN = n;
|
||||
RCC_OscInitStruct.PLL.PLLP = p;
|
||||
RCC_OscInitStruct.PLL.PLLQ = q;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
|
||||
goto fail;
|
||||
}
|
||||
set_clk:
|
||||
//printf("%lu %lu %lu %lu %lu\n", sysclk_source, m, n, p, q);
|
||||
|
||||
// set PLL as system clock source
|
||||
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
|
||||
goto fail;
|
||||
}
|
||||
// let the USB CDC have a chance to process before we change the clock
|
||||
HAL_Delay(USBD_CDC_POLLING_INTERVAL + 2);
|
||||
|
||||
// re-init TIM3 for USB CDC rate
|
||||
timer_tim3_init();
|
||||
// desired system clock source is in sysclk_source
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct;
|
||||
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
|
||||
if (sysclk_source == RCC_SYSCLKSOURCE_PLLCLK) {
|
||||
// set HSE as system clock source to allow modification of the PLL configuration
|
||||
// we then change to PLL after re-configuring PLL
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
|
||||
} else {
|
||||
// directly set the system clock source as desired
|
||||
RCC_ClkInitStruct.SYSCLKSource = sysclk_source;
|
||||
}
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
// re-configure PLL
|
||||
// even if we don't use the PLL for the system clock, we still need it for USB, RNG and SDIO
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct;
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = m;
|
||||
RCC_OscInitStruct.PLL.PLLN = n;
|
||||
RCC_OscInitStruct.PLL.PLLP = p;
|
||||
RCC_OscInitStruct.PLL.PLLQ = q;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
void __fatal_error(const char *msg);
|
||||
fail:
|
||||
__fatal_error("can't change freq");
|
||||
// set PLL as system clock source if wanted
|
||||
if (sysclk_source == RCC_SYSCLKSOURCE_PLLCLK) {
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "can't make valid freq"));
|
||||
|
||||
// re-init TIM3 for USB CDC rate
|
||||
timer_tim3_init();
|
||||
|
||||
return mp_const_none;
|
||||
|
||||
fail:;
|
||||
void NORETURN __fatal_error(const char *msg);
|
||||
__fatal_error("can't change freq");
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_freq_obj, 0, 1, pyb_freq);
|
||||
|
||||
@@ -41,9 +41,11 @@
|
||||
#include "runtime.h"
|
||||
#include "modnetwork.h"
|
||||
|
||||
/// \module usocket
|
||||
/// \module usocket - socket module
|
||||
///
|
||||
/// Socket functionality.
|
||||
|
||||
/// \method socket(family=AF_INET, type=SOCK_STREAM, fileno=-1)
|
||||
/// \function socket(family=AF_INET, type=SOCK_STREAM, fileno=-1)
|
||||
/// Create a socket.
|
||||
STATIC mp_obj_t mod_usocket_socket(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
@@ -75,7 +77,7 @@ STATIC mp_obj_t mod_usocket_socket(mp_uint_t n_args, const mp_obj_t *pos_args, m
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_usocket_socket_obj, 0, mod_usocket_socket);
|
||||
|
||||
/// \method getaddrinfo(host, port)
|
||||
/// \function getaddrinfo(host, port)
|
||||
STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
|
||||
mp_uint_t hlen;
|
||||
const char *host = mp_obj_str_get_data(host_in, &hlen);
|
||||
|
||||
@@ -48,21 +48,7 @@
|
||||
#include "ethernet/socket.h"
|
||||
#include "internet/dns/dns.h"
|
||||
|
||||
/// \module wiznet5k - control WIZnet5x00 Ethernet adaptors
|
||||
///
|
||||
/// This module allows you to control WIZnet5x00 Ethernet adaptors based on
|
||||
/// the W5200 and W5500 chipsets (only W5200 tested).
|
||||
///
|
||||
/// Example usage:
|
||||
///
|
||||
/// import wiznet5k
|
||||
/// w = wiznet5k.WIZnet5k()
|
||||
/// print(w.ipaddr())
|
||||
/// w.gethostbyname('micropython.org')
|
||||
/// s = w.socket()
|
||||
/// s.connect(('192.168.0.2', 8080))
|
||||
/// s.send('hello')
|
||||
/// print(s.recv(10))
|
||||
/// \moduleref network
|
||||
|
||||
#define IPADDR_BUF_SIZE (4)
|
||||
|
||||
@@ -164,6 +150,20 @@ STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len,
|
||||
// Micro Python bindings
|
||||
|
||||
/// \class WIZnet5k - driver for WIZnet5x00 Ethernet modules
|
||||
///
|
||||
/// This class allows you to control WIZnet5x00 Ethernet adaptors based on
|
||||
/// the W5200 and W5500 chipsets (only W5200 tested).
|
||||
///
|
||||
/// Example usage:
|
||||
///
|
||||
/// import wiznet5k
|
||||
/// w = wiznet5k.WIZnet5k()
|
||||
/// print(w.ipaddr())
|
||||
/// w.gethostbyname('micropython.org')
|
||||
/// s = w.socket()
|
||||
/// s.connect(('192.168.0.2', 8080))
|
||||
/// s.send('hello')
|
||||
/// print(s.recv(10))
|
||||
|
||||
STATIC void wiznet5k_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
print(env, "WIZnet5k()");
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
*/
|
||||
#define MICROPY_ENABLE_LFN (1)
|
||||
#define MICROPY_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
|
||||
#define MICROPY_STREAMS_NON_BLOCK (1)
|
||||
#define MICROPY_MODULE_WEAK_LINKS (1)
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
|
||||
|
||||
@@ -144,6 +144,7 @@ Q(baudrate)
|
||||
Q(bits)
|
||||
Q(stop)
|
||||
Q(parity)
|
||||
Q(flow)
|
||||
Q(read_buf_len)
|
||||
Q(buf)
|
||||
Q(len)
|
||||
@@ -155,6 +156,8 @@ Q(any)
|
||||
Q(writechar)
|
||||
Q(readchar)
|
||||
Q(readinto)
|
||||
Q(RTS)
|
||||
Q(CTS)
|
||||
|
||||
// for CAN class
|
||||
Q(CAN)
|
||||
@@ -167,6 +170,7 @@ Q(recv)
|
||||
Q(addr)
|
||||
Q(fifo)
|
||||
Q(timeout)
|
||||
Q(extframe)
|
||||
Q(NORMAL)
|
||||
Q(LOOPBACK)
|
||||
Q(SILENT)
|
||||
|
||||
@@ -65,10 +65,10 @@ void *memcpy(void *dst, const void *src, size_t n) {
|
||||
}
|
||||
|
||||
void *memmove(void *dest, const void *src, size_t n) {
|
||||
if (src < dest && dest < src + n) {
|
||||
if (src < dest && (uint8_t*)dest < (const uint8_t*)src + n) {
|
||||
// need to copy backwards
|
||||
uint8_t *d = dest + n - 1;
|
||||
const uint8_t *s = src + n - 1;
|
||||
uint8_t *d = (uint8_t*)dest + n - 1;
|
||||
const uint8_t *s = (const uint8_t*)src + n - 1;
|
||||
for (; n > 0; n--) {
|
||||
*d-- = *s--;
|
||||
}
|
||||
|
||||
@@ -80,13 +80,14 @@
|
||||
|
||||
struct _pyb_uart_obj_t {
|
||||
mp_obj_base_t base;
|
||||
pyb_uart_t uart_id;
|
||||
bool is_enabled;
|
||||
UART_HandleTypeDef uart;
|
||||
UART_HandleTypeDef uart; // this is 17 words big
|
||||
IRQn_Type irqn;
|
||||
pyb_uart_t uart_id : 8;
|
||||
bool is_enabled : 1;
|
||||
byte char_width; // 0 for 7,8 bit chars, 1 for 9 bit chars
|
||||
uint16_t char_mask; // 0x7f for 7 bit, 0xff for 8 bit, 0x1ff for 9 bit
|
||||
uint16_t timeout; // timeout waiting for first char
|
||||
uint16_t timeout_char; // timeout waiting between chars
|
||||
uint16_t char_width; // 0 for 7,8 bit chars, 1 for 9 bit chars
|
||||
uint16_t read_buf_len; // len in chars; buf can hold len-1 chars
|
||||
volatile uint16_t read_buf_head; // indexes first empty slot
|
||||
uint16_t read_buf_tail; // indexes first full slot (not full if equals head)
|
||||
@@ -115,7 +116,7 @@ void uart_deinit(void) {
|
||||
}
|
||||
|
||||
// assumes Init parameters have been set up correctly
|
||||
bool uart_init2(pyb_uart_obj_t *uart_obj) {
|
||||
STATIC bool uart_init2(pyb_uart_obj_t *uart_obj) {
|
||||
USART_TypeDef *UARTx;
|
||||
IRQn_Type irqn;
|
||||
uint32_t GPIO_Pin;
|
||||
@@ -140,7 +141,7 @@ bool uart_init2(pyb_uart_obj_t *uart_obj) {
|
||||
__USART1_CLK_ENABLE();
|
||||
break;
|
||||
|
||||
// USART2 is on PA2/PA3 (CK on PA4), PD5/PD6 (CK on PD7)
|
||||
// USART2 is on PA2/PA3 (CTS,RTS,CK on PA0,PA1,PA4), PD5/PD6 (CK on PD7)
|
||||
case PYB_UART_2:
|
||||
UARTx = USART2;
|
||||
irqn = USART2_IRQn;
|
||||
@@ -149,10 +150,17 @@ bool uart_init2(pyb_uart_obj_t *uart_obj) {
|
||||
GPIO_Port = GPIOA;
|
||||
GPIO_Pin = GPIO_PIN_2 | GPIO_PIN_3;
|
||||
|
||||
if (uart_obj->uart.Init.HwFlowCtl & UART_HWCONTROL_RTS) {
|
||||
GPIO_Pin |= GPIO_PIN_1;
|
||||
}
|
||||
if (uart_obj->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS) {
|
||||
GPIO_Pin |= GPIO_PIN_0;
|
||||
}
|
||||
|
||||
__USART2_CLK_ENABLE();
|
||||
break;
|
||||
|
||||
// USART3 is on PB10/PB11 (CK on PB12), PC10/PC11 (CK on PC12), PD8/PD9 (CK on PD10)
|
||||
// USART3 is on PB10/PB11 (CK,CTS,RTS on PB12,PB13,PB14), PC10/PC11 (CK on PC12), PD8/PD9 (CK on PD10)
|
||||
case PYB_UART_3:
|
||||
UARTx = USART3;
|
||||
irqn = USART3_IRQn;
|
||||
@@ -161,6 +169,13 @@ bool uart_init2(pyb_uart_obj_t *uart_obj) {
|
||||
#if defined(PYBV3) || defined(PYBV4) | defined(PYBV10)
|
||||
GPIO_Port = GPIOB;
|
||||
GPIO_Pin = GPIO_PIN_10 | GPIO_PIN_11;
|
||||
|
||||
if (uart_obj->uart.Init.HwFlowCtl & UART_HWCONTROL_RTS) {
|
||||
GPIO_Pin |= GPIO_PIN_14;
|
||||
}
|
||||
if (uart_obj->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS) {
|
||||
GPIO_Pin |= GPIO_PIN_13;
|
||||
}
|
||||
#else
|
||||
GPIO_Port = GPIOD;
|
||||
GPIO_Pin = GPIO_PIN_8 | GPIO_PIN_9;
|
||||
@@ -266,7 +281,7 @@ int uart_rx_char(pyb_uart_obj_t *self) {
|
||||
return data;
|
||||
} else {
|
||||
// no buffering
|
||||
return self->uart.Instance->DR;
|
||||
return self->uart.Instance->DR & self->char_mask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,6 +316,7 @@ void uart_irq_handler(mp_uint_t uart_id) {
|
||||
|
||||
if (__HAL_UART_GET_FLAG(&self->uart, UART_FLAG_RXNE) != RESET) {
|
||||
int data = self->uart.Instance->DR; // clears UART_FLAG_RXNE
|
||||
data &= self->char_mask;
|
||||
if (self->read_buf_len != 0) {
|
||||
uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len;
|
||||
if (next_head != self->read_buf_tail) {
|
||||
@@ -326,9 +342,12 @@ STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void
|
||||
if (!self->is_enabled) {
|
||||
print(env, "UART(%u)", self->uart_id);
|
||||
} else {
|
||||
mp_int_t bits = (self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9);
|
||||
if (self->uart.Init.Parity != UART_PARITY_NONE) {
|
||||
bits -= 1;
|
||||
}
|
||||
print(env, "UART(%u, baudrate=%u, bits=%u, parity=",
|
||||
self->uart_id, self->uart.Init.BaudRate,
|
||||
self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9);
|
||||
self->uart_id, self->uart.Init.BaudRate, bits);
|
||||
if (self->uart.Init.Parity == UART_PARITY_NONE) {
|
||||
print(env, "None");
|
||||
} else {
|
||||
@@ -345,7 +364,7 @@ STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void
|
||||
/// Initialise the UART bus with the given parameters:
|
||||
///
|
||||
/// - `baudrate` is the clock rate.
|
||||
/// - `bits` is the number of bits per byte, 8 or 9.
|
||||
/// - `bits` is the number of bits per byte, 7, 8 or 9.
|
||||
/// - `parity` is the parity, `None`, 0 (even) or 1 (odd).
|
||||
/// - `stop` is the number of stop bits, 1 or 2.
|
||||
/// - `timeout` is the timeout in milliseconds to wait for the first character.
|
||||
@@ -357,6 +376,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
|
||||
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} },
|
||||
{ MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_HWCONTROL_NONE} },
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} },
|
||||
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_read_buf_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
|
||||
@@ -369,20 +389,40 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
|
||||
// set the UART configuration values
|
||||
memset(&self->uart, 0, sizeof(self->uart));
|
||||
UART_InitTypeDef *init = &self->uart.Init;
|
||||
|
||||
// baudrate
|
||||
init->BaudRate = args[0].u_int;
|
||||
init->WordLength = args[1].u_int == 8 ? UART_WORDLENGTH_8B : UART_WORDLENGTH_9B;
|
||||
|
||||
// parity
|
||||
mp_int_t bits = args[1].u_int;
|
||||
if (args[2].u_obj == mp_const_none) {
|
||||
init->Parity = UART_PARITY_NONE;
|
||||
} else {
|
||||
mp_int_t parity = mp_obj_get_int(args[2].u_obj);
|
||||
init->Parity = (parity & 1) ? UART_PARITY_ODD : UART_PARITY_EVEN;
|
||||
bits += 1; // STs convention has bits including parity
|
||||
}
|
||||
|
||||
// number of bits
|
||||
if (bits == 8) {
|
||||
init->WordLength = UART_WORDLENGTH_8B;
|
||||
} else if (bits == 9) {
|
||||
init->WordLength = UART_WORDLENGTH_9B;
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "unsupported combination of bits and parity"));
|
||||
}
|
||||
|
||||
// stop bits
|
||||
switch (args[3].u_int) {
|
||||
case 1: init->StopBits = UART_STOPBITS_1; break;
|
||||
default: init->StopBits = UART_STOPBITS_2; break;
|
||||
}
|
||||
|
||||
// flow control
|
||||
init->HwFlowCtl = args[4].u_int;
|
||||
|
||||
// extra config (not yet configurable)
|
||||
init->Mode = UART_MODE_TX_RX;
|
||||
init->HwFlowCtl = UART_HWCONTROL_NONE;
|
||||
init->OverSampling = UART_OVERSAMPLING_16;
|
||||
|
||||
// init UART (if it fails, it's because the port doesn't exist)
|
||||
@@ -391,19 +431,25 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
|
||||
}
|
||||
|
||||
// set timeouts
|
||||
self->timeout = args[4].u_int;
|
||||
self->timeout_char = args[5].u_int;
|
||||
self->timeout = args[5].u_int;
|
||||
self->timeout_char = args[6].u_int;
|
||||
|
||||
// setup the read buffer
|
||||
m_del(byte, self->read_buf, self->read_buf_len << self->char_width);
|
||||
if (init->WordLength == UART_WORDLENGTH_9B && init->Parity == UART_PARITY_NONE) {
|
||||
self->char_mask = 0x1ff;
|
||||
self->char_width = CHAR_WIDTH_9BIT;
|
||||
} else {
|
||||
if (init->WordLength == UART_WORDLENGTH_9B || init->Parity == UART_PARITY_NONE) {
|
||||
self->char_mask = 0xff;
|
||||
} else {
|
||||
self->char_mask = 0x7f;
|
||||
}
|
||||
self->char_width = CHAR_WIDTH_8BIT;
|
||||
}
|
||||
self->read_buf_head = 0;
|
||||
self->read_buf_tail = 0;
|
||||
if (args[6].u_int <= 0) {
|
||||
if (args[7].u_int <= 0) {
|
||||
// no read buffer
|
||||
self->read_buf_len = 0;
|
||||
self->read_buf = NULL;
|
||||
@@ -411,8 +457,8 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
|
||||
__HAL_UART_DISABLE_IT(&self->uart, UART_IT_RXNE);
|
||||
} else {
|
||||
// read buffer using interrupts
|
||||
self->read_buf_len = args[6].u_int;
|
||||
self->read_buf = m_new(byte, args[6].u_int << self->char_width);
|
||||
self->read_buf_len = args[7].u_int;
|
||||
self->read_buf = m_new(byte, args[7].u_int << self->char_width);
|
||||
__HAL_UART_ENABLE_IT(&self->uart, UART_IT_RXNE);
|
||||
HAL_NVIC_SetPriority(self->irqn, 0xd, 0xd); // next-to-next-to lowest priority
|
||||
HAL_NVIC_EnableIRQ(self->irqn);
|
||||
@@ -595,6 +641,10 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_writechar), (mp_obj_t)&pyb_uart_writechar_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readchar), (mp_obj_t)&pyb_uart_readchar_obj },
|
||||
|
||||
// class constants
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTS), MP_OBJ_NEW_SMALL_INT(UART_HWCONTROL_RTS) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_CTS), MP_OBJ_NEW_SMALL_INT(UART_HWCONTROL_CTS) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
|
||||
|
||||
55
stmhal/usb.c
@@ -24,7 +24,9 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_desc.h"
|
||||
@@ -40,6 +42,7 @@
|
||||
#include "stream.h"
|
||||
#include "bufhelper.h"
|
||||
#include "usb.h"
|
||||
#include "pybioctl.h"
|
||||
|
||||
#ifdef USE_DEVICE_MODE
|
||||
USBD_HandleTypeDef hUSBDDevice;
|
||||
@@ -243,16 +246,6 @@ STATIC mp_obj_t pyb_usb_vcp_recv(mp_uint_t n_args, const mp_obj_t *args, mp_map_
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_vcp_recv_obj, 1, pyb_usb_vcp_recv);
|
||||
|
||||
STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
int ret = USBD_CDC_Rx((byte*)buf, size, -1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||
int ret = USBD_CDC_Tx((const byte*)buf, size, -1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mp_obj_t pyb_usb_vcp___exit__(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
return mp_const_none;
|
||||
}
|
||||
@@ -279,9 +272,51 @@ STATIC const mp_map_elem_t pyb_usb_vcp_locals_dict_table[] = {
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_usb_vcp_locals_dict, pyb_usb_vcp_locals_dict_table);
|
||||
|
||||
STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
int ret = USBD_CDC_Rx((byte*)buf, size, 0);
|
||||
if (ret == 0) {
|
||||
// return EAGAIN error to indicate non-blocking
|
||||
*errcode = EAGAIN;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||
int ret = USBD_CDC_Tx((const byte*)buf, size, 0);
|
||||
if (ret == 0) {
|
||||
// return EAGAIN error to indicate non-blocking
|
||||
*errcode = EAGAIN;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t pyb_usb_vcp_ioctl(mp_obj_t self_in, mp_uint_t request, int *errcode, ...) {
|
||||
va_list vargs;
|
||||
va_start(vargs, errcode);
|
||||
mp_uint_t ret;
|
||||
if (request == MP_IOCTL_POLL) {
|
||||
mp_uint_t flags = va_arg(vargs, mp_uint_t);
|
||||
ret = 0;
|
||||
if ((flags & MP_IOCTL_POLL_RD) && USBD_CDC_RxNum() > 0) {
|
||||
ret |= MP_IOCTL_POLL_RD;
|
||||
}
|
||||
if ((flags & MP_IOCTL_POLL_WR) && USBD_CDC_TxHalfEmpty()) {
|
||||
ret |= MP_IOCTL_POLL_WR;
|
||||
}
|
||||
} else {
|
||||
*errcode = EINVAL;
|
||||
ret = MP_STREAM_ERROR;
|
||||
}
|
||||
va_end(vargs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC const mp_stream_p_t pyb_usb_vcp_stream_p = {
|
||||
.read = pyb_usb_vcp_read,
|
||||
.write = pyb_usb_vcp_write,
|
||||
.ioctl = pyb_usb_vcp_ioctl,
|
||||
};
|
||||
|
||||
const mp_obj_type_t pyb_usb_vcp_type = {
|
||||
|
||||
@@ -402,6 +402,14 @@ void USBD_CDC_SetInterrupt(int chr, void *data) {
|
||||
user_interrupt_data = data;
|
||||
}
|
||||
|
||||
int USBD_CDC_TxHalfEmpty(void) {
|
||||
int32_t tx_waiting = (int32_t)UserTxBufPtrIn - (int32_t)UserTxBufPtrOut;
|
||||
if (tx_waiting < 0) {
|
||||
tx_waiting += APP_TX_DATA_SIZE;
|
||||
}
|
||||
return tx_waiting <= APP_TX_DATA_SIZE / 2;
|
||||
}
|
||||
|
||||
// timout in milliseconds.
|
||||
// Returns number of bytes written to the device.
|
||||
int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout) {
|
||||
|
||||
@@ -37,6 +37,7 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void);
|
||||
int USBD_CDC_IsConnected(void);
|
||||
void USBD_CDC_SetInterrupt(int chr, void *data);
|
||||
|
||||
int USBD_CDC_TxHalfEmpty(void);
|
||||
int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout);
|
||||
void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ INC += -I../stmhal
|
||||
INC += -I$(BUILD)
|
||||
INC += -Icore
|
||||
|
||||
CFLAGS = $(INC) -Wall -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4)
|
||||
CFLAGS = $(INC) -Wall -Wpointer-arith -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4)
|
||||
LDFLAGS = -nostdlib -T mk20dx256.ld -msoft-float -mfloat-abi=soft
|
||||
|
||||
ifeq ($(USE_ARDUINO_TOOLCHAIN),1)
|
||||
|
||||
@@ -1,5 +1,43 @@
|
||||
import sys
|
||||
# test builtin callable
|
||||
|
||||
# primitives should not be callable
|
||||
print(callable(None))
|
||||
print(callable(1))
|
||||
print(callable([]))
|
||||
print(callable("dfsd"))
|
||||
print(callable(callable))
|
||||
|
||||
# modules should not be callabe
|
||||
import sys
|
||||
print(callable(sys))
|
||||
|
||||
# builtins should be callable
|
||||
print(callable(callable))
|
||||
|
||||
# lambdas should be callable
|
||||
print(callable(lambda:None))
|
||||
|
||||
# user defined functions should be callable
|
||||
def f():
|
||||
pass
|
||||
print(callable(f))
|
||||
|
||||
# types should be callable, but not instances
|
||||
class A:
|
||||
pass
|
||||
print(callable(A))
|
||||
print(callable(A()))
|
||||
|
||||
# instances with __call__ method should be callable
|
||||
class B:
|
||||
def __call__(self):
|
||||
pass
|
||||
print(callable(B()))
|
||||
|
||||
# this checks internal use of callable when extracting members from an instance
|
||||
class C:
|
||||
def f(self):
|
||||
return "A.f"
|
||||
class D:
|
||||
g = C() # g is a value and is not callable
|
||||
print(callable(D().g))
|
||||
print(D().g.f())
|
||||
|
||||
14
tests/basics/builtin_round.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# test round()
|
||||
|
||||
# check basic cases
|
||||
tests = [
|
||||
False, True,
|
||||
0, 1, -1, 10,
|
||||
0.0, 1.0, 0.1, -0.1, 123.4, 123.6, -123.4, -123.6
|
||||
]
|
||||
for t in tests:
|
||||
print(round(t))
|
||||
|
||||
# check .5 cases
|
||||
for i in range(11):
|
||||
print(round((i - 5) / 2))
|
||||
@@ -18,6 +18,8 @@ print(a[1:])
|
||||
print(a[:-1])
|
||||
print(a[2:3])
|
||||
|
||||
print(str(bytearray(b"123"), "utf-8"))
|
||||
|
||||
# Comparisons
|
||||
print(bytearray([1]) == bytearray([1]))
|
||||
print(bytearray([1]) == bytearray([2]))
|
||||
|
||||
@@ -48,3 +48,17 @@ a -= 1
|
||||
print(a)
|
||||
# This would overflow
|
||||
#a -= 1
|
||||
|
||||
|
||||
# Shifts to big amounts are undefined behavior in C and is CPU-specific
|
||||
|
||||
# These are compile-time constexprs
|
||||
print(1 >> 32)
|
||||
print(1 >> 64)
|
||||
print(1 >> 128)
|
||||
|
||||
# These are runtime calcs
|
||||
a = 1
|
||||
print(a >> 32)
|
||||
print(a >> 64)
|
||||
print(a >> 128)
|
||||
|
||||
15
tests/extmod/uctypes_bytearray.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import uctypes
|
||||
|
||||
desc = {
|
||||
"arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2),
|
||||
"arr2": (uctypes.ARRAY | 2, uctypes.INT8 | 2),
|
||||
}
|
||||
|
||||
data = bytearray(b"01234567")
|
||||
|
||||
S = uctypes.struct(desc, uctypes.addressof(data), uctypes.LITTLE_ENDIAN)
|
||||
|
||||
# Arrays of UINT8 are accessed as bytearrays
|
||||
print(S.arr)
|
||||
# But not INT8, because value range is different
|
||||
print(type(S.arr2))
|
||||