summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--README.md21
-rw-r--r--py/builtin.h6
-rw-r--r--py/builtinimport.c9
-rw-r--r--py/builtintables.c150
-rw-r--r--py/builtintables.h2
-rw-r--r--py/makeqstrdata.py4
-rw-r--r--py/modarray.c25
-rw-r--r--py/modcollections.c25
-rw-r--r--py/modmath.c (renamed from py/builtinmath.c)0
-rw-r--r--py/modmicropython.c (renamed from py/builtinmp.c)1
-rw-r--r--py/mpconfig.h8
-rw-r--r--py/obj.c28
-rw-r--r--py/obj.h44
-rw-r--r--py/objarray.c12
-rw-r--r--py/objexcept.c66
-rw-r--r--py/objmodule.c45
-rw-r--r--py/objmodule.h4
-rw-r--r--py/objstr.c91
-rw-r--r--py/objtype.c4
-rw-r--r--py/py.mk7
-rw-r--r--py/qstr.c8
-rw-r--r--py/qstrdefs.h8
-rw-r--r--py/runtime.c187
-rw-r--r--py/runtime.h1
-rw-r--r--py/vm.c15
-rw-r--r--stm/main.c6
-rw-r--r--stm/pybmodule.c3
-rw-r--r--stmhal/Makefile17
-rw-r--r--stmhal/accel.c80
-rw-r--r--stmhal/accel.h4
-rw-r--r--stmhal/adc.c345
-rw-r--r--stmhal/adc.h3
-rw-r--r--stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h2
-rw-r--r--stmhal/boards/PYBOARD3/mpconfigboard.h2
-rw-r--r--stmhal/boards/PYBOARD4/mpconfigboard.h2
-rw-r--r--stmhal/boards/PYBv10/mpconfigboard.h2
-rw-r--r--stmhal/boards/STM32F4DISC/mpconfigboard.h2
-rwxr-xr-xstmhal/boards/make-pins.py63
-rw-r--r--stmhal/boards/stm32f4xx-af.csv50
-rw-r--r--stmhal/boards/stm32f4xx-prefix.c4
-rw-r--r--stmhal/dac.c279
-rw-r--r--stmhal/dac.h3
-rw-r--r--stmhal/exti.c4
-rw-r--r--stmhal/help.c90
-rw-r--r--stmhal/i2c.c184
-rw-r--r--stmhal/i2c.h6
-rw-r--r--stmhal/led.c46
-rw-r--r--stmhal/led.h2
-rw-r--r--stmhal/main.c107
-rw-r--r--stmhal/modos.c (renamed from stmhal/osmodule.c)2
-rw-r--r--stmhal/modos.h (renamed from stmhal/osmodule.h)0
-rw-r--r--stmhal/modpyb.c (renamed from stmhal/pybmodule.c)36
-rw-r--r--stmhal/modpyb.h (renamed from stmhal/pybmodule.h)0
-rw-r--r--stmhal/modtime.c (renamed from stmhal/timemodule.c)2
-rw-r--r--stmhal/modtime.h (renamed from stmhal/timemodule.h)0
-rw-r--r--stmhal/mpconfigport.h11
-rw-r--r--stmhal/pin.h14
-rw-r--r--stmhal/pyexec.c61
-rw-r--r--stmhal/pyexec.h11
-rw-r--r--stmhal/qstrdefsport.h2
-rw-r--r--stmhal/servo.c55
-rw-r--r--stmhal/servo.h3
-rw-r--r--stmhal/usart.c76
-rw-r--r--stmhal/usart.h4
-rw-r--r--stmhal/usbd_cdc_interface.c2
-rw-r--r--tests/basics/exception1.py6
-rw-r--r--tests/basics/exceptpoly.py208
-rw-r--r--tests/basics/string_rfind.py23
-rw-r--r--tests/basics/try-as-var.py10
-rw-r--r--tests/basics/types1.py5
-rw-r--r--tools/pyboard.py127
71 files changed, 2020 insertions, 715 deletions
diff --git a/README.md b/README.md
index 113229f9ae..9ca44e75fd 100644
--- a/README.md
+++ b/README.md
@@ -13,21 +13,22 @@ changes. The software will not start to mature until March 2014 at the
earliest.
See the repository www.github.com/micropython/pyboard for the Micro
-Python board. At the moment, finalising the design of the board is
-the top priority.
+Python board.
Major components in this repository:
- py/ -- the core Python implementation, including compiler and runtime.
- unix/ -- a version of Micro Python that runs on Unix.
-- stm/ -- a version of Micro Python that runs on the Micro Python board
- with an STM32F405RG.
+- stmhal/ -- a version of Micro Python that runs on the Micro Python board
+ with an STM32F405RG (using ST's new Cube HAL drivers).
+- stm/ -- obsolete version of Micro Python for the Micro Python board
+ that uses ST's old peripheral drivers.
- teensy/ -- a version of Micro Python that runs on the Teensy 3.1
(preliminary but functional).
Additional components:
- unix-cpy/ -- a version of Micro Python that outputs bytecode (for testing).
- tests/ -- test framework and test scripts.
-- tools/ -- various tools.
+- tools/ -- various tools, including the pyboard.py module.
- examples/ -- a few example Python scripts.
"make" is used to build the components, or "gmake" on BSD-based systems.
@@ -58,17 +59,21 @@ module (recommended, enable in unix/mpconfigport.mk), libffi-dev is required.
The STM version
---------------
-The "stm" part requires an ARM compiler, arm-none-eabi-gcc, and associated
+The "stmhal" part requires an ARM compiler, arm-none-eabi-gcc, and associated
bin-utils. For those using Arch Linux, you need arm-none-eabi-binutils and
arm-none-eabi-gcc packages from the AUR. Otherwise, try here:
https://launchpad.net/gcc-arm-embedded
To build:
- $ cd stm
+ $ cd stmhal
$ make
-Then to flash it via USB DFU to your device:
+You then need to get your board into DFU mode. On the pyboard, connect the
+3V3 pin to the P1/DFU pin with a wire (on PYBv1.0 they are next to each other
+on the bottom left of the board, second row from the bottom).
+
+Then to flash the code via USB DFU to your device:
$ dfu-util -a 0 -D build/flash.dfu
diff --git a/py/builtin.h b/py/builtin.h
index d9414045de..45da172d10 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -1,4 +1,4 @@
-mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args);
+mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin___build_class___obj);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin___import___obj);
@@ -6,7 +6,6 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin___repl_print___obj);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_abs_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_all_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_any_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_bytes_obj); // Temporary hack
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_callable_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_chr_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_dir_obj);
@@ -30,9 +29,10 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_range_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_repr_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sorted_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_str_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_namedtuple_obj);
+extern const mp_obj_module_t mp_module_array;
+extern const mp_obj_module_t mp_module_collections;
extern const mp_obj_module_t mp_module_math;
extern const mp_obj_module_t mp_module_micropython;
diff --git a/py/builtinimport.c b/py/builtinimport.c
index 2b9b3a30b9..882b128df1 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -12,6 +12,7 @@
#include "lexerunix.h"
#include "parse.h"
#include "obj.h"
+#include "objmodule.h"
#include "parsehelper.h"
#include "compile.h"
#include "runtime0.h"
@@ -128,7 +129,7 @@ void do_load(mp_obj_t module_obj, vstr_t *file) {
rt_globals_set(old_globals);
}
-mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
+mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args) {
/*
printf("import:\n");
for (int i = 0; i < n_args; i++) {
@@ -156,7 +157,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
const char *mod_str = (const char*)mp_obj_str_get_data(args[0], &mod_len);
// check if module already exists
- mp_obj_t module_obj = mp_obj_module_get(mp_obj_str_get_qstr(args[0]));
+ mp_obj_t module_obj = mp_module_get(mp_obj_str_get_qstr(args[0]));
if (module_obj != MP_OBJ_NULL) {
// If it's not a package, return module right away
char *p = strchr(mod_str, '.');
@@ -169,7 +170,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
}
// Otherwise, we need to return top-level package
qstr pkg_name = qstr_from_strn(mod_str, p - mod_str);
- return mp_obj_module_get(pkg_name);
+ return mp_module_get(pkg_name);
}
uint last = 0;
@@ -200,7 +201,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "ImportError: No module named '%s'", qstr_str(mod_name)));
}
- module_obj = mp_obj_module_get(mod_name);
+ module_obj = mp_module_get(mod_name);
if (module_obj == MP_OBJ_NULL) {
// module not already loaded, so load it!
diff --git a/py/builtintables.c b/py/builtintables.c
new file mode 100644
index 0000000000..0aa0b66a72
--- /dev/null
+++ b/py/builtintables.c
@@ -0,0 +1,150 @@
+#include <stdlib.h>
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "builtin.h"
+#include "builtintables.h"
+#include "objarray.h"
+
+// builtins
+// we put these tables in ROM because they're always needed and take up quite a bit of room in RAM
+// in fact, it uses less ROM here in table form than the equivalent in code form initialising a dynamic mp_map_t object in RAM
+// at the moment it's a linear table, but we could convert it to a const mp_map_t table with a simple preprocessing script
+
+typedef struct _mp_builtin_elem_t {
+ qstr qstr;
+ mp_obj_t elem;
+} mp_builtin_elem_t;
+
+STATIC const mp_builtin_elem_t builtin_object_table[] = {
+ // built-in core functions
+ { MP_QSTR___build_class__, (mp_obj_t)&mp_builtin___build_class___obj },
+ { MP_QSTR___import__, (mp_obj_t)&mp_builtin___import___obj },
+ { MP_QSTR___repl_print__, (mp_obj_t)&mp_builtin___repl_print___obj },
+
+ // built-in types
+ { MP_QSTR_bool, (mp_obj_t)&bool_type },
+ { MP_QSTR_bytes, (mp_obj_t)&bytes_type },
+#if MICROPY_ENABLE_FLOAT
+ { MP_QSTR_complex, (mp_obj_t)&mp_type_complex },
+#endif
+ { MP_QSTR_dict, (mp_obj_t)&dict_type },
+ { MP_QSTR_enumerate, (mp_obj_t)&enumerate_type },
+ { MP_QSTR_filter, (mp_obj_t)&filter_type },
+#if MICROPY_ENABLE_FLOAT
+ { MP_QSTR_float, (mp_obj_t)&mp_type_float },
+#endif
+ { MP_QSTR_int, (mp_obj_t)&int_type },
+ { MP_QSTR_list, (mp_obj_t)&list_type },
+ { MP_QSTR_map, (mp_obj_t)&map_type },
+ { MP_QSTR_object, (mp_obj_t)&mp_type_object },
+ { MP_QSTR_set, (mp_obj_t)&set_type },
+ { MP_QSTR_str, (mp_obj_t)&str_type },
+ { MP_QSTR_super, (mp_obj_t)&super_type },
+ { MP_QSTR_tuple, (mp_obj_t)&tuple_type },
+ { MP_QSTR_type, (mp_obj_t)&mp_type_type },
+ { MP_QSTR_zip, (mp_obj_t)&zip_type },
+
+ { MP_QSTR_classmethod, (mp_obj_t)&mp_type_classmethod },
+ { MP_QSTR_staticmethod, (mp_obj_t)&mp_type_staticmethod },
+
+ // built-in user functions
+ { MP_QSTR_abs, (mp_obj_t)&mp_builtin_abs_obj },
+ { MP_QSTR_all, (mp_obj_t)&mp_builtin_all_obj },
+ { MP_QSTR_any, (mp_obj_t)&mp_builtin_any_obj },
+ { MP_QSTR_callable, (mp_obj_t)&mp_builtin_callable_obj },
+ { MP_QSTR_chr, (mp_obj_t)&mp_builtin_chr_obj },
+ { MP_QSTR_dir, (mp_obj_t)&mp_builtin_dir_obj },
+ { MP_QSTR_divmod, (mp_obj_t)&mp_builtin_divmod_obj },
+ { MP_QSTR_eval, (mp_obj_t)&mp_builtin_eval_obj },
+ { MP_QSTR_exec, (mp_obj_t)&mp_builtin_exec_obj },
+ { MP_QSTR_hash, (mp_obj_t)&mp_builtin_hash_obj },
+ { MP_QSTR_id, (mp_obj_t)&mp_builtin_id_obj },
+ { MP_QSTR_isinstance, (mp_obj_t)&mp_builtin_isinstance_obj },
+ { MP_QSTR_issubclass, (mp_obj_t)&mp_builtin_issubclass_obj },
+ { MP_QSTR_iter, (mp_obj_t)&mp_builtin_iter_obj },
+ { MP_QSTR_len, (mp_obj_t)&mp_builtin_len_obj },
+ { MP_QSTR_max, (mp_obj_t)&mp_builtin_max_obj },
+ { MP_QSTR_min, (mp_obj_t)&mp_builtin_min_obj },
+ { MP_QSTR_next, (mp_obj_t)&mp_builtin_next_obj },
+ { MP_QSTR_ord, (mp_obj_t)&mp_builtin_ord_obj },
+ { MP_QSTR_pow, (mp_obj_t)&mp_builtin_pow_obj },
+ { MP_QSTR_print, (mp_obj_t)&mp_builtin_print_obj },
+ { MP_QSTR_range, (mp_obj_t)&mp_builtin_range_obj },
+ { MP_QSTR_repr, (mp_obj_t)&mp_builtin_repr_obj },
+ { MP_QSTR_sorted, (mp_obj_t)&mp_builtin_sorted_obj },
+ { MP_QSTR_sum, (mp_obj_t)&mp_builtin_sum_obj },
+ { MP_QSTR_bytearray, (mp_obj_t)&mp_builtin_bytearray_obj },
+
+ // built-in exceptions
+ { MP_QSTR_BaseException, (mp_obj_t)&mp_type_BaseException },
+ { MP_QSTR_ArithmeticError, (mp_obj_t)&mp_type_ArithmeticError },
+ { MP_QSTR_AssertionError, (mp_obj_t)&mp_type_AssertionError },
+ { MP_QSTR_AttributeError, (mp_obj_t)&mp_type_AttributeError },
+ { MP_QSTR_BufferError, (mp_obj_t)&mp_type_BufferError },
+ { MP_QSTR_EOFError, (mp_obj_t)&mp_type_EOFError },
+ { MP_QSTR_Exception, (mp_obj_t)&mp_type_Exception },
+ { MP_QSTR_FloatingPointError, (mp_obj_t)&mp_type_FloatingPointError },
+ { MP_QSTR_GeneratorExit, (mp_obj_t)&mp_type_GeneratorExit },
+ { MP_QSTR_IOError, (mp_obj_t)&mp_type_IOError },
+ { MP_QSTR_ImportError, (mp_obj_t)&mp_type_ImportError },
+ { MP_QSTR_IndentationError, (mp_obj_t)&mp_type_IndentationError },
+ { MP_QSTR_IndexError, (mp_obj_t)&mp_type_IndexError },
+ { MP_QSTR_KeyError, (mp_obj_t)&mp_type_KeyError },
+ { MP_QSTR_LookupError, (mp_obj_t)&mp_type_LookupError },
+ { MP_QSTR_MemoryError, (mp_obj_t)&mp_type_MemoryError },
+ { MP_QSTR_NameError, (mp_obj_t)&mp_type_NameError },
+ { MP_QSTR_NotImplementedError, (mp_obj_t)&mp_type_NotImplementedError },
+ { MP_QSTR_OSError, (mp_obj_t)&mp_type_OSError },
+ { MP_QSTR_OverflowError, (mp_obj_t)&mp_type_OverflowError },
+ { MP_QSTR_RuntimeError, (mp_obj_t)&mp_type_RuntimeError },
+ { MP_QSTR_StopIteration, (mp_obj_t)&mp_type_StopIteration },
+ { MP_QSTR_SyntaxError, (mp_obj_t)&mp_type_SyntaxError },
+ { MP_QSTR_SystemError, (mp_obj_t)&mp_type_SystemError },
+ { MP_QSTR_TypeError, (mp_obj_t)&mp_type_TypeError },
+ { MP_QSTR_UnboundLocalError, (mp_obj_t)&mp_type_UnboundLocalError },
+ { MP_QSTR_ValueError, (mp_obj_t)&mp_type_ValueError },
+ { MP_QSTR_ZeroDivisionError, (mp_obj_t)&mp_type_ZeroDivisionError },
+ // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/
+ // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation
+
+ // Extra builtins as defined by a port
+ MICROPY_EXTRA_BUILTINS
+
+ { MP_QSTR_, MP_OBJ_NULL }, // end of list sentinel
+};
+
+STATIC const mp_builtin_elem_t builtin_module_table[] = {
+ { MP_QSTR_micropython, (mp_obj_t)&mp_module_micropython },
+
+ { MP_QSTR_array, (mp_obj_t)&mp_module_array },
+ { MP_QSTR_collections, (mp_obj_t)&mp_module_collections },
+
+#if MICROPY_ENABLE_FLOAT
+ { MP_QSTR_math, (mp_obj_t)&mp_module_math },
+#endif
+
+ // extra builtin modules as defined by a port
+ MICROPY_EXTRA_BUILTIN_MODULES
+
+ { MP_QSTR_, MP_OBJ_NULL }, // end of list sentinel
+};
+
+STATIC mp_obj_t mp_builtin_tables_lookup(const mp_builtin_elem_t *table, qstr q) {
+ for (; table->qstr != MP_QSTR_; table++) {
+ if (table->qstr == q) {
+ return table->elem;
+ }
+ }
+ return MP_OBJ_NULL;
+}
+
+mp_obj_t mp_builtin_tables_lookup_object(qstr q) {
+ return mp_builtin_tables_lookup(&builtin_object_table[0], q);
+}
+
+mp_obj_t mp_builtin_tables_lookup_module(qstr q) {
+ return mp_builtin_tables_lookup(&builtin_module_table[0], q);
+}
diff --git a/py/builtintables.h b/py/builtintables.h
new file mode 100644
index 0000000000..9b22b66e03
--- /dev/null
+++ b/py/builtintables.h
@@ -0,0 +1,2 @@
+mp_obj_t mp_builtin_tables_lookup_object(qstr q);
+mp_obj_t mp_builtin_tables_lookup_module(qstr q);
diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py
index 934bc43beb..7413365712 100644
--- a/py/makeqstrdata.py
+++ b/py/makeqstrdata.py
@@ -18,9 +18,9 @@ codepoint2name[ord('/')] = 'slash'
# this must match the equivalent function in qstr.c
def compute_hash(qstr):
- hash = 0
+ hash = 5381
for char in qstr:
- hash += ord(char)
+ hash = (hash * 33) ^ ord(char)
return hash & 0xffff
def do_work(infiles):
diff --git a/py/modarray.c b/py/modarray.c
new file mode 100644
index 0000000000..2544f7ed59
--- /dev/null
+++ b/py/modarray.c
@@ -0,0 +1,25 @@
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "map.h"
+#include "builtin.h"
+
+STATIC const mp_map_elem_t mp_module_array_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_array) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_array), (mp_obj_t)&mp_type_array },
+};
+
+STATIC const mp_map_t mp_module_array_globals = {
+ .all_keys_are_qstrs = 1,
+ .table_is_fixed_array = 1,
+ .used = sizeof(mp_module_array_globals_table) / sizeof(mp_map_elem_t),
+ .alloc = sizeof(mp_module_array_globals_table) / sizeof(mp_map_elem_t),
+ .table = (mp_map_elem_t*)mp_module_array_globals_table,
+};
+
+const mp_obj_module_t mp_module_array = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_array,
+ .globals = (mp_map_t*)&mp_module_array_globals,
+};
diff --git a/py/modcollections.c b/py/modcollections.c
new file mode 100644
index 0000000000..ad951d5e9e
--- /dev/null
+++ b/py/modcollections.c
@@ -0,0 +1,25 @@
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "map.h"
+#include "builtin.h"
+
+STATIC const mp_map_elem_t mp_module_collections_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_collections) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_namedtuple), (mp_obj_t)&mp_namedtuple_obj },
+};
+
+STATIC const mp_map_t mp_module_collections_globals = {
+ .all_keys_are_qstrs = 1,
+ .table_is_fixed_array = 1,
+ .used = sizeof(mp_module_collections_globals_table) / sizeof(mp_map_elem_t),
+ .alloc = sizeof(mp_module_collections_globals_table) / sizeof(mp_map_elem_t),
+ .table = (mp_map_elem_t*)mp_module_collections_globals_table,
+};
+
+const mp_obj_module_t mp_module_collections = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_collections,
+ .globals = (mp_map_t*)&mp_module_collections_globals,
+};
diff --git a/py/builtinmath.c b/py/modmath.c
index b814822531..b814822531 100644
--- a/py/builtinmath.c
+++ b/py/modmath.c
diff --git a/py/builtinmp.c b/py/modmicropython.c
index 3b73517963..96ceb811c9 100644
--- a/py/builtinmp.c
+++ b/py/modmicropython.c
@@ -1,4 +1,3 @@
-
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 5b13c46480..09cc37913a 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -125,10 +125,16 @@ typedef double mp_float_t;
#define MICROPY_PATH_MAX (512)
#endif
-// Additional builtin function definitions - see runtime.c:builtin_table for format.
+// Additional builtin function definitions - see builtintables.c:builtin_object_table for format.
#ifndef MICROPY_EXTRA_BUILTINS
#define MICROPY_EXTRA_BUILTINS
#endif
+
+// Additional builtin module definitions - see builtintables.c:builtin_module_table for format.
+#ifndef MICROPY_EXTRA_BUILTIN_MODULES
+#define MICROPY_EXTRA_BUILTIN_MODULES
+#endif
+
/*****************************************************************************/
/* Miscellaneous settings */
diff --git a/py/obj.c b/py/obj.c
index 717df51641..18f66a2b47 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -206,21 +206,29 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
}
#endif
-mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o_in, machine_int_t n) {
- if (MP_OBJ_IS_TYPE(o_in, &tuple_type) || MP_OBJ_IS_TYPE(o_in, &list_type)) {
+void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items) {
+ if (MP_OBJ_IS_TYPE(o, &tuple_type)) {
+ mp_obj_tuple_get(o, len, items);
+ } else if (MP_OBJ_IS_TYPE(o, &list_type)) {
+ mp_obj_list_get(o, len, items);
+ } else {
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o)));
+ }
+}
+
+void mp_obj_get_array_fixed_n(mp_obj_t o, uint len, mp_obj_t **items) {
+ if (MP_OBJ_IS_TYPE(o, &tuple_type) || MP_OBJ_IS_TYPE(o, &list_type)) {
uint seq_len;
- mp_obj_t *seq_items;
- if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
- mp_obj_tuple_get(o_in, &seq_len, &seq_items);
+ if (MP_OBJ_IS_TYPE(o, &tuple_type)) {
+ mp_obj_tuple_get(o, &seq_len, items);
} else {
- mp_obj_list_get(o_in, &seq_len, &seq_items);
+ mp_obj_list_get(o, &seq_len, items);
}
- if (seq_len != n) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "requested length %d but object has length %d", n, seq_len));
+ if (seq_len != len) {
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "requested length %d but object has length %d", len, seq_len));
}
- return seq_items;
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in)));
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o)));
}
}
diff --git a/py/obj.h b/py/obj.h
index 9599d137dd..0a8b80e30b 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -175,7 +175,6 @@ struct _mp_obj_type_t {
abs float complex
hash bool int none str
equal int str
- get_array_n tuple list
unpack seq list tuple
*/
@@ -192,17 +191,12 @@ extern const mp_obj_type_t mp_type_ArithmeticError;
extern const mp_obj_type_t mp_type_AssertionError;
extern const mp_obj_type_t mp_type_AttributeError;
extern const mp_obj_type_t mp_type_BufferError;
-extern const mp_obj_type_t mp_type_BytesWarning;
-extern const mp_obj_type_t mp_type_DeprecationWarning;
extern const mp_obj_type_t mp_type_EOFError;
-extern const mp_obj_type_t mp_type_EnvironmentError;
extern const mp_obj_type_t mp_type_Exception;
extern const mp_obj_type_t mp_type_FloatingPointError;
-extern const mp_obj_type_t mp_type_FutureWarning;
extern const mp_obj_type_t mp_type_GeneratorExit;
extern const mp_obj_type_t mp_type_IOError;
extern const mp_obj_type_t mp_type_ImportError;
-extern const mp_obj_type_t mp_type_ImportWarning;
extern const mp_obj_type_t mp_type_IndentationError;
extern const mp_obj_type_t mp_type_IndexError;
extern const mp_obj_type_t mp_type_KeyError;
@@ -212,43 +206,16 @@ extern const mp_obj_type_t mp_type_NameError;
extern const mp_obj_type_t mp_type_NotImplementedError;
extern const mp_obj_type_t mp_type_OSError;
extern const mp_obj_type_t mp_type_OverflowError;
-extern const mp_obj_type_t mp_type_PendingDeprecationWarning;
-extern const mp_obj_type_t mp_type_ReferenceError;
-extern const mp_obj_type_t mp_type_ResourceWarning;
extern const mp_obj_type_t mp_type_RuntimeError;
-extern const mp_obj_type_t mp_type_RuntimeWarning;
+extern const mp_obj_type_t mp_type_StopIteration;
extern const mp_obj_type_t mp_type_SyntaxError;
-extern const mp_obj_type_t mp_type_SyntaxWarning;
extern const mp_obj_type_t mp_type_SystemError;
-extern const mp_obj_type_t mp_type_SystemExit;
-extern const mp_obj_type_t mp_type_TabError;
extern const mp_obj_type_t mp_type_TypeError;
extern const mp_obj_type_t mp_type_UnboundLocalError;
-extern const mp_obj_type_t mp_type_UserWarning;
extern const mp_obj_type_t mp_type_ValueError;
-extern const mp_obj_type_t mp_type_Warning;
extern const mp_obj_type_t mp_type_ZeroDivisionError;
-extern const mp_obj_type_t mp_type_StopIteration;
-/*extern const mp_obj_type_t mp_type_BaseException;
-extern const mp_obj_type_t mp_type_AssertionError;
-extern const mp_obj_type_t mp_type_AttributeError;
-extern const mp_obj_type_t mp_type_ImportError;
-extern const mp_obj_type_t mp_type_IndentationError;
-extern const mp_obj_type_t mp_type_IndexError;
-extern const mp_obj_type_t mp_type_KeyError;
-extern const mp_obj_type_t mp_type_NameError;
-extern const mp_obj_type_t mp_type_SyntaxError;
-extern const mp_obj_type_t mp_type_TypeError;
-extern const mp_obj_type_t mp_type_ValueError;
-extern const mp_obj_type_t mp_type_OverflowError;
-extern const mp_obj_type_t mp_type_OSError;
-extern const mp_obj_type_t mp_type_NotImplementedError;
-extern const mp_obj_type_t mp_type_StopIteration;
-extern const mp_obj_type_t mp_type_ZeroDivisionError;*/
-
// Constant objects, globally accessible
-
extern const mp_obj_t mp_const_none;
extern const mp_obj_t mp_const_false;
extern const mp_obj_t mp_const_true;
@@ -295,7 +262,7 @@ mp_obj_t mp_obj_new_module(qstr module_name);
mp_obj_type_t *mp_obj_get_type(mp_obj_t o_in);
const char *mp_obj_get_type_str(mp_obj_t o_in);
-bool mp_obj_is_subclass_fast(mp_obj_t object, mp_obj_t classinfo); // arguments should be type objects
+bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind);
void mp_obj_print(mp_obj_t o, mp_print_kind_t kind);
@@ -312,7 +279,8 @@ mp_float_t mp_obj_get_float(mp_obj_t self_in);
void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
#endif
//qstr mp_obj_get_qstr(mp_obj_t arg);
-mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o, machine_int_t n);
+void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items);
+void mp_obj_get_array_fixed_n(mp_obj_t o, uint len, mp_obj_t **items);
uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index, bool is_slice);
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); /* may return NULL */
@@ -419,7 +387,7 @@ void mp_obj_slice_get(mp_obj_t self_in, machine_int_t *start, machine_int_t *sto
extern const mp_obj_type_t zip_type;
// array
-extern const mp_obj_type_t array_type;
+extern const mp_obj_type_t mp_type_array;
uint mp_obj_array_len(mp_obj_t self_in);
mp_obj_t mp_obj_new_bytearray_by_ref(uint n, void *items);
@@ -456,8 +424,6 @@ typedef struct _mp_obj_module_t {
struct _mp_map_t *globals;
} mp_obj_module_t;
extern const mp_obj_type_t mp_type_module;
-mp_obj_t mp_obj_new_module(qstr module_name);
-mp_obj_t mp_obj_module_get(qstr module_name);
struct _mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in);
// staticmethod and classmethod types; defined here so we can make const versions
diff --git a/py/objarray.c b/py/objarray.c
index ee43bde960..69f60e000a 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -121,7 +121,7 @@ STATIC mp_obj_t array_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
}
STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) {
- assert(MP_OBJ_IS_TYPE(self_in, &array_type));
+ assert(MP_OBJ_IS_TYPE(self_in, &mp_type_array));
mp_obj_array_t *self = self_in;
if (self->free == 0) {
int item_sz = mp_binary_get_size(self->typecode);
@@ -154,7 +154,7 @@ STATIC const mp_method_t array_type_methods[] = {
{ NULL, NULL },
};
-const mp_obj_type_t array_type = {
+const mp_obj_type_t mp_type_array = {
{ &mp_type_type },
.name = MP_QSTR_array,
.print = array_print,
@@ -169,7 +169,7 @@ const mp_obj_type_t array_type = {
STATIC mp_obj_array_t *array_new(char typecode, uint n) {
mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
- o->base.type = &array_type;
+ o->base.type = &mp_type_array;
o->typecode = typecode;
o->free = 0;
o->len = n;
@@ -190,7 +190,7 @@ mp_obj_t mp_obj_new_bytearray(uint n, void *items) {
// Create bytearray which references specified memory area
mp_obj_t mp_obj_new_bytearray_by_ref(uint n, void *items) {
mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
- o->base.type = &array_type;
+ o->base.type = &mp_type_array;
o->typecode = BYTEARRAY_TYPECODE;
o->free = 0;
o->len = n;
@@ -207,7 +207,7 @@ typedef struct _mp_obj_array_it_t {
machine_uint_t cur;
} mp_obj_array_it_t;
-mp_obj_t array_it_iternext(mp_obj_t self_in) {
+STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
mp_obj_array_it_t *self = self_in;
if (self->cur < self->array->len) {
return mp_binary_get_val(self->array->typecode, self->array->items, self->cur++);
@@ -222,7 +222,7 @@ STATIC const mp_obj_type_t array_it_type = {
.iternext = array_it_iternext,
};
-mp_obj_t array_iterator_new(mp_obj_t array_in) {
+STATIC mp_obj_t array_iterator_new(mp_obj_t array_in) {
mp_obj_array_t *array = array_in;
mp_obj_array_it_t *o = m_new_obj(mp_obj_array_it_t);
o->base.type = &array_it_type;
diff --git a/py/objexcept.c b/py/objexcept.c
index f96523ed23..c75e3d3a57 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -55,16 +55,31 @@ STATIC mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_
o->base.type = type;
o->traceback = MP_OBJ_NULL;
o->msg = NULL;
+ o->args.base.type = &tuple_type;
o->args.len = n_args;
memcpy(o->args.items, args, n_args * sizeof(mp_obj_t));
return o;
}
+STATIC void exception_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
+ mp_obj_exception_t *self = self_in;
+ if (attr == MP_QSTR_args) {
+ dest[0] = &self->args;
+ } else if (self->base.type == &mp_type_StopIteration && attr == MP_QSTR_value) {
+ if (self->args.len == 0) {
+ dest[0] = mp_const_none;
+ } else {
+ dest[0] = self->args.items[0];
+ }
+ }
+}
+
const mp_obj_type_t mp_type_BaseException = {
{ &mp_type_type },
.name = MP_QSTR_BaseException,
.print = mp_obj_exception_print,
.make_new = mp_obj_exception_make_new,
+ .load_attr = exception_load_attr,
};
#define MP_DEFINE_EXCEPTION_BASE(base_name) \
@@ -76,13 +91,14 @@ const mp_obj_type_t mp_type_ ## exc_name = { \
.name = MP_QSTR_ ## exc_name, \
.print = mp_obj_exception_print, \
.make_new = mp_obj_exception_make_new, \
+ .load_attr = exception_load_attr, \
.bases_tuple = (mp_obj_t)&mp_type_ ## base_name ## _base_tuple, \
};
// List of all exceptions, arranged as in the table at:
// http://docs.python.org/3.3/library/exceptions.html
MP_DEFINE_EXCEPTION_BASE(BaseException)
-MP_DEFINE_EXCEPTION(SystemExit, BaseException)
+//MP_DEFINE_EXCEPTION(SystemExit, BaseException)
//MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException)
MP_DEFINE_EXCEPTION(GeneratorExit, BaseException)
MP_DEFINE_EXCEPTION(Exception, BaseException)
@@ -96,7 +112,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
MP_DEFINE_EXCEPTION(AssertionError, Exception)
MP_DEFINE_EXCEPTION(AttributeError, Exception)
MP_DEFINE_EXCEPTION(BufferError, Exception)
- MP_DEFINE_EXCEPTION(EnvironmentError, Exception)
+ //MP_DEFINE_EXCEPTION(EnvironmentError, Exception)
MP_DEFINE_EXCEPTION(EOFError, Exception)
MP_DEFINE_EXCEPTION(ImportError, Exception)
MP_DEFINE_EXCEPTION(IOError, Exception)
@@ -126,7 +142,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
MP_DEFINE_EXCEPTION(TimeoutError, OSError)*/
MP_DEFINE_EXCEPTION(FileExistsError, OSError)
MP_DEFINE_EXCEPTION(FileNotFoundError, OSError)
- MP_DEFINE_EXCEPTION(ReferenceError, Exception)
+ //MP_DEFINE_EXCEPTION(ReferenceError, Exception)
MP_DEFINE_EXCEPTION(RuntimeError, Exception)
MP_DEFINE_EXCEPTION_BASE(RuntimeError)
MP_DEFINE_EXCEPTION(NotImplementedError, RuntimeError)
@@ -134,7 +150,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
MP_DEFINE_EXCEPTION_BASE(SyntaxError)
MP_DEFINE_EXCEPTION(IndentationError, SyntaxError)
MP_DEFINE_EXCEPTION_BASE(IndentationError)
- MP_DEFINE_EXCEPTION(TabError, IndentationError)
+ //MP_DEFINE_EXCEPTION(TabError, IndentationError)
MP_DEFINE_EXCEPTION(SystemError, Exception)
MP_DEFINE_EXCEPTION(TypeError, Exception)
MP_DEFINE_EXCEPTION(ValueError, Exception)
@@ -193,20 +209,20 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
}
// return true if the given object is an exception type
-// TODO make this work for user defined exceptions
bool mp_obj_is_exception_type(mp_obj_t self_in) {
if (MP_OBJ_IS_TYPE(self_in, &mp_type_type)) {
+ // optimisation when self_in is a builtin exception
mp_obj_type_t *self = self_in;
- return self->make_new == mp_obj_exception_make_new;
- } else {
- return false;
+ if (self->make_new == mp_obj_exception_make_new) {
+ return true;
+ }
}
+ return mp_obj_is_subclass_fast(self_in, &mp_type_BaseException);
}
// return true if the given object is an instance of an exception type
-// TODO make this work for user defined exceptions
bool mp_obj_is_exception_instance(mp_obj_t self_in) {
- return mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new;
+ return mp_obj_is_exception_type(mp_obj_get_type(self_in));
}
// return true if exception (type or instance) is a subclass of given
@@ -218,26 +234,30 @@ bool mp_obj_exception_match(mp_obj_t exc, const mp_obj_type_t *exc_type) {
void mp_obj_exception_clear_traceback(mp_obj_t self_in) {
// make sure self_in is an exception instance
- assert(mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new);
- mp_obj_exception_t *self = self_in;
+ // TODO add traceback information to user-defined exceptions (need proper builtin subclassing for that)
+ if (mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new) {
+ mp_obj_exception_t *self = self_in;
- // just set the traceback to the null object
- // we don't want to call any memory management functions here
- self->traceback = MP_OBJ_NULL;
+ // just set the traceback to the null object
+ // we don't want to call any memory management functions here
+ self->traceback = MP_OBJ_NULL;
+ }
}
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block) {
// make sure self_in is an exception instance
- assert(mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new);
- mp_obj_exception_t *self = self_in;
+ // TODO add traceback information to user-defined exceptions (need proper builtin subclassing for that)
+ if (mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new) {
+ mp_obj_exception_t *self = self_in;
- // for traceback, we are just using the list object for convenience, it's not really a list of Python objects
- if (self->traceback == MP_OBJ_NULL) {
- self->traceback = mp_obj_new_list(0, NULL);
+ // for traceback, we are just using the list object for convenience, it's not really a list of Python objects
+ if (self->traceback == MP_OBJ_NULL) {
+ self->traceback = mp_obj_new_list(0, NULL);
+ }
+ mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)file);
+ mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)line);
+ mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)block);
}
- mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)file);
- mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)line);
- mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)block);
}
void mp_obj_exception_get_traceback(mp_obj_t self_in, machine_uint_t *n, machine_uint_t **values) {
diff --git a/py/objmodule.c b/py/objmodule.c
index e0778b4cf2..a388ca3f37 100644
--- a/py/objmodule.c
+++ b/py/objmodule.c
@@ -6,9 +6,12 @@
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
+#include "objmodule.h"
#include "runtime.h"
#include "map.h"
-#include "builtin.h"
+#include "builtintables.h"
+
+STATIC mp_map_t mp_loaded_modules_map; // TODO: expose as sys.modules
STATIC void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_module_t *self = self_in;
@@ -39,7 +42,7 @@ const mp_obj_type_t mp_type_module = {
};
mp_obj_t mp_obj_new_module(qstr module_name) {
- mp_map_elem_t *el = mp_map_lookup(rt_loaded_modules_get(), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
+ mp_map_elem_t *el = mp_map_lookup(&mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
// We could error out if module already exists, but let C extensions
// add new members to existing modules.
if (el->value != MP_OBJ_NULL) {
@@ -62,9 +65,27 @@ mp_obj_t mp_obj_new_module(qstr module_name) {
return o;
}
-mp_obj_t mp_obj_module_get(qstr module_name) {
+mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in) {
+ assert(MP_OBJ_IS_TYPE(self_in, &mp_type_module));
+ mp_obj_module_t *self = self_in;
+ return self->globals;
+}
+
+/******************************************************************************/
+// Global module table and related functions
+
+void mp_module_init(void) {
+ mp_map_init(&mp_loaded_modules_map, 3);
+}
+
+void mp_module_deinit(void) {
+ mp_map_deinit(&mp_loaded_modules_map);
+}
+
+// returns MP_OBJ_NULL if not found
+mp_obj_t mp_module_get(qstr module_name) {
// lookup module
- mp_map_elem_t *el = mp_map_lookup(rt_loaded_modules_get(), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
+ mp_map_elem_t *el = mp_map_lookup(&mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
// module found, return it
if (el != NULL) {
@@ -72,18 +93,10 @@ mp_obj_t mp_obj_module_get(qstr module_name) {
}
// module not found, look for builtin module names
-#if MICROPY_ENABLE_FLOAT
- if (module_name == MP_QSTR_math) {
- return (mp_obj_t)&mp_module_math;
- }
-#endif
-
- // no module found, return NULL object
- return MP_OBJ_NULL;
+ // it will return MP_OBJ_NULL if nothing found
+ return mp_builtin_tables_lookup_module(module_name);
}
-mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in) {
- assert(MP_OBJ_IS_TYPE(self_in, &mp_type_module));
- mp_obj_module_t *self = self_in;
- return self->globals;
+void mp_module_register(qstr qstr, mp_obj_t module) {
+ mp_map_lookup(&mp_loaded_modules_map, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module;
}
diff --git a/py/objmodule.h b/py/objmodule.h
new file mode 100644
index 0000000000..270551da4f
--- /dev/null
+++ b/py/objmodule.h
@@ -0,0 +1,4 @@
+void mp_module_init(void);
+void mp_module_deinit(void);
+mp_obj_t mp_module_get(qstr module_name);
+void mp_module_register(qstr qstr, mp_obj_t module);
diff --git a/py/objstr.c b/py/objstr.c
index 35a948700c..00586a3b3b 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -186,19 +186,26 @@ wrong_args:
// like strstr but with specified length and allows \0 bytes
// TODO replace with something more efficient/standard
-STATIC const byte *find_subbytes(const byte *haystack, uint hlen, const byte *needle, uint nlen) {
+STATIC const byte *find_subbytes(const byte *haystack, machine_uint_t hlen, const byte *needle, machine_uint_t nlen, machine_int_t direction) {
if (hlen >= nlen) {
- for (uint i = 0; i <= hlen - nlen; i++) {
- bool found = true;
- for (uint j = 0; j < nlen; j++) {
- if (haystack[i + j] != needle[j]) {
- found = false;
- break;
- }
+ machine_uint_t str_index, str_index_end;
+ if (direction > 0) {
+ str_index = 0;
+ str_index_end = hlen - nlen;
+ } else {
+ str_index = hlen - nlen;
+ str_index_end = 0;
+ }
+ for (;;) {
+ if (memcmp(&haystack[str_index], needle, nlen) == 0) {
+ //found
+ return haystack + str_index;
}
- if (found) {
- return haystack + i;
+ if (str_index == str_index_end) {
+ //not found
+ break;
}
+ str_index += direction;
}
}
return NULL;
@@ -260,7 +267,7 @@ STATIC mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
/* NOTE `a in b` is `b.__contains__(a)` */
if (MP_OBJ_IS_STR(rhs_in)) {
GET_STR_DATA_LEN(rhs_in, rhs_data, rhs_len);
- return MP_BOOL(find_subbytes(lhs_data, lhs_len, rhs_data, rhs_len) != NULL);
+ return MP_BOOL(find_subbytes(lhs_data, lhs_len, rhs_data, rhs_len, 1) != NULL);
}
break;
@@ -382,7 +389,7 @@ STATIC mp_obj_t str_split(uint n_args, const mp_obj_t *args) {
return res;
}
-STATIC mp_obj_t str_find(uint n_args, const mp_obj_t *args) {
+STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t direction) {
assert(2 <= n_args && n_args <= 4);
assert(MP_OBJ_IS_STR(args[0]));
assert(MP_OBJ_IS_STR(args[1]));
@@ -392,7 +399,6 @@ STATIC mp_obj_t str_find(uint n_args, const mp_obj_t *args) {
machine_uint_t start = 0;
machine_uint_t end = haystack_len;
- /* TODO use a non-exception-throwing mp_get_index */
if (n_args >= 3 && args[2] != mp_const_none) {
start = mp_get_index(&str_type, haystack_len, args[2], true);
}
@@ -400,20 +406,24 @@ STATIC mp_obj_t str_find(uint n_args, const mp_obj_t *args) {
end = mp_get_index(&str_type, haystack_len, args[3], true);
}
- const byte *p = find_subbytes(haystack + start, haystack_len - start, needle, needle_len);
+ const byte *p = find_subbytes(haystack + start, end - start, needle, needle_len, direction);
if (p == NULL) {
// not found
return MP_OBJ_NEW_SMALL_INT(-1);
} else {
// found
- machine_int_t pos = p - haystack;
- if (pos + needle_len > end) {
- pos = -1;
- }
- return MP_OBJ_NEW_SMALL_INT(pos);
+ return MP_OBJ_NEW_SMALL_INT(p - haystack);
}
}
+STATIC mp_obj_t str_find(uint n_args, const mp_obj_t *args) {
+ return str_finder(n_args, args, 1);
+}
+
+STATIC mp_obj_t str_rfind(uint n_args, const mp_obj_t *args) {
+ return str_finder(n_args, args, -1);
+}
+
// TODO: (Much) more variety in args
STATIC mp_obj_t str_startswith(mp_obj_t self_in, mp_obj_t arg) {
GET_STR_DATA_LEN(self_in, str, str_len);
@@ -424,15 +434,6 @@ STATIC mp_obj_t str_startswith(mp_obj_t self_in, mp_obj_t arg) {
return MP_BOOL(memcmp(str, prefix, prefix_len) == 0);
}
-STATIC bool chr_in_str(const byte* const str, const machine_uint_t str_len, int c) {
- for (machine_uint_t i = 0; i < str_len; i++) {
- if (str[i] == c) {
- return true;
- }
- }
- return false;
-}
-
STATIC mp_obj_t str_strip(uint n_args, const mp_obj_t *args) {
assert(1 <= n_args && n_args <= 2);
assert(MP_OBJ_IS_STR(args[0]));
@@ -457,7 +458,7 @@ STATIC mp_obj_t str_strip(uint n_args, const mp_obj_t *args) {
bool first_good_char_pos_set = false;
machine_uint_t last_good_char_pos = 0;
for (machine_uint_t i = 0; i < orig_str_len; i++) {
- if (!chr_in_str(chars_to_del, chars_to_del_len, orig_str[i])) {
+ if (find_subbytes(chars_to_del, chars_to_del_len, &orig_str[i], 1, 1) == NULL) {
last_good_char_pos = i;
if (!first_good_char_pos_set) {
first_good_char_pos = i;
@@ -547,7 +548,7 @@ STATIC mp_obj_t str_replace(uint n_args, const mp_obj_t *args) {
const byte *old_occurrence;
const byte *offset_ptr = str;
machine_uint_t offset_num = 0;
- while ((old_occurrence = find_subbytes(offset_ptr, str_len - offset_num, old, old_len)) != NULL) {
+ while ((old_occurrence = find_subbytes(offset_ptr, str_len - offset_num, old, old_len, 1)) != NULL) {
// copy from just after end of last occurrence of to-be-replaced string to right before start of next occurrence
if (data != NULL) {
memcpy(data + replaced_str_index, offset_ptr, old_occurrence - offset_ptr);
@@ -601,7 +602,6 @@ STATIC mp_obj_t str_count(uint n_args, const mp_obj_t *args) {
machine_uint_t start = 0;
machine_uint_t end = haystack_len;
- /* TODO use a non-exception-throwing mp_get_index */
if (n_args >= 3 && args[2] != mp_const_none) {
start = mp_get_index(&str_type, haystack_len, args[2], true);
}
@@ -648,27 +648,12 @@ STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, machine_int_t di
result[2] = self_in;
}
- if (str_len >= sep_len) {
- machine_uint_t str_index, str_index_end;
- if (direction > 0) {
- str_index = 0;
- str_index_end = str_len - sep_len;
- } else {
- str_index = str_len - sep_len;
- str_index_end = 0;
- }
- for (;;) {
- if (memcmp(&str[str_index], sep, sep_len) == 0) {
- result[0] = mp_obj_new_str(str, str_index, false);
- result[1] = arg;
- result[2] = mp_obj_new_str(str + str_index + sep_len, str_len - str_index - sep_len, false);
- break;
- }
- if (str_index == str_index_end) {
- break;
- }
- str_index += direction;
- }
+ const byte *position_ptr = find_subbytes(str, str_len, sep, sep_len, direction);
+ if (position_ptr != NULL) {
+ machine_uint_t position = position_ptr - str;
+ result[0] = mp_obj_new_str(str, position, false);
+ result[1] = arg;
+ result[2] = mp_obj_new_str(str + position + sep_len, str_len - position - sep_len, false);
}
return mp_obj_new_tuple(3, result);
@@ -697,6 +682,7 @@ STATIC machine_int_t str_get_buffer(mp_obj_t self_in, buffer_info_t *bufinfo, in
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_startswith_obj, str_startswith);
@@ -709,6 +695,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition);
STATIC const mp_method_t str_type_methods[] = {
{ "find", &str_find_obj },
+ { "rfind", &str_rfind_obj },
{ "join", &str_join_obj },
{ "split", &str_split_obj },
{ "startswith", &str_startswith_obj },
diff --git a/py/objtype.c b/py/objtype.c
index 4898c5ccb4..9cb29744c7 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -469,7 +469,7 @@ mp_obj_t mp_obj_new_super(mp_obj_t type, mp_obj_t obj) {
// object and classinfo should be type objects
// (but the function will fail gracefully if they are not)
-bool mp_obj_is_subclass_fast(mp_obj_t object, mp_obj_t classinfo) {
+bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
for (;;) {
if (object == classinfo) {
return true;
@@ -482,7 +482,7 @@ bool mp_obj_is_subclass_fast(mp_obj_t object, mp_obj_t classinfo) {
return false;
}
- mp_obj_type_t *self = object;
+ const mp_obj_type_t *self = object;
// for a const struct, this entry might be NULL
if (self->bases_tuple == MP_OBJ_NULL) {
diff --git a/py/py.mk b/py/py.mk
index 624797d823..2247b6babb 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -74,8 +74,11 @@ PY_O_BASENAME = \
builtin.o \
builtinimport.o \
builtinevex.o \
- builtinmp.o \
- builtinmath.o \
+ builtintables.o \
+ modarray.o \
+ modcollections.o \
+ modmath.o \
+ modmicropython.o \
vm.o \
showbc.o \
repl.o \
diff --git a/py/qstr.c b/py/qstr.c
index aebc2921cf..e4b5c111b5 100644
--- a/py/qstr.c
+++ b/py/qstr.c
@@ -18,7 +18,7 @@
// A qstr is an index into the qstr pool.
// The data for a qstr contains (hash, length, data).
// For now we use very simple encoding, just to get the framework correct:
-// - hash is 2 bytes (simply the sum of data bytes)
+// - hash is 2 bytes (see function below)
// - length is 2 bytes
// - data follows
// - \0 terminated (for now, so they can be printed using printf)
@@ -28,10 +28,12 @@
#define Q_GET_LENGTH(q) ((q)[2] | ((q)[3] << 8))
#define Q_GET_DATA(q) ((q) + 4)
+// this must match the equivalent function in makeqstrdata.py
machine_uint_t qstr_compute_hash(const byte *data, uint len) {
- machine_uint_t hash = 0;
+ // djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html
+ machine_uint_t hash = 5381;
for (const byte *top = data + len; data < top; data++) {
- hash += *data;
+ hash = ((hash << 5) + hash) ^ (*data); // hash * 33 ^ data
}
return hash & 0xffff;
}
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 898e67582f..1c8afe797d 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -17,6 +17,7 @@ Q(__repl_print__)
Q(__bool__)
Q(__len__)
+Q(__iter__)
Q(__getitem__)
Q(__setitem__)
Q(__add__)
@@ -39,7 +40,6 @@ Q(AssertionError)
Q(AttributeError)
Q(BufferError)
Q(EOFError)
-Q(EnvironmentError)
Q(Exception)
Q(FileExistsError)
Q(FileNotFoundError)
@@ -56,16 +56,12 @@ Q(NameError)
Q(NotImplementedError)
Q(OSError)
Q(OverflowError)
-Q(ReferenceError)
Q(RuntimeError)
Q(SyntaxError)
Q(SystemError)
-Q(SystemExit)
-Q(TabError)
Q(TypeError)
Q(UnboundLocalError)
Q(ValueError)
-Q(Warning)
Q(ZeroDivisionError)
Q(None)
@@ -78,6 +74,7 @@ Q(NoneType)
Q(abs)
Q(all)
Q(any)
+Q(args)
Q(array)
Q(bool)
Q(bytearray)
@@ -123,6 +120,7 @@ Q(str)
Q(sys)
Q(tuple)
Q(type)
+Q(value)
Q(zip)
Q(append)
diff --git a/py/runtime.c b/py/runtime.c
index bbd12895af..3e0ef98d8b 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -12,12 +12,13 @@
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
+#include "objmodule.h"
#include "parsenum.h"
#include "runtime0.h"
#include "runtime.h"
#include "map.h"
#include "builtin.h"
-#include "objarray.h"
+#include "builtintables.h"
#include "bc.h"
#include "intdivmod.h"
@@ -35,7 +36,6 @@
STATIC mp_map_t *map_locals;
STATIC mp_map_t *map_globals;
STATIC mp_map_t map_builtins;
-STATIC mp_map_t map_loaded_modules; // TODO: expose as sys.modules
typedef enum {
MP_CODE_NONE,
@@ -72,119 +72,6 @@ STATIC mp_code_t *unique_codes = NULL;
FILE *fp_write_code = NULL;
#endif
-// builtins
-// we put this table in ROM because it's always needed and takes up quite a bit of room in RAM
-// in fact, it uses less ROM here in table form than the equivalent in code form initialising a dynamic mp_map_t object in RAM
-// at the moment it's a linear table, but we could convert it to a const mp_map_t table with a simple preprocessing script
-// if we wanted to allow dynamic modification of the builtins, we could provide an mp_map_t object which is searched before this one
-
-typedef struct _mp_builtin_elem_t {
- qstr qstr;
- mp_obj_t fun;
-} mp_builtin_elem_t;
-
-STATIC const mp_builtin_elem_t builtin_table[] = {
- // built-in core functions
- { MP_QSTR___build_class__, (mp_obj_t)&mp_builtin___build_class___obj },
- { MP_QSTR___import__, (mp_obj_t)&mp_builtin___import___obj },
- { MP_QSTR___repl_print__, (mp_obj_t)&mp_builtin___repl_print___obj },
-
- // built-in types
- { MP_QSTR_bool, (mp_obj_t)&bool_type },
- { MP_QSTR_bytes, (mp_obj_t)&bytes_type },
-#if MICROPY_ENABLE_FLOAT
- { MP_QSTR_complex, (mp_obj_t)&mp_type_complex },
-#endif
- { MP_QSTR_dict, (mp_obj_t)&dict_type },
- { MP_QSTR_enumerate, (mp_obj_t)&enumerate_type },
- { MP_QSTR_filter, (mp_obj_t)&filter_type },
-#if MICROPY_ENABLE_FLOAT
- { MP_QSTR_float, (mp_obj_t)&mp_type_float },
-#endif
- { MP_QSTR_int, (mp_obj_t)&int_type },
- { MP_QSTR_list, (mp_obj_t)&list_type },
- { MP_QSTR_map, (mp_obj_t)&map_type },
- { MP_QSTR_object, (mp_obj_t)&mp_type_object },
- { MP_QSTR_set, (mp_obj_t)&set_type },
- { MP_QSTR_str, (mp_obj_t)&str_type },
- { MP_QSTR_super, (mp_obj_t)&super_type },
- { MP_QSTR_tuple, (mp_obj_t)&tuple_type },
- { MP_QSTR_type, (mp_obj_t)&mp_type_type },
- { MP_QSTR_zip, (mp_obj_t)&zip_type },
-
- { MP_QSTR_classmethod, (mp_obj_t)&mp_type_classmethod },
- { MP_QSTR_staticmethod, (mp_obj_t)&mp_type_staticmethod },
-
- // built-in user functions
- { MP_QSTR_abs, (mp_obj_t)&mp_builtin_abs_obj },
- { MP_QSTR_all, (mp_obj_t)&mp_builtin_all_obj },
- { MP_QSTR_any, (mp_obj_t)&mp_builtin_any_obj },
- { MP_QSTR_callable, (mp_obj_t)&mp_builtin_callable_obj },
- { MP_QSTR_chr, (mp_obj_t)&mp_builtin_chr_obj },
- { MP_QSTR_dir, (mp_obj_t)&mp_builtin_dir_obj },
- { MP_QSTR_divmod, (mp_obj_t)&mp_builtin_divmod_obj },
- { MP_QSTR_eval, (mp_obj_t)&mp_builtin_eval_obj },
- { MP_QSTR_exec, (mp_obj_t)&mp_builtin_exec_obj },
- { MP_QSTR_hash, (mp_obj_t)&mp_builtin_hash_obj },
- { MP_QSTR_id, (mp_obj_t)&mp_builtin_id_obj },
- { MP_QSTR_isinstance, (mp_obj_t)&mp_builtin_isinstance_obj },
- { MP_QSTR_issubclass, (mp_obj_t)&mp_builtin_issubclass_obj },
- { MP_QSTR_iter, (mp_obj_t)&mp_builtin_iter_obj },
- { MP_QSTR_len, (mp_obj_t)&mp_builtin_len_obj },
- { MP_QSTR_max, (mp_obj_t)&mp_builtin_max_obj },
- { MP_QSTR_min, (mp_obj_t)&mp_builtin_min_obj },
- { MP_QSTR_next, (mp_obj_t)&mp_builtin_next_obj },
- { MP_QSTR_ord, (mp_obj_t)&mp_builtin_ord_obj },
- { MP_QSTR_pow, (mp_obj_t)&mp_builtin_pow_obj },
- { MP_QSTR_print, (mp_obj_t)&mp_builtin_print_obj },
- { MP_QSTR_range, (mp_obj_t)&mp_builtin_range_obj },
- { MP_QSTR_repr, (mp_obj_t)&mp_builtin_repr_obj },
- { MP_QSTR_sorted, (mp_obj_t)&mp_builtin_sorted_obj },
- { MP_QSTR_sum, (mp_obj_t)&mp_builtin_sum_obj },
- { MP_QSTR_bytearray, (mp_obj_t)&mp_builtin_bytearray_obj },
-
- // built-in exceptions
- { MP_QSTR_BaseException, (mp_obj_t)&mp_type_BaseException },
- { MP_QSTR_ArithmeticError, (mp_obj_t)&mp_type_ArithmeticError },
- { MP_QSTR_AssertionError, (mp_obj_t)&mp_type_AssertionError },
- { MP_QSTR_AttributeError, (mp_obj_t)&mp_type_AttributeError },
- { MP_QSTR_BufferError, (mp_obj_t)&mp_type_BufferError },
- { MP_QSTR_EOFError, (mp_obj_t)&mp_type_EOFError },
- { MP_QSTR_EnvironmentError, (mp_obj_t)&mp_type_EnvironmentError },
- { MP_QSTR_Exception, (mp_obj_t)&mp_type_Exception },
- { MP_QSTR_FloatingPointError, (mp_obj_t)&mp_type_FloatingPointError },
- { MP_QSTR_GeneratorExit, (mp_obj_t)&mp_type_GeneratorExit },
- { MP_QSTR_IOError, (mp_obj_t)&mp_type_IOError },
- { MP_QSTR_ImportError, (mp_obj_t)&mp_type_ImportError },
- { MP_QSTR_IndentationError, (mp_obj_t)&mp_type_IndentationError },
- { MP_QSTR_IndexError, (mp_obj_t)&mp_type_IndexError },
- { MP_QSTR_KeyError, (mp_obj_t)&mp_type_KeyError },
- { MP_QSTR_LookupError, (mp_obj_t)&mp_type_LookupError },
- { MP_QSTR_MemoryError, (mp_obj_t)&mp_type_MemoryError },
- { MP_QSTR_NameError, (mp_obj_t)&mp_type_NameError },
- { MP_QSTR_NotImplementedError, (mp_obj_t)&mp_type_NotImplementedError },
- { MP_QSTR_OSError, (mp_obj_t)&mp_type_OSError },
- { MP_QSTR_OverflowError, (mp_obj_t)&mp_type_OverflowError },
- { MP_QSTR_ReferenceError, (mp_obj_t)&mp_type_ReferenceError },
- { MP_QSTR_RuntimeError, (mp_obj_t)&mp_type_RuntimeError },
- { MP_QSTR_SyntaxError, (mp_obj_t)&mp_type_SyntaxError },
- { MP_QSTR_SystemError, (mp_obj_t)&mp_type_SystemError },
- { MP_QSTR_SystemExit, (mp_obj_t)&mp_type_SystemExit },
- { MP_QSTR_TabError, (mp_obj_t)&mp_type_TabError },
- { MP_QSTR_TypeError, (mp_obj_t)&mp_type_TypeError },
- { MP_QSTR_UnboundLocalError, (mp_obj_t)&mp_type_UnboundLocalError },
- { MP_QSTR_ValueError, (mp_obj_t)&mp_type_ValueError },
- { MP_QSTR_ZeroDivisionError, (mp_obj_t)&mp_type_ZeroDivisionError },
- { MP_QSTR_StopIteration, (mp_obj_t)&mp_type_StopIteration },
- // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/
- // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation
-
- // Extra builtins as defined by a port
- MICROPY_EXTRA_BUILTINS
-
- { MP_QSTR_, MP_OBJ_NULL }, // end of list sentinel
-};
-
// a good optimising compiler will inline this if necessary
STATIC void mp_map_add_qstr(mp_map_t *map, qstr qstr, mp_obj_t value) {
mp_map_lookup(map, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
@@ -193,23 +80,17 @@ STATIC void mp_map_add_qstr(mp_map_t *map, qstr qstr, mp_obj_t value) {
void rt_init(void) {
// locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
map_locals = map_globals = mp_map_new(1);
- mp_map_add_qstr(map_globals, MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR___main__));
// init built-in hash table
mp_map_init(&map_builtins, 3);
- // init loaded modules table
- mp_map_init(&map_loaded_modules, 3);
+ // init global module stuff
+ mp_module_init();
- // built-in objects
+ // add some builtins that can't be done in ROM
+ mp_map_add_qstr(map_globals, MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR___main__));
mp_map_add_qstr(&map_builtins, MP_QSTR_Ellipsis, mp_const_ellipsis);
- mp_obj_t m_array = mp_obj_new_module(MP_QSTR_array);
- rt_store_attr(m_array, MP_QSTR_array, (mp_obj_t)&array_type);
-
- mp_obj_t m_collections = mp_obj_new_module(MP_QSTR_collections);
- rt_store_attr(m_collections, MP_QSTR_namedtuple, (mp_obj_t)&mp_namedtuple_obj);
-
#if MICROPY_CPYTHON_COMPAT
// Precreate sys module, so "import sys" didn't throw exceptions.
mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys);
@@ -221,10 +102,6 @@ void rt_init(void) {
//sys_path = mp_obj_new_list(0, NULL);
//rt_store_attr(m_sys, MP_QSTR_path, sys_path);
- // we pre-import the micropython module
- // probably shouldn't do this, so we are compatible with CPython
- rt_store_name(MP_QSTR_micropython, (mp_obj_t)&mp_module_micropython);
-
// TODO: wastes one mp_code_t structure in mem
next_unique_code_id = 1; // 0 indicates "no code"
unique_codes_alloc = 0;
@@ -238,8 +115,8 @@ void rt_init(void) {
void rt_deinit(void) {
m_del(mp_code_t, unique_codes, unique_codes_alloc);
mp_map_free(map_globals);
- mp_map_deinit(&map_loaded_modules);
mp_map_deinit(&map_builtins);
+ mp_module_deinit();
#ifdef WRITE_CODE
if (fp_write_code != NULL) {
fclose(fp_write_code);
@@ -428,10 +305,9 @@ mp_obj_t rt_load_global(qstr qstr) {
if (elem == NULL) {
elem = mp_map_lookup(&map_builtins, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
if (elem == NULL) {
- for (const mp_builtin_elem_t *e = &builtin_table[0]; e->qstr != MP_QSTR_; e++) {
- if (e->qstr == qstr) {
- return e->fun;
- }
+ mp_obj_t o = mp_builtin_tables_lookup_object(qstr);
+ if (o != MP_OBJ_NULL) {
+ return o;
}
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_NameError, "name '%s' is not defined", qstr_str(qstr)));
}
@@ -441,10 +317,13 @@ mp_obj_t rt_load_global(qstr qstr) {
mp_obj_t rt_load_build_class(void) {
DEBUG_OP_printf("load_build_class\n");
+ // lookup __build_class__ in dynamic table of builtins first
mp_map_elem_t *elem = mp_map_lookup(&map_builtins, MP_OBJ_NEW_QSTR(MP_QSTR___build_class__), MP_MAP_LOOKUP);
if (elem != NULL) {
+ // found user-defined __build_class__, return it
return elem->value;
} else {
+ // no user-defined __build_class__, return builtin one
return (mp_obj_t)&mp_builtin___build_class___obj;
}
}
@@ -462,6 +341,11 @@ void rt_store_name(qstr qstr, mp_obj_t obj) {
mp_map_lookup(map_locals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = obj;
}
+void rt_delete_name(qstr qstr) {
+ DEBUG_OP_printf("delete name %s\n", qstr_str(qstr));
+ mp_map_lookup(map_locals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
+}
+
void rt_store_global(qstr qstr, mp_obj_t obj) {
DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj);
mp_map_lookup(map_globals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = obj;
@@ -996,7 +880,8 @@ void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
// no attribute/method called attr
// following CPython, we give a more detailed error message for type objects
if (MP_OBJ_IS_TYPE(base, &mp_type_type)) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "type object '%s' has no attribute '%s'", ((mp_obj_type_t*)base)->name, qstr_str(attr)));
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,
+ "type object '%s' has no attribute '%s'", qstr_str(((mp_obj_type_t*)base)->name), qstr_str(attr)));
} else {
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
}
@@ -1040,15 +925,21 @@ mp_obj_t rt_getiter(mp_obj_t o_in) {
if (type->getiter != NULL) {
return type->getiter(o_in);
} else {
- // check for __getitem__ method
+ // check for __iter__ method
mp_obj_t dest[2];
- rt_load_method_maybe(o_in, MP_QSTR___getitem__, dest);
+ rt_load_method_maybe(o_in, MP_QSTR___iter__, dest);
if (dest[0] != MP_OBJ_NULL) {
- // __getitem__ exists, create an iterator
- return mp_obj_new_getitem_iter(dest);
+ // __iter__ exists, call it and return its result
+ return rt_call_method_n_kw(0, 0, dest);
} else {
- // object not iterable
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(o_in)));
+ rt_load_method_maybe(o_in, MP_QSTR___getitem__, dest);
+ if (dest[0] != MP_OBJ_NULL) {
+ // __getitem__ exists, create an iterator
+ return mp_obj_new_getitem_iter(dest);
+ } else {
+ // object not iterable
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(o_in)));
+ }
}
}
}
@@ -1058,7 +949,15 @@ mp_obj_t rt_iternext(mp_obj_t o_in) {
if (type->iternext != NULL) {
return type->iternext(o_in);
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
+ // check for __next__ method
+ mp_obj_t dest[2];
+ rt_load_method_maybe(o_in, MP_QSTR___next__, dest);
+ if (dest[0] != MP_OBJ_NULL) {
+ // __next__ exists, call it and return its result
+ return rt_call_method_n_kw(0, 0, dest);
+ } else {
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
+ }
}
}
@@ -1135,10 +1034,6 @@ void rt_globals_set(mp_map_t *m) {
map_globals = m;
}
-mp_map_t *rt_loaded_modules_get(void) {
- return &map_loaded_modules;
-}
-
// these must correspond to the respective enum
void *const rt_fun_table[RT_F_NUMBER_OF] = {
rt_load_const_dec,
diff --git a/py/runtime.h b/py/runtime.h
index 7215cc8890..3980e50cc0 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -12,6 +12,7 @@ mp_obj_t rt_get_cell(mp_obj_t cell);
void rt_set_cell(mp_obj_t cell, mp_obj_t val);
void rt_store_name(qstr qstr, mp_obj_t obj);
void rt_store_global(qstr qstr, mp_obj_t obj);
+void rt_delete_name(qstr qstr);
mp_obj_t rt_unary_op(int op, mp_obj_t arg);
mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t rt_make_function_from_id(int unique_code_id, mp_obj_t def_args);
diff --git a/py/vm.c b/py/vm.c
index 48c4bdf04b..8ae619f9be 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -124,6 +124,7 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
// outer exception handling loop
for (;;) {
+outer_dispatch_loop:
if (nlr_push(&nlr) == 0) {
// If we have exception to inject, now that we finish setting up
// execution context, raise it. This works as if RAISE_VARARGS
@@ -283,6 +284,11 @@ dispatch_loop:
sp -= 3;
break;
+ case MP_BC_DELETE_NAME:
+ DECODE_QSTR;
+ rt_delete_name(qst);
+ break;
+
case MP_BC_DUP_TOP:
obj1 = TOP();
PUSH(obj1);
@@ -637,6 +643,15 @@ unwind_return:
} else {
// exception occurred
+ // check if it's a StopIteration within a for block
+ if (*save_ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
+ ip = save_ip + 1;
+ DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
+ --sp; // pop the exhausted iterator
+ ip += unum; // jump to after for-block
+ goto outer_dispatch_loop; // continue with dispatch loop
+ }
+
// set file and line number that the exception occurred at
// TODO: don't set traceback for exceptions re-raised by END_FINALLY.
// But consider how to handle nested exceptions.
diff --git a/stm/main.c b/stm/main.c
index 8279a9b7f4..44be4d348c 100644
--- a/stm/main.c
+++ b/stm/main.c
@@ -24,6 +24,7 @@
#include "lexerfatfs.h"
#include "parse.h"
#include "obj.h"
+#include "objmodule.h"
#include "parsehelper.h"
#include "compile.h"
#include "runtime0.h"
@@ -272,9 +273,8 @@ soft_reset:
rt_store_name(MP_QSTR_help, rt_make_function_n(0, pyb_help));
rt_store_name(MP_QSTR_open, rt_make_function_n(2, pyb_io_open));
- // we pre-import the pyb module
- // probably shouldn't do this, so we are compatible with CPython
- rt_store_name(MP_QSTR_pyb, (mp_obj_t)&pyb_module);
+ // load the pyb module
+ mp_module_register(MP_QSTR_pyb, (mp_obj_t)&pyb_module);
// check if user switch held (initiates reset of filesystem)
bool reset_filesystem = false;
diff --git a/stm/pybmodule.c b/stm/pybmodule.c
index ed705af73d..fde61b513d 100644
--- a/stm/pybmodule.c
+++ b/stm/pybmodule.c
@@ -181,7 +181,8 @@ STATIC mp_obj_t pyb_standby(void) {
MP_DEFINE_CONST_FUN_OBJ_0(pyb_standby_obj, pyb_standby);
STATIC mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
- mp_obj_t *items = mp_obj_get_array_fixed_n(arg, 4);
+ mp_obj_t *items;
+ mp_obj_get_array_fixed_n(arg, 4, &items);
uint8_t data[4];
data[0] = mp_obj_get_int(items[0]);
data[1] = mp_obj_get_int(items[1]);
diff --git a/stmhal/Makefile b/stmhal/Makefile
index 292bfdd61c..bf5db71867 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -72,10 +72,11 @@ SRC_C = \
malloc0.c \
gccollect.c \
pyexec.c \
+ help.c \
input.c \
- pybmodule.c \
- osmodule.c \
- timemodule.c \
+ modpyb.c \
+ modos.c \
+ modtime.c \
import.c \
lexerfatfs.c \
gpio.c \
@@ -91,11 +92,11 @@ SRC_C = \
lcd.c \
accel.c \
servo.c \
+ dac.c \
+ adc.c \
+ i2c.c \
# timer.c \
-# audio.c \
-# i2c.c \
-# adc.c \
# pybwlan.c \
SRC_S = \
@@ -104,7 +105,11 @@ SRC_S = \
SRC_HAL = $(addprefix $(HAL_DIR)/src/,\
stm32f4xx_hal.c \
+ stm32f4xx_hal_adc.c \
+ stm32f4xx_hal_adc_ex.c \
stm32f4xx_hal_cortex.c \
+ stm32f4xx_hal_dac.c \
+ stm32f4xx_hal_dac_ex.c \
stm32f4xx_hal_dma.c \
stm32f4xx_hal_flash.c \
stm32f4xx_hal_flash_ex.c \
diff --git a/stmhal/accel.c b/stmhal/accel.c
index cd513b3fe8..f791691619 100644
--- a/stmhal/accel.c
+++ b/stmhal/accel.c
@@ -3,11 +3,13 @@
#include <stm32f4xx_hal.h>
+#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
+#include "i2c.h"
#include "accel.h"
#define MMA_ADDR (0x98)
@@ -18,8 +20,6 @@
#define MMA_REG_MODE (7)
#define MMA_AXIS_SIGNED_VALUE(i) (((i) & 0x3f) | ((i) & 0x20 ? (~0x1f) : 0))
-STATIC I2C_HandleTypeDef I2cHandle;
-
void accel_init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
@@ -30,38 +30,12 @@ void accel_init(void) {
GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
GPIO_InitStructure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- // PB6=SCL, PB7=SDA
- GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
- GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
- GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
- GPIO_InitStructure.Pull = GPIO_NOPULL; // have external pull-up resistors on both lines
- GPIO_InitStructure.Alternate = GPIO_AF4_I2C1;
- HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- // enable the I2C1 clock
- __I2C1_CLK_ENABLE();
-
- // set up the I2C1 device
- memset(&I2cHandle, 0, sizeof(I2C_HandleTypeDef));
- I2cHandle.Instance = I2C1;
- I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
- I2cHandle.Init.ClockSpeed = 400000;
- I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
- I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9;
- I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
- I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
- I2cHandle.Init.OwnAddress1 = 0xfe; // unused
- I2cHandle.Init.OwnAddress2 = 0xfe; // unused
-
- if (HAL_I2C_Init(&I2cHandle) != HAL_OK) {
- // init error
- printf("accel_init: HAL_I2C_Init failed\n");
- return;
- }
}
-STATIC void accel_init_device(void) {
+STATIC void accel_start(void) {
+ // start the I2C bus
+ i2c_start(&I2cHandle_X);
+
// turn off AVDD, wait 20ms, turn on AVDD, wait 20ms again
GPIOB->BSRRH = GPIO_PIN_5; // turn off
HAL_Delay(20);
@@ -72,7 +46,7 @@ STATIC void accel_init_device(void) {
//printf("IsDeviceReady\n");
for (int i = 0; i < 10; i++) {
- status = HAL_I2C_IsDeviceReady(&I2cHandle, MMA_ADDR, 10, 200);
+ status = HAL_I2C_IsDeviceReady(&I2cHandle_X, MMA_ADDR, 10, 200);
//printf(" got %d\n", status);
if (status == HAL_OK) {
break;
@@ -82,7 +56,7 @@ STATIC void accel_init_device(void) {
//printf("MemWrite\n");
uint8_t data[1];
data[0] = 1; // active mode
- status = HAL_I2C_Mem_Write(&I2cHandle, MMA_ADDR, MMA_REG_MODE, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
+ status = HAL_I2C_Mem_Write(&I2cHandle_X, MMA_ADDR, MMA_REG_MODE, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
//printf(" got %d\n", status);
}
@@ -99,9 +73,22 @@ typedef struct _pyb_accel_obj_t {
STATIC pyb_accel_obj_t pyb_accel_obj;
+STATIC mp_obj_t pyb_accel_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+ // check arguments
+ if (!(n_args == 0 && n_kw == 0)) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Accel accepts no arguments"));
+ }
+
+ // init accel object
+ pyb_accel_obj.base.type = &pyb_accel_type;
+ accel_start();
+
+ return &pyb_accel_obj;
+}
+
STATIC mp_obj_t read_axis(int axis) {
uint8_t data[1];
- HAL_I2C_Mem_Read(&I2cHandle, MMA_ADDR, axis, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
+ HAL_I2C_Mem_Read(&I2cHandle_X, MMA_ADDR, axis, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
return mp_obj_new_int(MMA_AXIS_SIGNED_VALUE(data[0]));
}
@@ -125,7 +112,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_z_obj, pyb_accel_z);
STATIC mp_obj_t pyb_accel_tilt(mp_obj_t self_in) {
uint8_t data[1];
- HAL_I2C_Mem_Read(&I2cHandle, MMA_ADDR, MMA_REG_TILT, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
+ HAL_I2C_Mem_Read(&I2cHandle_X, MMA_ADDR, MMA_REG_TILT, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
return mp_obj_new_int(data[0]);
}
@@ -137,7 +124,7 @@ STATIC mp_obj_t pyb_accel_filtered_xyz(mp_obj_t self_in) {
memmove(self->buf, self->buf + NUM_AXIS, NUM_AXIS * (FILT_DEPTH - 1) * sizeof(int16_t));
uint8_t data[NUM_AXIS];
- HAL_I2C_Mem_Read(&I2cHandle, MMA_ADDR, MMA_REG_X, I2C_MEMADD_SIZE_8BIT, data, NUM_AXIS, 200);
+ HAL_I2C_Mem_Read(&I2cHandle_X, MMA_ADDR, MMA_REG_X, I2C_MEMADD_SIZE_8BIT, data, NUM_AXIS, 200);
mp_obj_t tuple[NUM_AXIS];
for (int i = 0; i < NUM_AXIS; i++) {
@@ -156,7 +143,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_filtered_xyz_obj, pyb_accel_filtered_
STATIC mp_obj_t pyb_accel_read_reg(mp_obj_t self_in, mp_obj_t reg) {
uint8_t data[1];
- HAL_I2C_Mem_Read(&I2cHandle, MMA_ADDR, mp_obj_get_int(reg), I2C_MEMADD_SIZE_8BIT, data, 1, 200);
+ HAL_I2C_Mem_Read(&I2cHandle_X, MMA_ADDR, mp_obj_get_int(reg), I2C_MEMADD_SIZE_8BIT, data, 1, 200);
return mp_obj_new_int(data[0]);
}
@@ -165,13 +152,13 @@ MP_DEFINE_CONST_FUN_OBJ_2(pyb_accel_read_reg_obj, pyb_accel_read_reg);
STATIC mp_obj_t pyb_accel_write_reg(mp_obj_t self_in, mp_obj_t reg, mp_obj_t val) {
uint8_t data[1];
data[0] = mp_obj_get_int(val);
- HAL_I2C_Mem_Write(&I2cHandle, MMA_ADDR, mp_obj_get_int(reg), I2C_MEMADD_SIZE_8BIT, data, 1, 200);
+ HAL_I2C_Mem_Write(&I2cHandle_X, MMA_ADDR, mp_obj_get_int(reg), I2C_MEMADD_SIZE_8BIT, data, 1, 200);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(pyb_accel_write_reg_obj, pyb_accel_write_reg);
-STATIC const mp_method_t accel_methods[] = {
+STATIC const mp_method_t pyb_accel_methods[] = {
{ "x", &pyb_accel_x_obj },
{ "y", &pyb_accel_y_obj },
{ "z", &pyb_accel_z_obj },
@@ -182,16 +169,9 @@ STATIC const mp_method_t accel_methods[] = {
{ NULL, NULL },
};
-STATIC const mp_obj_type_t accel_obj_type = {
+const mp_obj_type_t pyb_accel_type = {
{ &mp_type_type },
.name = MP_QSTR_Accel,
- .methods = accel_methods,
+ .make_new = pyb_accel_make_new,
+ .methods = pyb_accel_methods,
};
-
-STATIC mp_obj_t pyb_Accel(void) {
- pyb_accel_obj.base.type = &accel_obj_type;
- accel_init_device();
- return &pyb_accel_obj;
-}
-
-MP_DEFINE_CONST_FUN_OBJ_0(pyb_Accel_obj, pyb_Accel);
diff --git a/stmhal/accel.h b/stmhal/accel.h
index b2c0fd6b19..cfc54fcf67 100644
--- a/stmhal/accel.h
+++ b/stmhal/accel.h
@@ -1,3 +1,3 @@
-void accel_init(void);
+extern const mp_obj_type_t pyb_accel_type;
-MP_DECLARE_CONST_FUN_OBJ(pyb_Accel_obj);
+void accel_init(void);
diff --git a/stmhal/adc.c b/stmhal/adc.c
new file mode 100644
index 0000000000..e357a00308
--- /dev/null
+++ b/stmhal/adc.c
@@ -0,0 +1,345 @@
+#include <stdio.h>
+#include <stm32f4xx_hal.h>
+#include <string.h>
+
+#include "misc.h"
+#include "nlr.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "adc.h"
+#include "pin.h"
+#include "build/pins.h"
+
+// Usage Model:
+//
+// adc = pyb.ADC(pin)
+// val = adc.read()
+//
+// adc = pyb.ADC_all(resolution)
+// val = adc.read_channel(channel)
+// val = adc.read_core_temp()
+// val = adc.read_core_vbat()
+// val = adc.read_core_vref()
+
+/* ADC defintions */
+#define ADCx (ADC1)
+#define ADCx_CLK_ENABLE __ADC1_CLK_ENABLE
+#define ADC_NUM_CHANNELS (19)
+#define ADC_NUM_GPIO_CHANNELS (16)
+
+#if defined(STM32F405xx) || defined(STM32F415xx) || \
+ defined(STM32F407xx) || defined(STM32F417xx) || \
+ defined(STM32F401xC) || defined(STM32F401xE)
+#define VBAT_DIV (2)
+#elif defined(STM32F427xx) || defined(STM32F429xx) || \
+ defined(STM32F437xx) || defined(STM32F439xx)
+#define VBAT_DIV (4)
+#endif
+
+/* Core temperature sensor definitions */
+#define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resoultion) */
+#define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resoultion) */
+
+typedef struct _pyb_obj_adc_t {
+ mp_obj_base_t base;
+ mp_obj_t pin_name;
+ int channel;
+ ADC_HandleTypeDef handle;
+} pyb_obj_adc_t;
+
+void adc_init_single(pyb_obj_adc_t *adc_obj) {
+ if (!IS_ADC_CHANNEL(adc_obj->channel)) {
+ return;
+ }
+
+ if (adc_obj->channel < ADC_NUM_GPIO_CHANNELS) {
+ // Channels 0-16 correspond to real pins. Configure the GPIO pin in
+ // ADC mode.
+ const pin_obj_t *pin = pin_adc1[adc_obj->channel];
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.Pin = pin->pin_mask;
+ GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(pin->gpio, &GPIO_InitStructure);
+ }
+
+ ADCx_CLK_ENABLE();
+
+ ADC_HandleTypeDef *adcHandle = &adc_obj->handle;
+ adcHandle->Instance = ADCx;
+ adcHandle->Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
+ adcHandle->Init.Resolution = ADC_RESOLUTION12b;
+ adcHandle->Init.ScanConvMode = DISABLE;
+ adcHandle->Init.ContinuousConvMode = DISABLE;
+ adcHandle->Init.DiscontinuousConvMode = DISABLE;
+ adcHandle->Init.NbrOfDiscConversion = 0;
+ adcHandle->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
+ adcHandle->Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
+ adcHandle->Init.DataAlign = ADC_DATAALIGN_RIGHT;
+ adcHandle->Init.NbrOfConversion = 1;
+ adcHandle->Init.DMAContinuousRequests = DISABLE;
+ adcHandle->Init.EOCSelection = DISABLE;
+
+ HAL_ADC_Init(adcHandle);
+
+ ADC_ChannelConfTypeDef sConfig;
+
+ sConfig.Channel = adc_obj->channel;
+ sConfig.Rank = 1;
+ sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
+ sConfig.Offset = 0;
+
+ HAL_ADC_ConfigChannel(adcHandle, &sConfig);
+}
+
+uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) {
+ uint32_t rawValue = 0;
+
+ HAL_ADC_Start(adcHandle);
+ if (HAL_ADC_PollForConversion(adcHandle, 10) == HAL_OK && HAL_ADC_GetState(adcHandle) == HAL_ADC_STATE_EOC_REG) {
+ rawValue = HAL_ADC_GetValue(adcHandle);
+ }
+ HAL_ADC_Stop(adcHandle);
+
+ return rawValue;
+}
+
+/******************************************************************************/
+/* Micro Python bindings : adc object (single channel) */
+
+STATIC void adc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ pyb_obj_adc_t *self = self_in;
+ print(env, "<ADC on ");
+ mp_obj_print_helper(print, env, self->pin_name, PRINT_STR);
+ print(env, " channel=%lu>", self->channel);
+}
+
+STATIC mp_obj_t adc_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+ // check number of arguments
+ if (!(n_args == 1 && n_kw == 0)) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "ADC accepts 1 argument"));
+ }
+
+ // 1st argument is the pin name
+ mp_obj_t pin_obj = args[0];
+
+ uint32_t channel;
+
+ if (MP_OBJ_IS_INT(pin_obj)) {
+ channel = mp_obj_get_int(pin_obj);
+ } else {
+ const pin_obj_t *pin = pin_map_user_obj(pin_obj);
+ if ((pin->adc_num & PIN_ADC1) == 0) {
+ // No ADC1 function on that pin
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not have ADC capabilities", pin->name));
+ }
+ channel = pin->adc_channel;
+ }
+
+ if (!IS_ADC_CHANNEL(channel)) {
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Not a valid ADC Channel: %d", channel));
+ }
+ if (pin_adc1[channel] == NULL) {
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Channel %d not available on this board", channel));
+ }
+
+ pyb_obj_adc_t *o = m_new_obj(pyb_obj_adc_t);
+ memset(o, 0, sizeof(*o));
+ o->base.type = &pyb_adc_type;
+ o->pin_name = pin_obj;
+ o->channel = channel;
+ adc_init_single(o);
+
+ return o;
+}
+
+STATIC mp_obj_t adc_read(mp_obj_t self_in) {
+ pyb_obj_adc_t *self = self_in;
+
+ uint32_t data = adc_read_channel(&self->handle);
+ return mp_obj_new_int(data);
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read);
+
+STATIC const mp_method_t adc_methods[] = {
+ { "read", &adc_read_obj},
+ { NULL, NULL },
+};
+
+const mp_obj_type_t pyb_adc_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_ADC,
+ .print = adc_print,
+ .make_new = adc_make_new,
+ .methods = adc_methods,
+};
+
+/******************************************************************************/
+/* adc all object */
+
+typedef struct _pyb_obj_adc_all_t {
+ mp_obj_base_t base;
+ ADC_HandleTypeDef handle;
+} pyb_obj_adc_all_t;
+
+void adc_init_all(pyb_obj_adc_all_t *adc_all, uint32_t resolution) {
+
+ switch (resolution) {
+ case 6: resolution = ADC_RESOLUTION6b; break;
+ case 8: resolution = ADC_RESOLUTION8b; break;
+ case 10: resolution = ADC_RESOLUTION10b; break;
+ case 12: resolution = ADC_RESOLUTION12b; break;
+ default:
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ "resolution %d not supported", resolution));
+ }
+
+ for (uint32_t channel = 0; channel < ADC_NUM_GPIO_CHANNELS; channel++) {
+ // Channels 0-16 correspond to real pins. Configure the GPIO pin in
+ // ADC mode.
+ const pin_obj_t *pin = pin_adc1[channel];
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.Pin = pin->pin_mask;
+ GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(pin->gpio, &GPIO_InitStructure);
+ }
+
+ ADCx_CLK_ENABLE();
+
+ ADC_HandleTypeDef *adcHandle = &adc_all->handle;
+ adcHandle->Instance = ADCx;
+ adcHandle->Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
+ adcHandle->Init.Resolution = resolution;
+ adcHandle->Init.ScanConvMode = DISABLE;
+ adcHandle->Init.ContinuousConvMode = DISABLE;
+ adcHandle->Init.DiscontinuousConvMode = DISABLE;
+ adcHandle->Init.NbrOfDiscConversion = 0;
+ adcHandle->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
+ adcHandle->Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
+ adcHandle->Init.DataAlign = ADC_DATAALIGN_RIGHT;
+ adcHandle->Init.NbrOfConversion = 1;
+ adcHandle->Init.DMAContinuousRequests = DISABLE;
+ adcHandle->Init.EOCSelection = DISABLE;
+
+ HAL_ADC_Init(adcHandle);
+}
+
+uint32_t adc_config_and_read_channel(ADC_HandleTypeDef *adcHandle, uint32_t channel) {
+ ADC_ChannelConfTypeDef sConfig;
+ sConfig.Channel = channel;
+ sConfig.Rank = 1;
+ sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
+ sConfig.Offset = 0;
+ HAL_ADC_ConfigChannel(adcHandle, &sConfig);
+
+ return adc_read_channel(adcHandle);
+}
+
+int adc_get_resolution(ADC_HandleTypeDef *adcHandle) {
+ uint32_t res_reg = __HAL_ADC_GET_RESOLUTION(adcHandle);
+
+ switch (res_reg) {
+ case ADC_RESOLUTION6b: return 6;
+ case ADC_RESOLUTION8b: return 8;
+ case ADC_RESOLUTION10b: return 10;
+ }
+ return 12;
+}
+
+int adc_read_core_temp(ADC_HandleTypeDef *adcHandle) {
+ int32_t raw_value = adc_config_and_read_channel(adcHandle, ADC_CHANNEL_TEMPSENSOR);
+
+ // Note: constants assume 12-bit resolution, so we scale the raw value to
+ // be 12-bits.
+ raw_value <<= (12 - adc_get_resolution(adcHandle));
+
+ return ((raw_value - CORE_TEMP_V25) / CORE_TEMP_AVG_SLOPE) + 25;
+}
+
+float adc_read_core_vbat(ADC_HandleTypeDef *adcHandle) {
+ uint32_t raw_value = adc_config_and_read_channel(adcHandle, ADC_CHANNEL_VBAT);
+
+ // Note: constants assume 12-bit resolution, so we scale the raw value to
+ // be 12-bits.
+ raw_value <<= (12 - adc_get_resolution(adcHandle));
+
+ return raw_value * VBAT_DIV / 4096.0f * 3.3f;
+}
+
+float adc_read_core_vref(ADC_HandleTypeDef *adcHandle) {
+ uint32_t raw_value = adc_config_and_read_channel(adcHandle, ADC_CHANNEL_VREFINT);
+
+ // Note: constants assume 12-bit resolution, so we scale the raw value to
+ // be 12-bits.
+ raw_value <<= (12 - adc_get_resolution(adcHandle));
+
+ return raw_value * VBAT_DIV / 4096.0f * 3.3f;
+}
+
+/******************************************************************************/
+/* Micro Python bindings : adc_all object */
+
+STATIC void adc_all_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ print(env, "<ADC all>");
+}
+
+STATIC mp_obj_t adc_all_read_channel(mp_obj_t self_in, mp_obj_t channel) {
+ pyb_obj_adc_all_t *self = self_in;
+
+ uint32_t chan = mp_obj_get_int(channel);
+ uint32_t data = adc_config_and_read_channel(&self->handle, chan);
+ return mp_obj_new_int(data);
+}
+
+STATIC mp_obj_t adc_all_read_core_temp(mp_obj_t self_in) {
+ pyb_obj_adc_all_t *self = self_in;
+
+ int data = adc_read_core_temp(&self->handle);
+ return mp_obj_new_int(data);
+}
+
+STATIC mp_obj_t adc_all_read_core_vbat(mp_obj_t self_in) {
+ pyb_obj_adc_all_t *self = self_in;
+
+ float data = adc_read_core_vbat(&self->handle);
+ return mp_obj_new_float(data);
+}
+
+STATIC mp_obj_t adc_all_read_core_vref(mp_obj_t self_in) {
+ pyb_obj_adc_all_t *self = self_in;
+
+ float data = adc_read_core_vref(&self->handle);
+ return mp_obj_new_float(data);
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(adc_all_read_channel_obj, adc_all_read_channel);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_temp_obj, adc_all_read_core_temp);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_vbat_obj, adc_all_read_core_vbat);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_vref_obj, adc_all_read_core_vref);
+
+STATIC const mp_method_t adc_all_methods[] = {
+ { "read_channel", &adc_all_read_channel_obj},
+ { "read_core_temp", &adc_all_read_core_temp_obj},
+ { "read_core_vbat", &adc_all_read_core_vbat_obj},
+ { "read_core_vref", &adc_all_read_core_vref_obj},
+ { NULL, NULL },
+};
+
+STATIC const mp_obj_type_t adc_all_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_ADC,
+ .print = adc_all_print,
+ .methods = adc_all_methods,
+};
+
+STATIC mp_obj_t pyb_ADC_all(mp_obj_t resolution) {
+ pyb_obj_adc_all_t *o = m_new_obj(pyb_obj_adc_all_t);
+ o->base.type = &adc_all_type;
+ adc_init_all(o, mp_obj_get_int(resolution));
+ return o;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(pyb_ADC_all_obj, pyb_ADC_all);
diff --git a/stmhal/adc.h b/stmhal/adc.h
new file mode 100644
index 0000000000..c9f16932eb
--- /dev/null
+++ b/stmhal/adc.h
@@ -0,0 +1,3 @@
+extern const mp_obj_type_t pyb_adc_type;
+
+MP_DECLARE_CONST_FUN_OBJ(pyb_ADC_all_obj);
diff --git a/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h b/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h
index 412dede131..948b886819 100644
--- a/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h
+++ b/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h
@@ -16,7 +16,7 @@
#define MICROPY_HW_ENABLE_RTC (0)
#define MICROPY_HW_ENABLE_TIMER (1)
#define MICROPY_HW_ENABLE_SERVO (1)
-#define MICROPY_HW_ENABLE_AUDIO (0)
+#define MICROPY_HW_ENABLE_DAC (0)
// USRSW is pulled low. Pressing the button makes the input go high.
#define USRSW_PIN (pin_B11)
diff --git a/stmhal/boards/PYBOARD3/mpconfigboard.h b/stmhal/boards/PYBOARD3/mpconfigboard.h
index e0920f6859..1cd1d94818 100644
--- a/stmhal/boards/PYBOARD3/mpconfigboard.h
+++ b/stmhal/boards/PYBOARD3/mpconfigboard.h
@@ -12,7 +12,7 @@
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_TIMER (1)
#define MICROPY_HW_ENABLE_SERVO (1)
-#define MICROPY_HW_ENABLE_AUDIO (0)
+#define MICROPY_HW_ENABLE_DAC (0)
// USRSW has no pullup or pulldown, and pressing the switch makes the input go low
#define USRSW_PIN (pin_A13)
diff --git a/stmhal/boards/PYBOARD4/mpconfigboard.h b/stmhal/boards/PYBOARD4/mpconfigboard.h
index c3d5e119c9..9a046ffffa 100644
--- a/stmhal/boards/PYBOARD4/mpconfigboard.h
+++ b/stmhal/boards/PYBOARD4/mpconfigboard.h
@@ -12,7 +12,7 @@
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_TIMER (1)
#define MICROPY_HW_ENABLE_SERVO (1)
-#define MICROPY_HW_ENABLE_AUDIO (1)
+#define MICROPY_HW_ENABLE_DAC (1)
// USRSW has no pullup or pulldown, and pressing the switch makes the input go low
#define USRSW_PIN (pin_B3)
diff --git a/stmhal/boards/PYBv10/mpconfigboard.h b/stmhal/boards/PYBv10/mpconfigboard.h
index fba7ab4aba..f5ebe25cc4 100644
--- a/stmhal/boards/PYBv10/mpconfigboard.h
+++ b/stmhal/boards/PYBv10/mpconfigboard.h
@@ -12,7 +12,7 @@
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_TIMER (1)
#define MICROPY_HW_ENABLE_SERVO (1)
-#define MICROPY_HW_ENABLE_AUDIO (1)
+#define MICROPY_HW_ENABLE_DAC (1)
// USRSW has no pullup or pulldown, and pressing the switch makes the input go low
#define USRSW_PIN (pin_B3)
diff --git a/stmhal/boards/STM32F4DISC/mpconfigboard.h b/stmhal/boards/STM32F4DISC/mpconfigboard.h
index f713f9b756..2a58b27bdf 100644
--- a/stmhal/boards/STM32F4DISC/mpconfigboard.h
+++ b/stmhal/boards/STM32F4DISC/mpconfigboard.h
@@ -12,7 +12,7 @@
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_TIMER (1)
#define MICROPY_HW_ENABLE_SERVO (0)
-#define MICROPY_HW_ENABLE_AUDIO (0)
+#define MICROPY_HW_ENABLE_DAC (0)
// USRSW is pulled low. Pressing the button makes the input go high.
#define USRSW_PIN (pin_A0)
diff --git a/stmhal/boards/make-pins.py b/stmhal/boards/make-pins.py
index 8c1bedbf0c..ee11934985 100755
--- a/stmhal/boards/make-pins.py
+++ b/stmhal/boards/make-pins.py
@@ -94,6 +94,8 @@ class Pin(object):
self.alt_fn = []
self.board_name = None
self.alt_fn_count = 0
+ self.adc_num = 0
+ self.adc_channel = 0
def port_letter(self):
return chr(self.port + ord('A'))
@@ -101,6 +103,15 @@ class Pin(object):
def pin_name(self):
return '{:s}{:d}'.format(self.port_letter(), self.pin)
+ def parse_adc(self, adc_str):
+ if (adc_str[:3] != 'ADC'):
+ return
+ (adc,channel) = adc_str.split('_')
+ for idx in range(3, len(adc)):
+ adc_num = int(adc[idx]) # 1, 2, or 3
+ self.adc_num |= (1 << (adc_num - 1))
+ self.adc_channel = int(channel[2:])
+
def parse_af(self, af_idx, af_strs_in):
if len(af_strs_in) == 0:
return
@@ -113,10 +124,22 @@ class Pin(object):
if alt_fn.is_supported():
self.alt_fn_count += 1
- def alt_fn_name(self):
- if self.alt_fn_count > 0:
- return 'pin_{:s}_af'.format(self.pin_name())
- return 'NULL'
+ def alt_fn_name(self, null_if_0=False):
+ if null_if_0 and self.alt_fn_count == 0:
+ return 'NULL'
+ return 'pin_{:s}_af'.format(self.pin_name())
+
+ def adc_num_str(self):
+ str = ''
+ for adc_num in range(1,4):
+ if self.adc_num & (1 << (adc_num - 1)):
+ if len(str) > 0:
+ str += ' | '
+ str += 'PIN_ADC'
+ str += chr(ord('0') + adc_num)
+ if len(str) == 0:
+ str = '0'
+ return str
def print(self):
if self.alt_fn_count == 0:
@@ -128,9 +151,10 @@ class Pin(object):
print("// ", end='')
print('};')
print('')
- print('const pin_obj_t pin_{:s} = PIN({:s}, {:d}, {:d}, {:s});'.format(
+ print('const pin_obj_t pin_{:s} = PIN({:s}, {:d}, {:d}, {:s}, {:s}, {:d});'.format(
self.pin_name(), self.port_letter(), self.pin,
- self.alt_fn_count, self.alt_fn_name()))
+ self.alt_fn_count, self.alt_fn_name(null_if_0=True),
+ self.adc_num_str(), self.adc_channel))
print('')
def print_header(self, hdr_file):
@@ -162,7 +186,10 @@ class Pins(object):
continue
pin = Pin(port_num, pin_num)
for af_idx in range(af_col, len(row)):
- pin.parse_af(af_idx - af_col, row[af_idx])
+ if af_idx < af_col + 16:
+ pin.parse_af(af_idx - af_col, row[af_idx])
+ elif af_idx == af_col + 16:
+ pin.parse_adc(row[af_idx])
self.pins.append(pin)
def parse_board_file(self, filename):
@@ -198,11 +225,30 @@ class Pins(object):
print('')
self.print_named('board', self.board_pins)
+ def print_adc(self, adc_num):
+ print('');
+ print('const pin_obj_t * const pin_adc{:d}[] = {{'.format(adc_num))
+ for channel in range(16):
+ adc_found = False
+ for pin in self.pins:
+ if (pin.board_name and
+ (pin.adc_num & (1 << (adc_num - 1))) and (pin.adc_channel == channel)):
+ print(' &pin_{:s}, // {:d}'.format(pin.pin_name(), channel))
+ adc_found = True
+ break
+ if not adc_found:
+ print(' NULL, // {:d}'.format(channel))
+ print('};')
+
+
def print_header(self, hdr_filename):
with open(hdr_filename, 'wt') as hdr_file:
for pin in self.pins:
if pin.board_name:
pin.print_header(hdr_file)
+ hdr_file.write('extern const pin_obj_t * const pin_adc1[];\n')
+ hdr_file.write('extern const pin_obj_t * const pin_adc2[];\n')
+ hdr_file.write('extern const pin_obj_t * const pin_adc3[];\n')
def main():
@@ -254,6 +300,9 @@ def main():
with open(args.prefix_filename, 'r') as prefix_file:
print(prefix_file.read())
pins.print()
+ pins.print_adc(1)
+ pins.print_adc(2)
+ pins.print_adc(3)
pins.print_header(args.hdr_filename)
diff --git a/stmhal/boards/stm32f4xx-af.csv b/stmhal/boards/stm32f4xx-af.csv
index fde7fcfc11..0a21fc87d6 100644
--- a/stmhal/boards/stm32f4xx-af.csv
+++ b/stmhal/boards/stm32f4xx-af.csv
@@ -1,13 +1,13 @@
Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15
-,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11,I2C1/2/3,SPI1/SPI2/I2S2/I2S2ext,SPI3/I2Sext/I2S3,USART1/2/3/I2S3ext,UART4/5/USART6,CAN1/CAN2/TIM12/13/14,OTG_FS/OTG_HS,ETH,FSMC/SDIO/OTG_FS,DCMI,,
-PortA,PA0,,TIM2_CH1_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT
-PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII__REF_CLK,,,,EVENTOUT
-PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,ETH_MDIO,,,,EVENTOUT
-PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,,EVENTOUT
-PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,,EVENTOUT
-PortA,PA5,,TIM2_CH1_ETR,,TIM8_CH1N,,SPI1_SCK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT
-PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCK,,EVENTOUT
-PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,,,,EVENTOUT
+,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11,I2C1/2/3,SPI1/SPI2/I2S2/I2S2ext,SPI3/I2Sext/I2S3,USART1/2/3/I2S3ext,UART4/5/USART6,CAN1/CAN2/TIM12/13/14,OTG_FS/OTG_HS,ETH,FSMC/SDIO/OTG_FS,DCMI,,,ADC
+PortA,PA0,,TIM2_CH1_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT,ADC123_IN0
+PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII__REF_CLK,,,,EVENTOUT,ADC123_IN1
+PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,ETH_MDIO,,,,EVENTOUT,ADC123_IN2
+PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,,EVENTOUTADC123_IN3
+PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,,EVENTOUT,ADC12_IN4
+PortA,PA5,,TIM2_CH1_ETR,,TIM8_CH1N,,SPI1_SCK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT,ADC12_IN5
+PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCK,,EVENTOUT,ADC12_IN6
+PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,,,,EVENTOUT,ADC12_IN7
PortA,PA8,MCO1,TIM1_CH1,,,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,,EVENTOUT
PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,,,USART1_TX,,,,,,DCMI_D0,,EVENTOUT
PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT
@@ -16,8 +16,8 @@ PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT
PortA,PA13,JTMS-SWDIO,,,,,,,,,,,,,,,EVENTOUT
PortA,PA14,JTCK-SWCLK,,,,,,,,,,,,,,,EVENTOUT
PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,,,,,,,,,EVENTOUT
-PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,,,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT
-PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT
+PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,,,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT,AC12_IN8
+PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT,ADC12_IN9
PortB,PB2,,,,,,,,,,,,,,,,EVENTOUT
PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCKI2S3_CK,,,,,,,,,EVENTOUT
PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,I2S3ext_SD,,,,,,,,EVENTOUT
@@ -32,12 +32,12 @@ PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_UL
PortB,PB13,,TIM1_CH1N,,,,SPI2_SCKI2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT
PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,I2S2ext_SD,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT
PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT
-PortC,PC0,,,,,,,,,,,OTG_HS_ULPI_STP,,,,,EVENTOUT
-PortC,PC1,,,,,,,,,,,,ETH_MDC,,,,EVENTOUT
-PortC,PC2,,,,,,SPI2_MISO,I2S2ext_SD,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,,,,EVENTOUT
-PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,,,,EVENTOUT
-PortC,PC4,,,,,,,,,,,,ETH_MII_RXD0/ETH_RMII_RXD0,,,,EVENTOUT
-PortC,PC5,,,,,,,,,,,,ETH_MII_RXD1/ETH_RMII_RXD1,,,,EVENTOUT
+PortC,PC0,,,,,,,,,,,OTG_HS_ULPI_STP,,,,,EVENTOUT,ADC123_IN10
+PortC,PC1,,,,,,,,,,,,ETH_MDC,,,,EVENTOUT,ADC123_IN11
+PortC,PC2,,,,,,SPI2_MISO,I2S2ext_SD,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,,,,EVENTOUT,ADC123_IN12
+PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,,,,EVENTOUT,ADC123_IN13
+PortC,PC4,,,,,,,,,,,,ETH_MII_RXD0/ETH_RMII_RXD0,,,,EVENTOUT,ADC123_IN14
+PortC,PC5,,,,,,,,,,,,ETH_MII_RXD1/ETH_RMII_RXD1,,,,EVENTOUT,ADC123_IN15
PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,,,SDIO_D6,DCMI_D0,,EVENTOUT
PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,,,SDIO_D7,DCMI_D1,,EVENTOUT
PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,,USART6_CK,,,,SDIO_D0,DCMI_D2,,EVENTOUT
@@ -83,14 +83,14 @@ PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FSMC_D12,,,EVENTOUT
PortF,PF0,,,,,I2C2_SDA,,,,,,,,FSMC_A0,,,EVENTOUT
PortF,PF1,,,,,I2C2_SCL,,,,,,,,FSMC_A1,,,EVENTOUT
PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FSMC_A2,,,EVENTOUT
-PortF,PF3,,,,,,,,,,,,,FSMC_A3,,,EVENTOUT
-PortF,PF4,,,,,,,,,,,,,FSMC_A4,,,EVENTOUT
-PortF,PF5,,,,,,,,,,,,,FSMC_A5,,,EVENTOUT
-PortF,PF6,,,,TIM10_CH1,,,,,,,,,FSMC_NIORD,,,EVENTOUT
-PortF,PF7,,,,TIM11_CH1,,,,,,,,,FSMC_NREG,,,EVENTOUT
-PortF,PF8,,,,,,,,,,TIM13_CH1,,,FSMC_NIOWR,,,EVENTOUT
-PortF,PF9,,,,,,,,,,TIM14_CH1,,,FSMC_CD,,,EVENTOUT
-PortF,PF10,,,,,,,,,,,,,FSMC_INTR,,,EVENTOUT
+PortF,PF3,,,,,,,,,,,,,FSMC_A3,,,EVENTOUT,ADC3_IN9
+PortF,PF4,,,,,,,,,,,,,FSMC_A4,,,EVENTOUT,ADC3_IN14
+PortF,PF5,,,,,,,,,,,,,FSMC_A5,,,EVENTOUT,ADC3_IN15
+PortF,PF6,,,,TIM10_CH1,,,,,,,,,FSMC_NIORD,,,EVENTOUT,ADC3_IN4
+PortF,PF7,,,,TIM11_CH1,,,,,,,,,FSMC_NREG,,,EVENTOUT,ADC3_IN5
+PortF,PF8,,,,,,,,,,TIM13_CH1,,,FSMC_NIOWR,,,EVENTOUT,ADC3_IN6
+PortF,PF9,,,,,,,,,,TIM14_CH1,,,FSMC_CD,,,EVENTOUT,ADC3_IN7
+PortF,PF10,,,,,,,,,,,,,FSMC_INTR,,,EVENTOUT,ADC3_IN8
PortF,PF11,,,,,,,,,,,,,,DCMI_D12,,EVENTOUT
PortF,PF12,,,,,,,,,,,,,FSMC_A6,,,EVENTOUT
PortF,PF13,,,,,,,,,,,,,FSMC_A7,,,EVENTOUT
diff --git a/stmhal/boards/stm32f4xx-prefix.c b/stmhal/boards/stm32f4xx-prefix.c
index af3ed325cb..989b8f0048 100644
--- a/stmhal/boards/stm32f4xx-prefix.c
+++ b/stmhal/boards/stm32f4xx-prefix.c
@@ -21,7 +21,7 @@
.af_fn = (af_ptr) \
}
-#define PIN(p_port, p_pin, p_num_af, p_af) \
+#define PIN(p_port, p_pin, p_num_af, p_af, p_adc_num, p_adc_channel) \
{ \
{ &pin_obj_type }, \
.name = #p_port #p_pin, \
@@ -31,4 +31,6 @@
.pin_mask = (1 << ((p_pin) & 0x0f)), \
.gpio = GPIO ## p_port, \
.af = p_af, \
+ .adc_num = p_adc_num, \
+ .adc_channel = p_adc_channel, \
}
diff --git a/stmhal/dac.c b/stmhal/dac.c
new file mode 100644
index 0000000000..3814039ccd
--- /dev/null
+++ b/stmhal/dac.c
@@ -0,0 +1,279 @@
+#include <stdint.h>
+#include <string.h>
+
+#include "stm32f4xx_hal.h"
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "parse.h"
+#include "obj.h"
+#include "map.h"
+#include "runtime.h"
+#include "dac.h"
+
+TIM_HandleTypeDef TIM6_Handle;
+STATIC DAC_HandleTypeDef DAC_Handle;
+
+void dac_init(void) {
+ DAC_Handle.Instance = DAC;
+ DAC_Handle.State = HAL_DAC_STATE_RESET;
+ HAL_DAC_Init(&DAC_Handle);
+}
+
+STATIC void TIM6_Config(uint freq) {
+ // TIM6 clock enable
+ __TIM6_CLK_ENABLE();
+
+ // Compute the prescaler value so TIM6 triggers at freq-Hz
+ uint16_t period = (uint16_t) ((SystemCoreClock / 2) / freq) - 1;
+
+ // time base clock configuration
+ TIM6_Handle.Instance = TIM6;
+ TIM6_Handle.Init.Period = period;
+ TIM6_Handle.Init.Prescaler = 0; // timer runs at SystemCoreClock / 2
+ TIM6_Handle.Init.ClockDivision = 0; // unused for TIM6
+ TIM6_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; // unused for TIM6
+ HAL_TIM_Base_Init(&TIM6_Handle);
+
+ // TIM6 TRGO selection
+ TIM_MasterConfigTypeDef config;
+ config.MasterOutputTrigger = TIM_TRGO_UPDATE;
+ config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+ HAL_TIMEx_MasterConfigSynchronization(&TIM6_Handle, &config);
+
+ // TIM6 start counter
+ HAL_TIM_Base_Start(&TIM6_Handle);
+}
+
+/******************************************************************************/
+// Micro Python bindings
+
+typedef struct _pyb_dac_obj_t {
+ mp_obj_base_t base;
+ uint32_t dac_channel; // DAC_CHANNEL_1 or DAC_CHANNEL_2
+ DMA_Stream_TypeDef *dma_stream; // DMA1_Stream5 or DMA1_Stream6
+ machine_uint_t state;
+} pyb_dac_obj_t;
+
+STATIC pyb_dac_obj_t pyb_dac_channel_1 = {{&pyb_dac_type}, DAC_CHANNEL_1, DMA1_Stream5};
+STATIC pyb_dac_obj_t pyb_dac_channel_2 = {{&pyb_dac_type}, DAC_CHANNEL_2, DMA1_Stream6};
+
+// create the dac object
+// currently support either DAC1 on X5 (id = 1) or DAC2 on X6 (id = 2)
+
+STATIC mp_obj_t pyb_dac_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+ // check arguments
+ if (!(n_args == 1 && n_kw == 0)) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Dac accepts 1 argument"));
+ }
+
+ machine_int_t dac_id = mp_obj_get_int(args[0]);
+ uint32_t pin;
+ pyb_dac_obj_t *dac_obj;
+
+ if (dac_id == 1) {
+ pin = GPIO_PIN_4;
+ dac_obj = &pyb_dac_channel_1;
+ } else if (dac_id == 2) {
+ pin = GPIO_PIN_5;
+ dac_obj = &pyb_dac_channel_2;
+ } else {
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Dac %d does not exist", dac_id));
+ }
+
+ // GPIO configuration
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.Pin = pin;
+ GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+ // DAC peripheral clock
+ __DAC_CLK_ENABLE();
+
+ // stop anything already going on
+ HAL_DAC_Stop(&DAC_Handle, dac_obj->dac_channel);
+ HAL_DAC_Stop_DMA(&DAC_Handle, dac_obj->dac_channel);
+
+ dac_obj->state = 0;
+
+ // return object
+ return dac_obj;
+}
+
+STATIC mp_obj_t pyb_dac_noise(mp_obj_t self_in, mp_obj_t freq) {
+ pyb_dac_obj_t *self = self_in;
+
+ // set TIM6 to trigger the DAC at the given frequency
+ TIM6_Config(mp_obj_get_int(freq));
+
+ if (self->state != 2) {
+ // configure DAC to trigger via TIM6
+ DAC_ChannelConfTypeDef config;
+ config.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
+ config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
+ HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
+ self->state = 2;
+ }
+
+ // set noise wave generation
+ HAL_DACEx_NoiseWaveGenerate(&DAC_Handle, self->dac_channel, DAC_LFSRUNMASK_BITS10_0);
+ HAL_DAC_SetValue(&DAC_Handle, self->dac_channel, DAC_ALIGN_12B_L, 0x7ff0);
+ HAL_DAC_Start(&DAC_Handle, self->dac_channel);
+
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_noise_obj, pyb_dac_noise);
+
+STATIC mp_obj_t pyb_dac_triangle(mp_obj_t self_in, mp_obj_t freq) {
+ pyb_dac_obj_t *self = self_in;
+
+ // set TIM6 to trigger the DAC at the given frequency
+ TIM6_Config(mp_obj_get_int(freq));
+
+ if (self->state != 2) {
+ // configure DAC to trigger via TIM6
+ DAC_ChannelConfTypeDef config;
+ config.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
+ config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
+ HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
+ self->state = 2;
+ }
+
+ // set triangle wave generation
+ HAL_DACEx_TriangleWaveGenerate(&DAC_Handle, self->dac_channel, DAC_TRIANGLEAMPLITUDE_1023);
+ HAL_DAC_SetValue(&DAC_Handle, self->dac_channel, DAC_ALIGN_12B_R, 0x100);
+ HAL_DAC_Start(&DAC_Handle, self->dac_channel);
+
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_triangle_obj, pyb_dac_triangle);
+
+// direct access to DAC (8 bit only at the moment)
+STATIC mp_obj_t pyb_dac_write(mp_obj_t self_in, mp_obj_t val) {
+ pyb_dac_obj_t *self = self_in;
+
+ if (self->state != 1) {
+ DAC_ChannelConfTypeDef config;
+ config.DAC_Trigger = DAC_TRIGGER_NONE;
+ config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
+ HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
+ self->state = 1;
+ }
+
+ HAL_DAC_SetValue(&DAC_Handle, self->dac_channel, DAC_ALIGN_8B_R, mp_obj_get_int(val));
+ HAL_DAC_Start(&DAC_Handle, self->dac_channel);
+
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_write_obj, pyb_dac_write);
+
+// initiates a burst of RAM->DAC using DMA
+// input data is treated as an array of bytes (8 bit data)
+// TIM6 is used to set the frequency of the transfer
+// TODO still needs some attention to get it working properly
+mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ pyb_dac_obj_t *self = args[0];
+
+ // set TIM6 to trigger the DAC at the given frequency
+ TIM6_Config(mp_obj_get_int(args[2]));
+
+ mp_obj_type_t *type = mp_obj_get_type(args[1]);
+ if (type->buffer_p.get_buffer == NULL) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "buffer argument must support buffer protocol"));
+ }
+ buffer_info_t bufinfo;
+ type->buffer_p.get_buffer(args[1], &bufinfo, BUFFER_READ);
+
+ __DMA1_CLK_ENABLE();
+
+ /*
+ DMA_Cmd(self->dma_stream, DISABLE);
+ while (DMA_GetCmdStatus(self->dma_stream) != DISABLE) {
+ }
+
+ DAC_Cmd(self->dac_channel, DISABLE);
+ */
+
+ /*
+ // DAC channel configuration
+ DAC_InitTypeDef DAC_InitStructure;
+ DAC_InitStructure.DAC_Trigger = DAC_Trigger_T7_TRGO;
+ DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
+ DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_1; // unused, but need to set it to a valid value
+ DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
+ DAC_Init(self->dac_channel, &DAC_InitStructure);
+ */
+
+ if (self->state != 3) {
+ DAC_ChannelConfTypeDef config;
+ config.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
+ config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
+ HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
+ self->state = 3;
+ }
+
+ // DMA1_Stream[67] channel7 configuration
+ DMA_HandleTypeDef DMA_Handle;
+ DMA_Handle.Instance = self->dma_stream;
+ DMA_Handle.Init.Channel = DMA_CHANNEL_7;
+ DMA_Handle.Init.Direction = DMA_MEMORY_TO_PERIPH;
+ DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
+ DMA_Handle.Init.MemInc = DMA_MINC_ENABLE;
+ DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ mp_map_elem_t *kw_mode = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("mode")), MP_MAP_LOOKUP);
+ DMA_Handle.Init.Mode = kw_mode == NULL ? DMA_NORMAL : mp_obj_get_int(kw_mode->value); // normal = 0, circular = 0x100
+ DMA_Handle.Init.Priority = DMA_PRIORITY_HIGH;
+ DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
+ DMA_Handle.Init.MemBurst = DMA_MBURST_SINGLE;
+ DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE;
+ HAL_DMA_Init(&DMA_Handle);
+
+ __HAL_LINKDMA(&DAC_Handle, DMA_Handle1, DMA_Handle);
+
+ HAL_DAC_Start_DMA(&DAC_Handle, self->dac_channel, (uint32_t*)bufinfo.buf, bufinfo.len, DAC_ALIGN_8B_R);
+
+ /*
+ // enable DMA stream
+ DMA_Cmd(self->dma_stream, ENABLE);
+ while (DMA_GetCmdStatus(self->dma_stream) == DISABLE) {
+ }
+
+ // enable DAC channel
+ DAC_Cmd(self->dac_channel, ENABLE);
+
+ // enable DMA for DAC channel
+ DAC_DMACmd(self->dac_channel, ENABLE);
+ */
+
+ //printf("DMA: %p %lu\n", bufinfo.buf, bufinfo.len);
+
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_dac_dma_obj, 3, pyb_dac_dma);
+
+STATIC const mp_method_t pyb_dac_methods[] = {
+ { "noise", &pyb_dac_noise_obj },
+ { "triangle", &pyb_dac_triangle_obj },
+ { "write", &pyb_dac_write_obj },
+ { "dma", &pyb_dac_dma_obj },
+ // TODO add function that does double buffering:
+ // dma2(freq, buf1, buf2, callback)
+ // where callback is called when the buffer has been drained
+ { NULL, NULL },
+};
+
+const mp_obj_type_t pyb_dac_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_DAC,
+ .make_new = pyb_dac_make_new,
+ .methods = pyb_dac_methods,
+};
diff --git a/stmhal/dac.h b/stmhal/dac.h
new file mode 100644
index 0000000000..65e609576d
--- /dev/null
+++ b/stmhal/dac.h
@@ -0,0 +1,3 @@
+void dac_init(void);
+
+extern const mp_obj_type_t pyb_dac_type;
diff --git a/stmhal/exti.c b/stmhal/exti.c
index ec6d82e4fd..8aaa99d429 100644
--- a/stmhal/exti.c
+++ b/stmhal/exti.c
@@ -26,9 +26,7 @@
// def callback(line):
// print("line =", line)
//
-// # Configure the pin as a GPIO input.
-// pin = pyb.Pin.board.X1
-// pyb.gpio_in(pin, pyb.PULL_UP)
+// # Note: Exti will automatically configure the gpio line as an input.
// exti = pyb.Exti(pin, pyb.Exti.MODE_IRQ_FALLING, pyb.PULLUP, callback)
//
// Now every time a falling edge is seen on the X1 pin, the callback will be
diff --git a/stmhal/help.c b/stmhal/help.c
new file mode 100644
index 0000000000..9efe374524
--- /dev/null
+++ b/stmhal/help.c
@@ -0,0 +1,90 @@
+#include <stdio.h>
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "map.h"
+
+STATIC const char *help_text =
+"Welcome to Micro Python!\n"
+"\n"
+"For online help please visit http://micropython.org/help/.\n"
+"\n"
+"Specific commands for the board:\n"
+" pyb.info() -- print some general information\n"
+" pyb.gc() -- run the garbage collector\n"
+" pyb.repl_info(<val>) -- enable/disable printing of info after each command\n"
+" pyb.delay(<n>) -- wait for n milliseconds\n"
+" pyb.udelay(<n>) -- wait for n microseconds\n"
+" pyb.switch() -- return True/False if switch pressed or not\n"
+" pyb.Led(<n>) -- create Led object for LED n (n=1,2,3,4)\n"
+" Led methods: on(), off(), toggle(), intensity(<n>)\n"
+" pyb.Servo(<n>) -- create Servo object for servo n (n=1,2,3,4)\n"
+" Servo methods: angle(<x>)\n"
+" pyb.Accel() -- create an Accelerometer object\n"
+" Accelerometer methods: x(), y(), z(), tilt()\n"
+" pyb.rng() -- get a 30-bit hardware random number\n"
+" pyb.gpio(<port>) -- get port value (port='A4' for example)\n"
+" pyb.gpio(<port>, <val>) -- set port value, True or False, 1 or 0\n"
+" pyb.ADC(<port>) -- make an analog port object (port='C0' for example)\n"
+" ADC methods: read()\n"
+"\n"
+"Control commands:\n"
+" CTRL-A -- on a blank line, enter raw REPL mode\n"
+" CTRL-B -- on a blank line, enter normal REPL mode\n"
+" CTRL-C -- interrupt a running program\n"
+" CTRL-D -- on a blank line, do a soft reset of the board\n"
+;
+
+STATIC void pyb_help_print_info_about_object(mp_obj_t name_o, const char *name_str, mp_obj_t value) {
+ if (name_o != MP_OBJ_NULL) {
+ printf(" ");
+ mp_obj_print(name_o, PRINT_STR);
+ printf(" -- ");
+ } else {
+ printf(" %s -- ", name_str);
+ }
+ mp_obj_print(value, PRINT_STR);
+ printf("\n");
+}
+
+STATIC mp_obj_t pyb_help(uint n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ // print a general help message
+ printf("%s", help_text);
+
+ } else {
+ // try to print something sensible about the given object
+
+ printf("object ");
+ mp_obj_print(args[0], PRINT_STR);
+ printf(" is of type %s\n", mp_obj_get_type_str(args[0]));
+
+ mp_obj_type_t *type = mp_obj_get_type(args[0]);
+ mp_map_t *map = NULL;
+ if (type == &mp_type_module) {
+ map = mp_obj_module_get_globals(args[0]);
+ } else if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &dict_type)) {
+ map = mp_obj_dict_get_map(type->locals_dict);
+ }
+ if (map != NULL) {
+ for (uint i = 0; i < map->alloc; i++) {
+ if (map->table[i].key != MP_OBJ_NULL) {
+ pyb_help_print_info_about_object(map->table[i].key, NULL, map->table[i].value);
+ }
+ }
+ }
+
+ if (type->methods != NULL) {
+ for (const mp_method_t *meth = type->methods; meth->name != NULL; meth++) {
+ pyb_help_print_info_about_object(MP_OBJ_NULL, meth->name, (mp_obj_t)meth->fun);
+ }
+ }
+ }
+
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, pyb_help);
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
new file mode 100644
index 0000000000..b8608ad3ba
--- /dev/null
+++ b/stmhal/i2c.c
@@ -0,0 +1,184 @@
+#include <stdio.h>
+#include <string.h>
+
+#include <stm32f4xx_hal.h>
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "i2c.h"
+
+I2C_HandleTypeDef I2cHandle_X;
+I2C_HandleTypeDef I2cHandle_Y;
+
+void i2c_init(void) {
+ // init the I2C1 device
+ memset(&I2cHandle_X, 0, sizeof(I2C_HandleTypeDef));
+ I2cHandle_X.Instance = I2C1;
+
+ // init the I2C2 device
+ memset(&I2cHandle_Y, 0, sizeof(I2C_HandleTypeDef));
+ I2cHandle_Y.Instance = I2C2;
+}
+
+void i2c_start(I2C_HandleTypeDef *i2c_handle) {
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ // init the GPIO lines
+ GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
+ GPIO_InitStructure.Pull = GPIO_NOPULL; // have external pull-up resistors on both lines
+
+ if (i2c_handle == &I2cHandle_X) {
+ // X-skin: X9=PB6=SCL, X10=PB7=SDA
+ GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
+ GPIO_InitStructure.Alternate = GPIO_AF4_I2C1;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
+ // enable the I2C clock
+ __I2C1_CLK_ENABLE();
+ } else {
+ // Y-skin: Y9=PB10=SCL, Y10=PB11=SDA
+ GPIO_InitStructure.Pin = GPIO_PIN_10 | GPIO_PIN_11;
+ GPIO_InitStructure.Alternate = GPIO_AF4_I2C2;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
+ // enable the I2C clock
+ __I2C2_CLK_ENABLE();
+ }
+
+ // init the I2C device
+ i2c_handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+ i2c_handle->Init.ClockSpeed = 400000;
+ i2c_handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
+ i2c_handle->Init.DutyCycle = I2C_DUTYCYCLE_16_9;
+ i2c_handle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
+ i2c_handle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
+ i2c_handle->Init.OwnAddress1 = 0xfe; // unused
+ i2c_handle->Init.OwnAddress2 = 0xfe; // unused
+
+ if (HAL_I2C_Init(i2c_handle) != HAL_OK) {
+ // init error
+ printf("accel_init: HAL_I2C_Init failed\n");
+ return;
+ }
+}
+
+/******************************************************************************/
+/* Micro Python bindings */
+
+#define PYB_NUM_I2C (2)
+
+typedef struct _pyb_i2c_obj_t {
+ mp_obj_base_t base;
+ I2C_HandleTypeDef *i2c_handle;
+} pyb_i2c_obj_t;
+
+STATIC pyb_i2c_obj_t pyb_i2c_obj[PYB_NUM_I2C] = {{{&pyb_i2c_type}, &I2cHandle_X}, {{&pyb_i2c_type}, &I2cHandle_Y}};
+
+STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+ // check arguments
+ if (!(n_args == 1 && n_kw == 0)) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "I2C accepts 1 argument"));
+ }
+
+ // get i2c number
+ machine_int_t i2c_id = mp_obj_get_int(args[0]) - 1;
+
+ // check i2c number
+ if (!(0 <= i2c_id && i2c_id < PYB_NUM_I2C)) {
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C bus %d does not exist", i2c_id + 1));
+ }
+
+ // get i2c object
+ pyb_i2c_obj_t *i2c_obj = &pyb_i2c_obj[i2c_id];
+
+ // start the peripheral
+ i2c_start(i2c_obj->i2c_handle);
+
+ return &pyb_i2c_obj;
+}
+
+STATIC mp_obj_t pyb_i2c_is_ready(mp_obj_t self_in, mp_obj_t i2c_addr_o) {
+ pyb_i2c_obj_t *self = self_in;
+ machine_uint_t i2c_addr = mp_obj_get_int(i2c_addr_o) << 1;
+
+ //printf("IsDeviceReady\n");
+ for (int i = 0; i < 10; i++) {
+ HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(self->i2c_handle, i2c_addr, 10, 200);
+ //printf(" got %d\n", status);
+ if (status == HAL_OK) {
+ return mp_const_true;
+ }
+ }
+
+ return mp_const_false;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_is_ready_obj, pyb_i2c_is_ready);
+
+STATIC mp_obj_t pyb_i2c_mem_read(uint n_args, const mp_obj_t *args) {
+ pyb_i2c_obj_t *self = args[0];
+ machine_uint_t i2c_addr = mp_obj_get_int(args[1]) << 1;
+ machine_uint_t mem_addr = mp_obj_get_int(args[2]);
+ machine_uint_t n = mp_obj_get_int(args[3]);
+
+ byte *data;
+ mp_obj_t o = mp_obj_str_builder_start(&bytes_type, n, &data);
+ HAL_StatusTypeDef status = HAL_I2C_Mem_Read(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, data, n, 200);
+
+ //printf("Read got %d\n", status);
+
+ if (status != HAL_OK) {
+ // TODO really need a HardwareError object, or something
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Read failed with code %d", status));
+ }
+
+ return mp_obj_str_builder_end(o);
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_i2c_mem_read_obj, 4, 4, pyb_i2c_mem_read);
+
+STATIC mp_obj_t pyb_i2c_mem_write(uint n_args, const mp_obj_t *args) {
+ pyb_i2c_obj_t *self = args[0];
+ machine_uint_t i2c_addr = mp_obj_get_int(args[1]) << 1;
+ machine_uint_t mem_addr = mp_obj_get_int(args[2]);
+ HAL_StatusTypeDef status;
+ mp_obj_type_t *type = mp_obj_get_type(args[3]);
+ if (type->buffer_p.get_buffer != NULL) {
+ buffer_info_t bufinfo;
+ type->buffer_p.get_buffer(args[3], &bufinfo, BUFFER_READ);
+ status = HAL_I2C_Mem_Write(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, bufinfo.buf, bufinfo.len, 200);
+ } else if (MP_OBJ_IS_INT(args[3])) {
+ uint8_t data[1] = {mp_obj_get_int(args[3])};
+ status = HAL_I2C_Mem_Write(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
+ } else {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "data argument must be an integer or support the buffer protocol"));
+ }
+
+ //printf("Write got %d\n", status);
+
+ if (status != HAL_OK) {
+ // TODO really need a HardwareError object, or something
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Write failed with code %d", status));
+ }
+
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_i2c_mem_write_obj, 4, 4, pyb_i2c_mem_write);
+
+STATIC const mp_method_t pyb_i2c_methods[] = {
+ { "is_ready", &pyb_i2c_is_ready_obj },
+ { "mem_read", &pyb_i2c_mem_read_obj },
+ { "mem_write", &pyb_i2c_mem_write_obj },
+ { NULL, NULL },
+};
+
+const mp_obj_type_t pyb_i2c_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_I2C,
+ .make_new = pyb_i2c_make_new,
+ .methods = pyb_i2c_methods,
+};
diff --git a/stmhal/i2c.h b/stmhal/i2c.h
new file mode 100644
index 0000000000..32cba42595
--- /dev/null
+++ b/stmhal/i2c.h
@@ -0,0 +1,6 @@
+extern I2C_HandleTypeDef I2cHandle_X;
+extern I2C_HandleTypeDef I2cHandle_Y;
+extern const mp_obj_type_t pyb_i2c_type;
+
+void i2c_init(void);
+void i2c_start(I2C_HandleTypeDef *i2c_handle);
diff --git a/stmhal/led.c b/stmhal/led.c
index 102cbac5a7..688daefc81 100644
--- a/stmhal/led.c
+++ b/stmhal/led.c
@@ -3,6 +3,7 @@
#include "usbd_cdc_msc.h"
#include "usbd_cdc_interface.h"
+#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
@@ -183,14 +184,45 @@ void led_debug(int n, int delay) {
typedef struct _pyb_led_obj_t {
mp_obj_base_t base;
- uint led_id;
+ machine_uint_t led_id;
} pyb_led_obj_t;
+STATIC const pyb_led_obj_t pyb_led_obj[NUM_LEDS] = {
+ {{&pyb_led_type}, 1},
+#if defined(PYB_LED2)
+ {{&pyb_led_type}, 2},
+#if defined(PYB_LED3)
+ {{&pyb_led_type}, 3},
+#if defined(PYB_LED4)
+ {{&pyb_led_type}, 4},
+#endif
+#endif
+#endif
+};
+
void led_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_led_obj_t *self = self_in;
print(env, "<LED %lu>", self->led_id);
}
+STATIC mp_obj_t led_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+ // check arguments
+ if (!(n_args == 1 && n_kw == 0)) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Led accepts 1 argument"));
+ }
+
+ // get led number
+ machine_int_t led_id = mp_obj_get_int(args[0]) - 1;
+
+ // check led number
+ if (!(0 <= led_id && led_id < NUM_LEDS)) {
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Led %d does not exist", led_id));
+ }
+
+ // return static led object
+ return (mp_obj_t)&pyb_led_obj[led_id];
+}
+
mp_obj_t led_obj_on(mp_obj_t self_in) {
pyb_led_obj_t *self = self_in;
led_state(self->led_id, 1);
@@ -232,18 +264,10 @@ STATIC const mp_method_t led_methods[] = {
{ NULL, NULL },
};
-STATIC const mp_obj_type_t led_obj_type = {
+const mp_obj_type_t pyb_led_type = {
{ &mp_type_type },
.name = MP_QSTR_Led,
.print = led_obj_print,
+ .make_new = led_obj_make_new,
.methods = led_methods,
};
-
-STATIC mp_obj_t pyb_Led(mp_obj_t led_id) {
- pyb_led_obj_t *o = m_new_obj(pyb_led_obj_t);
- o->base.type = &led_obj_type;
- o->led_id = mp_obj_get_int(led_id);
- return o;
-}
-
-MP_DEFINE_CONST_FUN_OBJ_1(pyb_Led_obj, pyb_Led);
diff --git a/stmhal/led.h b/stmhal/led.h
index b3762271c1..ab2b2ea14e 100644
--- a/stmhal/led.h
+++ b/stmhal/led.h
@@ -21,4 +21,4 @@ void led_state(pyb_led_t led, int state);
void led_toggle(pyb_led_t led);
void led_debug(int value, int delay);
-MP_DECLARE_CONST_FUN_OBJ(pyb_Led_obj);
+extern const mp_obj_type_t pyb_led_type;
diff --git a/stmhal/main.c b/stmhal/main.c
index 9d88206978..1da7a9a649 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -21,22 +21,21 @@
#include "gc.h"
#include "gccollect.h"
#include "pyexec.h"
-#include "pybmodule.h"
-#include "osmodule.h"
-#include "timemodule.h"
#include "usart.h"
#include "led.h"
#include "exti.h"
#include "usrsw.h"
#include "usb.h"
-#include "rng.h"
#include "rtc.h"
#include "storage.h"
#include "sdcard.h"
#include "ff.h"
#include "lcd.h"
+#include "rng.h"
+#include "i2c.h"
#include "accel.h"
#include "servo.h"
+#include "dac.h"
#include "pin.h"
#if 0
#include "timer.h"
@@ -109,6 +108,7 @@ static const char fresh_boot_py[] =
"# boot.py -- run on boot-up\n"
"# can run arbitrary Python, but best to keep it minimal\n"
"\n"
+"import pyb\n"
"pyb.source_dir('/src')\n"
"pyb.main('main.py')\n"
"#pyb.usb_usr('VCP')\n"
@@ -121,34 +121,6 @@ static const char fresh_main_py[] =
"# main.py -- put your code here!\n"
;
-static const char *help_text =
-"Welcome to Micro Python!\n\n"
-"This is a *very* early version of Micro Python and has minimal functionality.\n\n"
-"Specific commands for the board:\n"
-" pyb.info() -- print some general information\n"
-" pyb.gc() -- run the garbage collector\n"
-" pyb.repl_info(<val>) -- enable/disable printing of info after each command\n"
-" pyb.delay(<n>) -- wait for n milliseconds\n"
-" pyb.udelay(<n>) -- wait for n microseconds\n"
-" pyb.Led(<n>) -- create Led object for LED n (n=1,2)\n"
-" Led methods: on(), off()\n"
-" pyb.Servo(<n>) -- create Servo object for servo n (n=1,2,3,4)\n"
-" Servo methods: angle(<x>)\n"
-" pyb.switch() -- return True/False if switch pressed or not\n"
-" pyb.accel() -- get accelerometer values\n"
-" pyb.rand() -- get a 16-bit random number\n"
-" pyb.gpio(<port>) -- get port value (port='A4' for example)\n"
-" pyb.gpio(<port>, <val>) -- set port value, True or False, 1 or 0\n"
-" pyb.ADC(<port>) -- make an analog port object (port='C0' for example)\n"
-" ADC methods: read()\n"
-;
-
-// get some help about available functions
-static mp_obj_t pyb_help(void) {
- printf("%s", help_text);
- return mp_const_none;
-}
-
int main(void) {
// TODO disable JTAG
@@ -249,37 +221,8 @@ soft_reset:
lcd_init();
#endif
-#if MICROPY_HW_ENABLE_RNG
- // RNG
- rng_init();
-#endif
-
-#if MICROPY_HW_ENABLE_SERVO
- // servo
- servo_init();
-#endif
-
-#if 0
-#if MICROPY_HW_ENABLE_TIMER
- // timer
- timer_init();
-#endif
-#endif
-
pin_map_init();
- // add some functions to the builtin Python namespace
- rt_store_name(MP_QSTR_help, rt_make_function_n(0, pyb_help));
-
- // we pre-import the pyb module
- // probably shouldn't do this, so we are compatible with CPython
- rt_store_name(MP_QSTR_pyb, (mp_obj_t)&pyb_module);
-
- // pre-import the os and time modules
- // TODO don't do this! (need a way of registering builtin modules...)
- rt_store_name(MP_QSTR_os, (mp_obj_t)&os_module);
- rt_store_name(MP_QSTR_time, (mp_obj_t)&time_module);
-
// check if user switch held (initiates reset of filesystem)
bool reset_filesystem = false;
#if MICROPY_HW_HAS_SWITCH
@@ -398,6 +341,9 @@ soft_reset:
}
}
}
+#else
+ // Get rid of compiler warning if no SDCARD is configured.
+ (void)first_soft_reset;
#endif
#if defined(USE_HOST_MODE)
@@ -408,11 +354,36 @@ soft_reset:
pyb_usb_dev_init(USBD_DEVICE_CDC_MSC, usbd_medium_kind);
#endif
+#if MICROPY_HW_ENABLE_RNG
+ // RNG
+ rng_init();
+#endif
+
+ // I2C
+ i2c_init();
+
#if MICROPY_HW_HAS_MMA7660
// MMA accel: init and reset
accel_init();
#endif
+#if MICROPY_HW_ENABLE_SERVO
+ // servo
+ servo_init();
+#endif
+
+#if 0
+#if MICROPY_HW_ENABLE_TIMER
+ // timer
+ timer_init();
+#endif
+#endif
+
+#if MICROPY_HW_ENABLE_DAC
+ // DAC
+ dac_init();
+#endif
+
// run main script
{
vstr_t *vstr = vstr_new();
@@ -477,7 +448,19 @@ soft_reset:
#endif
#endif
- pyexec_repl();
+ // enter REPL
+ // REPL mode can change, or it can request a soft reset
+ for (;;) {
+ if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
+ if (pyexec_raw_repl() != 0) {
+ break;
+ }
+ } else {
+ if (pyexec_friendly_repl() != 0) {
+ break;
+ }
+ }
+ }
printf("PYB: sync filesystems\n");
storage_flush();
diff --git a/stmhal/osmodule.c b/stmhal/modos.c
index 7f32fe6749..0ec9fcbb91 100644
--- a/stmhal/osmodule.c
+++ b/stmhal/modos.c
@@ -10,7 +10,7 @@
#include "rng.h"
#include "storage.h"
#include "ff.h"
-#include "osmodule.h"
+#include "modos.h"
#if _USE_LFN
static char lfn[_MAX_LFN + 1]; /* Buffer to store the LFN */
diff --git a/stmhal/osmodule.h b/stmhal/modos.h
index e3c13f756e..e3c13f756e 100644
--- a/stmhal/osmodule.h
+++ b/stmhal/modos.h
diff --git a/stmhal/pybmodule.c b/stmhal/modpyb.c
index 00a8c321db..432dc859c1 100644
--- a/stmhal/pybmodule.c
+++ b/stmhal/modpyb.c
@@ -20,17 +20,17 @@
#include "rng.h"
#include "rtc.h"
#include "usart.h"
+#include "adc.h"
#include "storage.h"
#include "sdcard.h"
#include "accel.h"
#include "servo.h"
+#include "dac.h"
+#include "i2c.h"
#if 0
#include "usb.h"
-#include "i2c.h"
-#include "adc.h"
-#include "audio.h"
#endif
-#include "pybmodule.h"
+#include "modpyb.h"
#include "ff.h"
// get lots of info about the board
@@ -242,7 +242,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
#if MICROPY_HW_ENABLE_SERVO
{ MP_OBJ_NEW_QSTR(MP_QSTR_pwm), (mp_obj_t)&pyb_pwm_set_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_servo), (mp_obj_t)&pyb_servo_set_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_Servo), (mp_obj_t)&pyb_Servo_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Servo), (mp_obj_t)&pyb_servo_type },
#endif
#if MICROPY_HW_HAS_SWITCH
@@ -253,26 +253,24 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sdcard_obj },
#endif
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Led), (mp_obj_t)&pyb_led_type },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Usart), (mp_obj_t)&pyb_usart_type },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_adc_type },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ADC_all), (mp_obj_t)&pyb_ADC_all_obj },
+
+#if MICROPY_HW_ENABLE_DAC
+ { MP_OBJ_NEW_QSTR(MP_QSTR_DAC), (mp_obj_t)&pyb_dac_type },
+#endif
+
#if MICROPY_HW_HAS_MMA7660
- { MP_OBJ_NEW_QSTR(MP_QSTR_Accel), (mp_obj_t)&pyb_Accel_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Accel), (mp_obj_t)&pyb_accel_type },
#endif
#if 0
{ MP_OBJ_NEW_QSTR(MP_QSTR_hid), (mp_obj_t)&pyb_hid_send_report_obj },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_Led), (mp_obj_t)&pyb_Led_obj },
-#if 0
- { MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_I2C_obj },
-#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_Usart), (mp_obj_t)&pyb_Usart_obj },
-#if 0
- { MP_OBJ_NEW_QSTR(MP_QSTR_ADC_all), (mp_obj_t)&pyb_ADC_all_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_ADC_obj },
-
-#if MICROPY_HW_ENABLE_AUDIO
- { MP_OBJ_NEW_QSTR(MP_QSTR_Audio), (mp_obj_t)&pyb_Audio_obj },
-#endif
-#endif
// input
{ MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&pyb_input_obj },
diff --git a/stmhal/pybmodule.h b/stmhal/modpyb.h
index 955aaefe3f..955aaefe3f 100644
--- a/stmhal/pybmodule.h
+++ b/stmhal/modpyb.h
diff --git a/stmhal/timemodule.c b/stmhal/modtime.c
index b2dac6a54c..4786c85c72 100644
--- a/stmhal/timemodule.c
+++ b/stmhal/modtime.c
@@ -6,7 +6,7 @@
#include "qstr.h"
#include "obj.h"
#include "map.h"
-#include "timemodule.h"
+#include "modtime.h"
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
#if MICROPY_ENABLE_FLOAT
diff --git a/stmhal/timemodule.h b/stmhal/modtime.h
index 70e35b1fde..70e35b1fde 100644
--- a/stmhal/timemodule.h
+++ b/stmhal/modtime.h
diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h
index 59c91942a0..b187c43bbe 100644
--- a/stmhal/mpconfigport.h
+++ b/stmhal/mpconfigport.h
@@ -19,12 +19,23 @@
#define MICROPY_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
// extra built in names to add to the global namespace
+extern const struct _mp_obj_fun_native_t mp_builtin_help_obj;
extern const struct _mp_obj_fun_native_t mp_builtin_input_obj;
extern const struct _mp_obj_fun_native_t mp_builtin_open_obj;
#define MICROPY_EXTRA_BUILTINS \
+ { MP_QSTR_help, (mp_obj_t)&mp_builtin_help_obj }, \
{ MP_QSTR_input, (mp_obj_t)&mp_builtin_input_obj }, \
{ MP_QSTR_open, (mp_obj_t)&mp_builtin_open_obj },
+// extra built in modules to add to the list of known ones
+extern const struct _mp_obj_module_t os_module;
+extern const struct _mp_obj_module_t pyb_module;
+extern const struct _mp_obj_module_t time_module;
+#define MICROPY_EXTRA_BUILTIN_MODULES \
+ { MP_QSTR_os, (mp_obj_t)&os_module }, \
+ { MP_QSTR_pyb, (mp_obj_t)&pyb_module }, \
+ { MP_QSTR_time, (mp_obj_t)&time_module }, \
+
// type definitions for the specific machine
#define BYTES_PER_WORD (4)
diff --git a/stmhal/pin.h b/stmhal/pin.h
index d5d769058a..2aa50655b4 100644
--- a/stmhal/pin.h
+++ b/stmhal/pin.h
@@ -50,6 +50,12 @@ enum {
AF_PIN_TYPE_SPI_NSS,
};
+enum {
+ PIN_ADC1 = (1 << 0),
+ PIN_ADC2 = (1 << 1),
+ PIN_ADC3 = (1 << 2),
+};
+
typedef struct {
mp_obj_base_t base;
uint8_t idx;
@@ -70,9 +76,11 @@ typedef struct {
typedef struct {
mp_obj_base_t base;
const char *name;
- uint16_t port : 4;
- uint16_t pin : 4;
- uint16_t num_af : 4;
+ uint16_t port : 4;
+ uint16_t pin : 4;
+ uint16_t num_af : 4;
+ uint16_t adc_channel : 4;
+ uint16_t adc_num : 3; // 1 bit per ADC
uint16_t pin_mask;
GPIO_TypeDef *gpio;
const pin_af_obj_t *af;
diff --git a/stmhal/pyexec.c b/stmhal/pyexec.c
index e17b9aea44..f1f28abde0 100644
--- a/stmhal/pyexec.c
+++ b/stmhal/pyexec.c
@@ -24,7 +24,8 @@
#include "usb.h"
#include "usart.h"
-static bool repl_display_debugging_info = 0;
+pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
+STATIC bool repl_display_debugging_info = 0;
void stdout_tx_str(const char *str) {
if (pyb_usart_global_debug != PYB_USART_NONE) {
@@ -279,12 +280,12 @@ bool parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bo
return ret;
}
-void pyexec_raw_repl(void) {
+int pyexec_raw_repl(void) {
vstr_t line;
vstr_init(&line, 32);
raw_repl_reset:
- stdout_tx_str("raw REPL; CTRL-C to exit\r\n");
+ stdout_tx_str("raw REPL; CTRL-B to exit\r\n");
for (;;) {
vstr_reset(&line);
@@ -292,11 +293,19 @@ raw_repl_reset:
for (;;) {
char c = stdin_rx_chr();
if (c == VCP_CHAR_CTRL_A) {
+ // reset raw REPL
goto raw_repl_reset;
+ } else if (c == VCP_CHAR_CTRL_B) {
+ // change to friendly REPL
+ stdout_tx_str("\r\n");
+ vstr_clear(&line);
+ pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
+ return 0;
} else if (c == VCP_CHAR_CTRL_C) {
+ // clear line
vstr_reset(&line);
- break;
} else if (c == VCP_CHAR_CTRL_D) {
+ // input finished
break;
} else if (c == '\r') {
vstr_add_char(&line, '\n');
@@ -305,30 +314,35 @@ raw_repl_reset:
}
}
+ // indicate reception of command
stdout_tx_str("OK");
- if (vstr_len(&line) == 0) {
- // finished
- break;
+ if (line.len == 0) {
+ // exit for a soft reset
+ stdout_tx_str("\r\n");
+ vstr_clear(&line);
+ return 1;
}
- mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line), vstr_len(&line), 0);
+ mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line.buf, line.len, 0);
parse_compile_execute(lex, MP_PARSE_FILE_INPUT, false);
+ // indicate end of output with EOF character
stdout_tx_str("\004");
}
-
- vstr_clear(&line);
- stdout_tx_str("\r\n");
}
-void pyexec_repl(void) {
+int pyexec_friendly_repl(void) {
+ vstr_t line;
+ vstr_init(&line, 32);
+
#if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD
// in host mode, we enable the LCD for the repl
mp_obj_t lcd_o = rt_call_function_0(rt_load_name(qstr_from_str("LCD")));
rt_call_function_1(rt_load_attr(lcd_o, qstr_from_str("light")), mp_const_true);
#endif
+friendly_repl_reset:
stdout_tx_str("Micro Python build <git hash> on 25/1/2014; " MICROPY_HW_BOARD_NAME " with STM32F405RG\r\n");
stdout_tx_str("Type \"help()\" for more information.\r\n");
@@ -350,22 +364,29 @@ void pyexec_repl(void) {
}
*/
- vstr_t line;
- vstr_init(&line, 32);
-
for (;;) {
vstr_reset(&line);
int ret = readline(&line, ">>> ");
if (ret == VCP_CHAR_CTRL_A) {
- pyexec_raw_repl();
- continue;
+ // change to raw REPL
+ stdout_tx_str("\r\n");
+ vstr_clear(&line);
+ pyexec_mode_kind = PYEXEC_MODE_RAW_REPL;
+ return 0;
+ } else if (ret == VCP_CHAR_CTRL_B) {
+ // reset friendly REPL
+ stdout_tx_str("\r\n");
+ goto friendly_repl_reset;
} else if (ret == VCP_CHAR_CTRL_C) {
+ // break
stdout_tx_str("\r\n");
continue;
} else if (ret == VCP_CHAR_CTRL_D) {
- // EOF
- break;
+ // exit for a soft reset
+ stdout_tx_str("\r\n");
+ vstr_clear(&line);
+ return 1;
} else if (vstr_len(&line) == 0) {
continue;
}
@@ -385,8 +406,6 @@ void pyexec_repl(void) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line), vstr_len(&line), 0);
parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, true);
}
-
- stdout_tx_str("\r\n");
}
bool pyexec_file(const char *filename) {
diff --git a/stmhal/pyexec.h b/stmhal/pyexec.h
index cad15af6fe..d191a2fc4e 100644
--- a/stmhal/pyexec.h
+++ b/stmhal/pyexec.h
@@ -1,5 +1,12 @@
-void pyexec_raw_repl(void);
-void pyexec_repl(void);
+typedef enum {
+ PYEXEC_MODE_RAW_REPL,
+ PYEXEC_MODE_FRIENDLY_REPL,
+} pyexec_mode_kind_t;
+
+extern pyexec_mode_kind_t pyexec_mode_kind;
+
+int pyexec_raw_repl(void);
+int pyexec_friendly_repl(void);
bool pyexec_file(const char *filename);
MP_DECLARE_CONST_FUN_OBJ(pyb_set_repl_info_obj);
diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h
index 18fc345a81..4036dcd25e 100644
--- a/stmhal/qstrdefsport.h
+++ b/stmhal/qstrdefsport.h
@@ -33,7 +33,7 @@ Q(gpio_out)
Q(Usart)
Q(ADC)
Q(ADC_all)
-Q(Audio)
+Q(DAC)
Q(open)
Q(File)
// Entries for sys.path
diff --git a/stmhal/servo.c b/stmhal/servo.c
index b0e0e8695d..81b290bf52 100644
--- a/stmhal/servo.c
+++ b/stmhal/servo.c
@@ -148,12 +148,35 @@ STATIC mp_obj_t pyb_pwm_set(mp_obj_t period, mp_obj_t pulse) {
MP_DEFINE_CONST_FUN_OBJ_2(pyb_pwm_set_obj, pyb_pwm_set);
-STATIC void servo_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void pyb_servo_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_servo_obj_t *self = self_in;
print(env, "<Servo %lu at %lu>", self->servo_id, self->pulse_cur);
}
-STATIC mp_obj_t servo_obj_angle(uint n_args, const mp_obj_t *args) {
+STATIC mp_obj_t pyb_servo_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+ // check arguments
+ if (!(n_args == 1 && n_kw == 0)) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Servo accepts 1 argument"));
+ }
+
+ // get servo number
+ machine_int_t servo_id = mp_obj_get_int(args[0]) - 1;
+
+ // check servo number
+ if (!(0 <= servo_id && servo_id < PYB_SERVO_NUM)) {
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Servo %d does not exist", servo_id));
+ }
+
+ // get and init servo object
+ pyb_servo_obj_t *s = &pyb_servo_obj[servo_id];
+ s->pulse_dest = s->pulse_cur;
+ s->time_left = 0;
+ servo_init_channel(s);
+
+ return s;
+}
+
+STATIC mp_obj_t pyb_servo_angle(uint n_args, const mp_obj_t *args) {
pyb_servo_obj_t *self = args[0];
if (n_args == 1) {
// get angle
@@ -180,31 +203,17 @@ STATIC mp_obj_t servo_obj_angle(uint n_args, const mp_obj_t *args) {
}
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(servo_obj_angle_obj, 1, 3, servo_obj_angle);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_servo_angle_obj, 1, 3, pyb_servo_angle);
-STATIC const mp_method_t servo_methods[] = {
- { "angle", &servo_obj_angle_obj },
+STATIC const mp_method_t pyb_servo_methods[] = {
+ { "angle", &pyb_servo_angle_obj },
{ NULL, NULL },
};
-STATIC const mp_obj_type_t servo_obj_type = {
+const mp_obj_type_t pyb_servo_type = {
{ &mp_type_type },
.name = MP_QSTR_Servo,
- .print = servo_obj_print,
- .methods = servo_methods,
+ .print = pyb_servo_print,
+ .make_new = pyb_servo_make_new,
+ .methods = pyb_servo_methods,
};
-
-STATIC mp_obj_t pyb_Servo(mp_obj_t servo_id_o) {
- machine_int_t servo_id = mp_obj_get_int(servo_id_o) - 1;
- if (0 <= servo_id && servo_id < PYB_SERVO_NUM) {
- pyb_servo_obj_t *s = &pyb_servo_obj[servo_id];
- s->pulse_dest = s->pulse_cur;
- s->time_left = 0;
- servo_init_channel(s);
- return s;
- } else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Servo %d does not exist", servo_id));
- }
-}
-
-MP_DEFINE_CONST_FUN_OBJ_1(pyb_Servo_obj, pyb_Servo);
diff --git a/stmhal/servo.h b/stmhal/servo.h
index 753ca49598..d5fb6a8505 100644
--- a/stmhal/servo.h
+++ b/stmhal/servo.h
@@ -3,6 +3,7 @@ extern TIM_HandleTypeDef TIM2_Handle;
void servo_init(void);
void servo_timer_irq_callback(void);
+extern const mp_obj_type_t pyb_servo_type;
+
MP_DECLARE_CONST_FUN_OBJ(pyb_servo_set_obj);
MP_DECLARE_CONST_FUN_OBJ(pyb_pwm_set_obj);
-MP_DECLARE_CONST_FUN_OBJ(pyb_Servo_obj);
diff --git a/stmhal/usart.c b/stmhal/usart.c
index bc8b0ec1c9..31308c22ad 100644
--- a/stmhal/usart.c
+++ b/stmhal/usart.c
@@ -1,7 +1,9 @@
#include <stdio.h>
#include <string.h>
-#include <stm32f4xx_hal.h>
+#include "stm32f4xx_hal.h"
+
+#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
@@ -71,8 +73,8 @@ void usart_init(pyb_usart_obj_t *usart_obj, uint32_t baudrate) {
break;
}
- /* Initialize USARTx */
-
+ // Initialize USARTx
+
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_Pin;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
@@ -135,7 +137,33 @@ void usart_tx_strn_cooked(pyb_usart_obj_t *usart_obj, const char *str, uint len)
/******************************************************************************/
/* Micro Python bindings */
-static mp_obj_t usart_obj_status(mp_obj_t self_in) {
+STATIC void usart_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ pyb_usart_obj_t *self = self_in;
+ print(env, "<Usart %lu>", self->usart_id);
+}
+
+STATIC mp_obj_t usart_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+ // check arguments
+ if (!(n_args == 2 && n_kw == 0)) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Usart accepts 2 arguments"));
+ }
+
+ if (mp_obj_get_int(args[0]) > PYB_USART_MAX) {
+ return mp_const_none;
+ }
+
+ pyb_usart_obj_t *o = m_new_obj(pyb_usart_obj_t);
+ o->base.type = &pyb_usart_type;
+ o->usart_id = mp_obj_get_int(args[0]);
+ o->is_enabled = true;
+
+ /* init USART */
+ usart_init(o, mp_obj_get_int(args[1]));
+
+ return o;
+}
+
+STATIC mp_obj_t usart_obj_status(mp_obj_t self_in) {
pyb_usart_obj_t *self = self_in;
if (usart_rx_any(self)) {
return mp_const_true;
@@ -144,7 +172,7 @@ static mp_obj_t usart_obj_status(mp_obj_t self_in) {
}
}
-static mp_obj_t usart_obj_rx_char(mp_obj_t self_in) {
+STATIC mp_obj_t usart_obj_rx_char(mp_obj_t self_in) {
mp_obj_t ret = mp_const_none;
pyb_usart_obj_t *self = self_in;
@@ -154,7 +182,7 @@ static mp_obj_t usart_obj_rx_char(mp_obj_t self_in) {
return ret;
}
-static mp_obj_t usart_obj_tx_char(mp_obj_t self_in, mp_obj_t c) {
+STATIC mp_obj_t usart_obj_tx_char(mp_obj_t self_in, mp_obj_t c) {
pyb_usart_obj_t *self = self_in;
uint len;
const char *str = mp_obj_str_get_data(c, &len);
@@ -164,7 +192,7 @@ static mp_obj_t usart_obj_tx_char(mp_obj_t self_in, mp_obj_t c) {
return mp_const_none;
}
-static mp_obj_t usart_obj_tx_str(mp_obj_t self_in, mp_obj_t s) {
+STATIC mp_obj_t usart_obj_tx_str(mp_obj_t self_in, mp_obj_t s) {
pyb_usart_obj_t *self = self_in;
if (self->is_enabled) {
if (MP_OBJ_IS_STR(s)) {
@@ -176,15 +204,10 @@ static mp_obj_t usart_obj_tx_str(mp_obj_t self_in, mp_obj_t s) {
return mp_const_none;
}
-static void usart_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
- pyb_usart_obj_t *self = self_in;
- print(env, "<Usart %lu>", self->usart_id);
-}
-
-static MP_DEFINE_CONST_FUN_OBJ_1(usart_obj_status_obj, usart_obj_status);
-static MP_DEFINE_CONST_FUN_OBJ_1(usart_obj_rx_char_obj, usart_obj_rx_char);
-static MP_DEFINE_CONST_FUN_OBJ_2(usart_obj_tx_char_obj, usart_obj_tx_char);
-static MP_DEFINE_CONST_FUN_OBJ_2(usart_obj_tx_str_obj, usart_obj_tx_str);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(usart_obj_status_obj, usart_obj_status);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(usart_obj_rx_char_obj, usart_obj_rx_char);
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(usart_obj_tx_char_obj, usart_obj_tx_char);
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(usart_obj_tx_str_obj, usart_obj_tx_str);
STATIC const mp_method_t usart_methods[] = {
{ "status", &usart_obj_status_obj },
@@ -194,27 +217,10 @@ STATIC const mp_method_t usart_methods[] = {
{ NULL, NULL },
};
-STATIC const mp_obj_type_t usart_obj_type = {
+const mp_obj_type_t pyb_usart_type = {
{ &mp_type_type },
.name = MP_QSTR_Usart,
.print = usart_obj_print,
+ .make_new = usart_obj_make_new,
.methods = usart_methods,
};
-
-mp_obj_t pyb_Usart(mp_obj_t usart_id, mp_obj_t baudrate) {
- if (mp_obj_get_int(usart_id) > PYB_USART_MAX) {
- return mp_const_none;
- }
-
- pyb_usart_obj_t *o = m_new_obj(pyb_usart_obj_t);
- o->base.type = &usart_obj_type;
- o->usart_id = mp_obj_get_int(usart_id);
- o->is_enabled = true;
-
- /* init USART */
- usart_init(o, mp_obj_get_int(baudrate));
-
- return o;
-}
-
-MP_DEFINE_CONST_FUN_OBJ_2(pyb_Usart_obj, pyb_Usart);
diff --git a/stmhal/usart.h b/stmhal/usart.h
index c7119c833e..02464080b8 100644
--- a/stmhal/usart.h
+++ b/stmhal/usart.h
@@ -15,6 +15,7 @@ typedef enum {
typedef struct _pyb_usart_obj_t pyb_usart_obj_t;
extern pyb_usart_obj_t *pyb_usart_global_debug;
+extern const mp_obj_type_t pyb_usart_type;
void usart_init(pyb_usart_obj_t *usart_obj, uint32_t baudrate);
bool usart_rx_any(pyb_usart_obj_t *usart_obj);
@@ -23,6 +24,3 @@ void usart_tx_str(pyb_usart_obj_t *usart_obj, const char *str);
void usart_tx_strn(pyb_usart_obj_t *usart_obj, const char *str, uint len);
void usart_tx_strn_cooked(pyb_usart_obj_t *usart_obj, const char *str, uint len);
-mp_obj_t pyb_Usart(mp_obj_t usart_id, mp_obj_t baudrate);
-
-MP_DECLARE_CONST_FUN_OBJ(pyb_Usart_obj);
diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c
index a62f8a801f..c441e9c61c 100644
--- a/stmhal/usbd_cdc_interface.c
+++ b/stmhal/usbd_cdc_interface.c
@@ -363,7 +363,7 @@ void USBD_CDC_SetInterrupt(int chr, void *data) {
void USBD_CDC_Tx(const char *str, uint32_t len) {
for (int i = 0; i < len; i++) {
uint timeout = 200;
- while (UserTxBufPtrIn + 1 == UserTxBufPtrOut) {
+ while (((UserTxBufPtrIn + 1) & (APP_TX_DATA_SIZE - 1)) == UserTxBufPtrOut) {
if (timeout-- == 0) {
break;
}
diff --git a/tests/basics/exception1.py b/tests/basics/exception1.py
index 71d5ad3041..739dd32753 100644
--- a/tests/basics/exception1.py
+++ b/tests/basics/exception1.py
@@ -7,3 +7,9 @@ print(str(IndexError("foo")))
a = IndexError(1, "test", [100, 200])
print(repr(a))
print(str(a))
+print(a.args)
+
+s = StopIteration()
+print(s.value)
+s = StopIteration(1, 2, 3)
+print(s.value)
diff --git a/tests/basics/exceptpoly.py b/tests/basics/exceptpoly.py
index 0e5ac2d1a3..b2fc11afbe 100644
--- a/tests/basics/exceptpoly.py
+++ b/tests/basics/exceptpoly.py
@@ -38,25 +38,25 @@ try:
except BufferError:
print("Caught BufferError")
-try:
- raise BytesWarning
-except Warning:
- print("Caught BytesWarning via Warning")
+#try:
+# raise BytesWarning
+#except Warning:
+# print("Caught BytesWarning via Warning")
-try:
- raise BytesWarning
-except BytesWarning:
- print("Caught BytesWarning")
+#try:
+# raise BytesWarning
+#except BytesWarning:
+# print("Caught BytesWarning")
-try:
- raise DeprecationWarning
-except Warning:
- print("Caught DeprecationWarning via Warning")
+#try:
+# raise DeprecationWarning
+#except Warning:
+# print("Caught DeprecationWarning via Warning")
-try:
- raise DeprecationWarning
-except DeprecationWarning:
- print("Caught DeprecationWarning")
+#try:
+# raise DeprecationWarning
+#except DeprecationWarning:
+# print("Caught DeprecationWarning")
try:
raise EOFError
@@ -68,15 +68,15 @@ try:
except EOFError:
print("Caught EOFError")
-try:
- raise EnvironmentError
-except Exception:
- print("Caught EnvironmentError via Exception")
+#try:
+# raise EnvironmentError
+#except Exception:
+# print("Caught EnvironmentError via Exception")
-try:
- raise EnvironmentError
-except EnvironmentError:
- print("Caught EnvironmentError")
+#try:
+# raise EnvironmentError
+#except EnvironmentError:
+# print("Caught EnvironmentError")
try:
raise Exception
@@ -98,15 +98,15 @@ try:
except FloatingPointError:
print("Caught FloatingPointError")
-try:
- raise FutureWarning
-except Warning:
- print("Caught FutureWarning via Warning")
+#try:
+# raise FutureWarning
+#except Warning:
+# print("Caught FutureWarning via Warning")
-try:
- raise FutureWarning
-except FutureWarning:
- print("Caught FutureWarning")
+#try:
+# raise FutureWarning
+#except FutureWarning:
+# print("Caught FutureWarning")
try:
raise IOError
@@ -128,15 +128,15 @@ try:
except ImportError:
print("Caught ImportError")
-try:
- raise ImportWarning
-except Warning:
- print("Caught ImportWarning via Warning")
+#try:
+# raise ImportWarning
+#except Warning:
+# print("Caught ImportWarning via Warning")
-try:
- raise ImportWarning
-except ImportWarning:
- print("Caught ImportWarning")
+#try:
+# raise ImportWarning
+#except ImportWarning:
+# print("Caught ImportWarning")
try:
raise IndentationError
@@ -228,35 +228,35 @@ try:
except OverflowError:
print("Caught OverflowError")
-try:
- raise PendingDeprecationWarning
-except Warning:
- print("Caught PendingDeprecationWarning via Warning")
+#try:
+# raise PendingDeprecationWarning
+#except Warning:
+# print("Caught PendingDeprecationWarning via Warning")
-try:
- raise PendingDeprecationWarning
-except PendingDeprecationWarning:
- print("Caught PendingDeprecationWarning")
+#try:
+# raise PendingDeprecationWarning
+#except PendingDeprecationWarning:
+# print("Caught PendingDeprecationWarning")
-try:
- raise ReferenceError
-except Exception:
- print("Caught ReferenceError via Exception")
+#try:
+# raise ReferenceError
+#except Exception:
+# print("Caught ReferenceError via Exception")
-try:
- raise ReferenceError
-except ReferenceError:
- print("Caught ReferenceError")
+#try:
+# raise ReferenceError
+#except ReferenceError:
+# print("Caught ReferenceError")
-try:
- raise ResourceWarning
-except Warning:
- print("Caught ResourceWarning via Warning")
+#try:
+# raise ResourceWarning
+#except Warning:
+# print("Caught ResourceWarning via Warning")
-try:
- raise ResourceWarning
-except ResourceWarning:
- print("Caught ResourceWarning")
+#try:
+# raise ResourceWarning
+#except ResourceWarning:
+# print("Caught ResourceWarning")
try:
raise RuntimeError
@@ -268,15 +268,15 @@ try:
except RuntimeError:
print("Caught RuntimeError")
-try:
- raise RuntimeWarning
-except Warning:
- print("Caught RuntimeWarning via Warning")
+#try:
+# raise RuntimeWarning
+#except Warning:
+# print("Caught RuntimeWarning via Warning")
-try:
- raise RuntimeWarning
-except RuntimeWarning:
- print("Caught RuntimeWarning")
+#try:
+# raise RuntimeWarning
+#except RuntimeWarning:
+# print("Caught RuntimeWarning")
try:
raise SyntaxError
@@ -288,15 +288,15 @@ try:
except SyntaxError:
print("Caught SyntaxError")
-try:
- raise SyntaxWarning
-except Warning:
- print("Caught SyntaxWarning via Warning")
+#try:
+# raise SyntaxWarning
+#except Warning:
+# print("Caught SyntaxWarning via Warning")
-try:
- raise SyntaxWarning
-except SyntaxWarning:
- print("Caught SyntaxWarning")
+#try:
+# raise SyntaxWarning
+#except SyntaxWarning:
+# print("Caught SyntaxWarning")
try:
raise SystemError
@@ -308,15 +308,15 @@ try:
except SystemError:
print("Caught SystemError")
-try:
- raise TabError
-except IndentationError:
- print("Caught TabError via IndentationError")
+#try:
+# raise TabError
+#except IndentationError:
+# print("Caught TabError via IndentationError")
-try:
- raise TabError
-except TabError:
- print("Caught TabError")
+#try:
+# raise TabError
+#except TabError:
+# print("Caught TabError")
try:
raise TypeError
@@ -338,15 +338,15 @@ try:
except UnboundLocalError:
print("Caught UnboundLocalError")
-try:
- raise UserWarning
-except Warning:
- print("Caught UserWarning via Warning")
+#try:
+# raise UserWarning
+#except Warning:
+# print("Caught UserWarning via Warning")
-try:
- raise UserWarning
-except UserWarning:
- print("Caught UserWarning")
+#try:
+# raise UserWarning
+#except UserWarning:
+# print("Caught UserWarning")
try:
raise ValueError
@@ -358,15 +358,15 @@ try:
except ValueError:
print("Caught ValueError")
-try:
- raise Warning
-except Exception:
- print("Caught Warning via Exception")
+#try:
+# raise Warning
+#except Exception:
+# print("Caught Warning via Exception")
-try:
- raise Warning
-except Warning:
- print("Caught Warning")
+#try:
+# raise Warning
+#except Warning:
+# print("Caught Warning")
try:
raise ZeroDivisionError
diff --git a/tests/basics/string_rfind.py b/tests/basics/string_rfind.py
new file mode 100644
index 0000000000..4d0e84018f
--- /dev/null
+++ b/tests/basics/string_rfind.py
@@ -0,0 +1,23 @@
+print("hello world".rfind("ll"))
+print("hello world".rfind("ll", None))
+print("hello world".rfind("ll", 1))
+print("hello world".rfind("ll", 1, None))
+print("hello world".rfind("ll", None, None))
+print("hello world".rfind("ll", 1, -1))
+print("hello world".rfind("ll", 1, 1))
+print("hello world".rfind("ll", 1, 2))
+print("hello world".rfind("ll", 1, 3))
+print("hello world".rfind("ll", 1, 4))
+print("hello world".rfind("ll", 1, 5))
+print("hello world".rfind("ll", -100))
+print("0000".rfind('0'))
+print("0000".rfind('0', 0))
+print("0000".rfind('0', 1))
+print("0000".rfind('0', 2))
+print("0000".rfind('0', 3))
+print("0000".rfind('0', 4))
+print("0000".rfind('0', 5))
+print("0000".rfind('-1', 3))
+print("0000".rfind('1', 3))
+print("0000".rfind('1', 4))
+print("0000".rfind('1', 5))
diff --git a/tests/basics/try-as-var.py b/tests/basics/try-as-var.py
new file mode 100644
index 0000000000..0a92f1caee
--- /dev/null
+++ b/tests/basics/try-as-var.py
@@ -0,0 +1,10 @@
+try:
+ raise ValueError(534)
+except ValueError as e:
+ print(repr(e))
+
+# Var bound in except block is automatically deleted
+try:
+ e
+except NameError:
+ print("NameError")
diff --git a/tests/basics/types1.py b/tests/basics/types1.py
index 850b31b08c..57b33b842b 100644
--- a/tests/basics/types1.py
+++ b/tests/basics/types1.py
@@ -26,3 +26,8 @@ print(type(()) == tuple)
print(type([]) == list)
print(type({None}) == set)
print(type({}) == dict)
+
+try:
+ bool.foo
+except AttributeError:
+ print("AttributeError")
diff --git a/tools/pyboard.py b/tools/pyboard.py
new file mode 100644
index 0000000000..3ce6da5215
--- /dev/null
+++ b/tools/pyboard.py
@@ -0,0 +1,127 @@
+"""
+pyboard interface
+
+This module provides the Pyboard class, used to communicate with and
+control the pyboard over a serial USB connection.
+
+Example usage:
+
+ import pyboard
+ pyb = pyboard.Pyboard('/dev/ttyACM0')
+ pyb.enter_raw_repl()
+ pyb.exec('pyb.Led(1).on()')
+ pyb.exit_raw_repl()
+
+"""
+
+import time
+import serial
+
+class Pyboard:
+ def __init__(self, serial_device):
+ self.serial = serial.Serial(serial_device)
+
+ def close(self):
+ self.serial.close()
+
+ def enter_raw_repl(self):
+ self.serial.write(b'\r\x01') # ctrl-A: enter raw REPL
+ self.serial.write(b'\x04') # ctrl-D: soft reset
+ data = self.serial.read(1)
+ while self.serial.inWaiting() > 0:
+ data = data + self.serial.read(self.serial.inWaiting())
+ time.sleep(0.1)
+ if not data.endswith(b'raw REPL; CTRL-B to exit\r\n>'):
+ print(data)
+ raise Exception('could not enter raw repl')
+
+ def exit_raw_repl(self):
+ self.serial.write(b'\r\x02') # ctrl-B: enter friendly REPL
+
+ def eval(self, expression):
+ ret = self.exec('print({})'.format(expression))
+ ret = ret.strip()
+ return ret
+
+ def exec(self, command):
+ command_bytes = bytes(command, encoding='ascii')
+ for i in range(0, len(command_bytes), 10):
+ self.serial.write(command_bytes[i:min(i+10, len(command_bytes))])
+ time.sleep(0.01)
+ self.serial.write(b'\x04')
+ data = self.serial.read(2)
+ if data != b'OK':
+ raise Exception('could not exec command')
+ data = self.serial.read(2)
+ while self.serial.inWaiting() > 0:
+ data = data + self.serial.read(self.serial.inWaiting())
+ time.sleep(0.1)
+ if not data.endswith(b'\x04>'):
+ print(data)
+ raise Exception('could not exec command')
+ if data.startswith(b'Traceback') or data.startswith(b' File '):
+ print(data)
+ raise Exception('command failed')
+ return data[:-2]
+
+ def get_time(self):
+ t = str(self.exec('pyb.time()'), encoding='ascii').strip().split()[1].split(':')
+ return int(t[0]) * 3600 + int(t[1]) * 60 + int(t[2])
+
+def run_test():
+ device = '/dev/ttyACM0'
+ pyb = Pyboard(device)
+ pyb.enter_raw_repl()
+ print('opened device {}'.format(device))
+
+ print('seconds since boot:', pyb.get_time())
+
+ pyb.exec('def apply(l, f):\r\n for item in l:\r\n f(item)\r\n')
+
+ pyb.exec('leds=[pyb.Led(l) for l in range(1, 5)]')
+ pyb.exec('apply(leds, lambda l:l.off())')
+
+ ## USR switch test
+
+ if True:
+ for i in range(2):
+ print("press USR button")
+ pyb.exec('while pyb.switch(): pyb.delay(10)')
+ pyb.exec('while not pyb.switch(): pyb.delay(10)')
+
+ print('USR switch passed')
+
+ ## accel test
+
+ if True:
+ print("hold level")
+ pyb.exec('accel = pyb.Accel()')
+ pyb.exec('while abs(accel.x()) > 10 or abs(accel.y()) > 10: pyb.delay(10)')
+
+ print("tilt left")
+ pyb.exec('while accel.x() > -10: pyb.delay(10)')
+ pyb.exec('leds[0].on()')
+
+ print("tilt forward")
+ pyb.exec('while accel.y() < 10: pyb.delay(10)')
+ pyb.exec('leds[1].on()')
+
+ print("tilt right")
+ pyb.exec('while accel.x() < 10: pyb.delay(10)')
+ pyb.exec('leds[2].on()')
+
+ print("tilt backward")
+ pyb.exec('while accel.y() > -10: pyb.delay(10)')
+ pyb.exec('leds[3].on()')
+
+ print('accel passed')
+
+ print('seconds since boot:', pyb.get_time())
+
+ pyb.exec('apply(leds, lambda l:l.off())')
+
+ pyb.exit_raw_repl()
+ pyb.close()
+
+if __name__ == "__main__":
+ run_test()