From 2870862601c7f4957d2710f8e7247de002cf67c4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 2 Jan 2014 21:30:26 +0000 Subject: [PATCH] Add module object, to be used eventually for import. --- py/obj.h | 11 ++-- py/objmodule.c | 48 ++++++++++++++++++ py/runtime.c | 16 +++++- stm/Makefile | 1 + stm/main.c | 126 +++++++++++++++++----------------------------- stm/mma.c | 119 +++++++++++++++++++++++++++++++++++++++++++ stm/mma.h | 4 ++ unix-cpy/Makefile | 1 + unix/Makefile | 1 + 9 files changed, 243 insertions(+), 84 deletions(-) create mode 100644 py/objmodule.c diff --git a/py/obj.h b/py/obj.h index 839209a405..6a0cefd915 100644 --- a/py/obj.h +++ b/py/obj.h @@ -87,9 +87,9 @@ struct _mp_obj_type_t { dynamic_type instance compare_op - load_attr instance class list + load_attr module instance class list load_method instance str gen list user - store_attr instance class + store_attr module instance class store_subscr list dict len str tuple list map @@ -147,6 +147,7 @@ mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items); mp_obj_t mp_obj_new_bound_meth(mp_obj_t self, mp_obj_t meth); mp_obj_t mp_obj_new_class(struct _mp_map_t *class_locals); mp_obj_t mp_obj_new_instance(mp_obj_t clas); +mp_obj_t mp_obj_new_module(qstr module_name); const char *mp_obj_get_type_str(mp_obj_t o_in); @@ -238,5 +239,7 @@ mp_obj_t mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr); void mp_obj_instance_load_method(mp_obj_t self_in, qstr attr, mp_obj_t *dest); void mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value); -// temporary way of making C modules -mp_obj_t mp_module_new(void); +// module +extern const mp_obj_type_t module_type; +mp_obj_t mp_obj_new_module(qstr module_name); +struct _mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in); diff --git a/py/objmodule.c b/py/objmodule.c new file mode 100644 index 0000000000..addab14b75 --- /dev/null +++ b/py/objmodule.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime.h" +#include "map.h" + +typedef struct _mp_obj_module_t { + mp_obj_base_t base; + qstr name; + mp_map_t *globals; +} mp_obj_module_t; + +void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + mp_obj_module_t *self = self_in; + print(env, "", qstr_str(self->name)); +} + +const mp_obj_type_t module_type = { + { &mp_const_type }, + "module", + module_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_module(qstr module_name) { + mp_obj_module_t *o = m_new_obj(mp_obj_module_t); + o->base.type = &module_type; + o->name = module_name; + o->globals = mp_map_new(MP_MAP_QSTR, 0); + return o; +} + +mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &module_type)); + mp_obj_module_t *self = self_in; + return self->globals; +} diff --git a/py/runtime.c b/py/runtime.c index c3b3d74259..3fae61f6fe 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -779,11 +779,19 @@ mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) { if (MP_OBJ_IS_TYPE(base, &class_type)) { mp_map_elem_t *elem = mp_qstr_map_lookup(mp_obj_class_get_locals(base), attr, false); if (elem == NULL) { - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); + // TODO what about generic method lookup? + goto no_attr; } return elem->value; } else if (MP_OBJ_IS_TYPE(base, &instance_type)) { return mp_obj_instance_load_attr(base, attr); + } else if (MP_OBJ_IS_TYPE(base, &module_type)) { + mp_map_elem_t *elem = mp_qstr_map_lookup(mp_obj_module_get_globals(base), attr, false); + if (elem == NULL) { + // TODO what about generic method lookup? + goto no_attr; + } + return elem->value; } else if (MP_OBJ_IS_OBJ(base)) { // generic method lookup mp_obj_base_t *o = base; @@ -794,6 +802,8 @@ mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) { } } } + +no_attr: nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); } @@ -832,6 +842,10 @@ void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { mp_qstr_map_lookup(locals, attr, true)->value = value; } else if (MP_OBJ_IS_TYPE(base, &instance_type)) { mp_obj_instance_store_attr(base, attr, value); + } else if (MP_OBJ_IS_TYPE(base, &module_type)) { + // TODO CPython allows STORE_ATTR to a module, but is this the correct implementation? + mp_map_t *globals = mp_obj_module_get_globals(base); + mp_qstr_map_lookup(globals, attr, true)->value = value; } else { nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); } diff --git a/stm/Makefile b/stm/Makefile index 33d738d78f..174b14c3ee 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -72,6 +72,7 @@ PY_O = \ objgenerator.o \ objinstance.o \ objlist.o \ + objmodule.o \ objnone.o \ objrange.o \ objset.o \ diff --git a/stm/main.c b/stm/main.c index 8c2c96af2a..f16ce252d2 100644 --- a/stm/main.c +++ b/stm/main.c @@ -453,7 +453,7 @@ int readline(vstr_t *line, const char *prompt) { } void do_repl(void) { - stdout_tx_str("Micro Python 0.1; STM32F405RG; PYBv3\r\n"); + stdout_tx_str("Micro Python build on 2/1/2014; PYBv3 with STM32F405RG\r\n"); stdout_tx_str("Type \"help()\" for more information.\r\n"); vstr_t line; @@ -587,38 +587,53 @@ mp_obj_t pyb_gc(void) { return mp_const_none; } -#define MMA_ADDR (0x4c) +mp_obj_t pyb_gpio(int n_args, mp_obj_t *args) { + //assert(1 <= n_args && n_args <= 2); -int mma_buf[12]; - -mp_obj_t pyb_mma_read(void) { - for (int i = 0; i <= 6; i += 3) { - mma_buf[0 + i] = mma_buf[0 + i + 3]; - mma_buf[1 + i] = mma_buf[1 + i + 3]; - mma_buf[2 + i] = mma_buf[2 + i + 3]; + const char *pin_name = qstr_str(mp_obj_get_qstr(args[0])); + GPIO_TypeDef *port; + switch (pin_name[0]) { + case 'A': case 'a': port = GPIOA; break; + case 'B': case 'b': port = GPIOB; break; + case 'C': case 'c': port = GPIOC; break; + default: goto pin_error; } - - mma_start(MMA_ADDR, 1); - mma_send_byte(0); - mma_restart(MMA_ADDR, 0); - for (int i = 0; i <= 2; i++) { - int v = mma_read_ack() & 0x3f; - if (v & 0x20) { - v |= ~0x1f; + uint pin_num = 0; + for (const char *s = pin_name + 1; *s; s++) { + if (!('0' <= *s && *s <= '9')) { + goto pin_error; } - mma_buf[9 + i] = v; + pin_num = 10 * pin_num + *s - '0'; + } + if (!(0 <= pin_num && pin_num <= 15)) { + goto pin_error; } - int jolt_info = mma_read_nack(); - mp_obj_t data[4]; - data[0] = mp_obj_new_int(jolt_info); - data[1] = mp_obj_new_int(mma_buf[2] + mma_buf[5] + mma_buf[8] + mma_buf[11]); - data[2] = mp_obj_new_int(mma_buf[1] + mma_buf[4] + mma_buf[7] + mma_buf[10]); - data[3] = mp_obj_new_int(mma_buf[0] + mma_buf[3] + mma_buf[6] + mma_buf[9]); + if (n_args == 1) { + // get pin + if ((port->IDR & (1 << pin_num)) != (uint32_t)Bit_RESET) { + return MP_OBJ_NEW_SMALL_INT(1); + } else { + return MP_OBJ_NEW_SMALL_INT(0); + } + } else { + // set pin + if (rt_is_true(args[1])) { + // set pin high + port->BSRRL = 1 << pin_num; + } else { + // set pin low + port->BSRRH = 1 << pin_num; + } + return mp_const_none; + } - return rt_build_tuple(4, data); // items in reverse order in data +pin_error: + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "pin %s does not exist", pin_name)); } +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio); + mp_obj_t pyb_hid_send_report(mp_obj_t arg) { mp_obj_t *items = mp_obj_get_array_fixed_n(arg, 4); uint8_t data[4]; @@ -855,7 +870,7 @@ soft_reset: { rt_store_name(qstr_from_str_static("help"), rt_make_function_0(pyb_help)); - mp_obj_t m = mp_module_new(); + 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("sd_test"), rt_make_function_0(pyb_sd_test)); rt_store_attr(m, qstr_from_str_static("stop"), rt_make_function_0(pyb_stop)); @@ -869,7 +884,9 @@ soft_reset: rt_store_attr(m, qstr_from_str_static("switch"), rt_make_function_0(pyb_sw)); rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_2(pyb_servo_set)); rt_store_attr(m, qstr_from_str_static("pwm"), rt_make_function_2(pyb_pwm_set)); - rt_store_attr(m, qstr_from_str_static("accel"), rt_make_function_0(pyb_mma_read)); + rt_store_attr(m, qstr_from_str_static("accel"), (mp_obj_t)&pyb_mma_read_obj); + rt_store_attr(m, qstr_from_str_static("mma_read"), (mp_obj_t)&pyb_mma_read_all_obj); + rt_store_attr(m, qstr_from_str_static("mma_mode"), (mp_obj_t)&pyb_mma_write_mode_obj); rt_store_attr(m, qstr_from_str_static("hid"), rt_make_function_1(pyb_hid_send_report)); rt_store_attr(m, qstr_from_str_static("time"), rt_make_function_0(pyb_rtc_read)); rt_store_attr(m, qstr_from_str_static("uout"), rt_make_function_1(pyb_usart_send)); @@ -879,6 +896,7 @@ soft_reset: rt_store_attr(m, qstr_from_str_static("Led"), rt_make_function_1(pyb_Led)); rt_store_attr(m, qstr_from_str_static("Servo"), rt_make_function_1(pyb_Servo)); rt_store_attr(m, qstr_from_str_static("I2C"), rt_make_function_2(pyb_I2C)); + 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("open"), rt_make_function_2(pyb_io_open)); @@ -985,56 +1003,6 @@ soft_reset: if (first_soft_reset) { // init and reset address to zero mma_init(); - mma_start(MMA_ADDR, 1); - mma_send_byte(0); - mma_stop(); - - /* - // read and print all 11 registers - mma_start(MMA_ADDR, 1); - mma_send_byte(0); - mma_restart(MMA_ADDR, 0); - for (int i = 0; i <= 0xa; i++) { - int data; - if (i == 0xa) { - data = mma_read_nack(); - } else { - data = mma_read_ack(); - } - printf(" %02x", data); - } - printf("\n"); - */ - - // put into active mode - mma_start(MMA_ADDR, 1); - mma_send_byte(7); // mode - mma_send_byte(1); // active mode - mma_stop(); - - /* - // infinite loop to read values - for (;;) { - sys_tick_delay_ms(500); - - mma_start(MMA_ADDR, 1); - mma_send_byte(0); - mma_restart(MMA_ADDR, 0); - for (int i = 0; i <= 3; i++) { - int data; - if (i == 3) { - data = mma_read_nack(); - printf(" %02x\n", data); - } else { - data = mma_read_ack() & 0x3f; - if (data & 0x20) { - data |= ~0x1f; - } - printf(" % 2d", data); - } - } - } - */ } // turn boot-up LED off @@ -1220,9 +1188,9 @@ soft_reset: } else { data[0] = 0x00; } - mma_start(MMA_ADDR, 1); + mma_start(0x4c /* MMA_ADDR */, 1); mma_send_byte(0); - mma_restart(MMA_ADDR, 0); + mma_restart(0x4c /* MMA_ADDR */, 0); for (int i = 0; i <= 1; i++) { int v = mma_read_ack() & 0x3f; if (v & 0x20) { diff --git a/stm/mma.c b/stm/mma.c index 937da1cf7e..f5409ae120 100644 --- a/stm/mma.c +++ b/stm/mma.c @@ -5,9 +5,14 @@ #include #include "misc.h" +#include "mpconfig.h" #include "systick.h" +#include "obj.h" +#include "runtime.h" #include "mma.h" +#define MMA_ADDR (0x4c) + void mma_init(void) { RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // enable I2C1 @@ -67,6 +72,58 @@ void mma_init(void) { sys_tick_delay_ms(20); // set START bit in CR1 to generate a start cond! + + // init the chip via I2C commands + mma_start(MMA_ADDR, 1); + mma_send_byte(0); + mma_stop(); + + /* + // read and print all 11 registers + mma_start(MMA_ADDR, 1); + mma_send_byte(0); + mma_restart(MMA_ADDR, 0); + for (int i = 0; i <= 0xa; i++) { + int data; + if (i == 0xa) { + data = mma_read_nack(); + } else { + data = mma_read_ack(); + } + printf(" %02x", data); + } + printf("\n"); + */ + + // put into active mode + mma_start(MMA_ADDR, 1); + mma_send_byte(7); // mode + mma_send_byte(1); // active mode + mma_stop(); + + /* + // infinite loop to read values + for (;;) { + sys_tick_delay_ms(500); + + mma_start(MMA_ADDR, 1); + mma_send_byte(0); + mma_restart(MMA_ADDR, 0); + for (int i = 0; i <= 3; i++) { + int data; + if (i == 3) { + data = mma_read_nack(); + printf(" %02x\n", data); + } else { + data = mma_read_ack() & 0x3f; + if (data & 0x20) { + data |= ~0x1f; + } + printf(" % 2d", data); + } + } + } + */ } static uint32_t i2c_get_sr(void) { @@ -179,3 +236,65 @@ void mma_stop(void) { // send stop condition I2C1->CR1 |= I2C_CR1_STOP; } + +/******************************************************************************/ +/* Micro Python bindings */ + +int mma_buf[12]; + +mp_obj_t pyb_mma_read(void) { + for (int i = 0; i <= 6; i += 3) { + mma_buf[0 + i] = mma_buf[0 + i + 3]; + mma_buf[1 + i] = mma_buf[1 + i + 3]; + mma_buf[2 + i] = mma_buf[2 + i + 3]; + } + + mma_start(MMA_ADDR, 1); + mma_send_byte(0); + mma_restart(MMA_ADDR, 0); + for (int i = 0; i <= 2; i++) { + int v = mma_read_ack() & 0x3f; + if (v & 0x20) { + v |= ~0x1f; + } + mma_buf[9 + i] = v; + } + int jolt_info = mma_read_nack(); + + mp_obj_t data[4]; + data[0] = mp_obj_new_int(jolt_info); + data[1] = mp_obj_new_int(mma_buf[2] + mma_buf[5] + mma_buf[8] + mma_buf[11]); + data[2] = mp_obj_new_int(mma_buf[1] + mma_buf[4] + mma_buf[7] + mma_buf[10]); + data[3] = mp_obj_new_int(mma_buf[0] + mma_buf[3] + mma_buf[6] + mma_buf[9]); + + return rt_build_tuple(4, data); // items in reverse order in data +} + +MP_DEFINE_CONST_FUN_OBJ_0(pyb_mma_read_obj, pyb_mma_read); + +mp_obj_t pyb_mma_read_all(void) { + mp_obj_t data[11]; + mma_start(MMA_ADDR, 1); + mma_send_byte(0); + mma_restart(MMA_ADDR, 0); + for (int i = 0; i <= 9; i++) { + data[10 - i] = mp_obj_new_int(mma_read_ack()); + } + data[0] = mp_obj_new_int(mma_read_nack()); + + return rt_build_tuple(11, data); // items in reverse order in data +} + +MP_DEFINE_CONST_FUN_OBJ_0(pyb_mma_read_all_obj, pyb_mma_read_all); + +mp_obj_t pyb_mma_write_mode(mp_obj_t o_int, mp_obj_t o_mode) { + mma_start(MMA_ADDR, 1); + mma_send_byte(6); // start at int + mma_send_byte(mp_obj_get_int(o_int)); + mma_send_byte(mp_obj_get_int(o_mode)); + mma_stop(); + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_2(pyb_mma_write_mode_obj, pyb_mma_write_mode); + diff --git a/stm/mma.h b/stm/mma.h index f43d182954..0bdf5d1009 100644 --- a/stm/mma.h +++ b/stm/mma.h @@ -5,3 +5,7 @@ void mma_send_byte(uint8_t data); uint8_t mma_read_ack(void); uint8_t mma_read_nack(void); void mma_stop(void); + +MP_DECLARE_CONST_FUN_OBJ(pyb_mma_read_obj); +MP_DECLARE_CONST_FUN_OBJ(pyb_mma_read_all_obj); +MP_DECLARE_CONST_FUN_OBJ(pyb_mma_write_mode_obj); diff --git a/unix-cpy/Makefile b/unix-cpy/Makefile index ef1999a1b0..9399a765c3 100644 --- a/unix-cpy/Makefile +++ b/unix-cpy/Makefile @@ -39,6 +39,7 @@ PY_O = \ objgenerator.o \ objinstance.o \ objlist.o \ + objmodule.o \ objnone.o \ objrange.o \ objset.o \ diff --git a/unix/Makefile b/unix/Makefile index 492962c8c7..b8955d11a8 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -46,6 +46,7 @@ PY_O = \ objgenerator.o \ objinstance.o \ objlist.o \ + objmodule.o \ objnone.o \ objrange.o \ objset.o \