Merge branch 'master' of github.com:micropython/micropython

This commit is contained in:
Damien George 2014-02-10 22:51:35 +00:00
commit f1081f400b
16 changed files with 459 additions and 91 deletions

View File

@ -2764,7 +2764,7 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
}
assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // 2 is something...
// pns->nodes[2] is return/whole function annotation
compile_node(comp, pns->nodes[3]); // 3 is function body
// emit return if it wasn't the last opcode

View File

@ -33,8 +33,8 @@ DEF_RULE(decorator, nc, and(4), tok(DEL_AT), rule(dotted_name), opt_rule(trailer
DEF_RULE(decorators, nc, one_or_more, rule(decorator))
DEF_RULE(decorated, c(decorated), and(2), rule(decorators), rule(decorated_body))
DEF_RULE(decorated_body, nc, or(2), rule(classdef), rule(funcdef))
DEF_RULE(funcdef, c(funcdef), and(8), tok(KW_DEF), tok(NAME), tok(DEL_PAREN_OPEN), opt_rule(typedargslist), tok(DEL_PAREN_CLOSE), opt_rule(funcdef_2), tok(DEL_COLON), rule(suite))
DEF_RULE(funcdef_2, nc, and(2), tok(DEL_MINUS_MORE), rule(test))
DEF_RULE(funcdef, c(funcdef), and(8), tok(KW_DEF), tok(NAME), tok(DEL_PAREN_OPEN), opt_rule(typedargslist), tok(DEL_PAREN_CLOSE), opt_rule(funcdefrettype), tok(DEL_COLON), rule(suite))
DEF_RULE(funcdefrettype, nc, and(2), tok(DEL_MINUS_MORE), rule(test))
// TODO typedargslist lets through more than is allowed
DEF_RULE(typedargslist, nc, list_with_end, rule(typedargslist_item), tok(DEL_COMMA))
DEF_RULE(typedargslist_item, nc, or(3), rule(typedargslist_name), rule(typedargslist_star), rule(typedargslist_dbl_star))

View File

@ -1,5 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "misc.h"
#include "mpconfig.h"
@ -37,20 +38,10 @@ void *m_malloc(int num_bytes) {
}
void *m_malloc0(int num_bytes) {
if (num_bytes == 0) {
return NULL;
void *ptr = m_malloc(num_bytes);
if (ptr != NULL) {
memset(ptr, 0, num_bytes);
}
void *ptr = calloc(1, num_bytes);
if (ptr == NULL) {
printf("could not allocate memory, allocating %d bytes\n", num_bytes);
return NULL;
}
#if MICROPY_MEM_STATS
total_bytes_allocated += num_bytes;
current_bytes_allocated += num_bytes;
UPDATE_PEAK();
#endif
DEBUG_printf("malloc0 %d : %p\n", num_bytes, ptr);
return ptr;
}

View File

@ -29,14 +29,6 @@ void *realloc(void *ptr, size_t n) {
#endif
void *calloc(size_t sz, size_t n) {
char *ptr = malloc(sz * n);
for (int i = 0; i < sz * n; i++) {
ptr[i] = 0;
}
return ptr;
}
void *malloc(size_t n) {
return gc_alloc(n);
}

View File

@ -4,7 +4,6 @@ void __assert_func(void);
void *malloc(size_t n);
void free(void *ptr);
void *calloc(size_t sz, size_t n);
void *realloc(void *ptr, size_t n);
void *memcpy(void *dest, const void *src, size_t n);

View File

@ -1,5 +1,8 @@
include ../py/mkenv.mk
# qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h
# include py core make definitions
include ../py/py.mk
@ -32,6 +35,8 @@ SRC_C = \
lexerfatfs.c \
lexermemzip.c \
memzip.c \
servo.c \
usart.c \
usb.c \
STM_SRC_C = $(addprefix stm/,\
@ -54,7 +59,7 @@ SRC_TEENSY = \
usb_serial.c \
yield.c \
OBJ = $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(STM_SRC_S:.s=.o) $(SRC_TEENSY:.c=.o)) $(PY_O)
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(STM_SRC_S:.s=.o) $(SRC_TEENSY:.c=.o))
#LIB = -lreadline
# the following is needed for BSD
#LIB += -ltermcap

View File

@ -2,6 +2,7 @@
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "led.h"

View File

@ -2,11 +2,13 @@
#include <stdio.h>
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "lexer.h"
typedef int FIL;
#include "../stm/lexerfatfs.h"
mp_lexer_t *mp_lexer_new_from_file(const char *filename, mp_lexer_file_buf_t *fb) {
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
printf("import not implemented\n");
return NULL;
}
@ -15,3 +17,8 @@ mp_lexer_t *mp_import_open_file(qstr mod_name) {
printf("import not implemented\n");
return NULL;
}
mp_import_stat_t mp_import_stat(const char *path) {
// TODO implement me!
return MP_IMPORT_STAT_NO_EXIST;
}

View File

@ -2,6 +2,8 @@
#include <stdlib.h>
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "lexer.h"
#include "memzip.h"
@ -13,6 +15,7 @@ mp_lexer_t *mp_lexer_new_from_memzip_file(const char *filename)
if (memzip_locate(filename, &data, &len) != MZ_OK) {
return NULL;
}
return mp_lexer_new_from_str_len(filename, (const char *)data, (uint)len, 0);
return mp_lexer_new_from_str_len(qstr_from_str(filename), (const char *)data, (uint)len, 0);
}

View File

@ -6,7 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "qstr.h"
#include "lexer.h"
#include "lexermemzip.h"
#include "parse.h"
@ -15,6 +15,7 @@
#include "runtime0.h"
#include "runtime.h"
#include "repl.h"
#include "servo.h"
#include "usb.h"
#include "gc.h"
#include "led.h"
@ -54,6 +55,32 @@ static const char *help_text =
#endif
;
mp_obj_t pyb_analog_read(mp_obj_t pin_obj) {
uint pin = mp_obj_get_int(pin_obj);
int val = analogRead(pin);
return MP_OBJ_NEW_SMALL_INT(val);
}
mp_obj_t pyb_analog_write(mp_obj_t pin_obj, mp_obj_t val_obj) {
uint pin = mp_obj_get_int(pin_obj);
int val = mp_obj_get_int(val_obj);
analogWrite(pin, val);
return mp_const_none;
}
mp_obj_t pyb_analog_write_resolution(mp_obj_t res_obj) {
int res = mp_obj_get_int(res_obj);
analogWriteResolution(res);
return mp_const_none;
}
mp_obj_t pyb_analog_write_frequency(mp_obj_t pin_obj, mp_obj_t freq_obj) {
uint pin = mp_obj_get_int(pin_obj);
int freq = mp_obj_get_int(freq_obj);
analogWriteFrequency(pin, freq);
return mp_const_none;
}
// get some help about available functions
static mp_obj_t pyb_help(void) {
printf("%s", help_text);
@ -181,16 +208,26 @@ mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
}
#endif
static qstr pyb_config_source_dir = 0;
static qstr pyb_config_main = 0;
static mp_obj_t pyb_config_source_dir = MP_OBJ_NULL;
static mp_obj_t pyb_config_main = MP_OBJ_NULL;
mp_obj_t pyb_source_dir(mp_obj_t source_dir) {
pyb_config_source_dir = mp_obj_get_qstr(source_dir);
if (MP_OBJ_IS_STR(source_dir)) {
pyb_config_source_dir = source_dir;
printf("source_dir = '");
mp_obj_print(source_dir, PRINT_STR);
printf("'\n");
}
return mp_const_none;
}
mp_obj_t pyb_main(mp_obj_t main) {
pyb_config_main = mp_obj_get_qstr(main);
if (MP_OBJ_IS_STR(main)) {
pyb_config_main = main;
printf("main = '");
mp_obj_print(main, PRINT_STR);
printf("'\n");
}
return mp_const_none;
}
@ -205,7 +242,7 @@ mp_obj_t pyb_led(mp_obj_t state) {
}
mp_obj_t pyb_run(mp_obj_t filename_obj) {
const char *filename = qstr_str(mp_obj_get_qstr(filename_obj));
const char *filename = qstr_str(mp_obj_str_get_qstr(filename_obj));
do_file(filename);
return mp_const_none;
}
@ -309,15 +346,24 @@ bool do_file(const char *filename) {
return false;
}
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
qstr parse_exc_id;
const char *parse_exc_msg;
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg);
qstr source_name = mp_lexer_source_name(lex);
mp_lexer_free(lex);
if (pn == MP_PARSE_NODE_NULL) {
// parse error
mp_lexer_show_error_pythonic_prefix(lex);
printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg);
mp_lexer_free(lex);
return false;
}
mp_lexer_free(lex);
mp_obj_t module_fun = mp_compile(pn, source_name, false);
mp_parse_node_free(pn);
if (module_fun == mp_const_none) {
return false;
}
@ -329,7 +375,7 @@ bool do_file(const char *filename) {
return true;
} else {
// uncaught exception
mp_obj_print((mp_obj_t)nlr.ret_val);
mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR);
printf("\n");
return false;
}
@ -340,7 +386,7 @@ void do_repl(void) {
stdout_tx_str("Type \"help()\" for more information.\r\n");
vstr_t line;
vstr_init(&line);
vstr_init(&line, 32);
for (;;) {
vstr_reset(&line);
@ -366,12 +412,21 @@ void do_repl(void) {
}
}
mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", vstr_str(&line), vstr_len(&line), 0);
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT);
mp_lexer_free(lex);
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line), vstr_len(&line), 0);
qstr parse_exc_id;
const char *parse_exc_msg;
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_exc_id, &parse_exc_msg);
qstr source_name = mp_lexer_source_name(lex);
if (pn != MP_PARSE_NODE_NULL) {
mp_obj_t module_fun = mp_compile(pn, true);
if (pn == MP_PARSE_NODE_NULL) {
// parse error
mp_lexer_show_error_pythonic_prefix(lex);
printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg);
mp_lexer_free(lex);
} else {
// parse okay
mp_lexer_free(lex);
mp_obj_t module_fun = mp_compile(pn, source_name, true);
if (module_fun != mp_const_none) {
nlr_buf_t nlr;
uint32_t start = micros();
@ -381,11 +436,11 @@ void do_repl(void) {
// optional timing
if (0) {
uint32_t ticks = micros() - start; // TODO implement a function that does this properly
printf("(took %lu us)\n", ticks);
printf("(took %lu ms)\n", ticks);
}
} else {
// uncaught exception
mp_obj_print((mp_obj_t)nlr.ret_val);
mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR);
printf("\n");
}
}
@ -396,11 +451,15 @@ void do_repl(void) {
}
int main(void) {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
#if 0
// Wait for host side to get connected
while (!usb_vcp_is_connected()) {
;
}
#else
delay(1000);
#endif
led_init();
led_state(PYB_LED_BUILTIN, 1);
@ -415,28 +474,34 @@ soft_reset:
qstr_init();
rt_init();
#if 1
// add some functions to the python namespace
{
rt_store_name(qstr_from_str_static("help"), rt_make_function_0(pyb_help));
mp_obj_t m = mp_obj_new_module(qstr_from_str_static("pyb"));
rt_store_attr(m, qstr_from_str_static("info"), rt_make_function_0(pyb_info));
rt_store_attr(m, qstr_from_str_static("source_dir"), rt_make_function_1(pyb_source_dir));
rt_store_attr(m, qstr_from_str_static("main"), rt_make_function_1(pyb_main));
rt_store_attr(m, qstr_from_str_static("gc"), rt_make_function_0(pyb_gc));
rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_1(pyb_delay));
rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led));
rt_store_attr(m, qstr_from_str_static("Led"), rt_make_function_1(pyb_Led));
rt_store_attr(m, qstr_from_str_static("gpio"), (mp_obj_t)&pyb_gpio_obj);
rt_store_name(qstr_from_str_static("pyb"), m);
rt_store_name(qstr_from_str_static("run"), rt_make_function_1(pyb_run));
}
#endif
rt_store_name(MP_QSTR_help, rt_make_function_n(0, pyb_help));
mp_obj_t m = mp_obj_new_module(MP_QSTR_pyb);
rt_store_attr(m, MP_QSTR_info, rt_make_function_n(0, pyb_info));
rt_store_attr(m, MP_QSTR_source_dir, rt_make_function_n(1, pyb_source_dir));
rt_store_attr(m, MP_QSTR_main, rt_make_function_n(1, pyb_main));
rt_store_attr(m, MP_QSTR_gc, rt_make_function_n(0, pyb_gc));
rt_store_attr(m, MP_QSTR_delay, rt_make_function_n(1, pyb_delay));
rt_store_attr(m, MP_QSTR_led, rt_make_function_n(1, pyb_led));
rt_store_attr(m, MP_QSTR_Led, rt_make_function_n(1, pyb_Led));
rt_store_attr(m, MP_QSTR_analogRead, rt_make_function_n(1, pyb_analog_read));
rt_store_attr(m, MP_QSTR_analogWrite, rt_make_function_n(2, pyb_analog_write));
rt_store_attr(m, MP_QSTR_analogWriteResolution, rt_make_function_n(1, pyb_analog_write_resolution));
rt_store_attr(m, MP_QSTR_analogWriteFrequency, rt_make_function_n(2, pyb_analog_write_frequency));
rt_store_attr(m, MP_QSTR_gpio, (mp_obj_t)&pyb_gpio_obj);
rt_store_attr(m, MP_QSTR_Servo, rt_make_function_n(0, pyb_Servo));
rt_store_name(MP_QSTR_pyb, m);
rt_store_name(MP_QSTR_run, rt_make_function_n(1, pyb_run));
}
printf("About execute /boot.py\n");
if (!do_file("/boot.py")) {
printf("Unable to open '/boot.py'\n");
flash_error(4);
}
printf("Done executing /boot.py\n");
// Turn bootup LED off
led_state(PYB_LED_BUILTIN, 0);
@ -445,21 +510,23 @@ soft_reset:
{
vstr_t *vstr = vstr_new();
vstr_add_str(vstr, "/");
if (pyb_config_source_dir == 0) {
if (pyb_config_source_dir == MP_OBJ_NULL) {
vstr_add_str(vstr, "src");
} else {
vstr_add_str(vstr, qstr_str(pyb_config_source_dir));
vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_source_dir));
}
vstr_add_char(vstr, '/');
if (pyb_config_main == 0) {
if (pyb_config_main == MP_OBJ_NULL) {
vstr_add_str(vstr, "main.py");
} else {
vstr_add_str(vstr, qstr_str(pyb_config_main));
vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_main));
}
printf("About execute '%s'\n", vstr_str(vstr));
if (!do_file(vstr_str(vstr))) {
printf("Unable to open '%s'\n", vstr_str(vstr));
flash_error(3);
}
printf("Done executing '%s'\n", vstr_str(vstr));
vstr_free(vstr);
}
@ -471,16 +538,6 @@ soft_reset:
goto soft_reset;
}
double __aeabi_f2d(float x) {
// TODO
return 0.0;
}
float __aeabi_d2f(double x) {
// TODO
return 0.0;
}
double sqrt(double x) {
// TODO
return 0.0;

36
teensy/qstrdefsport.h Normal file
View File

@ -0,0 +1,36 @@
// qstrs specific to this port
Q(help)
Q(pyb)
Q(info)
Q(sd_test)
Q(stop)
Q(standby)
Q(source_dir)
Q(main)
Q(sync)
Q(gc)
Q(delay)
Q(switch)
Q(servo)
Q(pwm)
Q(accel)
Q(mma_read)
Q(mma_mode)
Q(hid)
Q(time)
Q(rand)
Q(Led)
Q(led)
Q(Servo)
Q(I2C)
Q(gpio)
Q(Usart)
Q(ADC)
Q(open)
Q(analogRead)
Q(analogWrite)
Q(analogWriteResolution)
Q(analogWriteFrequency)
Q(run)

264
teensy/servo.c Normal file
View File

@ -0,0 +1,264 @@
#include <stdio.h>
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "nlr.h"
#include "obj.h"
#include "servo.h"
#include "Arduino.h"
#define MAX_SERVOS 12
#define INVALID_SERVO -1
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds
#define PDB_CONFIG (PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_PDBIE \
| PDB_SC_CONT | PDB_SC_PRESCALER(2) | PDB_SC_MULT(0))
#define PDB_PRESCALE 4
#define usToTicks(us) ((us) * (F_BUS / 1000) / PDB_PRESCALE / 1000)
#define ticksToUs(ticks) ((ticks) * PDB_PRESCALE * 1000 / (F_BUS / 1000))
static uint16_t servo_active_mask = 0;
static uint16_t servo_allocated_mask = 0;
static uint8_t servo_pin[MAX_SERVOS];
static uint16_t servo_ticks[MAX_SERVOS];
typedef struct _pyb_servo_obj_t {
mp_obj_base_t base;
uint servo_id;
uint min_usecs;
uint max_usecs;
} pyb_servo_obj_t;
#define clamp(v, min_val, max_val) ((v) < (min_val) ? (min_val) : (v) > (max_val) ? (max_val) : (v))
static float map_uint_to_float(uint x, uint in_min, uint in_max, float out_min, float out_max)
{
return (float)(x - in_min) * (out_max - out_min) / (float)(in_max - in_min) + (float)out_min;
}
static uint map_float_to_uint(float x, float in_min, float in_max, uint out_min, uint out_max)
{
return (int)((x - in_min) * (float)(out_max - out_min) / (in_max - in_min) + (float)out_min);
}
static mp_obj_t servo_obj_attach(mp_obj_t self_in, mp_obj_t pin_obj) {
pyb_servo_obj_t *self = self_in;
uint pin = mp_obj_get_int(pin_obj);
if (pin > CORE_NUM_DIGITAL) {
goto pin_error;
}
pinMode(pin, OUTPUT);
servo_pin[self->servo_id] = pin;
servo_active_mask |= (1 << self->servo_id);
if (!(SIM_SCGC6 & SIM_SCGC6_PDB)) {
SIM_SCGC6 |= SIM_SCGC6_PDB; // TODO: use bitband for atomic bitset
PDB0_MOD = 0xFFFF;
PDB0_CNT = 0;
PDB0_IDLY = 0;
PDB0_SC = PDB_CONFIG;
// TODO: maybe this should be a higher priority than most
// other interrupts (init all to some default?)
PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;
}
NVIC_ENABLE_IRQ(IRQ_PDB);
return mp_const_none;
pin_error:
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "pin %d does not exist", pin));
}
static mp_obj_t servo_obj_detach(mp_obj_t self_in) {
//pyb_servo_obj_t *self = self_in;
return mp_const_none;
}
static mp_obj_t servo_obj_pin(mp_obj_t self_in) {
pyb_servo_obj_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT(servo_pin[self->servo_id]);
}
static mp_obj_t servo_obj_min_usecs(int n_args, const mp_obj_t *args) {
pyb_servo_obj_t *self = args[0];
if (n_args == 1) {
// get min
return MP_OBJ_NEW_SMALL_INT(self->min_usecs);
}
// Set min
self->min_usecs = mp_obj_get_int(args[1]);
return mp_const_none;
}
static mp_obj_t servo_obj_max_usecs(int n_args, const mp_obj_t *args) {
pyb_servo_obj_t *self = args[0];
if (n_args == 1) {
// get max
return MP_OBJ_NEW_SMALL_INT(self->max_usecs);
}
// Set max
self->max_usecs = mp_obj_get_int(args[1]);
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;
}
static mp_obj_t servo_obj_usecs(int n_args, const mp_obj_t *args) {
pyb_servo_obj_t *self = args[0];
uint usecs;
if (n_args == 1) {
// get
return MP_OBJ_NEW_SMALL_INT(ticksToUs(servo_ticks[self->servo_id]));
}
// Set
usecs = mp_obj_get_int(args[1]);
if (self->min_usecs < self->max_usecs) {
usecs = clamp(usecs, self->min_usecs, self->max_usecs);
} else {
usecs = clamp(usecs, self->max_usecs, self->min_usecs);
}
servo_ticks[self->servo_id] = usToTicks(usecs);
return mp_const_none;
}
static mp_obj_t servo_obj_attached(mp_obj_t self_in) {
pyb_servo_obj_t *self = self_in;
uint attached = (servo_active_mask & (1 << self->servo_id)) != 0;
return MP_OBJ_NEW_SMALL_INT(attached);
}
static void servo_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
pyb_servo_obj_t *self = self_in;
print(env, "<Servo %lu>", self->servo_id);
}
static MP_DEFINE_CONST_FUN_OBJ_2(servo_obj_attach_obj, servo_obj_attach);
static MP_DEFINE_CONST_FUN_OBJ_1(servo_obj_detach_obj, servo_obj_detach);
static MP_DEFINE_CONST_FUN_OBJ_1(servo_obj_pin_obj, servo_obj_pin);
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(servo_obj_min_usecs_obj, 1, 2, servo_obj_min_usecs);
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(servo_obj_max_usecs_obj, 1, 2, servo_obj_max_usecs);
static MP_DEFINE_CONST_FUN_OBJ_1(servo_obj_attached_obj, servo_obj_attached);
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(servo_obj_angle_obj, 1, 2, servo_obj_angle);
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(servo_obj_usecs_obj, 1, 2, servo_obj_usecs);
static const mp_method_t servo_methods[] = {
{ "attach", &servo_obj_attach_obj },
{ "detach", &servo_obj_detach_obj },
{ "pin", &servo_obj_pin_obj },
{ "min_usecs", &servo_obj_min_usecs_obj },
{ "max_usecs", &servo_obj_max_usecs_obj },
{ "attached", &servo_obj_attached_obj },
{ "angle", &servo_obj_angle_obj },
{ "usecs", &servo_obj_usecs_obj },
{ NULL, NULL },
};
/*
* Notes:
*
* ISR needs to know pin #, ticks
*/
static const mp_obj_type_t servo_obj_type = {
{ &mp_const_type },
"Servo",
.print = servo_obj_print,
.methods = servo_methods,
};
/* servo = pyb.Servo(pin, [min_uecs, [max_usecs]]) */
mp_obj_t pyb_Servo(void) {
uint16_t mask;
pyb_servo_obj_t *self = m_new_obj(pyb_servo_obj_t);
self->base.type = &servo_obj_type;
self->min_usecs = MIN_PULSE_WIDTH;
self->max_usecs = MAX_PULSE_WIDTH;
/* Find an unallocated servo id */
self->servo_id = 0;
for (mask=1; mask < (1<<MAX_SERVOS); mask <<= 1) {
if (!(servo_allocated_mask & mask)) {
servo_allocated_mask |= mask;
servo_active_mask &= ~mask;
servo_ticks[self->servo_id] = usToTicks(DEFAULT_PULSE_WIDTH);
return self;
}
self->servo_id++;
}
m_del_obj(pyb_servo_obj_t, self);
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "No available servo ids"));
return mp_const_none;
}
void pdb_isr(void)
{
static int8_t channel = 0, channel_high = MAX_SERVOS;
static uint32_t tick_accum = 0;
uint32_t ticks;
int32_t wait_ticks;
// first, if any channel was left high from the previous
// run, now is the time to shut it off
if (servo_active_mask & (1 << channel_high)) {
digitalWrite(servo_pin[channel_high], LOW);
channel_high = MAX_SERVOS;
}
// search for the next channel to turn on
while (channel < MAX_SERVOS) {
if (servo_active_mask & (1 << channel)) {
digitalWrite(servo_pin[channel], HIGH);
channel_high = channel;
ticks = servo_ticks[channel];
tick_accum += ticks;
PDB0_IDLY += ticks;
PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
channel++;
return;
}
channel++;
}
// when all channels have output, wait for the
// minimum refresh interval
wait_ticks = usToTicks(REFRESH_INTERVAL) - tick_accum;
if (wait_ticks < usToTicks(100)) wait_ticks = usToTicks(100);
else if (wait_ticks > 60000) wait_ticks = 60000;
tick_accum += wait_ticks;
PDB0_IDLY += wait_ticks;
PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
// if this wait is enough to satisfy the refresh
// interval, next time begin again at channel zero
if (tick_accum >= usToTicks(REFRESH_INTERVAL)) {
tick_accum = 0;
channel = 0;
}
}

