summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/builtinmath.c24
-rw-r--r--py/obj.c11
-rw-r--r--py/obj.h1
-rw-r--r--py/objcomplex.c14
-rw-r--r--py/objfloat.c4
-rw-r--r--py/objint_longlong.c79
-rw-r--r--py/objint_mpz.c11
-rw-r--r--py/objtuple.c11
-rw-r--r--py/parsenum.c257
-rw-r--r--py/parsenum.h2
-rw-r--r--py/qstrdefs.h11
-rw-r--r--py/runtime.c2
-rw-r--r--stmhal/Makefile3
-rw-r--r--stmhal/accel.c137
-rw-r--r--stmhal/accel.h11
-rw-r--r--stmhal/import.c9
-rw-r--r--stmhal/led.c8
-rw-r--r--stmhal/led.h1
-rw-r--r--stmhal/main.c37
-rw-r--r--stmhal/pybmodule.c8
-rw-r--r--tests/basics/int-big-mod.py10
-rw-r--r--tests/basics/math-fun.py49
22 files changed, 515 insertions, 185 deletions
diff --git a/py/builtinmath.c b/py/builtinmath.c
index eeb715048a..fd1368ce3c 100644
--- a/py/builtinmath.c
+++ b/py/builtinmath.c
@@ -17,6 +17,7 @@
mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_float(y_obj))); } \
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name);
+STATIC const mp_obj_float_t mp_math_e_obj = {{&mp_type_float}, M_E};
STATIC const mp_obj_float_t mp_math_pi_obj = {{&mp_type_float}, M_PI};
MATH_FUN_1(sqrt, sqrt)
@@ -39,9 +40,22 @@ MATH_FUN_1(acos, acos)
MATH_FUN_1(asin, asin)
MATH_FUN_1(atan, atan)
MATH_FUN_2(atan2, atan2)
+MATH_FUN_1(ceil, ceil)
+MATH_FUN_2(copysign, copysign)
+MATH_FUN_1(fabs, fabs)
+MATH_FUN_1(floor, floor) //TODO: delegate to x.__floor__() if x is not a float
+MATH_FUN_2(fmod, fmod)
+//MATH_FUN_1(frexp, frexp)
+MATH_FUN_1(isfinite, isfinite)
+MATH_FUN_1(isinf, isinf)
+MATH_FUN_1(isnan, isnan)
+MATH_FUN_1(trunc, trunc)
+
+//TODO: factorial, fsum, frexp, ldexp, modf
STATIC const mp_map_elem_t mp_module_math_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_math) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_e), (mp_obj_t)&mp_math_e_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pi), (mp_obj_t)&mp_math_pi_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sqrt), (mp_obj_t)&mp_math_sqrt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pow), (mp_obj_t)&mp_math_pow_obj },
@@ -63,6 +77,16 @@ STATIC const mp_map_elem_t mp_module_math_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_asin), (mp_obj_t)&mp_math_asin_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_atan), (mp_obj_t)&mp_math_atan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_atan2), (mp_obj_t)&mp_math_atan2_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ceil), (mp_obj_t)&mp_math_ceil_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_copysign), (mp_obj_t)&mp_math_copysign_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_fabs), (mp_obj_t)&mp_math_fabs_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_floor), (mp_obj_t)&mp_math_floor_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_fmod), (mp_obj_t)&mp_math_fmod_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_frexp), (mp_obj_t)&mp_math_frexp_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_isfinite), (mp_obj_t)&mp_math_isfinite_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_isinf), (mp_obj_t)&mp_math_isinf_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_isnan), (mp_obj_t)&mp_math_isnan_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_trunc), (mp_obj_t)&mp_math_trunc_obj },
};
STATIC const mp_map_t mp_module_math_globals = {
diff --git a/py/obj.c b/py/obj.c
index e98dbae6cf..0c91e8f6d8 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -81,9 +81,16 @@ machine_int_t mp_obj_hash(mp_obj_t o_in) {
return mp_obj_str_get_hash(o_in);
} else if (MP_OBJ_IS_TYPE(o_in, &none_type)) {
return (machine_int_t)o_in;
+ } else if (MP_OBJ_IS_TYPE(o_in, &fun_native_type) || MP_OBJ_IS_TYPE(o_in, &fun_bc_type)) {
+ return (machine_int_t)o_in;
+ } else if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
+ return mp_obj_tuple_hash(o_in);
+
+ // TODO hash class and instances
+ // TODO delegate to __hash__ method if it exists
+
} else {
- assert(0);
- return 0;
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unhashable type: '%s'", mp_obj_get_type_str(o_in)));
}
}
diff --git a/py/obj.h b/py/obj.h
index dd80b3f021..1daa943447 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -330,6 +330,7 @@ mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_im
extern const mp_obj_type_t tuple_type;
void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
void mp_obj_tuple_del(mp_obj_t self_in);
+machine_int_t mp_obj_tuple_hash(mp_obj_t self_in);
// list
extern const mp_obj_type_t list_type;
diff --git a/py/objcomplex.c b/py/objcomplex.c
index 65957cbf60..2ba5226150 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -6,6 +6,7 @@
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
+#include "parsenum.h"
#include "runtime0.h"
#include "map.h"
@@ -36,15 +37,20 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
return mp_obj_new_complex(0, 0);
case 1:
- // TODO allow string as first arg and parse it
- if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) {
+ if (MP_OBJ_IS_STR(args[0])) {
+ // a string, parse it
+ uint l;
+ const char *s = mp_obj_str_get_data(args[0], &l);
+ return mp_parse_num_decimal(s, l, true, true);
+ } else if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) {
+ // a complex, just return it
return args[0];
} else {
+ // something else, try to cast it to a complex
return mp_obj_new_complex(mp_obj_get_float(args[0]), 0);
}
- case 2:
- {
+ case 2: {
mp_float_t real, imag;
if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) {
mp_obj_complex_get(args[0], &real, &imag);
diff --git a/py/objfloat.c b/py/objfloat.c
index 401c1145ee..c51e13e7a1 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -38,10 +38,12 @@ STATIC mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
// a string, parse it
uint l;
const char *s = mp_obj_str_get_data(args[0], &l);
- return mp_parse_num_decimal(s, l);
+ return mp_parse_num_decimal(s, l, false, false);
} else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) {
+ // a float, just return it
return args[0];
} else {
+ // something else, try to cast it to a float
return mp_obj_new_float(mp_obj_get_float(args[0]));
}
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index 52aaa9e7b5..6a0dfa70e9 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -41,80 +41,71 @@ mp_obj_t int_unary_op(int op, mp_obj_t o_in) {
}
mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
- mp_obj_int_t *lhs = lhs_in;
- mp_obj_int_t *rhs = rhs_in;
+ long long lhs_val;
long long rhs_val;
- // TODO it can be that lhs is a small int (eg 1 + longlong)
- // TODO inplace operations should not modify the int!
+ if (MP_OBJ_IS_SMALL_INT(lhs_in)) {
+ lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs_in);
+ } else if (MP_OBJ_IS_TYPE(lhs_in, &int_type)) {
+ lhs_val = ((mp_obj_int_t*)lhs_in)->val;
+ } else {
+ return MP_OBJ_NULL;
+ }
- if (MP_OBJ_IS_SMALL_INT(rhs)) {
- rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
- } else if (MP_OBJ_IS_TYPE(rhs, &int_type)) {
- rhs_val = rhs->val;
+ if (MP_OBJ_IS_SMALL_INT(rhs_in)) {
+ rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs_in);
+ } else if (MP_OBJ_IS_TYPE(rhs_in, &int_type)) {
+ rhs_val = ((mp_obj_int_t*)rhs_in)->val;
} else {
return MP_OBJ_NULL;
}
switch (op) {
case RT_BINARY_OP_ADD:
- return mp_obj_new_int_from_ll(lhs->val + rhs_val);
- case RT_BINARY_OP_SUBTRACT:
- return mp_obj_new_int_from_ll(lhs->val - rhs_val);
- case RT_BINARY_OP_MULTIPLY:
- return mp_obj_new_int_from_ll(lhs->val * rhs_val);
- case RT_BINARY_OP_FLOOR_DIVIDE:
- return mp_obj_new_int_from_ll(lhs->val / rhs_val);
- case RT_BINARY_OP_MODULO:
- return mp_obj_new_int_from_ll(lhs->val % rhs_val);
-
case RT_BINARY_OP_INPLACE_ADD:
- lhs->val += rhs_val; return lhs;
+ return mp_obj_new_int_from_ll(lhs_val + rhs_val);
+ case RT_BINARY_OP_SUBTRACT:
case RT_BINARY_OP_INPLACE_SUBTRACT:
- lhs->val -= rhs_val; return lhs;
+ return mp_obj_new_int_from_ll(lhs_val - rhs_val);
+ case RT_BINARY_OP_MULTIPLY:
case RT_BINARY_OP_INPLACE_MULTIPLY:
- lhs->val *= rhs_val; return lhs;
+ return mp_obj_new_int_from_ll(lhs_val * rhs_val);
+ case RT_BINARY_OP_FLOOR_DIVIDE:
case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE:
- lhs->val /= rhs_val; return lhs;
+ return mp_obj_new_int_from_ll(lhs_val / rhs_val);
+ case RT_BINARY_OP_MODULO:
case RT_BINARY_OP_INPLACE_MODULO:
- lhs->val %= rhs_val; return lhs;
+ return mp_obj_new_int_from_ll(lhs_val % rhs_val);
case RT_BINARY_OP_AND:
- return mp_obj_new_int_from_ll(lhs->val & rhs_val);
- case RT_BINARY_OP_OR:
- return mp_obj_new_int_from_ll(lhs->val | rhs_val);
- case RT_BINARY_OP_XOR:
- return mp_obj_new_int_from_ll(lhs->val ^ rhs_val);
-
case RT_BINARY_OP_INPLACE_AND:
- lhs->val &= rhs_val; return lhs;
+ return mp_obj_new_int_from_ll(lhs_val & rhs_val);
+ case RT_BINARY_OP_OR:
case RT_BINARY_OP_INPLACE_OR:
- lhs->val |= rhs_val; return lhs;
+ return mp_obj_new_int_from_ll(lhs_val | rhs_val);
+ case RT_BINARY_OP_XOR:
case RT_BINARY_OP_INPLACE_XOR:
- lhs->val ^= rhs_val; return lhs;
+ return mp_obj_new_int_from_ll(lhs_val ^ rhs_val);
case RT_BINARY_OP_LSHIFT:
- return mp_obj_new_int_from_ll(lhs->val << (int)rhs_val);
- case RT_BINARY_OP_RSHIFT:
- return mp_obj_new_int_from_ll(lhs->val >> (int)rhs_val);
-
case RT_BINARY_OP_INPLACE_LSHIFT:
- lhs->val <<= (int)rhs_val; return lhs;
+ return mp_obj_new_int_from_ll(lhs_val << (int)rhs_val);
+ case RT_BINARY_OP_RSHIFT:
case RT_BINARY_OP_INPLACE_RSHIFT:
- lhs->val >>= (int)rhs_val; return lhs;
+ return mp_obj_new_int_from_ll(lhs_val >> (int)rhs_val);
case RT_BINARY_OP_LESS:
- return MP_BOOL(lhs->val < rhs_val);
+ return MP_BOOL(lhs_val < rhs_val);
case RT_BINARY_OP_MORE:
- return MP_BOOL(lhs->val > rhs_val);
+ return MP_BOOL(lhs_val > rhs_val);
case RT_BINARY_OP_LESS_EQUAL:
- return MP_BOOL(lhs->val <= rhs_val);
+ return MP_BOOL(lhs_val <= rhs_val);
case RT_BINARY_OP_MORE_EQUAL:
- return MP_BOOL(lhs->val >= rhs_val);
+ return MP_BOOL(lhs_val >= rhs_val);
case RT_BINARY_OP_EQUAL:
- return MP_BOOL(lhs->val == rhs_val);
+ return MP_BOOL(lhs_val == rhs_val);
case RT_BINARY_OP_NOT_EQUAL:
- return MP_BOOL(lhs->val != rhs_val);
+ return MP_BOOL(lhs_val != rhs_val);
default:
// op not supported
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 342e8ec276..21e3202a95 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -100,9 +100,14 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mpz_deinit(&rem);
break;
}
-
- //case RT_BINARY_OP_MODULO:
- //case RT_BINARY_OP_INPLACE_MODULO:
+ case RT_BINARY_OP_MODULO:
+ case RT_BINARY_OP_INPLACE_MODULO: {
+ // TODO check that this operation matches the CPython operation
+ mpz_t quo; mpz_init_zero(&quo);
+ mpz_divmod_inpl(&quo, &res->mpz, zlhs, zrhs);
+ mpz_deinit(&quo);
+ break;
+ }
//case RT_BINARY_OP_AND:
//case RT_BINARY_OP_INPLACE_AND:
diff --git a/py/objtuple.c b/py/objtuple.c
index 83d1f21cea..3378b4ec1c 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -218,6 +218,17 @@ void mp_obj_tuple_del(mp_obj_t self_in) {
m_del_var(mp_obj_tuple_t, mp_obj_t, self->len, self);
}
+machine_int_t mp_obj_tuple_hash(mp_obj_t self_in) {
+ assert(MP_OBJ_IS_TYPE(self_in, &tuple_type));
+ mp_obj_tuple_t *self = self_in;
+ // start hash with pointer to empty tuple, to make it fairly unique
+ machine_int_t hash = (machine_int_t)mp_const_empty_tuple;
+ for (uint i = 0; i < self->len; i++) {
+ hash += mp_obj_hash(self->items[i]);
+ }
+ return hash;
+}
+
/******************************************************************************/
/* tuple iterator */
diff --git a/py/parsenum.c b/py/parsenum.c
index c9cef5fcd8..6be042fe89 100644
--- a/py/parsenum.c
+++ b/py/parsenum.c
@@ -9,139 +9,208 @@
#include "parsenumbase.h"
#include "parsenum.h"
-#if defined(UNIX)
-
-#include <ctype.h>
-#include <errno.h>
+#if MICROPY_ENABLE_FLOAT
+#include <math.h>
+#endif
mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) {
- // TODO at the moment we ignore len; we should honour it!
- // TODO detect integer overflow and return bignum
-
- int c, neg = 0;
- const char *p = str;
- char *num;
- long found;
+ const char *restrict top = str + len;
+ bool neg = false;
// check radix base
if ((base != 0 && base < 2) || base > 36) {
nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "ValueError: int() arg 2 must be >=2 and <= 36"));
}
- // skip surrounded whitespace
- while (isspace((c = *(p++))));
- if (c == 0) {
- goto value_error;
- }
- // preced sign
- if (c == '+' || c == '-') {
- neg = - (c == '-');
- } else {
- p--;
+
+ // skip leading space
+ for (; str < top && unichar_isspace(*str); str++) {
}
- len -= p - str;
- int skip = mp_parse_num_base(p, len, &base);
- p += skip;
- len -= skip;
-
- errno = 0;
- found = strtol(p, &num, base);
- if (errno) {
- goto value_error;
- } else if (found && *(num) == 0) {
- goto done;
- } else if (found || num != p) {
- goto check_tail_space;
- } else {
- goto value_error;
+ // parse optional sign
+ if (str < top) {
+ if (*str == '+') {
+ str++;
+ } else if (*str == '-') {
+ str++;
+ neg = true;
+ }
}
-check_tail_space:
- if (*(num) != 0) {
- while (isspace((c = *(num++))));
- if (c != 0) {
- goto value_error;
+ // parse optional base prefix
+ str += mp_parse_num_base(str, top - str, &base);
+
+ // string should be an integer number
+ machine_int_t int_val = 0;
+ for (; str < top; str++) {
+ machine_int_t old_val = int_val;
+ int dig = *str;
+ if (unichar_isdigit(dig) && dig - '0' < base) {
+ // 0-9 digit
+ int_val = base * int_val + dig - '0';
+ } else if (base == 16) {
+ dig |= 0x20;
+ if ('a' <= dig && dig <= 'f') {
+ // a-f hex digit
+ int_val = base * int_val + dig - 'a' + 10;
+ } else {
+ // unknown character
+ break;
+ }
+ } else {
+ // unknown character
+ break;
+ }
+ if (int_val < old_val) {
+ // If new value became less than previous, it's overflow
+ goto overflow;
+ } else if ((old_val ^ int_val) & WORD_MSBIT_HIGH) {
+ // If signed number changed sign - it's overflow
+ goto overflow;
}
}
-done:
- return MP_OBJ_NEW_SMALL_INT((found ^ neg) - neg);
+ // negate value if needed
+ if (neg) {
+ int_val = -int_val;
+ }
-value_error:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid literal for int() with base %d: '%s'", base, str));
-}
+ // skip trailing space
+ for (; str < top && unichar_isspace(*str); str++) {
+ }
-#else /* defined(UNIX) */
+ // check we reached the end of the string
+ if (str != top) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number"));
+ }
-mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) {
- // TODO port strtol to stm
- return MP_OBJ_NEW_SMALL_INT(0);
-}
+ // return the object
+ return MP_OBJ_NEW_SMALL_INT(int_val);
-#endif /* defined(UNIX) */
+overflow:
+ // TODO reparse using bignum
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "overflow parsing integer"));
+}
#define PARSE_DEC_IN_INTG (1)
#define PARSE_DEC_IN_FRAC (2)
#define PARSE_DEC_IN_EXP (3)
-mp_obj_t mp_parse_num_decimal(const char *str, uint len) {
+mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool force_complex) {
#if MICROPY_ENABLE_FLOAT
- int in = PARSE_DEC_IN_INTG;
+ const char *top = str + len;
mp_float_t dec_val = 0;
- bool exp_neg = false;
- int exp_val = 0;
- int exp_extra = 0;
+ bool dec_neg = false;
bool imag = false;
- const char *top = str + len;
- for (; str < top; str++) {
- int dig = *str;
- if ('0' <= dig && dig <= '9') {
- dig -= '0';
- if (in == PARSE_DEC_IN_EXP) {
- exp_val = 10 * exp_val + dig;
- } else {
- dec_val = 10 * dec_val + dig;
- if (in == PARSE_DEC_IN_FRAC) {
- exp_extra -= 1;
- }
+
+ // skip leading space
+ for (; str < top && unichar_isspace(*str); str++) {
+ }
+
+ // parse optional sign
+ if (str < top) {
+ if (*str == '+') {
+ str++;
+ } else if (*str == '-') {
+ str++;
+ dec_neg = true;
+ }
+ }
+
+ // determine what the string is
+ if (str < top && (str[0] | 0x20) == 'i') {
+ // string starts with 'i', should be 'inf' or 'infinity' (case insensitive)
+ if (str + 2 < top && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'f') {
+ // inf
+ str += 3;
+ dec_val = INFINITY;
+ if (str + 4 < top && (str[0] | 0x20) == 'i' && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'i' && (str[3] | 0x20) == 't' && (str[4] | 0x20) == 'y') {
+ // infinity
+ str += 5;
}
- } else if (in == PARSE_DEC_IN_INTG && dig == '.') {
- in = PARSE_DEC_IN_FRAC;
- } else if (in != PARSE_DEC_IN_EXP && (dig == 'E' || dig == 'e')) {
- in = PARSE_DEC_IN_EXP;
- if (str[1] == '+') {
- str++;
- } else if (str[1] == '-') {
+ }
+ } else if (str < top && (str[0] | 0x20) == 'n') {
+ // string starts with 'n', should be 'nan' (case insensitive)
+ if (str + 2 < top && (str[1] | 0x20) == 'a' && (str[2] | 0x20) == 'n') {
+ // NaN
+ str += 3;
+ dec_val = MICROPY_FLOAT_C_FUN(nan)("");
+ }
+ } else {
+ // string should be a decimal number
+ int in = PARSE_DEC_IN_INTG;
+ bool exp_neg = false;
+ int exp_val = 0;
+ int exp_extra = 0;
+ for (; str < top; str++) {
+ int dig = *str;
+ if ('0' <= dig && dig <= '9') {
+ dig -= '0';
+ if (in == PARSE_DEC_IN_EXP) {
+ exp_val = 10 * exp_val + dig;
+ } else {
+ dec_val = 10 * dec_val + dig;
+ if (in == PARSE_DEC_IN_FRAC) {
+ exp_extra -= 1;
+ }
+ }
+ } else if (in == PARSE_DEC_IN_INTG && dig == '.') {
+ in = PARSE_DEC_IN_FRAC;
+ } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20) == 'e')) {
+ in = PARSE_DEC_IN_EXP;
+ if (str[1] == '+') {
+ str++;
+ } else if (str[1] == '-') {
+ str++;
+ exp_neg = true;
+ }
+ } else if (allow_imag && (dig | 0x20) == 'j') {
str++;
- exp_neg = true;
+ imag = true;
+ break;
+ } else {
+ // unknown character
+ break;
}
- } else if (dig == 'J' || dig == 'j') {
- str++;
- imag = true;
- break;
- } else {
- // unknown character
- break;
+ }
+
+ // work out the exponent
+ if (exp_neg) {
+ exp_val = -exp_val;
+ }
+ exp_val += exp_extra;
+
+ // apply the exponent
+ for (; exp_val > 0; exp_val--) {
+ dec_val *= 10;
+ }
+ for (; exp_val < 0; exp_val++) {
+ dec_val *= 0.1;
}
}
- if (*str != 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number"));
- }
- if (exp_neg) {
- exp_val = -exp_val;
+
+ // negate value if needed
+ if (dec_neg) {
+ dec_val = -dec_val;
}
- exp_val += exp_extra;
- for (; exp_val > 0; exp_val--) {
- dec_val *= 10;
+
+ // skip trailing space
+ for (; str < top && unichar_isspace(*str); str++) {
}
- for (; exp_val < 0; exp_val++) {
- dec_val *= 0.1;
+
+ // check we reached the end of the string
+ if (str != top) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number"));
}
+
+ // return the object
if (imag) {
return mp_obj_new_complex(0, dec_val);
+ } else if (force_complex) {
+ return mp_obj_new_complex(dec_val, 0);
} else {
return mp_obj_new_float(dec_val);
}
+
#else
nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "decimal numbers not supported"));
#endif
diff --git a/py/parsenum.h b/py/parsenum.h
index 5a2e42da50..97578423c7 100644
--- a/py/parsenum.h
+++ b/py/parsenum.h
@@ -1,2 +1,2 @@
mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base);
-mp_obj_t mp_parse_num_decimal(const char *str, uint len);
+mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool force_complex);
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 8f6cc1167f..649f89eb1e 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -119,6 +119,7 @@ Q(module)
Q(slice)
Q(math)
+Q(e)
Q(pi)
Q(sqrt)
Q(pow)
@@ -140,6 +141,16 @@ Q(acos)
Q(asin)
Q(atan)
Q(atan2)
+Q(ceil)
+Q(copysign)
+Q(fabs)
+Q(floor)
+Q(fmod)
+Q(frexp)
+Q(isfinite)
+Q(isinf)
+Q(isnan)
+Q(trunc)
Q(mem_total)
Q(mem_current)
diff --git a/py/runtime.c b/py/runtime.c
index 9c8ba636c0..c268fd5464 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -375,7 +375,7 @@ mp_obj_t rt_load_const_dec(qstr qstr) {
DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
uint len;
const byte* data = qstr_data(qstr, &len);
- return mp_parse_num_decimal((const char*)data, len);
+ return mp_parse_num_decimal((const char*)data, len, true, false);
}
mp_obj_t rt_load_const_str(qstr qstr) {
diff --git a/stmhal/Makefile b/stmhal/Makefile
index 9f3e365a19..a1a5a1db68 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -84,9 +84,9 @@ SRC_C = \
sdcard.c \
diskio.c \
lcd.c \
+ accel.c \
# servo.c \
-# accel.c \
# timer.c \
# audio.c \
# i2c.c \
@@ -104,6 +104,7 @@ SRC_HAL = $(addprefix $(HAL_DIR)/src/,\
stm32f4xx_hal_flash.c \
stm32f4xx_hal_flash_ex.c \
stm32f4xx_hal_gpio.c \
+ stm32f4xx_hal_i2c.c \
stm32f4xx_hal_pcd.c \
stm32f4xx_hal_rcc.c \
stm32f4xx_hal_rcc_ex.c \
diff --git a/stmhal/accel.c b/stmhal/accel.c
new file mode 100644
index 0000000000..f380242bf6
--- /dev/null
+++ b/stmhal/accel.c
@@ -0,0 +1,137 @@
+#include <stdio.h>
+#include <string.h>
+
+#include <stm32f4xx_hal.h>
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "accel.h"
+
+#define MMA_ADDR (0x98)
+#define MMA_REG_MODE (7)
+
+STATIC I2C_HandleTypeDef I2cHandle;
+
+void accel_init(void) {
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ // PB5 is connected to AVDD; pull high to enable MMA accel device
+ GPIOB->BSRRH = GPIO_PIN_5; // turn off AVDD
+ GPIO_InitStructure.Pin = GPIO_PIN_5;
+ GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+ // wait 20ms, then turn on AVDD, then wait 20ms again
+ HAL_Delay(20);
+ GPIOB->BSRRL = GPIO_PIN_5;
+ HAL_Delay(20);
+
+ // 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;
+ }
+
+ HAL_StatusTypeDef status;
+
+ //printf("IsDeviceReady\n");
+ for (int i = 0; i < 10; i++) {
+ status = HAL_I2C_IsDeviceReady(&I2cHandle, MMA_ADDR, 10, 200);
+ //printf(" got %d\n", status);
+ if (status == HAL_OK) {
+ break;
+ }
+ }
+
+ //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);
+ //printf(" got %d\n", status);
+}
+
+/******************************************************************************/
+/* Micro Python bindings */
+
+int accel_buf[12];
+
+mp_obj_t pyb_accel_read(void) {
+ for (int i = 0; i <= 6; i += 3) {
+ accel_buf[0 + i] = accel_buf[0 + i + 3];
+ accel_buf[1 + i] = accel_buf[1 + i + 3];
+ accel_buf[2 + i] = accel_buf[2 + i + 3];
+ }
+
+ uint8_t data_[4];
+ HAL_I2C_Mem_Read(&I2cHandle, MMA_ADDR, 0, I2C_MEMADD_SIZE_8BIT, data_, 4, 200);
+ accel_buf[9] = data_[0] & 0x3f; if (accel_buf[9] & 0x20) accel_buf[9] |= ~0x1f;
+ accel_buf[10] = data_[1] & 0x3f; if (accel_buf[10] & 0x20) accel_buf[10] |= ~0x1f;
+ accel_buf[11] = data_[2] & 0x3f; if (accel_buf[11] & 0x20) accel_buf[11] |= ~0x1f;
+ int jolt_info = data_[3];
+
+ mp_obj_t data[4];
+ data[0] = mp_obj_new_int(accel_buf[0] + accel_buf[3] + accel_buf[6] + accel_buf[9]);
+ data[1] = mp_obj_new_int(accel_buf[1] + accel_buf[4] + accel_buf[7] + accel_buf[10]);
+ data[2] = mp_obj_new_int(accel_buf[2] + accel_buf[5] + accel_buf[8] + accel_buf[11]);
+ data[3] = mp_obj_new_int(jolt_info);
+
+ return rt_build_tuple(4, data);
+}
+
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_accel_read_obj, pyb_accel_read);
+
+/*
+mp_obj_t pyb_accel_read_all(void) {
+ mp_obj_t data[11];
+ accel_start(MMA_ADDR, 1);
+ accel_send_byte(0);
+ accel_restart(MMA_ADDR, 0);
+ for (int i = 0; i <= 9; i++) {
+ data[i] = mp_obj_new_int(accel_read_ack());
+ }
+ data[10] = mp_obj_new_int(accel_read_nack());
+
+ return rt_build_tuple(11, data);
+}
+
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_accel_read_all_obj, pyb_accel_read_all);
+
+mp_obj_t pyb_accel_write_mode(mp_obj_t o_int, mp_obj_t o_mode) {
+ accel_start(MMA_ADDR, 1);
+ accel_send_byte(6); // start at int
+ accel_send_byte(mp_obj_get_int(o_int));
+ accel_send_byte(mp_obj_get_int(o_mode));
+ accel_stop();
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_2(pyb_accel_write_mode_obj, pyb_accel_write_mode);
+*/
diff --git a/stmhal/accel.h b/stmhal/accel.h
new file mode 100644
index 0000000000..c2320f1a4e
--- /dev/null
+++ b/stmhal/accel.h
@@ -0,0 +1,11 @@
+void accel_init(void);
+void accel_restart(uint8_t addr, int write);
+void accel_start(uint8_t addr, int write);
+void accel_send_byte(uint8_t data);
+uint8_t accel_read_ack(void);
+uint8_t accel_read_nack(void);
+void accel_stop(void);
+
+MP_DECLARE_CONST_FUN_OBJ(pyb_accel_read_obj);
+MP_DECLARE_CONST_FUN_OBJ(pyb_accel_read_all_obj);
+MP_DECLARE_CONST_FUN_OBJ(pyb_accel_write_mode_obj);
diff --git a/stmhal/import.c b/stmhal/import.c
index f2fd3b3dee..c977dcf2ec 100644
--- a/stmhal/import.c
+++ b/stmhal/import.c
@@ -1,16 +1,18 @@
+#include <stdio.h>
#include <stdint.h>
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "lexer.h"
-#if 0
#include "ff.h"
-#endif
mp_import_stat_t mp_import_stat(const char *path) {
-#if 0
FILINFO fno;
+#if _USE_LFN
+ fno.lfname = NULL;
+ fno.lfsize = 0;
+#endif
FRESULT res = f_stat(path, &fno);
if (res == FR_OK) {
if ((fno.fattrib & AM_DIR) != 0) {
@@ -19,6 +21,5 @@ mp_import_stat_t mp_import_stat(const char *path) {
return MP_IMPORT_STAT_FILE;
}
}
-#endif
return MP_IMPORT_STAT_NO_EXIST;
}
diff --git a/stmhal/led.c b/stmhal/led.c
index 677c151b33..80c1e145f1 100644
--- a/stmhal/led.c
+++ b/stmhal/led.c
@@ -73,6 +73,14 @@ void led_toggle(pyb_led_t led) {
}
}
+void led_debug(int n, int delay) {
+ led_state(1, n & 1);
+ led_state(2, n & 2);
+ led_state(3, n & 4);
+ led_state(4, n & 8);
+ HAL_Delay(delay);
+}
+
/******************************************************************************/
/* Micro Python bindings */
diff --git a/stmhal/led.h b/stmhal/led.h
index 44c68d4ebe..b3762271c1 100644
--- a/stmhal/led.h
+++ b/stmhal/led.h
@@ -19,5 +19,6 @@ typedef enum {
void led_init(void);
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);
diff --git a/stmhal/main.c b/stmhal/main.c
index d77733429b..522ebfa6b1 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -33,9 +33,9 @@
#include "sdcard.h"
#include "ff.h"
#include "lcd.h"
+#include "accel.h"
#if 0
#include "servo.h"
-#include "accel.h"
#include "timer.h"
#include "pybwlan.h"
#include "pin.h"
@@ -170,22 +170,6 @@ int main(void) {
// enable the CCM RAM
__CCMDATARAMEN_CLK_ENABLE();
- // some test code to flash LEDs
- led_init();
-
- led_state(0, 1);
- led_state(1, 0);
- led_state(2, 1);
-
-#if 0
- for (;;) {
- HAL_Delay(500);
- led_state(1, 1);
- HAL_Delay(500);
- led_state(1, 0);
- }
-#endif
-
#if 0
#if defined(NETDUINO_PLUS_2)
{
@@ -348,6 +332,11 @@ soft_reset:
// make sure we have a /boot.py
{
FILINFO fno;
+#if _USE_LFN
+ fno.lfname = NULL;
+ fno.lfsize = 0;
+#endif
+ led_debug(0, 500);
FRESULT res = f_stat("0:/boot.py", &fno);
if (res == FR_OK) {
if (fno.fattrib & AM_DIR) {
@@ -382,15 +371,6 @@ soft_reset:
flash_error(4);
}
- if (first_soft_reset) {
-#if 0
-#if MICROPY_HW_HAS_MMA7660
- // MMA accel: init and reset address to zero
- accel_init();
-#endif
-#endif
- }
-
// turn boot-up LED off
led_state(PYB_LED_GREEN, 0);
@@ -419,6 +399,11 @@ soft_reset:
pyb_usb_dev_init(PYB_USB_DEV_VCP_MSC);
#endif
+#if MICROPY_HW_HAS_MMA7660
+ // MMA accel: init and reset
+ accel_init();
+#endif
+
// run main script
{
vstr_t *vstr = vstr_new();
diff --git a/stmhal/pybmodule.c b/stmhal/pybmodule.c
index b6b269b065..3db23dc6de 100644
--- a/stmhal/pybmodule.c
+++ b/stmhal/pybmodule.c
@@ -21,10 +21,10 @@
#include "usart.h"
#include "storage.h"
#include "sdcard.h"
+#include "accel.h"
#if 0
#include "servo.h"
#include "usb.h"
-#include "accel.h"
#include "i2c.h"
#include "adc.h"
#include "audio.h"
@@ -256,13 +256,13 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sdcard_obj },
#endif
-#if 0
#if MICROPY_HW_HAS_MMA7660
{ MP_OBJ_NEW_QSTR(MP_QSTR_accel), (mp_obj_t)&pyb_accel_read_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_accel_read), (mp_obj_t)&pyb_accel_read_all_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_accel_mode), (mp_obj_t)&pyb_accel_write_mode_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_accel_read), (mp_obj_t)&pyb_accel_read_all_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_accel_mode), (mp_obj_t)&pyb_accel_write_mode_obj },
#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 },
diff --git a/tests/basics/int-big-mod.py b/tests/basics/int-big-mod.py
new file mode 100644
index 0000000000..77c0ffc468
--- /dev/null
+++ b/tests/basics/int-big-mod.py
@@ -0,0 +1,10 @@
+# test % operation on big integers
+
+delta = 100000000000000000000000000000012345
+
+for i in range(11):
+ for j in range(11):
+ x = delta * (i)# - 5) # TODO reinstate negative number test when % is working with sign correctly
+ y = delta * (j)# - 5) # TODO reinstate negative number test when % is working with sign correctly
+ if y != 0:
+ print(x % y)
diff --git a/tests/basics/math-fun.py b/tests/basics/math-fun.py
new file mode 100644
index 0000000000..f5ffbf40d5
--- /dev/null
+++ b/tests/basics/math-fun.py
@@ -0,0 +1,49 @@
+# Tests the functions imported from math
+
+from math import *
+
+test_values = [-100., -1.23456, -1, -0.5, 0.0, 0.5, 1.23456, 100.]
+p_test_values = [0.1, 0.5, 1.23456]
+unit_range_test_values = [-1., -0.75, -0.5, -0.25, 0., 0.25, 0.5, 0.75, 1.]
+#IEEE_test_values = [1, 0, float('NaN'), float('Inf'), -float('NaN'), -float('Inf')]
+#TODO: float('NaN')
+
+functions = [(sqrt, p_test_values),
+ (exp, test_values),
+ (expm1, test_values),
+ (log, p_test_values),
+ (log2, p_test_values),
+ (log10, p_test_values),
+ (cosh, test_values),
+ (sinh, test_values),
+ (tanh, test_values),
+ (acosh, [1.0, 5.0, 1.0]),
+ (asinh, test_values),
+ (atanh, [-0.99, -0.5, 0.0, 0.5, 0.99]),
+ (cos, test_values),
+ (sin, test_values),
+ (tan, test_values),
+ (acos, unit_range_test_values),
+ (asin, unit_range_test_values),
+ (atan, test_values),
+ (ceil, test_values),
+ (fabs, test_values),
+ (floor, test_values),
+ #(frexp, test_values),
+ #(isfinite, [1, 0, float('NaN'), float('Inf')])
+ (trunc, test_values)
+ ]
+
+for function, test_vals in functions:
+ for value in test_vals:
+ print("{:8.7f}".format(function(value)))
+
+binary_functions = [(copysign, [(23., 42.), (-23., 42.), (23., -42.),
+ (-23., -42.), (1., 0.0), (1., -0.0)])
+ ]
+
+#for function, test_vals in binary_functions:
+# for value1, value2 in test_vals:
+# print("{:8.7f}".format(function(value1, value2)))
+
+