From b637d3911e71c6136f761960f293954366dd76a1 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Sat, 24 Oct 2020 20:48:35 -0500 Subject: Initial commit --- shared-module/busdevice/I2CDevice.c | 101 ++++++++++++++++++++++++++++++++++++ shared-module/busdevice/I2CDevice.h | 40 ++++++++++++++ shared-module/busdevice/__init__.c | 0 3 files changed, 141 insertions(+) create mode 100644 shared-module/busdevice/I2CDevice.c create mode 100644 shared-module/busdevice/I2CDevice.h create mode 100644 shared-module/busdevice/__init__.c (limited to 'shared-module') diff --git a/shared-module/busdevice/I2CDevice.c b/shared-module/busdevice/I2CDevice.c new file mode 100644 index 000000000..30f4aad33 --- /dev/null +++ b/shared-module/busdevice/I2CDevice.c @@ -0,0 +1,101 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * 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 "shared-bindings/busdevice/I2CDevice.h" +#include "shared-bindings/busio/I2C.h" +#include "py/mperrno.h" +#include "py/nlr.h" + +void common_hal_busdevice_i2cdevice_construct(busdevice_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address, bool probe) { + self->i2c = i2c; + self->device_address = device_address; + self->probe = probe; + + if (self->probe == true) { + common_hal_busdevice_i2cdevice___probe_for_device(self); + } +} + +void common_hal_busdevice_i2cdevice_lock(busdevice_i2cdevice_obj_t *self) { + bool success = false; + while (!success) { + success = common_hal_busio_i2c_try_lock(self->i2c); + } +} + +void common_hal_busdevice_i2cdevice_unlock(busdevice_i2cdevice_obj_t *self) { + common_hal_busio_i2c_unlock(self->i2c); +} + +uint8_t common_hal_busdevice_i2cdevice_readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length) { + uint8_t status = common_hal_busio_i2c_read(self->i2c, self->device_address, buffer, length); + + return status; +} + +uint8_t common_hal_busdevice_i2cdevice_write(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length) { + uint8_t status = common_hal_busio_i2c_write(self->i2c, self->device_address, buffer, length, true); + + return status; +} + +uint8_t common_hal_busdevice_i2cdevice_write_then_readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t out_buffer, mp_obj_t in_buffer, + size_t out_length, size_t in_length) { + uint8_t status = 0; + + status = common_hal_busio_i2c_write(self->i2c, self->device_address, out_buffer, out_length, true); + + status = common_hal_busio_i2c_read(self->i2c, self->device_address, in_buffer, in_length); + + return status; +} + +uint8_t common_hal_busdevice_i2cdevice___probe_for_device(busdevice_i2cdevice_obj_t *self) { + + + + + // write "" + + +/* + while not self.i2c.try_lock(): + pass + try: + self.i2c.writeto(self.device_address, b"") + except OSError: + # some OS's dont like writing an empty bytesting... + # Retry by reading a byte + try: + result = bytearray(1) + self.i2c.readfrom_into(self.device_address, result) + except OSError: + raise ValueError("No I2C device at address: %x" % self.device_address) + finally: + self.i2c.unlock() +*/ + return 0; +} diff --git a/shared-module/busdevice/I2CDevice.h b/shared-module/busdevice/I2CDevice.h new file mode 100644 index 000000000..c872704db --- /dev/null +++ b/shared-module/busdevice/I2CDevice.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * 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_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H +#define MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H + +#include "py/obj.h" +#include "common-hal/busio/I2C.h" + +typedef struct { + mp_obj_base_t base; + busio_i2c_obj_t *i2c; + uint8_t device_address; + bool probe; +} busdevice_i2cdevice_obj_t; + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H diff --git a/shared-module/busdevice/__init__.c b/shared-module/busdevice/__init__.c new file mode 100644 index 000000000..e69de29bb -- cgit v1.2.3 From 12d770b427e77c207b85aa9ddcda0047fa6d040a Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Sun, 25 Oct 2020 10:15:45 -0500 Subject: Added __probe_for_device --- shared-bindings/busdevice/I2CDevice.c | 24 +++++++++++++------- shared-bindings/busdevice/I2CDevice.h | 4 +--- shared-module/busdevice/I2CDevice.c | 41 ++++++++++++----------------------- 3 files changed, 31 insertions(+), 38 deletions(-) (limited to 'shared-module') diff --git a/shared-bindings/busdevice/I2CDevice.c b/shared-bindings/busdevice/I2CDevice.c index 02dac6a95..fa5cb02e0 100644 --- a/shared-bindings/busdevice/I2CDevice.c +++ b/shared-bindings/busdevice/I2CDevice.c @@ -37,6 +37,7 @@ #include "py/runtime.h" #include "supervisor/shared/translate.h" + //| class I2CDevice: //| """Two wire serial protocol""" //| @@ -59,6 +60,10 @@ STATIC mp_obj_t busdevice_i2cdevice_make_new(const mp_obj_type_t *type, size_t n busio_i2c_obj_t* i2c = args[ARG_i2c].u_obj; common_hal_busdevice_i2cdevice_construct(self, i2c, args[ARG_device_address].u_int, args[ARG_probe].u_bool); + if (args[ARG_probe].u_bool == true) { + common_hal_busdevice_i2cdevice___probe_for_device(self); + } + return (mp_obj_t)self; } @@ -204,28 +209,31 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busdevice_i2cdevice_write_then_readinto_obj, 3, busde STATIC mp_obj_t busdevice_i2cdevice___probe_for_device(mp_obj_t self_in) { - //busdevice_i2cdevice_obj_t *self = self_in; + busdevice_i2cdevice_obj_t *self = self_in; + common_hal_busdevice_i2cdevice___probe_for_device(self); - //common_hal_busdevice_i2cdevice_lock(self_in); +/* common_hal_busdevice_i2cdevice_lock(self); -/* - uint8_t buffer; + + //uint8_t buffer; mp_buffer_info_t bufinfo; - mp_get_buffer_raise(&buffer, &bufinfo, MP_BUFFER_WRITE); + //mp_obj_t bufobj = MP_OBJ_FROM_PTR(&buffer) + mp_obj_t buffer = mp_obj_new_bytearray_of_zeros(1); + + mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE); uint8_t status = common_hal_busdevice_i2cdevice_readinto(self_in, (uint8_t*)bufinfo.buf, 1); if (status != 0) { common_hal_busdevice_i2cdevice_unlock(self_in); mp_raise_ValueError_varg(translate("No I2C device at address: %x"), self->device_address); } + + common_hal_busdevice_i2cdevice_unlock(self); */ - //common_hal_busdevice_i2cdevice_unlock(self_in); - return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(busdevice_i2cdevice___probe_for_device_obj, busdevice_i2cdevice___probe_for_device); - STATIC const mp_rom_map_elem_t busdevice_i2cdevice_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&busdevice_i2cdevice___enter___obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&busdevice_i2cdevice___exit___obj) }, diff --git a/shared-bindings/busdevice/I2CDevice.h b/shared-bindings/busdevice/I2CDevice.h index bc85023d7..795905b32 100644 --- a/shared-bindings/busdevice/I2CDevice.h +++ b/shared-bindings/busdevice/I2CDevice.h @@ -45,14 +45,12 @@ extern const mp_obj_type_t busdevice_i2cdevice_type; // Initializes the hardware peripheral. extern void common_hal_busdevice_i2cdevice_construct(busdevice_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address, bool probe); -extern void common_hal_busdevice_i2cdevice___enter__(busdevice_i2cdevice_obj_t *self); -extern void common_hal_busdevice_i2cdevice___exit__(busdevice_i2cdevice_obj_t *self); extern uint8_t common_hal_busdevice_i2cdevice_readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length); extern uint8_t common_hal_busdevice_i2cdevice_write(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length); extern uint8_t common_hal_busdevice_i2cdevice_write_then_readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t out_buffer, mp_obj_t in_buffer, size_t out_length, size_t in_length); -extern uint8_t common_hal_busdevice_i2cdevice___probe_for_device(busdevice_i2cdevice_obj_t *self); extern void common_hal_busdevice_i2cdevice_lock(busdevice_i2cdevice_obj_t *self); extern void common_hal_busdevice_i2cdevice_unlock(busdevice_i2cdevice_obj_t *self); +extern void common_hal_busdevice_i2cdevice___probe_for_device(busdevice_i2cdevice_obj_t *self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_I2CDEVICE_H diff --git a/shared-module/busdevice/I2CDevice.c b/shared-module/busdevice/I2CDevice.c index 30f4aad33..516132c84 100644 --- a/shared-module/busdevice/I2CDevice.c +++ b/shared-module/busdevice/I2CDevice.c @@ -28,15 +28,12 @@ #include "shared-bindings/busio/I2C.h" #include "py/mperrno.h" #include "py/nlr.h" +#include "py/runtime.h" void common_hal_busdevice_i2cdevice_construct(busdevice_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address, bool probe) { self->i2c = i2c; self->device_address = device_address; self->probe = probe; - - if (self->probe == true) { - common_hal_busdevice_i2cdevice___probe_for_device(self); - } } void common_hal_busdevice_i2cdevice_lock(busdevice_i2cdevice_obj_t *self) { @@ -73,29 +70,19 @@ uint8_t common_hal_busdevice_i2cdevice_write_then_readinto(busdevice_i2cdevice_o return status; } -uint8_t common_hal_busdevice_i2cdevice___probe_for_device(busdevice_i2cdevice_obj_t *self) { - - +void common_hal_busdevice_i2cdevice___probe_for_device(busdevice_i2cdevice_obj_t *self) { + common_hal_busdevice_i2cdevice_lock(self); + mp_buffer_info_t bufinfo; + mp_obj_t buffer = mp_obj_new_bytearray_of_zeros(1); - // write "" + mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE); - -/* - while not self.i2c.try_lock(): - pass - try: - self.i2c.writeto(self.device_address, b"") - except OSError: - # some OS's dont like writing an empty bytesting... - # Retry by reading a byte - try: - result = bytearray(1) - self.i2c.readfrom_into(self.device_address, result) - except OSError: - raise ValueError("No I2C device at address: %x" % self.device_address) - finally: - self.i2c.unlock() -*/ - return 0; -} + uint8_t status = common_hal_busdevice_i2cdevice_readinto(self, (uint8_t*)bufinfo.buf, 1); + if (status != 0) { + common_hal_busdevice_i2cdevice_unlock(self); + mp_raise_ValueError_varg(translate("No I2C device at address: %x"), self->device_address); + } + + common_hal_busdevice_i2cdevice_unlock(self); +} \ No newline at end of file -- cgit v1.2.3 From 8a379830a8a583750daedb2b1c72369f6bb413ef Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Mon, 26 Oct 2020 16:54:24 -0500 Subject: Added doc and translations --- locale/circuitpython.pot | 12 ++- shared-bindings/busdevice/I2CDevice.c | 141 +++++++++++++++++++--------------- shared-module/busdevice/I2CDevice.c | 2 +- 3 files changed, 89 insertions(+), 66 deletions(-) (limited to 'shared-module') diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 7ed2d1ba1..f96b67d2a 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-10-16 19:50-0500\n" +"POT-Creation-Date: 2020-10-26 16:48-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -477,7 +477,8 @@ msgstr "" msgid "Buffer must be a multiple of 512 bytes" msgstr "" -#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c +#: shared-bindings/bitbangio/I2C.c shared-bindings/busdevice/I2CDevice.c +#: shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "" @@ -1251,6 +1252,11 @@ msgstr "" msgid "No DMA channel found" msgstr "" +#: shared-module/busdevice/I2CDevice.c +#, c-format +msgid "No I2C device at address: %x" +msgstr "" + #: ports/esp32s2/common-hal/busio/SPI.c ports/mimxrt10xx/common-hal/busio/SPI.c #: ports/stm/common-hal/busio/SPI.c msgid "No MISO Pin" @@ -3181,6 +3187,8 @@ msgstr "" #: ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.h #: ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.h #: ports/esp32s2/boards/muselab_nanoesp32_s2/mpconfigboard.h +#: ports/esp32s2/boards/targett_module_clip_wroom/mpconfigboard.h +#: ports/esp32s2/boards/targett_module_clip_wrover/mpconfigboard.h #: ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h #: ports/esp32s2/boards/unexpectedmaker_feathers2_prerelease/mpconfigboard.h msgid "pressing boot button at start up.\n" diff --git a/shared-bindings/busdevice/I2CDevice.c b/shared-bindings/busdevice/I2CDevice.c index fa5cb02e0..d8db9362f 100644 --- a/shared-bindings/busdevice/I2CDevice.c +++ b/shared-bindings/busdevice/I2CDevice.c @@ -39,12 +39,29 @@ //| class I2CDevice: -//| """Two wire serial protocol""" -//| -//| def __init__(self, i2c, device_address, probe=True) -> None: -//| -//| ... -//| +//| """ +//| Represents a single I2C device and manages locking the bus and the device +//| address. +//| :param ~busio.I2C i2c: The I2C bus the device is on +//| :param int device_address: The 7 bit device address +//| :param bool probe: Probe for the device upon object creation, default is true +//| .. note:: This class is **NOT** built into CircuitPython. See +//| :ref:`here for install instructions `. +//| Example: +//| .. code-block:: python +//| import busio +//| from board import * +//| from adafruit_bus_device.i2c_device import I2CDevice +//| with busio.I2C(SCL, SDA) as i2c: +//| device = I2CDevice(i2c, 0x70) +//| bytes_read = bytearray(4) +//| with device: +//| device.readinto(bytes_read) +//| # A second transaction +//| with device: +//| device.write(bytes_read)""" +//| ... +//| STATIC mp_obj_t busdevice_i2cdevice_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { busdevice_i2cdevice_obj_t *self = m_new_obj(busdevice_i2cdevice_obj_t); self->base.type = &busdevice_i2cdevice_type; @@ -67,28 +84,30 @@ STATIC mp_obj_t busdevice_i2cdevice_make_new(const mp_obj_type_t *type, size_t n return (mp_obj_t)self; } -//| def __enter__(self) -> None: -//| """Automatically initializes the hardware on context exit. See FIX -//| :ref:`lifetime-and-contextmanagers` for more info.""" -//| ... -//| STATIC mp_obj_t busdevice_i2cdevice_obj___enter__(mp_obj_t self_in) { common_hal_busdevice_i2cdevice_lock(self_in); return self_in; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(busdevice_i2cdevice___enter___obj, busdevice_i2cdevice_obj___enter__); -//| def __exit__(self) -> None: -//| """Automatically deinitializes the hardware on context exit. See -//| :ref:`lifetime-and-contextmanagers` for more info.""" -//| ... -//| STATIC mp_obj_t busdevice_i2cdevice_obj___exit__(size_t n_args, const mp_obj_t *args) { common_hal_busdevice_i2cdevice_unlock(args[0]); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busdevice_i2cdevice___exit___obj, 4, 4, busdevice_i2cdevice_obj___exit__); +//| def readinto(self, buf, *, start=0, end=None): +//| """ +//| Read into ``buf`` from the device. The number of bytes read will be the +//| length of ``buf``. +//| If ``start`` or ``end`` is provided, then the buffer will be sliced +//| as if ``buf[start:end]``. This will not cause an allocation like +//| ``buf[start:end]`` will so it saves memory. +//| :param bytearray buffer: buffer to write into +//| :param int start: Index to start writing at +//| :param int end: Index to write up to but not include; if None, use ``len(buf)``""" +//| ... +//| STATIC void readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t start, mp_int_t end) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE); @@ -123,7 +142,19 @@ STATIC mp_obj_t busdevice_i2cdevice_readinto(size_t n_args, const mp_obj_t *pos_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(busdevice_i2cdevice_readinto_obj, 2, busdevice_i2cdevice_readinto); - +//| def write(self, buf, *, start=0, end=None): +//| """ +//| Write the bytes from ``buffer`` to the device, then transmit a stop +//| bit. +//| If ``start`` or ``end`` is provided, then the buffer will be sliced +//| as if ``buffer[start:end]``. This will not cause an allocation like +//| ``buffer[start:end]`` will so it saves memory. +//| :param bytearray buffer: buffer containing the bytes to write +//| :param int start: Index to start writing from +//| :param int end: Index to read up to but not include; if None, use ``len(buf)`` +//| """ +//| ... +//| STATIC void write(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t start, mp_int_t end) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ); @@ -158,32 +189,28 @@ STATIC mp_obj_t busdevice_i2cdevice_write(size_t n_args, const mp_obj_t *pos_arg MP_DEFINE_CONST_FUN_OBJ_KW(busdevice_i2cdevice_write_obj, 2, busdevice_i2cdevice_write); -/*STATIC void write_then_readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t out_buffer, mp_obj_t in_buffer, - int32_t out_start, mp_int_t out_end, int32_t in_start, mp_int_t in_end) { - mp_buffer_info_t out_bufinfo; - mp_get_buffer_raise(out_buffer, &out_bufinfo, MP_BUFFER_READ); - - size_t out_length = out_bufinfo.len; - normalize_buffer_bounds(&out_start, out_end, &out_length); - if (out_length == 0) { - mp_raise_ValueError(translate("Buffer must be at least length 1")); - } - - mp_buffer_info_t in_bufinfo; - mp_get_buffer_raise(in_buffer, &in_bufinfo, MP_BUFFER_WRITE); - - size_t in_length = in_bufinfo.len; - normalize_buffer_bounds(&in_start, in_end, &in_length); - if (in_length == 0) { - mp_raise_ValueError(translate("Buffer must be at least length 1")); - } - - uint8_t status = common_hal_busdevice_i2cdevice_write_then_readinto(self, out_buffer, in_buffer, out_length, in_length); - if (status != 0) { - mp_raise_OSError(status); - } -}*/ - +//| def write_then_readinto(self, out_buffer, in_buffer, *, out_start=0, out_end=None, in_start=0, in_end=None): +//| """ +//| Write the bytes from ``out_buffer`` to the device, then immediately +//| reads into ``in_buffer`` from the device. The number of bytes read +//| will be the length of ``in_buffer``. +//| If ``out_start`` or ``out_end`` is provided, then the output buffer +//| will be sliced as if ``out_buffer[out_start:out_end]``. This will +//| not cause an allocation like ``buffer[out_start:out_end]`` will so +//| it saves memory. +//| If ``in_start`` or ``in_end`` is provided, then the input buffer +//| will be sliced as if ``in_buffer[in_start:in_end]``. This will not +//| cause an allocation like ``in_buffer[in_start:in_end]`` will so +//| it saves memory. +//| :param bytearray out_buffer: buffer containing the bytes to write +//| :param bytearray in_buffer: buffer containing the bytes to read into +//| :param int out_start: Index to start writing from +//| :param int out_end: Index to read up to but not include; if None, use ``len(out_buffer)`` +//| :param int in_start: Index to start writing at +//| :param int in_end: Index to write up to but not include; if None, use ``len(in_buffer)`` +//| """ +//| ... +//| STATIC mp_obj_t busdevice_i2cdevice_write_then_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; static const mp_arg_t allowed_args[] = { @@ -207,29 +234,17 @@ STATIC mp_obj_t busdevice_i2cdevice_write_then_readinto(size_t n_args, const mp_ } MP_DEFINE_CONST_FUN_OBJ_KW(busdevice_i2cdevice_write_then_readinto_obj, 3, busdevice_i2cdevice_write_then_readinto); - +//| def __probe_for_device(self): +//| """ +//| Try to read a byte from an address, +//| if you get an OSError it means the device is not there +//| or that the device does not support these means of probing +//| """ +//| ... +//| STATIC mp_obj_t busdevice_i2cdevice___probe_for_device(mp_obj_t self_in) { busdevice_i2cdevice_obj_t *self = self_in; common_hal_busdevice_i2cdevice___probe_for_device(self); - -/* common_hal_busdevice_i2cdevice_lock(self); - - - //uint8_t buffer; - mp_buffer_info_t bufinfo; - //mp_obj_t bufobj = MP_OBJ_FROM_PTR(&buffer) - mp_obj_t buffer = mp_obj_new_bytearray_of_zeros(1); - - mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE); - - uint8_t status = common_hal_busdevice_i2cdevice_readinto(self_in, (uint8_t*)bufinfo.buf, 1); - if (status != 0) { - common_hal_busdevice_i2cdevice_unlock(self_in); - mp_raise_ValueError_varg(translate("No I2C device at address: %x"), self->device_address); - } - - common_hal_busdevice_i2cdevice_unlock(self); -*/ return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(busdevice_i2cdevice___probe_for_device_obj, busdevice_i2cdevice___probe_for_device); diff --git a/shared-module/busdevice/I2CDevice.c b/shared-module/busdevice/I2CDevice.c index 516132c84..085c4171f 100644 --- a/shared-module/busdevice/I2CDevice.c +++ b/shared-module/busdevice/I2CDevice.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2020 Mark Komus * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal -- cgit v1.2.3 From 2374b0d013e60b543164f208315ed9f52895dac2 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Tue, 27 Oct 2020 09:13:14 -0500 Subject: Fixed whitespace issues --- shared-bindings/busdevice/I2CDevice.c | 16 ++++++++-------- shared-bindings/busdevice/__init__.c | 2 +- shared-module/busdevice/I2CDevice.c | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'shared-module') diff --git a/shared-bindings/busdevice/I2CDevice.c b/shared-bindings/busdevice/I2CDevice.c index d21ac8c6e..1f3da4652 100644 --- a/shared-bindings/busdevice/I2CDevice.c +++ b/shared-bindings/busdevice/I2CDevice.c @@ -61,7 +61,7 @@ //| with device: //| device.write(bytes_read)""" //| ... -//| +//| STATIC mp_obj_t busdevice_i2cdevice_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { busdevice_i2cdevice_obj_t *self = m_new_obj(busdevice_i2cdevice_obj_t); self->base.type = &busdevice_i2cdevice_type; @@ -107,7 +107,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busdevice_i2cdevice___exit___obj, 4, //| :param int start: Index to start writing at //| :param int end: Index to write up to but not include; if None, use ``len(buf)``""" //| ... -//| +//| STATIC void readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t start, mp_int_t end) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE); @@ -131,7 +131,7 @@ STATIC mp_obj_t busdevice_i2cdevice_readinto(size_t n_args, const mp_obj_t *pos_ { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, }; - + busdevice_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -179,7 +179,7 @@ STATIC mp_obj_t busdevice_i2cdevice_write(size_t n_args, const mp_obj_t *pos_arg { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, }; busdevice_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -210,7 +210,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busdevice_i2cdevice_write_obj, 2, busdevice_i2cdevice //| :param int in_end: Index to write up to but not include; if None, use ``len(in_buffer)`` //| """ //| ... -//| +//| STATIC mp_obj_t busdevice_i2cdevice_write_then_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; static const mp_arg_t allowed_args[] = { @@ -227,7 +227,7 @@ STATIC mp_obj_t busdevice_i2cdevice_write_then_readinto(size_t n_args, const mp_ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); write(self, args[ARG_out_buffer].u_obj, args[ARG_out_start].u_int, args[ARG_out_end].u_int); - + readinto(self, args[ARG_in_buffer].u_obj, args[ARG_in_start].u_int, args[ARG_in_end].u_int); return mp_const_none; @@ -241,7 +241,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busdevice_i2cdevice_write_then_readinto_obj, 3, busde //| or that the device does not support these means of probing //| """ //| ... -//| +//| STATIC mp_obj_t busdevice_i2cdevice___probe_for_device(mp_obj_t self_in) { busdevice_i2cdevice_obj_t *self = self_in; common_hal_busdevice_i2cdevice___probe_for_device(self); @@ -266,4 +266,4 @@ const mp_obj_type_t busdevice_i2cdevice_type = { .name = MP_QSTR_I2CDevice, .make_new = busdevice_i2cdevice_make_new, .locals_dict = (mp_obj_dict_t*)&busdevice_i2cdevice_locals_dict, -}; \ No newline at end of file +}; diff --git a/shared-bindings/busdevice/__init__.c b/shared-bindings/busdevice/__init__.c index 91f250c6a..112dabb7e 100644 --- a/shared-bindings/busdevice/__init__.c +++ b/shared-bindings/busdevice/__init__.c @@ -37,7 +37,7 @@ //| """Hardware accelerated external bus access //| -//| The I2CDevice and SPIDevice helper classes make managing transaction state on a bus easy. +//| The I2CDevice and SPIDevice helper classes make managing transaction state on a bus easy. //| For example, they manage locking the bus to prevent other concurrent access. For SPI //| devices, it manages the chip select and protocol changes such as mode. For I2C, it //| manages the device address. diff --git a/shared-module/busdevice/I2CDevice.c b/shared-module/busdevice/I2CDevice.c index 085c4171f..91013d52c 100644 --- a/shared-module/busdevice/I2CDevice.c +++ b/shared-module/busdevice/I2CDevice.c @@ -83,6 +83,6 @@ void common_hal_busdevice_i2cdevice___probe_for_device(busdevice_i2cdevice_obj_t common_hal_busdevice_i2cdevice_unlock(self); mp_raise_ValueError_varg(translate("No I2C device at address: %x"), self->device_address); } - + common_hal_busdevice_i2cdevice_unlock(self); -} \ No newline at end of file +} -- cgit v1.2.3 From e7da852db7c3784c8c162f7914815ba439baa989 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Thu, 29 Oct 2020 16:13:03 -0500 Subject: Fixing review comments --- shared-bindings/busdevice/I2CDevice.c | 40 +++++++++++------------------------ shared-bindings/busdevice/I2CDevice.h | 6 ++---- shared-module/busdevice/I2CDevice.c | 26 ++++++----------------- shared-module/busdevice/I2CDevice.h | 1 - 4 files changed, 20 insertions(+), 53 deletions(-) (limited to 'shared-module') diff --git a/shared-bindings/busdevice/I2CDevice.c b/shared-bindings/busdevice/I2CDevice.c index 1f3da4652..f5e968137 100644 --- a/shared-bindings/busdevice/I2CDevice.c +++ b/shared-bindings/busdevice/I2CDevice.c @@ -76,22 +76,23 @@ STATIC mp_obj_t busdevice_i2cdevice_make_new(const mp_obj_type_t *type, size_t n busio_i2c_obj_t* i2c = args[ARG_i2c].u_obj; - common_hal_busdevice_i2cdevice_construct(self, i2c, args[ARG_device_address].u_int, args[ARG_probe].u_bool); + common_hal_busdevice_i2cdevice_construct(MP_OBJ_TO_PTR(self), i2c, args[ARG_device_address].u_int); if (args[ARG_probe].u_bool == true) { - common_hal_busdevice_i2cdevice___probe_for_device(self); + common_hal_busdevice_i2cdevice_probe_for_device(self); } return (mp_obj_t)self; } STATIC mp_obj_t busdevice_i2cdevice_obj___enter__(mp_obj_t self_in) { - common_hal_busdevice_i2cdevice_lock(self_in); - return self_in; + busdevice_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_busdevice_i2cdevice_lock(self); + return self; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(busdevice_i2cdevice___enter___obj, busdevice_i2cdevice_obj___enter__); STATIC mp_obj_t busdevice_i2cdevice_obj___exit__(size_t n_args, const mp_obj_t *args) { - common_hal_busdevice_i2cdevice_unlock(args[0]); + common_hal_busdevice_i2cdevice_unlock(MP_OBJ_TO_PTR(args[0])); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busdevice_i2cdevice___exit___obj, 4, 4, busdevice_i2cdevice_obj___exit__); @@ -118,7 +119,7 @@ STATIC void readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t s mp_raise_ValueError(translate("Buffer must be at least length 1")); } - uint8_t status = common_hal_busdevice_i2cdevice_readinto(self, ((uint8_t*)bufinfo.buf) + start, length); + uint8_t status = common_hal_busdevice_i2cdevice_readinto(MP_OBJ_TO_PTR(self), ((uint8_t*)bufinfo.buf) + start, length); if (status != 0) { mp_raise_OSError(status); } @@ -127,7 +128,7 @@ STATIC void readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t s STATIC mp_obj_t busdevice_i2cdevice_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, }; @@ -165,7 +166,7 @@ STATIC void write(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t star mp_raise_ValueError(translate("Buffer must be at least length 1")); } - uint8_t status = common_hal_busdevice_i2cdevice_write(self, ((uint8_t*)bufinfo.buf) + start, length); + uint8_t status = common_hal_busdevice_i2cdevice_write(MP_OBJ_TO_PTR(self), ((uint8_t*)bufinfo.buf) + start, length); if (status != 0) { mp_raise_OSError(status); } @@ -174,7 +175,7 @@ STATIC void write(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t star STATIC mp_obj_t busdevice_i2cdevice_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, }; @@ -214,8 +215,8 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busdevice_i2cdevice_write_obj, 2, busdevice_i2cdevice STATIC mp_obj_t busdevice_i2cdevice_write_then_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_out_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_in_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_out_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_in_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, { MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, @@ -234,31 +235,14 @@ STATIC mp_obj_t busdevice_i2cdevice_write_then_readinto(size_t n_args, const mp_ } MP_DEFINE_CONST_FUN_OBJ_KW(busdevice_i2cdevice_write_then_readinto_obj, 3, busdevice_i2cdevice_write_then_readinto); -//| def __probe_for_device(self): -//| """ -//| Try to read a byte from an address, -//| if you get an OSError it means the device is not there -//| or that the device does not support these means of probing -//| """ -//| ... -//| -STATIC mp_obj_t busdevice_i2cdevice___probe_for_device(mp_obj_t self_in) { - busdevice_i2cdevice_obj_t *self = self_in; - common_hal_busdevice_i2cdevice___probe_for_device(self); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(busdevice_i2cdevice___probe_for_device_obj, busdevice_i2cdevice___probe_for_device); - STATIC const mp_rom_map_elem_t busdevice_i2cdevice_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&busdevice_i2cdevice___enter___obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&busdevice_i2cdevice___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&busdevice_i2cdevice_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&busdevice_i2cdevice_write_obj) }, { MP_ROM_QSTR(MP_QSTR_write_then_readinto), MP_ROM_PTR(&busdevice_i2cdevice_write_then_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR___probe_for_device), MP_ROM_PTR(&busdevice_i2cdevice___probe_for_device_obj) }, }; - STATIC MP_DEFINE_CONST_DICT(busdevice_i2cdevice_locals_dict, busdevice_i2cdevice_locals_dict_table); const mp_obj_type_t busdevice_i2cdevice_type = { diff --git a/shared-bindings/busdevice/I2CDevice.h b/shared-bindings/busdevice/I2CDevice.h index 146013cb7..a1f869c45 100644 --- a/shared-bindings/busdevice/I2CDevice.h +++ b/shared-bindings/busdevice/I2CDevice.h @@ -43,13 +43,11 @@ extern const mp_obj_type_t busdevice_i2cdevice_type; // Initializes the hardware peripheral. -extern void common_hal_busdevice_i2cdevice_construct(busdevice_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address, bool probe); +extern void common_hal_busdevice_i2cdevice_construct(busdevice_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address); extern uint8_t common_hal_busdevice_i2cdevice_readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length); extern uint8_t common_hal_busdevice_i2cdevice_write(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length); -extern uint8_t common_hal_busdevice_i2cdevice_write_then_readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t out_buffer, - mp_obj_t in_buffer, size_t out_length, size_t in_length); extern void common_hal_busdevice_i2cdevice_lock(busdevice_i2cdevice_obj_t *self); extern void common_hal_busdevice_i2cdevice_unlock(busdevice_i2cdevice_obj_t *self); -extern void common_hal_busdevice_i2cdevice___probe_for_device(busdevice_i2cdevice_obj_t *self); +extern void common_hal_busdevice_i2cdevice_probe_for_device(busdevice_i2cdevice_obj_t *self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_I2CDEVICE_H diff --git a/shared-module/busdevice/I2CDevice.c b/shared-module/busdevice/I2CDevice.c index 91013d52c..41706c1a8 100644 --- a/shared-module/busdevice/I2CDevice.c +++ b/shared-module/busdevice/I2CDevice.c @@ -30,16 +30,17 @@ #include "py/nlr.h" #include "py/runtime.h" -void common_hal_busdevice_i2cdevice_construct(busdevice_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address, bool probe) { +void common_hal_busdevice_i2cdevice_construct(busdevice_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address) { self->i2c = i2c; self->device_address = device_address; - self->probe = probe; } void common_hal_busdevice_i2cdevice_lock(busdevice_i2cdevice_obj_t *self) { bool success = false; while (!success) { success = common_hal_busio_i2c_try_lock(self->i2c); + RUN_BACKGROUND_TASKS; + mp_handle_pending(); } } @@ -48,29 +49,14 @@ void common_hal_busdevice_i2cdevice_unlock(busdevice_i2cdevice_obj_t *self) { } uint8_t common_hal_busdevice_i2cdevice_readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length) { - uint8_t status = common_hal_busio_i2c_read(self->i2c, self->device_address, buffer, length); - - return status; + return common_hal_busio_i2c_read(self->i2c, self->device_address, buffer, length); } uint8_t common_hal_busdevice_i2cdevice_write(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length) { - uint8_t status = common_hal_busio_i2c_write(self->i2c, self->device_address, buffer, length, true); - - return status; -} - -uint8_t common_hal_busdevice_i2cdevice_write_then_readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t out_buffer, mp_obj_t in_buffer, - size_t out_length, size_t in_length) { - uint8_t status = 0; - - status = common_hal_busio_i2c_write(self->i2c, self->device_address, out_buffer, out_length, true); - - status = common_hal_busio_i2c_read(self->i2c, self->device_address, in_buffer, in_length); - - return status; + return common_hal_busio_i2c_write(self->i2c, self->device_address, buffer, length, true); } -void common_hal_busdevice_i2cdevice___probe_for_device(busdevice_i2cdevice_obj_t *self) { +void common_hal_busdevice_i2cdevice_probe_for_device(busdevice_i2cdevice_obj_t *self) { common_hal_busdevice_i2cdevice_lock(self); mp_buffer_info_t bufinfo; diff --git a/shared-module/busdevice/I2CDevice.h b/shared-module/busdevice/I2CDevice.h index c872704db..918dc7719 100644 --- a/shared-module/busdevice/I2CDevice.h +++ b/shared-module/busdevice/I2CDevice.h @@ -34,7 +34,6 @@ typedef struct { mp_obj_base_t base; busio_i2c_obj_t *i2c; uint8_t device_address; - bool probe; } busdevice_i2cdevice_obj_t; #endif // MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H -- cgit v1.2.3 From 78477a374afad09aa7141af5cf590652b32c141f Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Sat, 31 Oct 2020 12:17:29 -0500 Subject: Initial SPI commit --- py/circuitpy_defns.mk | 1 + shared-bindings/busdevice/SPIDevice.c | 124 ++++++++++++++++++++++++++++++++++ shared-bindings/busdevice/SPIDevice.h | 50 ++++++++++++++ shared-module/busdevice/SPIDevice.c | 85 +++++++++++++++++++++++ shared-module/busdevice/SPIDevice.h | 44 ++++++++++++ 5 files changed, 304 insertions(+) create mode 100644 shared-bindings/busdevice/SPIDevice.c create mode 100644 shared-bindings/busdevice/SPIDevice.h create mode 100644 shared-module/busdevice/SPIDevice.c create mode 100644 shared-module/busdevice/SPIDevice.h (limited to 'shared-module') diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 9318bd466..4822c0320 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -437,6 +437,7 @@ SRC_SHARED_MODULE_ALL = \ board/__init__.c \ busdevice/__init__.c \ busdevice/I2CDevice.c \ + busdevice/SPIDevice.c \ busio/OneWire.c \ displayio/Bitmap.c \ displayio/ColorConverter.c \ diff --git a/shared-bindings/busdevice/SPIDevice.c b/shared-bindings/busdevice/SPIDevice.c new file mode 100644 index 000000000..7ef047349 --- /dev/null +++ b/shared-bindings/busdevice/SPIDevice.c @@ -0,0 +1,124 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Mark Komus + * + * 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. + */ + +// This file contains all of the Python API definitions for the +// busio.SPI class. + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/busdevice/SPIDevice.h" +#include "shared-bindings/util.h" +#include "shared-module/busdevice/SPIDevice.h" +#include "common-hal/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + + +#include "lib/utils/buffer_helper.h" +#include "lib/utils/context_manager_helpers.h" +#include "py/runtime.h" +#include "supervisor/shared/translate.h" + + +//| class SPIDevice: +//| """ +//| Represents a single SPI device and manages locking the bus and the device +//| address. +//| :param ~busio.SPI spi: The SPI bus the device is on +//| :param int device_address: The 7 bit device address +//| :param bool probe: Probe for the device upon object creation, default is true +//| .. note:: This class is **NOT** built into CircuitPython. See +//| :ref:`here for install instructions `. +//| Example: +//| .. code-block:: python +//| import busio +//| from board import * +//| from adafruit_bus_device.spi_device import SPIDevice +//| with busio.SPI(SCL, SDA) as spi: +//| device = SPIDevice(spi, 0x70) +//| bytes_read = bytearray(4) +//| with device: +//| device.readinto(bytes_read) +//| # A second transaction +//| with device: +//| device.write(bytes_read)""" +//| ... +//| +STATIC mp_obj_t busdevice_spidevice_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + busdevice_spidevice_obj_t *self = m_new_obj(busdevice_spidevice_obj_t); + self->base.type = &busdevice_spidevice_type; + enum { ARG_spi, ARG_chip_select, ARG_baudrate, ARG_polarity, ARG_phase, ARG_extra_clocks }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_spi, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_chip_select, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} }, + { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_extra_clocks, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + 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); + + busio_spi_obj_t* spi = args[ARG_spi].u_obj; + + common_hal_busdevice_spidevice_construct(MP_OBJ_TO_PTR(self), spi, args[ARG_chip_select].u_obj, args[ARG_baudrate].u_int, args[ARG_polarity].u_int, + args[ARG_phase].u_int, args[ARG_extra_clocks].u_int); + + if (args[ARG_chip_select].u_obj != MP_OBJ_NULL) { + digitalinout_result_t result = common_hal_digitalio_digitalinout_switch_to_output(MP_OBJ_TO_PTR(args[ARG_chip_select].u_obj), + true, DRIVE_MODE_PUSH_PULL); + if (result == DIGITALINOUT_INPUT_ONLY) { + mp_raise_NotImplementedError(translate("Pin is input only")); + } + } + + return (mp_obj_t)self; +} + +STATIC mp_obj_t busdevice_spidevice_obj___enter__(mp_obj_t self_in) { + busdevice_spidevice_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_busdevice_spidevice_enter(self); + return self; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(busdevice_spidevice___enter___obj, busdevice_spidevice_obj___enter__); + +STATIC mp_obj_t busdevice_spidevice_obj___exit__(size_t n_args, const mp_obj_t *args) { + common_hal_busdevice_spidevice_exit(MP_OBJ_TO_PTR(args[0])); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busdevice_spidevice___exit___obj, 4, 4, busdevice_spidevice_obj___exit__); + +STATIC const mp_rom_map_elem_t busdevice_spidevice_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&busdevice_spidevice___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&busdevice_spidevice___exit___obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(busdevice_spidevice_locals_dict, busdevice_spidevice_locals_dict_table); + +const mp_obj_type_t busdevice_spidevice_type = { + { &mp_type_type }, + .name = MP_QSTR_SPIDevice, + .make_new = busdevice_spidevice_make_new, + .locals_dict = (mp_obj_dict_t*)&busdevice_spidevice_locals_dict, +}; diff --git a/shared-bindings/busdevice/SPIDevice.h b/shared-bindings/busdevice/SPIDevice.h new file mode 100644 index 000000000..040f98548 --- /dev/null +++ b/shared-bindings/busdevice/SPIDevice.h @@ -0,0 +1,50 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Mark Komus + * + * 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. + */ + +// Machine is the HAL for low-level, hardware accelerated functions. It is not +// meant to simplify APIs, its only meant to unify them so that other modules +// do not require port specific logic. +// +// This file includes externs for all functions a port should implement to +// support the machine module. + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_SPIDEVICE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_SPIDEVICE_H + +#include "py/obj.h" + +#include "shared-module/busdevice/SPIDevice.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t busdevice_spidevice_type; + +// Initializes the hardware peripheral. +extern void common_hal_busdevice_spidevice_construct(busdevice_spidevice_obj_t *self, busio_spi_obj_t *spi, digitalio_digitalinout_obj_t *cs, + uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t extra_clocks); +extern void common_hal_busdevice_spidevice_enter(busdevice_spidevice_obj_t *self); +extern void common_hal_busdevice_spidevice_exit(busdevice_spidevice_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_SPIDEVICE_H diff --git a/shared-module/busdevice/SPIDevice.c b/shared-module/busdevice/SPIDevice.c new file mode 100644 index 000000000..d9b63a007 --- /dev/null +++ b/shared-module/busdevice/SPIDevice.c @@ -0,0 +1,85 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Mark Komus + * + * 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 "shared-bindings/busdevice/SPIDevice.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "py/mperrno.h" +#include "py/nlr.h" +#include "py/runtime.h" + +void common_hal_busdevice_spidevice_construct(busdevice_spidevice_obj_t *self, busio_spi_obj_t *spi, digitalio_digitalinout_obj_t *cs, + uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t extra_clocks) { + self->spi = spi; + self->baudrate = baudrate; + self->polarity = polarity; + self->phase = phase; + self->extra_clocks = extra_clocks; + self->chip_select = cs; +} + +void common_hal_busdevice_spidevice_enter(busdevice_spidevice_obj_t *self) { + bool success = false; + while (!success) { + success = common_hal_busio_spi_try_lock(self->spi); + RUN_BACKGROUND_TASKS; + mp_handle_pending(); + } + + common_hal_busio_spi_configure(self->spi, self->baudrate, self->polarity, self->phase, 8); + + if (self->chip_select != MP_OBJ_NULL) { + common_hal_digitalio_digitalinout_set_value(MP_OBJ_TO_PTR(self->chip_select), false); + } +} + +void common_hal_busdevice_spidevice_exit(busdevice_spidevice_obj_t *self) { + if (self->chip_select != MP_OBJ_NULL) { + common_hal_digitalio_digitalinout_set_value(MP_OBJ_TO_PTR(self->chip_select), true); + } + + if (self->extra_clocks > 0) { + + mp_buffer_info_t bufinfo; + mp_obj_t buffer = mp_obj_new_bytearray_of_zeros(1); + + mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ); + ((uint8_t*)bufinfo.buf)[0] = 0xFF; + + uint8_t clocks = self->extra_clocks / 8; + if ((self->extra_clocks % 8) != 0) + clocks += 1; + + while (clocks > 0) { + if (!common_hal_busio_spi_write(self->spi, ((uint8_t*)bufinfo.buf), 1)) { + mp_raise_OSError(MP_EIO); + } + clocks--; + } + } + + common_hal_busio_spi_unlock(self->spi); +} diff --git a/shared-module/busdevice/SPIDevice.h b/shared-module/busdevice/SPIDevice.h new file mode 100644 index 000000000..ffabf79df --- /dev/null +++ b/shared-module/busdevice/SPIDevice.h @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * 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_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H +#define MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H + +#include "py/obj.h" +#include "common-hal/busio/SPI.h" +#include "common-hal/digitalio/DigitalInOut.h" + +typedef struct { + mp_obj_base_t base; + busio_spi_obj_t *spi; + uint32_t baudrate; + uint8_t polarity; + uint8_t phase; + uint8_t extra_clocks; + digitalio_digitalinout_obj_t *chip_select; +} busdevice_spidevice_obj_t; + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H -- cgit v1.2.3 From 8bbbb2833ad6d9b649132559795f58f8f31f486f Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Sun, 1 Nov 2020 21:38:20 -0600 Subject: Fixes from testing SPI --- shared-bindings/busdevice/SPIDevice.c | 2 +- shared-bindings/busdevice/__init__.c | 2 ++ shared-module/busdevice/I2CDevice.c | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'shared-module') diff --git a/shared-bindings/busdevice/SPIDevice.c b/shared-bindings/busdevice/SPIDevice.c index 4c633b4fd..631d0eec4 100644 --- a/shared-bindings/busdevice/SPIDevice.c +++ b/shared-bindings/busdevice/SPIDevice.c @@ -103,7 +103,7 @@ STATIC mp_obj_t busdevice_spidevice_make_new(const mp_obj_type_t *type, size_t n STATIC mp_obj_t busdevice_spidevice_obj___enter__(mp_obj_t self_in) { busdevice_spidevice_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_busdevice_spidevice_enter(self); - return self; + return self->spi; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(busdevice_spidevice___enter___obj, busdevice_spidevice_obj___enter__); diff --git a/shared-bindings/busdevice/__init__.c b/shared-bindings/busdevice/__init__.c index 391d3698a..6e6ede532 100644 --- a/shared-bindings/busdevice/__init__.c +++ b/shared-bindings/busdevice/__init__.c @@ -33,6 +33,7 @@ #include "shared-bindings/busdevice/__init__.h" #include "shared-bindings/busdevice/I2CDevice.h" +#include "shared-bindings/busdevice/SPIDevice.h" //| """Hardware accelerated external bus access @@ -46,6 +47,7 @@ STATIC const mp_rom_map_elem_t busdevice_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_busdevice) }, { MP_ROM_QSTR(MP_QSTR_I2CDevice), MP_ROM_PTR(&busdevice_i2cdevice_type) }, + { MP_ROM_QSTR(MP_QSTR_SPIDevice), MP_ROM_PTR(&busdevice_spidevice_type) }, }; STATIC MP_DEFINE_CONST_DICT(busdevice_module_globals, busdevice_module_globals_table); diff --git a/shared-module/busdevice/I2CDevice.c b/shared-module/busdevice/I2CDevice.c index 41706c1a8..b9f8ee25c 100644 --- a/shared-module/busdevice/I2CDevice.c +++ b/shared-module/busdevice/I2CDevice.c @@ -39,8 +39,8 @@ void common_hal_busdevice_i2cdevice_lock(busdevice_i2cdevice_obj_t *self) { bool success = false; while (!success) { success = common_hal_busio_i2c_try_lock(self->i2c); - RUN_BACKGROUND_TASKS; - mp_handle_pending(); + //RUN_BACKGROUND_TASKS; + //mp_handle_pending(); } } -- cgit v1.2.3 From 4c93db35959e96889b3a28af792c837fbe1fdca5 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Tue, 3 Nov 2020 18:35:20 -0600 Subject: Renamed to adafruit_bus_device --- py/circuitpy_defns.mk | 8 +- py/circuitpy_mpconfig.h | 4 +- py/circuitpy_mpconfig.mk | 2 +- shared-bindings/adafruit_bus_device/I2CDevice.c | 262 ++++++++++++++++++++++++ shared-bindings/adafruit_bus_device/I2CDevice.h | 53 +++++ shared-bindings/adafruit_bus_device/SPIDevice.c | 128 ++++++++++++ shared-bindings/adafruit_bus_device/SPIDevice.h | 50 +++++ shared-bindings/adafruit_bus_device/__init__.c | 78 +++++++ shared-bindings/adafruit_bus_device/__init__.h | 32 +++ shared-bindings/busdevice/I2CDevice.c | 262 ------------------------ shared-bindings/busdevice/I2CDevice.h | 53 ----- shared-bindings/busdevice/SPIDevice.c | 128 ------------ shared-bindings/busdevice/SPIDevice.h | 50 ----- shared-bindings/busdevice/__init__.c | 78 ------- shared-bindings/busdevice/__init__.h | 32 --- shared-module/adafruit_bus_device/I2CDevice.c | 74 +++++++ shared-module/adafruit_bus_device/I2CDevice.h | 39 ++++ shared-module/adafruit_bus_device/SPIDevice.c | 85 ++++++++ shared-module/adafruit_bus_device/SPIDevice.h | 44 ++++ shared-module/adafruit_bus_device/__init__.c | 0 shared-module/busdevice/I2CDevice.c | 74 ------- shared-module/busdevice/I2CDevice.h | 39 ---- shared-module/busdevice/SPIDevice.c | 85 -------- shared-module/busdevice/SPIDevice.h | 44 ---- shared-module/busdevice/__init__.c | 0 25 files changed, 852 insertions(+), 852 deletions(-) create mode 100644 shared-bindings/adafruit_bus_device/I2CDevice.c create mode 100644 shared-bindings/adafruit_bus_device/I2CDevice.h create mode 100644 shared-bindings/adafruit_bus_device/SPIDevice.c create mode 100644 shared-bindings/adafruit_bus_device/SPIDevice.h create mode 100644 shared-bindings/adafruit_bus_device/__init__.c create mode 100644 shared-bindings/adafruit_bus_device/__init__.h delete mode 100644 shared-bindings/busdevice/I2CDevice.c delete mode 100644 shared-bindings/busdevice/I2CDevice.h delete mode 100644 shared-bindings/busdevice/SPIDevice.c delete mode 100644 shared-bindings/busdevice/SPIDevice.h delete mode 100644 shared-bindings/busdevice/__init__.c delete mode 100644 shared-bindings/busdevice/__init__.h create mode 100644 shared-module/adafruit_bus_device/I2CDevice.c create mode 100644 shared-module/adafruit_bus_device/I2CDevice.h create mode 100644 shared-module/adafruit_bus_device/SPIDevice.c create mode 100644 shared-module/adafruit_bus_device/SPIDevice.h create mode 100644 shared-module/adafruit_bus_device/__init__.c delete mode 100644 shared-module/busdevice/I2CDevice.c delete mode 100644 shared-module/busdevice/I2CDevice.h delete mode 100644 shared-module/busdevice/SPIDevice.c delete mode 100644 shared-module/busdevice/SPIDevice.h delete mode 100644 shared-module/busdevice/__init__.c (limited to 'shared-module') diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 4822c0320..41ef8d742 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -134,7 +134,7 @@ ifeq ($(CIRCUITPY_BOARD),1) SRC_PATTERNS += board/% endif ifeq ($(CIRCUITPY_BUSDEVICE),1) -SRC_PATTERNS += busdevice/% +SRC_PATTERNS += adafruit_bus_device/% endif ifeq ($(CIRCUITPY_BUSIO),1) SRC_PATTERNS += busio/% bitbangio/OneWire.% @@ -435,9 +435,9 @@ SRC_SHARED_MODULE_ALL = \ bitbangio/SPI.c \ bitbangio/__init__.c \ board/__init__.c \ - busdevice/__init__.c \ - busdevice/I2CDevice.c \ - busdevice/SPIDevice.c \ + adafruit_bus_device/__init__.c \ + adafruit_bus_device/I2CDevice.c \ + adafruit_bus_device/SPIDevice.c \ busio/OneWire.c \ displayio/Bitmap.c \ displayio/ColorConverter.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 240fac189..78de7905a 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -325,8 +325,8 @@ extern const struct _mp_obj_module_t board_module; #endif #if CIRCUITPY_BUSDEVICE -extern const struct _mp_obj_module_t busdevice_module; -#define BUSDEVICE_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_busdevice), (mp_obj_t)&busdevice_module }, +extern const struct _mp_obj_module_t adafruit_bus_device_module; +#define BUSDEVICE_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_adafruit_bus_device), (mp_obj_t)&adafruit_bus_device_module }, #else #define BUSDEVICE_MODULE #endif diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 1f96a8f2d..e814edd16 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -90,7 +90,7 @@ CFLAGS += -DCIRCUITPY_BLEIO=$(CIRCUITPY_BLEIO) CIRCUITPY_BOARD ?= 1 CFLAGS += -DCIRCUITPY_BOARD=$(CIRCUITPY_BOARD) -CIRCUITPY_BUSDEVICE ?= 1 +CIRCUITPY_BUSDEVICE ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_BUSDEVICE=$(CIRCUITPY_BUSDEVICE) CIRCUITPY_BUSIO ?= 1 diff --git a/shared-bindings/adafruit_bus_device/I2CDevice.c b/shared-bindings/adafruit_bus_device/I2CDevice.c new file mode 100644 index 000000000..3ec4dae12 --- /dev/null +++ b/shared-bindings/adafruit_bus_device/I2CDevice.c @@ -0,0 +1,262 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Mark Komus + * + * 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. + */ + +// This file contains all of the Python API definitions for the +// busio.I2C class. + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/adafruit_bus_device/I2CDevice.h" +#include "shared-bindings/util.h" +#include "shared-module/adafruit_bus_device/I2CDevice.h" + +#include "lib/utils/buffer_helper.h" +#include "lib/utils/context_manager_helpers.h" +#include "py/runtime.h" +#include "supervisor/shared/translate.h" + + +//| class I2CDevice: +//| """I2C Device Manager""" +//| +//| def __init__(self, i2c: busio.I2C, device_address: int, probe: bool = True) -> None: +//| +//| """Represents a single I2C device and manages locking the bus and the device +//| address. +//| :param ~busio.I2C i2c: The I2C bus the device is on +//| :param int device_address: The 7 bit device address +//| :param bool probe: Probe for the device upon object creation, default is true +//| +//| Example:: +//| +//| import busio +//| from board import * +//| from adafruit_bus_device.i2c_device import I2CDevice +//| with busio.I2C(SCL, SDA) as i2c: +//| device = I2CDevice(i2c, 0x70) +//| bytes_read = bytearray(4) +//| with device: +//| device.readinto(bytes_read) +//| # A second transaction +//| with device: +//| device.write(bytes_read)""" +//| ... +//| +STATIC mp_obj_t adafruit_bus_device_i2cdevice_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + adafruit_bus_device_i2cdevice_obj_t *self = m_new_obj(adafruit_bus_device_i2cdevice_obj_t); + self->base.type = &adafruit_bus_device_i2cdevice_type; + enum { ARG_i2c, ARG_device_address, ARG_probe }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_i2c, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_device_address, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_probe, MP_ARG_BOOL, {.u_bool = true} }, + }; + 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); + + busio_i2c_obj_t* i2c = args[ARG_i2c].u_obj; + + common_hal_adafruit_bus_device_i2cdevice_construct(MP_OBJ_TO_PTR(self), i2c, args[ARG_device_address].u_int); + if (args[ARG_probe].u_bool == true) { + common_hal_adafruit_bus_device_i2cdevice_probe_for_device(self); + } + + return (mp_obj_t)self; +} + +//| def __enter__(self) -> I2C: +//| """Context manager entry to lock bus.""" +//| ... +//| +STATIC mp_obj_t adafruit_bus_device_i2cdevice_obj___enter__(mp_obj_t self_in) { + adafruit_bus_device_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_adafruit_bus_device_i2cdevice_lock(self); + return self; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(adafruit_bus_device_i2cdevice___enter___obj, adafruit_bus_device_i2cdevice_obj___enter__); + +//| def __exit__(self) -> None: +//| """Automatically unlocks the bus on exit.""" +//| ... +//| +STATIC mp_obj_t adafruit_bus_device_i2cdevice_obj___exit__(size_t n_args, const mp_obj_t *args) { + common_hal_adafruit_bus_device_i2cdevice_unlock(MP_OBJ_TO_PTR(args[0])); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(adafruit_bus_device_i2cdevice___exit___obj, 4, 4, adafruit_bus_device_i2cdevice_obj___exit__); + +//| def readinto(self, buf, *, start=0, end=None) -> None: +//| """ +//| Read into ``buf`` from the device. The number of bytes read will be the +//| length of ``buf``. +//| If ``start`` or ``end`` is provided, then the buffer will be sliced +//| as if ``buf[start:end]``. This will not cause an allocation like +//| ``buf[start:end]`` will so it saves memory. +//| :param bytearray buffer: buffer to write into +//| :param int start: Index to start writing at +//| :param int end: Index to write up to but not include; if None, use ``len(buf)``""" +//| ... +//| +STATIC void readinto(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t start, mp_int_t end) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE); + + size_t length = bufinfo.len; + normalize_buffer_bounds(&start, end, &length); + if (length == 0) { + mp_raise_ValueError(translate("Buffer must be at least length 1")); + } + + uint8_t status = common_hal_adafruit_bus_device_i2cdevice_readinto(MP_OBJ_TO_PTR(self), ((uint8_t*)bufinfo.buf) + start, length); + if (status != 0) { + mp_raise_OSError(status); + } +} + +STATIC mp_obj_t adafruit_bus_device_i2cdevice_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_buffer, ARG_start, ARG_end }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + }; + + adafruit_bus_device_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + readinto(self, args[ARG_buffer].u_obj, args[ARG_start].u_int, args[ARG_end].u_int); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_readinto_obj, 2, adafruit_bus_device_i2cdevice_readinto); + +//| def write(self, buf, *, start=0, end=None) -> None: +//| """ +//| Write the bytes from ``buffer`` to the device, then transmit a stop bit. +//| If ``start`` or ``end`` is provided, then the buffer will be sliced +//| as if ``buffer[start:end]``. This will not cause an allocation like +//| ``buffer[start:end]`` will so it saves memory. +//| :param bytearray buffer: buffer containing the bytes to write +//| :param int start: Index to start writing from +//| :param int end: Index to read up to but not include; if None, use ``len(buf)`` +//| """ +//| ... +//| +STATIC void write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t start, mp_int_t end) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ); + + size_t length = bufinfo.len; + normalize_buffer_bounds(&start, end, &length); + if (length == 0) { + mp_raise_ValueError(translate("Buffer must be at least length 1")); + } + + uint8_t status = common_hal_adafruit_bus_device_i2cdevice_write(MP_OBJ_TO_PTR(self), ((uint8_t*)bufinfo.buf) + start, length); + if (status != 0) { + mp_raise_OSError(status); + } +} + +STATIC mp_obj_t adafruit_bus_device_i2cdevice_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_buffer, ARG_start, ARG_end }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + }; + adafruit_bus_device_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + write(self, args[ARG_buffer].u_obj, args[ARG_start].u_int, args[ARG_end].u_int); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_write_obj, 2, adafruit_bus_device_i2cdevice_write); + + +//| def write_then_readinto(self, out_buffer, in_buffer, *, out_start=0, out_end=None, in_start=0, in_end=None) -> None: +//| """ +//| Write the bytes from ``out_buffer`` to the device, then immediately +//| reads into ``in_buffer`` from the device. The number of bytes read +//| will be the length of ``in_buffer``. +//| If ``out_start`` or ``out_end`` is provided, then the output buffer +//| will be sliced as if ``out_buffer[out_start:out_end]``. This will +//| not cause an allocation like ``buffer[out_start:out_end]`` will so +//| it saves memory. +//| If ``in_start`` or ``in_end`` is provided, then the input buffer +//| will be sliced as if ``in_buffer[in_start:in_end]``. This will not +//| cause an allocation like ``in_buffer[in_start:in_end]`` will so +//| it saves memory. +//| :param bytearray out_buffer: buffer containing the bytes to write +//| :param bytearray in_buffer: buffer containing the bytes to read into +//| :param int out_start: Index to start writing from +//| :param int out_end: Index to read up to but not include; if None, use ``len(out_buffer)`` +//| :param int in_start: Index to start writing at +//| :param int in_end: Index to write up to but not include; if None, use ``len(in_buffer)`` +//| """ +//| ... +//| +STATIC mp_obj_t adafruit_bus_device_i2cdevice_write_then_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_out_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_in_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + { MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + }; + adafruit_bus_device_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + write(self, args[ARG_out_buffer].u_obj, args[ARG_out_start].u_int, args[ARG_out_end].u_int); + + readinto(self, args[ARG_in_buffer].u_obj, args[ARG_in_start].u_int, args[ARG_in_end].u_int); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_write_then_readinto_obj, 3, adafruit_bus_device_i2cdevice_write_then_readinto); + +STATIC const mp_rom_map_elem_t adafruit_bus_device_i2cdevice_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&adafruit_bus_device_i2cdevice___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&adafruit_bus_device_i2cdevice___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&adafruit_bus_device_i2cdevice_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&adafruit_bus_device_i2cdevice_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_then_readinto), MP_ROM_PTR(&adafruit_bus_device_i2cdevice_write_then_readinto_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(adafruit_bus_device_i2cdevice_locals_dict, adafruit_bus_device_i2cdevice_locals_dict_table); + +const mp_obj_type_t adafruit_bus_device_i2cdevice_type = { + { &mp_type_type }, + .name = MP_QSTR_I2CDevice, + .make_new = adafruit_bus_device_i2cdevice_make_new, + .locals_dict = (mp_obj_dict_t*)&adafruit_bus_device_i2cdevice_locals_dict, +}; diff --git a/shared-bindings/adafruit_bus_device/I2CDevice.h b/shared-bindings/adafruit_bus_device/I2CDevice.h new file mode 100644 index 000000000..7b2182ff0 --- /dev/null +++ b/shared-bindings/adafruit_bus_device/I2CDevice.h @@ -0,0 +1,53 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Mark Komus + * + * 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. + */ + +// Machine is the HAL for low-level, hardware accelerated functions. It is not +// meant to simplify APIs, its only meant to unify them so that other modules +// do not require port specific logic. +// +// This file includes externs for all functions a port should implement to +// support the machine module. + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_I2CDEVICE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_I2CDEVICE_H + +#include "py/obj.h" + +#include "shared-module/adafruit_bus_device/I2CDevice.h" +//#include "shared-bindings/busio/I2C.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t adafruit_bus_device_i2cdevice_type; + +// Initializes the hardware peripheral. +extern void common_hal_adafruit_bus_device_i2cdevice_construct(adafruit_bus_device_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address); +extern uint8_t common_hal_adafruit_bus_device_i2cdevice_readinto(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length); +extern uint8_t common_hal_adafruit_bus_device_i2cdevice_write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length); +extern void common_hal_adafruit_bus_device_i2cdevice_lock(adafruit_bus_device_i2cdevice_obj_t *self); +extern void common_hal_adafruit_bus_device_i2cdevice_unlock(adafruit_bus_device_i2cdevice_obj_t *self); +extern void common_hal_adafruit_bus_device_i2cdevice_probe_for_device(adafruit_bus_device_i2cdevice_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_I2CDEVICE_H diff --git a/shared-bindings/adafruit_bus_device/SPIDevice.c b/shared-bindings/adafruit_bus_device/SPIDevice.c new file mode 100644 index 000000000..e127e39b8 --- /dev/null +++ b/shared-bindings/adafruit_bus_device/SPIDevice.c @@ -0,0 +1,128 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Mark Komus + * + * 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 "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/adafruit_bus_device/SPIDevice.h" +#include "shared-bindings/util.h" +#include "shared-module/adafruit_bus_device/SPIDevice.h" +#include "common-hal/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + + +#include "lib/utils/buffer_helper.h" +#include "lib/utils/context_manager_helpers.h" +#include "py/runtime.h" +#include "supervisor/shared/translate.h" + + +//| class SPIDevice: +//| """SPI Device Manager""" +//| +//| def __init__(self, spi: busio.SPI, chip_select: microcontroller.Pin, *, baudrate: int = 100000, polarity: int = 0, phase: int = 0, extra_clocks : int = 0) -> None: +//| +//| """ +//| Represents a single SPI device and manages locking the bus and the device address. +//| :param ~busio.SPI spi: The SPI bus the device is on +//| :param ~digitalio.DigitalInOut chip_select: The chip select pin object that implements the DigitalInOut API. +//| :param int extra_clocks: The minimum number of clock cycles to cycle the bus after CS is high. (Used for SD cards.) +//| +//| Example:: +//| +//| import busio +//| import digitalio +//| from board import * +//| from adafruit_bus_device.spi_device import SPIDevice +//| with busio.SPI(SCK, MOSI, MISO) as spi_bus: +//| cs = digitalio.DigitalInOut(D10) +//| device = SPIDevice(spi_bus, cs) +//| bytes_read = bytearray(4) +//| # The object assigned to spi in the with statements below +//| # is the original spi_bus object. We are using the busio.SPI +//| # operations busio.SPI.readinto() and busio.SPI.write(). +//| with device as spi: +//| spi.readinto(bytes_read) +//| # A second transaction +//| with device as spi: +//| spi.write(bytes_read)""" +//| ... +//| +STATIC mp_obj_t adafruit_bus_device_spidevice_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + adafruit_bus_device_spidevice_obj_t *self = m_new_obj(adafruit_bus_device_spidevice_obj_t); + self->base.type = &adafruit_bus_device_spidevice_type; + enum { ARG_spi, ARG_chip_select, ARG_baudrate, ARG_polarity, ARG_phase, ARG_extra_clocks }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_spi, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_chip_select, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} }, + { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_extra_clocks, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + 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); + + busio_spi_obj_t* spi = args[ARG_spi].u_obj; + + common_hal_adafruit_bus_device_spidevice_construct(MP_OBJ_TO_PTR(self), spi, args[ARG_chip_select].u_obj, args[ARG_baudrate].u_int, args[ARG_polarity].u_int, + args[ARG_phase].u_int, args[ARG_extra_clocks].u_int); + + if (args[ARG_chip_select].u_obj != MP_OBJ_NULL) { + digitalinout_result_t result = common_hal_digitalio_digitalinout_switch_to_output(MP_OBJ_TO_PTR(args[ARG_chip_select].u_obj), + true, DRIVE_MODE_PUSH_PULL); + if (result == DIGITALINOUT_INPUT_ONLY) { + mp_raise_NotImplementedError(translate("Pin is input only")); + } + } + + return (mp_obj_t)self; +} + +STATIC mp_obj_t adafruit_bus_device_spidevice_obj___enter__(mp_obj_t self_in) { + adafruit_bus_device_spidevice_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_adafruit_bus_device_spidevice_enter(self); + return self->spi; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(adafruit_bus_device_spidevice___enter___obj, adafruit_bus_device_spidevice_obj___enter__); + +STATIC mp_obj_t adafruit_bus_device_spidevice_obj___exit__(size_t n_args, const mp_obj_t *args) { + common_hal_adafruit_bus_device_spidevice_exit(MP_OBJ_TO_PTR(args[0])); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(adafruit_bus_device_spidevice___exit___obj, 4, 4, adafruit_bus_device_spidevice_obj___exit__); + +STATIC const mp_rom_map_elem_t adafruit_bus_device_spidevice_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&adafruit_bus_device_spidevice___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&adafruit_bus_device_spidevice___exit___obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(adafruit_bus_device_spidevice_locals_dict, adafruit_bus_device_spidevice_locals_dict_table); + +const mp_obj_type_t adafruit_bus_device_spidevice_type = { + { &mp_type_type }, + .name = MP_QSTR_SPIDevice, + .make_new = adafruit_bus_device_spidevice_make_new, + .locals_dict = (mp_obj_dict_t*)&adafruit_bus_device_spidevice_locals_dict, +}; diff --git a/shared-bindings/adafruit_bus_device/SPIDevice.h b/shared-bindings/adafruit_bus_device/SPIDevice.h new file mode 100644 index 000000000..5596b157f --- /dev/null +++ b/shared-bindings/adafruit_bus_device/SPIDevice.h @@ -0,0 +1,50 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Mark Komus + * + * 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. + */ + +// Machine is the HAL for low-level, hardware accelerated functions. It is not +// meant to simplify APIs, its only meant to unify them so that other modules +// do not require port specific logic. +// +// This file includes externs for all functions a port should implement to +// support the machine module. + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_SPIDEVICE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_SPIDEVICE_H + +#include "py/obj.h" + +#include "shared-module/adafruit_bus_device/SPIDevice.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t adafruit_bus_device_spidevice_type; + +// Initializes the hardware peripheral. +extern void common_hal_adafruit_bus_device_spidevice_construct(adafruit_bus_device_spidevice_obj_t *self, busio_spi_obj_t *spi, digitalio_digitalinout_obj_t *cs, + uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t extra_clocks); +extern void common_hal_adafruit_bus_device_spidevice_enter(adafruit_bus_device_spidevice_obj_t *self); +extern void common_hal_adafruit_bus_device_spidevice_exit(adafruit_bus_device_spidevice_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_SPIDEVICE_H diff --git a/shared-bindings/adafruit_bus_device/__init__.c b/shared-bindings/adafruit_bus_device/__init__.c new file mode 100644 index 000000000..e01abcab3 --- /dev/null +++ b/shared-bindings/adafruit_bus_device/__init__.c @@ -0,0 +1,78 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Mark Komus + * + * 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 + +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mphal.h" +#include "py/objproperty.h" + +#include "shared-bindings/adafruit_bus_device/__init__.h" +#include "shared-bindings/adafruit_bus_device/I2CDevice.h" +#include "shared-bindings/adafruit_bus_device/SPIDevice.h" + +STATIC const mp_rom_map_elem_t adafruit_bus_device_i2c_device_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_i2c_device) }, + { MP_ROM_QSTR(MP_QSTR_I2CDevice), MP_ROM_PTR(&adafruit_bus_device_i2cdevice_type) }, +}; +STATIC MP_DEFINE_CONST_DICT(adafruit_bus_device_i2c_device_globals, adafruit_bus_device_i2c_device_globals_table); + +const mp_obj_module_t adafruit_bus_device_i2c_device_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&adafruit_bus_device_i2c_device_globals, +}; + +STATIC const mp_rom_map_elem_t adafruit_bus_device_spi_device_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_spi_device) }, + { MP_ROM_QSTR(MP_QSTR_SPIDevice), MP_ROM_PTR(&adafruit_bus_device_spidevice_type) }, +}; +STATIC MP_DEFINE_CONST_DICT(adafruit_bus_device_spi_device_globals, adafruit_bus_device_spi_device_globals_table); + +const mp_obj_module_t adafruit_bus_device_spi_device_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&adafruit_bus_device_spi_device_globals, +}; + +//| """Hardware accelerated external bus access +//| +//| The I2CDevice and SPIDevice helper classes make managing transaction state on a bus easy. +//| For example, they manage locking the bus to prevent other concurrent access. For SPI +//| devices, it manages the chip select and protocol changes such as mode. For I2C, it +//| manages the device address.""" +//| +STATIC const mp_rom_map_elem_t adafruit_bus_device_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_adafruit_bus_device) }, + { MP_ROM_QSTR(MP_QSTR_i2c_device), MP_ROM_PTR(&adafruit_bus_device_i2c_device_module) }, + { MP_ROM_QSTR(MP_QSTR_spi_device), MP_ROM_PTR(&adafruit_bus_device_spi_device_module) }, +}; + +STATIC MP_DEFINE_CONST_DICT(adafruit_bus_device_module_globals, adafruit_bus_device_module_globals_table); + +const mp_obj_module_t adafruit_bus_device_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&adafruit_bus_device_module_globals, +}; diff --git a/shared-bindings/adafruit_bus_device/__init__.h b/shared-bindings/adafruit_bus_device/__init__.h new file mode 100644 index 000000000..4a669807b --- /dev/null +++ b/shared-bindings/adafruit_bus_device/__init__.h @@ -0,0 +1,32 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Mark Komus + * + * 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_SHARED_BINDINGS_BUSDEVICE___INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE___INIT___H + +// Nothing now. + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE___INIT___H diff --git a/shared-bindings/busdevice/I2CDevice.c b/shared-bindings/busdevice/I2CDevice.c deleted file mode 100644 index 43996138b..000000000 --- a/shared-bindings/busdevice/I2CDevice.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 Mark Komus - * - * 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. - */ - -// This file contains all of the Python API definitions for the -// busio.I2C class. - -#include "shared-bindings/microcontroller/Pin.h" -#include "shared-bindings/busdevice/I2CDevice.h" -#include "shared-bindings/util.h" -#include "shared-module/busdevice/I2CDevice.h" - -#include "lib/utils/buffer_helper.h" -#include "lib/utils/context_manager_helpers.h" -#include "py/runtime.h" -#include "supervisor/shared/translate.h" - - -//| class I2CDevice: -//| """I2C Device Manager""" -//| -//| def __init__(self, i2c: busio.I2C, device_address: int, probe: bool = True) -> None: -//| -//| """Represents a single I2C device and manages locking the bus and the device -//| address. -//| :param ~busio.I2C i2c: The I2C bus the device is on -//| :param int device_address: The 7 bit device address -//| :param bool probe: Probe for the device upon object creation, default is true -//| -//| Example:: -//| -//| import busio -//| from board import * -//| from adafruit_bus_device.i2c_device import I2CDevice -//| with busio.I2C(SCL, SDA) as i2c: -//| device = I2CDevice(i2c, 0x70) -//| bytes_read = bytearray(4) -//| with device: -//| device.readinto(bytes_read) -//| # A second transaction -//| with device: -//| device.write(bytes_read)""" -//| ... -//| -STATIC mp_obj_t busdevice_i2cdevice_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - busdevice_i2cdevice_obj_t *self = m_new_obj(busdevice_i2cdevice_obj_t); - self->base.type = &busdevice_i2cdevice_type; - enum { ARG_i2c, ARG_device_address, ARG_probe }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_i2c, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_device_address, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_probe, MP_ARG_BOOL, {.u_bool = true} }, - }; - 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); - - busio_i2c_obj_t* i2c = args[ARG_i2c].u_obj; - - common_hal_busdevice_i2cdevice_construct(MP_OBJ_TO_PTR(self), i2c, args[ARG_device_address].u_int); - if (args[ARG_probe].u_bool == true) { - common_hal_busdevice_i2cdevice_probe_for_device(self); - } - - return (mp_obj_t)self; -} - -//| def __enter__(self) -> I2C: -//| """Context manager entry to lock bus.""" -//| ... -//| -STATIC mp_obj_t busdevice_i2cdevice_obj___enter__(mp_obj_t self_in) { - busdevice_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_busdevice_i2cdevice_lock(self); - return self; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(busdevice_i2cdevice___enter___obj, busdevice_i2cdevice_obj___enter__); - -//| def __exit__(self) -> None: -//| """Automatically unlocks the bus on exit.""" -//| ... -//| -STATIC mp_obj_t busdevice_i2cdevice_obj___exit__(size_t n_args, const mp_obj_t *args) { - common_hal_busdevice_i2cdevice_unlock(MP_OBJ_TO_PTR(args[0])); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busdevice_i2cdevice___exit___obj, 4, 4, busdevice_i2cdevice_obj___exit__); - -//| def readinto(self, buf, *, start=0, end=None) -> None: -//| """ -//| Read into ``buf`` from the device. The number of bytes read will be the -//| length of ``buf``. -//| If ``start`` or ``end`` is provided, then the buffer will be sliced -//| as if ``buf[start:end]``. This will not cause an allocation like -//| ``buf[start:end]`` will so it saves memory. -//| :param bytearray buffer: buffer to write into -//| :param int start: Index to start writing at -//| :param int end: Index to write up to but not include; if None, use ``len(buf)``""" -//| ... -//| -STATIC void readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t start, mp_int_t end) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE); - - size_t length = bufinfo.len; - normalize_buffer_bounds(&start, end, &length); - if (length == 0) { - mp_raise_ValueError(translate("Buffer must be at least length 1")); - } - - uint8_t status = common_hal_busdevice_i2cdevice_readinto(MP_OBJ_TO_PTR(self), ((uint8_t*)bufinfo.buf) + start, length); - if (status != 0) { - mp_raise_OSError(status); - } -} - -STATIC mp_obj_t busdevice_i2cdevice_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_buffer, ARG_start, ARG_end }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, - }; - - busdevice_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - readinto(self, args[ARG_buffer].u_obj, args[ARG_start].u_int, args[ARG_end].u_int); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(busdevice_i2cdevice_readinto_obj, 2, busdevice_i2cdevice_readinto); - -//| def write(self, buf, *, start=0, end=None) -> None: -//| """ -//| Write the bytes from ``buffer`` to the device, then transmit a stop bit. -//| If ``start`` or ``end`` is provided, then the buffer will be sliced -//| as if ``buffer[start:end]``. This will not cause an allocation like -//| ``buffer[start:end]`` will so it saves memory. -//| :param bytearray buffer: buffer containing the bytes to write -//| :param int start: Index to start writing from -//| :param int end: Index to read up to but not include; if None, use ``len(buf)`` -//| """ -//| ... -//| -STATIC void write(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t start, mp_int_t end) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ); - - size_t length = bufinfo.len; - normalize_buffer_bounds(&start, end, &length); - if (length == 0) { - mp_raise_ValueError(translate("Buffer must be at least length 1")); - } - - uint8_t status = common_hal_busdevice_i2cdevice_write(MP_OBJ_TO_PTR(self), ((uint8_t*)bufinfo.buf) + start, length); - if (status != 0) { - mp_raise_OSError(status); - } -} - -STATIC mp_obj_t busdevice_i2cdevice_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_buffer, ARG_start, ARG_end }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, - }; - busdevice_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - write(self, args[ARG_buffer].u_obj, args[ARG_start].u_int, args[ARG_end].u_int); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(busdevice_i2cdevice_write_obj, 2, busdevice_i2cdevice_write); - - -//| def write_then_readinto(self, out_buffer, in_buffer, *, out_start=0, out_end=None, in_start=0, in_end=None) -> None: -//| """ -//| Write the bytes from ``out_buffer`` to the device, then immediately -//| reads into ``in_buffer`` from the device. The number of bytes read -//| will be the length of ``in_buffer``. -//| If ``out_start`` or ``out_end`` is provided, then the output buffer -//| will be sliced as if ``out_buffer[out_start:out_end]``. This will -//| not cause an allocation like ``buffer[out_start:out_end]`` will so -//| it saves memory. -//| If ``in_start`` or ``in_end`` is provided, then the input buffer -//| will be sliced as if ``in_buffer[in_start:in_end]``. This will not -//| cause an allocation like ``in_buffer[in_start:in_end]`` will so -//| it saves memory. -//| :param bytearray out_buffer: buffer containing the bytes to write -//| :param bytearray in_buffer: buffer containing the bytes to read into -//| :param int out_start: Index to start writing from -//| :param int out_end: Index to read up to but not include; if None, use ``len(out_buffer)`` -//| :param int in_start: Index to start writing at -//| :param int in_end: Index to write up to but not include; if None, use ``len(in_buffer)`` -//| """ -//| ... -//| -STATIC mp_obj_t busdevice_i2cdevice_write_then_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_out_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_in_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, - { MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, - }; - busdevice_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - write(self, args[ARG_out_buffer].u_obj, args[ARG_out_start].u_int, args[ARG_out_end].u_int); - - readinto(self, args[ARG_in_buffer].u_obj, args[ARG_in_start].u_int, args[ARG_in_end].u_int); - - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(busdevice_i2cdevice_write_then_readinto_obj, 3, busdevice_i2cdevice_write_then_readinto); - -STATIC const mp_rom_map_elem_t busdevice_i2cdevice_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&busdevice_i2cdevice___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&busdevice_i2cdevice___exit___obj) }, - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&busdevice_i2cdevice_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&busdevice_i2cdevice_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_write_then_readinto), MP_ROM_PTR(&busdevice_i2cdevice_write_then_readinto_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(busdevice_i2cdevice_locals_dict, busdevice_i2cdevice_locals_dict_table); - -const mp_obj_type_t busdevice_i2cdevice_type = { - { &mp_type_type }, - .name = MP_QSTR_I2CDevice, - .make_new = busdevice_i2cdevice_make_new, - .locals_dict = (mp_obj_dict_t*)&busdevice_i2cdevice_locals_dict, -}; diff --git a/shared-bindings/busdevice/I2CDevice.h b/shared-bindings/busdevice/I2CDevice.h deleted file mode 100644 index a1f869c45..000000000 --- a/shared-bindings/busdevice/I2CDevice.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 Mark Komus - * - * 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. - */ - -// Machine is the HAL for low-level, hardware accelerated functions. It is not -// meant to simplify APIs, its only meant to unify them so that other modules -// do not require port specific logic. -// -// This file includes externs for all functions a port should implement to -// support the machine module. - -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_I2CDEVICE_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_I2CDEVICE_H - -#include "py/obj.h" - -#include "shared-module/busdevice/I2CDevice.h" -//#include "shared-bindings/busio/I2C.h" - -// Type object used in Python. Should be shared between ports. -extern const mp_obj_type_t busdevice_i2cdevice_type; - -// Initializes the hardware peripheral. -extern void common_hal_busdevice_i2cdevice_construct(busdevice_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address); -extern uint8_t common_hal_busdevice_i2cdevice_readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length); -extern uint8_t common_hal_busdevice_i2cdevice_write(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length); -extern void common_hal_busdevice_i2cdevice_lock(busdevice_i2cdevice_obj_t *self); -extern void common_hal_busdevice_i2cdevice_unlock(busdevice_i2cdevice_obj_t *self); -extern void common_hal_busdevice_i2cdevice_probe_for_device(busdevice_i2cdevice_obj_t *self); - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_I2CDEVICE_H diff --git a/shared-bindings/busdevice/SPIDevice.c b/shared-bindings/busdevice/SPIDevice.c deleted file mode 100644 index 631d0eec4..000000000 --- a/shared-bindings/busdevice/SPIDevice.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 Mark Komus - * - * 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 "shared-bindings/microcontroller/Pin.h" -#include "shared-bindings/busdevice/SPIDevice.h" -#include "shared-bindings/util.h" -#include "shared-module/busdevice/SPIDevice.h" -#include "common-hal/digitalio/DigitalInOut.h" -#include "shared-bindings/digitalio/DigitalInOut.h" - - -#include "lib/utils/buffer_helper.h" -#include "lib/utils/context_manager_helpers.h" -#include "py/runtime.h" -#include "supervisor/shared/translate.h" - - -//| class SPIDevice: -//| """SPI Device Manager""" -//| -//| def __init__(self, spi: busio.SPI, chip_select: microcontroller.Pin, *, baudrate: int = 100000, polarity: int = 0, phase: int = 0, extra_clocks : int = 0) -> None: -//| -//| """ -//| Represents a single SPI device and manages locking the bus and the device address. -//| :param ~busio.SPI spi: The SPI bus the device is on -//| :param ~digitalio.DigitalInOut chip_select: The chip select pin object that implements the DigitalInOut API. -//| :param int extra_clocks: The minimum number of clock cycles to cycle the bus after CS is high. (Used for SD cards.) -//| -//| Example:: -//| -//| import busio -//| import digitalio -//| from board import * -//| from adafruit_bus_device.spi_device import SPIDevice -//| with busio.SPI(SCK, MOSI, MISO) as spi_bus: -//| cs = digitalio.DigitalInOut(D10) -//| device = SPIDevice(spi_bus, cs) -//| bytes_read = bytearray(4) -//| # The object assigned to spi in the with statements below -//| # is the original spi_bus object. We are using the busio.SPI -//| # operations busio.SPI.readinto() and busio.SPI.write(). -//| with device as spi: -//| spi.readinto(bytes_read) -//| # A second transaction -//| with device as spi: -//| spi.write(bytes_read)""" -//| ... -//| -STATIC mp_obj_t busdevice_spidevice_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - busdevice_spidevice_obj_t *self = m_new_obj(busdevice_spidevice_obj_t); - self->base.type = &busdevice_spidevice_type; - enum { ARG_spi, ARG_chip_select, ARG_baudrate, ARG_polarity, ARG_phase, ARG_extra_clocks }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_spi, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_chip_select, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} }, - { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_extra_clocks, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - }; - 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); - - busio_spi_obj_t* spi = args[ARG_spi].u_obj; - - common_hal_busdevice_spidevice_construct(MP_OBJ_TO_PTR(self), spi, args[ARG_chip_select].u_obj, args[ARG_baudrate].u_int, args[ARG_polarity].u_int, - args[ARG_phase].u_int, args[ARG_extra_clocks].u_int); - - if (args[ARG_chip_select].u_obj != MP_OBJ_NULL) { - digitalinout_result_t result = common_hal_digitalio_digitalinout_switch_to_output(MP_OBJ_TO_PTR(args[ARG_chip_select].u_obj), - true, DRIVE_MODE_PUSH_PULL); - if (result == DIGITALINOUT_INPUT_ONLY) { - mp_raise_NotImplementedError(translate("Pin is input only")); - } - } - - return (mp_obj_t)self; -} - -STATIC mp_obj_t busdevice_spidevice_obj___enter__(mp_obj_t self_in) { - busdevice_spidevice_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_busdevice_spidevice_enter(self); - return self->spi; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(busdevice_spidevice___enter___obj, busdevice_spidevice_obj___enter__); - -STATIC mp_obj_t busdevice_spidevice_obj___exit__(size_t n_args, const mp_obj_t *args) { - common_hal_busdevice_spidevice_exit(MP_OBJ_TO_PTR(args[0])); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busdevice_spidevice___exit___obj, 4, 4, busdevice_spidevice_obj___exit__); - -STATIC const mp_rom_map_elem_t busdevice_spidevice_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&busdevice_spidevice___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&busdevice_spidevice___exit___obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(busdevice_spidevice_locals_dict, busdevice_spidevice_locals_dict_table); - -const mp_obj_type_t busdevice_spidevice_type = { - { &mp_type_type }, - .name = MP_QSTR_SPIDevice, - .make_new = busdevice_spidevice_make_new, - .locals_dict = (mp_obj_dict_t*)&busdevice_spidevice_locals_dict, -}; diff --git a/shared-bindings/busdevice/SPIDevice.h b/shared-bindings/busdevice/SPIDevice.h deleted file mode 100644 index 040f98548..000000000 --- a/shared-bindings/busdevice/SPIDevice.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 Mark Komus - * - * 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. - */ - -// Machine is the HAL for low-level, hardware accelerated functions. It is not -// meant to simplify APIs, its only meant to unify them so that other modules -// do not require port specific logic. -// -// This file includes externs for all functions a port should implement to -// support the machine module. - -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_SPIDEVICE_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_SPIDEVICE_H - -#include "py/obj.h" - -#include "shared-module/busdevice/SPIDevice.h" - -// Type object used in Python. Should be shared between ports. -extern const mp_obj_type_t busdevice_spidevice_type; - -// Initializes the hardware peripheral. -extern void common_hal_busdevice_spidevice_construct(busdevice_spidevice_obj_t *self, busio_spi_obj_t *spi, digitalio_digitalinout_obj_t *cs, - uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t extra_clocks); -extern void common_hal_busdevice_spidevice_enter(busdevice_spidevice_obj_t *self); -extern void common_hal_busdevice_spidevice_exit(busdevice_spidevice_obj_t *self); - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_SPIDEVICE_H diff --git a/shared-bindings/busdevice/__init__.c b/shared-bindings/busdevice/__init__.c deleted file mode 100644 index a9a1a83a3..000000000 --- a/shared-bindings/busdevice/__init__.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 Mark Komus - * - * 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 - -#include "py/obj.h" -#include "py/runtime.h" -#include "py/mphal.h" -#include "py/objproperty.h" - -#include "shared-bindings/busdevice/__init__.h" -#include "shared-bindings/busdevice/I2CDevice.h" -#include "shared-bindings/busdevice/SPIDevice.h" - -STATIC const mp_rom_map_elem_t busdevice_i2c_device_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_i2c_device) }, - { MP_ROM_QSTR(MP_QSTR_I2CDevice), MP_ROM_PTR(&busdevice_i2cdevice_type) }, -}; -STATIC MP_DEFINE_CONST_DICT(busdevice_i2c_device_globals, busdevice_i2c_device_globals_table); - -const mp_obj_module_t busdevice_i2c_device_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&busdevice_i2c_device_globals, -}; - -STATIC const mp_rom_map_elem_t busdevice_spi_device_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_spi_device) }, - { MP_ROM_QSTR(MP_QSTR_SPIDevice), MP_ROM_PTR(&busdevice_spidevice_type) }, -}; -STATIC MP_DEFINE_CONST_DICT(busdevice_spi_device_globals, busdevice_spi_device_globals_table); - -const mp_obj_module_t busdevice_spi_device_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&busdevice_spi_device_globals, -}; - -//| """Hardware accelerated external bus access -//| -//| The I2CDevice and SPIDevice helper classes make managing transaction state on a bus easy. -//| For example, they manage locking the bus to prevent other concurrent access. For SPI -//| devices, it manages the chip select and protocol changes such as mode. For I2C, it -//| manages the device address.""" -//| -STATIC const mp_rom_map_elem_t busdevice_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_busdevice) }, - { MP_ROM_QSTR(MP_QSTR_i2c_device), MP_ROM_PTR(&busdevice_i2c_device_module) }, - { MP_ROM_QSTR(MP_QSTR_spi_device), MP_ROM_PTR(&busdevice_spi_device_module) }, -}; - -STATIC MP_DEFINE_CONST_DICT(busdevice_module_globals, busdevice_module_globals_table); - -const mp_obj_module_t busdevice_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&busdevice_module_globals, -}; diff --git a/shared-bindings/busdevice/__init__.h b/shared-bindings/busdevice/__init__.h deleted file mode 100644 index 4a669807b..000000000 --- a/shared-bindings/busdevice/__init__.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 Mark Komus - * - * 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_SHARED_BINDINGS_BUSDEVICE___INIT___H -#define MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE___INIT___H - -// Nothing now. - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE___INIT___H diff --git a/shared-module/adafruit_bus_device/I2CDevice.c b/shared-module/adafruit_bus_device/I2CDevice.c new file mode 100644 index 000000000..d790ff53a --- /dev/null +++ b/shared-module/adafruit_bus_device/I2CDevice.c @@ -0,0 +1,74 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Mark Komus + * + * 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 "shared-bindings/adafruit_bus_device/I2CDevice.h" +#include "shared-bindings/busio/I2C.h" +#include "py/mperrno.h" +#include "py/nlr.h" +#include "py/runtime.h" + +void common_hal_adafruit_bus_device_i2cdevice_construct(adafruit_bus_device_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address) { + self->i2c = i2c; + self->device_address = device_address; +} + +void common_hal_adafruit_bus_device_i2cdevice_lock(adafruit_bus_device_i2cdevice_obj_t *self) { + bool success = false; + while (!success) { + success = common_hal_busio_i2c_try_lock(self->i2c); + //RUN_BACKGROUND_TASKS; + //mp_handle_pending(); + } +} + +void common_hal_adafruit_bus_device_i2cdevice_unlock(adafruit_bus_device_i2cdevice_obj_t *self) { + common_hal_busio_i2c_unlock(self->i2c); +} + +uint8_t common_hal_adafruit_bus_device_i2cdevice_readinto(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length) { + return common_hal_busio_i2c_read(self->i2c, self->device_address, buffer, length); +} + +uint8_t common_hal_adafruit_bus_device_i2cdevice_write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length) { + return common_hal_busio_i2c_write(self->i2c, self->device_address, buffer, length, true); +} + +void common_hal_adafruit_bus_device_i2cdevice_probe_for_device(adafruit_bus_device_i2cdevice_obj_t *self) { + common_hal_adafruit_bus_device_i2cdevice_lock(self); + + mp_buffer_info_t bufinfo; + mp_obj_t buffer = mp_obj_new_bytearray_of_zeros(1); + + mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE); + + uint8_t status = common_hal_adafruit_bus_device_i2cdevice_readinto(self, (uint8_t*)bufinfo.buf, 1); + if (status != 0) { + common_hal_adafruit_bus_device_i2cdevice_unlock(self); + mp_raise_ValueError_varg(translate("No I2C device at address: %x"), self->device_address); + } + + common_hal_adafruit_bus_device_i2cdevice_unlock(self); +} diff --git a/shared-module/adafruit_bus_device/I2CDevice.h b/shared-module/adafruit_bus_device/I2CDevice.h new file mode 100644 index 000000000..d06adb9f5 --- /dev/null +++ b/shared-module/adafruit_bus_device/I2CDevice.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * 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_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H +#define MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H + +#include "py/obj.h" +#include "common-hal/busio/I2C.h" + +typedef struct { + mp_obj_base_t base; + busio_i2c_obj_t *i2c; + uint8_t device_address; +} adafruit_bus_device_i2cdevice_obj_t; + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H diff --git a/shared-module/adafruit_bus_device/SPIDevice.c b/shared-module/adafruit_bus_device/SPIDevice.c new file mode 100644 index 000000000..e489fc7c0 --- /dev/null +++ b/shared-module/adafruit_bus_device/SPIDevice.c @@ -0,0 +1,85 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Mark Komus + * + * 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 "shared-bindings/adafruit_bus_device/SPIDevice.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "py/mperrno.h" +#include "py/nlr.h" +#include "py/runtime.h" + +void common_hal_adafruit_bus_device_spidevice_construct(adafruit_bus_device_spidevice_obj_t *self, busio_spi_obj_t *spi, digitalio_digitalinout_obj_t *cs, + uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t extra_clocks) { + self->spi = spi; + self->baudrate = baudrate; + self->polarity = polarity; + self->phase = phase; + self->extra_clocks = extra_clocks; + self->chip_select = cs; +} + +void common_hal_adafruit_bus_device_spidevice_enter(adafruit_bus_device_spidevice_obj_t *self) { + bool success = false; + while (!success) { + success = common_hal_busio_spi_try_lock(self->spi); + RUN_BACKGROUND_TASKS; + mp_handle_pending(); + } + + common_hal_busio_spi_configure(self->spi, self->baudrate, self->polarity, self->phase, 8); + + if (self->chip_select != MP_OBJ_NULL) { + common_hal_digitalio_digitalinout_set_value(MP_OBJ_TO_PTR(self->chip_select), false); + } +} + +void common_hal_adafruit_bus_device_spidevice_exit(adafruit_bus_device_spidevice_obj_t *self) { + if (self->chip_select != MP_OBJ_NULL) { + common_hal_digitalio_digitalinout_set_value(MP_OBJ_TO_PTR(self->chip_select), true); + } + + if (self->extra_clocks > 0) { + + mp_buffer_info_t bufinfo; + mp_obj_t buffer = mp_obj_new_bytearray_of_zeros(1); + + mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ); + ((uint8_t*)bufinfo.buf)[0] = 0xFF; + + uint8_t clocks = self->extra_clocks / 8; + if ((self->extra_clocks % 8) != 0) + clocks += 1; + + while (clocks > 0) { + if (!common_hal_busio_spi_write(self->spi, ((uint8_t*)bufinfo.buf), 1)) { + mp_raise_OSError(MP_EIO); + } + clocks--; + } + } + + common_hal_busio_spi_unlock(self->spi); +} diff --git a/shared-module/adafruit_bus_device/SPIDevice.h b/shared-module/adafruit_bus_device/SPIDevice.h new file mode 100644 index 000000000..1a7c70fa7 --- /dev/null +++ b/shared-module/adafruit_bus_device/SPIDevice.h @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * 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_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H +#define MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H + +#include "py/obj.h" +#include "common-hal/busio/SPI.h" +#include "common-hal/digitalio/DigitalInOut.h" + +typedef struct { + mp_obj_base_t base; + busio_spi_obj_t *spi; + uint32_t baudrate; + uint8_t polarity; + uint8_t phase; + uint8_t extra_clocks; + digitalio_digitalinout_obj_t *chip_select; +} adafruit_bus_device_spidevice_obj_t; + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H diff --git a/shared-module/adafruit_bus_device/__init__.c b/shared-module/adafruit_bus_device/__init__.c new file mode 100644 index 000000000..e69de29bb diff --git a/shared-module/busdevice/I2CDevice.c b/shared-module/busdevice/I2CDevice.c deleted file mode 100644 index b9f8ee25c..000000000 --- a/shared-module/busdevice/I2CDevice.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 Mark Komus - * - * 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 "shared-bindings/busdevice/I2CDevice.h" -#include "shared-bindings/busio/I2C.h" -#include "py/mperrno.h" -#include "py/nlr.h" -#include "py/runtime.h" - -void common_hal_busdevice_i2cdevice_construct(busdevice_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address) { - self->i2c = i2c; - self->device_address = device_address; -} - -void common_hal_busdevice_i2cdevice_lock(busdevice_i2cdevice_obj_t *self) { - bool success = false; - while (!success) { - success = common_hal_busio_i2c_try_lock(self->i2c); - //RUN_BACKGROUND_TASKS; - //mp_handle_pending(); - } -} - -void common_hal_busdevice_i2cdevice_unlock(busdevice_i2cdevice_obj_t *self) { - common_hal_busio_i2c_unlock(self->i2c); -} - -uint8_t common_hal_busdevice_i2cdevice_readinto(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length) { - return common_hal_busio_i2c_read(self->i2c, self->device_address, buffer, length); -} - -uint8_t common_hal_busdevice_i2cdevice_write(busdevice_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length) { - return common_hal_busio_i2c_write(self->i2c, self->device_address, buffer, length, true); -} - -void common_hal_busdevice_i2cdevice_probe_for_device(busdevice_i2cdevice_obj_t *self) { - common_hal_busdevice_i2cdevice_lock(self); - - mp_buffer_info_t bufinfo; - mp_obj_t buffer = mp_obj_new_bytearray_of_zeros(1); - - mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE); - - uint8_t status = common_hal_busdevice_i2cdevice_readinto(self, (uint8_t*)bufinfo.buf, 1); - if (status != 0) { - common_hal_busdevice_i2cdevice_unlock(self); - mp_raise_ValueError_varg(translate("No I2C device at address: %x"), self->device_address); - } - - common_hal_busdevice_i2cdevice_unlock(self); -} diff --git a/shared-module/busdevice/I2CDevice.h b/shared-module/busdevice/I2CDevice.h deleted file mode 100644 index 918dc7719..000000000 --- a/shared-module/busdevice/I2CDevice.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * - * 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_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H -#define MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H - -#include "py/obj.h" -#include "common-hal/busio/I2C.h" - -typedef struct { - mp_obj_base_t base; - busio_i2c_obj_t *i2c; - uint8_t device_address; -} busdevice_i2cdevice_obj_t; - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H diff --git a/shared-module/busdevice/SPIDevice.c b/shared-module/busdevice/SPIDevice.c deleted file mode 100644 index d9b63a007..000000000 --- a/shared-module/busdevice/SPIDevice.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 Mark Komus - * - * 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 "shared-bindings/busdevice/SPIDevice.h" -#include "shared-bindings/busio/SPI.h" -#include "shared-bindings/digitalio/DigitalInOut.h" -#include "py/mperrno.h" -#include "py/nlr.h" -#include "py/runtime.h" - -void common_hal_busdevice_spidevice_construct(busdevice_spidevice_obj_t *self, busio_spi_obj_t *spi, digitalio_digitalinout_obj_t *cs, - uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t extra_clocks) { - self->spi = spi; - self->baudrate = baudrate; - self->polarity = polarity; - self->phase = phase; - self->extra_clocks = extra_clocks; - self->chip_select = cs; -} - -void common_hal_busdevice_spidevice_enter(busdevice_spidevice_obj_t *self) { - bool success = false; - while (!success) { - success = common_hal_busio_spi_try_lock(self->spi); - RUN_BACKGROUND_TASKS; - mp_handle_pending(); - } - - common_hal_busio_spi_configure(self->spi, self->baudrate, self->polarity, self->phase, 8); - - if (self->chip_select != MP_OBJ_NULL) { - common_hal_digitalio_digitalinout_set_value(MP_OBJ_TO_PTR(self->chip_select), false); - } -} - -void common_hal_busdevice_spidevice_exit(busdevice_spidevice_obj_t *self) { - if (self->chip_select != MP_OBJ_NULL) { - common_hal_digitalio_digitalinout_set_value(MP_OBJ_TO_PTR(self->chip_select), true); - } - - if (self->extra_clocks > 0) { - - mp_buffer_info_t bufinfo; - mp_obj_t buffer = mp_obj_new_bytearray_of_zeros(1); - - mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ); - ((uint8_t*)bufinfo.buf)[0] = 0xFF; - - uint8_t clocks = self->extra_clocks / 8; - if ((self->extra_clocks % 8) != 0) - clocks += 1; - - while (clocks > 0) { - if (!common_hal_busio_spi_write(self->spi, ((uint8_t*)bufinfo.buf), 1)) { - mp_raise_OSError(MP_EIO); - } - clocks--; - } - } - - common_hal_busio_spi_unlock(self->spi); -} diff --git a/shared-module/busdevice/SPIDevice.h b/shared-module/busdevice/SPIDevice.h deleted file mode 100644 index ffabf79df..000000000 --- a/shared-module/busdevice/SPIDevice.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * - * 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_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H -#define MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H - -#include "py/obj.h" -#include "common-hal/busio/SPI.h" -#include "common-hal/digitalio/DigitalInOut.h" - -typedef struct { - mp_obj_base_t base; - busio_spi_obj_t *spi; - uint32_t baudrate; - uint8_t polarity; - uint8_t phase; - uint8_t extra_clocks; - digitalio_digitalinout_obj_t *chip_select; -} busdevice_spidevice_obj_t; - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H diff --git a/shared-module/busdevice/__init__.c b/shared-module/busdevice/__init__.c deleted file mode 100644 index e69de29bb..000000000 -- cgit v1.2.3 From 03b110b44c8e8fed1feb43b7c14b03bbfddf4f2c Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Wed, 11 Nov 2020 09:58:08 -0600 Subject: Add abort check in I2C lock --- shared-module/adafruit_bus_device/I2CDevice.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'shared-module') diff --git a/shared-module/adafruit_bus_device/I2CDevice.c b/shared-module/adafruit_bus_device/I2CDevice.c index d790ff53a..ee4b4fa55 100644 --- a/shared-module/adafruit_bus_device/I2CDevice.c +++ b/shared-module/adafruit_bus_device/I2CDevice.c @@ -29,6 +29,7 @@ #include "py/mperrno.h" #include "py/nlr.h" #include "py/runtime.h" +#include "lib/utils/interrupt_char.h" void common_hal_adafruit_bus_device_i2cdevice_construct(adafruit_bus_device_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address) { self->i2c = i2c; @@ -36,11 +37,15 @@ void common_hal_adafruit_bus_device_i2cdevice_construct(adafruit_bus_device_i2cd } void common_hal_adafruit_bus_device_i2cdevice_lock(adafruit_bus_device_i2cdevice_obj_t *self) { - bool success = false; + bool success = common_hal_busio_i2c_try_lock(self->i2c); + while (!success) { + RUN_BACKGROUND_TASKS; + if (mp_hal_is_interrupted()) { + break; + } + success = common_hal_busio_i2c_try_lock(self->i2c); - //RUN_BACKGROUND_TASKS; - //mp_handle_pending(); } } -- cgit v1.2.3