summaryrefslogtreecommitdiff
path: root/shared-bindings
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2018-01-02 21:25:41 -0500
committerDan Halbert <halbert@halwitz.org>2018-01-02 21:25:41 -0500
commit065e82015f0d2bd6732c62b7375fcc7af87fa0cf (patch)
treee48fa8caa5675d529d335a2b154e69eba8199cff /shared-bindings
parentce81c8dda9686d3cd78d9c5383b6982c148ac7ec (diff)
merge from 2.2.0 + fix up board defs
Diffstat (limited to 'shared-bindings')
-rw-r--r--shared-bindings/_stage/Layer.c130
-rw-r--r--shared-bindings/_stage/Layer.h34
-rw-r--r--shared-bindings/_stage/Text.c109
-rw-r--r--shared-bindings/_stage/Text.h34
-rw-r--r--shared-bindings/_stage/__init__.c97
-rw-r--r--shared-bindings/_stage/__init__.h32
-rw-r--r--shared-bindings/audiobusio/PDMIn.c53
-rw-r--r--shared-bindings/bitbangio/I2C.c7
-rw-r--r--shared-bindings/bitbangio/SPI.c11
-rw-r--r--shared-bindings/busio/I2C.c8
-rw-r--r--shared-bindings/busio/SPI.c92
-rw-r--r--shared-bindings/busio/SPI.h3
-rw-r--r--shared-bindings/digitalio/DigitalInOut.c14
-rw-r--r--shared-bindings/digitalio/DigitalInOut.h14
-rw-r--r--shared-bindings/digitalio/Direction.h4
-rw-r--r--shared-bindings/digitalio/DriveMode.h4
-rw-r--r--shared-bindings/digitalio/Pull.h4
-rw-r--r--shared-bindings/microcontroller/RunMode.c90
-rw-r--r--shared-bindings/microcontroller/RunMode.h47
-rw-r--r--shared-bindings/microcontroller/__init__.c44
-rw-r--r--shared-bindings/microcontroller/__init__.h5
21 files changed, 790 insertions, 46 deletions
diff --git a/shared-bindings/_stage/Layer.c b/shared-bindings/_stage/Layer.c
new file mode 100644
index 000000000..3e615c497
--- /dev/null
+++ b/shared-bindings/_stage/Layer.c
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Radomir Dopieralski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <py/runtime.h>
+
+#include "__init__.h"
+#include "Layer.h"
+
+//| .. currentmodule:: _stage
+//|
+//| :class:`Layer` -- Keep information about a single layer of graphics
+//| ===================================================================
+//|
+//| .. class:: Layer(width, height, graphic, palette, [grid])
+//|
+//| Keep internal information about a layer of graphics (either a
+//| ``Grid`` or a ``Sprite``) in a format suitable for fast rendering
+//| with the ``render()`` function.
+//|
+//| :param int width: The width of the grid in tiles, or 1 for sprites.
+//| :param int height: The height of the grid in tiles, or 1 for sprites.
+//| :param bytearray graphic: The graphic data of the tiles.
+//| :param bytearray palette: The color palette to be used.
+//| :param bytearray grid: The contents of the grid map.
+//|
+//| This class is intended for internal use in the ``stage`` library and
+//| it shouldn't be used on its own.
+//|
+STATIC mp_obj_t layer_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, 4, 5, false);
+
+ layer_obj_t *self = m_new_obj(layer_obj_t);
+ self->base.type = type;
+
+ self->width = mp_obj_get_int(args[0]);
+ self->height = mp_obj_get_int(args[1]);
+ self->x = 0;
+ self->y = 0;
+ self->frame = 0;
+ self->rotation = false;
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
+ self->graphic = bufinfo.buf;
+ if (bufinfo.len != 2048) {
+ mp_raise_ValueError("graphic must be 2048 bytes long");
+ }
+
+ mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
+ self->palette = bufinfo.buf;
+ if (bufinfo.len != 32) {
+ mp_raise_ValueError("palette must be 32 bytes long");
+ }
+
+ if (n_args > 4) {
+ mp_get_buffer_raise(args[4], &bufinfo, MP_BUFFER_READ);
+ self->map = bufinfo.buf;
+ if (bufinfo.len < (self->width * self->height) / 2) {
+ mp_raise_ValueError("map buffer too small");
+ }
+ } else {
+ self-> map = NULL;
+ }
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: move(x, y)
+//|
+//| Set the offset of the layer to the specified values.
+//|
+STATIC mp_obj_t layer_move(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {
+ layer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ self->x = mp_obj_get_int(x_in);
+ self->y = mp_obj_get_int(y_in);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(layer_move_obj, layer_move);
+
+//| .. method:: frame(frame, rotation)
+//|
+//| Set the animation frame of the sprite, and optionally rotation its
+//| graphic.
+//|
+STATIC mp_obj_t layer_frame(mp_obj_t self_in, mp_obj_t frame_in,
+ mp_obj_t rotation_in) {
+ layer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ self->frame = mp_obj_get_int(frame_in);
+ self->rotation = mp_obj_get_int(rotation_in);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(layer_frame_obj, layer_frame);
+
+
+STATIC const mp_rom_map_elem_t layer_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_move), MP_ROM_PTR(&layer_move_obj) },
+ { MP_ROM_QSTR(MP_QSTR_frame), MP_ROM_PTR(&layer_frame_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(layer_locals_dict, layer_locals_dict_table);
+
+const mp_obj_type_t mp_type_layer = {
+ { &mp_type_type },
+ .name = MP_QSTR_Layer,
+ .make_new = layer_make_new,
+ .locals_dict = (mp_obj_dict_t*)&layer_locals_dict,
+};
diff --git a/shared-bindings/_stage/Layer.h b/shared-bindings/_stage/Layer.h
new file mode 100644
index 000000000..6d15dfb28
--- /dev/null
+++ b/shared-bindings/_stage/Layer.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Radomir Dopieralski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED__STAGE_LAYER_H
+#define MICROPY_INCLUDED__STAGE_LAYER_H
+
+#include "shared-module/_stage/Layer.h"
+
+extern const mp_obj_type_t mp_type_layer;
+
+#endif // MICROPY_INCLUDED__STAGE_LAYER
diff --git a/shared-bindings/_stage/Text.c b/shared-bindings/_stage/Text.c
new file mode 100644
index 000000000..c62d22afe
--- /dev/null
+++ b/shared-bindings/_stage/Text.c
@@ -0,0 +1,109 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Radomir Dopieralski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <py/runtime.h>
+
+#include "__init__.h"
+#include "Text.h"
+
+//| .. currentmodule:: _stage
+//|
+//| :class:`Text` -- Keep information about a single text of text
+//| ==============================================================
+//|
+//| .. class:: Text(width, height, font, palette, chars)
+//|
+//| Keep internal information about a text of text
+//| in a format suitable for fast rendering
+//| with the ``render()`` function.
+//|
+//| :param int width: The width of the grid in tiles, or 1 for sprites.
+//| :param int height: The height of the grid in tiles, or 1 for sprites.
+//| :param bytearray font: The font data of the characters.
+//| :param bytearray palette: The color palette to be used.
+//| :param bytearray chars: The contents of the character grid.
+//|
+//| This class is intended for internal use in the ``stage`` library and
+//| it shouldn't be used on its own.
+//|
+STATIC mp_obj_t text_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, 5, 5, false);
+
+ text_obj_t *self = m_new_obj(text_obj_t);
+ self->base.type = type;
+
+ self->width = mp_obj_get_int(args[0]);
+ self->height = mp_obj_get_int(args[1]);
+ self->x = 0;
+ self->y = 0;
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
+ self->font = bufinfo.buf;
+ if (bufinfo.len != 2048) {
+ mp_raise_ValueError("font must be 2048 bytes long");
+ }
+
+ mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
+ self->palette = bufinfo.buf;
+ if (bufinfo.len != 32) {
+ mp_raise_ValueError("palette must be 32 bytes long");
+ }
+
+ mp_get_buffer_raise(args[4], &bufinfo, MP_BUFFER_READ);
+ self->chars = bufinfo.buf;
+ if (bufinfo.len < self->width * self->height) {
+ mp_raise_ValueError("chars buffer too small");
+ }
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: move(x, y)
+//|
+//| Set the offset of the text to the specified values.
+//|
+STATIC mp_obj_t text_move(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {
+ text_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ self->x = mp_obj_get_int(x_in);
+ self->y = mp_obj_get_int(y_in);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(text_move_obj, text_move);
+
+
+STATIC const mp_rom_map_elem_t text_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_move), MP_ROM_PTR(&text_move_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(text_locals_dict, text_locals_dict_table);
+
+const mp_obj_type_t mp_type_text = {
+ { &mp_type_type },
+ .name = MP_QSTR_Text,
+ .make_new = text_make_new,
+ .locals_dict = (mp_obj_dict_t*)&text_locals_dict,
+};
diff --git a/shared-bindings/_stage/Text.h b/shared-bindings/_stage/Text.h
new file mode 100644
index 000000000..77de62a11
--- /dev/null
+++ b/shared-bindings/_stage/Text.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Radomir Dopieralski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED__STAGE_TEXT_H
+#define MICROPY_INCLUDED__STAGE_TEXT_H
+
+#include "shared-module/_stage/Text.h"
+
+extern const mp_obj_type_t mp_type_text;
+
+#endif // MICROPY_INCLUDED__STAGE_TEXT
diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c
new file mode 100644
index 000000000..16e0b58d9
--- /dev/null
+++ b/shared-bindings/_stage/__init__.c
@@ -0,0 +1,97 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Radomir Dopieralski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "__init__.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
+#include "shared-bindings/busio/SPI.h"
+#include "shared-module/_stage/__init__.h"
+#include "Layer.h"
+#include "Text.h"
+
+//| .. currentmodule:: _stage
+//|
+//| .. function:: render(x0, y0, x1, y1, layers, buffer, spi)
+//|
+//| Render and send to the display a fragment of the screen.
+//|
+//| :param int x0: Left edge of the fragment.
+//| :param int y0: Top edge of the fragment.
+//| :param int x1: Right edge of the fragment.
+//| :param int y1: Bottom edge of the fragment.
+//| :param list layers: A list of the `Layer` objects.
+//| :param bytearray buffer: A buffer to use for rendering.
+//| :param SPI spi: The SPI device to use.
+//|
+//| Note that this function only sends the raw pixel data. Setting up
+//| the display for receiving it and handling the chip-select and
+//| data-command pins has to be done outside of it.
+//| There are also no sanity checks, outside of the basic overflow
+//| checking. The caller is responsible for making the passed parameters
+//| valid.
+//|
+//| This function is intended for internal use in the ``stage`` library
+//| and all the necessary checks are performed there.
+STATIC mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) {
+ uint8_t x0 = mp_obj_get_int(args[0]);
+ uint8_t y0 = mp_obj_get_int(args[1]);
+ uint8_t x1 = mp_obj_get_int(args[2]);
+ uint8_t y1 = mp_obj_get_int(args[3]);
+
+ size_t layers_size = 0;
+ mp_obj_t *layers;
+ mp_obj_get_array(args[4], &layers_size, &layers);
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[5], &bufinfo, MP_BUFFER_WRITE);
+ uint16_t *buffer = bufinfo.buf;
+ size_t buffer_size = bufinfo.len / 2; // 16-bit indexing
+
+ busio_spi_obj_t *spi = MP_OBJ_TO_PTR(args[6]);
+
+ if (!render_stage(x0, y0, x1, y1, layers, layers_size,
+ buffer, buffer_size, spi)) {
+ mp_raise_OSError(MP_EIO);
+ }
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stage_render_obj, 7, 7, stage_render);
+
+
+STATIC const mp_rom_map_elem_t stage_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__stage) },
+ { MP_ROM_QSTR(MP_QSTR_Layer), MP_ROM_PTR(&mp_type_layer) },
+ { MP_ROM_QSTR(MP_QSTR_Text), MP_ROM_PTR(&mp_type_text) },
+ { MP_ROM_QSTR(MP_QSTR_render), MP_ROM_PTR(&stage_render_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(stage_module_globals, stage_module_globals_table);
+
+const mp_obj_module_t stage_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&stage_module_globals,
+};
diff --git a/shared-bindings/_stage/__init__.h b/shared-bindings/_stage/__init__.h
new file mode 100644
index 000000000..2df81cb3b
--- /dev/null
+++ b/shared-bindings/_stage/__init__.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Radomir Dopieralski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED__STAGE_H
+#define MICROPY_INCLUDED__STAGE_H
+
+#include "shared-module/_stage/__init__.h"
+
+#endif // MICROPY_INCLUDED__STAGE
diff --git a/shared-bindings/audiobusio/PDMIn.c b/shared-bindings/audiobusio/PDMIn.c
index b43adecba..f273c7a3d 100644
--- a/shared-bindings/audiobusio/PDMIn.c
+++ b/shared-bindings/audiobusio/PDMIn.c
@@ -28,6 +28,7 @@
#include "lib/utils/context_manager_helpers.h"
#include "py/binary.h"
+#include "py/mphal.h"
#include "py/objproperty.h"
#include "py/runtime.h"
#include "shared-bindings/microcontroller/Pin.h"
@@ -41,7 +42,7 @@
//|
//| PDMIn can be used to record an input audio signal on a given set of pins.
//|
-//| .. class:: PDMIn(clock_pin, data_pin, \*, frequency=8000, bit_depth=8, mono=True, oversample=64)
+//| .. class:: PDMIn(clock_pin, data_pin, \*, frequency=16000, bit_depth=8, mono=True, oversample=64, startup_delay=0.11)
//|
//| Create a PDMIn object associated with the given pins. This allows you to
//| record audio signals from the given pins. Individual ports may put further
@@ -51,11 +52,16 @@
//|
//| :param ~microcontroller.Pin clock_pin: The pin to output the clock to
//| :param ~microcontroller.Pin data_pin: The pin to read the data from
-//| :param int frequency: Target frequency in Hz of the resulting samples. Check `frequency` for real value
+//| :param int frequency: Target frequency of the resulting samples. Check `frequency` for actual value.
+//| Minimum frequency is about 16000 Hz.
//| :param int bit_depth: Final number of bits per sample. Must be divisible by 8
//| :param bool mono: True when capturing a single channel of audio, captures two channels otherwise
//| :param int oversample: Number of single bit samples to decimate into a final sample. Must be divisible by 8
+//| :param float startup_delay: seconds to wait after starting microphone clock
+//| to allow microphone to turn on. Most require only 0.01s; some require 0.1s. Longer is safer.
+//| Must be in range 0.0-1.0 seconds.
//|
+
//| Record 8-bit unsigned samples to buffer::
//|
//| import audiobusio
@@ -81,15 +87,19 @@
//| mic.record(b, len(b))
//|
STATIC mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
- enum { ARG_frequency, ARG_bit_depth, ARG_mono, ARG_oversample };
+ enum { ARG_frequency, ARG_bit_depth, ARG_mono, ARG_oversample, ARG_startup_delay };
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_frequency, MP_ARG_INT, {.u_int = 8000} },
- { MP_QSTR_bit_depth, MP_ARG_INT, {.u_int = 8} },
- { MP_QSTR_mono, MP_ARG_BOOL,{.u_bool = true} },
- { MP_QSTR_oversample, MP_ARG_INT, {.u_int = 64} },
+ { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16000} },
+ { MP_QSTR_bit_depth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
+ { MP_QSTR_mono, MP_ARG_KW_ONLY | MP_ARG_BOOL,{.u_bool = true} },
+ { MP_QSTR_oversample, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
+ { MP_QSTR_startup_delay, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
+ // Default microphone startup delay is 110msecs. Have seen mics that need 100 msecs plus a bit.
+ static const float STARTUP_DELAY_DEFAULT = 0.110F;
+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 2, pos_args + 2, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -118,8 +128,18 @@ STATIC mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_ar
}
bool mono = args[ARG_mono].u_bool;
+ float startup_delay = (args[ARG_startup_delay].u_obj == MP_OBJ_NULL)
+ ? STARTUP_DELAY_DEFAULT
+ : mp_obj_get_float(args[ARG_startup_delay].u_obj);
+ if (startup_delay < 0.0 || startup_delay > 1.0) {
+ mp_raise_ValueError("Microphone startup delay must be in range 0.0 to 1.0");
+ }
+
common_hal_audiobusio_pdmin_construct(self, clock_pin, data_pin, frequency,
- bit_depth, mono, oversample);
+ bit_depth, mono, oversample);
+
+ // Wait for the microphone to start up. Some start in 10 msecs; some take as much as 100 msecs.
+ mp_hal_delay_ms(startup_delay * 1000);
return MP_OBJ_FROM_PTR(self);
}
@@ -162,11 +182,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_pdmin___exit___obj, 4, 4,
//| audio at the given rate. For internal flash, writing all 1s to the file
//| before recording is recommended to speed up writes.
//|
+//| :return: The number of samples recorded. If this is less than `destination_length`,
+//| some samples were missed due to processing time.
+//|
STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destination, mp_obj_t destination_length) {
audiobusio_pdmin_obj_t *self = MP_OBJ_TO_PTR(self_obj);
raise_error_if_deinited(common_hal_audiobusio_pdmin_deinited(self));
- if (!MP_OBJ_IS_SMALL_INT(destination_length)) {
- mp_raise_TypeError("destination_length must be int");
+ if (!MP_OBJ_IS_SMALL_INT(destination_length) || MP_OBJ_SMALL_INT_VALUE(destination_length) < 0) {
+ mp_raise_TypeError("destination_length must be an int >= 0");
}
uint32_t length = MP_OBJ_SMALL_INT_VALUE(destination_length);
@@ -174,8 +197,8 @@ STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destinat
if (MP_OBJ_IS_TYPE(destination, &fatfs_type_fileio)) {
mp_raise_NotImplementedError("");
} else if (mp_get_buffer(destination, &bufinfo, MP_BUFFER_WRITE)) {
- if (bufinfo.len < length) {
- mp_raise_ValueError("Target buffer cannot hold destination_length bytes.");
+ if (bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL) < length) {
+ mp_raise_ValueError("Destination capacity is smaller than destination_length.");
}
uint8_t bit_depth = common_hal_audiobusio_pdmin_get_bit_depth(self);
if (bufinfo.typecode != 'H' && bit_depth == 16) {
@@ -183,12 +206,10 @@ STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destinat
} else if (bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE && bit_depth == 8) {
mp_raise_ValueError("destination buffer must be a bytearray or array of type 'B' for bit_depth = 8");
}
- length *= bit_depth / 8;
+ // length is the buffer length in slots, not bytes.
uint32_t length_written =
common_hal_audiobusio_pdmin_record_to_buffer(self, bufinfo.buf, length);
- if (length_written != length) {
- mp_printf(&mp_plat_print, "length mismatch %d %d\n", length_written, length);
- }
+ return MP_OBJ_NEW_SMALL_INT(length_written);
}
return mp_const_none;
}
diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c
index 80718090a..f8f60210e 100644
--- a/shared-bindings/bitbangio/I2C.c
+++ b/shared-bindings/bitbangio/I2C.c
@@ -157,6 +157,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock);
//|
//| Read into ``buffer`` from the slave specified by ``address``.
//| The number of bytes read will be the length of ``buffer``.
+//| At least one byte must be read.
//|
//| If ``start`` or ``end`` is provided, then the buffer will be sliced
//| as if ``buffer[start:end]``. This will not cause an allocation like
@@ -186,6 +187,9 @@ STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_a
int32_t start = args[ARG_start].u_int;
uint32_t length = bufinfo.len;
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
+ if (length == 0) {
+ mp_raise_ValueError("Buffer must be at least length 1");
+ }
uint8_t status = shared_module_bitbangio_i2c_read(self,
args[ARG_address].u_int,
((uint8_t*)bufinfo.buf) + start,
@@ -206,6 +210,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_rea
//| as if ``buffer[start:end]``. This will not cause an allocation like
//| ``buffer[start:end]`` will so it saves memory.
//|
+//| Writing a buffer or slice of length zero is permitted, as it can be used
+//| to poll for the existence of a device.
+//|
//| :param int address: 7-bit device address
//| :param bytearray buffer: buffer containing the bytes to write
//| :param int start: Index to start writing from
diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c
index 6c7bac3e5..5442b9ea2 100644
--- a/shared-bindings/bitbangio/SPI.c
+++ b/shared-bindings/bitbangio/SPI.c
@@ -191,6 +191,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_unlock_obj, bitbangio_spi_obj_unlock);
//| .. method:: SPI.write(buf)
//|
//| Write the data contained in ``buf``. Requires the SPI being locked.
+//| If the buffer is empty, nothing happens.
//|
// TODO(tannewt): Add support for start and end kwargs.
STATIC mp_obj_t bitbangio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) {
@@ -198,6 +199,9 @@ STATIC mp_obj_t bitbangio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) {
raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self));
mp_buffer_info_t src;
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
+ if (src.len == 0) {
+ return mp_const_none;
+ }
check_lock(self);
bool ok = shared_module_bitbangio_spi_write(self, src.buf, src.len);
if (!ok) {
@@ -210,7 +214,9 @@ MP_DEFINE_CONST_FUN_OBJ_2(bitbangio_spi_write_obj, bitbangio_spi_write);
//| .. method:: SPI.readinto(buf)
//|
-//| Read into the buffer specified by ``buf`` while writing zeroes. Requires the SPI being locked.
+//| Read into the buffer specified by ``buf`` while writing zeroes.
+//| Requires the SPI being locked.
+//| If the number of bytes to read is 0, nothing happens.
//|
// TODO(tannewt): Add support for start and end kwargs.
STATIC mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *args) {
@@ -218,6 +224,9 @@ STATIC mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *args) {
raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self));
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
+ if (bufinfo.len == 0) {
+ return mp_const_none;
+ }
check_lock(args[0]);
bool ok = shared_module_bitbangio_spi_read(self, bufinfo.buf, bufinfo.len);
if (!ok) {
diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c
index cdc960f80..b0954d6c8 100644
--- a/shared-bindings/busio/I2C.c
+++ b/shared-bindings/busio/I2C.c
@@ -171,6 +171,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock);
//|
//| Read into ``buffer`` from the slave specified by ``address``.
//| The number of bytes read will be the length of ``buffer``.
+//| At least one byte must be read.
//|
//| If ``start`` or ``end`` is provided, then the buffer will be sliced
//| as if ``buffer[start:end]``. This will not cause an allocation like
@@ -201,6 +202,10 @@ STATIC mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args,
int32_t start = args[ARG_start].u_int;
uint32_t length = bufinfo.len;
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
+ if (length == 0) {
+ mp_raise_ValueError("Buffer must be at least length 1");
+ }
+
uint8_t status = common_hal_busio_i2c_read(self, args[ARG_address].u_int, ((uint8_t*)bufinfo.buf) + start, length);
if (status != 0) {
mp_raise_OSError(status);
@@ -219,6 +224,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 3, busio_i2c_readfrom_in
//| as if ``buffer[start:end]``. This will not cause an allocation like
//| ``buffer[start:end]`` will so it saves memory.
//|
+//| Writing a buffer or slice of length zero is permitted, as it can be used
+//| to poll for the existence of a device.
+//|
//| :param int address: 7-bit device address
//| :param bytearray buffer: buffer containing the bytes to write
//| :param int start: Index to start writing from
diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c
index 12f888f23..c4c139105 100644
--- a/shared-bindings/busio/SPI.c
+++ b/shared-bindings/busio/SPI.c
@@ -206,11 +206,12 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock);
//| .. method:: SPI.write(buffer, \*, start=0, end=len(buffer))
//|
-//| Write the data contained in ``buf``. Requires the SPI being locked.
+//| Write the data contained in ``buffer``. The SPI object must be locked.
+//| If the buffer is empty, nothing happens.
//|
-//| :param bytearray buffer: buffer containing the bytes to write
-//| :param int start: Index to start writing from
-//| :param int end: Index to read up to but not include
+//| :param bytearray buffer: Write out the data in this buffer
+//| :param int start: Start of the slice of ``buffer`` to write out: ``buffer[start:end]``
+//| :param int end: End of the slice; this index is not included
//|
STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer, ARG_start, ARG_end };
@@ -231,6 +232,10 @@ STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_
uint32_t length = bufinfo.len;
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
+ if (length == 0) {
+ return mp_const_none;
+ }
+
bool ok = common_hal_busio_spi_write(self, ((uint8_t*)bufinfo.buf) + start, length);
if (!ok) {
mp_raise_OSError(MP_EIO);
@@ -242,12 +247,14 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 2, busio_spi_write);
//| .. method:: SPI.readinto(buffer, \*, start=0, end=len(buffer), write_value=0)
//|
-//| Read into the buffer specified by ``buf`` while writing zeroes. Requires the SPI being locked.
+//| Read into ``buffer`` while writing ``write_value`` for each byte read.
+//| The SPI object must be locked.
+//| If the number of bytes to read is 0, nothing happens.
//|
-//| :param bytearray buffer: buffer to write into
-//| :param int start: Index to start writing at
-//| :param int end: Index to write up to but not include
-//| :param int write_value: Value to write reading. (Usually ignored.)
+//| :param bytearray buffer: Read data into this buffer
+//| :param int start: Start of the slice of ``buffer`` to read into: ``buffer[start:end]``
+//| :param int end: End of the slice; this index is not included
+//| :param int write_value: Value to write while reading. (Usually ignored.)
//|
STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer, ARG_start, ARG_end, ARG_write_value };
@@ -269,6 +276,10 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m
uint32_t length = bufinfo.len;
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
+ if (length == 0) {
+ return mp_const_none;
+ }
+
bool ok = common_hal_busio_spi_read(self, ((uint8_t*)bufinfo.buf) + start, length, args[ARG_write_value].u_int);
if (!ok) {
mp_raise_OSError(MP_EIO);
@@ -277,6 +288,68 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m
}
MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_readinto_obj, 2, busio_spi_readinto);
+//| .. method:: SPI.write_readinto(buffer_out, buffer_in, \*, out_start=0, out_end=len(buffer_out), in_start=0, in_end=len(buffer_in))
+//|
+//| Write out the data in ``buffer_out`` while simultaneously reading data into ``buffer_in``.
+//| The SPI object must be locked.
+//| The lengths of the slices defined by ``buffer_out[out_start:out_end]`` and ``buffer_in[in_start:in_end]``
+//| must be equal.
+//| If buffer slice lengths are both 0, nothing happens.
+//|
+//| :param bytearray buffer_out: Write out the data in this buffer
+//| :param bytearray buffer_in: Read data into this buffer
+//| :param int out_start: Start of the slice of buffer_out to write out: ``buffer_out[out_start:out_end]``
+//| :param int out_end: End of the slice; this index is not included
+//| :param int in_start: Start of the slice of ``buffer_in`` to read into: ``buffer_in[in_start:in_end]``
+//| :param int in_end: End of the slice; this index is not included
+//|
+STATIC mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_buffer_out, ARG_buffer_in, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_buffer_out, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_buffer_in, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
+ { MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
+ };
+ busio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ raise_error_if_deinited(common_hal_busio_spi_deinited(self));
+ check_lock(self);
+ 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);
+
+ mp_buffer_info_t buf_out_info;
+ mp_get_buffer_raise(args[ARG_buffer_out].u_obj, &buf_out_info, MP_BUFFER_READ);
+ int32_t out_start = args[ARG_out_start].u_int;
+ uint32_t out_length = buf_out_info.len;
+ normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length);
+
+ mp_buffer_info_t buf_in_info;
+ mp_get_buffer_raise(args[ARG_buffer_in].u_obj, &buf_in_info, MP_BUFFER_WRITE);
+ int32_t in_start = args[ARG_in_start].u_int;
+ uint32_t in_length = buf_in_info.len;
+ normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length);
+
+ if (out_length != in_length) {
+ mp_raise_ValueError("buffer slices must be of equal length");
+ }
+
+ if (out_length == 0) {
+ return mp_const_none;
+ }
+
+ bool ok = common_hal_busio_spi_transfer(self,
+ ((uint8_t*)buf_out_info.buf) + out_start,
+ ((uint8_t*)buf_in_info.buf) + in_start,
+ out_length);
+ if (!ok) {
+ mp_raise_OSError(MP_EIO);
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_readinto_obj, 2, busio_spi_write_readinto);
+
STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_spi_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
@@ -288,6 +361,7 @@ STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&busio_spi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&busio_spi_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&busio_spi_write_readinto_obj) },
};
STATIC MP_DEFINE_CONST_DICT(busio_spi_locals_dict, busio_spi_locals_dict_table);
diff --git a/shared-bindings/busio/SPI.h b/shared-bindings/busio/SPI.h
index ac31d5060..b6e5c9b1b 100644
--- a/shared-bindings/busio/SPI.h
+++ b/shared-bindings/busio/SPI.h
@@ -55,4 +55,7 @@ extern bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *dat
// Reads in len bytes while outputting zeroes.
extern bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value);
+// Reads and write len bytes simultaneously.
+extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len);
+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H
diff --git a/shared-bindings/digitalio/DigitalInOut.c b/shared-bindings/digitalio/DigitalInOut.c
index ea2ba0b89..008883b8b 100644
--- a/shared-bindings/digitalio/DigitalInOut.c
+++ b/shared-bindings/digitalio/DigitalInOut.c
@@ -124,7 +124,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_output(size_t n_args, const mp_
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 digitalio_drive_mode_t drive_mode = DRIVE_MODE_PUSH_PULL;
+ digitalio_drive_mode_t drive_mode = DRIVE_MODE_PUSH_PULL;
if (args[ARG_drive_mode].u_rom_obj == &digitalio_drive_mode_open_drain_obj) {
drive_mode = DRIVE_MODE_OPEN_DRAIN;
}
@@ -161,7 +161,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_input(size_t n_args, const mp_o
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 digitalio_pull_t pull = PULL_NONE;
+ digitalio_pull_t pull = PULL_NONE;
if (args[ARG_pull].u_rom_obj == &digitalio_pull_up_obj) {
pull = PULL_UP;
}else if (args[ARG_pull].u_rom_obj == &digitalio_pull_down_obj) {
@@ -191,7 +191,7 @@ extern const digitalio_digitalio_direction_obj_t digitalio_digitalio_direction_o
STATIC mp_obj_t digitalio_digitalinout_obj_get_direction(mp_obj_t self_in) {
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
- enum digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(self);
+ digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(self);
if (direction == DIRECTION_INPUT) {
return (mp_obj_t)&digitalio_direction_input_obj;
}
@@ -262,7 +262,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_get_drive_mode(mp_obj_t self_in) {
mp_raise_AttributeError("Drive mode not used when direction is input.");
return mp_const_none;
}
- enum digitalio_drive_mode_t drive_mode = common_hal_digitalio_digitalinout_get_drive_mode(self);
+ digitalio_drive_mode_t drive_mode = common_hal_digitalio_digitalinout_get_drive_mode(self);
if (drive_mode == DRIVE_MODE_PUSH_PULL) {
return (mp_obj_t)&digitalio_drive_mode_push_pull_obj;
}
@@ -277,7 +277,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_set_drive_mode(mp_obj_t self_in, mp_o
mp_raise_AttributeError("Drive mode not used when direction is input.");
return mp_const_none;
}
- enum digitalio_drive_mode_t c_drive_mode = DRIVE_MODE_PUSH_PULL;
+ digitalio_drive_mode_t c_drive_mode = DRIVE_MODE_PUSH_PULL;
if (drive_mode == &digitalio_drive_mode_open_drain_obj) {
c_drive_mode = DRIVE_MODE_OPEN_DRAIN;
}
@@ -307,7 +307,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_get_pull(mp_obj_t self_in) {
mp_raise_AttributeError("Pull not used when direction is output.");
return mp_const_none;
}
- enum digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(self);
+ digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(self);
if (pull == PULL_UP) {
return (mp_obj_t)&digitalio_pull_up_obj;
} else if (pull == PULL_DOWN) {
@@ -324,7 +324,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_set_pull(mp_obj_t self_in, mp_obj_t p
mp_raise_AttributeError("Pull not used when direction is output.");
return mp_const_none;
}
- enum digitalio_pull_t pull = PULL_NONE;
+ digitalio_pull_t pull = PULL_NONE;
if (pull_obj == &digitalio_pull_up_obj) {
pull = PULL_UP;
} else if (pull_obj == &digitalio_pull_down_obj) {
diff --git a/shared-bindings/digitalio/DigitalInOut.h b/shared-bindings/digitalio/DigitalInOut.h
index 74970881b..2aaa31b7f 100644
--- a/shared-bindings/digitalio/DigitalInOut.h
+++ b/shared-bindings/digitalio/DigitalInOut.h
@@ -43,14 +43,14 @@ typedef enum {
digitalinout_result_t common_hal_digitalio_digitalinout_construct(digitalio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin);
void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self);
bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t* self);
-void common_hal_digitalio_digitalinout_switch_to_input(digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull);
-void common_hal_digitalio_digitalinout_switch_to_output(digitalio_digitalinout_obj_t* self, bool value, enum digitalio_drive_mode_t drive_mode);
-enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(digitalio_digitalinout_obj_t* self);
+void common_hal_digitalio_digitalinout_switch_to_input(digitalio_digitalinout_obj_t* self, digitalio_pull_t pull);
+void common_hal_digitalio_digitalinout_switch_to_output(digitalio_digitalinout_obj_t* self, bool value, digitalio_drive_mode_t drive_mode);
+digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(digitalio_digitalinout_obj_t* self);
void common_hal_digitalio_digitalinout_set_value(digitalio_digitalinout_obj_t* self, bool value);
bool common_hal_digitalio_digitalinout_get_value(digitalio_digitalinout_obj_t* self);
-void common_hal_digitalio_digitalinout_set_drive_mode(digitalio_digitalinout_obj_t* self, enum digitalio_drive_mode_t drive_mode);
-enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(digitalio_digitalinout_obj_t* self);
-void common_hal_digitalio_digitalinout_set_pull(digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull);
-enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(digitalio_digitalinout_obj_t* self);
+void common_hal_digitalio_digitalinout_set_drive_mode(digitalio_digitalinout_obj_t* self, digitalio_drive_mode_t drive_mode);
+digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(digitalio_digitalinout_obj_t* self);
+void common_hal_digitalio_digitalinout_set_pull(digitalio_digitalinout_obj_t* self, digitalio_pull_t pull);
+digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(digitalio_digitalinout_obj_t* self);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DIGITALIO_DIGITALINOUT_H
diff --git a/shared-bindings/digitalio/Direction.h b/shared-bindings/digitalio/Direction.h
index e8fbf181d..d71f48c2e 100644
--- a/shared-bindings/digitalio/Direction.h
+++ b/shared-bindings/digitalio/Direction.h
@@ -29,10 +29,10 @@
#include "py/obj.h"
-enum digitalio_direction_t {
+typedef enum {
DIRECTION_INPUT,
DIRECTION_OUTPUT
-};
+} digitalio_direction_t;
typedef struct {
mp_obj_base_t base;
} digitalio_direction_obj_t;
diff --git a/shared-bindings/digitalio/DriveMode.h b/shared-bindings/digitalio/DriveMode.h
index 959885b1b..47d036b3a 100644
--- a/shared-bindings/digitalio/DriveMode.h
+++ b/shared-bindings/digitalio/DriveMode.h
@@ -29,10 +29,10 @@
#include "py/obj.h"
-enum digitalio_drive_mode_t {
+typedef enum {
DRIVE_MODE_PUSH_PULL,
DRIVE_MODE_OPEN_DRAIN
-};
+} digitalio_drive_mode_t;
typedef struct {
mp_obj_base_t base;
diff --git a/shared-bindings/digitalio/Pull.h b/shared-bindings/digitalio/Pull.h
index 8c88d8673..22fb6cd0e 100644
--- a/shared-bindings/digitalio/Pull.h
+++ b/shared-bindings/digitalio/Pull.h
@@ -29,11 +29,11 @@
#include "py/obj.h"
-enum digitalio_pull_t {
+typedef enum _digitalio_pull_t {
PULL_NONE,
PULL_UP,
PULL_DOWN
-};
+} digitalio_pull_t;
const mp_obj_type_t digitalio_pull_type;
diff --git a/shared-bindings/microcontroller/RunMode.c b/shared-bindings/microcontroller/RunMode.c
new file mode 100644
index 000000000..b27a3c090
--- /dev/null
+++ b/shared-bindings/microcontroller/RunMode.c
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/microcontroller/RunMode.h"
+
+//| .. currentmodule:: microcontroller
+//|
+//| :class:`RunMode` -- run state of the microcontroller
+//| =============================================================
+//|
+//| .. class:: microcontroller.RunMode
+//|
+//| Enum-like class to define the run mode of the microcontroller and
+//| CircuitPython.
+//|
+//| .. data:: NORMAL
+//|
+//| Run CircuitPython as normal.
+//|
+//| .. data:: SAFE_MODE
+//|
+//| Run CircuitPython in safe mode. User code will not be run and the
+//| file system will be writeable over USB.
+//|
+//| .. data:: BOOTLOADER
+//|
+//| Run the bootloader.
+//|
+const mp_obj_type_t mcu_runmode_type;
+
+const mcu_runmode_obj_t mcu_runmode_normal_obj = {
+ { &mcu_runmode_type },
+};
+
+const mcu_runmode_obj_t mcu_runmode_safe_mode_obj = {
+ { &mcu_runmode_type },
+};
+
+const mcu_runmode_obj_t mcu_runmode_bootloader_obj = {
+ { &mcu_runmode_type },
+};
+
+STATIC const mp_rom_map_elem_t mcu_runmode_locals_dict_table[] = {
+ {MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_PTR(&mcu_runmode_normal_obj)},
+ {MP_ROM_QSTR(MP_QSTR_SAFE_MODE), MP_ROM_PTR(&mcu_runmode_safe_mode_obj)},
+ {MP_ROM_QSTR(MP_QSTR_BOOTLOADER), MP_ROM_PTR(&mcu_runmode_bootloader_obj)},
+};
+STATIC MP_DEFINE_CONST_DICT(mcu_runmode_locals_dict, mcu_runmode_locals_dict_table);
+
+STATIC void mcu_runmode_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ qstr runmode = MP_QSTR_NORMAL;
+ if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&mcu_runmode_safe_mode_obj)) {
+ runmode = MP_QSTR_SAFE_MODE;
+ } else if (MP_OBJ_TO_PTR(self_in) ==
+ MP_ROM_PTR(&mcu_runmode_bootloader_obj)) {
+ runmode = MP_QSTR_SAFE_MODE;
+ }
+ mp_printf(print, "%q.%q.%q", MP_QSTR_microcontroller, MP_QSTR_RunMode,
+ runmode);
+}
+
+const mp_obj_type_t mcu_runmode_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_RunMode,
+ .print = mcu_runmode_print,
+ .locals_dict = (mp_obj_t)&mcu_runmode_locals_dict,
+};
diff --git a/shared-bindings/microcontroller/RunMode.h b/shared-bindings/microcontroller/RunMode.h
new file mode 100644
index 000000000..5e8b6e646
--- /dev/null
+++ b/shared-bindings/microcontroller/RunMode.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H
+
+#include "py/obj.h"
+
+typedef enum {
+ RUNMODE_NORMAL,
+ RUNMODE_SAFE_MODE,
+ RUNMODE_BOOTLOADER
+} mcu_runmode_t;
+
+const mp_obj_type_t mcu_runmode_type;
+
+typedef struct {
+ mp_obj_base_t base;
+} mcu_runmode_obj_t;
+extern const mcu_runmode_obj_t mcu_runmode_normal_obj;
+extern const mcu_runmode_obj_t mcu_runmode_safe_mode_obj;
+extern const mcu_runmode_obj_t mcu_runmode_bootloader_obj;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H
diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c
index 58ed876c2..f261178f0 100644
--- a/shared-bindings/microcontroller/__init__.c
+++ b/shared-bindings/microcontroller/__init__.c
@@ -106,6 +106,47 @@ STATIC mp_obj_t mcu_enable_interrupts(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_enable_interrupts_obj, mcu_enable_interrupts);
+//| .. method:: on_next_reset(run_mode)
+//|
+//| Configure the run mode used the next time the microcontroller is reset but
+//| not powered down.
+//|
+//| :param ~microcontroller.RunMode run_mode: The next run mode
+//|
+STATIC mp_obj_t mcu_on_next_reset(mp_obj_t run_mode_obj) {
+ mcu_runmode_t run_mode;
+ if (run_mode_obj == &mcu_runmode_normal_obj) {
+ run_mode = RUNMODE_NORMAL;
+ } else if (run_mode_obj == &mcu_runmode_safe_mode_obj) {
+ run_mode = RUNMODE_SAFE_MODE;
+ } else if (run_mode_obj == &mcu_runmode_bootloader_obj) {
+ run_mode = RUNMODE_BOOTLOADER;
+ } else {
+ mp_raise_ValueError("Invalid run mode.");
+ }
+
+ common_hal_mcu_on_next_reset(run_mode);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mcu_on_next_reset_obj, mcu_on_next_reset);
+
+//| .. method:: reset()
+//|
+//| Reset the microcontroller. After reset, the microcontroller will enter the
+//| run mode last set by `one_next_reset`.
+//|
+//| .. warning:: This may result in file system corruption when connected to a
+//| host computer. Be very careful when calling this! Make sure the device
+//| "Safely removed" on Windows or "ejected" on Mac OSX and Linux.
+//|
+STATIC mp_obj_t mcu_reset(void) {
+ common_hal_mcu_reset();
+ // We won't actually get here because we're resetting.
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_reset_obj, mcu_reset);
+
//| .. attribute:: nvm
//|
//| Available non-volatile memory.
@@ -132,11 +173,14 @@ STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) },
{ MP_ROM_QSTR(MP_QSTR_disable_interrupts), MP_ROM_PTR(&mcu_disable_interrupts_obj) },
{ MP_ROM_QSTR(MP_QSTR_enable_interrupts), MP_ROM_PTR(&mcu_enable_interrupts_obj) },
+ { MP_ROM_QSTR(MP_QSTR_on_next_reset), MP_ROM_PTR(&mcu_on_next_reset_obj) },
+ { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&mcu_reset_obj) },
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0
{ MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&common_hal_mcu_nvm_obj) },
#else
{ MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&mp_const_none_obj) },
#endif
+ { MP_ROM_QSTR(MP_QSTR_RunMode), MP_ROM_PTR(&mcu_runmode_type) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&mcu_pin_type) },
{ MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&mcu_pin_module) },
{ MP_ROM_QSTR(MP_QSTR_Processor), MP_ROM_PTR(&mcu_processor_type) },
diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h
index d43db4bf4..e1487c555 100644
--- a/shared-bindings/microcontroller/__init__.h
+++ b/shared-bindings/microcontroller/__init__.h
@@ -33,11 +33,16 @@
#include "common-hal/microcontroller/Processor.h"
+#include "shared-bindings/microcontroller/RunMode.h"
+
extern void common_hal_mcu_delay_us(uint32_t);
extern void common_hal_mcu_disable_interrupts(void);
extern void common_hal_mcu_enable_interrupts(void);
+extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode);
+extern void common_hal_mcu_reset(void);
+
extern const mp_obj_dict_t mcu_pin_globals;
extern const mcu_processor_obj_t common_hal_mcu_processor_obj;