Merge tag 'v1.8.4' into parse-bytecode
Support for stream decompression in uzlib, and more ESP8266 features This release includes some bug fixes, code clean-up, updates to the docs, more tests, and various feature additions. The uzlib module now supports efficient stream decompression in the form of the uzlib.DecompIO class. Freezing of bytecode now supports floats for the ESP8266 port, as well as complex numbers for all ports. The stmhal port has ADC working on L4 microcontrollers, fixed initialisation for DAC, and addition of the machine.WDT class and machine.reset_cause function. For the ESP8266 port Pin(16) now works as an input pin and the hardware SPI peripheral is exposed as machine.SPI(1). The os.umount function is implemented and the port supports mounting of externally connected SD cards. The machine.WDT class is added, wlan.scan() is fixed to return all access points, and there is support for DS18S20 devices. py core: - runtime: factor out exception raising helpers - runtime: define mp_check_self(pred) helper macro - objdict: get rid of asserts (remove/replace with mp_check_self()) - get rid of assert() in method argument checking functions - objtuple: in tuple_cmp_helper, use mp_check_self instead of raising - objstr: use mp_raise_{Type,Value}Error instead of mp_raise_msg - obj.h: for obj reprs A,B,C use void* explicitly for mp_obj_t typedef - mpconfigport.h: remove typedef of machine_ptr_t, it's no longer needed - sequence: allow to use bignums as indices in slice objects - stream.c: use mp_obj_get_type in mp_get_stream_raise - gc: add MICROPY_GC_CONSERVATIVE_CLEAR option to always zero memory - compile: don't compile assert statements when optimisations enabled - modstruct: use more compact mp_raise_ValueError function - emitglue: use more compact mp_raise_ValueError function - rename struct mp_code_state to mp_code_state_t - mkrules.mk: allow to override name of libmicropython.a - mpprint: fail an assertion with unsupported format specifiers - makeqstrdata.py: compute the qstr hash from bytes, not characters - if str/bytes hash is 0 then explicitly compute it - emitglue.c: provide mp_raw_code_load_file for any unix architecture - add MICROPY_USE_INTERNAL_PRINTF option, defaults to enabled extmod: - modwebrepl: set_password(): raise exception for too long password - uzlib/: update uzlib to v2.0: new API supporting stream decompression - moduzlib: refactor to new stream-compatible uzlib 2.0 API - uzlib/: update uzlib to v2.0.1: fixes for pedantic compiler warnings - uzlib/: update uzlib to v2.0.2: consistently use stdint types - modbtree: do CHECK_ERROR after __bt_seq() - modubinascii: implement binascii.crc32 - modubinascii: make crc32() support configurable - modframebuf: fix pixel accessor to return a 1-bit result - add machine_spi with generic SPI C-protocol and helper methods - modframebuf: fix fill and scroll when height not divisible by 8 - moduzlib: implement zlib stream decompressor class, DecompIO - moduzlib: use mperrno.h for error constants - modframebuf: include font from stmhal directory explicitly - moduzlib: support wbits arg to DecompIO - framebuf: add the xstep!=0 case to scroll() method lib: - utils/stdout_helpers: fix function signature to match py/mphal.h - berkeley-db-1.xx: update to upstream, fixes MacOSX build - utils/pyexec: qstr_pool_info() requires size_t* parameters drivers: - sdcard: port the SDCard driver to new machine API, with backwards compatibility for pyboard tools: - mpy-tool.py: support freezing float literals with obj-repr C - mpy-tool.py: store qstr config values in global config object - mpy-tool.py: compute the hash value for str/bytes objects - mpy-tool.py: support freezing of complex numbers tests: - rename zlibd_decompress.py -> uzlib_decompress.py - basics: add more tuple tests to improve coverage testing - basics: add more list tests to improve coverage testing - misc/non_compliant: add tests to improve coverage testing - basics: add test for break from within try within a for-loop - basics: add a test file for overriding special methods - basics/special_methods: enable tests for extra special methods - uzlib_decompress: actually test raw DEFLATE stream - run-tests: disable thread/thread_lock4.py on Travis - run-tests: disable thread/stress_heap.py when running on Travis - cmdline: add test for -O option to check optimisation value - extmod/vfs_fat_ramdisk: add tests for VFS.umount() - run-tests: disable thread_gc1.py test on Travis - unix/extra_coverage: add test for str/bytes with invalid hash - extmod: add test for uzlib.DecompIO - extmod: add a test for framebuf module, tested by coverage build - extmod/uzlib_decompio: add zlib bitstream testcases - extmod/framebuf1: add tests for scrolling in the x-direction - run-tests: disable thread/stress_recurse.py test on Travis unix port: - mpconfigport.h: don't include stdio.h on MacOS - when find'ing frozen files don't use extra slash, do follow symlinks qemu-arm port: - enable MICROPY_PY_ALL_SPECIAL_METHODS stmhal port: - boards: update STM32L476 pin defs to include ADC channels - adc.c: get ADC working on STM32L4 MCUs - fix timer capture/compare interrupt handling for TIM1 and TIM8 - remove obsolete code for special handling of TIM3 irq settings - make ADC channel 16 available on L4 MCUs - update pin print to print new constants - modusocket: set self->nic to MP_OBJ_NULL after socket close - update boot.py files to use VCP instead of CDC - spi: factor out SPI transfer code to a single function - spi: support new machine SPI methods in legacy SPI object - add machine.WDT class - set STM32F7DISC CPU Frequency to 216 MHz - dac: fix DAC (re-)initialisation by resetting DMA - wdt: implement keyword args to WDT constructor - modmachine: implement machine.reset_cause() function, and consts - machine.POWER_ON is renamed to machine.PWRON_RESET - when find'ing frozen files don't use extra slash, do follow symlinks cc3200 port: - add machine.PWRON_RESET constant (machine.POWER_ON is now deprecated) teensy port: - fix execution of frozen boot.py and main.py esp8266 port: - fix reading of pin object for GPIO16; Pin(16) now works as an input - PULL_UP is not supported on Pin(16), so raise an exception in this case - enable support for all special methods - modpybhspi: add a HSPI module for hardware SPI support - modmachinespi: add a factory method for SoftSPI/HSPI - esp_mphal: no longer disable watchdog on startup - modpybrtc: use 64-bit arithmetic when computing alarm expiry - hspi: enable duplex operation of hardware SPI - modous: add os.umount method to unmount a filesystem - modmachinewdt: implement machine.WDT class - modules: split onewire.py into OneWire and DS18X20 driver - modules/onewire: change onewire.read() to onewire.readinto() - modules/ds18x20.py: add support for DS18S20 devices - modpybspi: use generic SPI helper methods to implement SPI - modpybhspi: simplify HSPI driver by using 1 function for xfers - modmachinewdt: add .deinit() method - modmachine: add WDT_RESET and SOFT_RESET constants - modmachine: don't expose internal SoftSPI and HSPI classes - modmachine: simplify SPI class implementation multiplexing - espneopixel: disable IRQs during eps.neopixel_write - modnetwork: fix wlan.scan() method so it returns all networks - modmachine: map PWR_ON_RESET to vendor's REASON_DEFAULT_RST - machine.PWR_ON_RESET is renamed to machine.PWRON_RESET - when find'ing frozen files don't use extra slash, do follow symlinks docs: - esp8266/tutorial/pins: fix typo in commands for pin input mode - esp8266/intro: add command to install esptool.py 1.0.1 via pip - library/machine.WDT: add note that WDT is only available on WiPy - esp8266/quickref: fix and update the SPI docs - esp8266: update quickref and tutorial for OneWire/DS18X20 driver - pyboard: update USB mouse tutorial to use VCP instead of CDC - pyboard: update USB mouse tutorial to use pyb.USB_HID() - library: add reference for pyb.usb_mode and pyb.USB_HID - pyboard/quickref: add links to pinouts for other pyboard variants - pyboard/quickref: add section on "delay and timing" for utime mod - esp8266/quickref: add internal links to docs for some modules - esp8266/quickref: update information on SPI classes - esp8266/quickref: further improvements for SPI subsections - library/machine.WDT: add that WDT is available on pyboard - reference/isr_rules.rst: two minor additions to docs for using ISR misc: - add *.pyc to .gitignore, because Python 2 doesn't use __pycache__ - build mpy-cross as part of the Travis process
This commit is contained in:
commit
1db008349c
|
@ -32,6 +32,7 @@ tests/*.out
|
|||
# Python cache files
|
||||
######################
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Customized Makefile/project overrides
|
||||
######################
|
||||
|
|
|
@ -23,6 +23,7 @@ before_script:
|
|||
- python3 --version
|
||||
|
||||
script:
|
||||
- make -C mpy-cross
|
||||
- make -C minimal test
|
||||
- make -C unix deplibs
|
||||
- make -C unix
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#define MICROPY_CPYTHON_COMPAT (0)
|
||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
|
||||
#define MICROPY_USE_INTERNAL_PRINTF (0)
|
||||
|
||||
// type definitions for the specific machine
|
||||
|
||||
|
@ -54,8 +55,6 @@
|
|||
|
||||
typedef int32_t mp_int_t; // must be pointer size
|
||||
typedef uint32_t mp_uint_t; // must be pointer size
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
typedef long mp_off_t;
|
||||
|
||||
// dummy print
|
||||
|
|
|
@ -154,7 +154,6 @@ APP_LIB_SRC_C = $(addprefix lib/,\
|
|||
timeutils/timeutils.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/printf.c \
|
||||
)
|
||||
|
||||
APP_STM_SRC_C = $(addprefix stmhal/,\
|
||||
|
|
|
@ -198,7 +198,8 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = {
|
|||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IDLE), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_ACTIVE) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_LPDS) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_HIBERNATE) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) }, // legacy constant
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PWRON_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HARD_RESET) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WDT_RESET) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HIB_RESET) },
|
||||
|
|
|
@ -185,8 +185,6 @@ extern const struct _mp_obj_module_t mp_module_ussl;
|
|||
|
||||
typedef int32_t mp_int_t; // must be pointer size
|
||||
typedef unsigned int mp_uint_t; // must be pointer size
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
typedef long mp_off_t;
|
||||
|
||||
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
|
||||
|
|
|
@ -99,7 +99,7 @@ copyright = '2014-2016, Damien P. George and contributors'
|
|||
# The short X.Y version.
|
||||
version = '1.8'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.8.3'
|
||||
release = '1.8.4'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
@ -23,14 +23,14 @@ Tab-completion is useful to find out what methods an object has.
|
|||
Paste mode (ctrl-E) is useful to paste a large slab of Python code into
|
||||
the REPL.
|
||||
|
||||
The ``machine`` module::
|
||||
The :mod:`machine` module::
|
||||
|
||||
import machine
|
||||
|
||||
machine.freq() # get the current frequency of the CPU
|
||||
machine.freq(160000000) # set the CPU frequency to 160 MHz
|
||||
|
||||
The ``esp`` module::
|
||||
The :mod:`esp` module::
|
||||
|
||||
import esp
|
||||
|
||||
|
@ -40,7 +40,7 @@ The ``esp`` module::
|
|||
Networking
|
||||
----------
|
||||
|
||||
The ``network`` module::
|
||||
The :mod:`network` module::
|
||||
|
||||
import network
|
||||
|
||||
|
@ -69,13 +69,13 @@ A useful function for connecting to your local WiFi network is::
|
|||
pass
|
||||
print('network config:', wlan.ifconfig())
|
||||
|
||||
Once the network is established the ``socket`` module can be used
|
||||
Once the network is established the :mod:`socket <usocket>` module can be used
|
||||
to create and use TCP/UDP sockets as usual.
|
||||
|
||||
Delay and timing
|
||||
----------------
|
||||
|
||||
Use the ``time`` module::
|
||||
Use the :mod:`time <utime>` module::
|
||||
|
||||
import time
|
||||
|
||||
|
@ -162,17 +162,18 @@ Use the ``machine.ADC`` class::
|
|||
adc = ADC(0) # create ADC object on ADC pin
|
||||
adc.read() # read value, 0-1024
|
||||
|
||||
SPI bus
|
||||
-------
|
||||
Software SPI bus
|
||||
----------------
|
||||
|
||||
The SPI driver is implemented in software and works on all pins::
|
||||
There are two SPI drivers. One is implemented in software (bit-banging)
|
||||
and works on all pins::
|
||||
|
||||
from machine import Pin, SPI
|
||||
|
||||
# construct an SPI bus on the given pins
|
||||
# polarity is the idle state of SCK
|
||||
# phase=0 means sample on the first edge of SCK, phase=1 means the second
|
||||
spi = SPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
|
||||
spi = SPI(-1, baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
|
||||
|
||||
spi.init(baudrate=200000) # set the baudrate
|
||||
|
||||
|
@ -189,6 +190,21 @@ The SPI driver is implemented in software and works on all pins::
|
|||
spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer
|
||||
spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf
|
||||
|
||||
|
||||
Hardware SPI bus
|
||||
----------------
|
||||
|
||||
The hardware SPI is faster (up to 80Mhz), but only works on following pins:
|
||||
``MISO`` is GPIO12, ``MOSI`` is GPIO13, and ``SCK`` is GPIO14. It has the same
|
||||
methods as the bitbanging SPI class above, except for the pin parameters for the
|
||||
constructor and init (as those are fixed)::
|
||||
|
||||
from machine import Pin, SPI
|
||||
|
||||
hspi = SPI(1, baudrate=80000000, polarity=0, phase=0)
|
||||
|
||||
(``SPI(0)`` is used for FlashROM and not available to users.)
|
||||
|
||||
I2C bus
|
||||
-------
|
||||
|
||||
|
@ -239,15 +255,14 @@ The OneWire driver is implemented in software and works on all pins::
|
|||
ow.scan() # return a list of devices on the bus
|
||||
ow.reset() # reset the bus
|
||||
ow.readbyte() # read a byte
|
||||
ow.read(5) # read 5 bytes
|
||||
ow.writebyte(0x12) # write a byte on the bus
|
||||
ow.write('123') # write bytes on the bus
|
||||
ow.select_rom(b'12345678') # select a specific device by its ROM code
|
||||
|
||||
There is a specific driver for DS18B20 devices::
|
||||
There is a specific driver for DS18S20 and DS18B20 devices::
|
||||
|
||||
import time
|
||||
ds = onewire.DS18B20(ow)
|
||||
import time, ds18x20
|
||||
ds = ds18x20.DS18X20(ow)
|
||||
roms = ds.scan()
|
||||
ds.convert_temp()
|
||||
time.sleep_ms(750)
|
||||
|
|
|
@ -135,6 +135,10 @@ after it, here are troubleshooting recommendations:
|
|||
rate may be too high and lead to errors. Try a more common 115200 baud
|
||||
rate instead in such cases.
|
||||
|
||||
* If lower baud rate didn't help, you may want to try older version of
|
||||
esptool.py, which had a different programming algorithm::
|
||||
pip install esptool==1.0.1
|
||||
|
||||
* The ``--flash_size`` option in the commands above is mandatory. Omitting
|
||||
it will lead to a corrupted firmware.
|
||||
|
||||
|
|
|
@ -6,19 +6,19 @@ The 1-wire bus is a serial bus that uses just a single wire for communication
|
|||
is a very popular 1-wire device, and here we show how to use the onewire module
|
||||
to read from such a device.
|
||||
|
||||
For the following code to work you need to have at least one DS18B20 temperature
|
||||
For the following code to work you need to have at least one DS18S20 or DS18B20 temperature
|
||||
sensor with its data line connected to GPIO12. You must also power the sensors
|
||||
and connect a 4.7k Ohm resistor between the data pin and the power pin. ::
|
||||
|
||||
import time
|
||||
import machine
|
||||
import onewire
|
||||
import onewire, ds18x20
|
||||
|
||||
# the device is on GPIO12
|
||||
dat = machine.Pin(12)
|
||||
|
||||
# create the onewire object
|
||||
ds = onewire.DS18B20(onewire.OneWire(dat))
|
||||
ds = ds18x20.DS18X20(onewire.OneWire(dat))
|
||||
|
||||
# scan for devices on the bus
|
||||
roms = ds.scan()
|
||||
|
|
|
@ -14,7 +14,7 @@ Here, the "0" is the pin that you want to access. Usually you want to
|
|||
configure the pin to be input or output, and you do this when constructing
|
||||
it. To make an input pin use::
|
||||
|
||||
>>> pin = machine.Pin(0, machine.Pin.OUT, machine.Pin.PULL_UP)
|
||||
>>> pin = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)
|
||||
|
||||
You can either use PULL_UP or None for the input pull-mode. If it's
|
||||
not specified then it defaults to None, which is no pull resistor.
|
||||
|
|
|
@ -14,6 +14,8 @@ Example usage::
|
|||
wdt = WDT(timeout=2000) # enable it with a timeout of 2s
|
||||
wdt.feed()
|
||||
|
||||
Availability of this class: pyboard, WiPy.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ Constants
|
|||
|
||||
irq wake values
|
||||
|
||||
.. data:: machine.POWER_ON
|
||||
.. data:: machine.PWRON_RESET
|
||||
.. data:: machine.HARD_RESET
|
||||
.. data:: machine.WDT_RESET
|
||||
.. data:: machine.DEEPSLEEP_RESET
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
.. currentmodule:: pyb
|
||||
|
||||
class USB_HID -- USB Human Interface Device (HID)
|
||||
=================================================
|
||||
|
||||
The USB_HID class allows creation of an object representing the USB
|
||||
Human Interface Device (HID) interface. It can be used to emulate
|
||||
a peripheral such as a mouse or keyboard.
|
||||
|
||||
Before you can use this class, you need to use :meth:`pyb.usb_mode()` to set the USB mode to include the HID interface.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.USB_HID()
|
||||
|
||||
Create a new USB_HID object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: USB_HID.send(data)
|
||||
|
||||
Send data over the USB HID interface:
|
||||
|
||||
- ``data`` is the data to send (a tuple/list of integers, or a
|
||||
bytearray).
|
|
@ -188,7 +188,7 @@ Miscellaneous functions
|
|||
Takes a 4-tuple (or list) and sends it to the USB host (the PC) to
|
||||
signal a HID mouse-motion event.
|
||||
|
||||
.. note:: This function is deprecated. Use pyb.USB_HID().send(...) instead.
|
||||
.. note:: This function is deprecated. Use :meth:`pyb.USB_HID.send()` instead.
|
||||
|
||||
.. function:: info([dump_alloc_table])
|
||||
|
||||
|
@ -254,6 +254,33 @@ Miscellaneous functions
|
|||
|
||||
Returns a string of 12 bytes (96 bits), which is the unique ID of the MCU.
|
||||
|
||||
.. function:: usb_mode([modestr], vid=0xf055, pid=0x9801, hid=pyb.hid_mouse)
|
||||
|
||||
If called with no arguments, return the current USB mode as a string.
|
||||
|
||||
If called with ``modestr`` provided, attempts to set USB mode.
|
||||
This can only be done when called from ``boot.py`` before
|
||||
:meth:`pyb.main()` has been called. The following values of
|
||||
``modestr`` are understood:
|
||||
|
||||
- ``None``: disables USB
|
||||
- ``'VCP'``: enable with VCP (Virtual COM Port) interface
|
||||
- ``'VCP+MSC'``: enable with VCP and MSC (mass storage device class)
|
||||
- ``'VCP+HID'``: enable with VCP and HID (human interface device)
|
||||
|
||||
For backwards compatibility, ``'CDC'`` is understood to mean
|
||||
``'VCP'`` (and similarly for ``'CDC+MSC'`` and ``'CDC+HID'``).
|
||||
|
||||
The ``vid`` and ``pid`` parameters allow you to specify the VID
|
||||
(vendor id) and PID (product id).
|
||||
|
||||
If enabling HID mode, you may also specify the HID details by
|
||||
passing the ``hid`` keyword parameter. It takes a tuple of
|
||||
(subclass, protocol, max packet length, polling interval, report
|
||||
descriptor). By default it will set appropriate values for a USB
|
||||
mouse. There is also a ``pyb.hid_keyboard`` constant, which is an
|
||||
appropriate tuple for a USB keyboard.
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
|
@ -277,4 +304,5 @@ Classes
|
|||
pyb.Switch.rst
|
||||
pyb.Timer.rst
|
||||
pyb.UART.rst
|
||||
pyb.USB_HID.rst
|
||||
pyb.USB_VCP.rst
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
Quick reference for the pyboard
|
||||
===============================
|
||||
|
||||
The below pinout is for PYBv1.0. You can also view pinouts for
|
||||
other versions of the pyboard:
|
||||
`PYBv1.1 <http://micropython.org/resources/pybv11-pinout.jpg>`__
|
||||
or `PYBLITEv1.0-AC <http://micropython.org/resources/pyblitev10ac-pinout.jpg>`__
|
||||
or `PYBLITEv1.0 <http://micropython.org/resources/pyblitev10-pinout.jpg>`__.
|
||||
|
||||
.. image:: http://micropython.org/resources/pybv10-pinout.jpg
|
||||
:alt: PYBv1.0 pinout
|
||||
:width: 700px
|
||||
|
@ -14,14 +20,25 @@ See :mod:`pyb`. ::
|
|||
|
||||
import pyb
|
||||
|
||||
pyb.delay(50) # wait 50 milliseconds
|
||||
pyb.millis() # number of milliseconds since bootup
|
||||
pyb.repl_uart(pyb.UART(1, 9600)) # duplicate REPL on UART(1)
|
||||
pyb.wfi() # pause CPU, waiting for interrupt
|
||||
pyb.freq() # get CPU and bus frequencies
|
||||
pyb.freq(60000000) # set CPU freq to 60MHz
|
||||
pyb.stop() # stop CPU, waiting for external interrupt
|
||||
|
||||
Delay and timing
|
||||
----------------
|
||||
|
||||
Use the :mod:`time <utime>` module::
|
||||
|
||||
import time
|
||||
|
||||
time.sleep(1) # sleep for 1 second
|
||||
time.sleep_ms(500) # sleep for 500 milliseconds
|
||||
time.sleep_us(10) # sleep for 10 microseconds
|
||||
start = time.ticks_ms() # get value of millisecond counter
|
||||
delta = time.ticks_diff(start, time.ticks_ms()) # compute time difference
|
||||
|
||||
LEDs
|
||||
----
|
||||
|
||||
|
|
|
@ -13,23 +13,23 @@ will look something like this::
|
|||
|
||||
import pyb
|
||||
#pyb.main('main.py') # main script to run after this one
|
||||
#pyb.usb_mode('CDC+MSC') # act as a serial and a storage device
|
||||
#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
|
||||
#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device
|
||||
#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
|
||||
|
||||
To enable the mouse mode, uncomment the last line of the file, to
|
||||
make it look like::
|
||||
|
||||
pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
|
||||
pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
|
||||
|
||||
If you already changed your ``boot.py`` file, then the minimum code it
|
||||
needs to work is::
|
||||
|
||||
import pyb
|
||||
pyb.usb_mode('CDC+HID')
|
||||
pyb.usb_mode('VCP+HID')
|
||||
|
||||
This tells the pyboard to configure itself as a CDC (serial) and HID
|
||||
(human interface device, in our case a mouse) USB device when it boots
|
||||
up.
|
||||
This tells the pyboard to configure itself as a VCP (Virtual COM Port,
|
||||
ie serial port) and HID (human interface device, in our case a mouse)
|
||||
USB device when it boots up.
|
||||
|
||||
Eject/unmount the pyboard drive and reset it using the RST switch.
|
||||
Your PC should now detect the pyboard as a mouse!
|
||||
|
@ -41,7 +41,8 @@ To get the py-mouse to do anything we need to send mouse events to the PC.
|
|||
We will first do this manually using the REPL prompt. Connect to your
|
||||
pyboard using your serial program and type the following::
|
||||
|
||||
>>> pyb.hid((0, 10, 0, 0))
|
||||
>>> hid = pyb.USB_HID()
|
||||
>>> hid.send((0, 10, 0, 0))
|
||||
|
||||
Your mouse should move 10 pixels to the right! In the command above you
|
||||
are sending 4 pieces of information: button status, x, y and scroll. The
|
||||
|
@ -52,7 +53,7 @@ Let's make the mouse oscillate left and right::
|
|||
>>> import math
|
||||
>>> def osc(n, d):
|
||||
... for i in range(n):
|
||||
... pyb.hid((0, int(20 * math.sin(i / 10)), 0, 0))
|
||||
... hid.send((0, int(20 * math.sin(i / 10)), 0, 0))
|
||||
... pyb.delay(d)
|
||||
...
|
||||
>>> osc(100, 50)
|
||||
|
@ -100,9 +101,10 @@ In ``main.py`` put the following code::
|
|||
|
||||
switch = pyb.Switch()
|
||||
accel = pyb.Accel()
|
||||
hid = pyb.USB_HID()
|
||||
|
||||
while not switch():
|
||||
pyb.hid((0, accel.x(), accel.y(), 0))
|
||||
hid.send((0, accel.x(), accel.y(), 0))
|
||||
pyb.delay(20)
|
||||
|
||||
Save your file, eject/unmount your pyboard drive, and reset it using the RST
|
||||
|
@ -112,7 +114,7 @@ the mouse around. Try it out, and see if you can make the mouse stand still!
|
|||
Press the USR switch to stop the mouse motion.
|
||||
|
||||
You'll note that the y-axis is inverted. That's easy to fix: just put a
|
||||
minus sign in front of the y-coordinate in the ``pyb.hid()`` line above.
|
||||
minus sign in front of the y-coordinate in the ``hid.send()`` line above.
|
||||
|
||||
Restoring your pyboard to normal
|
||||
--------------------------------
|
||||
|
@ -121,9 +123,9 @@ If you leave your pyboard as-is, it'll behave as a mouse everytime you plug
|
|||
it in. You probably want to change it back to normal. To do this you need
|
||||
to first enter safe mode (see above), and then edit the ``boot.py`` file.
|
||||
In the ``boot.py`` file, comment out (put a # in front of) the line with the
|
||||
``CDC+HID`` setting, so it looks like::
|
||||
``VCP+HID`` setting, so it looks like::
|
||||
|
||||
#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
|
||||
#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
|
||||
|
||||
Save your file, eject/unmount the drive, and reset the pyboard. It is now
|
||||
back to normal operating mode.
|
||||
|
|
|
@ -110,6 +110,19 @@ the flag. The memory allocation occurs in the main program code when the object
|
|||
The MicroPython library I/O methods usually provide an option to use a pre-allocated buffer. For
|
||||
example ``pyb.i2c.recv()`` can accept a mutable buffer as its first argument: this enables its use in an ISR.
|
||||
|
||||
A means of creating an object without employing a class or globals is as follows:
|
||||
|
||||
.. code:: python
|
||||
|
||||
def set_volume(t, buf=bytearray(3)):
|
||||
buf[0] = 0xa5
|
||||
buf[1] = t >> 4
|
||||
buf[2] = 0x5a
|
||||
return buf
|
||||
|
||||
The compiler instantiates the default ``buf`` argument when the function is
|
||||
loaded for the first time (usually when the module it's in is imported).
|
||||
|
||||
Use of Python objects
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -300,3 +313,20 @@ that access to the critical variables is denied. A simple example of a mutex may
|
|||
but only for the duration of eight machine instructions: the benefit of this approach is that other interrupts are
|
||||
virtually unaffected.
|
||||
|
||||
Interrupts and the REPL
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Interrupt handlers, such as those associated with timers, can continue to run
|
||||
after a program terminates. This may produce unexpected results where you might
|
||||
have expected the object raising the callback to have gone out of scope. For
|
||||
example on the Pyboard:
|
||||
|
||||
.. code:: python
|
||||
|
||||
def bar():
|
||||
foo = pyb.Timer(2, freq=4, callback=lambda t: print('.', end=''))
|
||||
|
||||
bar()
|
||||
|
||||
This continues to run until the timer is explicitly disabled or the board is
|
||||
reset with ``ctrl D``.
|
||||
|
|
|
@ -4,31 +4,41 @@ Micro Python driver for SD cards using SPI bus.
|
|||
Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
|
||||
methods so the device can be mounted as a filesystem.
|
||||
|
||||
Example usage:
|
||||
Example usage on pyboard:
|
||||
|
||||
import pyb, sdcard, os
|
||||
sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
|
||||
pyb.mount(sd, '/sd2')
|
||||
os.listdir('/')
|
||||
|
||||
Example usage on ESP8266:
|
||||
|
||||
import machine, sdcard, os
|
||||
sd = sdcard.SDCard(machine.SPI(0), machine.Pin(15))
|
||||
os.umount()
|
||||
os.VfsFat(sd, "")
|
||||
os.listdir()
|
||||
|
||||
"""
|
||||
|
||||
import pyb
|
||||
import time
|
||||
|
||||
class SDCard:
|
||||
CMD_TIMEOUT = const(100)
|
||||
|
||||
R1_IDLE_STATE = const(1 << 0)
|
||||
_CMD_TIMEOUT = const(100)
|
||||
|
||||
_R1_IDLE_STATE = const(1 << 0)
|
||||
#R1_ERASE_RESET = const(1 << 1)
|
||||
R1_ILLEGAL_COMMAND = const(1 << 2)
|
||||
_R1_ILLEGAL_COMMAND = const(1 << 2)
|
||||
#R1_COM_CRC_ERROR = const(1 << 3)
|
||||
#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
|
||||
#R1_ADDRESS_ERROR = const(1 << 5)
|
||||
#R1_PARAMETER_ERROR = const(1 << 6)
|
||||
TOKEN_CMD25 = const(0xfc)
|
||||
TOKEN_STOP_TRAN = const(0xfd)
|
||||
TOKEN_DATA = const(0xfe)
|
||||
_TOKEN_CMD25 = const(0xfc)
|
||||
_TOKEN_STOP_TRAN = const(0xfd)
|
||||
_TOKEN_DATA = const(0xfe)
|
||||
|
||||
|
||||
class SDCard:
|
||||
def __init__(self, spi, cs):
|
||||
self.spi = spi
|
||||
self.cs = cs
|
||||
|
@ -42,30 +52,39 @@ class SDCard:
|
|||
# initialise the card
|
||||
self.init_card()
|
||||
|
||||
def init_spi(self, baudrate):
|
||||
try:
|
||||
master = self.spi.MASTER
|
||||
except AttributeError:
|
||||
# on ESP8266
|
||||
self.spi.init(baudrate=baudrate, phase=0, polarity=0)
|
||||
else:
|
||||
# on pyboard
|
||||
self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
|
||||
|
||||
def init_card(self):
|
||||
# init CS pin
|
||||
self.cs.high()
|
||||
self.cs.init(self.cs.OUT_PP)
|
||||
self.cs.init(self.cs.OUT, value=1)
|
||||
|
||||
# init SPI bus; use low data rate for initialisation
|
||||
self.spi.init(self.spi.MASTER, baudrate=100000, phase=0, polarity=0)
|
||||
self.init_spi(100000)
|
||||
|
||||
# clock card at least 100 cycles with cs high
|
||||
for i in range(16):
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
# CMD0: init card; should return R1_IDLE_STATE (allow 5 attempts)
|
||||
# CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
|
||||
for _ in range(5):
|
||||
if self.cmd(0, 0, 0x95) == R1_IDLE_STATE:
|
||||
if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
|
||||
break
|
||||
else:
|
||||
raise OSError("no SD card")
|
||||
|
||||
# CMD8: determine card version
|
||||
r = self.cmd(8, 0x01aa, 0x87, 4)
|
||||
if r == R1_IDLE_STATE:
|
||||
if r == _R1_IDLE_STATE:
|
||||
self.init_card_v2()
|
||||
elif r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND):
|
||||
elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
|
||||
self.init_card_v1()
|
||||
else:
|
||||
raise OSError("couldn't determine SD card version")
|
||||
|
@ -86,10 +105,10 @@ class SDCard:
|
|||
raise OSError("can't set 512 block size")
|
||||
|
||||
# set to high data rate now that it's initialised
|
||||
self.spi.init(self.spi.MASTER, baudrate=1320000, phase=0, polarity=0)
|
||||
self.init_spi(1320000)
|
||||
|
||||
def init_card_v1(self):
|
||||
for i in range(CMD_TIMEOUT):
|
||||
for i in range(_CMD_TIMEOUT):
|
||||
self.cmd(55, 0, 0)
|
||||
if self.cmd(41, 0, 0) == 0:
|
||||
self.cdv = 512
|
||||
|
@ -98,8 +117,8 @@ class SDCard:
|
|||
raise OSError("timeout waiting for v1 card")
|
||||
|
||||
def init_card_v2(self):
|
||||
for i in range(CMD_TIMEOUT):
|
||||
pyb.delay(50)
|
||||
for i in range(_CMD_TIMEOUT):
|
||||
time.sleep_ms(50)
|
||||
self.cmd(58, 0, 0, 4)
|
||||
self.cmd(55, 0, 0)
|
||||
if self.cmd(41, 0x40000000, 0) == 0:
|
||||
|
@ -120,87 +139,87 @@ class SDCard:
|
|||
buf[3] = arg >> 8
|
||||
buf[4] = arg
|
||||
buf[5] = crc
|
||||
self.spi.send(buf)
|
||||
self.spi.write(buf)
|
||||
|
||||
# wait for the repsonse (response[7] == 0)
|
||||
for i in range(CMD_TIMEOUT):
|
||||
response = self.spi.send_recv(0xff)[0]
|
||||
for i in range(_CMD_TIMEOUT):
|
||||
response = self.spi.read(1, 0xff)[0]
|
||||
if not (response & 0x80):
|
||||
# this could be a big-endian integer that we are getting here
|
||||
for j in range(final):
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
if release:
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
return response
|
||||
|
||||
# timeout
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
return -1
|
||||
|
||||
def cmd_nodata(self, cmd):
|
||||
self.spi.send(cmd)
|
||||
self.spi.send_recv(0xff) # ignore stuff byte
|
||||
for _ in range(CMD_TIMEOUT):
|
||||
if self.spi.send_recv(0xff)[0] == 0xff:
|
||||
self.spi.write(cmd)
|
||||
self.spi.read(1, 0xff) # ignore stuff byte
|
||||
for _ in range(_CMD_TIMEOUT):
|
||||
if self.spi.read(1, 0xff)[0] == 0xff:
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
return 0 # OK
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
return 1 # timeout
|
||||
|
||||
def readinto(self, buf):
|
||||
self.cs.low()
|
||||
|
||||
# read until start byte (0xff)
|
||||
while self.spi.send_recv(0xff)[0] != 0xfe:
|
||||
while self.spi.read(1, 0xff)[0] != 0xfe:
|
||||
pass
|
||||
|
||||
# read data
|
||||
mv = self.dummybuf_memoryview[:len(buf)]
|
||||
self.spi.send_recv(mv, recv=buf)
|
||||
self.spi.write_readinto(mv, buf)
|
||||
|
||||
# read checksum
|
||||
self.spi.send(0xff)
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
def write(self, token, buf):
|
||||
self.cs.low()
|
||||
|
||||
# send: start of block, data, checksum
|
||||
self.spi.send(token)
|
||||
self.spi.send(buf)
|
||||
self.spi.send(0xff)
|
||||
self.spi.send(0xff)
|
||||
self.spi.read(1, token)
|
||||
self.spi.write(buf)
|
||||
self.spi.write(b'\xff')
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
# check the response
|
||||
if (self.spi.send_recv(0xff)[0] & 0x1f) != 0x05:
|
||||
if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05:
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
return
|
||||
|
||||
# wait for write to finish
|
||||
while self.spi.send_recv(0xff)[0] == 0:
|
||||
while self.spi.read(1, 0xff)[0] == 0:
|
||||
pass
|
||||
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
def write_token(self, token):
|
||||
self.cs.low()
|
||||
self.spi.send(token)
|
||||
self.spi.send(0xff)
|
||||
self.spi.read(1, token)
|
||||
self.spi.write(b'\xff')
|
||||
# wait for write to finish
|
||||
while self.spi.send_recv(0xff)[0] == 0:
|
||||
while self.spi.read(1, 0xff)[0] == 0x00:
|
||||
pass
|
||||
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
def count(self):
|
||||
return self.sectors
|
||||
|
@ -224,7 +243,7 @@ class SDCard:
|
|||
self.readinto(mv[offset : offset + 512])
|
||||
offset += 512
|
||||
nblocks -= 1
|
||||
return self.cmd_nodata(12)
|
||||
return self.cmd_nodata(b'\x0c') # cmd 12
|
||||
return 0
|
||||
|
||||
def writeblocks(self, block_num, buf):
|
||||
|
@ -236,7 +255,7 @@ class SDCard:
|
|||
return 1
|
||||
|
||||
# send the data
|
||||
self.write(TOKEN_DATA, buf)
|
||||
self.write(_TOKEN_DATA, buf)
|
||||
else:
|
||||
# CMD25: set write address for first block
|
||||
if self.cmd(25, block_num * self.cdv, 0) != 0:
|
||||
|
@ -245,8 +264,8 @@ class SDCard:
|
|||
offset = 0
|
||||
mv = memoryview(buf)
|
||||
while nblocks:
|
||||
self.write(TOKEN_CMD25, mv[offset : offset + 512])
|
||||
self.write(_TOKEN_CMD25, mv[offset : offset + 512])
|
||||
offset += 512
|
||||
nblocks -= 1
|
||||
self.write_token(TOKEN_STOP_TRAN)
|
||||
self.write_token(_TOKEN_STOP_TRAN)
|
||||
return 0
|
||||
|
|
|
@ -78,7 +78,9 @@ SRC_C = \
|
|||
modpybrtc.c \
|
||||
modpybadc.c \
|
||||
modpybuart.c \
|
||||
modmachinewdt.c \
|
||||
modpybspi.c \
|
||||
modpybhspi.c \
|
||||
modesp.c \
|
||||
modnetwork.c \
|
||||
modutime.c \
|
||||
|
@ -89,6 +91,7 @@ SRC_C = \
|
|||
$(BUILD)/frozen.c \
|
||||
fatfs_port.c \
|
||||
axtls_helpers.c \
|
||||
hspi.c \
|
||||
$(SRC_MOD)
|
||||
|
||||
STM_SRC_C = $(addprefix stmhal/,\
|
||||
|
@ -125,7 +128,6 @@ LIB_SRC_C = $(addprefix lib/,\
|
|||
timeutils/timeutils.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/printf.c \
|
||||
fatfs/ff.c \
|
||||
fatfs/option/ccsbcs.c \
|
||||
)
|
||||
|
@ -137,7 +139,7 @@ DRIVERS_SRC_C = $(addprefix drivers/,\
|
|||
SRC_S = \
|
||||
gchelper.s \
|
||||
|
||||
FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR)/ -type f -name '*.py')
|
||||
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
|
||||
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
|
||||
|
||||
OBJ =
|
||||
|
|
|
@ -141,7 +141,10 @@ SECTIONS
|
|||
*modpybadc.o(.literal*, .text*)
|
||||
*modpybuart.o(.literal*, .text*)
|
||||
*modpybi2c.o(.literal*, .text*)
|
||||
*modmachinewdt.o(.literal*, .text*)
|
||||
*modpybspi.o(.literal*, .text*)
|
||||
*modpybhspi.o(.literal*, .text*)
|
||||
*hspi.o(.literal*, .text*)
|
||||
*modesp.o(.literal* .text*)
|
||||
*modnetwork.o(.literal* .text*)
|
||||
*moduos.o(.literal* .text*)
|
||||
|
|
|
@ -36,17 +36,13 @@
|
|||
#include "extmod/misc.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
|
||||
extern void ets_wdt_disable(void);
|
||||
extern void wdt_feed(void);
|
||||
extern void ets_delay_us();
|
||||
|
||||
STATIC byte input_buf_array[256];
|
||||
ringbuf_t input_buf = {input_buf_array, sizeof(input_buf_array)};
|
||||
void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len);
|
||||
const mp_print_t mp_debug_print = {NULL, mp_hal_debug_tx_strn_cooked};
|
||||
|
||||
void mp_hal_init(void) {
|
||||
ets_wdt_disable(); // it's a pain while developing
|
||||
//ets_wdt_disable(); // it's a pain while developing
|
||||
mp_hal_rtc_init();
|
||||
uart_init(UART_BIT_RATE_115200, UART_BIT_RATE_115200);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32
|
|||
}
|
||||
#endif
|
||||
|
||||
uint32_t irq_state = mp_hal_quiet_timing_enter();
|
||||
for(t = time0;; t = time0) {
|
||||
if(pix & mask) t = time1; // Bit high duration
|
||||
while(((c = mp_hal_ticks_cpu()) - startTime) < period); // Wait for bit start
|
||||
|
@ -55,4 +56,5 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32
|
|||
}
|
||||
}
|
||||
while((mp_hal_ticks_cpu() - startTime) < period); // Wait for last bit
|
||||
mp_hal_quiet_timing_exit(irq_state);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@ void ets_timer_arm_new(os_timer_t *tim, uint32_t millis, bool repeat, bool is_mi
|
|||
void ets_timer_setfn(os_timer_t *tim, ETSTimerFunc callback, void *cb_data);
|
||||
void ets_timer_disarm(os_timer_t *tim);
|
||||
|
||||
extern void ets_wdt_disable(void);
|
||||
extern void wdt_feed(void);
|
||||
|
||||
// Opaque structure
|
||||
typedef char MD5_CTX[64];
|
||||
|
||||
|
|
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 David Ogilvy (MetalPhreak)
|
||||
* Modified 2016 by Radomir Dopieralski
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "hspi.h"
|
||||
|
||||
/*
|
||||
Wrapper to setup HSPI/SPI GPIO pins and default SPI clock
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
Not used in Micropython.
|
||||
*/
|
||||
void spi_init(uint8_t spi_no) {
|
||||
spi_init_gpio(spi_no, SPI_CLK_USE_DIV);
|
||||
spi_clock(spi_no, SPI_CLK_PREDIV, SPI_CLK_CNTDIV);
|
||||
spi_tx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW);
|
||||
spi_rx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW);
|
||||
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Configures SPI mode parameters for clock edge and clock polarity.
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
spi_cpha - (0) Data is valid on clock leading edge
|
||||
(1) Data is valid on clock trailing edge
|
||||
spi_cpol - (0) Clock is low when inactive
|
||||
(1) Clock is high when inactive
|
||||
For Micropython this version is different from original.
|
||||
*/
|
||||
void spi_mode(uint8_t spi_no, uint8_t spi_cpha, uint8_t spi_cpol) {
|
||||
if (spi_cpol) {
|
||||
SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE);
|
||||
}
|
||||
if (spi_cpha == spi_cpol) {
|
||||
// Mode 3 - MOSI is set on falling edge of clock
|
||||
// Mode 0 - MOSI is set on falling edge of clock
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE);
|
||||
SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE);
|
||||
} else {
|
||||
// Mode 2 - MOSI is set on rising edge of clock
|
||||
// Mode 1 - MOSI is set on rising edge of clock
|
||||
SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Initialise the GPIO pins for use as SPI pins.
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
sysclk_as_spiclk -
|
||||
SPI_CLK_80MHZ_NODIV (1) if using 80MHz for SPI clock.
|
||||
SPI_CLK_USE_DIV (0) if using divider for lower speed.
|
||||
*/
|
||||
void spi_init_gpio(uint8_t spi_no, uint8_t sysclk_as_spiclk) {
|
||||
uint32_t clock_div_flag = 0;
|
||||
if (sysclk_as_spiclk) {
|
||||
clock_div_flag = 0x0001;
|
||||
}
|
||||
if (spi_no == SPI) {
|
||||
// Set bit 8 if 80MHz sysclock required
|
||||
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005 | (clock_div_flag<<8));
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);
|
||||
} else if (spi_no == HSPI) {
|
||||
// Set bit 9 if 80MHz sysclock required
|
||||
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105 | (clock_div_flag<<9));
|
||||
// GPIO12 is HSPI MISO pin (Master Data In)
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);
|
||||
// GPIO13 is HSPI MOSI pin (Master Data Out)
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);
|
||||
// GPIO14 is HSPI CLK pin (Clock)
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);
|
||||
// GPIO15 is HSPI CS pin (Chip Select / Slave Select)
|
||||
// In Micropython, we are handling CS ourself in drivers.
|
||||
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Set up the control registers for the SPI clock
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
prediv - predivider value (actual division value)
|
||||
cntdiv - postdivider value (actual division value)
|
||||
Set either divider to 0 to disable all division (80MHz sysclock)
|
||||
*/
|
||||
void spi_clock(uint8_t spi_no, uint16_t prediv, uint8_t cntdiv) {
|
||||
if (prediv == 0 || cntdiv == 0) {
|
||||
WRITE_PERI_REG(SPI_CLOCK(spi_no), SPI_CLK_EQU_SYSCLK);
|
||||
} else {
|
||||
WRITE_PERI_REG(SPI_CLOCK(spi_no),
|
||||
(((prediv - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
|
||||
(((cntdiv - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
|
||||
(((cntdiv >> 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
|
||||
((0 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Setup the byte order for shifting data out of buffer
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
byte_order -
|
||||
SPI_BYTE_ORDER_HIGH_TO_LOW (1)
|
||||
Data is sent out starting with Bit31 and down to Bit0
|
||||
SPI_BYTE_ORDER_LOW_TO_HIGH (0)
|
||||
Data is sent out starting with the lowest BYTE, from MSB to LSB,
|
||||
followed by the second lowest BYTE, from MSB to LSB, followed by
|
||||
the second highest BYTE, from MSB to LSB, followed by the highest
|
||||
BYTE, from MSB to LSB 0xABCDEFGH would be sent as 0xGHEFCDAB.
|
||||
*/
|
||||
void spi_tx_byte_order(uint8_t spi_no, uint8_t byte_order) {
|
||||
if (byte_order) {
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Setup the byte order for shifting data into buffer
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
byte_order -
|
||||
SPI_BYTE_ORDER_HIGH_TO_LOW (1)
|
||||
Data is read in starting with Bit31 and down to Bit0
|
||||
SPI_BYTE_ORDER_LOW_TO_HIGH (0)
|
||||
Data is read in starting with the lowest BYTE, from MSB to LSB,
|
||||
followed by the second lowest BYTE, from MSB to LSB, followed by
|
||||
the second highest BYTE, from MSB to LSB, followed by the highest
|
||||
BYTE, from MSB to LSB 0xABCDEFGH would be read as 0xGHEFCDAB
|
||||
*/
|
||||
void spi_rx_byte_order(uint8_t spi_no, uint8_t byte_order) {
|
||||
if (byte_order) {
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
SPI transaction function
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
cmd_bits - actual number of bits to transmit
|
||||
cmd_data - command data
|
||||
addr_bits - actual number of bits to transmit
|
||||
addr_data - address data
|
||||
dout_bits - actual number of bits to transmit
|
||||
dout_data - output data
|
||||
din_bits - actual number of bits to receive
|
||||
Returns: read data - uint32_t containing read in data only if RX was set
|
||||
0 - something went wrong (or actual read data was 0)
|
||||
1 - data sent ok (or actual read data is 1)
|
||||
Note: all data is assumed to be stored in the lower bits of the data variables
|
||||
(for anything <32 bits).
|
||||
*/
|
||||
uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data,
|
||||
uint32_t addr_bits, uint32_t addr_data,
|
||||
uint32_t dout_bits, uint32_t dout_data,
|
||||
uint32_t din_bits, uint32_t dummy_bits) {
|
||||
while (spi_busy(spi_no)) {}; // Wait for SPI to be ready
|
||||
|
||||
// Enable SPI Functions
|
||||
// Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set.
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO |
|
||||
SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY);
|
||||
|
||||
// Enable functions based on number of bits. 0 bits = disabled.
|
||||
// This is rather inefficient but allows for a very generic function.
|
||||
// CMD ADDR and MOSI are set below to save on an extra if statement.
|
||||
if (din_bits) {
|
||||
if (dout_bits) {
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_DOUTDIN);
|
||||
} else {
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);
|
||||
}
|
||||
}
|
||||
if (dummy_bits) {
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_DUMMY);
|
||||
}
|
||||
|
||||
// Setup Bitlengths
|
||||
WRITE_PERI_REG(SPI_USER1(spi_no),
|
||||
// Number of bits in Address
|
||||
((addr_bits - 1) & SPI_USR_ADDR_BITLEN) << SPI_USR_ADDR_BITLEN_S |
|
||||
// Number of bits to Send
|
||||
((dout_bits - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S |
|
||||
// Number of bits to receive
|
||||
((din_bits - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S |
|
||||
// Number of Dummy bits to insert
|
||||
((dummy_bits - 1) & SPI_USR_DUMMY_CYCLELEN) << SPI_USR_DUMMY_CYCLELEN_S);
|
||||
|
||||
// Setup Command Data
|
||||
if (cmd_bits) {
|
||||
// Enable COMMAND function in SPI module
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_COMMAND);
|
||||
// Align command data to high bits
|
||||
uint16_t command = cmd_data << (16-cmd_bits);
|
||||
// Swap byte order
|
||||
command = ((command>>8)&0xff) | ((command<<8)&0xff00);
|
||||
WRITE_PERI_REG(SPI_USER2(spi_no), (
|
||||
(((cmd_bits - 1) & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) |
|
||||
(command & SPI_USR_COMMAND_VALUE)
|
||||
));
|
||||
}
|
||||
|
||||
// Setup Address Data
|
||||
if (addr_bits) {
|
||||
// Enable ADDRess function in SPI module
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_ADDR);
|
||||
// Align address data to high bits
|
||||
WRITE_PERI_REG(SPI_ADDR(spi_no), addr_data << (32 - addr_bits));
|
||||
}
|
||||
|
||||
// Setup DOUT data
|
||||
if (dout_bits) {
|
||||
// Enable MOSI function in SPI module
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
|
||||
// Copy data to W0
|
||||
if (READ_PERI_REG(SPI_USER(spi_no))&SPI_WR_BYTE_ORDER) {
|
||||
WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - dout_bits));
|
||||
} else {
|
||||
uint8_t dout_extra_bits = dout_bits%8;
|
||||
|
||||
if (dout_extra_bits) {
|
||||
// If your data isn't a byte multiple (8/16/24/32 bits) and you
|
||||
// don't have SPI_WR_BYTE_ORDER set, you need this to move the
|
||||
// non-8bit remainder to the MSBs. Not sure if there's even a use
|
||||
// case for this, but it's here if you need it... For example,
|
||||
// 0xDA4 12 bits without SPI_WR_BYTE_ORDER would usually be output
|
||||
// as if it were 0x0DA4, of which 0xA4, and then 0x0 would be
|
||||
// shifted out (first 8 bits of low byte, then 4 MSB bits of high
|
||||
// byte - ie reverse byte order).
|
||||
// The code below shifts it out as 0xA4 followed by 0xD as you
|
||||
// might require.
|
||||
WRITE_PERI_REG(SPI_W0(spi_no), (
|
||||
(0xFFFFFFFF << (dout_bits - dout_extra_bits) & dout_data)
|
||||
<< (8-dout_extra_bits) |
|
||||
((0xFFFFFFFF >> (32 - (dout_bits - dout_extra_bits)))
|
||||
& dout_data)
|
||||
));
|
||||
} else {
|
||||
WRITE_PERI_REG(SPI_W0(spi_no), dout_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Begin SPI Transaction
|
||||
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
|
||||
|
||||
// Return DIN data
|
||||
if (din_bits) {
|
||||
while (spi_busy(spi_no)) {}; // Wait for SPI transaction to complete
|
||||
if (READ_PERI_REG(SPI_USER(spi_no))&SPI_RD_BYTE_ORDER) {
|
||||
// Assuming data in is written to MSB. TBC
|
||||
return READ_PERI_REG(SPI_W0(spi_no)) >> (32 - din_bits);
|
||||
} else {
|
||||
// Read in the same way as DOUT is sent. Note existing contents of
|
||||
// SPI_W0 remain unless overwritten!
|
||||
return READ_PERI_REG(SPI_W0(spi_no));
|
||||
}
|
||||
return 0; // Something went wrong
|
||||
}
|
||||
|
||||
// Transaction completed
|
||||
return 1; // Success
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Just do minimal work needed to send 8 bits.
|
||||
*/
|
||||
inline void spi_tx8fast(uint8_t spi_no, uint8_t dout_data) {
|
||||
while (spi_busy(spi_no)) {}; // Wait for SPI to be ready
|
||||
|
||||
// Enable SPI Functions
|
||||
// Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set.
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO |
|
||||
SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY);
|
||||
|
||||
// Setup Bitlengths
|
||||
WRITE_PERI_REG(SPI_USER1(spi_no),
|
||||
// Number of bits to Send
|
||||
((8 - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S |
|
||||
// Number of bits to receive
|
||||
((8 - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S);
|
||||
|
||||
|
||||
// Setup DOUT data
|
||||
// Enable MOSI function in SPI module
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
|
||||
// Copy data to W0
|
||||
if (READ_PERI_REG(SPI_USER(spi_no)) & SPI_WR_BYTE_ORDER) {
|
||||
WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - 8));
|
||||
} else {
|
||||
WRITE_PERI_REG(SPI_W0(spi_no), dout_data);
|
||||
}
|
||||
|
||||
// Begin SPI Transaction
|
||||
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 David Ogilvy (MetalPhreak)
|
||||
* Modified 2016 by Radomir Dopieralski
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SPI_APP_H
|
||||
#define SPI_APP_H
|
||||
|
||||
#include "hspi_register.h"
|
||||
#include "ets_sys.h"
|
||||
#include "osapi.h"
|
||||
#include "os_type.h"
|
||||
|
||||
// Define SPI hardware modules
|
||||
#define SPI 0
|
||||
#define HSPI 1
|
||||
|
||||
#define SPI_CLK_USE_DIV 0
|
||||
#define SPI_CLK_80MHZ_NODIV 1
|
||||
|
||||
#define SPI_BYTE_ORDER_HIGH_TO_LOW 1
|
||||
#define SPI_BYTE_ORDER_LOW_TO_HIGH 0
|
||||
|
||||
#ifndef CPU_CLK_FREQ //Should already be defined in eagle_soc.h
|
||||
#define CPU_CLK_FREQ (80 * 1000000)
|
||||
#endif
|
||||
|
||||
// Define some default SPI clock settings
|
||||
#define SPI_CLK_PREDIV 10
|
||||
#define SPI_CLK_CNTDIV 2
|
||||
#define SPI_CLK_FREQ (CPU_CLK_FREQ / (SPI_CLK_PREDIV * SPI_CLK_CNTDIV))
|
||||
// 80 / 20 = 4 MHz
|
||||
|
||||
void spi_init(uint8_t spi_no);
|
||||
void spi_mode(uint8_t spi_no, uint8_t spi_cpha,uint8_t spi_cpol);
|
||||
void spi_init_gpio(uint8_t spi_no, uint8_t sysclk_as_spiclk);
|
||||
void spi_clock(uint8_t spi_no, uint16_t prediv, uint8_t cntdiv);
|
||||
void spi_tx_byte_order(uint8_t spi_no, uint8_t byte_order);
|
||||
void spi_rx_byte_order(uint8_t spi_no, uint8_t byte_order);
|
||||
uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data,
|
||||
uint32_t addr_bits, uint32_t addr_data,
|
||||
uint32_t dout_bits, uint32_t dout_data,
|
||||
uint32_t din_bits, uint32_t dummy_bits);
|
||||
void spi_tx8fast(uint8_t spi_no, uint8_t dout_data);
|
||||
|
||||
// Expansion Macros
|
||||
#define spi_busy(spi_no) READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR
|
||||
|
||||
#define spi_txd(spi_no, bits, data) spi_transaction(spi_no, 0, 0, 0, 0, bits, (uint32_t) data, 0, 0)
|
||||
#define spi_tx8(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 8, (uint32_t) data, 0, 0)
|
||||
#define spi_tx16(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 16, (uint32_t) data, 0, 0)
|
||||
#define spi_tx32(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 32, (uint32_t) data, 0, 0)
|
||||
|
||||
#define spi_rxd(spi_no, bits) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, bits, 0)
|
||||
#define spi_rx8(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 8, 0)
|
||||
#define spi_rx16(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 16, 0)
|
||||
#define spi_rx32(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 32, 0)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* Copyright (c) 2010 - 2011 Espressif System
|
||||
* Modified by David Ogilvy (MetalPhreak)
|
||||
* Based on original file included in SDK 1.0.0
|
||||
*
|
||||
* Missing defines from previous SDK versions have
|
||||
* been added and are noted with comments. The
|
||||
* names of these defines are likely to change.
|
||||
*/
|
||||
|
||||
#ifndef SPI_REGISTER_H_INCLUDED
|
||||
#define SPI_REGISTER_H_INCLUDED
|
||||
|
||||
#define REG_SPI_BASE(i) (0x60000200-i*0x100)
|
||||
|
||||
#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0)
|
||||
#define SPI_FLASH_READ (BIT(31)) //From previous SDK
|
||||
#define SPI_FLASH_WREN (BIT(30)) //From previous SDK
|
||||
#define SPI_FLASH_WRDI (BIT(29)) //From previous SDK
|
||||
#define SPI_FLASH_RDID (BIT(28)) //From previous SDK
|
||||
#define SPI_FLASH_RDSR (BIT(27)) //From previous SDK
|
||||
#define SPI_FLASH_WRSR (BIT(26)) //From previous SDK
|
||||
#define SPI_FLASH_PP (BIT(25)) //From previous SDK
|
||||
#define SPI_FLASH_SE (BIT(24)) //From previous SDK
|
||||
#define SPI_FLASH_BE (BIT(23)) //From previous SDK
|
||||
#define SPI_FLASH_CE (BIT(22)) //From previous SDK
|
||||
#define SPI_FLASH_DP (BIT(21)) //From previous SDK
|
||||
#define SPI_FLASH_RES (BIT(20)) //From previous SDK
|
||||
#define SPI_FLASH_HPM (BIT(19)) //From previous SDK
|
||||
#define SPI_USR (BIT(18))
|
||||
|
||||
#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4)
|
||||
|
||||
#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8)
|
||||
#define SPI_WR_BIT_ORDER (BIT(26))
|
||||
#define SPI_RD_BIT_ORDER (BIT(25))
|
||||
#define SPI_QIO_MODE (BIT(24))
|
||||
#define SPI_DIO_MODE (BIT(23))
|
||||
#define SPI_TWO_BYTE_STATUS_EN (BIT(22)) //From previous SDK
|
||||
#define SPI_WP_REG (BIT(21)) //From previous SDK
|
||||
#define SPI_QOUT_MODE (BIT(20))
|
||||
#define SPI_SHARE_BUS (BIT(19)) //From previous SDK
|
||||
#define SPI_HOLD_MODE (BIT(18)) //From previous SDK
|
||||
#define SPI_ENABLE_AHB (BIT(17)) //From previous SDK
|
||||
#define SPI_SST_AAI (BIT(16)) //From previous SDK
|
||||
#define SPI_RESANDRES (BIT(15)) //From previous SDK
|
||||
#define SPI_DOUT_MODE (BIT(14))
|
||||
#define SPI_FASTRD_MODE (BIT(13))
|
||||
|
||||
#define SPI_CTRL1(i) (REG_SPI_BASE (i) + 0xC) //From previous SDK. Removed _FLASH_ from name to match other registers.
|
||||
#define SPI_CS_HOLD_DELAY 0x0000000F //Espressif BBS
|
||||
#define SPI_CS_HOLD_DELAY_S 28 //Espressif BBS
|
||||
#define SPI_CS_HOLD_DELAY_RES 0x00000FFF //Espressif BBS
|
||||
#define SPI_CS_HOLD_DELAY_RES_S 16 //Espressif BBS
|
||||
#define SPI_BUS_TIMER_LIMIT 0x0000FFFF //From previous SDK
|
||||
#define SPI_BUS_TIMER_LIMIT_S 0 //From previous SDK
|
||||
|
||||
|
||||
#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10)
|
||||
#define SPI_STATUS_EXT 0x000000FF //From previous SDK
|
||||
#define SPI_STATUS_EXT_S 24 //From previous SDK
|
||||
#define SPI_WB_MODE 0x000000FF //From previous SDK
|
||||
#define SPI_WB_MODE_S 16 //From previous SDK
|
||||
#define SPI_FLASH_STATUS_PRO_FLAG (BIT(7)) //From previous SDK
|
||||
#define SPI_FLASH_TOP_BOT_PRO_FLAG (BIT(5)) //From previous SDK
|
||||
#define SPI_FLASH_BP2 (BIT(4)) //From previous SDK
|
||||
#define SPI_FLASH_BP1 (BIT(3)) //From previous SDK
|
||||
#define SPI_FLASH_BP0 (BIT(2)) //From previous SDK
|
||||
#define SPI_FLASH_WRENABLE_FLAG (BIT(1)) //From previous SDK
|
||||
#define SPI_FLASH_BUSY_FLAG (BIT(0)) //From previous SDK
|
||||
|
||||
#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14)
|
||||
#define SPI_CS_DELAY_NUM 0x0000000F
|
||||
#define SPI_CS_DELAY_NUM_S 28
|
||||
#define SPI_CS_DELAY_MODE 0x00000003
|
||||
#define SPI_CS_DELAY_MODE_S 26
|
||||
#define SPI_MOSI_DELAY_NUM 0x00000007
|
||||
#define SPI_MOSI_DELAY_NUM_S 23
|
||||
#define SPI_MOSI_DELAY_MODE 0x00000003 //mode 0 : posedge; data set at positive edge of clk
|
||||
//mode 1 : negedge + 1 cycle delay, only if freq<10MHz ; data set at negitive edge of clk
|
||||
//mode 2 : Do not use this mode.
|
||||
#define SPI_MOSI_DELAY_MODE_S 21
|
||||
#define SPI_MISO_DELAY_NUM 0x00000007
|
||||
#define SPI_MISO_DELAY_NUM_S 18
|
||||
#define SPI_MISO_DELAY_MODE 0x00000003
|
||||
#define SPI_MISO_DELAY_MODE_S 16
|
||||
#define SPI_CK_OUT_HIGH_MODE 0x0000000F
|
||||
#define SPI_CK_OUT_HIGH_MODE_S 12
|
||||
#define SPI_CK_OUT_LOW_MODE 0x0000000F
|
||||
#define SPI_CK_OUT_LOW_MODE_S 8
|
||||
#define SPI_HOLD_TIME 0x0000000F
|
||||
#define SPI_HOLD_TIME_S 4
|
||||
#define SPI_SETUP_TIME 0x0000000F
|
||||
#define SPI_SETUP_TIME_S 0
|
||||
|
||||
#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18)
|
||||
#define SPI_CLK_EQU_SYSCLK (BIT(31))
|
||||
#define SPI_CLKDIV_PRE 0x00001FFF
|
||||
#define SPI_CLKDIV_PRE_S 18
|
||||
#define SPI_CLKCNT_N 0x0000003F
|
||||
#define SPI_CLKCNT_N_S 12
|
||||
#define SPI_CLKCNT_H 0x0000003F
|
||||
#define SPI_CLKCNT_H_S 6
|
||||
#define SPI_CLKCNT_L 0x0000003F
|
||||
#define SPI_CLKCNT_L_S 0
|
||||
|
||||
#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C)
|
||||
#define SPI_USR_COMMAND (BIT(31))
|
||||
#define SPI_USR_ADDR (BIT(30))
|
||||
#define SPI_USR_DUMMY (BIT(29))
|
||||
#define SPI_USR_MISO (BIT(28))
|
||||
#define SPI_USR_MOSI (BIT(27))
|
||||
#define SPI_USR_DUMMY_IDLE (BIT(26)) //From previous SDK
|
||||
#define SPI_USR_MOSI_HIGHPART (BIT(25))
|
||||
#define SPI_USR_MISO_HIGHPART (BIT(24))
|
||||
#define SPI_USR_PREP_HOLD (BIT(23)) //From previous SDK
|
||||
#define SPI_USR_CMD_HOLD (BIT(22)) //From previous SDK
|
||||
#define SPI_USR_ADDR_HOLD (BIT(21)) //From previous SDK
|
||||
#define SPI_USR_DUMMY_HOLD (BIT(20)) //From previous SDK
|
||||
#define SPI_USR_DIN_HOLD (BIT(19)) //From previous SDK
|
||||
#define SPI_USR_DOUT_HOLD (BIT(18)) //From previous SDK
|
||||
#define SPI_USR_HOLD_POL (BIT(17)) //From previous SDK
|
||||
#define SPI_SIO (BIT(16))
|
||||
#define SPI_FWRITE_QIO (BIT(15))
|
||||
#define SPI_FWRITE_DIO (BIT(14))
|
||||
#define SPI_FWRITE_QUAD (BIT(13))
|
||||
#define SPI_FWRITE_DUAL (BIT(12))
|
||||
#define SPI_WR_BYTE_ORDER (BIT(11))
|
||||
#define SPI_RD_BYTE_ORDER (BIT(10))
|
||||
#define SPI_AHB_ENDIAN_MODE 0x00000003 //From previous SDK
|
||||
#define SPI_AHB_ENDIAN_MODE_S 8 //From previous SDK
|
||||
#define SPI_CK_OUT_EDGE (BIT(7))
|
||||
#define SPI_CK_I_EDGE (BIT(6))
|
||||
#define SPI_CS_SETUP (BIT(5))
|
||||
#define SPI_CS_HOLD (BIT(4))
|
||||
#define SPI_AHB_USR_COMMAND (BIT(3)) //From previous SDK
|
||||
#define SPI_FLASH_MODE (BIT(2))
|
||||
#define SPI_AHB_USR_COMMAND_4BYTE (BIT(1)) //From previous SDK
|
||||
#define SPI_DOUTDIN (BIT(0)) //From previous SDK
|
||||
|
||||
//AHB = http://en.wikipedia.org/wiki/Advanced_Microcontroller_Bus_Architecture ?
|
||||
|
||||
|
||||
#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20)
|
||||
#define SPI_USR_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_USR_ADDR_BITLEN_S 26
|
||||
#define SPI_USR_MOSI_BITLEN 0x000001FF
|
||||
#define SPI_USR_MOSI_BITLEN_S 17
|
||||
#define SPI_USR_MISO_BITLEN 0x000001FF
|
||||
#define SPI_USR_MISO_BITLEN_S 8
|
||||
#define SPI_USR_DUMMY_CYCLELEN 0x000000FF
|
||||
#define SPI_USR_DUMMY_CYCLELEN_S 0
|
||||
|
||||
#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24)
|
||||
#define SPI_USR_COMMAND_BITLEN 0x0000000F
|
||||
#define SPI_USR_COMMAND_BITLEN_S 28
|
||||
#define SPI_USR_COMMAND_VALUE 0x0000FFFF
|
||||
#define SPI_USR_COMMAND_VALUE_S 0
|
||||
|
||||
#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28)
|
||||
//previously defined as SPI_FLASH_USER3. No further info available.
|
||||
|
||||
#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C)
|
||||
#define SPI_IDLE_EDGE (BIT(29))
|
||||
#define SPI_CS2_DIS (BIT(2))
|
||||
#define SPI_CS1_DIS (BIT(1))
|
||||
#define SPI_CS0_DIS (BIT(0))
|
||||
|
||||
#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30)
|
||||
#define SPI_SYNC_RESET (BIT(31))
|
||||
#define SPI_SLAVE_MODE (BIT(30))
|
||||
#define SPI_SLV_WR_RD_BUF_EN (BIT(29))
|
||||
#define SPI_SLV_WR_RD_STA_EN (BIT(28))
|
||||
#define SPI_SLV_CMD_DEFINE (BIT(27))
|
||||
#define SPI_TRANS_CNT 0x0000000F
|
||||
#define SPI_TRANS_CNT_S 23
|
||||
#define SPI_SLV_LAST_STATE 0x00000007 //From previous SDK
|
||||
#define SPI_SLV_LAST_STATE_S 20 //From previous SDK
|
||||
#define SPI_SLV_LAST_COMMAND 0x00000007 //From previous SDK
|
||||
#define SPI_SLV_LAST_COMMAND_S 17 //From previous SDK
|
||||
#define SPI_CS_I_MODE 0x00000003 //From previous SDK
|
||||
#define SPI_CS_I_MODE_S 10 //From previous SDK
|
||||
#define SPI_TRANS_DONE_EN (BIT(9))
|
||||
#define SPI_SLV_WR_STA_DONE_EN (BIT(8))
|
||||
#define SPI_SLV_RD_STA_DONE_EN (BIT(7))
|
||||
#define SPI_SLV_WR_BUF_DONE_EN (BIT(6))
|
||||
#define SPI_SLV_RD_BUF_DONE_EN (BIT(5))
|
||||
#define SLV_SPI_INT_EN 0x0000001f
|
||||
#define SLV_SPI_INT_EN_S 5
|
||||
#define SPI_TRANS_DONE (BIT(4))
|
||||
#define SPI_SLV_WR_STA_DONE (BIT(3))
|
||||
#define SPI_SLV_RD_STA_DONE (BIT(2))
|
||||
#define SPI_SLV_WR_BUF_DONE (BIT(1))
|
||||
#define SPI_SLV_RD_BUF_DONE (BIT(0))
|
||||
|
||||
#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34)
|
||||
#define SPI_SLV_STATUS_BITLEN 0x0000001F
|
||||
#define SPI_SLV_STATUS_BITLEN_S 27
|
||||
#define SPI_SLV_STATUS_FAST_EN (BIT(26)) //From previous SDK
|
||||
#define SPI_SLV_STATUS_READBACK (BIT(25)) //From previous SDK
|
||||
#define SPI_SLV_BUF_BITLEN 0x000001FF
|
||||
#define SPI_SLV_BUF_BITLEN_S 16
|
||||
#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_SLV_RD_ADDR_BITLEN_S 10
|
||||
#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_SLV_WR_ADDR_BITLEN_S 4
|
||||
#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3))
|
||||
#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2))
|
||||
#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1))
|
||||
#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0))
|
||||
|
||||
|
||||
|
||||
#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38)
|
||||
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24
|
||||
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16
|
||||
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8
|
||||
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF
|
||||
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0
|
||||
|
||||
#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C)
|
||||
#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_WRSTA_CMD_VALUE_S 24
|
||||
#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_RDSTA_CMD_VALUE_S 16
|
||||
#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_WRBUF_CMD_VALUE_S 8
|
||||
#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_RDBUF_CMD_VALUE_S 0
|
||||
|
||||
//Previous SDKs referred to these following registers as SPI_C0 etc.
|
||||
|
||||
#define SPI_W0(i) (REG_SPI_BASE(i) +0x40)
|
||||
#define SPI_W1(i) (REG_SPI_BASE(i) +0x44)
|
||||
#define SPI_W2(i) (REG_SPI_BASE(i) +0x48)
|
||||
#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C)
|
||||
#define SPI_W4(i) (REG_SPI_BASE(i) +0x50)
|
||||
#define SPI_W5(i) (REG_SPI_BASE(i) +0x54)
|
||||
#define SPI_W6(i) (REG_SPI_BASE(i) +0x58)
|
||||
#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C)
|
||||
#define SPI_W8(i) (REG_SPI_BASE(i) +0x60)
|
||||
#define SPI_W9(i) (REG_SPI_BASE(i) +0x64)
|
||||
#define SPI_W10(i) (REG_SPI_BASE(i) +0x68)
|
||||
#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C)
|
||||
#define SPI_W12(i) (REG_SPI_BASE(i) +0x70)
|
||||
#define SPI_W13(i) (REG_SPI_BASE(i) +0x74)
|
||||
#define SPI_W14(i) (REG_SPI_BASE(i) +0x78)
|
||||
#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C)
|
||||
|
||||
// +0x80 to +0xBC could be SPI_W16 through SPI_W31?
|
||||
|
||||
// +0xC0 to +0xEC not currently defined.
|
||||
|
||||
#define SPI_EXT0(i) (REG_SPI_BASE(i) + 0xF0) //From previous SDK. Removed _FLASH_ from name to match other registers.
|
||||
#define SPI_T_PP_ENA (BIT(31)) //From previous SDK
|
||||
#define SPI_T_PP_SHIFT 0x0000000F //From previous SDK
|
||||
#define SPI_T_PP_SHIFT_S 16 //From previous SDK
|
||||
#define SPI_T_PP_TIME 0x00000FFF //From previous SDK
|
||||
#define SPI_T_PP_TIME_S 0 //From previous SDK
|
||||
|
||||
#define SPI_EXT1(i) (REG_SPI_BASE(i) + 0xF4) //From previous SDK. Removed _FLASH_ from name to match other registers.
|
||||
#define SPI_T_ERASE_ENA (BIT(31)) //From previous SDK
|
||||
#define SPI_T_ERASE_SHIFT 0x0000000F //From previous SDK
|
||||
#define SPI_T_ERASE_SHIFT_S 16 //From previous SDK
|
||||
#define SPI_T_ERASE_TIME 0x00000FFF //From previous SDK
|
||||
#define SPI_T_ERASE_TIME_S 0 //From previous SDK
|
||||
|
||||
#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8) //From previous SDK. Removed _FLASH_ from name to match other registers.
|
||||
#define SPI_ST 0x00000007 //From previous SDK
|
||||
#define SPI_ST_S 0 //From previous SDK
|
||||
|
||||
#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
|
||||
#define SPI_INT_HOLD_ENA 0x00000003
|
||||
#define SPI_INT_HOLD_ENA_S 0
|
||||
#endif // SPI_REGISTER_H_INCLUDED
|
|
@ -49,6 +49,8 @@
|
|||
//#define MACHINE_WAKE_SLEEP (0x02)
|
||||
#define MACHINE_WAKE_DEEPSLEEP (0x04)
|
||||
|
||||
extern const mp_obj_type_t esp_wdt_type;
|
||||
|
||||
STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
// get
|
||||
|
@ -246,20 +248,23 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
|||
|
||||
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&esp_timer_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&esp_wdt_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pyb_pin_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pyb_pwm_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_hspi_type) },
|
||||
|
||||
// wake abilities
|
||||
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) },
|
||||
|
||||
// reset causes
|
||||
{ MP_ROM_QSTR(MP_QSTR_PWR_ON_RESET), MP_ROM_INT(REASON_EXT_SYS_RST) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(REASON_DEFAULT_RST) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(REASON_EXT_SYS_RST) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(REASON_DEEP_SLEEP_AWAKE) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(REASON_WDT_RST) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(REASON_SOFT_RESTART) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "user_interface.h"
|
||||
#include "etshal.h"
|
||||
|
||||
const mp_obj_type_t esp_wdt_type;
|
||||
|
||||
typedef struct _machine_wdt_obj_t {
|
||||
mp_obj_base_t base;
|
||||
} machine_wdt_obj_t;
|
||||
|
||||
STATIC machine_wdt_obj_t wdt_default = {{&esp_wdt_type}};
|
||||
|
||||
STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
|
||||
mp_int_t id = 0;
|
||||
if (n_args > 0) {
|
||||
id = mp_obj_get_int(args[0]);
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case 0:
|
||||
return &wdt_default;
|
||||
default:
|
||||
mp_raise_ValueError("");
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
system_soft_wdt_feed();
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed);
|
||||
|
||||
STATIC mp_obj_t machine_wdt_deinit(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
ets_wdt_disable();
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_deinit_obj, machine_wdt_deinit);
|
||||
|
||||
STATIC const mp_map_elem_t machine_wdt_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_feed), (mp_obj_t)&machine_wdt_feed_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&machine_wdt_deinit_obj },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t esp_wdt_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_WDT,
|
||||
.make_new = machine_wdt_make_new,
|
||||
.locals_dict = (mp_obj_t)&machine_wdt_locals_dict,
|
||||
};
|
|
@ -130,17 +130,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_status_obj, esp_status);
|
|||
|
||||
STATIC mp_obj_t *esp_scan_list = NULL;
|
||||
|
||||
STATIC void esp_scan_cb(scaninfo *si, STATUS status) {
|
||||
STATIC void esp_scan_cb(void *result, STATUS status) {
|
||||
if (esp_scan_list == NULL) {
|
||||
// called unexpectedly
|
||||
return;
|
||||
}
|
||||
if (si->pbss && status == 0) {
|
||||
if (result && status == 0) {
|
||||
// we need to catch any memory errors
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
struct bss_info *bs;
|
||||
STAILQ_FOREACH(bs, si->pbss, next) {
|
||||
for (struct bss_info *bs = result; bs; bs = STAILQ_NEXT(bs, next)) {
|
||||
mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
|
||||
#if 1
|
||||
// struct bss_info::ssid_len is not documented in SDK API Guide,
|
||||
|
|
|
@ -10,6 +10,8 @@ extern const mp_obj_type_t pyb_rtc_type;
|
|||
extern const mp_obj_type_t pyb_uart_type;
|
||||
extern const mp_obj_type_t pyb_i2c_type;
|
||||
extern const mp_obj_type_t pyb_spi_type;
|
||||
extern const mp_obj_type_t pyb_hspi_type;
|
||||
extern const mp_obj_type_t machine_spi_type;
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(pyb_info_obj);
|
||||
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Damien P. George
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ets_sys.h"
|
||||
#include "etshal.h"
|
||||
#include "ets_alt_task.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
|
||||
#include "hspi.h"
|
||||
|
||||
mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||
size_t n_kw, const mp_obj_t *args);
|
||||
|
||||
typedef struct _pyb_hspi_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint32_t baudrate;
|
||||
uint8_t polarity;
|
||||
uint8_t phase;
|
||||
} pyb_hspi_obj_t;
|
||||
|
||||
|
||||
STATIC void hspi_transfer(mp_obj_base_t *self_in, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf) {
|
||||
(void)self_in;
|
||||
|
||||
if (dest_len == 0) {
|
||||
// fast case when we only need to write data
|
||||
size_t chunk_size = 1024;
|
||||
size_t count = src_len / chunk_size;
|
||||
size_t i = 0;
|
||||
for (size_t j = 0; j < count; ++j) {
|
||||
for (size_t k = 0; k < chunk_size; ++k) {
|
||||
spi_tx8fast(HSPI, src_buf[i]);
|
||||
++i;
|
||||
}
|
||||
ets_loop_iter();
|
||||
}
|
||||
while (i < src_len) {
|
||||
spi_tx8fast(HSPI, src_buf[i]);
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
// we need to read and write data
|
||||
|
||||
// Process data in chunks, let the pending tasks run in between
|
||||
size_t chunk_size = 1024; // TODO this should depend on baudrate
|
||||
size_t count = dest_len / chunk_size;
|
||||
size_t i = 0;
|
||||
for (size_t j = 0; j < count; ++j) {
|
||||
for (size_t k = 0; k < chunk_size; ++k) {
|
||||
uint32_t data_out;
|
||||
if (src_len == 1) {
|
||||
data_out = src_buf[0];
|
||||
} else {
|
||||
data_out = src_buf[i];
|
||||
}
|
||||
dest_buf[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, data_out, 8, 0);
|
||||
++i;
|
||||
}
|
||||
ets_loop_iter();
|
||||
}
|
||||
while (i < dest_len) {
|
||||
uint32_t data_out;
|
||||
if (src_len == 1) {
|
||||
data_out = src_buf[0];
|
||||
} else {
|
||||
data_out = src_buf[i];
|
||||
}
|
||||
dest_buf[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, data_out, 8, 0);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
// MicroPython bindings for HSPI
|
||||
|
||||
STATIC void pyb_hspi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
pyb_hspi_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "HSPI(id=1, baudrate=%u, polarity=%u, phase=%u)",
|
||||
self->baudrate, self->polarity, self->phase);
|
||||
}
|
||||
|
||||
STATIC void pyb_hspi_init_helper(pyb_hspi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} },
|
||||
};
|
||||
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);
|
||||
|
||||
if (args[ARG_baudrate].u_int != -1) {
|
||||
self->baudrate = args[ARG_baudrate].u_int;
|
||||
}
|
||||
if (args[ARG_polarity].u_int != -1) {
|
||||
self->polarity = args[ARG_polarity].u_int;
|
||||
}
|
||||
if (args[ARG_phase].u_int != -1) {
|
||||
self->phase = args[ARG_phase].u_int;
|
||||
}
|
||||
if (self->baudrate == 80000000L) {
|
||||
// Special case for full speed.
|
||||
spi_init_gpio(HSPI, SPI_CLK_80MHZ_NODIV);
|
||||
spi_clock(HSPI, 0, 0);
|
||||
} else if (self->baudrate > 40000000L) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"impossible baudrate"));
|
||||
} else {
|
||||
uint32_t divider = 40000000L / self->baudrate;
|
||||
uint16_t prediv = MIN(divider, SPI_CLKDIV_PRE + 1);
|
||||
uint16_t cntdiv = (divider / prediv) * 2; // cntdiv has to be even
|
||||
if (cntdiv > SPI_CLKCNT_N + 1 || cntdiv == 0 || prediv == 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"impossible baudrate"));
|
||||
}
|
||||
self->baudrate = 80000000L / (prediv * cntdiv);
|
||||
spi_init_gpio(HSPI, SPI_CLK_USE_DIV);
|
||||
spi_clock(HSPI, prediv, cntdiv);
|
||||
}
|
||||
// TODO: Make the byte order configurable too (discuss param names)
|
||||
spi_tx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW);
|
||||
spi_rx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE | SPI_USR_MISO |
|
||||
SPI_USR_ADDR | SPI_USR_COMMAND | SPI_USR_DUMMY);
|
||||
// Clear Dual or Quad lines transmission mode
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL(HSPI), SPI_QIO_MODE | SPI_DIO_MODE |
|
||||
SPI_DOUT_MODE | SPI_QOUT_MODE);
|
||||
spi_mode(HSPI, self->phase, self->polarity);
|
||||
}
|
||||
|
||||
mp_obj_t pyb_hspi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, true);
|
||||
mp_int_t id = -1;
|
||||
if (n_args > 0) {
|
||||
id = mp_obj_get_int(args[0]);
|
||||
}
|
||||
|
||||
if (id == -1) {
|
||||
// Multiplex to bitbanging SPI
|
||||
if (n_args > 0) {
|
||||
args++;
|
||||
}
|
||||
return pyb_spi_make_new(type, 0, n_kw, args);
|
||||
}
|
||||
|
||||
if (id != 1) {
|
||||
// FlashROM is on SPI0, so far we don't support its usage
|
||||
mp_raise_ValueError("");
|
||||
}
|
||||
|
||||
pyb_hspi_obj_t *self = m_new_obj(pyb_hspi_obj_t);
|
||||
self->base.type = &pyb_hspi_type;
|
||||
// set defaults
|
||||
self->baudrate = 80000000L;
|
||||
self->polarity = 0;
|
||||
self->phase = 0;
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
pyb_hspi_init_helper(self, n_args, args, &kw_args);
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_hspi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
pyb_hspi_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_hspi_init_obj, 1, pyb_hspi_init);
|
||||
|
||||
STATIC const mp_rom_map_elem_t pyb_hspi_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_hspi_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_hspi_locals_dict, pyb_hspi_locals_dict_table);
|
||||
|
||||
STATIC const mp_machine_spi_p_t pyb_hspi_p = {
|
||||
.transfer = hspi_transfer,
|
||||
};
|
||||
|
||||
const mp_obj_type_t pyb_hspi_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_HSPI,
|
||||
.print = pyb_hspi_print,
|
||||
.make_new = pyb_hspi_make_new,
|
||||
.protocol = &pyb_hspi_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&pyb_hspi_locals_dict,
|
||||
};
|
|
@ -244,7 +244,11 @@ STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, c
|
|||
|
||||
// configure the GPIO as requested
|
||||
if (self->phys_port == 16) {
|
||||
// TODO: Set pull up/pull down
|
||||
// only pull-down seems to be supported by the hardware, and
|
||||
// we only expose pull-up behaviour in software
|
||||
if (pull != GPIO_PULL_NONE) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin(16) doesn't support pull"));
|
||||
}
|
||||
} else {
|
||||
PIN_FUNC_SELECT(self->periph, self->func);
|
||||
#if 0
|
||||
|
@ -301,7 +305,7 @@ STATIC mp_obj_t pyb_pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
|
|||
pyb_pin_obj_t *self = self_in;
|
||||
if (n_args == 0) {
|
||||
// get pin
|
||||
return MP_OBJ_NEW_SMALL_INT(GPIO_INPUT_GET(self->phys_port));
|
||||
return MP_OBJ_NEW_SMALL_INT(pin_get(self->phys_port));
|
||||
} else {
|
||||
// set pin
|
||||
pin_set(self->phys_port, mp_obj_is_true(args[0]));
|
||||
|
|
|
@ -212,7 +212,7 @@ STATIC mp_obj_t pyb_rtc_alarm(mp_obj_t self_in, mp_obj_t alarm_id, mp_obj_t time
|
|||
}
|
||||
|
||||
// set expiry time (in microseconds)
|
||||
pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_2000() + mp_obj_get_int(time_in) * 1000;
|
||||
pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_2000() + (uint64_t)mp_obj_get_int(time_in) * 1000;
|
||||
|
||||
return mp_const_none;
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
|
||||
typedef struct _pyb_spi_obj_t {
|
||||
mp_obj_base_t base;
|
||||
|
@ -46,7 +47,8 @@ typedef struct _pyb_spi_obj_t {
|
|||
mp_hal_pin_obj_t miso;
|
||||
} pyb_spi_obj_t;
|
||||
|
||||
STATIC void mp_hal_spi_transfer(pyb_spi_obj_t *self, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf) {
|
||||
STATIC void mp_hal_spi_transfer(mp_obj_base_t *self_in, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf) {
|
||||
pyb_spi_obj_t *self = (pyb_spi_obj_t*)self_in;
|
||||
// only MSB transfer is implemented
|
||||
uint32_t delay_half = 500000 / self->baudrate + 1;
|
||||
for (size_t i = 0; i < src_len || i < dest_len; ++i) {
|
||||
|
@ -131,7 +133,7 @@ STATIC void pyb_spi_init_helper(pyb_spi_obj_t *self, size_t n_args, const mp_obj
|
|||
mp_hal_pin_input(self->miso);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
pyb_spi_obj_t *self = m_new_obj(pyb_spi_obj_t);
|
||||
self->base.type = &pyb_spi_type;
|
||||
|
@ -154,69 +156,25 @@ STATIC mp_obj_t pyb_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_a
|
|||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init);
|
||||
|
||||
STATIC mp_obj_t pyb_spi_read(size_t n_args, const mp_obj_t *args) {
|
||||
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
uint8_t write_byte = 0;
|
||||
if (n_args == 3) {
|
||||
write_byte = mp_obj_get_int(args[2]);
|
||||
}
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, mp_obj_get_int(args[1]));
|
||||
mp_hal_spi_transfer(self, 1, &write_byte, vstr.len, (uint8_t*)vstr.buf);
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_spi_read_obj, 2, 3, pyb_spi_read);
|
||||
|
||||
STATIC mp_obj_t pyb_spi_readinto(size_t n_args, const mp_obj_t *args) {
|
||||
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
|
||||
uint8_t write_byte = 0;
|
||||
if (n_args == 3) {
|
||||
write_byte = mp_obj_get_int(args[2]);
|
||||
}
|
||||
mp_hal_spi_transfer(self, 1, &write_byte, bufinfo.len, (uint8_t*)bufinfo.buf);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_spi_readinto_obj, 2, 3, pyb_spi_readinto);
|
||||
|
||||
STATIC mp_obj_t pyb_spi_write(mp_obj_t self_in, mp_obj_t wr_buf_in) {
|
||||
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_buffer_info_t src_buf;
|
||||
mp_get_buffer_raise(wr_buf_in, &src_buf, MP_BUFFER_READ);
|
||||
mp_hal_spi_transfer(self, src_buf.len, (const uint8_t*)src_buf.buf, 0, NULL);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_write_obj, pyb_spi_write);
|
||||
|
||||
STATIC mp_obj_t pyb_spi_write_readinto(mp_obj_t self_in, mp_obj_t wr_buf_in, mp_obj_t rd_buf_in) {
|
||||
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_buffer_info_t src_buf;
|
||||
mp_get_buffer_raise(wr_buf_in, &src_buf, MP_BUFFER_READ);
|
||||
mp_buffer_info_t dest_buf;
|
||||
mp_get_buffer_raise(rd_buf_in, &dest_buf, MP_BUFFER_WRITE);
|
||||
if (src_buf.len != dest_buf.len) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "buffers must be the same length"));
|
||||
}
|
||||
mp_hal_spi_transfer(self, src_buf.len, (const uint8_t*)src_buf.buf, dest_buf.len, (uint8_t*)dest_buf.buf);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(pyb_spi_write_readinto_obj, pyb_spi_write_readinto);
|
||||
|
||||
STATIC const mp_rom_map_elem_t pyb_spi_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_spi_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&pyb_spi_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&pyb_spi_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_spi_write_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&pyb_spi_write_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);
|
||||
|
||||
STATIC const mp_machine_spi_p_t pyb_spi_p = {
|
||||
.transfer = mp_hal_spi_transfer,
|
||||
};
|
||||
|
||||
const mp_obj_type_t pyb_spi_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_SPI,
|
||||
.name = MP_QSTR_SoftSPI,
|
||||
.print = pyb_spi_print,
|
||||
.make_new = pyb_spi_make_new,
|
||||
.protocol = &pyb_spi_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&pyb_spi_locals_dict,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
# DS18x20 temperature sensor driver for MicroPython.
|
||||
# MIT license; Copyright (c) 2016 Damien P. George
|
||||
|
||||
_CONVERT = const(0x44)
|
||||
_RD_SCRATCH = const(0xbe)
|
||||
_WR_SCRATCH = const(0x4e)
|
||||
|
||||
class DS18X20:
|
||||
def __init__(self, onewire):
|
||||
self.ow = onewire
|
||||
self.buf = bytearray(9)
|
||||
|
||||
def scan(self):
|
||||
return [rom for rom in self.ow.scan() if rom[0] == 0x10 or rom[0] == 0x28]
|
||||
|
||||
def convert_temp(self):
|
||||
self.ow.reset(True)
|
||||
self.ow.writebyte(self.ow.SKIP_ROM)
|
||||
self.ow.writebyte(_CONVERT)
|
||||
|
||||
def read_scratch(self, rom):
|
||||
self.ow.reset(True)
|
||||
self.ow.select_rom(rom)
|
||||
self.ow.writebyte(_RD_SCRATCH)
|
||||
self.ow.readinto(self.buf)
|
||||
if self.ow.crc8(self.buf):
|
||||
raise Exception('CRC error')
|
||||
return self.buf
|
||||
|
||||
def write_scratch(self, rom, buf):
|
||||
self.ow.reset(True)
|
||||
self.ow.select_rom(rom)
|
||||
self.ow.writebyte(_WR_SCRATCH)
|
||||
self.ow.write(buf)
|
||||
|
||||
def read_temp(self, rom):
|
||||
buf = self.read_scratch(rom)
|
||||
if rom[0] == 0x10:
|
||||
if buf[1]:
|
||||
t = buf[0] >> 1 | 0x80
|
||||
t = -((~t + 1) & 0xff)
|
||||
else:
|
||||
t = buf[0] >> 1
|
||||
return t - 0.25 + (buf[7] - buf[6]) / buf[7]
|
||||
else:
|
||||
return (buf[1] << 8 | buf[0]) / 16
|
|
@ -15,8 +15,11 @@ class OneWire:
|
|||
self.pin = pin
|
||||
self.pin.init(pin.OPEN_DRAIN)
|
||||
|
||||
def reset(self):
|
||||
return _ow.reset(self.pin)
|
||||
def reset(self, required=False):
|
||||
reset = _ow.reset(self.pin)
|
||||
if required and not reset:
|
||||
raise OneWireError
|
||||
return reset
|
||||
|
||||
def readbit(self):
|
||||
return _ow.readbit(self.pin)
|
||||
|
@ -24,11 +27,9 @@ class OneWire:
|
|||
def readbyte(self):
|
||||
return _ow.readbyte(self.pin)
|
||||
|
||||
def read(self, count):
|
||||
buf = bytearray(count)
|
||||
for i in range(count):
|
||||
def readinto(self, buf):
|
||||
for i in range(len(buf)):
|
||||
buf[i] = _ow.readbyte(self.pin)
|
||||
return buf
|
||||
|
||||
def writebit(self, value):
|
||||
return _ow.writebit(self.pin, value)
|
||||
|
@ -87,41 +88,3 @@ class OneWire:
|
|||
|
||||
def crc8(self, data):
|
||||
return _ow.crc8(data)
|
||||
|
||||
class DS18B20:
|
||||
CONVERT = const(0x44)
|
||||
RD_SCRATCH = const(0xbe)
|
||||
WR_SCRATCH = const(0x4e)
|
||||
|
||||
def __init__(self, onewire):
|
||||
self.ow = onewire
|
||||
|
||||
def scan(self):
|
||||
return [rom for rom in self.ow.scan() if rom[0] == 0x28]
|
||||
|
||||
def convert_temp(self):
|
||||
if not self.ow.reset():
|
||||
raise OneWireError
|
||||
self.ow.writebyte(SKIP_ROM)
|
||||
self.ow.writebyte(CONVERT)
|
||||
|
||||
def read_scratch(self, rom):
|
||||
if not self.ow.reset():
|
||||
raise OneWireError
|
||||
self.ow.select_rom(rom)
|
||||
self.ow.writebyte(RD_SCRATCH)
|
||||
buf = self.ow.read(9)
|
||||
if self.ow.crc8(buf):
|
||||
raise OneWireError
|
||||
return buf
|
||||
|
||||
def write_scratch(self, rom, buf):
|
||||
if not self.ow.reset():
|
||||
raise OneWireError
|
||||
self.ow.select_rom(rom)
|
||||
self.ow.writebyte(WR_SCRATCH)
|
||||
self.ow.write(buf)
|
||||
|
||||
def read_temp(self, rom):
|
||||
buf = self.read_scratch(rom)
|
||||
return (buf[1] << 8 | buf[0]) / 16
|
|
@ -123,6 +123,10 @@ STATIC mp_obj_t os_rename(mp_obj_t path_old, mp_obj_t path_new) {
|
|||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename);
|
||||
|
||||
STATIC mp_obj_t os_umount(void) {
|
||||
return vfs_proxy_call(MP_QSTR_umount, 0, NULL);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_umount_obj, os_umount);
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t os_urandom(mp_obj_t num) {
|
||||
|
@ -166,6 +170,7 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&os_remove_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&os_rename_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&os_stat_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&os_umount_obj) },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#define MICROPY_MODULE_WEAK_LINKS (1)
|
||||
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
|
||||
#define MICROPY_USE_INTERNAL_ERRNO (1)
|
||||
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
|
||||
#define MICROPY_PY_BUILTINS_COMPLEX (0)
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
|
||||
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
|
||||
|
@ -62,6 +63,7 @@
|
|||
#define MICROPY_PY_MACHINE (1)
|
||||
#define MICROPY_PY_MACHINE_PULSE (1)
|
||||
#define MICROPY_PY_MACHINE_I2C (1)
|
||||
#define MICROPY_PY_MACHINE_SPI (1)
|
||||
#define MICROPY_PY_WEBSOCKET (1)
|
||||
#define MICROPY_PY_WEBREPL (1)
|
||||
#define MICROPY_PY_WEBREPL_DELAY (20)
|
||||
|
@ -114,8 +116,6 @@
|
|||
|
||||
typedef int32_t mp_int_t; // must be pointer size
|
||||
typedef uint32_t mp_uint_t; // must be pointer size
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
typedef long mp_off_t;
|
||||
typedef uint32_t sys_prot_t; // for modlwip
|
||||
// ssize_t, off_t as required by POSIX-signatured functions in stream.h
|
||||
|
|
|
@ -16,10 +16,10 @@ pyb.LED(3).off() # indicate that we finished waiting for the swit
|
|||
pyb.LED(4).on() # indicate that we are selecting the mode
|
||||
|
||||
if switch_value:
|
||||
pyb.usb_mode('CDC+MSC')
|
||||
pyb.usb_mode('VCP+MSC')
|
||||
pyb.main('cardreader.py') # if switch was pressed, run this
|
||||
else:
|
||||
pyb.usb_mode('CDC+HID')
|
||||
pyb.usb_mode('VCP+HID')
|
||||
pyb.main('datalogger.py') # if switch wasn't pressed, run this
|
||||
|
||||
pyb.LED(4).off() # indicate that we finished selecting the mode
|
||||
|
|
|
@ -127,9 +127,6 @@ typedef long long mp_off_t;
|
|||
typedef long mp_off_t;
|
||||
#endif
|
||||
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
|
||||
// We need to provide a declaration/definition of alloca()
|
||||
#ifdef __FreeBSD__
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -162,7 +162,7 @@ STATIC mp_obj_t fatfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
|
|||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(fsuser_mount_obj, 2, fatfs_mount);
|
||||
|
||||
STATIC mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in) {
|
||||
mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in) {
|
||||
size_t i = 0;
|
||||
if (MP_OBJ_IS_STR(bdev_or_path_in)) {
|
||||
mp_uint_t mnt_len;
|
||||
|
|
|
@ -55,6 +55,7 @@ typedef struct _fs_user_mount_t {
|
|||
} fs_user_mount_t;
|
||||
|
||||
fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, bool mkfs);
|
||||
mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(fsuser_mount_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(fsuser_umount_obj);
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Damien P. George
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_SPI
|
||||
|
||||
STATIC void mp_machine_spi_transfer(mp_obj_t self, size_t slen, const uint8_t *src, size_t dlen, uint8_t *dest) {
|
||||
mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self);
|
||||
mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol;
|
||||
spi_p->transfer(s, slen, src, dlen, dest);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) {
|
||||
uint8_t write_byte = 0;
|
||||
if (n_args == 3) {
|
||||
write_byte = mp_obj_get_int(args[2]);
|
||||
}
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, mp_obj_get_int(args[1]));
|
||||
mp_machine_spi_transfer(args[0], 1, &write_byte, vstr.len, (uint8_t*)vstr.buf);
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read);
|
||||
|
||||
STATIC mp_obj_t mp_machine_spi_readinto(size_t n_args, const mp_obj_t *args) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
|
||||
uint8_t write_byte = 0;
|
||||
if (n_args == 3) {
|
||||
write_byte = mp_obj_get_int(args[2]);
|
||||
}
|
||||
mp_machine_spi_transfer(args[0], 1, &write_byte, bufinfo.len, (uint8_t*)bufinfo.buf);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp_machine_spi_readinto);
|
||||
|
||||
STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self, mp_obj_t wr_buf) {
|
||||
mp_buffer_info_t src;
|
||||
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
|
||||
mp_machine_spi_transfer(self, src.len, (const uint8_t*)src.buf, 0, NULL);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write);
|
||||
|
||||
STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self, mp_obj_t wr_buf, mp_obj_t rd_buf) {
|
||||
mp_buffer_info_t src;
|
||||
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
|
||||
mp_buffer_info_t dest;
|
||||
mp_get_buffer_raise(rd_buf, &dest, MP_BUFFER_WRITE);
|
||||
if (src.len != dest.len) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "buffers must be the same length"));
|
||||
}
|
||||
mp_machine_spi_transfer(self, src.len, (const uint8_t*)src.buf, dest.len, (uint8_t*)dest.buf);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_spi_write_readinto);
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_SPI
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Damien P. George
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
// SPI protocol
|
||||
typedef struct _mp_machine_spi_p_t {
|
||||
void (*transfer)(mp_obj_base_t *obj, size_t slen, const uint8_t *src, size_t dlen, uint8_t *dest);
|
||||
} mp_machine_spi_p_t;
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_read_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_readinto_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_write_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_write_readinto_obj);
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
|
|
@ -133,6 +133,7 @@ STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) {
|
|||
}
|
||||
|
||||
int res = __bt_seq(self->db, &key, &val, flags);
|
||||
CHECK_ERROR(res);
|
||||
if (res == RET_SPECIAL) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
#if MICROPY_PY_FRAMEBUF
|
||||
|
||||
#include "font_petme128_8x8.h"
|
||||
#include "stmhal/font_petme128_8x8.h"
|
||||
|
||||
// 1-bit frame buffer, each byte is a column of 8 pixels
|
||||
typedef struct _mp_obj_framebuf1_t {
|
||||
|
@ -68,7 +68,8 @@ STATIC mp_obj_t framebuf1_fill(mp_obj_t self_in, mp_obj_t col_in) {
|
|||
if (col) {
|
||||
col = 0xff;
|
||||
}
|
||||
for (int y = 0; y < self->height / 8; ++y) {
|
||||
int end = (self->height + 7) >> 3;
|
||||
for (int y = 0; y < end; ++y) {
|
||||
memset(self->buf + y * self->stride, col, self->width);
|
||||
}
|
||||
return mp_const_none;
|
||||
|
@ -83,7 +84,7 @@ STATIC mp_obj_t framebuf1_pixel(size_t n_args, const mp_obj_t *args) {
|
|||
int index = (y / 8) * self->stride + x;
|
||||
if (n_args == 3) {
|
||||
// get
|
||||
return MP_OBJ_NEW_SMALL_INT(self->buf[index] >> (y & 7));
|
||||
return MP_OBJ_NEW_SMALL_INT((self->buf[index] >> (y & 7)) & 1);
|
||||
} else {
|
||||
// set
|
||||
if (mp_obj_get_int(args[3])) {
|
||||
|
@ -101,8 +102,9 @@ STATIC mp_obj_t framebuf1_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t y
|
|||
mp_obj_framebuf1_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_int_t xstep = mp_obj_get_int(xstep_in);
|
||||
mp_int_t ystep = mp_obj_get_int(ystep_in);
|
||||
if (xstep == 0 && ystep > 0) {
|
||||
for (int y = self->height / 8; y > 0;) {
|
||||
int end = (self->height + 7) >> 3;
|
||||
if (ystep > 0) {
|
||||
for (int y = end; y > 0;) {
|
||||
--y;
|
||||
for (int x = 0; x < self->width; ++x) {
|
||||
int prev = 0;
|
||||
|
@ -112,18 +114,31 @@ STATIC mp_obj_t framebuf1_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t y
|
|||
self->buf[y * self->stride + x] = (self->buf[y * self->stride + x] << ystep) | prev;
|
||||
}
|
||||
}
|
||||
} else if (xstep == 0 && ystep < 0) {
|
||||
for (int y = 0; y < self->height / 8; ++y) {
|
||||
} else if (ystep < 0) {
|
||||
for (int y = 0; y < end; ++y) {
|
||||
for (int x = 0; x < self->width; ++x) {
|
||||
int prev = 0;
|
||||
if (y + 1 < self->height / 8) {
|
||||
if (y + 1 < end) {
|
||||
prev = self->buf[(y + 1) * self->stride + x] << (8 + ystep);
|
||||
}
|
||||
self->buf[y * self->stride + x] = (self->buf[y * self->stride + x] >> -ystep) | prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO xstep!=0
|
||||
if (xstep < 0) {
|
||||
for (int y = 0; y < end; ++y) {
|
||||
for (int x = 0; x < self->width + xstep; ++x) {
|
||||
self->buf[y * self->stride + x] = self->buf[y * self->stride + x - xstep];
|
||||
}
|
||||
}
|
||||
} else if (xstep > 0) {
|
||||
for (int y = 0; y < end; ++y) {
|
||||
for (int x = self->width - 1; x >= xstep; --x) {
|
||||
self->buf[y * self->stride + x] = self->buf[y * self->stride + x - xstep];
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Should we clear the margin created by scrolling?
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf1_scroll_obj, framebuf1_scroll);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "py/binary.h"
|
||||
#include "extmod/modubinascii.h"
|
||||
|
||||
#include "uzlib/tinf.h"
|
||||
|
||||
mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
|
||||
// Second argument is for an extension to allow a separator to be used
|
||||
|
@ -203,6 +204,17 @@ mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
|
|||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64);
|
||||
|
||||
#if MICROPY_PY_UBINASCII_CRC32
|
||||
mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
|
||||
uint32_t crc = (n_args > 1) ? mp_obj_get_int(args[1]) : 0;
|
||||
crc = uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff);
|
||||
return MP_OBJ_NEW_SMALL_INT(crc ^ 0xffffffff);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UBINASCII
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = {
|
||||
|
@ -211,6 +223,9 @@ STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&mod_binascii_unhexlify_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) },
|
||||
#if MICROPY_PY_UBINASCII_CRC32
|
||||
{ MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&mod_binascii_crc32_obj) },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table);
|
||||
|
|
|
@ -31,10 +31,12 @@ extern mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args);
|
|||
extern mp_obj_t mod_binascii_unhexlify(mp_obj_t data);
|
||||
extern mp_obj_t mod_binascii_a2b_base64(mp_obj_t data);
|
||||
extern mp_obj_t mod_binascii_b2a_base64(mp_obj_t data);
|
||||
extern mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_hexlify_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_unhexlify_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_a2b_base64_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_b2a_base64_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_crc32_obj);
|
||||
|
||||
#endif /* MICROPY_EXTMOD_MODUBINASCII */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Paul Sokolovsky
|
||||
* Copyright (c) 2014-2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -25,9 +25,12 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mperrno.h"
|
||||
|
||||
#if MICROPY_PY_UZLIB
|
||||
|
||||
|
@ -39,16 +42,99 @@
|
|||
#define DEBUG_printf(...) (void)0
|
||||
#endif
|
||||
|
||||
STATIC int mod_uzlib_grow_buf(TINF_DATA *d, unsigned alloc_req) {
|
||||
if (alloc_req < 256) {
|
||||
alloc_req = 256;
|
||||
typedef struct _mp_obj_decompio_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t src_stream;
|
||||
TINF_DATA decomp;
|
||||
bool eof;
|
||||
} mp_obj_decompio_t;
|
||||
|
||||
STATIC unsigned char read_src_stream(TINF_DATA *data) {
|
||||
byte *p = (void*)data;
|
||||
p -= offsetof(mp_obj_decompio_t, decomp);
|
||||
mp_obj_decompio_t *self = (mp_obj_decompio_t*)p;
|
||||
|
||||
const mp_stream_p_t *stream = mp_get_stream_raise(self->src_stream, MP_STREAM_OP_READ);
|
||||
int err;
|
||||
byte c;
|
||||
mp_uint_t out_sz = stream->read(self->src_stream, &c, 1, &err);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(err)));
|
||||
}
|
||||
DEBUG_printf("uzlib: Resizing buffer to " UINT_FMT " bytes\n", d->destSize + alloc_req);
|
||||
d->destStart = m_renew(byte, d->destStart, d->destSize, d->destSize + alloc_req);
|
||||
d->destSize += alloc_req;
|
||||
if (out_sz == 0) {
|
||||
nlr_raise(mp_obj_new_exception(&mp_type_EOFError));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, 2, false);
|
||||
mp_obj_decompio_t *o = m_new_obj(mp_obj_decompio_t);
|
||||
o->base.type = type;
|
||||
memset(&o->decomp, 0, sizeof(o->decomp));
|
||||
o->decomp.readSource = read_src_stream;
|
||||
o->src_stream = args[0];
|
||||
o->eof = false;
|
||||
|
||||
mp_int_t dict_opt = 0;
|
||||
int dict_sz;
|
||||
if (n_args > 1) {
|
||||
dict_opt = mp_obj_get_int(args[1]);
|
||||
}
|
||||
if (dict_opt >= 0) {
|
||||
dict_opt = uzlib_zlib_parse_header(&o->decomp);
|
||||
if (dict_opt < 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "zlib header"));
|
||||
}
|
||||
dict_sz = 1 << dict_opt;
|
||||
} else {
|
||||
dict_sz = 1 << -dict_opt;
|
||||
}
|
||||
|
||||
uzlib_uncompress_init(&o->decomp, m_new(byte, dict_sz), dict_sz);
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_decompio_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
if (o->eof) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
o->decomp.dest = buf;
|
||||
o->decomp.destSize = size;
|
||||
int st = uzlib_uncompress_chksum(&o->decomp);
|
||||
if (st == TINF_DONE) {
|
||||
o->eof = true;
|
||||
}
|
||||
if (st < 0) {
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return o->decomp.dest - (byte*)buf;
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
|
||||
|
||||
STATIC const mp_stream_p_t decompio_stream_p = {
|
||||
.read = decompio_read,
|
||||
};
|
||||
|
||||
STATIC const mp_obj_type_t decompio_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_DecompIO,
|
||||
.make_new = decompio_make_new,
|
||||
.protocol = &decompio_stream_p,
|
||||
.locals_dict = (void*)&decompio_locals_dict,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
mp_obj_t data = args[0];
|
||||
|
@ -56,36 +142,62 @@ STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
|
|||
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
TINF_DATA *decomp = m_new_obj(TINF_DATA);
|
||||
memset(decomp, 0, sizeof(*decomp));
|
||||
DEBUG_printf("sizeof(TINF_DATA)=" UINT_FMT "\n", sizeof(*decomp));
|
||||
uzlib_uncompress_init(decomp, NULL, 0);
|
||||
mp_uint_t dest_buf_size = (bufinfo.len + 15) & ~15;
|
||||
byte *dest_buf = m_new(byte, dest_buf_size);
|
||||
|
||||
decomp->destSize = (bufinfo.len + 15) & ~15;
|
||||
decomp->destStart = m_new(byte, decomp->destSize);
|
||||
decomp->dest = dest_buf;
|
||||
decomp->destSize = dest_buf_size;
|
||||
DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", decomp->destSize);
|
||||
decomp->destGrow = mod_uzlib_grow_buf;
|
||||
decomp->source = bufinfo.buf;
|
||||
|
||||
int st;
|
||||
bool is_zlib = true;
|
||||
|
||||
if (n_args > 1 && MP_OBJ_SMALL_INT_VALUE(args[1]) < 0) {
|
||||
st = tinf_uncompress_dyn(decomp);
|
||||
} else {
|
||||
st = tinf_zlib_uncompress_dyn(decomp, bufinfo.len);
|
||||
}
|
||||
if (st != 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st)));
|
||||
is_zlib = false;
|
||||
}
|
||||
|
||||
mp_uint_t final_sz = decomp->dest - decomp->destStart;
|
||||
DEBUG_printf("uzlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", decomp->destSize, final_sz);
|
||||
decomp->destStart = (byte*)m_renew(byte, decomp->destStart, decomp->destSize, final_sz);
|
||||
mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, decomp->destStart);
|
||||
if (is_zlib) {
|
||||
st = uzlib_zlib_parse_header(decomp);
|
||||
if (st < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
st = uzlib_uncompress_chksum(decomp);
|
||||
if (st < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (st == TINF_DONE) {
|
||||
break;
|
||||
}
|
||||
size_t offset = decomp->dest - dest_buf;
|
||||
dest_buf = m_renew(byte, dest_buf, dest_buf_size, dest_buf_size + 256);
|
||||
dest_buf_size += 256;
|
||||
decomp->dest = dest_buf + offset;
|
||||
decomp->destSize = 256;
|
||||
}
|
||||
|
||||
mp_uint_t final_sz = decomp->dest - dest_buf;
|
||||
DEBUG_printf("uzlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", dest_buf_size, final_sz);
|
||||
dest_buf = (byte*)m_renew(byte, dest_buf, dest_buf_size, final_sz);
|
||||
mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, dest_buf);
|
||||
m_del_obj(TINF_DATA, decomp);
|
||||
return res;
|
||||
|
||||
error:
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_uzlib_decompress);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_uzlib_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uzlib) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&mod_uzlib_decompress_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DecompIO), MP_ROM_PTR(&decompio_type) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_uzlib_globals, mp_module_uzlib_globals_table);
|
||||
|
@ -102,5 +214,6 @@ const mp_obj_module_t mp_module_uzlib = {
|
|||
#include "uzlib/tinflate.c"
|
||||
#include "uzlib/tinfzlib.c"
|
||||
#include "uzlib/adler32.c"
|
||||
#include "uzlib/crc32.c"
|
||||
|
||||
#endif // MICROPY_PY_UZLIB
|
||||
|
|
|
@ -310,9 +310,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_close_obj, webrepl_close);
|
|||
STATIC mp_obj_t webrepl_set_password(mp_obj_t passwd_in) {
|
||||
mp_uint_t len;
|
||||
const char *passwd = mp_obj_str_get_data(passwd_in, &len);
|
||||
len = MIN(len, sizeof(webrepl_passwd) - 1);
|
||||
memcpy(webrepl_passwd, passwd, len);
|
||||
webrepl_passwd[len] = 0;
|
||||
if (len > sizeof(webrepl_passwd) - 1) {
|
||||
mp_raise_ValueError("");
|
||||
}
|
||||
strcpy(webrepl_passwd, passwd);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_set_password_obj, webrepl_set_password);
|
||||
|
|
|
@ -41,12 +41,12 @@
|
|||
#define A32_BASE 65521
|
||||
#define A32_NMAX 5552
|
||||
|
||||
unsigned int tinf_adler32(const void *data, unsigned int length)
|
||||
uint32_t uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum /* 1 */)
|
||||
{
|
||||
const unsigned char *buf = (const unsigned char *)data;
|
||||
|
||||
unsigned int s1 = 1;
|
||||
unsigned int s2 = 0;
|
||||
unsigned int s1 = prev_sum & 0xffff;
|
||||
unsigned int s2 = prev_sum >> 16;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* CRC32 checksum
|
||||
*
|
||||
* Copyright (c) 1998-2003 by Joergen Ibsen / Jibz
|
||||
* All Rights Reserved
|
||||
*
|
||||
* http://www.ibsensoftware.com/
|
||||
*
|
||||
* This software is provided 'as-is', without any express
|
||||
* or implied warranty. In no event will the authors be
|
||||
* held liable for any damages arising from the use of
|
||||
* this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software
|
||||
* for any purpose, including commercial applications,
|
||||
* and to alter it and redistribute it freely, subject to
|
||||
* the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be
|
||||
* misrepresented; you must not claim that you
|
||||
* wrote the original software. If you use this
|
||||
* software in a product, an acknowledgment in
|
||||
* the product documentation would be appreciated
|
||||
* but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked
|
||||
* as such, and must not be misrepresented as
|
||||
* being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from
|
||||
* any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* CRC32 algorithm taken from the zlib source, which is
|
||||
* Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
|
||||
*/
|
||||
|
||||
#include "tinf.h"
|
||||
|
||||
static const unsigned int tinf_crc32tab[16] = {
|
||||
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190,
|
||||
0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344,
|
||||
0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278,
|
||||
0xbdbdf21c
|
||||
};
|
||||
|
||||
/* crc is previous value for incremental computation, 0xffffffff initially */
|
||||
uint32_t uzlib_crc32(const void *data, unsigned int length, uint32_t crc)
|
||||
{
|
||||
const unsigned char *buf = (const unsigned char *)data;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < length; ++i)
|
||||
{
|
||||
crc ^= buf[i];
|
||||
crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4);
|
||||
crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4);
|
||||
}
|
||||
|
||||
// return value suitable for passing in next time, for final value invert it
|
||||
return crc/* ^ 0xffffffff*/;
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
* All Rights Reserved
|
||||
* http://www.ibsensoftware.com/
|
||||
*
|
||||
* Copyright (c) 2014 by Paul Sokolovsky
|
||||
* Copyright (c) 2014-2016 by Paul Sokolovsky
|
||||
*/
|
||||
|
||||
#ifndef TINF_H_INCLUDED
|
||||
|
@ -26,9 +26,17 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ok status, more data produced */
|
||||
#define TINF_OK 0
|
||||
/* end of compressed stream reached */
|
||||
#define TINF_DONE 1
|
||||
#define TINF_DATA_ERROR (-3)
|
||||
#define TINF_DEST_OVERFLOW (-4)
|
||||
#define TINF_CHKSUM_ERROR (-4)
|
||||
|
||||
/* checksum types */
|
||||
#define TINF_CHKSUM_NONE 0
|
||||
#define TINF_CHKSUM_ADLER 1
|
||||
#define TINF_CHKSUM_CRC 2
|
||||
|
||||
/* data structures */
|
||||
|
||||
|
@ -40,6 +48,10 @@ typedef struct {
|
|||
struct TINF_DATA;
|
||||
typedef struct TINF_DATA {
|
||||
const unsigned char *source;
|
||||
/* If source above is NULL, this function will be used to read
|
||||
next byte from source stream */
|
||||
unsigned char (*readSource)(struct TINF_DATA *data);
|
||||
|
||||
unsigned int tag;
|
||||
unsigned int bitcount;
|
||||
|
||||
|
@ -51,49 +63,51 @@ typedef struct TINF_DATA {
|
|||
unsigned char *dest;
|
||||
/* Remaining bytes in buffer */
|
||||
unsigned int destRemaining;
|
||||
/* Argument is the allocation size which didn't fit into buffer. Note that
|
||||
exact mimumum size to grow buffer by is lastAlloc - destRemaining. But
|
||||
growing by this exact size is ineficient, as the next allocation will
|
||||
fail again. */
|
||||
int (*destGrow)(struct TINF_DATA *data, unsigned int lastAlloc);
|
||||
|
||||
/* Accumulating checksum */
|
||||
unsigned int checksum;
|
||||
char checksum_type;
|
||||
|
||||
int btype;
|
||||
int bfinal;
|
||||
unsigned int curlen;
|
||||
int lzOff;
|
||||
unsigned char *dict_ring;
|
||||
unsigned int dict_size;
|
||||
unsigned int dict_idx;
|
||||
|
||||
TINF_TREE ltree; /* dynamic length/symbol tree */
|
||||
TINF_TREE dtree; /* dynamic distance tree */
|
||||
} TINF_DATA;
|
||||
|
||||
#define TINF_PUT(d, c) \
|
||||
{ \
|
||||
*d->dest++ = c; \
|
||||
if (d->dict_ring) { d->dict_ring[d->dict_idx++] = c; if (d->dict_idx == d->dict_size) d->dict_idx = 0; } \
|
||||
}
|
||||
|
||||
/* low-level API */
|
||||
unsigned char TINFCC uzlib_get_byte(TINF_DATA *d);
|
||||
|
||||
/* Step 1: Allocate TINF_DATA structure */
|
||||
/* Step 2: Set destStart, destSize, and destGrow fields */
|
||||
/* Step 3: Set source field */
|
||||
/* Step 4: Call tinf_uncompress_dyn() */
|
||||
/* Step 5: In response to destGrow callback, update destStart and destSize fields */
|
||||
/* Step 6: When tinf_uncompress_dyn() returns, buf.dest points to a byte past last uncompressed byte */
|
||||
/* Decompression API */
|
||||
|
||||
int TINFCC tinf_uncompress_dyn(TINF_DATA *d);
|
||||
int TINFCC tinf_zlib_uncompress_dyn(TINF_DATA *d, unsigned int sourceLen);
|
||||
void TINFCC uzlib_init(void);
|
||||
void TINFCC uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen);
|
||||
int TINFCC uzlib_uncompress(TINF_DATA *d);
|
||||
int TINFCC uzlib_uncompress_chksum(TINF_DATA *d);
|
||||
|
||||
/* high-level API */
|
||||
int TINFCC uzlib_zlib_parse_header(TINF_DATA *d);
|
||||
int TINFCC uzlib_gzip_parse_header(TINF_DATA *d);
|
||||
|
||||
void TINFCC tinf_init(void);
|
||||
/* Compression API */
|
||||
|
||||
int TINFCC tinf_uncompress(void *dest, unsigned int *destLen,
|
||||
const void *source, unsigned int sourceLen);
|
||||
void TINFCC uzlib_compress(void *data, const uint8_t *src, unsigned slen);
|
||||
|
||||
int TINFCC tinf_gzip_uncompress(void *dest, unsigned int *destLen,
|
||||
const void *source, unsigned int sourceLen);
|
||||
/* Checksum API */
|
||||
|
||||
int TINFCC tinf_zlib_uncompress(void *dest, unsigned int *destLen,
|
||||
const void *source, unsigned int sourceLen);
|
||||
|
||||
unsigned int TINFCC tinf_adler32(const void *data, unsigned int length);
|
||||
|
||||
unsigned int TINFCC tinf_crc32(const void *data, unsigned int length);
|
||||
|
||||
/* compression API */
|
||||
|
||||
void TINFCC tinf_compress(void *data, const uint8_t *src, unsigned slen);
|
||||
/* prev_sum is previous value for incremental computation, 1 initially */
|
||||
uint32_t TINFCC uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum);
|
||||
/* crc is previous value for incremental computation, 0xffffffff initially */
|
||||
uint32_t TINFCC uzlib_crc32(const void *data, unsigned int length, uint32_t crc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* All Rights Reserved
|
||||
* http://www.ibsensoftware.com/
|
||||
*
|
||||
* Copyright (c) 2014 by Paul Sokolovsky
|
||||
* Copyright (c) 2014-2016 by Paul Sokolovsky
|
||||
*
|
||||
* This software is provided 'as-is', without any express
|
||||
* or implied warranty. In no event will the authors be
|
||||
|
@ -32,8 +32,12 @@
|
|||
* any source distribution.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "tinf.h"
|
||||
|
||||
uint32_t tinf_get_le_uint32(TINF_DATA *d);
|
||||
uint32_t tinf_get_be_uint32(TINF_DATA *d);
|
||||
|
||||
/* --------------------------------------------------- *
|
||||
* -- uninitialized global data (static structures) -- *
|
||||
* --------------------------------------------------- */
|
||||
|
@ -89,21 +93,6 @@ const unsigned char clcidx[] = {
|
|||
* -- utility functions -- *
|
||||
* ----------------------- */
|
||||
|
||||
/* Execute callback to grow destination buffer */
|
||||
static int tinf_grow_dest_buf(TINF_DATA *d, unsigned int lastAlloc)
|
||||
{
|
||||
unsigned int oldsize = d->dest - d->destStart;
|
||||
/* This will update only destStart and destSize */
|
||||
if (!d->destGrow)
|
||||
{
|
||||
return TINF_DEST_OVERFLOW;
|
||||
}
|
||||
d->destGrow(d, lastAlloc);
|
||||
d->dest = d->destStart + oldsize;
|
||||
d->destRemaining = d->destSize - oldsize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef RUNTIME_BITS_TABLES
|
||||
/* build extra bits and base tables */
|
||||
static void tinf_build_bits_base(unsigned char *bits, unsigned short *base, int delta, int first)
|
||||
|
@ -180,6 +169,34 @@ static void tinf_build_tree(TINF_TREE *t, const unsigned char *lengths, unsigned
|
|||
* -- decode functions -- *
|
||||
* ---------------------- */
|
||||
|
||||
unsigned char uzlib_get_byte(TINF_DATA *d)
|
||||
{
|
||||
if (d->source) {
|
||||
return *d->source++;
|
||||
}
|
||||
return d->readSource(d);
|
||||
}
|
||||
|
||||
uint32_t tinf_get_le_uint32(TINF_DATA *d)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
int i;
|
||||
for (i = 4; i--;) {
|
||||
val = val >> 8 | uzlib_get_byte(d) << 24;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t tinf_get_be_uint32(TINF_DATA *d)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
int i;
|
||||
for (i = 4; i--;) {
|
||||
val = val << 8 | uzlib_get_byte(d);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/* get one bit from source stream */
|
||||
static int tinf_getbit(TINF_DATA *d)
|
||||
{
|
||||
|
@ -189,7 +206,7 @@ static int tinf_getbit(TINF_DATA *d)
|
|||
if (!d->bitcount--)
|
||||
{
|
||||
/* load next tag */
|
||||
d->tag = *d->source++;
|
||||
d->tag = uzlib_get_byte(d);
|
||||
d->bitcount = 7;
|
||||
}
|
||||
|
||||
|
@ -318,121 +335,91 @@ static void tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
|||
/* given a stream and two trees, inflate a block of data */
|
||||
static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (d->curlen == 0) {
|
||||
unsigned int offs;
|
||||
int dist;
|
||||
int sym = tinf_decode_symbol(d, lt);
|
||||
//printf("huff sym: %02x\n", sym);
|
||||
|
||||
/* check for end of block */
|
||||
if (sym == 256)
|
||||
{
|
||||
/* literal byte */
|
||||
if (sym < 256) {
|
||||
TINF_PUT(d, sym);
|
||||
return TINF_OK;
|
||||
}
|
||||
|
||||
if (sym < 256)
|
||||
{
|
||||
if (d->destRemaining == 0)
|
||||
{
|
||||
int res = tinf_grow_dest_buf(d, 1);
|
||||
if (res) return res;
|
||||
/* end of block */
|
||||
if (sym == 256) {
|
||||
return TINF_DONE;
|
||||
}
|
||||
|
||||
*d->dest++ = sym;
|
||||
d->destRemaining--;
|
||||
|
||||
} else {
|
||||
|
||||
unsigned int length, offs, i;
|
||||
int dist;
|
||||
|
||||
/* substring from sliding dictionary */
|
||||
sym -= 257;
|
||||
|
||||
/* possibly get more bits from length code */
|
||||
length = tinf_read_bits(d, length_bits[sym], length_base[sym]);
|
||||
d->curlen = tinf_read_bits(d, length_bits[sym], length_base[sym]);
|
||||
|
||||
dist = tinf_decode_symbol(d, dt);
|
||||
|
||||
/* possibly get more bits from distance code */
|
||||
offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
|
||||
|
||||
if (d->destRemaining < length)
|
||||
{
|
||||
int res = tinf_grow_dest_buf(d, length);
|
||||
if (res) return res;
|
||||
if (d->dict_ring) {
|
||||
d->lzOff = d->dict_idx - offs;
|
||||
if (d->lzOff < 0) {
|
||||
d->lzOff += d->dict_size;
|
||||
}
|
||||
} else {
|
||||
d->lzOff = -offs;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy match */
|
||||
for (i = 0; i < length; ++i)
|
||||
{
|
||||
d->dest[i] = d->dest[(int)(i - offs)];
|
||||
}
|
||||
|
||||
d->dest += length;
|
||||
d->destRemaining -= length;
|
||||
/* copy next byte from dict substring */
|
||||
if (d->dict_ring) {
|
||||
TINF_PUT(d, d->dict_ring[d->lzOff]);
|
||||
if ((unsigned)++d->lzOff == d->dict_size) {
|
||||
d->lzOff = 0;
|
||||
}
|
||||
} else {
|
||||
d->dest[0] = d->dest[d->lzOff];
|
||||
d->dest++;
|
||||
}
|
||||
d->curlen--;
|
||||
return TINF_OK;
|
||||
}
|
||||
|
||||
/* inflate an uncompressed block of data */
|
||||
static int tinf_inflate_uncompressed_block(TINF_DATA *d)
|
||||
{
|
||||
if (d->curlen == 0) {
|
||||
unsigned int length, invlength;
|
||||
unsigned int i;
|
||||
|
||||
/* get length */
|
||||
length = d->source[1];
|
||||
length = 256*length + d->source[0];
|
||||
|
||||
length = uzlib_get_byte(d) + 256 * uzlib_get_byte(d);
|
||||
/* get one's complement of length */
|
||||
invlength = d->source[3];
|
||||
invlength = 256*invlength + d->source[2];
|
||||
|
||||
invlength = uzlib_get_byte(d) + 256 * uzlib_get_byte(d);
|
||||
/* check length */
|
||||
if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR;
|
||||
|
||||
if (d->destRemaining < length)
|
||||
{
|
||||
int res = tinf_grow_dest_buf(d, length);
|
||||
if (res) return res;
|
||||
}
|
||||
|
||||
d->source += 4;
|
||||
|
||||
/* copy block */
|
||||
for (i = length; i; --i) *d->dest++ = *d->source++;
|
||||
d->destRemaining -= length;
|
||||
/* increment length to properly return TINF_DONE below, without
|
||||
producing data at the same time */
|
||||
d->curlen = length + 1;
|
||||
|
||||
/* make sure we start next block on a byte boundary */
|
||||
d->bitcount = 0;
|
||||
}
|
||||
|
||||
if (--d->curlen == 0) {
|
||||
return TINF_DONE;
|
||||
}
|
||||
|
||||
unsigned char c = uzlib_get_byte(d);
|
||||
TINF_PUT(d, c);
|
||||
return TINF_OK;
|
||||
}
|
||||
|
||||
/* inflate a block of data compressed with fixed huffman trees */
|
||||
static int tinf_inflate_fixed_block(TINF_DATA *d)
|
||||
{
|
||||
/* build fixed huffman trees */
|
||||
tinf_build_fixed_trees(&d->ltree, &d->dtree);
|
||||
|
||||
/* decode block using fixed trees */
|
||||
return tinf_inflate_block_data(d, &d->ltree, &d->dtree);
|
||||
}
|
||||
|
||||
/* inflate a block of data compressed with dynamic huffman trees */
|
||||
static int tinf_inflate_dynamic_block(TINF_DATA *d)
|
||||
{
|
||||
/* decode trees from stream */
|
||||
tinf_decode_trees(d, &d->ltree, &d->dtree);
|
||||
|
||||
/* decode block using decoded trees */
|
||||
return tinf_inflate_block_data(d, &d->ltree, &d->dtree);
|
||||
}
|
||||
|
||||
/* ---------------------- *
|
||||
* -- public functions -- *
|
||||
* ---------------------- */
|
||||
|
||||
/* initialize global (static) data */
|
||||
void tinf_init(void)
|
||||
void uzlib_init(void)
|
||||
{
|
||||
#ifdef RUNTIME_BITS_TABLES
|
||||
/* build extra bits and base tables */
|
||||
|
@ -445,72 +432,117 @@ void tinf_init(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* inflate stream from source to dest */
|
||||
int tinf_uncompress(void *dest, unsigned int *destLen,
|
||||
const void *source, unsigned int sourceLen)
|
||||
/* initialize decompression structure */
|
||||
void uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen)
|
||||
{
|
||||
(void)sourceLen;
|
||||
TINF_DATA d;
|
||||
int res;
|
||||
|
||||
/* initialise data */
|
||||
d.source = (const unsigned char *)source;
|
||||
|
||||
d.destStart = (unsigned char *)dest;
|
||||
d.destRemaining = *destLen;
|
||||
d.destSize = *destLen;
|
||||
|
||||
res = tinf_uncompress_dyn(&d);
|
||||
|
||||
*destLen = d.dest - d.destStart;
|
||||
|
||||
return res;
|
||||
d->bitcount = 0;
|
||||
d->bfinal = 0;
|
||||
d->btype = -1;
|
||||
d->dict_size = dictLen;
|
||||
d->dict_ring = dict;
|
||||
d->dict_idx = 0;
|
||||
d->curlen = 0;
|
||||
}
|
||||
|
||||
/* inflate stream from source to dest */
|
||||
int tinf_uncompress_dyn(TINF_DATA *d)
|
||||
/* inflate next byte of compressed stream */
|
||||
int uzlib_uncompress(TINF_DATA *d)
|
||||
{
|
||||
int bfinal;
|
||||
|
||||
/* initialise data */
|
||||
d->bitcount = 0;
|
||||
|
||||
d->dest = d->destStart;
|
||||
d->destRemaining = d->destSize;
|
||||
|
||||
do {
|
||||
|
||||
unsigned int btype;
|
||||
int res;
|
||||
|
||||
/* start a new block */
|
||||
if (d->btype == -1) {
|
||||
next_blk:
|
||||
/* read final block flag */
|
||||
bfinal = tinf_getbit(d);
|
||||
|
||||
d->bfinal = tinf_getbit(d);
|
||||
/* read block type (2 bits) */
|
||||
btype = tinf_read_bits(d, 2, 0);
|
||||
d->btype = tinf_read_bits(d, 2, 0);
|
||||
|
||||
/* decompress block */
|
||||
switch (btype)
|
||||
//printf("Started new block: type=%d final=%d\n", d->btype, d->bfinal);
|
||||
|
||||
if (d->btype == 1) {
|
||||
/* build fixed huffman trees */
|
||||
tinf_build_fixed_trees(&d->ltree, &d->dtree);
|
||||
} else if (d->btype == 2) {
|
||||
/* decode trees from stream */
|
||||
tinf_decode_trees(d, &d->ltree, &d->dtree);
|
||||
}
|
||||
}
|
||||
|
||||
/* process current block */
|
||||
switch (d->btype)
|
||||
{
|
||||
case 0:
|
||||
/* decompress uncompressed block */
|
||||
res = tinf_inflate_uncompressed_block(d);
|
||||
break;
|
||||
case 1:
|
||||
/* decompress block with fixed huffman trees */
|
||||
res = tinf_inflate_fixed_block(d);
|
||||
break;
|
||||
case 2:
|
||||
/* decompress block with dynamic huffman trees */
|
||||
res = tinf_inflate_dynamic_block(d);
|
||||
/* decompress block with fixed/dyanamic huffman trees */
|
||||
/* trees were decoded previously, so it's the same routine for both */
|
||||
res = tinf_inflate_block_data(d, &d->ltree, &d->dtree);
|
||||
break;
|
||||
default:
|
||||
return TINF_DATA_ERROR;
|
||||
}
|
||||
|
||||
if (res != TINF_OK) return TINF_DATA_ERROR;
|
||||
if (res == TINF_DONE && !d->bfinal) {
|
||||
/* the block has ended (without producing more data), but we
|
||||
can't return without data, so start procesing next block */
|
||||
goto next_blk;
|
||||
}
|
||||
|
||||
} while (!bfinal);
|
||||
if (res != TINF_OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
} while (--d->destSize);
|
||||
|
||||
return TINF_OK;
|
||||
}
|
||||
|
||||
int uzlib_uncompress_chksum(TINF_DATA *d)
|
||||
{
|
||||
int res;
|
||||
unsigned char *data = d->dest;
|
||||
|
||||
res = uzlib_uncompress(d);
|
||||
|
||||
if (res < 0) return res;
|
||||
|
||||
switch (d->checksum_type) {
|
||||
|
||||
case TINF_CHKSUM_ADLER:
|
||||
d->checksum = uzlib_adler32(data, d->dest - data, d->checksum);
|
||||
break;
|
||||
|
||||
case TINF_CHKSUM_CRC:
|
||||
d->checksum = uzlib_crc32(data, d->dest - data, d->checksum);
|
||||
break;
|
||||
}
|
||||
|
||||
if (res == TINF_DONE) {
|
||||
unsigned int val;
|
||||
|
||||
switch (d->checksum_type) {
|
||||
|
||||
case TINF_CHKSUM_ADLER:
|
||||
val = tinf_get_be_uint32(d);
|
||||
if (d->checksum != val) {
|
||||
return TINF_CHKSUM_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case TINF_CHKSUM_CRC:
|
||||
val = tinf_get_le_uint32(d);
|
||||
if (~d->checksum != val) {
|
||||
return TINF_CHKSUM_ERROR;
|
||||
}
|
||||
// Uncompressed size. TODO: Check
|
||||
val = tinf_get_le_uint32(d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*
|
||||
* http://www.ibsensoftware.com/
|
||||
*
|
||||
* Copyright (c) 2014-2016 by Paul Sokolovsky
|
||||
*
|
||||
* This software is provided 'as-is', without any express
|
||||
* or implied warranty. In no event will the authors be
|
||||
* held liable for any damages arising from the use of
|
||||
|
@ -33,35 +35,14 @@
|
|||
|
||||
#include "tinf.h"
|
||||
|
||||
int tinf_zlib_uncompress(void *dest, unsigned int *destLen,
|
||||
const void *source, unsigned int sourceLen)
|
||||
int uzlib_zlib_parse_header(TINF_DATA *d)
|
||||
{
|
||||
TINF_DATA d;
|
||||
int res;
|
||||
|
||||
/* initialise data */
|
||||
d.source = (const unsigned char *)source;
|
||||
|
||||
d.destStart = (unsigned char *)dest;
|
||||
d.destRemaining = *destLen;
|
||||
|
||||
res = tinf_zlib_uncompress_dyn(&d, sourceLen);
|
||||
|
||||
*destLen = d.dest - d.destStart;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int tinf_zlib_uncompress_dyn(TINF_DATA *d, unsigned int sourceLen)
|
||||
{
|
||||
unsigned int a32;
|
||||
int res;
|
||||
unsigned char cmf, flg;
|
||||
|
||||
/* -- get header bytes -- */
|
||||
|
||||
cmf = d->source[0];
|
||||
flg = d->source[1];
|
||||
cmf = uzlib_get_byte(d);
|
||||
flg = uzlib_get_byte(d);
|
||||
|
||||
/* -- check format -- */
|
||||
|
||||
|
@ -77,25 +58,9 @@ int tinf_zlib_uncompress_dyn(TINF_DATA *d, unsigned int sourceLen)
|
|||
/* check there is no preset dictionary */
|
||||
if (flg & 0x20) return TINF_DATA_ERROR;
|
||||
|
||||
/* -- get adler32 checksum -- */
|
||||
/* initialize for adler32 checksum */
|
||||
d->checksum_type = TINF_CHKSUM_ADLER;
|
||||
d->checksum = 1;
|
||||
|
||||
a32 = d->source[sourceLen - 4];
|
||||
a32 = 256*a32 + d->source[sourceLen - 3];
|
||||
a32 = 256*a32 + d->source[sourceLen - 2];
|
||||
a32 = 256*a32 + d->source[sourceLen - 1];
|
||||
|
||||
d->source += 2;
|
||||
|
||||
/* -- inflate -- */
|
||||
|
||||
res = tinf_uncompress_dyn(d);
|
||||
|
||||
if (res != TINF_OK) return res;
|
||||
|
||||
/* -- check adler32 checksum -- */
|
||||
|
||||
if (a32 != tinf_adler32(d->destStart, d->dest - d->destStart)) return TINF_DATA_ERROR;
|
||||
|
||||
return TINF_OK;
|
||||
return cmf >> 4;
|
||||
}
|
||||
|
||||
|
|
|
@ -250,6 +250,13 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
|
|||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat);
|
||||
|
||||
// Unmount the filesystem
|
||||
STATIC mp_obj_t fat_vfs_umount(mp_obj_t vfs_in) {
|
||||
fatfs_umount(((fs_user_mount_t *)vfs_in)->readblocks[1]);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, fat_vfs_umount);
|
||||
|
||||
STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) },
|
||||
|
@ -261,6 +268,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&fat_vfs_rename_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&fat_vfs_stat_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table);
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 78a4787948bb80cbfafcfd7910f95f61a4dd0d4c
|
||||
Subproject commit dab957dacddcbf6cbc85d42df62e189e4877bb72
|
|
@ -24,6 +24,10 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
|
||||
#if MICROPY_USE_INTERNAL_PRINTF
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -127,3 +131,5 @@ int snprintf(char *str, size_t size, const char *fmt, ...) {
|
|||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif //MICROPY_USE_INTERNAL_PRINTF
|
||||
|
|
|
@ -112,7 +112,7 @@ STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind,
|
|||
printf("took " UINT_FMT " ms\n", ticks);
|
||||
// qstr info
|
||||
{
|
||||
mp_uint_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
|
||||
size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
|
||||
qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
|
||||
printf("qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT "\n n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT "\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
// Send "cooked" string of given length, where every occurance of
|
||||
// LF character is replaced with CR LF.
|
||||
void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) {
|
||||
void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
|
||||
while (len--) {
|
||||
if (*str == '\n') {
|
||||
mp_hal_stdout_tx_strn("\r", 1);
|
||||
|
|
|
@ -46,7 +46,6 @@ SRC_C = \
|
|||
main.c \
|
||||
uart_core.c \
|
||||
lib/utils/stdout_helpers.c \
|
||||
lib/utils/printf.c \
|
||||
lib/utils/pyexec.c \
|
||||
lib/libc/string0.c \
|
||||
lib/mp-readline/readline.c \
|
||||
|
|
|
@ -65,8 +65,6 @@
|
|||
typedef int mp_int_t; // must be pointer size
|
||||
typedef unsigned mp_uint_t; // must be pointer size
|
||||
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
typedef long mp_off_t;
|
||||
|
||||
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
|
||||
#define MICROPY_CPYTHON_COMPAT (1)
|
||||
#define MICROPY_USE_INTERNAL_PRINTF (0)
|
||||
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
|
||||
|
||||
|
@ -107,9 +108,6 @@ typedef long long mp_off_t;
|
|||
typedef long mp_off_t;
|
||||
#endif
|
||||
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
|
||||
#define MP_PLAT_PRINT_STRN(str, len) (void)0
|
||||
|
||||
#ifndef MP_NOINLINE
|
||||
|
|
|
@ -83,8 +83,6 @@
|
|||
typedef int mp_int_t; // must be pointer size
|
||||
typedef unsigned int mp_uint_t; // must be pointer size
|
||||
|
||||
typedef void *machine_ptr_t; // must be pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be pointer size
|
||||
typedef int mp_off_t;
|
||||
|
||||
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
|
||||
|
|
2
py/bc.c
2
py/bc.c
|
@ -89,7 +89,7 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) {
|
|||
// - code_state->ip should contain the offset in bytes from the start of
|
||||
// the bytecode chunk to just after n_state and n_exc_stack
|
||||
// - code_state->n_state should be set to the state size (locals plus stack)
|
||||
void mp_setup_code_state(mp_code_state *code_state, mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// This function is pretty complicated. It's main aim is to be efficient in speed and RAM
|
||||
// usage for the common case of positional only args.
|
||||
size_t n_state = code_state->n_state;
|
||||
|
|
14
py/bc.h
14
py/bc.h
|
@ -60,7 +60,7 @@
|
|||
// constN : obj
|
||||
|
||||
// Exception stack entry
|
||||
typedef struct _mp_exc_stack {
|
||||
typedef struct _mp_exc_stack_t {
|
||||
const byte *handler;
|
||||
// bit 0 is saved currently_in_except_block value
|
||||
// bit 1 is whether the opcode was SETUP_WITH or SETUP_FINALLY
|
||||
|
@ -69,7 +69,7 @@ typedef struct _mp_exc_stack {
|
|||
mp_obj_base_t *prev_exc;
|
||||
} mp_exc_stack_t;
|
||||
|
||||
typedef struct _mp_code_state {
|
||||
typedef struct _mp_code_state_t {
|
||||
const byte *code_info;
|
||||
const byte *ip;
|
||||
const mp_uint_t *const_table;
|
||||
|
@ -78,21 +78,21 @@ typedef struct _mp_code_state {
|
|||
mp_exc_stack_t *exc_sp;
|
||||
mp_obj_dict_t *old_globals;
|
||||
#if MICROPY_STACKLESS
|
||||
struct _mp_code_state *prev;
|
||||
struct _mp_code_state_t *prev;
|
||||
#endif
|
||||
size_t n_state;
|
||||
// Variable-length
|
||||
mp_obj_t state[0];
|
||||
// Variable-length, never accessed by name, only as (void*)(state + n_state)
|
||||
//mp_exc_stack_t exc_state[0];
|
||||
} mp_code_state;
|
||||
} mp_code_state_t;
|
||||
|
||||
mp_uint_t mp_decode_uint(const byte **ptr);
|
||||
|
||||
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc);
|
||||
mp_code_state *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc);
|
||||
mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
struct _mp_obj_fun_bc_t;
|
||||
void mp_setup_code_state(mp_code_state *code_state, struct _mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
void mp_setup_code_state(mp_code_state_t *code_state, struct _mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
void mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len, const mp_uint_t *const_table);
|
||||
void mp_bytecode_print2(const byte *code, mp_uint_t len);
|
||||
const byte *mp_bytecode_print_str(const byte *ip);
|
||||
|
|
|
@ -1200,6 +1200,11 @@ STATIC void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns)
|
|||
}
|
||||
|
||||
STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
// with optimisations enabled we don't compile assertions
|
||||
if (MP_STATE_VM(mp_optimise_value) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint l_end = comp_next_label(comp);
|
||||
c_if_cond(comp, pns->nodes[0], true, l_end);
|
||||
EMIT_LOAD_GLOBAL(MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython
|
||||
|
|
|
@ -349,12 +349,10 @@ mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader) {
|
|||
byte header[4];
|
||||
read_bytes(reader, header, sizeof(header));
|
||||
if (strncmp((char*)header, "M\x00", 2) != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"invalid .mpy file"));
|
||||
mp_raise_ValueError("invalid .mpy file");
|
||||
}
|
||||
if (header[2] != MPY_FEATURE_FLAGS || header[3] > mp_small_int_bits()) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"incompatible .mpy file"));
|
||||
mp_raise_ValueError("incompatible .mpy file");
|
||||
}
|
||||
return load_raw_code(reader);
|
||||
}
|
||||
|
@ -382,7 +380,7 @@ mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) {
|
|||
// here we define mp_raw_code_load_file depending on the port
|
||||
// TODO abstract this away properly
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || (defined(__arm__) && (defined(__unix__)))
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || defined(__unix__)
|
||||
// unix file reader
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
@ -560,8 +558,7 @@ STATIC void save_bytecode_qstrs(mp_print_t *print, const byte *ip, const byte *i
|
|||
|
||||
STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc) {
|
||||
if (rc->kind != MP_CODE_BYTECODE) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"can only save bytecode"));
|
||||
mp_raise_ValueError("can only save bytecode");
|
||||
}
|
||||
|
||||
// save bytecode
|
||||
|
|
|
@ -628,7 +628,7 @@ STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg);
|
|||
STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num);
|
||||
STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num);
|
||||
|
||||
#define STATE_START (sizeof(mp_code_state) / sizeof(mp_uint_t))
|
||||
#define STATE_START (sizeof(mp_code_state_t) / sizeof(mp_uint_t))
|
||||
|
||||
STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
|
||||
DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope);
|
||||
|
@ -775,10 +775,10 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
|
|||
|
||||
// set code_state.ip (offset from start of this function to prelude info)
|
||||
// XXX this encoding may change size
|
||||
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state, ip) / sizeof(mp_uint_t), REG_ARG_1);
|
||||
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(mp_uint_t), REG_ARG_1);
|
||||
|
||||
// set code_state.n_state
|
||||
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->n_state, offsetof(mp_code_state, n_state) / sizeof(mp_uint_t), REG_ARG_1);
|
||||
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->n_state, offsetof(mp_code_state_t, n_state) / sizeof(mp_uint_t), REG_ARG_1);
|
||||
|
||||
// put address of code_state into first arg
|
||||
ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, 0, REG_ARG_1);
|
||||
|
|
10
py/gc.c
10
py/gc.c
|
@ -480,12 +480,17 @@ found:
|
|||
|
||||
GC_EXIT();
|
||||
|
||||
#if MICROPY_GC_CONSERVATIVE_CLEAR
|
||||
// be conservative and zero out all the newly allocated blocks
|
||||
memset((byte*)ret_ptr, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK);
|
||||
#else
|
||||
// zero out the additional bytes of the newly allocated blocks
|
||||
// This is needed because the blocks may have previously held pointers
|
||||
// to the heap and will not be set to something else if the caller
|
||||
// doesn't actually use the entire block. As such they will continue
|
||||
// to point to the heap and may prevent other blocks from being reclaimed.
|
||||
memset((byte*)ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes);
|
||||
#endif
|
||||
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
if (has_finaliser) {
|
||||
|
@ -713,8 +718,13 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {
|
|||
|
||||
GC_EXIT();
|
||||
|
||||
#if MICROPY_GC_CONSERVATIVE_CLEAR
|
||||
// be conservative and zero out all the newly allocated blocks
|
||||
memset((byte*)ptr_in + n_blocks * BYTES_PER_BLOCK, 0, (new_blocks - n_blocks) * BYTES_PER_BLOCK);
|
||||
#else
|
||||
// zero out the additional bytes of the newly allocated blocks (see comment above in gc_alloc)
|
||||
memset((byte*)ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes);
|
||||
#endif
|
||||
|
||||
#if EXTENSIVE_HEAP_PROFILING
|
||||
gc_dump_alloc_table();
|
||||
|
|
|
@ -14,11 +14,13 @@ import sys
|
|||
# - codepoint2name lives in a different module
|
||||
import platform
|
||||
if platform.python_version_tuple()[0] == '2':
|
||||
ord_bytes = ord
|
||||
bytes_cons = lambda val, enc=None: bytearray(val)
|
||||
from htmlentitydefs import codepoint2name
|
||||
elif platform.python_version_tuple()[0] == '3':
|
||||
ord_bytes = lambda x:x
|
||||
bytes_cons = bytes
|
||||
from html.entities import codepoint2name
|
||||
# end compatibility code
|
||||
|
||||
codepoint2name[ord('-')] = 'hyphen';
|
||||
|
||||
# add some custom names to map characters that aren't in HTML
|
||||
|
@ -52,8 +54,8 @@ codepoint2name[ord('~')] = 'tilde'
|
|||
# this must match the equivalent function in qstr.c
|
||||
def compute_hash(qstr, bytes_hash):
|
||||
hash = 5381
|
||||
for char in qstr:
|
||||
hash = (hash * 33) ^ ord(char)
|
||||
for b in qstr:
|
||||
hash = (hash * 33) ^ b
|
||||
# Make sure that valid hash is never zero, zero means "hash not computed"
|
||||
return (hash & ((1 << (8 * bytes_hash)) - 1)) or 1
|
||||
|
||||
|
@ -115,16 +117,15 @@ def parse_input_headers(infiles):
|
|||
return qcfgs, qstrs
|
||||
|
||||
def make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr):
|
||||
qhash = compute_hash(qstr, cfg_bytes_hash)
|
||||
qbytes = bytes_cons(qstr, 'utf8')
|
||||
qlen = len(qbytes)
|
||||
qhash = compute_hash(qbytes, cfg_bytes_hash)
|
||||
if all(32 <= ord(c) <= 126 and c != '\\' and c != '"' for c in qstr):
|
||||
# qstr is all printable ASCII so render it as-is (for easier debugging)
|
||||
qlen = len(qstr)
|
||||
qdata = qstr
|
||||
else:
|
||||
# qstr contains non-printable codes so render entire thing as hex pairs
|
||||
qbytes = qstr.encode('utf8')
|
||||
qlen = len(qbytes)
|
||||
qdata = ''.join(('\\x%02x' % ord_bytes(b)) for b in qbytes)
|
||||
qdata = ''.join(('\\x%02x' % b) for b in qbytes)
|
||||
if qlen >= (1 << (8 * cfg_bytes_len)):
|
||||
print('qstr is too long:', qstr)
|
||||
assert False
|
||||
|
|
|
@ -117,7 +117,10 @@ void *m_malloc0(size_t num_bytes) {
|
|||
if (ptr == NULL && num_bytes != 0) {
|
||||
return m_malloc_fail(num_bytes);
|
||||
}
|
||||
// If this config is set then the GC clears all memory, so we don't need to.
|
||||
#if !MICROPY_GC_CONSERVATIVE_CLEAR
|
||||
memset(ptr, 0, num_bytes);
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -123,8 +123,9 @@ clean-prog:
|
|||
.PHONY: clean-prog
|
||||
endif
|
||||
|
||||
lib: $(OBJ)
|
||||
$(AR) rcs libmicropython.a $^
|
||||
LIBMICROPYTHON = libmicropython.a
|
||||
lib $(LIBMICROPYTHON): $(OBJ)
|
||||
$(AR) rcs $(LIBMICROPYTHON) $^
|
||||
|
||||
clean:
|
||||
$(RM) -rf $(BUILD) $(CLEAN_EXTRA)
|
||||
|
|
|
@ -376,7 +376,6 @@ STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
|
|||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_pow(size_t n_args, const mp_obj_t *args) {
|
||||
assert(2 <= n_args && n_args <= 3);
|
||||
switch (n_args) {
|
||||
case 2: return mp_binary_op(MP_BINARY_OP_POWER, args[0], args[1]);
|
||||
default: return mp_binary_op(MP_BINARY_OP_MODULO, mp_binary_op(MP_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise...
|
||||
|
@ -492,7 +491,6 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) {
|
|||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj, 1, 2, mp_builtin_round);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) {
|
||||
assert(1 <= n_args && n_args <= 2);
|
||||
mp_obj_t value;
|
||||
switch (n_args) {
|
||||
case 1: value = MP_OBJ_NEW_SMALL_INT(0); break;
|
||||
|
@ -508,7 +506,6 @@ STATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) {
|
|||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
|
||||
assert(n_args >= 1);
|
||||
if (n_args > 1) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
|
||||
"must use keyword argument for key function"));
|
||||
|
|
|
@ -114,7 +114,7 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
|
|||
mp_uint_t align;
|
||||
size_t sz = mp_binary_get_size(fmt_type, *fmt, &align);
|
||||
if (sz == 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "unsupported format"));
|
||||
mp_raise_ValueError("unsupported format");
|
||||
}
|
||||
while (cnt--) {
|
||||
// Apply alignment
|
||||
|
@ -149,7 +149,7 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) {
|
|||
// negative offsets are relative to the end of the buffer
|
||||
offset = bufinfo.len + offset;
|
||||
if (offset < 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small"));
|
||||
mp_raise_ValueError("buffer too small");
|
||||
}
|
||||
}
|
||||
p += offset;
|
||||
|
@ -164,7 +164,7 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) {
|
|||
sz = get_fmt_num(&fmt);
|
||||
}
|
||||
if (p + sz > end_p) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small"));
|
||||
mp_raise_ValueError("buffer too small");
|
||||
}
|
||||
mp_obj_t item;
|
||||
if (*fmt == 's') {
|
||||
|
@ -197,7 +197,7 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, byte* end_p, siz
|
|||
sz = get_fmt_num(&fmt);
|
||||
}
|
||||
if (p + sz > end_p) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small"));
|
||||
mp_raise_ValueError("buffer too small");
|
||||
}
|
||||
|
||||
if (*fmt == 's') {
|
||||
|
@ -240,7 +240,7 @@ STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) {
|
|||
// negative offsets are relative to the end of the buffer
|
||||
offset = (mp_int_t)bufinfo.len + offset;
|
||||
if (offset < 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small"));
|
||||
mp_raise_ValueError("buffer too small");
|
||||
}
|
||||
}
|
||||
byte *p = (byte *)bufinfo.buf;
|
||||
|
|
|
@ -107,6 +107,15 @@
|
|||
#define MICROPY_ALLOC_GC_STACK_SIZE (64)
|
||||
#endif
|
||||
|
||||
// Be conservative and always clear to zero newly (re)allocated memory in the GC.
|
||||
// This helps eliminate stray pointers that hold on to memory that's no longer
|
||||
// used. It decreases performance due to unnecessary memory clearing.
|
||||
// TODO Do analysis to understand why some memory is not properly cleared and
|
||||
// find a more efficient way to clear it.
|
||||
#ifndef MICROPY_GC_CONSERVATIVE_CLEAR
|
||||
#define MICROPY_GC_CONSERVATIVE_CLEAR (1)
|
||||
#endif
|
||||
|
||||
// Support automatic GC when reaching allocation threshold,
|
||||
// configurable by gc.threshold().
|
||||
#ifndef MICROPY_GC_ALLOC_THRESHOLD
|
||||
|
@ -572,6 +581,11 @@ typedef double mp_float_t;
|
|||
#define MICROPY_USE_INTERNAL_ERRNO (0)
|
||||
#endif
|
||||
|
||||
// Whether to use internally defined *printf() functions (otherwise external ones)
|
||||
#ifndef MICROPY_USE_INTERNAL_PRINTF
|
||||
#define MICROPY_USE_INTERNAL_PRINTF (1)
|
||||
#endif
|
||||
|
||||
// Support for user-space VFS mount (selected ports)
|
||||
#ifndef MICROPY_FSUSERMOUNT
|
||||
#define MICROPY_FSUSERMOUNT (0)
|
||||
|
@ -887,6 +901,11 @@ typedef double mp_float_t;
|
|||
#define MICROPY_PY_UBINASCII (0)
|
||||
#endif
|
||||
|
||||
// Depends on MICROPY_PY_UZLIB
|
||||
#ifndef MICROPY_PY_UBINASCII_CRC32
|
||||
#define MICROPY_PY_UBINASCII_CRC32 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_URANDOM
|
||||
#define MICROPY_PY_URANDOM (0)
|
||||
#endif
|
||||
|
@ -909,6 +928,10 @@ typedef double mp_float_t;
|
|||
#define MICROPY_PY_MACHINE_I2C (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_MACHINE_SPI
|
||||
#define MICROPY_PY_MACHINE_SPI (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_USSL
|
||||
#define MICROPY_PY_USSL (0)
|
||||
#endif
|
||||
|
|
|
@ -537,10 +537,12 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
|
|||
chrs += mp_print_int(print, arg_value, *fmt == 'd', 10, 'a', flags, fill, width);
|
||||
break;
|
||||
}
|
||||
// fall through to default case to print unknown format char
|
||||
assert(!"unsupported fmt char");
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
// if it's not %% then it's an unsupported format character
|
||||
assert(*fmt == '%' || !"unsupported fmt char");
|
||||
print->print_strn(print->data, fmt, 1);
|
||||
chrs += 1;
|
||||
break;
|
||||
|
|
10
py/obj.h
10
py/obj.h
|
@ -31,15 +31,15 @@
|
|||
#include "py/qstr.h"
|
||||
#include "py/mpprint.h"
|
||||
|
||||
// All Micro Python objects are at least this type
|
||||
// The bit-size must be at least pointer size
|
||||
|
||||
// This is the definition of the opaque MicroPython object type.
|
||||
// All concrete objects have an encoding within this type and the
|
||||
// particular encoding is specified by MICROPY_OBJ_REPR.
|
||||
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||
typedef uint64_t mp_obj_t;
|
||||
typedef uint64_t mp_const_obj_t;
|
||||
#else
|
||||
typedef machine_ptr_t mp_obj_t;
|
||||
typedef machine_const_ptr_t mp_const_obj_t;
|
||||
typedef void *mp_obj_t;
|
||||
typedef const void *mp_const_obj_t;
|
||||
#endif
|
||||
|
||||
// This mp_obj_type_t struct is a concrete MicroPython object which holds info
|
||||
|
|
32
py/objdict.c
32
py/objdict.c
|
@ -223,7 +223,7 @@ STATIC mp_obj_t dict_getiter(mp_obj_t self_in) {
|
|||
/* dict methods */
|
||||
|
||||
STATIC mp_obj_t dict_clear(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
mp_map_clear(&self->map);
|
||||
|
@ -233,7 +233,7 @@ STATIC mp_obj_t dict_clear(mp_obj_t self_in) {
|
|||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear);
|
||||
|
||||
STATIC mp_obj_t dict_copy(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_t other_out = mp_obj_new_dict(self->map.alloc);
|
||||
mp_obj_dict_t *other = MP_OBJ_TO_PTR(other_out);
|
||||
|
@ -249,7 +249,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy);
|
|||
|
||||
// this is a classmethod
|
||||
STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) {
|
||||
assert(2 <= n_args && n_args <= 3);
|
||||
mp_obj_t iter = mp_getiter(args[1]);
|
||||
mp_obj_t len = mp_obj_len_maybe(iter);
|
||||
mp_obj_t value = mp_const_none;
|
||||
|
@ -303,8 +302,7 @@ STATIC mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, mp
|
|||
}
|
||||
|
||||
STATIC mp_obj_t dict_get(size_t n_args, const mp_obj_t *args) {
|
||||
assert(2 <= n_args && n_args <= 3);
|
||||
assert(MP_OBJ_IS_DICT_TYPE(args[0]));
|
||||
mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0]));
|
||||
mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
return dict_get_helper(&self->map,
|
||||
|
@ -315,8 +313,7 @@ STATIC mp_obj_t dict_get(size_t n_args, const mp_obj_t *args) {
|
|||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_get_obj, 2, 3, dict_get);
|
||||
|
||||
STATIC mp_obj_t dict_pop(size_t n_args, const mp_obj_t *args) {
|
||||
assert(2 <= n_args && n_args <= 3);
|
||||
assert(MP_OBJ_IS_DICT_TYPE(args[0]));
|
||||
mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0]));
|
||||
mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
return dict_get_helper(&self->map,
|
||||
|
@ -328,8 +325,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_pop_obj, 2, 3, dict_pop);
|
|||
|
||||
|
||||
STATIC mp_obj_t dict_setdefault(size_t n_args, const mp_obj_t *args) {
|
||||
assert(2 <= n_args && n_args <= 3);
|
||||
assert(MP_OBJ_IS_DICT_TYPE(args[0]));
|
||||
mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0]));
|
||||
mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
return dict_get_helper(&self->map,
|
||||
|
@ -341,7 +337,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setde
|
|||
|
||||
|
||||
STATIC mp_obj_t dict_popitem(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_uint_t cur = 0;
|
||||
mp_map_elem_t *next = dict_iter_next(self, &cur);
|
||||
|
@ -359,7 +355,7 @@ STATIC mp_obj_t dict_popitem(mp_obj_t self_in) {
|
|||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem);
|
||||
|
||||
STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
|
||||
assert(MP_OBJ_IS_DICT_TYPE(args[0]));
|
||||
mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0]));
|
||||
mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
mp_arg_check_num(n_args, kwargs->used, 1, 2, true);
|
||||
|
@ -438,7 +434,7 @@ typedef struct _mp_obj_dict_view_t {
|
|||
} mp_obj_dict_view_t;
|
||||
|
||||
STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &dict_view_it_type));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &dict_view_it_type));
|
||||
mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur);
|
||||
|
||||
|
@ -467,7 +463,7 @@ STATIC const mp_obj_type_t dict_view_it_type = {
|
|||
};
|
||||
|
||||
STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) {
|
||||
assert(MP_OBJ_IS_TYPE(view_in, &dict_view_type));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(view_in, &dict_view_type));
|
||||
mp_obj_dict_view_t *view = MP_OBJ_TO_PTR(view_in);
|
||||
mp_obj_dict_view_it_t *o = m_new_obj(mp_obj_dict_view_it_t);
|
||||
o->base.type = &dict_view_it_type;
|
||||
|
@ -479,7 +475,7 @@ STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) {
|
|||
|
||||
STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &dict_view_type));
|
||||
mp_obj_dict_view_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
bool first = true;
|
||||
mp_print_str(print, mp_dict_view_names[self->kind]);
|
||||
|
@ -525,7 +521,7 @@ STATIC mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) {
|
|||
}
|
||||
|
||||
STATIC mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) {
|
||||
assert(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
return mp_obj_new_dict_view(self_in, kind);
|
||||
}
|
||||
|
||||
|
@ -612,21 +608,21 @@ mp_uint_t mp_obj_dict_len(mp_obj_t self_in) {
|
|||
}
|
||||
|
||||
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
|
||||
assert(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
|
||||
return self_in;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key) {
|
||||
assert(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
dict_get_helper(&self->map, key, MP_OBJ_NULL, MP_MAP_LOOKUP_REMOVE_IF_FOUND);
|
||||
return self_in;
|
||||
}
|
||||
|
||||
mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
|
||||
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return &self->map;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ STATIC mp_obj_t filter_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||
}
|
||||
|
||||
STATIC mp_obj_t filter_iternext(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_filter));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_filter));
|
||||
mp_obj_filter_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_t next;
|
||||
while ((next = mp_iternext(self->iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
|
|
14
py/objfun.c
14
py/objfun.c
|
@ -165,7 +165,7 @@ STATIC void dump_args(const mp_obj_t *a, mp_uint_t sz) {
|
|||
#define VM_DETECT_STACK_OVERFLOW (0)
|
||||
|
||||
#if MICROPY_STACKLESS
|
||||
mp_code_state *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
MP_STACK_CHECK();
|
||||
mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
|
@ -178,8 +178,8 @@ mp_code_state *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args,
|
|||
|
||||
// allocate state for locals and stack
|
||||
size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
|
||||
mp_code_state *code_state;
|
||||
code_state = m_new_obj_var_maybe(mp_code_state, byte, state_size);
|
||||
mp_code_state_t *code_state;
|
||||
code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);
|
||||
if (!code_state) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -220,12 +220,12 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
|
|||
|
||||
// allocate state for locals and stack
|
||||
mp_uint_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
|
||||
mp_code_state *code_state = NULL;
|
||||
mp_code_state_t *code_state = NULL;
|
||||
if (state_size > VM_MAX_STATE_ON_STACK) {
|
||||
code_state = m_new_obj_var_maybe(mp_code_state, byte, state_size);
|
||||
code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);
|
||||
}
|
||||
if (code_state == NULL) {
|
||||
code_state = alloca(sizeof(mp_code_state) + state_size);
|
||||
code_state = alloca(sizeof(mp_code_state_t) + state_size);
|
||||
state_size = 0; // indicate that we allocated using alloca
|
||||
}
|
||||
|
||||
|
@ -287,7 +287,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
|
|||
|
||||
// free the state if it was allocated on the heap
|
||||
if (state_size != 0) {
|
||||
m_del_var(mp_code_state, byte, state_size, code_state);
|
||||
m_del_var(mp_code_state_t, byte, state_size, code_state);
|
||||
}
|
||||
|
||||
if (vm_return_kind == MP_VM_RETURN_NORMAL) {
|
||||
|
|
|
@ -46,7 +46,7 @@ typedef struct _mp_obj_gen_wrap_t {
|
|||
typedef struct _mp_obj_gen_instance_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_dict_t *globals;
|
||||
mp_code_state code_state;
|
||||
mp_code_state_t code_state;
|
||||
} mp_obj_gen_instance_t;
|
||||
|
||||
STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
|
@ -96,7 +96,7 @@ STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_pri
|
|||
}
|
||||
|
||||
mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance));
|
||||
mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (self->code_state.ip == 0) {
|
||||
// Trying to resume already stopped generator
|
||||
|
|
32
py/objlist.c
32
py/objlist.c
|
@ -89,7 +89,7 @@ STATIC mp_obj_t list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_
|
|||
|
||||
// Don't pass MP_BINARY_OP_NOT_EQUAL here
|
||||
STATIC bool list_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
if (!MP_OBJ_IS_TYPE(another_in, &mp_type_list)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
|||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_bound_slice_t slice;
|
||||
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
|
||||
assert(0);
|
||||
mp_not_implemented("");
|
||||
}
|
||||
|
||||
mp_int_t len_adj = slice.start - slice.stop;
|
||||
|
@ -192,11 +192,11 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
|||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
assert(MP_OBJ_IS_TYPE(value, &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(value, &mp_type_list));
|
||||
mp_obj_list_t *slice = MP_OBJ_TO_PTR(value);
|
||||
mp_bound_slice_t slice_out;
|
||||
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
|
||||
assert(0);
|
||||
mp_not_implemented("");
|
||||
}
|
||||
mp_int_t len_adj = slice->len - (slice_out.stop - slice_out.start);
|
||||
//printf("Len adj: %d\n", len_adj);
|
||||
|
@ -230,7 +230,7 @@ STATIC mp_obj_t list_getiter(mp_obj_t o_in) {
|
|||
}
|
||||
|
||||
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (self->len >= self->alloc) {
|
||||
self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2);
|
||||
|
@ -242,7 +242,7 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
|
|||
}
|
||||
|
||||
STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
if (MP_OBJ_IS_TYPE(arg_in, &mp_type_list)) {
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_list_t *arg = MP_OBJ_TO_PTR(arg_in);
|
||||
|
@ -263,8 +263,7 @@ STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
|
|||
}
|
||||
|
||||
STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) {
|
||||
assert(1 <= n_args && n_args <= 2);
|
||||
assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
if (self->len == 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list"));
|
||||
|
@ -324,7 +323,7 @@ mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_
|
|||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
||||
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
|
||||
|
||||
assert(MP_OBJ_IS_TYPE(pos_args[0], &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(pos_args[0], &mp_type_list));
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
|
||||
if (self->len > 1) {
|
||||
|
@ -337,7 +336,7 @@ mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_
|
|||
}
|
||||
|
||||
STATIC mp_obj_t list_clear(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
self->len = 0;
|
||||
self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC);
|
||||
|
@ -347,26 +346,25 @@ STATIC mp_obj_t list_clear(mp_obj_t self_in) {
|
|||
}
|
||||
|
||||
STATIC mp_obj_t list_copy(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_obj_new_list(self->len, self->items);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_seq_count_obj(self->items, self->len, value);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t list_index(size_t n_args, const mp_obj_t *args) {
|
||||
assert(2 <= n_args && n_args <= 4);
|
||||
assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
return mp_seq_index_obj(self->items, self->len, n_args, args);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
// insert has its own strange index logic
|
||||
mp_int_t index = MP_OBJ_SMALL_INT_VALUE(idx);
|
||||
|
@ -391,7 +389,7 @@ STATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) {
|
|||
}
|
||||
|
||||
mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_obj_t args[] = {self_in, value};
|
||||
args[1] = list_index(2, args);
|
||||
list_pop(2, args);
|
||||
|
@ -400,7 +398,7 @@ mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value) {
|
|||
}
|
||||
|
||||
STATIC mp_obj_t list_reverse(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
mp_int_t len = self->len;
|
||||
|
|
|
@ -49,7 +49,7 @@ STATIC mp_obj_t map_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
|
|||
}
|
||||
|
||||
STATIC mp_obj_t map_iternext(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_map));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_map));
|
||||
mp_obj_map_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_t *nextses = m_new(mp_obj_t, self->n_iters);
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ const mp_obj_type_t mp_type_property = {
|
|||
};
|
||||
|
||||
const mp_obj_t *mp_obj_property_get(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_property));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_property));
|
||||
mp_obj_property_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return self->proxy;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ STATIC mp_obj_t reversed_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||
}
|
||||
|
||||
STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_reversed));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_reversed));
|
||||
mp_obj_reversed_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
// "raise" stop iteration if we are at the end (the start) of the sequence
|
||||
|
|
|
@ -224,8 +224,6 @@ STATIC mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) {
|
|||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_discard_obj, set_discard);
|
||||
|
||||
STATIC mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) {
|
||||
assert(n_args > 0);
|
||||
|
||||
mp_obj_t self;
|
||||
if (update) {
|
||||
check_set(args[0]);
|
||||
|
@ -443,8 +441,6 @@ STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) {
|
|||
}
|
||||
|
||||
STATIC mp_obj_t set_update(size_t n_args, const mp_obj_t *args) {
|
||||
assert(n_args > 0);
|
||||
|
||||
for (mp_uint_t i = 1; i < n_args; i++) {
|
||||
set_update_int(MP_OBJ_TO_PTR(args[0]), args[i]);
|
||||
}
|
||||
|
@ -587,7 +583,7 @@ mp_obj_t mp_obj_new_set(mp_uint_t n_args, mp_obj_t *items) {
|
|||
}
|
||||
|
||||
void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
|
||||
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||
}
|
||||
|
|
104
py/objstr.c
104
py/objstr.c
|
@ -158,6 +158,9 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
|
|||
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);
|
||||
if (str_hash == 0) {
|
||||
str_hash = qstr_compute_hash(str_data, str_len);
|
||||
}
|
||||
mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(type, NULL, str_len));
|
||||
o->data = str_data;
|
||||
o->hash = str_hash;
|
||||
|
@ -191,6 +194,9 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size
|
|||
}
|
||||
GET_STR_DATA_LEN(args[0], str_data, str_len);
|
||||
GET_STR_HASH(args[0], str_hash);
|
||||
if (str_hash == 0) {
|
||||
str_hash = qstr_compute_hash(str_data, str_len);
|
||||
}
|
||||
mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(&mp_type_bytes, NULL, str_len));
|
||||
o->data = str_data;
|
||||
o->hash = str_hash;
|
||||
|
@ -231,7 +237,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size
|
|||
mp_int_t val = mp_obj_get_int(item);
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
if (val < 0 || val > 255) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bytes value out of range"));
|
||||
mp_raise_ValueError("bytes value out of range");
|
||||
}
|
||||
#endif
|
||||
vstr_add_byte(&vstr, val);
|
||||
|
@ -240,7 +246,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size
|
|||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
|
||||
wrong_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "wrong number of arguments"));
|
||||
mp_raise_TypeError("wrong number of arguments");
|
||||
}
|
||||
|
||||
// like strstr but with specified length and allows \0 bytes
|
||||
|
@ -412,7 +418,7 @@ STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
|||
}
|
||||
|
||||
STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
|
||||
assert(MP_OBJ_IS_STR_OR_BYTES(self_in));
|
||||
mp_check_self(MP_OBJ_IS_STR_OR_BYTES(self_in));
|
||||
const mp_obj_type_t *self_type = mp_obj_get_type(self_in);
|
||||
|
||||
// get separation string
|
||||
|
@ -436,8 +442,8 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
|
|||
mp_uint_t required_len = 0;
|
||||
for (mp_uint_t i = 0; i < seq_len; i++) {
|
||||
if (mp_obj_get_type(seq_items[i]) != self_type) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
|
||||
"join expects a list of str/bytes objects consistent with self object"));
|
||||
mp_raise_TypeError(
|
||||
"join expects a list of str/bytes objects consistent with self object");
|
||||
}
|
||||
if (i > 0) {
|
||||
required_len += sep_len;
|
||||
|
@ -511,7 +517,7 @@ mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) {
|
|||
const char *sep_str = mp_obj_str_get_data(sep, &sep_len);
|
||||
|
||||
if (sep_len == 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "empty separator"));
|
||||
mp_raise_ValueError("empty separator");
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
@ -609,7 +615,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) {
|
|||
const char *sep_str = mp_obj_str_get_data(sep, &sep_len);
|
||||
|
||||
if (sep_len == 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "empty separator"));
|
||||
mp_raise_ValueError("empty separator");
|
||||
}
|
||||
|
||||
const byte *beg = s;
|
||||
|
@ -648,8 +654,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) {
|
|||
|
||||
STATIC mp_obj_t str_finder(mp_uint_t n_args, const mp_obj_t *args, mp_int_t direction, bool is_index) {
|
||||
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
|
||||
assert(2 <= n_args && n_args <= 4);
|
||||
assert(MP_OBJ_IS_STR_OR_BYTES(args[0]));
|
||||
mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0]));
|
||||
|
||||
// check argument type
|
||||
if (mp_obj_get_type(args[1]) != self_type) {
|
||||
|
@ -672,7 +677,7 @@ STATIC mp_obj_t str_finder(mp_uint_t n_args, const mp_obj_t *args, mp_int_t dire
|
|||
if (p == NULL) {
|
||||
// not found
|
||||
if (is_index) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "substring not found"));
|
||||
mp_raise_ValueError("substring not found");
|
||||
} else {
|
||||
return MP_OBJ_NEW_SMALL_INT(-1);
|
||||
}
|
||||
|
@ -734,8 +739,7 @@ STATIC mp_obj_t str_endswith(size_t n_args, const mp_obj_t *args) {
|
|||
enum { LSTRIP, RSTRIP, STRIP };
|
||||
|
||||
STATIC mp_obj_t str_uni_strip(int type, mp_uint_t n_args, const mp_obj_t *args) {
|
||||
assert(1 <= n_args && n_args <= 2);
|
||||
assert(MP_OBJ_IS_STR_OR_BYTES(args[0]));
|
||||
mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0]));
|
||||
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
|
||||
|
||||
const byte *chars_to_del;
|
||||
|
@ -878,7 +882,7 @@ STATIC mp_obj_t arg_as_int(mp_obj_t arg) {
|
|||
}
|
||||
|
||||
STATIC NORETURN void terse_str_format_value_error(void) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad format string"));
|
||||
mp_raise_ValueError("bad format string");
|
||||
}
|
||||
|
||||
STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
|
||||
|
@ -896,8 +900,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
|
|||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"single '}' encountered in format string"));
|
||||
mp_raise_ValueError("single '}' encountered in format string");
|
||||
}
|
||||
}
|
||||
if (*str != '{') {
|
||||
|
@ -936,12 +939,11 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
|
|||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"bad conversion specifier"));
|
||||
mp_raise_ValueError("bad conversion specifier");
|
||||
} else {
|
||||
if (str >= top) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"end of format while looking for conversion specifier"));
|
||||
mp_raise_ValueError(
|
||||
"end of format while looking for conversion specifier");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"unknown conversion specifier %c", *str));
|
||||
|
@ -975,16 +977,14 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
|
|||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"unmatched '{' in format"));
|
||||
mp_raise_ValueError("unmatched '{' in format");
|
||||
}
|
||||
}
|
||||
if (*str != '}') {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"expected ':' after format specifier"));
|
||||
mp_raise_ValueError("expected ':' after format specifier");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -997,13 +997,13 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
|
|||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"can't switch from automatic field numbering to manual field specification"));
|
||||
mp_raise_ValueError(
|
||||
"can't switch from automatic field numbering to manual field specification");
|
||||
}
|
||||
}
|
||||
field_name = str_to_int(field_name, field_name_top, &index);
|
||||
if ((uint)index >= n_args - 1) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range"));
|
||||
mp_raise_msg(&mp_type_IndexError, "tuple index out of range");
|
||||
}
|
||||
arg = args[index + 1];
|
||||
*arg_i = -1;
|
||||
|
@ -1026,12 +1026,12 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
|
|||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"can't switch from manual field specification to automatic field numbering"));
|
||||
mp_raise_ValueError(
|
||||
"can't switch from manual field specification to automatic field numbering");
|
||||
}
|
||||
}
|
||||
if ((uint)*arg_i >= n_args - 1) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range"));
|
||||
mp_raise_msg(&mp_type_IndexError, "tuple index out of range");
|
||||
}
|
||||
arg = args[(*arg_i) + 1];
|
||||
(*arg_i)++;
|
||||
|
@ -1120,8 +1120,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
|
|||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"invalid format specifier"));
|
||||
mp_raise_ValueError("invalid format specifier");
|
||||
}
|
||||
}
|
||||
vstr_clear(&format_spec_vstr);
|
||||
|
@ -1142,16 +1141,15 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
|
|||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"sign not allowed in string format specifier"));
|
||||
mp_raise_ValueError("sign not allowed in string format specifier");
|
||||
}
|
||||
}
|
||||
if (type == 'c') {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"sign not allowed with integer format specifier 'c'"));
|
||||
mp_raise_ValueError(
|
||||
"sign not allowed with integer format specifier 'c'");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1295,8 +1293,8 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
|
|||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"'=' alignment not allowed in string format specifier"));
|
||||
mp_raise_ValueError(
|
||||
"'=' alignment not allowed in string format specifier");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1331,7 +1329,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
|
|||
}
|
||||
|
||||
mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
|
||||
assert(MP_OBJ_IS_STR_OR_BYTES(args[0]));
|
||||
mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0]));
|
||||
|
||||
GET_STR_DATA_LEN(args[0], str, len);
|
||||
int arg_i = 0;
|
||||
|
@ -1340,7 +1338,7 @@ mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
|||
}
|
||||
|
||||
STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_obj_t *args, mp_obj_t dict) {
|
||||
assert(MP_OBJ_IS_STR_OR_BYTES(pattern));
|
||||
mp_check_self(MP_OBJ_IS_STR_OR_BYTES(pattern));
|
||||
|
||||
GET_STR_DATA_LEN(pattern, str, len);
|
||||
const byte *start_str = str;
|
||||
|
@ -1372,8 +1370,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_o
|
|||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"incomplete format key"));
|
||||
mp_raise_ValueError("incomplete format key");
|
||||
}
|
||||
}
|
||||
++str;
|
||||
|
@ -1431,8 +1428,7 @@ incomplete_format:
|
|||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
terse_str_format_value_error();
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"incomplete format"));
|
||||
mp_raise_ValueError("incomplete format");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1440,7 +1436,7 @@ incomplete_format:
|
|||
if (arg == MP_OBJ_NULL) {
|
||||
if ((uint)arg_i >= n_args) {
|
||||
not_enough_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "not enough arguments for format string"));
|
||||
mp_raise_TypeError("not enough arguments for format string");
|
||||
}
|
||||
arg = args[arg_i++];
|
||||
}
|
||||
|
@ -1450,16 +1446,14 @@ not_enough_args:
|
|||
mp_uint_t slen;
|
||||
const char *s = mp_obj_str_get_data(arg, &slen);
|
||||
if (slen != 1) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
|
||||
"%%c requires int or char"));
|
||||
mp_raise_TypeError("%%c requires int or char");
|
||||
}
|
||||
mp_print_strn(&print, s, 1, flags, ' ', width);
|
||||
} else if (arg_looks_integer(arg)) {
|
||||
char ch = mp_obj_get_int(arg);
|
||||
mp_print_strn(&print, &ch, 1, flags, ' ', width);
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
|
||||
"integer required"));
|
||||
mp_raise_TypeError("integer required");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1529,7 +1523,7 @@ not_enough_args:
|
|||
}
|
||||
|
||||
if ((uint)arg_i != n_args) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "not all arguments converted during string formatting"));
|
||||
mp_raise_TypeError("not all arguments converted during string formatting");
|
||||
}
|
||||
|
||||
return mp_obj_new_str_from_vstr(is_bytes ? &mp_type_bytes : &mp_type_str, &vstr);
|
||||
|
@ -1538,7 +1532,7 @@ not_enough_args:
|
|||
// The implementation is optimized, returning the original string if there's
|
||||
// nothing to replace.
|
||||
STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) {
|
||||
assert(MP_OBJ_IS_STR_OR_BYTES(args[0]));
|
||||
mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0]));
|
||||
|
||||
mp_int_t max_rep = -1;
|
||||
if (n_args == 4) {
|
||||
|
@ -1644,8 +1638,7 @@ STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) {
|
|||
|
||||
STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) {
|
||||
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
|
||||
assert(2 <= n_args && n_args <= 4);
|
||||
assert(MP_OBJ_IS_STR_OR_BYTES(args[0]));
|
||||
mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0]));
|
||||
|
||||
// check argument type
|
||||
if (mp_obj_get_type(args[1]) != self_type) {
|
||||
|
@ -1685,7 +1678,7 @@ STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) {
|
|||
|
||||
#if MICROPY_PY_BUILTINS_STR_PARTITION
|
||||
STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, mp_int_t direction) {
|
||||
assert(MP_OBJ_IS_STR_OR_BYTES(self_in));
|
||||
mp_check_self(MP_OBJ_IS_STR_OR_BYTES(self_in));
|
||||
mp_obj_type_t *self_type = mp_obj_get_type(self_in);
|
||||
if (self_type != mp_obj_get_type(arg)) {
|
||||
bad_implicit_conversion(arg);
|
||||
|
@ -1695,7 +1688,7 @@ STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, mp_int_t directi
|
|||
GET_STR_DATA_LEN(arg, sep, sep_len);
|
||||
|
||||
if (sep_len == 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "empty separator"));
|
||||
mp_raise_ValueError("empty separator");
|
||||
}
|
||||
|
||||
mp_obj_t result[3];
|
||||
|
@ -2061,8 +2054,7 @@ bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) {
|
|||
|
||||
STATIC void bad_implicit_conversion(mp_obj_t self_in) {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
|
||||
"can't convert to str implicitly"));
|
||||
mp_raise_TypeError("can't convert to str implicitly");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"can't convert '%s' object to str implicitly",
|
||||
|
|
|
@ -39,6 +39,7 @@ typedef struct _mp_obj_str_t {
|
|||
#define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte*)str}
|
||||
|
||||
// use this macro to extract the string hash
|
||||
// warning: the hash can be 0, meaning invalid, and must then be explicitly computed from the data
|
||||
#define GET_STR_HASH(str_obj_in, str_hash) \
|
||||
mp_uint_t str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) \
|
||||
{ str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->hash; }
|
||||
|
|
|
@ -104,10 +104,8 @@ STATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_arg
|
|||
|
||||
// Don't pass MP_BINARY_OP_NOT_EQUAL here
|
||||
STATIC bool tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) {
|
||||
mp_obj_type_t *self_type = mp_obj_get_type(self_in);
|
||||
if (self_type->getiter != mp_obj_tuple_getiter) {
|
||||
assert(0);
|
||||
}
|
||||
// type check is done on getiter method to allow tuple, namedtuple, attrtuple
|
||||
mp_check_self(mp_obj_get_type(self_in)->getiter == mp_obj_tuple_getiter);
|
||||
mp_obj_type_t *another_type = mp_obj_get_type(another_in);
|
||||
mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (another_type->getiter != mp_obj_tuple_getiter) {
|
||||
|
@ -202,14 +200,14 @@ mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in) {
|
|||
}
|
||||
|
||||
STATIC mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
|
||||
mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_seq_count_obj(self->items, self->len, value);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(tuple_count_obj, tuple_count);
|
||||
|
||||
STATIC mp_obj_t tuple_index(size_t n_args, const mp_obj_t *args) {
|
||||
assert(MP_OBJ_IS_TYPE(args[0], &mp_type_tuple));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_tuple));
|
||||
mp_obj_tuple_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
return mp_seq_index_obj(self->items, self->len, n_args, args);
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ STATIC mp_obj_t zip_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
|
|||
}
|
||||
|
||||
STATIC mp_obj_t zip_iternext(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_zip));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_zip));
|
||||
mp_obj_zip_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (self->n_iters == 0) {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
|
|
2
py/py.mk
2
py/py.mk
|
@ -208,6 +208,7 @@ PY_O_BASENAME = \
|
|||
../extmod/machine_pinbase.o \
|
||||
../extmod/machine_pulse.o \
|
||||
../extmod/machine_i2c.o \
|
||||
../extmod/machine_spi.o \
|
||||
../extmod/modussl_axtls.o \
|
||||
../extmod/modurandom.o \
|
||||
../extmod/modwebsocket.o \
|
||||
|
@ -222,6 +223,7 @@ PY_O_BASENAME = \
|
|||
../extmod/vfs_fat_misc.o \
|
||||
../extmod/moduos_dupterm.o \
|
||||
../lib/embed/abort_.o \
|
||||
../lib/utils/printf.o \
|
||||
|
||||
# prepend the build destination prefix to the py object files
|
||||
PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME))
|
||||
|
|
20
py/runtime.c
20
py/runtime.c
|
@ -217,6 +217,10 @@ mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
|
|||
} else if (op == MP_UNARY_OP_HASH && MP_OBJ_IS_STR_OR_BYTES(arg)) {
|
||||
// fast path for hashing str/bytes
|
||||
GET_STR_HASH(arg, h);
|
||||
if (h == 0) {
|
||||
GET_STR_DATA_LEN(arg, data, len);
|
||||
h = qstr_compute_hash(data, len);
|
||||
}
|
||||
return MP_OBJ_NEW_SMALL_INT(h);
|
||||
} else {
|
||||
mp_obj_type_t *type = mp_obj_get_type(arg);
|
||||
|
@ -1390,6 +1394,18 @@ void *m_malloc_fail(size_t num_bytes) {
|
|||
}
|
||||
}
|
||||
|
||||
NORETURN void mp_not_implemented(const char *msg) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError, msg));
|
||||
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg) {
|
||||
nlr_raise(mp_obj_new_exception_msg(exc_type, msg));
|
||||
}
|
||||
|
||||
NORETURN void mp_raise_ValueError(const char *msg) {
|
||||
mp_raise_msg(&mp_type_ValueError, msg);
|
||||
}
|
||||
|
||||
NORETURN void mp_raise_TypeError(const char *msg) {
|
||||
mp_raise_msg(&mp_type_TypeError, msg);
|
||||
}
|
||||
|
||||
NORETURN void mp_not_implemented(const char *msg) {
|
||||
mp_raise_msg(&mp_type_NotImplementedError, msg);
|
||||
}
|
||||
|
|
17
py/runtime.h
17
py/runtime.h
|
@ -133,10 +133,23 @@ mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level);
|
|||
mp_obj_t mp_import_from(mp_obj_t module, qstr name);
|
||||
void mp_import_all(mp_obj_t module);
|
||||
|
||||
// Raise NotImplementedError with given message
|
||||
NORETURN void mp_not_implemented(const char *msg);
|
||||
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg);
|
||||
//NORETURN void nlr_raise_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...);
|
||||
NORETURN void mp_raise_ValueError(const char *msg);
|
||||
NORETURN void mp_raise_TypeError(const char *msg);
|
||||
NORETURN void mp_not_implemented(const char *msg); // Raise NotImplementedError with given message
|
||||
NORETURN void mp_exc_recursion_depth(void);
|
||||
|
||||
#if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
|
||||
#undef mp_check_self
|
||||
#define mp_check_self(pred)
|
||||
#else
|
||||
// A port may define to raise TypeError for example
|
||||
#ifndef mp_check_self
|
||||
#define mp_check_self(pred) assert(pred)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// helper functions for native/viper code
|
||||
mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type);
|
||||
mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type);
|
||||
|
|
|
@ -56,12 +56,12 @@ bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice
|
|||
if (ostart == mp_const_none) {
|
||||
start = 0;
|
||||
} else {
|
||||
start = MP_OBJ_SMALL_INT_VALUE(ostart);
|
||||
start = mp_obj_get_int(ostart);
|
||||
}
|
||||
if (ostop == mp_const_none) {
|
||||
stop = len;
|
||||
} else {
|
||||
stop = MP_OBJ_SMALL_INT_VALUE(ostop);
|
||||
stop = mp_obj_get_int(ostop);
|
||||
}
|
||||
|
||||
// Unlike subscription, out-of-bounds slice indexes are never error
|
||||
|
@ -88,7 +88,7 @@ bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice
|
|||
indexes->stop = stop;
|
||||
|
||||
if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {
|
||||
indexes->step = MP_OBJ_SMALL_INT_VALUE(ostep);
|
||||
indexes->step = mp_obj_get_int(ostep);
|
||||
return false;
|
||||
}
|
||||
indexes->step = 1;
|
||||
|
|
|
@ -94,8 +94,8 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode
|
|||
}
|
||||
|
||||
const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) {
|
||||
mp_obj_base_t *o = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
|
||||
const mp_stream_p_t *stream_p = o->type->protocol;
|
||||
mp_obj_type_t *type = mp_obj_get_type(self_in);
|
||||
const mp_stream_p_t *stream_p = type->protocol;
|
||||
if (stream_p == NULL
|
||||
|| ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL)
|
||||
|| ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL)
|
||||
|
|
10
py/vm.c
10
py/vm.c
|
@ -127,7 +127,7 @@ typedef enum {
|
|||
// MP_VM_RETURN_NORMAL, sp valid, return value in *sp
|
||||
// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
|
||||
// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
|
||||
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc) {
|
||||
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) {
|
||||
#define SELECTIVE_EXC_IP (0)
|
||||
#if SELECTIVE_EXC_IP
|
||||
#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */
|
||||
|
@ -904,7 +904,7 @@ unwind_jump:;
|
|||
code_state->ip = ip;
|
||||
code_state->sp = sp;
|
||||
code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
|
||||
mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1);
|
||||
mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1);
|
||||
if (new_state) {
|
||||
new_state->prev = code_state;
|
||||
code_state = new_state;
|
||||
|
@ -940,7 +940,7 @@ unwind_jump:;
|
|||
mp_call_args_t out_args;
|
||||
mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
|
||||
|
||||
mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
|
||||
mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
|
||||
out_args.n_args, out_args.n_kw, out_args.args);
|
||||
m_del(mp_obj_t, out_args.args, out_args.n_alloc);
|
||||
if (new_state) {
|
||||
|
@ -976,7 +976,7 @@ unwind_jump:;
|
|||
mp_uint_t n_kw = (unum >> 8) & 0xff;
|
||||
int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
|
||||
|
||||
mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);
|
||||
mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);
|
||||
if (new_state) {
|
||||
new_state->prev = code_state;
|
||||
code_state = new_state;
|
||||
|
@ -1011,7 +1011,7 @@ unwind_jump:;
|
|||
mp_call_args_t out_args;
|
||||
mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
|
||||
|
||||
mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
|
||||
mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
|
||||
out_args.n_args, out_args.n_kw, out_args.args);
|
||||
m_del(mp_obj_t, out_args.args, out_args.n_alloc);
|
||||
if (new_state) {
|
||||
|
|
|
@ -16,12 +16,14 @@
|
|||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
|
||||
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
|
||||
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
|
||||
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
|
||||
#define MICROPY_PY_BUILTINS_FROZENSET (1)
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
|
||||
#define MICROPY_PY_IO (0)
|
||||
#define MICROPY_PY_SYS_EXIT (1)
|
||||
#define MICROPY_PY_SYS_MAXSIZE (1)
|
||||
#define MICROPY_USE_INTERNAL_PRINTF (0)
|
||||
|
||||
// type definitions for the specific machine
|
||||
|
||||
|
@ -36,8 +38,6 @@
|
|||
|
||||
typedef int32_t mp_int_t; // must be pointer size
|
||||
typedef uint32_t mp_uint_t; // must be pointer size
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
typedef long mp_off_t;
|
||||
|
||||
#include <unistd.h>
|
||||
|
|
|
@ -111,7 +111,6 @@ SRC_LIB = $(addprefix lib/,\
|
|||
timeutils/timeutils.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/printf.c \
|
||||
)
|
||||
|
||||
SRC_C = \
|
||||
|
@ -138,6 +137,7 @@ SRC_C = \
|
|||
uart.c \
|
||||
can.c \
|
||||
usb.c \
|
||||
wdt.c \
|
||||
gccollect.c \
|
||||
pybstdio.c \
|
||||
help.c \
|
||||
|
@ -284,7 +284,7 @@ endif
|
|||
ifneq ($(FROZEN_MPY_DIR),)
|
||||
# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and
|
||||
# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch).
|
||||
FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR)/ -type f -name '*.py')
|
||||
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
|
||||
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
|
||||
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
|
||||
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue