From ccbb5e84f980e252f7380d96fcc5c417a8a64523 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 3 Nov 2016 15:50:59 -0700 Subject: This introduces an alternative hardware API called nativeio structured around different functions that are typically accelerated by native hardware. Its not meant to reflect the structure of the hardware. Docs are here: http://tannewt-micropython.readthedocs.io/en/microcontroller/ It differs from upstream's machine in the following ways: * Python API is identical across ports due to code structure. (Lives in shared-bindings) * Focuses on abstracting common functionality (AnalogIn) and not representing structure (ADC). * Documentation lives with code making it easy to ensure they match. * Pin is split into references (board.D13 and microcontroller.pin.PA17) and functionality (DigitalInOut). * All nativeio classes claim underlying hardware resources when inited on construction, support Context Managers (aka with statements) and have deinit methods which release the claimed hardware. * All constructors take pin references rather than peripheral ids. Its up to the implementation to find hardware or throw and exception. --- shared-bindings/bitbangio/I2C.c | 181 +++++++++++ shared-bindings/bitbangio/I2C.h | 59 ++++ shared-bindings/bitbangio/SPI.c | 178 +++++++++++ shared-bindings/bitbangio/SPI.h | 51 ++++ shared-bindings/bitbangio/__init__.c | 93 ++++++ shared-bindings/bitbangio/__init__.h | 34 +++ shared-bindings/board/__init__.c | 44 +++ shared-bindings/board/__init__.h | 34 +++ shared-bindings/index.rst | 2 +- shared-bindings/microcontroller/Pin.c | 46 +++ shared-bindings/microcontroller/Pin.h | 35 +++ shared-bindings/microcontroller/__init__.c | 99 ++++++ shared-bindings/microcontroller/__init__.h | 36 +++ shared-bindings/modules/machine.c | 466 ----------------------------- shared-bindings/modules/machine.h | 92 ------ shared-bindings/nativeio/AnalogIn.c | 106 +++++++ shared-bindings/nativeio/AnalogIn.h | 38 +++ shared-bindings/nativeio/AnalogOut.c | 121 ++++++++ shared-bindings/nativeio/AnalogOut.h | 39 +++ shared-bindings/nativeio/DigitalInOut.c | 445 +++++++++++++++++++++++++++ shared-bindings/nativeio/DigitalInOut.h | 68 +++++ shared-bindings/nativeio/I2C.c | 180 +++++++++++ shared-bindings/nativeio/I2C.h | 64 ++++ shared-bindings/nativeio/PWMOut.c | 151 ++++++++++ shared-bindings/nativeio/PWMOut.h | 40 +++ shared-bindings/nativeio/SPI.c | 167 +++++++++++ shared-bindings/nativeio/SPI.h | 51 ++++ shared-bindings/nativeio/__init__.c | 122 ++++++++ shared-bindings/nativeio/__init__.h | 34 +++ shared-bindings/neopixel_write/__init__.c | 75 +++++ shared-bindings/neopixel_write/__init__.h | 37 +++ shared-bindings/time/__init__.c | 91 ++++++ shared-bindings/time/__init__.h | 36 +++ 33 files changed, 2756 insertions(+), 559 deletions(-) create mode 100644 shared-bindings/bitbangio/I2C.c create mode 100644 shared-bindings/bitbangio/I2C.h create mode 100644 shared-bindings/bitbangio/SPI.c create mode 100644 shared-bindings/bitbangio/SPI.h create mode 100644 shared-bindings/bitbangio/__init__.c create mode 100644 shared-bindings/bitbangio/__init__.h create mode 100644 shared-bindings/board/__init__.c create mode 100644 shared-bindings/board/__init__.h create mode 100644 shared-bindings/microcontroller/Pin.c create mode 100644 shared-bindings/microcontroller/Pin.h create mode 100644 shared-bindings/microcontroller/__init__.c create mode 100644 shared-bindings/microcontroller/__init__.h delete mode 100644 shared-bindings/modules/machine.c delete mode 100644 shared-bindings/modules/machine.h create mode 100644 shared-bindings/nativeio/AnalogIn.c create mode 100644 shared-bindings/nativeio/AnalogIn.h create mode 100644 shared-bindings/nativeio/AnalogOut.c create mode 100644 shared-bindings/nativeio/AnalogOut.h create mode 100644 shared-bindings/nativeio/DigitalInOut.c create mode 100644 shared-bindings/nativeio/DigitalInOut.h create mode 100644 shared-bindings/nativeio/I2C.c create mode 100644 shared-bindings/nativeio/I2C.h create mode 100644 shared-bindings/nativeio/PWMOut.c create mode 100644 shared-bindings/nativeio/PWMOut.h create mode 100644 shared-bindings/nativeio/SPI.c create mode 100644 shared-bindings/nativeio/SPI.h create mode 100644 shared-bindings/nativeio/__init__.c create mode 100644 shared-bindings/nativeio/__init__.h create mode 100644 shared-bindings/neopixel_write/__init__.c create mode 100644 shared-bindings/neopixel_write/__init__.h create mode 100644 shared-bindings/time/__init__.c create mode 100644 shared-bindings/time/__init__.h (limited to 'shared-bindings') diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c new file mode 100644 index 000000000..d92b0db82 --- /dev/null +++ b/shared-bindings/bitbangio/I2C.c @@ -0,0 +1,181 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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 +// bitbangio.I2C class. + +#include "shared-bindings/bitbangio/I2C.h" + +#include "py/runtime.h" +//| .. currentmodule:: bitbangio +//| +//| :class:`I2C` --- Two wire serial protocol +//| ------------------------------------------ +//| +//| .. class:: I2C(scl, sda, \*, freq=400000) +//| +//| I2C is a two-wire protocol for communicating between devices. At the +//| physical level it consists of 2 wires: SCL and SDA, the clock and data +//| lines respectively. +//| +//| :param ~microcontroller.Pin scl: The clock pin +//| :param ~microcontroller.Pin sda: The data pin +//| :param int freq: The clock frequency +//| +STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + bitbangio_i2c_obj_t *self = m_new_obj(bitbangio_i2c_obj_t); + self->base.type = &bitbangio_i2c_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_scl, ARG_sda, ARG_freq }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + }; + 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); + const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj); + const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj); + shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_freq].u_int); + return (mp_obj_t)self; +} + +//| .. method:: I2C.deinit() +//| +//| Releases control of the underlying hardware so other classes can use it. +//| +STATIC mp_obj_t bitbangio_i2c_obj_deinit(mp_obj_t self_in) { + bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + shared_module_bitbangio_i2c_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_deinit_obj, bitbangio_i2c_obj_deinit); + +//| .. method:: I2C.__enter__() +//| +//| No-op used in Context Managers. +//| +STATIC mp_obj_t bitbangio_i2c_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c___enter___obj, bitbangio_i2c_obj___enter__); + +//| .. method:: I2C.__exit__() +//| +//| Automatically deinitializes the hardware on context exit. +//| +STATIC mp_obj_t bitbangio_i2c_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + shared_module_bitbangio_i2c_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_i2c_obj___exit___obj, 4, 4, bitbangio_i2c_obj___exit__); + +//| .. method:: I2C.scan() +//| +//| Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of +//| those that respond. A device responds if it pulls the SDA line low after +//| its address (including a read bit) is sent on the bus. +//| +STATIC mp_obj_t bitbangio_i2c_scan(mp_obj_t self_in) { + bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_t list = mp_obj_new_list(0, NULL); + // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved + for (int addr = 0x08; addr < 0x78; ++addr) { + bool success = shared_module_bitbangio_i2c_probe(self, addr); + if (success) { + mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); + } + } + return list; +} +MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_scan_obj, bitbangio_i2c_scan); + +//| .. method:: I2C.writeto(address, buffer, stop=True) +//| +//| Write the bytes from ``buffer`` to the slave specified by ``address``. +//| Transmits a stop bit if ``stop`` is set. +//| +STATIC mp_obj_t bitbangio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_address, ARG_buffer, ARG_stop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_stop, MP_ARG_BOOL, {.u_bool = true} }, + }; + bitbangio_i2c_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); + + // get the buffer to write the data from + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); + + // do the transfer + bool ok = shared_module_bitbangio_i2c_write(self, args[ARG_address].u_int, + bufinfo.buf, bufinfo.len, args[ARG_stop].u_bool); + if (!ok) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_writeto); + +//| .. method:: I2C.readfrom_into(address, buffer) +//| +//| Read into ``buffer`` from the slave specified by ``address``. +//| The number of bytes read will be the length of `buf`. +//| +STATIC mp_obj_t bitbangio_i2c_readfrom_into(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) { + bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); + shared_module_bitbangio_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)bufinfo.buf, bufinfo.len); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_3(bitbangio_i2c_readfrom_into_obj, bitbangio_i2c_readfrom_into); + +STATIC const mp_rom_map_elem_t bitbangio_i2c_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bitbangio_i2c_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&bitbangio_i2c___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&bitbangio_i2c_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&bitbangio_i2c_scan_obj) }, + + // standard bus operations + { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&bitbangio_i2c_writeto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&bitbangio_i2c_readfrom_into_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bitbangio_i2c_locals_dict, bitbangio_i2c_locals_dict_table); + +const mp_obj_type_t bitbangio_i2c_type = { + { &mp_type_type }, + .name = MP_QSTR_I2C, + .make_new = bitbangio_i2c_make_new, + .locals_dict = (mp_obj_dict_t*)&bitbangio_i2c_locals_dict, +}; diff --git a/shared-bindings/bitbangio/I2C.h b/shared-bindings/bitbangio/I2C.h new file mode 100644 index 000000000..71d379eb8 --- /dev/null +++ b/shared-bindings/bitbangio/I2C.h @@ -0,0 +1,59 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_BITBANGIO_I2C_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO_I2C_H__ + +#include "py/obj.h" + +#include "common-hal/microcontroller/types.h" +#include "shared-module/bitbangio/types.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t bitbangio_i2c_type; + +// Initializes the hardware peripheral. +extern void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self, + const mcu_pin_obj_t * scl, + const mcu_pin_obj_t * sda, + uint32_t freq); + +extern void shared_module_bitbangio_i2c_deinit(bitbangio_i2c_obj_t *self); + +// Probe the bus to see if a device acknowledges the given address. +extern bool shared_module_bitbangio_i2c_probe(bitbangio_i2c_obj_t *self, uint8_t addr); + +extern bool shared_module_bitbangio_i2c_write(bitbangio_i2c_obj_t *self, + uint16_t address, + const uint8_t * data, size_t len, + bool stop); + +// Reads memory of the i2c device picking up where it left off. +extern bool shared_module_bitbangio_i2c_read(bitbangio_i2c_obj_t *self, + uint16_t address, + uint8_t * data, size_t len); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO_I2C_H__ diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c new file mode 100644 index 000000000..560834ac8 --- /dev/null +++ b/shared-bindings/bitbangio/SPI.c @@ -0,0 +1,178 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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 +// bitbangio.SPI class. + +#include + +#include "shared-bindings/bitbangio/SPI.h" + +#include "py/runtime.h" + +//| .. currentmodule:: bitbangio +//| +//| :class:`SPI` -- a 3-4 wire serial protocol +//| ----------------------------------------------- +//| +//| SPI is a serial protocol that has exclusive pins for data in and out of the +//| master. It is typically faster than :py:class:`~bitbangio.I2C` because a +//| separate pin is used to control the active slave rather than a transmitted +//| address. This class only manages three of the four SPI lines: `!clock`, +//| `!MOSI`, `!MISO`. Its up to the client to manage the appropriate slave +//| select line. (This is common because multiple slaves can share the `!clock`, +//| `!MOSI` and `!MISO` lines and therefore the hardware.) +//| +//| .. class:: SPI(clock, MOSI, MISO, baudrate=1000000) +//| +//| Construct an SPI object on the given pins. +//| +//| :param ~microcontroller.Pin clock: the pin to use for the clock. +//| :param ~microcontroller.Pin MOSI: the Master Out Slave In pin. +//| :param ~microcontroller.Pin MISO: the Master In Slave Out pin. +//| :param int baudrate: is the SCK clock rate. +//| + +// TODO(tannewt): Support LSB SPI. +// TODO(tannewt): Support phase, polarity and bit order. +STATIC mp_obj_t bitbangio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + bitbangio_spi_obj_t *self = m_new_obj(bitbangio_spi_obj_t); + self->base.type = &bitbangio_spi_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_MOSI, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_MISO, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { 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 = 400000} }, + { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, + }; + 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); + const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(args[ARG_clock].u_obj); + const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(args[ARG_MOSI].u_obj); + const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(args[ARG_MISO].u_obj); + shared_module_bitbangio_spi_construct(self, clock, mosi, miso, args[ARG_baudrate].u_int); + return (mp_obj_t)self; +} + +//| .. method:: SPI.deinit() +//| +//| Turn off the SPI bus. +//| +STATIC mp_obj_t bitbangio_spi_obj_deinit(mp_obj_t self_in) { + bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + shared_module_bitbangio_spi_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_deinit_obj, bitbangio_spi_obj_deinit); + +//| .. method:: SPI.__enter__() +//| +//| No-op used by Context Managers. +//| +STATIC mp_obj_t bitbangio_spi_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi___enter___obj, bitbangio_spi_obj___enter__); + +//| .. method:: SPI.__exit__() +//| +//| Automatically deinitializes the hardware when exiting a context. +//| +STATIC mp_obj_t bitbangio_spi_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + shared_module_bitbangio_spi_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_spi_obj___exit___obj, 4, 4, bitbangio_spi_obj___exit__); + +//| .. method:: SPI.transfer(write_buffer=None, read_buffer=None, address=0) +//| +//| Write out ``write_buffer`` and then read into ``read_buffer``. They do +//| not need to be the same length. If either buffer is omitted then the +//| transfer skips the corresponding portion. +//| +//| ``address`` is taken for I2C compatibility but is ignored. +//| +//| When writing, data received is dropped. When reading, zeroes are written +//| out. +//| +STATIC mp_obj_t bitbangio_spi_transfer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_write_buffer, ARG_read_buffer, ARG_address }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_write_buffer, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL } }, + { MP_QSTR_read_buffer, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL } }, + { MP_QSTR_address, MP_ARG_INT, {.u_int = 0} }, + }; + bitbangio_spi_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); + + // get the buffer to store data into + mp_buffer_info_t write_bufinfo; + if (!mp_get_buffer(args[ARG_write_buffer].u_obj, &write_bufinfo, MP_BUFFER_READ)) { + write_bufinfo.len = 0; + } + + mp_buffer_info_t read_bufinfo; + if (!mp_get_buffer(args[ARG_read_buffer].u_obj, &read_bufinfo, MP_BUFFER_WRITE)) { + read_bufinfo.len = 0; + } + + if (write_bufinfo.len == 0 && read_bufinfo.len == 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "At least one buffer should be provided.")); + } + + // do the transfer + bool ok = shared_module_bitbangio_spi_transfer(self, write_bufinfo.buf, + write_bufinfo.len, read_bufinfo.buf, read_bufinfo.len); + if (!ok) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_spi_transfer_obj, 2, bitbangio_spi_transfer); + +STATIC const mp_rom_map_elem_t bitbangio_spi_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bitbangio_spi_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&bitbangio_spi___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&bitbangio_spi_obj___exit___obj) }, + + { MP_ROM_QSTR(MP_QSTR_transfer), MP_ROM_PTR(&bitbangio_spi_transfer_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(bitbangio_spi_locals_dict, bitbangio_spi_locals_dict_table); + +const mp_obj_type_t bitbangio_spi_type = { + { &mp_type_type }, + .name = MP_QSTR_SPI, + .make_new = bitbangio_spi_make_new, + .locals_dict = (mp_obj_dict_t*)&bitbangio_spi_locals_dict, +}; diff --git a/shared-bindings/bitbangio/SPI.h b/shared-bindings/bitbangio/SPI.h new file mode 100644 index 000000000..a11df1f7b --- /dev/null +++ b/shared-bindings/bitbangio/SPI.h @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_BITBANGIO_SPI_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO_SPI_H__ + +#include "py/obj.h" + +#include "common-hal/microcontroller/types.h" +#include "shared-module/bitbangio/types.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t bitbangio_spi_type; + +// Construct an underlying SPI object. +extern void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self, + const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, + const mcu_pin_obj_t * miso, uint32_t baudrate); + +extern void shared_module_bitbangio_spi_deinit(bitbangio_spi_obj_t *self); + +// Write out write_buffer then read read_buffer. Returns true on success, false +// otherwise. +extern bool shared_module_bitbangio_spi_transfer(bitbangio_spi_obj_t *self, + const uint8_t *write_buffer, size_t write_buffer_len, + uint8_t *read_buffer, size_t read_buffer_len); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO_SPI_H__ diff --git a/shared-bindings/bitbangio/__init__.c b/shared-bindings/bitbangio/__init__.c new file mode 100644 index 000000000..69e39a2e5 --- /dev/null +++ b/shared-bindings/bitbangio/__init__.c @@ -0,0 +1,93 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// bitbangio implements some standard protocols in the processor. Its only +// dependency is nativeio.DigitalInOut. + +#include +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/bitbangio/__init__.h" +#include "shared-bindings/bitbangio/I2C.h" +#include "shared-bindings/bitbangio/SPI.h" +#include "shared-module/bitbangio/types.h" + +#include "py/runtime.h" + +//| :mod:`bitbangio` --- Digital protocols implemented by the CPU +//| ============================================================= +//| +//| .. module:: bitbangio +//| :synopsis: Digital protocols implemented by the CPU +//| :platform: SAMD21 +//| +//| The `bitbangio` module contains classes to provide digital protocol support +//| regardless of whether the underlying hardware exists to use the protocol. +//| +//| First try to use `nativeio` module instead which utilizes peripheral +//| hardware to implement the protocols. Native implementations will be faster +//| than bitbanged versions and have more capabilities. +//| +//| Libraries +//| +//| .. toctree:: +//| :maxdepth: 3 +//| +//| I2C +//| SPI +//| +//| All libraries change hardware state and should be deinitialized when they +//| are no longer needed. To do so, either call :py:meth:`!deinit` or use a +//| context manager. +//| +//| For example:: +//| +//| import bitbangio +//| from board import * +//| +//| with bitbangio.I2C(SCL, SDA) as i2c: +//| i2c.scan() +//| +//| This example will initialize the the device, run +//| :py:meth:`~bitbangio.I2C.scan` and then :py:meth:`~bitbangio.I2C.deinit` the +//| hardware. +//| + +STATIC const mp_rom_map_elem_t bitbangio_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bitbangio) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&bitbangio_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&bitbangio_spi_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bitbangio_module_globals, bitbangio_module_globals_table); + +const mp_obj_module_t bitbangio_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&bitbangio_module_globals, +}; diff --git a/shared-bindings/bitbangio/__init__.h b/shared-bindings/bitbangio/__init__.h new file mode 100644 index 000000000..4404501eb --- /dev/null +++ b/shared-bindings/bitbangio/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_BITBANGIO___INIT___H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO___INIT___H__ + +#include "py/obj.h" + +// Nothing now. + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO___INIT___H__ diff --git a/shared-bindings/board/__init__.c b/shared-bindings/board/__init__.c new file mode 100644 index 000000000..06c2f218f --- /dev/null +++ b/shared-bindings/board/__init__.c @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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 "py/obj.h" + +#include "shared-bindings/board/__init__.h" + +//| :mod:`board` --- Board specific pin names +//| ======================================================== +//| +//| .. module:: board +//| :synopsis: Board specific pin names +//| :platform: SAMD21 +//| +//| Common container for board base pin names. These will vary from board to +//| board so don't expect portability when using this module. + +const mp_obj_module_t board_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&board_module_globals, +}; diff --git a/shared-bindings/board/__init__.h b/shared-bindings/board/__init__.h new file mode 100644 index 000000000..9ab646a45 --- /dev/null +++ b/shared-bindings/board/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_BOARD___INIT___H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_BOARD___INIT___H__ + +#include "py/obj.h" + +extern const mp_obj_dict_t board_module_globals; + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_BOARD___INIT___H__ diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst index 42394febe..c1c63276c 100644 --- a/shared-bindings/index.rst +++ b/shared-bindings/index.rst @@ -9,4 +9,4 @@ follow. :glob: :maxdepth: 3 - modules/* + */__init__ diff --git a/shared-bindings/microcontroller/Pin.c b/shared-bindings/microcontroller/Pin.c new file mode 100644 index 000000000..733fa29ec --- /dev/null +++ b/shared-bindings/microcontroller/Pin.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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" + +//| .. currentmodule:: microcontroller +//| +//| :class:`Pin` --- Pin reference +//| ------------------------------------------ +//| +//| Identifies an IO pin on the microcontroller. +//| +//| .. class:: Pin +//| +//| Identifies an IO pin on the microcontroller. They are fixed by the +//| hardware so they cannot be constructed on demand. Instead, use +//| `board` or `microcontroller.pin` to reference the desired pin. +//| + +const mp_obj_type_t mcu_pin_type = { + { &mp_type_type }, + .name = MP_QSTR_Pin, +}; diff --git a/shared-bindings/microcontroller/Pin.h b/shared-bindings/microcontroller/Pin.h new file mode 100644 index 000000000..96df67ef8 --- /dev/null +++ b/shared-bindings/microcontroller/Pin.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_MICROCONTROLLER_PIN_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_PIN_H__ + +#include "py/obj.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t mcu_pin_type; + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_PIN_H__ diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c new file mode 100644 index 000000000..239251805 --- /dev/null +++ b/shared-bindings/microcontroller/__init__.c @@ -0,0 +1,99 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// Microcontroller contains pin references and microcontroller specific control +// functions. + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "common-hal/microcontroller/types.h" + +#include "py/runtime.h" + +//| :mod:`microcontroller` --- Pin references and core functionality +//| ================================================================ +//| +//| .. module:: microcontroller +//| :synopsis: Pin references and core functionality +//| :platform: SAMD21 +//| +//| The `microcontroller` module defines the pins from the perspective of the +//| microcontroller. See `board` for board-specific pin mappings. +//| +//| Libraries +//| +//| .. toctree:: +//| :maxdepth: 3 +//| +//| Pin +//| + +//| .. method:: delay_us(delay) +//| +//| Dedicated delay method used for very short delays. DO NOT do long delays +//| because it will stall any concurrent code. +//| +STATIC mp_obj_t mcu_delay_us(mp_obj_t delay_obj) { + uint32_t delay = mp_obj_get_int(delay_obj); + + common_hal_mcu_delay_us(delay); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mcu_delay_us_obj, mcu_delay_us); + +//| :mod:`microcontroller.pin` --- Microcontroller pin names +//| -------------------------------------------------------- +//| +//| .. module:: microcontroller.pin +//| :synopsis: Microcontroller pin names +//| :platform: SAMD21 +//| +//| References to pins as named by the microcontroller +//| +const mp_obj_module_t mcu_pin_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mcu_pin_globals, +}; + +STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_microcontroller) }, + { MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) }, + { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&mcu_pin_type) }, + { MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&mcu_pin_module) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mcu_module_globals, mcu_module_globals_table); + +const mp_obj_module_t microcontroller_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mcu_module_globals, +}; diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h new file mode 100644 index 000000000..3600d3b08 --- /dev/null +++ b/shared-bindings/microcontroller/__init__.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_MICROCONTROLLER___INIT___H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER___INIT___H__ + +#include "py/obj.h" + +extern void common_hal_mcu_delay_us(uint32_t); + +extern const mp_obj_dict_t mcu_pin_globals; + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER___INIT___H__ diff --git a/shared-bindings/modules/machine.c b/shared-bindings/modules/machine.c deleted file mode 100644 index 49c8b00aa..000000000 --- a/shared-bindings/modules/machine.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Scott Shawcroft - * - * 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 machine module. -// 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. - -#include "machine.h" - -#include "py/runtime.h" - -//| :mod:`machine` --- functions related to the board -//| ================================================= -//| -//| .. module:: machine -//| :synopsis: functions related to the board -//| :platform: SAMD21 -//| -//| The ``machine`` module contains specific functions related to the board. -//| -//| This is soon to be renamed to distinguish it from upstream's `machine`! -//| -//| :class:`I2C` --- Two wire serial protocol -//| ------------------------------------------ -//| -//| .. class:: I2C(scl, sda, \*, freq=400000) -//| -//| I2C is a two-wire protocol for communicating between devices. At the -//| physical level it consists of 2 wires: SCL and SDA, the clock and data lines -//| respectively. -//| -//| I2C objects are created attached to a specific bus. They can be initialised -//| when created, or initialised later on. -//| -//| :param str scl: The clock pin -//| :param str sda: The data pin -//| :param int freq: The clock frequency -//| -STATIC mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { - mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); - machine_i2c_obj_t *self = m_new_obj(machine_i2c_obj_t); - self->base.type = &machine_i2c_type; - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_scl, ARG_sda, ARG_freq }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, - }; - 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); - // TODO(tannewt): Replace pin_find with a unified version. - const pin_obj_t* scl = pin_find(args[ARG_scl].u_obj); - const pin_obj_t* sda = pin_find(args[ARG_sda].u_obj); - mp_hal_i2c_construct(self, scl, sda, args[ARG_freq].u_int); - return (mp_obj_t)self; -} - - -//| .. method:: I2C.deinit() -//| -//| Releases control of the underlying hardware so other classes can use it. -//| -STATIC mp_obj_t machine_i2c_obj_deinit(mp_obj_t self_in) { - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_hal_i2c_deinit(self); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_deinit_obj, machine_i2c_obj_deinit); - -//| .. method:: I2C.__enter__() -//| -//| No-op used in Context Managers. -//| -STATIC mp_obj_t machine_i2c_obj___enter__(mp_obj_t self_in) { - return self_in; -} -MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c___enter___obj, machine_i2c_obj___enter__); - -//| .. method:: I2C.__exit__() -//| -//| Automatically deinitializes the hardware on context exit. -//| -STATIC mp_obj_t machine_i2c_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - mp_hal_i2c_deinit(args[0]); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_obj___exit___obj, 4, 4, machine_i2c_obj___exit__); - -//| .. method:: I2C.scan() -//| -//| Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of -//| those that respond. A device responds if it pulls the SDA line low after -//| its address (including a read bit) is sent on the bus. -//| -STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_t list = mp_obj_new_list(0, NULL); - // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved - for (int addr = 0x08; addr < 0x78; ++addr) { - bool success = mp_hal_i2c_probe(self, addr); - if (success) { - mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); - } - } - return list; -} -MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan); - -//| .. method:: I2C.readfrom(addr, nbytes) -//| -//| Read `nbytes` from the slave specified by `addr`. -//| -//| :param int addr: The 7 bit address of the device -//| :param int nbytes: The number of bytes to read -//| :return: the data read -//| :rtype: bytes -//| -STATIC mp_obj_t machine_i2c_readfrom(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t nbytes_in) { - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - vstr_t vstr; - vstr_init_len(&vstr, mp_obj_get_int(nbytes_in)); - mp_hal_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)vstr.buf, vstr.len); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); -} -MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_obj, machine_i2c_readfrom); - -//| .. method:: I2C.readfrom_into(addr, buf) -//| -//| Read into `buf` from the slave specified by `addr`. -//| The number of bytes read will be the length of `buf`. -//| -STATIC mp_obj_t machine_i2c_readfrom_into(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) { - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); - mp_hal_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)bufinfo.buf, bufinfo.len); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_into_obj, machine_i2c_readfrom_into); - -//| .. method:: I2C.writeto(addr, buf) -//| -//| Write the bytes from `buf` to the slave specified by `addr`. -//| -STATIC mp_obj_t machine_i2c_writeto(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) { - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - mp_hal_i2c_write(self, mp_obj_get_int(addr_in), bufinfo.buf, bufinfo.len); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_writeto_obj, machine_i2c_writeto); - -//| .. method:: I2C.readfrom_mem(addr, memaddr, nbytes, \*, addrsize=8) -//| -//| Read `nbytes` from the slave specified by `addr` starting from the memory -//| address specified by `memaddr`. -//| The argument `addrsize` specifies the address size in bits (on ESP8266 -//| this argument is not recognised and the address size is always 8 bits). -//| Returns a `bytes` object with the data read. -//| -STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_n, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO - }; - machine_i2c_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); - - // create the buffer to store data into - vstr_t vstr; - vstr_init_len(&vstr, args[ARG_n].u_int); - - // do the transfer - mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, (uint8_t*)vstr.buf, vstr.len); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem); - - -//| .. method:: I2C.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8) -//| -//| Read into `buf` from the slave specified by `addr` starting from the -//| memory address specified by `memaddr`. The number of bytes read is the -//| length of `buf`. -//| The argument `addrsize` specifies the address size in bits (on ESP8266 -//| this argument is not recognised and the address size is always 8 bits). -//| -STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO - }; - machine_i2c_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); - - // get the buffer to store data into - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE); - - // do the transfer - mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into); - -//| .. method:: I2C.writeto_mem(addr, memaddr, buf, \*, addrsize=8) -//| -//| Write `buf` to the slave specified by `addr` starting from the -//| memory address specified by `memaddr`. -//| The argument `addrsize` specifies the address size in bits (on ESP8266 -//| this argument is not recognised and the address size is always 8 bits). -//| -STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO - }; - machine_i2c_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); - - // get the buffer to write the data from - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ); - - // do the transfer - mp_hal_i2c_write_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem); - -STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2c_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&machine_i2c___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&machine_i2c_obj___exit___obj) }, - { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) }, - - // standard bus operations - { MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) }, - { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) }, - - // memory operations - // TODO(tannewt): Move these into a separate loadable Python module. - { MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) }, - { MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(machine_i2c_locals_dict, machine_i2c_locals_dict_table); - -const mp_obj_type_t machine_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .make_new = machine_i2c_make_new, - .locals_dict = (mp_obj_dict_t*)&machine_i2c_locals_dict, -}; - -//| :class:`SPI` -- a 3-4 wire serial protocol -//| ----------------------------------------------- -//| -//| SPI is a serial protocol that has exlusive pins for data in and out of the -//| master. It is typically faster than `I2C` because a separate pin is used to -//| control the active slave rather than a transitted address. This class only -//| manages three of the four SPI lines: `clock`, `MOSI`, `MISO`. Its up to the -//| client to manage the appropriate slave select line. (This is common because -//| multiple slaves can share the `clock`, `MOSI` and `MISO` lines and therefore -//| the hardware.) -//| -//| .. class:: SPI(clock, MOSI, MISO, baudrate=1000000) -//| -//| Construct an SPI object on the given bus. ``id`` can be only 0. -//| With no additional parameters, the SPI object is created but not -//| initialised (it has the settings from the last initialisation of -//| the bus, if any). If extra arguments are given, the bus is initialised. -//| See ``init`` for parameters of initialisation. -//| -//| - ``clock`` is the pin to use for the clock. -//| - ``MOSI`` is the Master Out Slave In pin. -//| - ``MISO`` is the Master In Slave Out pin. -//| - ``baudrate`` is the SCK clock rate. -//| - -// TODO(tannewt): Support LSB SPI. -// TODO(tannewt): Support phase, polarity and bit order. -STATIC mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { - mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); - machine_spi_obj_t *self = m_new_obj(machine_spi_obj_t); - self->base.type = &machine_spi_type; - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_MOSI, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_MISO, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { 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 = 400000} }, - { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, - { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, - }; - 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); - // TODO(tannewt): Replace pin_find with a unified version. - const pin_obj_t* clock = pin_find(args[ARG_clock].u_obj); - const pin_obj_t* mosi = pin_find(args[ARG_MOSI].u_obj); - const pin_obj_t* miso = pin_find(args[ARG_MISO].u_obj); - mp_hal_spi_construct(self, clock, mosi, miso, args[ARG_baudrate].u_int); - return (mp_obj_t)self; -} - -//| .. method:: SPI.deinit() -//| -//| Turn off the SPI bus. -//| -STATIC mp_obj_t machine_spi_obj_deinit(mp_obj_t self_in) { - machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_hal_spi_deinit(self); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_obj_deinit); - -//| .. method:: SPI.__enter__() -//| -//| No-op used by Context Managers. -//| -STATIC mp_obj_t machine_spi_obj___enter__(mp_obj_t self_in) { - return self_in; -} -MP_DEFINE_CONST_FUN_OBJ_1(machine_spi___enter___obj, machine_spi_obj___enter__); - -//| .. method:: SPI.__enter__() -//| -//| Automatically deinitializes the hardware when exiting a context. -//| -STATIC mp_obj_t machine_spi_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - mp_hal_spi_deinit(args[0]); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_spi_obj___exit___obj, 4, 4, machine_spi_obj___exit__); - -//| .. method:: SPI.write_readinto(write_buf, read_buf) -//| -//| Write from ``write_buf`` and read into ``read_buf``. Both buffers must have the -//| same length. This is the same as a SPI transfer function on other platforms. -//| Returns the number of bytes written -//| -STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self_in, mp_obj_t wr_buf, mp_obj_t rd_buf) { - mp_buffer_info_t src; - mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); - mp_buffer_info_t dest; - mp_get_buffer_raise(rd_buf, &dest, MP_BUFFER_WRITE); - if (src.len != dest.len) { - mp_raise_ValueError("buffers must be the same length"); - } - machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_hal_spi_transfer(self, src.len, (uint8_t *) src.buf, (uint8_t *) dest.buf); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_spi_write_readinto); - -//| .. method:: SPI.write(buf) -//| -//| Write the data contained in ``buf``. -//| Returns the number of bytes written. -//| -STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) { - mp_buffer_info_t src; - mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); - machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_hal_spi_transfer(self, src.len, (uint8_t *) src.buf, NULL); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write); - -//| .. method:: SPI.read(nbytes, *, write=0x00) -//| -//| Read the ``nbytes`` while writing the data specified by ``write``. -//| Return the number of bytes read. -//| -STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) { - vstr_t vstr; - vstr_init_len(&vstr, mp_obj_get_int(args[1])); - memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len); - mp_hal_spi_transfer(args[0], vstr.len, (uint8_t *) vstr.buf, (uint8_t *) vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read); - -//| .. method:: SPI.readinto(buf, *, write=0x00) -//| -//| Read into the buffer specified by ``buf`` while writing the data -//| specified by ``write``. -//| Return the number of bytes read. -//| -STATIC mp_obj_t mp_machine_spi_readinto(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); - memset(bufinfo.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, bufinfo.len); - mp_hal_spi_transfer(args[0], bufinfo.len, (uint8_t *) bufinfo.buf, (uint8_t *) bufinfo.buf); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp_machine_spi_readinto); - -STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_spi_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&machine_spi___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&machine_spi_obj___exit___obj) }, - - // Standard simultaneous read/write transfer. - { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) }, - - // Helper methods. - // TODO(tannewt): Move these into a helper Python class. - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(machine_spi_locals_dict, machine_spi_locals_dict_table); - -const mp_obj_type_t machine_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .make_new = machine_spi_make_new, - .locals_dict = (mp_obj_dict_t*)&machine_spi_locals_dict, -}; diff --git a/shared-bindings/modules/machine.h b/shared-bindings/modules/machine.h deleted file mode 100644 index a3f8a4a0c..000000000 --- a/shared-bindings/modules/machine.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Scott Shawcroft - * - * 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_API_MACHINE_H__ -#define __MICROPY_INCLUDED_API_MACHINE_H__ - -#include "py/obj.h" - -// Should include these structs which will be passed through to the port -// implementation: -// * pin_obj_t -// * machine_i2c_obj_t - -// TODO(tannewt): Standardize the type names. - -#include "machine_types.h" - -#include "modmachine_pin.h" - -// Type object used in Python. Should be shared between ports. -extern const mp_obj_type_t machine_i2c_type; -extern const mp_obj_type_t machine_spi_type; - -// Initializes the hardware peripheral. -extern void mp_hal_i2c_construct(machine_i2c_obj_t *self, const pin_obj_t * scl, - const pin_obj_t * sda, uint32_t freq); - -extern void mp_hal_i2c_init(machine_i2c_obj_t *self); -extern void mp_hal_i2c_deinit(machine_i2c_obj_t *self); - -// Probe the bus to see if a device acknowledges the given address. -extern bool mp_hal_i2c_probe(machine_i2c_obj_t *self, uint8_t addr); - -// Reads memory of the i2c device picking up where it left off. -extern void mp_hal_i2c_read(machine_i2c_obj_t *self, uint8_t addr, - uint8_t *data, size_t len); - -// Reads memory of the i2c device starting at memaddr. -extern void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr, - uint16_t memaddr, uint8_t *dest, size_t len); - -extern void mp_hal_i2c_write(machine_i2c_obj_t *self, uint8_t addr, - uint8_t *data, size_t len); - -// Writes memory of the i2c device starting at memaddr. -extern void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr, - uint16_t memaddr, const uint8_t *src, - size_t len); - -// Construct an underlying SPI object. -extern void mp_hal_spi_construct(machine_spi_obj_t *self, const pin_obj_t * clock, - const pin_obj_t * mosi, const pin_obj_t * miso, - uint32_t baudrate); - -extern void mp_hal_spi_init(machine_spi_obj_t *self); -extern void mp_hal_spi_deinit(machine_spi_obj_t *self); - -// Concurrently write and read len bytes from the SPI port. Chip select is -// handled externally. -extern void mp_hal_spi_transfer(machine_spi_obj_t *self, size_t len, const uint8_t *src, uint8_t *dest); - -#endif // __MICROPY_INCLUDED_API_MACHINE_H__ diff --git a/shared-bindings/nativeio/AnalogIn.c b/shared-bindings/nativeio/AnalogIn.c new file mode 100644 index 000000000..9c5a601da --- /dev/null +++ b/shared-bindings/nativeio/AnalogIn.c @@ -0,0 +1,106 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/binary.h" +#include "py/mphal.h" +#include "py/nlr.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/nativeio/AnalogIn.h" + +//| .. currentmodule:: nativeio +//| +//| :class:`AnalogIn` -- read analog voltage +//| ============================================ +//| +//| Usage:: +//| +//| import nativeio +//| from board import * +//| +//| with nativeio.AnalogIn(A1) as adc: +//| val = adc.value +//| + +//| .. class:: AnalogIn(pin) +//| +//| Use the AnalogIn on the given pin. +//| +//| :param ~microcontroller.Pin pin: the pin to read from +//| +STATIC mp_obj_t nativeio_analogin_make_new(const mp_obj_type_t *type, + mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + // check number of arguments + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + // 1st argument is the pin + mp_obj_t pin_obj = args[0]; + + nativeio_analogin_obj_t *self = m_new_obj(nativeio_analogin_obj_t); + self->base.type = &nativeio_analogin_type; + const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj); + common_hal_nativeio_analogin_construct(self, pin); + + return (mp_obj_t) self; +} + +//| .. attribute:: value +//| +//| Read the value on the analog pin and return it. The returned value +//| will be between 0 and 65535 inclusive (16-bit). Even if the underlying +//| analog to digital converter (ADC) is lower resolution, the result will +//| be scaled to be 16-bit. +//| +//| :return: the data read +//| :rtype: int +//| +STATIC mp_obj_t nativeio_analogin_obj_get_value(mp_obj_t self_in) { + nativeio_analogin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_nativeio_analogin_get_value(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_analogin_get_value_obj, nativeio_analogin_obj_get_value); + +mp_obj_property_t nativeio_analogin_value_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_analogin_get_value_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t nativeio_analogin_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_value), MP_ROM_PTR(&nativeio_analogin_value_obj)}, +}; + +STATIC MP_DEFINE_CONST_DICT(nativeio_analogin_locals_dict, nativeio_analogin_locals_dict_table); + +const mp_obj_type_t nativeio_analogin_type = { + { &mp_type_type }, + .name = MP_QSTR_AnalogIn, + .make_new = nativeio_analogin_make_new, + .locals_dict = (mp_obj_t)&nativeio_analogin_locals_dict, +}; diff --git a/shared-bindings/nativeio/AnalogIn.h b/shared-bindings/nativeio/AnalogIn.h new file mode 100644 index 000000000..e901aa3b7 --- /dev/null +++ b/shared-bindings/nativeio/AnalogIn.h @@ -0,0 +1,38 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_ANALOGIN_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_ANALOGIN_H__ + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +extern const mp_obj_type_t nativeio_analogin_type; + +void common_hal_nativeio_analogin_construct(nativeio_analogin_obj_t* self, const mcu_pin_obj_t *pin); +uint16_t common_hal_nativeio_analogin_get_value(nativeio_analogin_obj_t *self); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_ANALOGIN_H__ diff --git a/shared-bindings/nativeio/AnalogOut.c b/shared-bindings/nativeio/AnalogOut.c new file mode 100644 index 000000000..7de336a6a --- /dev/null +++ b/shared-bindings/nativeio/AnalogOut.c @@ -0,0 +1,121 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/nativeio/AnalogOut.h" + +//| .. currentmodule:: nativeio +//| +//| :class:`AnalogOut` -- output analog voltage +//| ============================================ +//| +//| The AnalogOut is used to output analog values (a specific voltage). +//| +//| Example usage:: +//| +//| import nativeio +//| from microcontroller import pin +//| +//| with nativeio.AnalogOut(pin.PA02) as dac: # output on pin PA02 +//| dac.value = 32768 # makes PA02 1.65V +//| + +//| .. class:: AnalogOut(pin) +//| +//| Use the AnalogOut on the given pin. +//| +//| :param ~microcontroller.Pin pin: the pin to output to +//| +STATIC mp_obj_t nativeio_analogout_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + nativeio_analogout_obj_t *self = m_new_obj(nativeio_analogout_obj_t); + self->base.type = &nativeio_analogout_type; + + const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(args[0]); + + common_hal_nativeio_analogout_construct(self, pin); + + return self; +} + +//| .. method:: deinit() +//| +//| Turn off the AnalogOut and release the pin for other use. +//| +STATIC mp_obj_t nativeio_analogout_deinit(mp_obj_t self_in) { + nativeio_analogout_obj_t *self = self_in; + + common_hal_nativeio_analogout_deinit(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(nativeio_analogout_deinit_obj, nativeio_analogout_deinit); + +//| .. attribute:: value +//| +//| The value on the analog pin. The value must be between 0 and 65535 +//| inclusive (16-bit). Even if the underlying digital to analog converter +//| is lower resolution, the input must be scaled to be 16-bit. +//| +//| :return: the last value written +//| :rtype: int +//| +STATIC mp_obj_t nativeio_analogout_obj_set_value(mp_obj_t self_in, mp_obj_t value) { + nativeio_analogout_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_nativeio_analogout_set_value(self, mp_obj_get_int(value)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_analogout_set_value_obj, nativeio_analogout_obj_set_value); + +mp_obj_property_t nativeio_analogout_value_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&nativeio_analogout_set_value_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t nativeio_analogout_locals_dict_table[] = { + // instance methods + { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&nativeio_analogout_deinit_obj }, + + // Properties + { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&nativeio_analogout_value_obj }, +}; + +STATIC MP_DEFINE_CONST_DICT(nativeio_analogout_locals_dict, nativeio_analogout_locals_dict_table); + +const mp_obj_type_t nativeio_analogout_type = { + { &mp_type_type }, + .name = MP_QSTR_AnalogOut, + .make_new = nativeio_analogout_make_new, + .locals_dict = (mp_obj_t)&nativeio_analogout_locals_dict, +}; diff --git a/shared-bindings/nativeio/AnalogOut.h b/shared-bindings/nativeio/AnalogOut.h new file mode 100644 index 000000000..195e4c313 --- /dev/null +++ b/shared-bindings/nativeio/AnalogOut.h @@ -0,0 +1,39 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_ANALOGOUT_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_ANALOGOUT_H__ + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +extern const mp_obj_type_t nativeio_analogout_type; + +void common_hal_nativeio_analogout_construct(nativeio_analogout_obj_t* self, const mcu_pin_obj_t *pin); +void common_hal_nativeio_analogout_deinit(nativeio_analogout_obj_t *self); +void common_hal_nativeio_analogout_set_value(nativeio_analogout_obj_t *self, uint16_t value); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_ANALOGOUT_H__ diff --git a/shared-bindings/nativeio/DigitalInOut.c b/shared-bindings/nativeio/DigitalInOut.c new file mode 100644 index 000000000..ce1e12986 --- /dev/null +++ b/shared-bindings/nativeio/DigitalInOut.c @@ -0,0 +1,445 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "py/nlr.h" +#include "py/objtype.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/mphal.h" + +#include "shared-bindings/nativeio/DigitalInOut.h" + +//| .. currentmodule:: nativeio +//| +//| :class:`DigitalInOut` -- digital input and output +//| ========================================================= +//| +//| A DigitalInOut is used to digitally control I/O pins. For analog control of +//| a pin, see the :py:class:`~nativeio.AnalogIn` and +//| :py:class:`~nativeio.AnalogOut` classes. +//| + +//| .. class:: DigitalInOut(pin) +//| +//| Create a new DigitalInOut object associated with the pin. Defaults to input +//| with no pull. Use :py:meth:`switch_to_input` and +//| :py:meth:`switch_to_output` to change the direction. +//| +//| :param ~microcontroller.Pin pin: The pin to control +//| +STATIC mp_obj_t nativeio_digitalinout_make_new(const mp_obj_type_t *type, + mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + nativeio_digitalinout_obj_t *self = m_new_obj(nativeio_digitalinout_obj_t); + self->base.type = &nativeio_digitalinout_type; + + mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(args[0]); + common_hal_nativeio_digitalinout_construct(self, pin); + + return (mp_obj_t)self; +} + +//| .. method:: deinit() +//| +//| Turn off the DigitalInOut and release the pin for other use. +//| +STATIC mp_obj_t nativeio_digitalinout_obj_deinit(mp_obj_t self_in) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_nativeio_digitalinout_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout_deinit_obj, nativeio_digitalinout_obj_deinit); + +//| .. method:: __enter__() +//| +//| No-op used by Context Managers. +//| +STATIC mp_obj_t nativeio_digitalinout_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout___enter___obj, nativeio_digitalinout_obj___enter__); + +//| .. method:: __exit__() +//| +//| Automatically deinitializes the hardware when exiting a context. +//| +STATIC mp_obj_t nativeio_digitalinout_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_nativeio_digitalinout_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nativeio_digitalinout_obj___exit___obj, 4, 4, nativeio_digitalinout_obj___exit__); + +//| +//| .. method:: switch_to_output(value=False, drive_mode=DriveMode.push_pull) +//| +//| Switch to writing out digital values. +//| +//| :param bool value: default value to set upon switching +//| :param DriveMode push_pull: drive mode for the output +//| +typedef struct { + mp_obj_base_t base; +} nativeio_digitalinout_drive_mode_obj_t; +extern const nativeio_digitalinout_drive_mode_obj_t nativeio_digitalinout_drive_mode_push_pull_obj; +extern const nativeio_digitalinout_drive_mode_obj_t nativeio_digitalinout_drive_mode_open_drain_obj; + +STATIC mp_obj_t nativeio_digitalinout_switch_to_output(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_value, ARG_drive_mode }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_drive_mode, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = &nativeio_digitalinout_drive_mode_push_pull_obj} }, + }; + nativeio_digitalinout_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); + + enum digitalinout_drive_mode_t drive_mode = DRIVE_MODE_PUSH_PULL; + if (args[ARG_drive_mode].u_rom_obj == &nativeio_digitalinout_drive_mode_open_drain_obj) { + drive_mode = DRIVE_MODE_OPEN_DRAIN; + } + // do the transfer + common_hal_nativeio_digitalinout_switch_to_output(self, args[ARG_value].u_bool, drive_mode); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(nativeio_digitalinout_switch_to_output_obj, 1, nativeio_digitalinout_switch_to_output); + +//| .. method:: switch_to_input(pull=None) +//| +//| Switch to read in digital values. +//| +//| :param Pull pull: pull configuration for the input +//| +typedef struct { + mp_obj_base_t base; +} nativeio_digitalinout_pull_obj_t; +extern const nativeio_digitalinout_pull_obj_t nativeio_digitalinout_pull_up_obj; +extern const nativeio_digitalinout_pull_obj_t nativeio_digitalinout_pull_down_obj; + +STATIC mp_obj_t nativeio_digitalinout_switch_to_input(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_pull }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = mp_const_none} }, + }; + nativeio_digitalinout_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); + + enum digitalinout_pull_t pull = PULL_NONE; + if (args[ARG_pull].u_rom_obj == &nativeio_digitalinout_pull_up_obj) { + pull = PULL_UP; + }else if (args[ARG_pull].u_rom_obj == &nativeio_digitalinout_pull_down_obj) { + pull = PULL_DOWN; + } + // do the transfer + common_hal_nativeio_digitalinout_switch_to_input(self, pull); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(nativeio_digitalinout_switch_to_input_obj, 1, nativeio_digitalinout_switch_to_input); + +//| .. attribute:: direction +//| +//| Get the direction of the pin. +//| +//| :raises AttributeError: when set. Use :py:meth:`switch_to_input` and :py:meth:`switch_to_output` to change the direction. +//| +typedef struct { + mp_obj_base_t base; +} nativeio_digitalinout_direction_obj_t; +extern const nativeio_digitalinout_direction_obj_t nativeio_digitalinout_direction_in_obj; +extern const nativeio_digitalinout_direction_obj_t nativeio_digitalinout_direction_out_obj; + +STATIC mp_obj_t nativeio_digitalinout_obj_get_direction(mp_obj_t self_in) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + enum digitalinout_direction_t direction = common_hal_nativeio_digitalinout_get_direction(self); + if (direction == DIRECTION_IN) { + return (mp_obj_t)&nativeio_digitalinout_direction_in_obj; + } + return (mp_obj_t)&nativeio_digitalinout_direction_out_obj; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout_get_direction_obj, nativeio_digitalinout_obj_get_direction); + +mp_obj_property_t nativeio_digitalinout_direction_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_digitalinout_get_direction_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. attribute:: value +//| +//| Get or set the digital logic level of the pin. +//| +STATIC mp_obj_t nativeio_digitalinout_obj_get_value(mp_obj_t self_in) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + bool value = common_hal_nativeio_digitalinout_get_value(self); + return mp_obj_new_bool(value); +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout_get_value_obj, nativeio_digitalinout_obj_get_value); + +STATIC mp_obj_t nativeio_digitalinout_obj_set_value(mp_obj_t self_in, mp_obj_t value) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (common_hal_nativeio_digitalinout_get_direction(self) == DIRECTION_IN) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Cannot set value when direction is input.")); + return mp_const_none; + } + common_hal_nativeio_digitalinout_set_value(self, mp_obj_is_true(value)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_digitalinout_set_value_obj, nativeio_digitalinout_obj_set_value); + +mp_obj_property_t nativeio_digitalinout_value_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_digitalinout_get_value_obj, + (mp_obj_t)&nativeio_digitalinout_set_value_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. attribute:: drive_mode +//| +//| Get or set the pin drive mode. +//| +STATIC mp_obj_t nativeio_digitalinout_obj_get_drive_mode(mp_obj_t self_in) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (common_hal_nativeio_digitalinout_get_direction(self) == DIRECTION_IN) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Drive mode not used when direction is input.")); + return mp_const_none; + } + enum digitalinout_drive_mode_t drive_mode = common_hal_nativeio_digitalinout_get_drive_mode(self); + if (drive_mode == DRIVE_MODE_PUSH_PULL) { + return (mp_obj_t)&nativeio_digitalinout_drive_mode_push_pull_obj; + } + return (mp_obj_t)&nativeio_digitalinout_drive_mode_open_drain_obj; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout_get_drive_mode_obj, nativeio_digitalinout_obj_get_drive_mode); + +STATIC mp_obj_t nativeio_digitalinout_obj_set_drive_mode(mp_obj_t self_in, mp_obj_t drive_mode) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (common_hal_nativeio_digitalinout_get_direction(self) == DIRECTION_IN) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Drive mode not used when direction is input.")); + return mp_const_none; + } + enum digitalinout_drive_mode_t c_drive_mode = DRIVE_MODE_PUSH_PULL; + if (drive_mode == &nativeio_digitalinout_drive_mode_open_drain_obj) { + c_drive_mode = DRIVE_MODE_OPEN_DRAIN; + } + common_hal_nativeio_digitalinout_set_drive_mode(self, c_drive_mode); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_digitalinout_set_drive_mode_obj, nativeio_digitalinout_obj_set_drive_mode); + +mp_obj_property_t nativeio_digitalinout_drive_mode_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_digitalinout_get_drive_mode_obj, + (mp_obj_t)&nativeio_digitalinout_set_drive_mode_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. attribute:: pull +//| +//| Get or set the pin pull. +//| +//| :raises AttributeError: if the direction is `out`. +//| +STATIC mp_obj_t nativeio_digitalinout_obj_get_pull(mp_obj_t self_in) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (common_hal_nativeio_digitalinout_get_direction(self) == DIRECTION_OUT) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Pull not used when direction is output.")); + return mp_const_none; + } + enum digitalinout_pull_t pull = common_hal_nativeio_digitalinout_get_pull(self); + if (pull == PULL_UP) { + return (mp_obj_t)&nativeio_digitalinout_pull_up_obj; + } else if (pull == PULL_DOWN) { + return (mp_obj_t)&nativeio_digitalinout_pull_down_obj; + } + return (mp_obj_t)&mp_const_none_obj; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout_get_pull_obj, nativeio_digitalinout_obj_get_pull); + +STATIC mp_obj_t nativeio_digitalinout_obj_set_pull(mp_obj_t self_in, mp_obj_t pull) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (common_hal_nativeio_digitalinout_get_direction(self) == DIRECTION_OUT) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Pull not used when direction is output.")); + return mp_const_none; + } + common_hal_nativeio_digitalinout_set_pull(self, (enum digitalinout_pull_t) MP_OBJ_SMALL_INT_VALUE(pull)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_digitalinout_set_pull_obj, nativeio_digitalinout_obj_set_pull); + +mp_obj_property_t nativeio_digitalinout_pull_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_digitalinout_get_pull_obj, + (mp_obj_t)&nativeio_digitalinout_set_pull_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. class:: microcontroller.DigitalInOut.Direction +//| +//| Enum-like class to define which direction the digital values are +//| going. +//| +//| .. data:: in +//| +//| Read digital data in +//| +//| .. data:: out +//| +//| Write digital data out +//| +const mp_obj_type_t nativeio_digitalinout_direction_type; + +const nativeio_digitalinout_direction_obj_t nativeio_digitalinout_direction_in_obj = { + { &nativeio_digitalinout_direction_type }, +}; + +const nativeio_digitalinout_direction_obj_t nativeio_digitalinout_direction_out_obj = { + { &nativeio_digitalinout_direction_type }, +}; + +STATIC const mp_rom_map_elem_t nativeio_digitalinout_direction_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_in), MP_ROM_PTR(&nativeio_digitalinout_direction_in_obj) }, + { MP_ROM_QSTR(MP_QSTR_out), MP_ROM_PTR(&nativeio_digitalinout_direction_out_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(nativeio_digitalinout_direction_locals_dict, nativeio_digitalinout_direction_locals_dict_table); + +const mp_obj_type_t nativeio_digitalinout_direction_type = { + { &mp_type_type }, + .name = MP_QSTR_Direction, + .locals_dict = (mp_obj_t)&nativeio_digitalinout_direction_locals_dict, +}; + +//| .. class:: nativeio.DigitalInOut.DriveMode +//| +//| Enum-like class to define the drive mode used when outputting +//| digital values. +//| +//| .. data:: push_pull +//| +//| Output both high and low digital values +//| +//| .. data:: open_drain +//| +//| Output low digital values but go into high z for digital high. This is +//| useful for i2c and other protocols that share a digital line. +//| +const mp_obj_type_t nativeio_digitalinout_drive_mode_type; + +const nativeio_digitalinout_drive_mode_obj_t nativeio_digitalinout_drive_mode_push_pull_obj = { + { &nativeio_digitalinout_drive_mode_type }, +}; + +const nativeio_digitalinout_drive_mode_obj_t nativeio_digitalinout_drive_mode_open_drain_obj = { + { &nativeio_digitalinout_drive_mode_type }, +}; + +STATIC const mp_rom_map_elem_t nativeio_digitalinout_drive_mode_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_push_pull), MP_ROM_PTR(&nativeio_digitalinout_drive_mode_push_pull_obj) }, + { MP_ROM_QSTR(MP_QSTR_open_drain), MP_ROM_PTR(&nativeio_digitalinout_drive_mode_open_drain_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(nativeio_digitalinout_drive_mode_locals_dict, nativeio_digitalinout_drive_mode_locals_dict_table); + +const mp_obj_type_t nativeio_digitalinout_drive_mode_type = { + { &mp_type_type }, + .name = MP_QSTR_DriveMode, + .locals_dict = (mp_obj_t)&nativeio_digitalinout_drive_mode_locals_dict, +}; + +//| .. class:: nativeio.DigitalInOut.Pull +//| +//| Enum-like class to define the pull value, if any, used while reading +//| digital values in. +//| +//| .. data:: up +//| +//| When the input line isn't being driven the pull up can pull the state +//| of the line high so it reads as true. +//| +//| .. data:: down +//| +//| When the input line isn't being driven the pull down can pull the +//| state of the line low so it reads as false. +//| +const mp_obj_type_t nativeio_digitalinout_pull_type; + +const nativeio_digitalinout_pull_obj_t nativeio_digitalinout_pull_up_obj = { + { &nativeio_digitalinout_pull_type }, +}; + +const nativeio_digitalinout_pull_obj_t nativeio_digitalinout_pull_down_obj = { + { &nativeio_digitalinout_pull_type }, +}; + +STATIC const mp_rom_map_elem_t nativeio_digitalinout_pull_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_up), MP_ROM_PTR(&nativeio_digitalinout_pull_up_obj) }, + { MP_ROM_QSTR(MP_QSTR_down), MP_ROM_PTR(&nativeio_digitalinout_pull_down_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(nativeio_digitalinout_pull_locals_dict, nativeio_digitalinout_pull_locals_dict_table); + +const mp_obj_type_t nativeio_digitalinout_pull_type = { + { &mp_type_type }, + .name = MP_QSTR_Pull, + .locals_dict = (mp_obj_t)&nativeio_digitalinout_pull_locals_dict, +}; + +STATIC const mp_rom_map_elem_t nativeio_digitalinout_locals_dict_table[] = { + // instance methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&nativeio_digitalinout_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&nativeio_digitalinout___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&nativeio_digitalinout_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_switch_to_output), MP_ROM_PTR(&nativeio_digitalinout_switch_to_output_obj) }, + { MP_ROM_QSTR(MP_QSTR_switch_to_input), MP_ROM_PTR(&nativeio_digitalinout_switch_to_input_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_direction), MP_ROM_PTR(&nativeio_digitalinout_direction_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&nativeio_digitalinout_value_obj) }, + { MP_ROM_QSTR(MP_QSTR_drive_mode), MP_ROM_PTR(&nativeio_digitalinout_drive_mode_obj) }, + { MP_ROM_QSTR(MP_QSTR_pull), MP_ROM_PTR(&nativeio_digitalinout_pull_obj) }, + + // Nested Enum-like Classes. + { MP_ROM_QSTR(MP_QSTR_Direction), MP_ROM_PTR(&nativeio_digitalinout_direction_type) }, + { MP_ROM_QSTR(MP_QSTR_DriveMode), MP_ROM_PTR(&nativeio_digitalinout_drive_mode_type) }, + { MP_ROM_QSTR(MP_QSTR_Pull), MP_ROM_PTR(&nativeio_digitalinout_pull_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(nativeio_digitalinout_locals_dict, nativeio_digitalinout_locals_dict_table); + +const mp_obj_type_t nativeio_digitalinout_type = { + { &mp_type_type }, + .name = MP_QSTR_DigitalInOut, + .make_new = nativeio_digitalinout_make_new, + .locals_dict = (mp_obj_t)&nativeio_digitalinout_locals_dict, +}; diff --git a/shared-bindings/nativeio/DigitalInOut.h b/shared-bindings/nativeio/DigitalInOut.h new file mode 100644 index 000000000..b712a811c --- /dev/null +++ b/shared-bindings/nativeio/DigitalInOut.h @@ -0,0 +1,68 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_DIGITALINOUT_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_DIGITALINOUT_H__ + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +extern const mp_obj_type_t nativeio_digitalinout_type; + +enum digitalinout_direction_t { + DIRECTION_IN, + DIRECTION_OUT +}; + +enum digitalinout_pull_t { + PULL_NONE, + PULL_UP, + PULL_DOWN +}; + +enum digitalinout_drive_mode_t { + DRIVE_MODE_PUSH_PULL, + DRIVE_MODE_OPEN_DRAIN +}; + +typedef enum { + DIGITALINOUT_OK, + DIGITALINOUT_PIN_BUSY +} digitalinout_result_t; + +digitalinout_result_t common_hal_nativeio_digitalinout_construct(nativeio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin); +void common_hal_nativeio_digitalinout_deinit(nativeio_digitalinout_obj_t* self); +void common_hal_nativeio_digitalinout_switch_to_input(nativeio_digitalinout_obj_t* self, enum digitalinout_pull_t pull); +void common_hal_nativeio_digitalinout_switch_to_output(nativeio_digitalinout_obj_t* self, bool value, enum digitalinout_drive_mode_t drive_mode); +enum digitalinout_direction_t common_hal_nativeio_digitalinout_get_direction(nativeio_digitalinout_obj_t* self); +void common_hal_nativeio_digitalinout_set_value(nativeio_digitalinout_obj_t* self, bool value); +bool common_hal_nativeio_digitalinout_get_value(nativeio_digitalinout_obj_t* self); +void common_hal_nativeio_digitalinout_set_drive_mode(nativeio_digitalinout_obj_t* self, enum digitalinout_drive_mode_t drive_mode); +enum digitalinout_drive_mode_t common_hal_nativeio_digitalinout_get_drive_mode(nativeio_digitalinout_obj_t* self); +void common_hal_nativeio_digitalinout_set_pull(nativeio_digitalinout_obj_t* self, enum digitalinout_pull_t pull); +enum digitalinout_pull_t common_hal_nativeio_digitalinout_get_pull(nativeio_digitalinout_obj_t* self); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_DIGITALINOUT_H__ diff --git a/shared-bindings/nativeio/I2C.c b/shared-bindings/nativeio/I2C.c new file mode 100644 index 000000000..325d7c56b --- /dev/null +++ b/shared-bindings/nativeio/I2C.c @@ -0,0 +1,180 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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 +// nativeio.I2C class. + +#include "shared-bindings/nativeio/I2C.h" + +#include "py/runtime.h" +//| .. currentmodule:: nativeio +//| +//| :class:`I2C` --- Two wire serial protocol +//| ------------------------------------------ +//| +//| .. class:: I2C(scl, sda, \*, freq=400000) +//| +//| I2C is a two-wire protocol for communicating between devices. At the +//| physical level it consists of 2 wires: SCL and SDA, the clock and data +//| lines respectively. +//| +//| :param ~microcontroller.Pin scl: The clock pin +//| :param ~microcontroller.Pin sda: The data pin +//| :param int freq: The clock frequency +//| +STATIC mp_obj_t nativeio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + nativeio_i2c_obj_t *self = m_new_obj(nativeio_i2c_obj_t); + self->base.type = &nativeio_i2c_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_scl, ARG_sda, ARG_freq }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + }; + 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); + const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj); + const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj); + common_hal_nativeio_i2c_construct(self, scl, sda, args[ARG_freq].u_int); + return (mp_obj_t)self; +} + +//| .. method:: I2C.deinit() +//| +//| Releases control of the underlying hardware so other classes can use it. +//| +STATIC mp_obj_t nativeio_i2c_obj_deinit(mp_obj_t self_in) { + nativeio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_nativeio_i2c_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_i2c_deinit_obj, nativeio_i2c_obj_deinit); + +//| .. method:: I2C.__enter__() +//| +//| No-op used in Context Managers. +//| +STATIC mp_obj_t nativeio_i2c_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_i2c___enter___obj, nativeio_i2c_obj___enter__); + +//| .. method:: I2C.__exit__() +//| +//| Automatically deinitializes the hardware on context exit. +//| +STATIC mp_obj_t nativeio_i2c_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_nativeio_i2c_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nativeio_i2c_obj___exit___obj, 4, 4, nativeio_i2c_obj___exit__); + +//| .. method:: I2C.scan() +//| +//| Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of +//| those that respond. A device responds if it pulls the SDA line low after +//| its address (including a read bit) is sent on the bus. +//| +STATIC mp_obj_t nativeio_i2c_scan(mp_obj_t self_in) { + nativeio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_t list = mp_obj_new_list(0, NULL); + // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved + for (int addr = 0x08; addr < 0x78; ++addr) { + bool success = common_hal_nativeio_i2c_probe(self, addr); + if (success) { + mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); + } + } + return list; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_i2c_scan_obj, nativeio_i2c_scan); + +//| .. method:: I2C.readfrom_into(address, buffer) +//| +//| Read into ``buffer`` from the slave specified by ``address``. +//| The number of bytes read will be the length of `buf`. +//| +STATIC mp_obj_t nativeio_i2c_readfrom_into(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) { + nativeio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); + common_hal_nativeio_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)bufinfo.buf, bufinfo.len); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_3(nativeio_i2c_readfrom_into_obj, nativeio_i2c_readfrom_into); + +//| .. method:: I2C.writeto(address, buffer, stop=True) +//| +//| Write the bytes from ``buffer`` to the slave specified by ``address``. +//| Transmits a stop bit if ``stop`` is set. +//| +STATIC mp_obj_t nativeio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_address, ARG_buffer, ARG_stop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_stop, MP_ARG_BOOL, {.u_bool = true} }, + }; + nativeio_i2c_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); + + // get the buffer to write the data from + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); + + // do the transfer + bool ok = common_hal_nativeio_i2c_write(self, args[ARG_address].u_int, + bufinfo.buf, bufinfo.len, args[ARG_stop].u_bool); + if (!ok) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(nativeio_i2c_writeto_obj, 1, nativeio_i2c_writeto); + +STATIC const mp_rom_map_elem_t nativeio_i2c_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&nativeio_i2c_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&nativeio_i2c___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&nativeio_i2c_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&nativeio_i2c_scan_obj) }, + + { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&nativeio_i2c_readfrom_into_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&nativeio_i2c_writeto_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(nativeio_i2c_locals_dict, nativeio_i2c_locals_dict_table); + +const mp_obj_type_t nativeio_i2c_type = { + { &mp_type_type }, + .name = MP_QSTR_I2C, + .make_new = nativeio_i2c_make_new, + .locals_dict = (mp_obj_dict_t*)&nativeio_i2c_locals_dict, +}; diff --git a/shared-bindings/nativeio/I2C.h b/shared-bindings/nativeio/I2C.h new file mode 100644 index 000000000..9f90de536 --- /dev/null +++ b/shared-bindings/nativeio/I2C.h @@ -0,0 +1,64 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_NATIVEIO_I2C_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_I2C_H__ + +#include "py/obj.h" + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t nativeio_i2c_type; + +// Initializes the hardware peripheral. +extern void common_hal_nativeio_i2c_construct(nativeio_i2c_obj_t *self, + const mcu_pin_obj_t * scl, + const mcu_pin_obj_t * sda, + uint32_t freq); + +extern void common_hal_nativeio_i2c_deinit(nativeio_i2c_obj_t *self); + +// Probe the bus to see if a device acknowledges the given address. +extern bool common_hal_nativeio_i2c_probe(nativeio_i2c_obj_t *self, uint8_t addr); + +extern bool common_hal_nativeio_i2c_write(nativeio_i2c_obj_t *self, uint16_t address, + const uint8_t * data, size_t len, + bool stop); + +// Reads memory of the i2c device picking up where it left off. +extern bool common_hal_nativeio_i2c_read(nativeio_i2c_obj_t *self, uint16_t address, + uint8_t * data, size_t len); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_I2C_H__ diff --git a/shared-bindings/nativeio/PWMOut.c b/shared-bindings/nativeio/PWMOut.c new file mode 100644 index 000000000..13897ad1d --- /dev/null +++ b/shared-bindings/nativeio/PWMOut.c @@ -0,0 +1,151 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/nativeio/PWMOut.h" + +//| .. currentmodule:: nativeio +//| +//| :class:`PWMOut` -- Output a Pulse Width Modulated signal +//| ======================================================== +//| +//| PWMOut can be used to output a PWM signal on a given pin. +//| +//| .. class:: PWMOut(pin, duty=0) +//| +//| Create a PWM object associated with the given pin. This allows you to +//| write PWM signals out on the given pin. Frequency is currently fixed at +//| ~735Hz like Arduino. +//| +//| :param ~microcontroller.Pin pin: The pin to output to +//| +STATIC mp_obj_t nativeio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + mp_obj_t pin_obj = args[0]; + const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj); + + // create PWM object from the given pin + nativeio_pwmout_obj_t *self = m_new_obj(nativeio_pwmout_obj_t); + self->base.type = &nativeio_pwmout_type; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + enum { ARG_duty }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_duty, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, args + 1, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, parsed_args); + uint8_t duty = parsed_args[ARG_duty].u_int; + + common_hal_nativeio_pwmout_construct(self, pin, duty); + + return MP_OBJ_FROM_PTR(self); +} + +//| .. method:: deinit() +//| +//| Deinitialises the PWMOut and releases any hardware resources for reuse. +//| +STATIC mp_obj_t nativeio_pwmout_deinit(mp_obj_t self_in) { + nativeio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_nativeio_pwmout_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(nativeio_pwmout_deinit_obj, nativeio_pwmout_deinit); + +//| .. method:: __enter__() +//| +//| No-op used by Context Managers. +//| +STATIC mp_obj_t nativeio_pwmout_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_pwmout___enter___obj, nativeio_pwmout_obj___enter__); + +//| .. method:: __exit__() +//| +//| Automatically deinitializes the hardware when exiting a context. +//| +STATIC mp_obj_t nativeio_pwmout_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_nativeio_pwmout_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nativeio_pwmout_obj___exit___obj, 4, 4, nativeio_pwmout_obj___exit__); + +//| .. attribute:: duty_cycle +//| +//| 8 bit value that dictates how much of one cycle is high (1) versus low +//| (0). 255 will always be high, 0 will always be low and 127 will be half +//| high and then half low. +STATIC mp_obj_t nativeio_pwmout_obj_get_duty_cycle(mp_obj_t self_in) { + nativeio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_nativeio_pwmout_get_duty_cycle(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_pwmout_get_duty_cycle_obj, nativeio_pwmout_obj_get_duty_cycle); + +STATIC mp_obj_t nativeio_pwmout_obj_set_duty_cycle(mp_obj_t self_in, mp_obj_t duty_cycle) { + nativeio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_int_t duty = mp_obj_get_int(duty_cycle); + if (duty < 0 || duty > 255) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "PWM duty must be between 0 and 255 (8 bit resolution), not %d", + duty)); + } + common_hal_nativeio_pwmout_set_duty_cycle(self, duty); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_pwmout_set_duty_cycle_obj, nativeio_pwmout_obj_set_duty_cycle); + +mp_obj_property_t nativeio_pwmout_duty_cycle_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_pwmout_get_duty_cycle_obj, + (mp_obj_t)&nativeio_pwmout_set_duty_cycle_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t nativeio_pwmout_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&nativeio_pwmout_deinit_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_duty_cycle), MP_ROM_PTR(&nativeio_pwmout_duty_cycle_obj) }, + // TODO(tannewt): Add frequency. + // TODO(tannewt): Add enabled to determine whether the signal is output + // without giving up the resources. Useful for IR output. +}; +STATIC MP_DEFINE_CONST_DICT(nativeio_pwmout_locals_dict, nativeio_pwmout_locals_dict_table); + +const mp_obj_type_t nativeio_pwmout_type = { + { &mp_type_type }, + .name = MP_QSTR_PWMOut, + .make_new = nativeio_pwmout_make_new, + .locals_dict = (mp_obj_dict_t*)&nativeio_pwmout_locals_dict, +}; diff --git a/shared-bindings/nativeio/PWMOut.h b/shared-bindings/nativeio/PWMOut.h new file mode 100644 index 000000000..0be553315 --- /dev/null +++ b/shared-bindings/nativeio/PWMOut.h @@ -0,0 +1,40 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_PWMOUT_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_PWMOUT_H__ + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +extern const mp_obj_type_t nativeio_pwmout_type; + +extern void common_hal_nativeio_pwmout_construct(nativeio_pwmout_obj_t* self, const mcu_pin_obj_t* pin, uint16_t duty); +extern void common_hal_nativeio_pwmout_deinit(nativeio_pwmout_obj_t* self); +extern void common_hal_nativeio_pwmout_set_duty_cycle(nativeio_pwmout_obj_t* self, uint16_t duty); +extern uint16_t common_hal_nativeio_pwmout_get_duty_cycle(nativeio_pwmout_obj_t* self); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_PWMOUT_H__ diff --git a/shared-bindings/nativeio/SPI.c b/shared-bindings/nativeio/SPI.c new file mode 100644 index 000000000..f17814ffa --- /dev/null +++ b/shared-bindings/nativeio/SPI.c @@ -0,0 +1,167 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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 +// nativeio.SPI class. + +#include + +#include "shared-bindings/nativeio/SPI.h" + +#include "py/runtime.h" + +//| .. currentmodule:: nativeio +//| +//| :class:`SPI` -- a 3-4 wire serial protocol +//| ----------------------------------------------- +//| +//| SPI is a serial protocol that has exclusive pins for data in and out of the +//| master. It is typically faster than :py:class:`~nativeio.I2C` because a +//| separate pin is used to control the active slave rather than a transitted +//| address. This class only manages three of the four SPI lines: `!clock`, +//| `!MOSI`, `!MISO`. Its up to the client to manage the appropriate slave +//| select line. (This is common because multiple slaves can share the `!clock`, +//| `!MOSI` and `!MISO` lines and therefore the hardware.) +//| +//| .. class:: SPI(clock, MOSI, MISO, baudrate=1000000) +//| +//| Construct an SPI object on the given pins. +//| +//| :param ~microcontroller.Pin clock: the pin to use for the clock. +//| :param ~microcontroller.Pin MOSI: the Master Out Slave In pin. +//| :param ~microcontroller.Pin MISO: the Master In Slave Out pin. +//| :param int baudrate: is the SCK clock rate. +//| + +// TODO(tannewt): Support LSB SPI. +// TODO(tannewt): Support phase, polarity and bit order. +STATIC mp_obj_t nativeio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + nativeio_spi_obj_t *self = m_new_obj(nativeio_spi_obj_t); + self->base.type = &nativeio_spi_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_MOSI, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_MISO, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { 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 = 400000} }, + { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, + }; + 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); + const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(args[ARG_clock].u_obj); + const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(args[ARG_MOSI].u_obj); + const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(args[ARG_MISO].u_obj); + common_hal_nativeio_spi_construct(self, clock, mosi, miso, args[ARG_baudrate].u_int); + return (mp_obj_t)self; +} + +//| .. method:: SPI.deinit() +//| +//| Turn off the SPI bus. +//| +STATIC mp_obj_t nativeio_spi_obj_deinit(mp_obj_t self_in) { + nativeio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_nativeio_spi_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_spi_deinit_obj, nativeio_spi_obj_deinit); + +//| .. method:: SPI.__enter__() +//| +//| No-op used by Context Managers. +//| +STATIC mp_obj_t nativeio_spi_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_spi___enter___obj, nativeio_spi_obj___enter__); + +//| .. method:: SPI.__exit__() +//| +//| Automatically deinitializes the hardware when exiting a context. +//| +STATIC mp_obj_t nativeio_spi_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_nativeio_spi_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nativeio_spi_obj___exit___obj, 4, 4, nativeio_spi_obj___exit__); + +//| .. method:: SPI.write(buf) +//| +//| Write the data contained in `!buf`. +//| Returns the number of bytes written. +//| +STATIC mp_obj_t nativeio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) { + mp_buffer_info_t src; + mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); + nativeio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + bool ok = common_hal_nativeio_spi_write(self, src.buf, src.len); + if (!ok) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "SPI bus error")); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_spi_write_obj, nativeio_spi_write); + + +//| .. method:: SPI.readinto(buf) +//| +//| Read into the buffer specified by `!buf` while writing the data +//| specified by `!write`. +//| Return the number of bytes read. +//| +STATIC mp_obj_t nativeio_spi_readinto(size_t n_args, const mp_obj_t *args) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); + bool ok = common_hal_nativeio_spi_read(args[0], bufinfo.buf, bufinfo.len); + if (!ok) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "SPI bus error")); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nativeio_spi_readinto_obj, 2, 2, nativeio_spi_readinto); + +STATIC const mp_rom_map_elem_t nativeio_spi_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&nativeio_spi_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&nativeio_spi___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&nativeio_spi_obj___exit___obj) }, + + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&nativeio_spi_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&nativeio_spi_write_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(nativeio_spi_locals_dict, nativeio_spi_locals_dict_table); + +const mp_obj_type_t nativeio_spi_type = { + { &mp_type_type }, + .name = MP_QSTR_SPI, + .make_new = nativeio_spi_make_new, + .locals_dict = (mp_obj_dict_t*)&nativeio_spi_locals_dict, +}; diff --git a/shared-bindings/nativeio/SPI.h b/shared-bindings/nativeio/SPI.h new file mode 100644 index 000000000..ca1a8c5d4 --- /dev/null +++ b/shared-bindings/nativeio/SPI.h @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_NATIVEIO_SPI_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_SPI_H__ + +#include "py/obj.h" + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t nativeio_spi_type; + +// Construct an underlying SPI object. +extern void common_hal_nativeio_spi_construct(nativeio_spi_obj_t *self, + const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, + const mcu_pin_obj_t * miso, uint32_t baudrate); + +extern void common_hal_nativeio_spi_deinit(nativeio_spi_obj_t *self); + +// Writes out the given data. +extern bool common_hal_nativeio_spi_write(nativeio_spi_obj_t *self, const uint8_t *data, size_t len); + +// Reads in len bytes while outputting zeroes. +extern bool common_hal_nativeio_spi_read(nativeio_spi_obj_t *self, uint8_t *data, size_t len); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_SPI_H__ diff --git a/shared-bindings/nativeio/__init__.c b/shared-bindings/nativeio/__init__.c new file mode 100644 index 000000000..8f9819778 --- /dev/null +++ b/shared-bindings/nativeio/__init__.c @@ -0,0 +1,122 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// nativeio is the HAL for low-level, hardware accelerated classes. It +// is not meant to simplify APIs, its only meant to unify them so that other +// libraries do not require port specific logic. + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/nativeio/__init__.h" +#include "shared-bindings/nativeio/AnalogIn.h" +#include "shared-bindings/nativeio/AnalogOut.h" +#include "shared-bindings/nativeio/DigitalInOut.h" +#include "shared-bindings/nativeio/I2C.h" +#include "shared-bindings/nativeio/PWMOut.h" +#include "shared-bindings/nativeio/SPI.h" +#include "common-hal/nativeio/types.h" +#include "shared-bindings/nativeio/__init__.h" + +#include "py/runtime.h" + +//| :mod:`nativeio` --- Hardware accelerated behavior +//| ================================================= +//| +//| .. module:: nativeio +//| :synopsis: Hardware accelerated behavior +//| :platform: SAMD21 +//| +//| The `nativeio` module contains classes to provide access to IO accelerated +//| by hardware on the onboard microcontroller. The classes are meant to align +//| with commonly hardware accelerated IO and not necessarily match up with +//| microcontroller structure (because it varies). +//| +//| If the microcontroller doesn't not support the behavior in a hardware +//| accelerated fashion it throws a NotImplementedError on construction. Use +//| `bitbangio` module instead which only depends on +//| :py:class:`~nativeio.DigitalInOut` and is shared across hardware ports. +//| +//| Libraries +//| +//| .. toctree:: +//| :maxdepth: 3 +//| +//| AnalogIn +//| AnalogOut +//| DigitalInOut +//| I2C +//| PWMOut +//| SPI +//| +//| All libraries change hardware state and should be deinitialized when they +//| are no longer needed. To do so, either call :py:meth:`!deinit` or use a +//| context manager. +//| +//| For example:: +//| +//| import nativeio +//| from board import * +//| +//| with nativeio.I2C(SCL, SDA) as i2c: +//| i2c.scan() +//| +//| This example will initialize the the device, run +//| :py:meth:`~nativeio.I2C.scan` and then :py:meth:`~nativeio.I2C.deinit` the +//| hardware. +//| +//| Here is blinky:: +//| +//| import nativeio +//| from board import * +//| import time +//| +//| with nativeio.DigitalInOut(D13) as led: +//| led.value = True +//| time.sleep(0.1) +//| led.value = False +//| time.sleep(0.1) +//| + +STATIC const mp_rom_map_elem_t nativeio_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_nativeio) }, + { MP_ROM_QSTR(MP_QSTR_AnalogIn), MP_ROM_PTR(&nativeio_analogin_type) }, + { MP_ROM_QSTR(MP_QSTR_AnalogOut), MP_ROM_PTR(&nativeio_analogout_type) }, + { MP_ROM_QSTR(MP_QSTR_DigitalInOut), MP_ROM_PTR(&nativeio_digitalinout_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&nativeio_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_PWMOut), MP_ROM_PTR(&nativeio_pwmout_type) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&nativeio_spi_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(nativeio_module_globals, nativeio_module_globals_table); + +const mp_obj_module_t nativeio_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&nativeio_module_globals, +}; diff --git a/shared-bindings/nativeio/__init__.h b/shared-bindings/nativeio/__init__.h new file mode 100644 index 000000000..7f4c01e05 --- /dev/null +++ b/shared-bindings/nativeio/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_NATIVEIO___INIT___H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO___INIT___H__ + +#include "py/obj.h" + +// Nothing now. + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO___INIT___H__ diff --git a/shared-bindings/neopixel_write/__init__.c b/shared-bindings/neopixel_write/__init__.c new file mode 100644 index 000000000..73fd803c5 --- /dev/null +++ b/shared-bindings/neopixel_write/__init__.c @@ -0,0 +1,75 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 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 "py/obj.h" +#include "py/mphal.h" +#include "py/runtime.h" + +#include "common-hal/nativeio/types.h" + +#include "shared-bindings/neopixel_write/__init__.h" + +//| :mod:`neopixel_write` --- Low-level neopixel implementation +//| =========================================================== +//| +//| .. module:: neopixel_write +//| :synopsis: Low-level neopixel implementation +//| :platform: SAMD21 +//| +//| The `neopixel_write` module contains a helper method to write out bytes in +//| the neopixel protocol. + +//| .. method:: neopixel_write.neopixel_write(digitalinout, buf, is800KHz) +//| +//| Write buf out on the given DigitalInOut. +//| +//| :param ~nativeio.DigitalInOut gpio: the DigitalInOut to output with +//| :param bytearray buf: The bytes to clock out. No assumption is made about color order +//| :param bool is800KHz: True if the pixels are 800KHz, otherwise 400KHz is assumed. +//| +STATIC mp_obj_t neopixel_write_neopixel_write_(mp_obj_t digitalinout_obj, mp_obj_t buf, mp_obj_t is800k) { + // Convert parameters into expected types. + const nativeio_digitalinout_obj_t *digitalinout = MP_OBJ_TO_PTR(digitalinout_obj); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); + // Call platform's neopixel write function with provided buffer and options. + common_hal_neopixel_write(digitalinout, (uint8_t*)bufinfo.buf, bufinfo.len, + mp_obj_is_true(is800k)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(neopixel_write_neopixel_write_obj, neopixel_write_neopixel_write_); + +STATIC const mp_rom_map_elem_t neopixel_write_module_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&neopixel_write_neopixel_write_obj }, +}; + +STATIC MP_DEFINE_CONST_DICT(neopixel_write_module_globals, neopixel_write_module_globals_table); + +const mp_obj_module_t neopixel_write_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&neopixel_write_module_globals, +}; diff --git a/shared-bindings/neopixel_write/__init__.h b/shared-bindings/neopixel_write/__init__.h new file mode 100644 index 000000000..fdf3c38f6 --- /dev/null +++ b/shared-bindings/neopixel_write/__init__.h @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 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 SAMD_NEOPIXEL_WRITE_H +#define SAMD_NEOPIXEL_WRITE_H + +#include +#include + +#include "common-hal/nativeio/types.h" + +extern void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* gpio, uint8_t *pixels, uint32_t numBytes, bool is800KHz); + +#endif diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c new file mode 100644 index 000000000..cd41884fd --- /dev/null +++ b/shared-bindings/time/__init__.c @@ -0,0 +1,91 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2015 Josef Gajdusek + * Copyright (c) 2016 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 + +//#include "py/nlr.h" +#include "py/obj.h" +//#include "py/gc.h" +//#include "py/runtime.h" +//#include "py/mphal.h" +//#include "py/smallint.h" +#include "shared-bindings/time/__init__.h" + +//| :mod:`time` --- time and timing related functions +//| ======================================================== +//| +//| .. module:: time +//| :synopsis: time and timing related functions +//| :platform: SAMD21 +//| +//| The `time` module is a strict subset of the CPython `time` module. So, code +//| written in MicroPython will work in CPython but not necessarily the other +//| way around. +//| +//| .. method:: monotonic() +//| +//| Returns an always increasing value of time with an unknown reference +//| point. Only use it to compare against other values from `monotonic`. +//| +//| :return: the current monotonic time +//| :rtype: float +//| +STATIC mp_obj_t time_monotonic(void) { + return mp_obj_new_float(common_hal_time_monotonic() / 100.0); +} +MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_obj, time_monotonic); + +//| .. method:: sleep(seconds) +//| +//| Sleep for a given number of seconds. +//| +//| :param float seconds: the time to sleep in fractional seconds +//| +STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { + #if MICROPY_PY_BUILTINS_FLOAT + common_hal_time_delay_ms(1000 * mp_obj_get_float(seconds_o)); + #else + common_hal_time_delay_ms(1000 * mp_obj_get_int(seconds_o)); + #endif + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep); + +STATIC const mp_map_elem_t time_module_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_time) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_monotonic), (mp_obj_t)&time_monotonic_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj }, +}; + +STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); + +const mp_obj_module_t time_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&time_module_globals, +}; diff --git a/shared-bindings/time/__init__.h b/shared-bindings/time/__init__.h new file mode 100644 index 000000000..37bd26a4d --- /dev/null +++ b/shared-bindings/time/__init__.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 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_SHARED_BINDINGS_TIME___INIT___H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_TIME___INIT___H__ + +#include +#include + +extern uint64_t common_hal_time_monotonic(void); +extern void common_hal_time_delay_ms(uint32_t); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_TIME___INIT___H__ -- cgit v1.2.3