2
teensy/servo.h Normal file
View File

@ -0,0 +1,2 @@
mp_obj_t pyb_Servo(void);

View File

@ -4,7 +4,6 @@ void __assert_func(void);
void *malloc(size_t n);
void free(void *ptr);
void *calloc(size_t sz, size_t n);
void *realloc(void *ptr, size_t n);
void *memcpy(void *dest, const void *src, size_t n);

View File

@ -1,30 +1,38 @@
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "../stm/usart.h"
void usart_init(void) {
pyb_usart_t pyb_usart_global_debug = PYB_USART_NONE;
void usart_init(pyb_usart_t usart_id, uint32_t baudrate)
{
(void)usart_id;
(void)baudrate;
}
bool usart_is_enabled(void) {
bool usart_rx_any(pyb_usart_t usart_id)
{
(void)usart_id;
return false;
}
bool usart_rx_any(void) {
return false;
}
int usart_rx_char(void) {
int usart_rx_char(pyb_usart_t usart_id)
{
(void)usart_id;
return 0;
}
void usart_tx_char(int c) {
(void)c;
}
void usart_tx_str(const char *str) {
void usart_tx_str(pyb_usart_t usart_id, const char *str)
{
(void)usart_id;
(void)str;
}
void usart_tx_strn_cooked(const char *str, int len) {
(void)str;
(void)len;
void usart_tx_strn_cooked(pyb_usart_t usart_id, const char *str, int len)
{
(void)usart_id;
(void)str;
(void)len;
}

View File

@ -0,0 +1,4 @@
def foo(x: int, y: list) -> dict:
return {x: y}
print(foo(1, [2, 3]))