// Helper function to compute PWM value from timer period and percent value. // 'percent_in' can be an int or a float between 0 and 100 (out of range // values are clamped). STATIC uint32_t compute_pwm_value_from_percent(uint32_t period, mp_obj_t percent_in) { uint32_t cmp; if (0) { #if MICROPY_PY_BUILTINS_FLOAT } else if (MP_OBJ_IS_TYPE(percent_in, &mp_type_float)) { float percent = mp_obj_get_float(percent_in); if (percent <= 0.0) { cmp = 0; } else if (percent >= 100.0) { cmp = period; } else { cmp = percent / 100.0 * ((float)period); } #endif } else { // For integer arithmetic, if period is large and 100*period will // overflow, then divide period before multiplying by cmp. Otherwise // do it the other way round to retain precision. mp_int_t percent = mp_obj_get_int(percent_in); if (percent <= 0) { cmp = 0; } else if (percent >= 100) { cmp = period; } else if (period > MAX_PERIOD_DIV_100) { cmp = (uint32_t)percent * (period / 100); } else { cmp = ((uint32_t)percent * period) / 100; } } return cmp; }
// log(x[, base]) STATIC mp_obj_t mp_math_log(size_t n_args, const mp_obj_t *args) { mp_float_t x = mp_obj_get_float(args[0]); if (x <= (mp_float_t)0.0) { math_error(); } mp_float_t l = MICROPY_FLOAT_C_FUN(log)(x); if (n_args == 1) { return mp_obj_new_float(l); } else { mp_float_t base = mp_obj_get_float(args[1]); if (base <= (mp_float_t)0.0) { math_error(); } return mp_obj_new_float(l / MICROPY_FLOAT_C_FUN(log)(base)); } }
// Helper function to compute PWM value from timer period and percent value. // 'val' can be an int or a float between 0 and 100 (out of range values are // clamped). STATIC uint32_t compute_pwm_value_from_percent(uint32_t period, mp_obj_t percent_in) { uint32_t cmp; if (0) { #if MICROPY_PY_BUILTINS_FLOAT } else if (MP_OBJ_IS_TYPE(percent_in, &mp_type_float)) { float percent = mp_obj_get_float(percent_in); if (percent <= 0.0) { cmp = 0; } else if (percent >= 100.0) { cmp = period; } else { cmp = percent / 100.0 * ((float)period); } #endif } else { mp_int_t percent = mp_obj_get_int(percent_in); if (percent <= 0) { cmp = 0; } else if (percent >= 100) { cmp = period; } else { cmp = ((uint32_t)percent * period) / 100; } } return cmp; }
static mp_obj_t py_image_blend(mp_obj_t dst_image_obj, mp_obj_t src_image_obj, mp_obj_t param_obj) { int x,y; float alpha; image_t *src_image = NULL; image_t *dst_image = NULL; /* get C image pointer */ src_image = py_image_cobj(src_image_obj); dst_image = py_image_cobj(dst_image_obj); /* get x,y,alpha */ mp_obj_t *array; mp_obj_get_array_fixed_n(param_obj, 3, &array); x = mp_obj_get_int(array[0]); y = mp_obj_get_int(array[1]); alpha = mp_obj_get_float(array[2]); if ((src_image->w+x)>dst_image->w || (src_image->h+y)>dst_image->h) { printf("src image > dst image\n"); return mp_const_none; } imlib_blend(src_image, dst_image, x, y, (uint8_t)(alpha*256)); return mp_const_none; }
STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) { #if MICROPY_PY_BUILTINS_FLOAT struct timeval tv; mp_float_t val = mp_obj_get_float(arg); double ipart; tv.tv_usec = round(modf(val, &ipart) * 1000000); tv.tv_sec = ipart; int res; while (1) { MP_THREAD_GIL_EXIT(); res = sleep_select(0, NULL, NULL, NULL, &tv); MP_THREAD_GIL_ENTER(); #if MICROPY_SELECT_REMAINING_TIME // TODO: This assumes Linux behavior of modifying tv to the remaining // time. if (res != -1 || errno != EINTR) { break; } if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { return mp_const_none; } //printf("select: EINTR: %ld:%ld\n", tv.tv_sec, tv.tv_usec); #else break; #endif } RAISE_ERRNO(res, errno); #else // TODO: Handle EINTR MP_THREAD_GIL_EXIT(); sleep(mp_obj_get_int(arg)); MP_THREAD_GIL_ENTER(); #endif return mp_const_none; }
// Helper function to compute PWM value from timer period and percent value. // 'val' can be an int or a float between 0 and 100 (out of range values are // clamped). STATIC uint32_t compute_pwm_value_from_percent(uint32_t period, mp_obj_t val) { uint32_t cmp; if (0) { #if MICROPY_PY_BUILTINS_FLOAT } else if (MP_OBJ_IS_TYPE(val, &mp_type_float)) { cmp = mp_obj_get_float(val) / 100.0 * period; #endif } else { // For integer arithmetic, if period is large and 100*period will // overflow, then divide period before multiplying by cmp. Otherwise // do it the other way round to retain precision. // TODO we really need an mp_obj_get_uint_clamped function here so // that we can get long-int values as large as 0xffffffff. cmp = mp_obj_get_int(val); if (period > (1 << 31) / 100) { cmp = cmp * (period / 100); } else { cmp = (cmp * period) / 100; } } if (cmp < 0) { cmp = 0; } else if (cmp > period) { cmp = period; } return cmp; }
/// \function sleep(seconds) /// Sleep for the given number of seconds. STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { #if MICROPY_PY_BUILTINS_FLOAT mp_hal_delay_ms(1000 * mp_obj_get_float(seconds_o)); #else mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o)); #endif return mp_const_none; }
// Functions that return a tuple mp_obj_t mp_math_frexp(mp_obj_t x_obj) { int int_exponent = 0; mp_float_t significand = MICROPY_FLOAT_C_FUN(frexp)(mp_obj_get_float(x_obj), &int_exponent); mp_obj_t tuple[2]; tuple[0] = mp_obj_new_float(significand); tuple[1] = mp_obj_new_int(int_exponent); return mp_obj_new_tuple(2, tuple); }
mp_obj_t mp_math_modf(mp_obj_t x_obj) { mp_float_t int_part = 0.0; mp_float_t fractional_part = MICROPY_FLOAT_C_FUN(modf)(mp_obj_get_float(x_obj), &int_part); mp_obj_t tuple[2]; tuple[0] = mp_obj_new_float(fractional_part); tuple[1] = mp_obj_new_float(int_part); return mp_obj_new_tuple(2, tuple); }
static mp_obj_t py_select(uint n_args, const mp_obj_t *args) { int nfds=0; //highest-numbered fd plus 1 timeval tv={0}; fd_set rfds, wfds, xfds; mp_obj_t *rlist, *wlist, *xlist; uint rlist_len, wlist_len, xlist_len; /* read args */ mp_obj_get_array(args[0], &rlist_len, &rlist); mp_obj_get_array(args[1], &wlist_len, &wlist); mp_obj_get_array(args[2], &xlist_len, &xlist); if (n_args == 4) { float timeout = mp_obj_get_float(args[3]); tv.tv_sec = (int)timeout; tv.tv_usec = (timeout-(int)timeout)*1000*1000; } // add fds to their respective sets set_fds(&nfds, rlist, rlist_len, &rfds); set_fds(&nfds, wlist, wlist_len, &wfds); set_fds(&nfds, xlist, xlist_len, &xfds); // call select nfds = select(nfds+1, &rfds, &wfds, &xfds, &tv); // if any of the read sockets is closed, we add it to the read fd set, // a subsequent call to recv() returns 0. This behavior is consistent with BSD. for (int i=0; i<rlist_len; i++) { socket_t *s = rlist[i]; if (wlan_get_fd_state(s->fd)) { FD_SET(s->fd, &rfds); nfds = max(nfds, s->fd); } } // return value; a tuple of 3 lists mp_obj_t fds[3] = { mp_obj_new_list(0, NULL), mp_obj_new_list(0, NULL), mp_obj_new_list(0, NULL) }; // On success, select() returns the number of file descriptors contained // in the three returned descriptor sets which may be zero if the timeout // expires before anything interesting happens, -1 is returned on error. if (nfds == -1) { // select failed nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "select failed")); } else if (nfds) { // an fd is ready get_fds(rlist, rlist_len, fds[0], &rfds); get_fds(wlist, wlist_len, fds[1], &wfds); get_fds(xlist, xlist_len, fds[2], &xfds); } // select timedout return mp_obj_new_tuple(3, fds); }
STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { // TODO check n_kw == 0 switch (n_args) { case 0: return mp_obj_new_complex(0, 0); case 1: 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: { mp_float_t real, imag; if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) { mp_obj_complex_get(args[0], &real, &imag); } else { real = mp_obj_get_float(args[0]); imag = 0; } if (MP_OBJ_IS_TYPE(args[1], &mp_type_complex)) { mp_float_t real2, imag2; mp_obj_complex_get(args[1], &real2, &imag2); real -= imag2; imag += real2; } else { imag += mp_obj_get_float(args[1]); } return mp_obj_new_complex(real, imag); } default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "complex takes at most 2 arguments, %d given", n_args)); } }
STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 2, false); switch (n_args) { case 0: return mp_obj_new_complex(0, 0); case 1: if (MP_OBJ_IS_STR(args[0])) { // a string, parse it size_t l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_decimal(s, l, true, true, NULL); } 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: default: { mp_float_t real, imag; if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) { mp_obj_complex_get(args[0], &real, &imag); } else { real = mp_obj_get_float(args[0]); imag = 0; } if (MP_OBJ_IS_TYPE(args[1], &mp_type_complex)) { mp_float_t real2, imag2; mp_obj_complex_get(args[1], &real2, &imag2); real -= imag2; imag += real2; } else { imag += mp_obj_get_float(args[1]); } return mp_obj_new_complex(real, imag); } } }
mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_in) { mp_float_t rhs_val = mp_obj_get_float(rhs_in); // can be any type, this function will convert to float (if possible) switch (op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break; case MP_BINARY_OP_SUBTRACT: case MP_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break; case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break; case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: if (rhs_val == 0) { zero_division_error: nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero")); } // Python specs require that x == (x//y)*y + (x%y) so we must // call divmod to compute the correct floor division, which // returns the floor divide in lhs_val. mp_obj_float_divmod(&lhs_val, &rhs_val); break; case MP_BINARY_OP_TRUE_DIVIDE: case MP_BINARY_OP_INPLACE_TRUE_DIVIDE: if (rhs_val == 0) { goto zero_division_error; } lhs_val /= rhs_val; break; case MP_BINARY_OP_MODULO: case MP_BINARY_OP_INPLACE_MODULO: if (rhs_val == 0) { goto zero_division_error; } lhs_val = MICROPY_FLOAT_C_FUN(fmod)(lhs_val, rhs_val); // Python specs require that mod has same sign as second operand if (lhs_val == 0.0) { lhs_val = MICROPY_FLOAT_C_FUN(copysign)(0.0, rhs_val); } else { if ((lhs_val < 0.0) != (rhs_val < 0.0)) { lhs_val += rhs_val; } } break; case MP_BINARY_OP_POWER: case MP_BINARY_OP_INPLACE_POWER: lhs_val = MICROPY_FLOAT_C_FUN(pow)(lhs_val, rhs_val); break; case MP_BINARY_OP_LESS: return MP_BOOL(lhs_val < rhs_val); case MP_BINARY_OP_MORE: return MP_BOOL(lhs_val > rhs_val); case MP_BINARY_OP_EQUAL: return MP_BOOL(lhs_val == rhs_val); case MP_BINARY_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); case MP_BINARY_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val); default: return MP_OBJ_NULL; // op not supported } return mp_obj_new_float(lhs_val); }
/// \function sleep(seconds) /// Sleep for the given number of seconds. Seconds can be a floating-point number to /// sleep for a fractional number of seconds. STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { #if MICROPY_PY_BUILTINS_FLOAT if (MP_OBJ_IS_INT(seconds_o)) { #endif HAL_Delay(1000 * mp_obj_get_int(seconds_o)); #if MICROPY_PY_BUILTINS_FLOAT } else { HAL_Delay((uint32_t)(1000 * mp_obj_get_float(seconds_o))); } #endif return mp_const_none; }
STATIC mp_obj_t microbit_sleep(mp_obj_t ms_in) { mp_int_t ms; if (mp_obj_is_integer(ms_in)) { ms = mp_obj_get_int(ms_in); } else { ms = (mp_int_t)mp_obj_get_float(ms_in); } if (ms > 0) { mp_hal_delay_ms(ms); } return mp_const_none; }
STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) { #if MICROPY_PY_BUILTINS_FLOAT struct timeval tv; mp_float_t val = mp_obj_get_float(arg); double ipart; tv.tv_usec = round(modf(val, &ipart) * 1000000); tv.tv_sec = ipart; sleep_select(0, NULL, NULL, NULL, &tv); #else sleep(mp_obj_get_int(arg)); #endif return mp_const_none; }
static mp_obj_t servo_obj_angle(mp_obj_t self_in, mp_obj_t angle) { pyb_servo_obj_t *self = self_in; machine_int_t v = 152 + 85.0 * mp_obj_get_float(angle) / 90.0; if (v < 65) { v = 65; } if (v > 210) { v = 210; } switch (self->servo_id) { case 1: TIM2->CCR1 = v; break; case 2: TIM2->CCR2 = v; break; case 3: TIM2->CCR3 = v; break; case 4: TIM2->CCR4 = v; break; } return mp_const_none; }
static mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { // TODO check n_kw == 0 switch (n_args) { case 0: 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], &complex_type)) { return args[0]; } else { return mp_obj_new_complex(mp_obj_get_float(args[0]), 0); } case 2: { mp_float_t real, imag; if (MP_OBJ_IS_TYPE(args[0], &complex_type)) { mp_obj_complex_get(args[0], &real, &imag); } else { real = mp_obj_get_float(args[0]); imag = 0; } if (MP_OBJ_IS_TYPE(args[1], &complex_type)) { mp_float_t real2, imag2; mp_obj_complex_get(args[1], &real2, &imag2); real -= imag2; imag += real2; } else { imag += mp_obj_get_float(args[1]); } return mp_obj_new_complex(real, imag); } default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "complex takes at most 2 arguments, %d given", (void*)(machine_int_t)n_args)); } }
STATIC mp_obj_t lwip_socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { lwip_socket_obj_t *socket = self_in; mp_uint_t timeout; if (timeout_in == mp_const_none) { timeout = -1; } else { #if MICROPY_PY_BUILTIN_FLOAT timeout = 1000 * mp_obj_get_float(timeout_in); #else timeout = 1000 * mp_obj_get_int(timeout_in); #endif } socket->timeout = timeout; return mp_const_none; }
STATIC mp_obj_t servo_obj_angle(mp_obj_t self_in, mp_obj_t angle) { pyb_servo_obj_t *self = self_in; #if MICROPY_ENABLE_FLOAT machine_int_t v = 152 + 85.0 * mp_obj_get_float(angle) / 90.0; #else machine_int_t v = 152 + 85 * mp_obj_get_int(angle) / 90; #endif if (v < 65) { v = 65; } if (v > 210) { v = 210; } switch (self->servo_id) { case 1: TIM2->CCR1 = v; break; case 2: TIM2->CCR2 = v; break; case 3: TIM2->CCR3 = v; break; case 4: TIM2->CCR4 = v; break; } return mp_const_none; }
static mp_obj_t float_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { switch (n_args) { case 0: return mp_obj_new_float(0); case 1: // TODO allow string as arg and parse it if (MP_OBJ_IS_TYPE(args[0], &float_type)) { return args[0]; } else { return mp_obj_new_float(mp_obj_get_float(args[0])); } default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "float takes at most 1 argument, %d given", (void*)(machine_int_t)n_args)); } }
mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) { mp_float_t rhs_val = mp_obj_get_float(rhs_in); // can be any type, this function will convert to float (if possible) switch (op) { case RT_BINARY_OP_ADD: case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break; case RT_BINARY_OP_SUBTRACT: case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break; case RT_BINARY_OP_MULTIPLY: case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break; /* TODO floor(?) the value case RT_BINARY_OP_FLOOR_DIVIDE: case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break; */ case RT_BINARY_OP_TRUE_DIVIDE: case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break; return NULL; // op not supported } return mp_obj_new_float(lhs_val); }
void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms) { // Rather than waiting for the entire timeout specified, we wait sock->retries times // for SOCKET_POLL_US each, checking for a MicroPython interrupt between timeouts. // with SOCKET_POLL_MS == 100ms, sock->retries allows for timeouts up to 13 years. // if timeout_ms == UINT64_MAX, wait forever. sock->retries = (timeout_ms == UINT64_MAX) ? UINT_MAX : timeout_ms * 1000 / SOCKET_POLL_US; struct timeval timeout = { .tv_sec = 0, .tv_usec = timeout_ms ? SOCKET_POLL_US : 0 }; lwip_setsockopt_r(sock->fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&timeout, sizeof(timeout)); lwip_setsockopt_r(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)); lwip_fcntl_r(sock->fd, F_SETFL, timeout_ms ? 0 : O_NONBLOCK); } STATIC mp_obj_t socket_settimeout(const mp_obj_t arg0, const mp_obj_t arg1) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); if (arg1 == mp_const_none) _socket_settimeout(self, UINT64_MAX); else _socket_settimeout(self, mp_obj_get_float(arg1) * 1000L); return mp_const_none; }
// method socket.settimeout(value) // timeout=0 means non-blocking // timeout=None means blocking // otherwise, timeout is in seconds STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { mod_network_socket_obj_t *self = self_in; if (self->nic == MP_OBJ_NULL) { // not connected nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN))); } mp_uint_t timeout; if (timeout_in == mp_const_none) { timeout = -1; } else { #if MICROPY_PY_BUILTIN_FLOAT timeout = 1000 * mp_obj_get_float(timeout_in); #else timeout = 1000 * mp_obj_get_int(timeout_in); #endif } int _errno; if (self->nic_type->settimeout(self, timeout, &_errno) != 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } return mp_const_none; }
// method socket.settimeout(value) // timeout=0 means non-blocking // timeout=None means blocking // otherwise, timeout is in seconds STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { mod_network_socket_obj_t *self = self_in; if (self->nic == MP_OBJ_NULL) { // not connected mp_raise_OSError(MP_ENOTCONN); } mp_uint_t timeout; if (timeout_in == mp_const_none) { timeout = -1; } else { #if MICROPY_PY_BUILTINS_FLOAT timeout = 1000 * mp_obj_get_float(timeout_in); #else timeout = 1000 * mp_obj_get_int(timeout_in); #endif } int _errno; if (self->nic_type->settimeout(self, timeout, &_errno) != 0) { mp_raise_OSError(_errno); } return mp_const_none; }
mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) { mp_float_t rhs_val = mp_obj_get_float(rhs_in); // can be any type, this function will convert to float (if possible) switch (op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break; case MP_BINARY_OP_SUBTRACT: case MP_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break; case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break; // TODO: verify that C floor matches Python semantics case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: if (rhs_val == 0) { zero_division_error: nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "float division by zero")); } lhs_val = MICROPY_FLOAT_C_FUN(floor)(lhs_val / rhs_val); break; case MP_BINARY_OP_TRUE_DIVIDE: case MP_BINARY_OP_INPLACE_TRUE_DIVIDE: if (rhs_val == 0) { goto zero_division_error; } lhs_val /= rhs_val; break; case MP_BINARY_OP_POWER: case MP_BINARY_OP_INPLACE_POWER: lhs_val = MICROPY_FLOAT_C_FUN(pow)(lhs_val, rhs_val); break; case MP_BINARY_OP_LESS: return MP_BOOL(lhs_val < rhs_val); case MP_BINARY_OP_MORE: return MP_BOOL(lhs_val > rhs_val); case MP_BINARY_OP_EQUAL: return MP_BOOL(lhs_val == rhs_val); case MP_BINARY_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); case MP_BINARY_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val); default: return MP_OBJ_NOT_SUPPORTED; } return mp_obj_new_float(lhs_val); }
STATIC mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { case 0: return mp_obj_new_float(0); case 1: default: 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, 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])); } } }
/// \method speed([speed, time=0]) /// Get or set the speed of a continuous rotation servo. /// /// - `speed` is the speed to move to change to, between -100 and 100. /// - `time` is the number of milliseconds to take to get to the specified speed. STATIC mp_obj_t pyb_servo_speed(mp_uint_t n_args, const mp_obj_t *args) { pyb_servo_obj_t *self = args[0]; if (n_args == 1) { // get speed return mp_obj_new_int((self->pulse_cur - self->pulse_centre) * 100 / self->pulse_speed_100); } else { #if MICROPY_PY_BUILTINS_FLOAT self->pulse_dest = self->pulse_centre + self->pulse_speed_100 * mp_obj_get_float(args[1]) / 100.0; #else self->pulse_dest = self->pulse_centre + self->pulse_speed_100 * mp_obj_get_int(args[1]) / 100; #endif if (n_args == 2) { // set speed immediately self->time_left = 0; } else { // set speed over a given time (given in milli seconds) self->time_left = mp_obj_get_int(args[2]) / 20; self->pulse_accum = 0; } servo_timer_irq_callback(); return mp_const_none; } }
/// \method angle([angle, time=0]) /// Get or set the angle of the servo. /// /// - `angle` is the angle to move to in degrees. /// - `time` is the number of milliseconds to take to get to the specified angle. 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 return mp_obj_new_int((self->pulse_cur - self->pulse_centre) * 90 / self->pulse_angle_90); } else { #if MICROPY_ENABLE_FLOAT self->pulse_dest = self->pulse_centre + self->pulse_angle_90 * mp_obj_get_float(args[1]) / 90.0; #else self->pulse_dest = self->pulse_centre + self->pulse_angle_90 * mp_obj_get_int(args[1]) / 90; #endif if (n_args == 2) { // set angle immediately self->time_left = 0; } else { // set angle over a given time (given in milli seconds) self->time_left = mp_obj_get_int(args[2]) / 20; self->pulse_accum = 0; } servo_timer_irq_callback(); return mp_const_none; } }
static mp_obj_t servo_obj_angle(int n_args, const mp_obj_t *args) { pyb_servo_obj_t *self = args[0]; if (n_args == 1) { // get float angle = map_uint_to_float(servo_ticks[self->servo_id], usToTicks(self->min_usecs), usToTicks(self->max_usecs), 0.0, 180.0); return mp_obj_new_float(angle); } // Set float angle = mp_obj_get_float(args[1]); if (angle < 0.0F) { angle = 0.0F; } if (angle > 180.0F) { angle = 180.0F; } servo_ticks[self->servo_id] = map_float_to_uint(angle, 0.0F, 180.0F, usToTicks(self->min_usecs), usToTicks(self->max_usecs)); return mp_const_none; }