From 8bc3fc20feca9ebe9e9972aeb6b68a81d792c5df Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 6 Nov 2016 01:30:19 +0300 Subject: esp8266: Rename "machine" module implementation to use contemporary naming. Previously they used historical "pyb" affix causing confusion and inconsistency (there's no "pyb" module in modern ports; but people took esp8266 port as an example, and "pyb" naming kept proliferating, while other people complained that source structure is not clear). --- esp8266/Makefile | 18 +- esp8266/esp8266.ld | 16 +- esp8266/esp_mphal.h | 2 +- esp8266/esponewire.c | 2 +- esp8266/fatfs_port.c | 2 +- esp8266/intr.c | 2 +- esp8266/machine_adc.c | 83 +++++++++ esp8266/machine_hspi.c | 212 ++++++++++++++++++++++ esp8266/machine_pin.c | 462 ++++++++++++++++++++++++++++++++++++++++++++++++ esp8266/machine_pwm.c | 172 ++++++++++++++++++ esp8266/machine_rtc.c | 273 ++++++++++++++++++++++++++++ esp8266/machine_spi.c | 142 +++++++++++++++ esp8266/machine_uart.c | 279 +++++++++++++++++++++++++++++ esp8266/machine_wdt.c | 85 +++++++++ esp8266/modesp.c | 3 +- esp8266/modmachine.c | 3 +- esp8266/modmachine.h | 43 +++++ esp8266/modmachinewdt.c | 85 --------- esp8266/modonewire.c | 2 +- esp8266/modpyb.c | 4 +- esp8266/modpyb.h | 36 ---- esp8266/modpybadc.c | 83 --------- esp8266/modpybhspi.c | 212 ---------------------- esp8266/modpybpin.c | 462 ------------------------------------------------ esp8266/modpybpwm.c | 172 ------------------ esp8266/modpybrtc.c | 273 ---------------------------- esp8266/modpybrtc.h | 34 ---- esp8266/modpybspi.c | 142 --------------- esp8266/modpybuart.c | 279 ----------------------------- esp8266/modutime.c | 3 +- 30 files changed, 1778 insertions(+), 1808 deletions(-) create mode 100644 esp8266/machine_adc.c create mode 100644 esp8266/machine_hspi.c create mode 100644 esp8266/machine_pin.c create mode 100644 esp8266/machine_pwm.c create mode 100644 esp8266/machine_rtc.c create mode 100644 esp8266/machine_spi.c create mode 100644 esp8266/machine_uart.c create mode 100644 esp8266/machine_wdt.c create mode 100644 esp8266/modmachine.h delete mode 100644 esp8266/modmachinewdt.c delete mode 100644 esp8266/modpyb.h delete mode 100644 esp8266/modpybadc.c delete mode 100644 esp8266/modpybhspi.c delete mode 100644 esp8266/modpybpin.c delete mode 100644 esp8266/modpybpwm.c delete mode 100644 esp8266/modpybrtc.c delete mode 100644 esp8266/modpybrtc.h delete mode 100644 esp8266/modpybspi.c delete mode 100644 esp8266/modpybuart.c diff --git a/esp8266/Makefile b/esp8266/Makefile index 245f95b40..3fce1788c 100644 --- a/esp8266/Makefile +++ b/esp8266/Makefile @@ -78,19 +78,19 @@ SRC_C = \ espapa102.c \ intr.c \ modpyb.c \ - modpybpin.c \ - modpybpwm.c \ - modpybrtc.c \ - modpybadc.c \ - modpybuart.c \ - modmachinewdt.c \ - modpybspi.c \ - modpybhspi.c \ + modmachine.c \ + machine_pin.c \ + machine_pwm.c \ + machine_rtc.c \ + machine_adc.c \ + machine_uart.c \ + machine_wdt.c \ + machine_spi.c \ + machine_hspi.c \ modesp.c \ modnetwork.c \ modutime.c \ moduos.c \ - modmachine.c \ modonewire.c \ ets_alt_task.c \ fatfs_port.c \ diff --git a/esp8266/esp8266.ld b/esp8266/esp8266.ld index 5fb6f1379..20b259dff 100644 --- a/esp8266/esp8266.ld +++ b/esp8266/esp8266.ld @@ -137,16 +137,16 @@ SECTIONS *lexerstr32.o(.literal* .text*) *utils.o(.literal* .text*) *modpyb.o(.literal*, .text*) - *modpybpin.o(.literal*, .text*) - *modpybpwm.o(.literal*, .text*) - *modpybrtc.o(.literal*, .text*) - *modpybadc.o(.literal*, .text*) - *modpybuart.o(.literal*, .text*) + *machine_pin.o(.literal*, .text*) + *machine_pwm.o(.literal*, .text*) + *machine_rtc.o(.literal*, .text*) + *machine_adc.o(.literal*, .text*) + *machine_uart.o(.literal*, .text*) *modpybi2c.o(.literal*, .text*) *modmachine.o(.literal*, .text*) - *modmachinewdt.o(.literal*, .text*) - *modpybspi.o(.literal*, .text*) - *modpybhspi.o(.literal*, .text*) + *machine_wdt.o(.literal*, .text*) + *machine_spi.o(.literal*, .text*) + *machine_hspi.o(.literal*, .text*) *hspi.o(.literal*, .text*) *modesp.o(.literal* .text*) *modnetwork.o(.literal* .text*) diff --git a/esp8266/esp_mphal.h b/esp8266/esp_mphal.h index 7a71c0f03..1622667f9 100644 --- a/esp8266/esp_mphal.h +++ b/esp8266/esp_mphal.h @@ -75,7 +75,7 @@ void ets_event_poll(void); // C-level pin HAL #include "etshal.h" #include "gpio.h" -#include "esp8266/modpyb.h" +#include "esp8266/modmachine.h" #define mp_hal_pin_obj_t uint32_t #define mp_hal_get_pin_obj(o) mp_obj_get_pin(o) void mp_hal_pin_input(mp_hal_pin_obj_t pin); diff --git a/esp8266/esponewire.c b/esp8266/esponewire.c index 797ec0bd2..22bb45b15 100644 --- a/esp8266/esponewire.c +++ b/esp8266/esponewire.c @@ -28,7 +28,7 @@ #include "etshal.h" #include "user_interface.h" -#include "modpyb.h" +#include "modmachine.h" #include "esponewire.h" #define TIMING_RESET1 (0) diff --git a/esp8266/fatfs_port.c b/esp8266/fatfs_port.c index b87906f78..9c84f04e4 100644 --- a/esp8266/fatfs_port.c +++ b/esp8266/fatfs_port.c @@ -27,7 +27,7 @@ #include "py/obj.h" #include "lib/fatfs/ff.h" #include "timeutils.h" -#include "modpybrtc.h" +#include "modmachine.h" DWORD get_fattime(void) { diff --git a/esp8266/intr.c b/esp8266/intr.c index 62da4a721..456d6cb04 100644 --- a/esp8266/intr.c +++ b/esp8266/intr.c @@ -27,7 +27,7 @@ #include "etshal.h" #include "ets_alt_task.h" -#include "modpyb.h" +#include "modmachine.h" // this is in a separate file so it can go in iRAM void pin_intr_handler_iram(void *arg) { diff --git a/esp8266/machine_adc.c b/esp8266/machine_adc.c new file mode 100644 index 000000000..26b28c50b --- /dev/null +++ b/esp8266/machine_adc.c @@ -0,0 +1,83 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Josef Gajdusek + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "py/nlr.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "user_interface.h" + +const mp_obj_type_t pyb_adc_type; + +typedef struct _pyb_adc_obj_t { + mp_obj_base_t base; + bool isvdd; +} pyb_adc_obj_t; + +STATIC pyb_adc_obj_t pyb_adc_vdd3 = {{&pyb_adc_type}, true}; +STATIC pyb_adc_obj_t pyb_adc_adc = {{&pyb_adc_type}, false}; + +STATIC mp_obj_t pyb_adc_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + mp_int_t chn = mp_obj_get_int(args[0]); + + switch (chn) { + case 0: + return &pyb_adc_adc; + case 1: + return &pyb_adc_vdd3; + default: + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "not a valid ADC Channel: %d", chn)); + } +} + +STATIC mp_obj_t pyb_adc_read(mp_obj_t self_in) { + pyb_adc_obj_t *adc = self_in; + + if (adc->isvdd) { + return mp_obj_new_int(system_get_vdd33()); + } else { + return mp_obj_new_int(system_adc_read()); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_adc_read_obj, pyb_adc_read); + +STATIC const mp_map_elem_t pyb_adc_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&pyb_adc_read_obj } +}; +STATIC MP_DEFINE_CONST_DICT(pyb_adc_locals_dict, pyb_adc_locals_dict_table); + +const mp_obj_type_t pyb_adc_type = { + { &mp_type_type }, + .name = MP_QSTR_ADC, + .make_new = pyb_adc_make_new, + .locals_dict = (mp_obj_t)&pyb_adc_locals_dict, +}; diff --git a/esp8266/machine_hspi.c b/esp8266/machine_hspi.c new file mode 100644 index 000000000..10a090269 --- /dev/null +++ b/esp8266/machine_hspi.c @@ -0,0 +1,212 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "ets_sys.h" +#include "etshal.h" +#include "ets_alt_task.h" + +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mphal.h" +#include "extmod/machine_spi.h" + +#include "hspi.h" + +mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *args); + +typedef struct _pyb_hspi_obj_t { + mp_obj_base_t base; + uint32_t baudrate; + uint8_t polarity; + uint8_t phase; +} pyb_hspi_obj_t; + + +STATIC void hspi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { + (void)self_in; + + if (dest == NULL) { + // fast case when we only need to write data + size_t chunk_size = 1024; + size_t count = len / chunk_size; + size_t i = 0; + for (size_t j = 0; j < count; ++j) { + for (size_t k = 0; k < chunk_size; ++k) { + spi_tx8fast(HSPI, src[i]); + ++i; + } + ets_loop_iter(); + } + while (i < len) { + spi_tx8fast(HSPI, src[i]); + ++i; + } + } else { + // we need to read and write data + + // Process data in chunks, let the pending tasks run in between + size_t chunk_size = 1024; // TODO this should depend on baudrate + size_t count = len / chunk_size; + size_t i = 0; + for (size_t j = 0; j < count; ++j) { + for (size_t k = 0; k < chunk_size; ++k) { + dest[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, src[i], 8, 0); + ++i; + } + ets_loop_iter(); + } + while (i < len) { + dest[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, src[i], 8, 0); + ++i; + } + } +} + +/******************************************************************************/ +// MicroPython bindings for HSPI + +STATIC void pyb_hspi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + pyb_hspi_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "HSPI(id=1, baudrate=%u, polarity=%u, phase=%u)", + self->baudrate, self->polarity, self->phase); +} + +STATIC void pyb_hspi_init_helper(pyb_hspi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), + allowed_args, args); + + if (args[ARG_baudrate].u_int != -1) { + self->baudrate = args[ARG_baudrate].u_int; + } + if (args[ARG_polarity].u_int != -1) { + self->polarity = args[ARG_polarity].u_int; + } + if (args[ARG_phase].u_int != -1) { + self->phase = args[ARG_phase].u_int; + } + if (self->baudrate == 80000000L) { + // Special case for full speed. + spi_init_gpio(HSPI, SPI_CLK_80MHZ_NODIV); + spi_clock(HSPI, 0, 0); + } else if (self->baudrate > 40000000L) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, + "impossible baudrate")); + } else { + uint32_t divider = 40000000L / self->baudrate; + uint16_t prediv = MIN(divider, SPI_CLKDIV_PRE + 1); + uint16_t cntdiv = (divider / prediv) * 2; // cntdiv has to be even + if (cntdiv > SPI_CLKCNT_N + 1 || cntdiv == 0 || prediv == 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, + "impossible baudrate")); + } + self->baudrate = 80000000L / (prediv * cntdiv); + spi_init_gpio(HSPI, SPI_CLK_USE_DIV); + spi_clock(HSPI, prediv, cntdiv); + } + // TODO: Make the byte order configurable too (discuss param names) + spi_tx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW); + spi_rx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW); + CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE | SPI_USR_MISO | + SPI_USR_ADDR | SPI_USR_COMMAND | SPI_USR_DUMMY); + // Clear Dual or Quad lines transmission mode + CLEAR_PERI_REG_MASK(SPI_CTRL(HSPI), SPI_QIO_MODE | SPI_DIO_MODE | + SPI_DOUT_MODE | SPI_QOUT_MODE); + spi_mode(HSPI, self->phase, self->polarity); +} + +mp_obj_t pyb_hspi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, true); + mp_int_t id = -1; + if (n_args > 0) { + id = mp_obj_get_int(args[0]); + } + + if (id == -1) { + // Multiplex to bitbanging SPI + if (n_args > 0) { + args++; + } + return pyb_spi_make_new(type, 0, n_kw, args); + } + + if (id != 1) { + // FlashROM is on SPI0, so far we don't support its usage + mp_raise_ValueError(""); + } + + pyb_hspi_obj_t *self = m_new_obj(pyb_hspi_obj_t); + self->base.type = &pyb_hspi_type; + // set defaults + self->baudrate = 80000000L; + self->polarity = 0; + self->phase = 0; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + pyb_hspi_init_helper(self, n_args, args, &kw_args); + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t pyb_hspi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + pyb_hspi_init_helper(args[0], n_args - 1, args + 1, kw_args); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(pyb_hspi_init_obj, 1, pyb_hspi_init); + +STATIC const mp_rom_map_elem_t pyb_hspi_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_hspi_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(pyb_hspi_locals_dict, pyb_hspi_locals_dict_table); + +STATIC const mp_machine_spi_p_t pyb_hspi_p = { + .transfer = hspi_transfer, +}; + +const mp_obj_type_t pyb_hspi_type = { + { &mp_type_type }, + .name = MP_QSTR_HSPI, + .print = pyb_hspi_print, + .make_new = pyb_hspi_make_new, + .protocol = &pyb_hspi_p, + .locals_dict = (mp_obj_dict_t*)&pyb_hspi_locals_dict, +}; diff --git a/esp8266/machine_pin.c b/esp8266/machine_pin.c new file mode 100644 index 000000000..205c58aae --- /dev/null +++ b/esp8266/machine_pin.c @@ -0,0 +1,462 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014, 2015 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "etshal.h" +#include "c_types.h" +#include "user_interface.h" +#include "gpio.h" + +#include "py/nlr.h" +#include "py/runtime.h" +#include "py/gc.h" +#include "py/mphal.h" +#include "modmachine.h" + +#define GET_TRIGGER(phys_port) \ + GPIO_PIN_INT_TYPE_GET(GPIO_REG_READ(GPIO_PIN_ADDR(phys_port))) +#define SET_TRIGGER(phys_port, trig) \ + (GPIO_REG_WRITE(GPIO_PIN_ADDR(phys_port), \ + (GPIO_REG_READ(GPIO_PIN_ADDR(phys_port)) & ~GPIO_PIN_INT_TYPE_MASK) \ + | GPIO_PIN_INT_TYPE_SET(trig))) \ + +#define GPIO_MODE_INPUT (0) +#define GPIO_MODE_OUTPUT (1) +#define GPIO_MODE_OPEN_DRAIN (2) // synthesised +#define GPIO_PULL_NONE (0) +#define GPIO_PULL_UP (1) +// Removed in SDK 1.1.0 +//#define GPIO_PULL_DOWN (2) + +typedef struct _pin_irq_obj_t { + mp_obj_base_t base; + uint16_t phys_port; +} pin_irq_obj_t; + +const pyb_pin_obj_t pyb_pin_obj[16 + 1] = { + {{&pyb_pin_type}, 0, FUNC_GPIO0, PERIPHS_IO_MUX_GPIO0_U}, + {{&pyb_pin_type}, 1, FUNC_GPIO1, PERIPHS_IO_MUX_U0TXD_U}, + {{&pyb_pin_type}, 2, FUNC_GPIO2, PERIPHS_IO_MUX_GPIO2_U}, + {{&pyb_pin_type}, 3, FUNC_GPIO3, PERIPHS_IO_MUX_U0RXD_U}, + {{&pyb_pin_type}, 4, FUNC_GPIO4, PERIPHS_IO_MUX_GPIO4_U}, + {{&pyb_pin_type}, 5, FUNC_GPIO5, PERIPHS_IO_MUX_GPIO5_U}, + {{NULL}, 0, 0, 0}, + {{NULL}, 0, 0, 0}, + {{NULL}, 0, 0, 0}, + {{&pyb_pin_type}, 9, FUNC_GPIO9, PERIPHS_IO_MUX_SD_DATA2_U}, + {{&pyb_pin_type}, 10, FUNC_GPIO10, PERIPHS_IO_MUX_SD_DATA3_U}, + {{NULL}, 0, 0, 0}, + {{&pyb_pin_type}, 12, FUNC_GPIO12, PERIPHS_IO_MUX_MTDI_U}, + {{&pyb_pin_type}, 13, FUNC_GPIO13, PERIPHS_IO_MUX_MTCK_U}, + {{&pyb_pin_type}, 14, FUNC_GPIO14, PERIPHS_IO_MUX_MTMS_U}, + {{&pyb_pin_type}, 15, FUNC_GPIO15, PERIPHS_IO_MUX_MTDO_U}, + // GPIO16 is special, belongs to different register set, and + // otherwise handled specially. + {{&pyb_pin_type}, 16, -1, -1}, +}; + +STATIC uint8_t pin_mode[16 + 1]; + +// forward declaration +STATIC const pin_irq_obj_t pin_irq_obj[16]; + +void pin_init0(void) { + ETS_GPIO_INTR_DISABLE(); + ETS_GPIO_INTR_ATTACH(pin_intr_handler_iram, NULL); + // disable all interrupts + memset(&MP_STATE_PORT(pin_irq_handler)[0], 0, 16 * sizeof(mp_obj_t)); + for (int p = 0; p < 16; ++p) { + GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << p); + SET_TRIGGER(p, 0); + } + ETS_GPIO_INTR_ENABLE(); +} + +void pin_intr_handler(uint32_t status) { + gc_lock(); + status &= 0xffff; + for (int p = 0; status; ++p, status >>= 1) { + if (status & 1) { + mp_obj_t handler = MP_STATE_PORT(pin_irq_handler)[p]; + if (handler != MP_OBJ_NULL) { + mp_call_function_1_protected(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p])); + } + } + } + gc_unlock(); +} + +pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in) { + if (mp_obj_get_type(pin_in) != &pyb_pin_type) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "expecting a pin")); + } + pyb_pin_obj_t *self = pin_in; + return self; +} + +uint mp_obj_get_pin(mp_obj_t pin_in) { + return mp_obj_get_pin_obj(pin_in)->phys_port; +} + +void mp_hal_pin_input(mp_hal_pin_obj_t pin_id) { + pin_mode[pin_id] = GPIO_MODE_INPUT; + if (pin_id == 16) { + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); + WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); + WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); // input + } else { + const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id]; + PIN_FUNC_SELECT(self->periph, self->func); + PIN_PULLUP_DIS(self->periph); + gpio_output_set(0, 0, 0, 1 << self->phys_port); + } +} + +void mp_hal_pin_output(mp_hal_pin_obj_t pin_id) { + pin_mode[pin_id] = GPIO_MODE_OUTPUT; + if (pin_id == 16) { + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); + WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); + WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); // output + } else { + const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id]; + PIN_FUNC_SELECT(self->periph, self->func); + PIN_PULLUP_DIS(self->periph); + gpio_output_set(0, 0, 1 << self->phys_port, 0); + } +} + +int pin_get(uint pin) { + if (pin == 16) { + return READ_PERI_REG(RTC_GPIO_IN_DATA) & 1; + } + return GPIO_INPUT_GET(pin); +} + +void pin_set(uint pin, int value) { + if (pin == 16) { + int out_en = (pin_mode[pin] == GPIO_MODE_OUTPUT); + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); + WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); + WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | out_en); + WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & ~1) | value); + return; + } + + uint32_t enable = 0; + uint32_t disable = 0; + switch (pin_mode[pin]) { + case GPIO_MODE_INPUT: + value = -1; + disable = 1; + break; + + case GPIO_MODE_OUTPUT: + enable = 1; + break; + + case GPIO_MODE_OPEN_DRAIN: + if (value == -1) { + return; + } else if (value == 0) { + enable = 1; + } else { + value = -1; + disable = 1; + } + break; + } + + enable <<= pin; + disable <<= pin; + if (value == -1) { + gpio_output_set(0, 0, enable, disable); + } else { + gpio_output_set(value << pin, (1 - value) << pin, enable, disable); + } +} + +STATIC void pyb_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + pyb_pin_obj_t *self = self_in; + + // pin name + mp_printf(print, "Pin(%u)", self->phys_port); +} + +// pin.init(mode, pull=None, *, value) +STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_pull, ARG_value }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + }; + + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // get io mode + uint mode = args[ARG_mode].u_int; + + // get pull mode + uint pull = GPIO_PULL_NONE; + if (args[ARG_pull].u_obj != mp_const_none) { + pull = mp_obj_get_int(args[ARG_pull].u_obj); + } + + // get initial value + int value; + if (args[ARG_value].u_obj == MP_OBJ_NULL) { + value = -1; + } else { + value = mp_obj_is_true(args[ARG_value].u_obj); + } + + // save the mode + pin_mode[self->phys_port] = mode; + + // configure the GPIO as requested + if (self->phys_port == 16) { + // only pull-down seems to be supported by the hardware, and + // we only expose pull-up behaviour in software + if (pull != GPIO_PULL_NONE) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin(16) doesn't support pull")); + } + } else { + PIN_FUNC_SELECT(self->periph, self->func); + #if 0 + // Removed in SDK 1.1.0 + if ((pull & GPIO_PULL_DOWN) == 0) { + PIN_PULLDWN_DIS(self->periph); + } + #endif + if ((pull & GPIO_PULL_UP) == 0) { + PIN_PULLUP_DIS(self->periph); + } + #if 0 + if ((pull & GPIO_PULL_DOWN) != 0) { + PIN_PULLDWN_EN(self->periph); + } + #endif + if ((pull & GPIO_PULL_UP) != 0) { + PIN_PULLUP_EN(self->periph); + } + } + + pin_set(self->phys_port, value); + + return mp_const_none; +} + +// constructor(id, ...) +STATIC mp_obj_t pyb_pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + // get the wanted pin object + int wanted_pin = mp_obj_get_int(args[0]); + pyb_pin_obj_t *pin = NULL; + if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(pyb_pin_obj)) { + pin = (pyb_pin_obj_t*)&pyb_pin_obj[wanted_pin]; + } + if (pin == NULL || pin->base.type == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin")); + } + + if (n_args > 1 || n_kw > 0) { + // pin mode given, so configure this GPIO + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + pyb_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args); + } + + return (mp_obj_t)pin; +} + +// fast method for getting/setting pin value +STATIC mp_obj_t pyb_pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + pyb_pin_obj_t *self = self_in; + if (n_args == 0) { + // get pin + return MP_OBJ_NEW_SMALL_INT(pin_get(self->phys_port)); + } else { + // set pin + pin_set(self->phys_port, mp_obj_is_true(args[0])); + return mp_const_none; + } +} + +// pin.init(mode, pull) +STATIC mp_obj_t pyb_pin_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + return pyb_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); +} +MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pin_init_obj, 1, pyb_pin_obj_init); + +// pin.value([value]) +STATIC mp_obj_t pyb_pin_value(mp_uint_t n_args, const mp_obj_t *args) { + return pyb_pin_call(args[0], n_args - 1, 0, args + 1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pin_value_obj, 1, 2, pyb_pin_value); + +// pin.low() +STATIC mp_obj_t pyb_pin_low(mp_obj_t self_in) { + pyb_pin_obj_t *self = self_in; + pin_set(self->phys_port, 0); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_low_obj, pyb_pin_low); + +// pin.high() +STATIC mp_obj_t pyb_pin_high(mp_obj_t self_in) { + pyb_pin_obj_t *self = self_in; + pin_set(self->phys_port, 1); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_high_obj, pyb_pin_high); + +// pin.irq(*, trigger, handler=None) +STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_trigger, ARG_handler }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + pyb_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (self->phys_port >= 16) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "pin does not have IRQ capabilities")); + } + + if (args[ARG_trigger].u_int != 0) { + // configure irq + mp_obj_t handler = args[ARG_handler].u_obj; + if (handler == mp_const_none) { + handler = MP_OBJ_NULL; + } + ETS_GPIO_INTR_DISABLE(); + MP_STATE_PORT(pin_irq_handler)[self->phys_port] = handler; + SET_TRIGGER(self->phys_port, args[ARG_trigger].u_int); + GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << self->phys_port); + ETS_GPIO_INTR_ENABLE(); + } + + // return the irq object + return MP_OBJ_FROM_PTR(&pin_irq_obj[self->phys_port]); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pin_irq_obj, 1, pyb_pin_irq); + +STATIC const mp_map_elem_t pyb_pin_locals_dict_table[] = { + // instance methods + { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_pin_init_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&pyb_pin_value_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pyb_pin_low_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pyb_pin_high_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_pin_irq_obj }, + + // class constants + { MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_INPUT) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OPEN_DRAIN) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_UP) }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_DOWN) }, + + // IRG triggers, can be or'd together + { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING), MP_OBJ_NEW_SMALL_INT(GPIO_PIN_INTR_POSEDGE) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_PIN_INTR_NEGEDGE) }, +}; + +STATIC MP_DEFINE_CONST_DICT(pyb_pin_locals_dict, pyb_pin_locals_dict_table); + +const mp_obj_type_t pyb_pin_type = { + { &mp_type_type }, + .name = MP_QSTR_Pin, + .print = pyb_pin_print, + .make_new = pyb_pin_make_new, + .call = pyb_pin_call, + .locals_dict = (mp_obj_t)&pyb_pin_locals_dict, +}; + +/******************************************************************************/ +// Pin IRQ object + +STATIC const mp_obj_type_t pin_irq_type; + +STATIC const pin_irq_obj_t pin_irq_obj[16] = { + {{&pin_irq_type}, 0}, + {{&pin_irq_type}, 1}, + {{&pin_irq_type}, 2}, + {{&pin_irq_type}, 3}, + {{&pin_irq_type}, 4}, + {{&pin_irq_type}, 5}, + {{&pin_irq_type}, 6}, + {{&pin_irq_type}, 7}, + {{&pin_irq_type}, 8}, + {{&pin_irq_type}, 9}, + {{&pin_irq_type}, 10}, + {{&pin_irq_type}, 11}, + {{&pin_irq_type}, 12}, + {{&pin_irq_type}, 13}, + {{&pin_irq_type}, 14}, + {{&pin_irq_type}, 15}, +}; + +STATIC mp_obj_t pin_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + pin_irq_obj_t *self = self_in; + mp_arg_check_num(n_args, n_kw, 0, 0, false); + pin_intr_handler(1 << self->phys_port); + return mp_const_none; +} + +STATIC mp_obj_t pin_irq_trigger(size_t n_args, const mp_obj_t *args) { + pin_irq_obj_t *self = args[0]; + uint32_t orig_trig = GET_TRIGGER(self->phys_port); + if (n_args == 2) { + // set trigger + SET_TRIGGER(self->phys_port, mp_obj_get_int(args[1])); + } + // return original trigger value + return MP_OBJ_NEW_SMALL_INT(orig_trig); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_irq_trigger_obj, 1, 2, pin_irq_trigger); + +STATIC const mp_rom_map_elem_t pin_irq_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&pin_irq_trigger_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(pin_irq_locals_dict, pin_irq_locals_dict_table); + +STATIC const mp_obj_type_t pin_irq_type = { + { &mp_type_type }, + .name = MP_QSTR_IRQ, + .call = pin_irq_call, + .locals_dict = (mp_obj_dict_t*)&pin_irq_locals_dict, +}; diff --git a/esp8266/machine_pwm.c b/esp8266/machine_pwm.c new file mode 100644 index 000000000..5d30f0965 --- /dev/null +++ b/esp8266/machine_pwm.c @@ -0,0 +1,172 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "esppwm.h" + +#include "py/nlr.h" +#include "py/runtime.h" +#include "modmachine.h" + +typedef struct _pyb_pwm_obj_t { + mp_obj_base_t base; + pyb_pin_obj_t *pin; + uint8_t active; + uint8_t channel; +} pyb_pwm_obj_t; + +STATIC bool pwm_inited = false; + +/******************************************************************************/ +// MicroPython bindings for PWM + +STATIC void pyb_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "PWM(%u", self->pin->phys_port); + if (self->active) { + mp_printf(print, ", freq=%u, duty=%u", + pwm_get_freq(self->channel), pwm_get_duty(self->channel)); + } + mp_printf(print, ")"); +} + +STATIC void pyb_pwm_init_helper(pyb_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_freq, ARG_duty }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_duty, MP_ARG_INT, {.u_int = -1} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + int channel = pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func); + if (channel == -1) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "PWM not supported on pin %d", self->pin->phys_port)); + } + + self->channel = channel; + self->active = 1; + if (args[ARG_freq].u_int != -1) { + pwm_set_freq(args[ARG_freq].u_int, self->channel); + } + if (args[ARG_duty].u_int != -1) { + pwm_set_duty(args[ARG_duty].u_int, self->channel); + } + + pwm_start(); +} + +STATIC mp_obj_t pyb_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + pyb_pin_obj_t *pin = mp_obj_get_pin_obj(args[0]); + + // create PWM object from the given pin + pyb_pwm_obj_t *self = m_new_obj(pyb_pwm_obj_t); + self->base.type = &pyb_pwm_type; + self->pin = pin; + self->active = 0; + self->channel = -1; + + // start the PWM subsystem if it's not already running + if (!pwm_inited) { + pwm_init(); + pwm_inited = true; + } + + // start the PWM running for this channel + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + pyb_pwm_init_helper(self, n_args - 1, args + 1, &kw_args); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t pyb_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + pyb_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pwm_init_obj, 1, pyb_pwm_init); + +STATIC mp_obj_t pyb_pwm_deinit(mp_obj_t self_in) { + pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); + pwm_delete(self->channel); + self->active = 0; + pwm_start(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pwm_deinit_obj, pyb_pwm_deinit); + +STATIC mp_obj_t pyb_pwm_freq(size_t n_args, const mp_obj_t *args) { + //pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (n_args == 1) { + // get + return MP_OBJ_NEW_SMALL_INT(pwm_get_freq(0)); + } else { + // set + pwm_set_freq(mp_obj_get_int(args[1]), 0); + pwm_start(); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pwm_freq_obj, 1, 2, pyb_pwm_freq); + +STATIC mp_obj_t pyb_pwm_duty(size_t n_args, const mp_obj_t *args) { + pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (!self->active) { + pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func); + self->active = 1; + } + if (n_args == 1) { + // get + return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel)); + } else { + // set + pwm_set_duty(mp_obj_get_int(args[1]), self->channel); + pwm_start(); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pwm_duty_obj, 1, 2, pyb_pwm_duty); + +STATIC const mp_rom_map_elem_t pyb_pwm_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_pwm_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_pwm_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_pwm_freq_obj) }, + { MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&pyb_pwm_duty_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(pyb_pwm_locals_dict, pyb_pwm_locals_dict_table); + +const mp_obj_type_t pyb_pwm_type = { + { &mp_type_type }, + .name = MP_QSTR_PWM, + .print = pyb_pwm_print, + .make_new = pyb_pwm_make_new, + .locals_dict = (mp_obj_dict_t*)&pyb_pwm_locals_dict, +}; diff --git a/esp8266/machine_rtc.c b/esp8266/machine_rtc.c new file mode 100644 index 000000000..54eeea6f6 --- /dev/null +++ b/esp8266/machine_rtc.c @@ -0,0 +1,273 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Josef Gajdusek + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "py/nlr.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "timeutils.h" +#include "user_interface.h" +#include "modmachine.h" + +typedef struct _pyb_rtc_obj_t { + mp_obj_base_t base; +} pyb_rtc_obj_t; + +#define MEM_MAGIC 0x75507921 +#define MEM_DELTA_ADDR 64 +#define MEM_CAL_ADDR (MEM_DELTA_ADDR + 2) +#define MEM_USER_MAGIC_ADDR (MEM_CAL_ADDR + 1) +#define MEM_USER_LEN_ADDR (MEM_USER_MAGIC_ADDR + 1) +#define MEM_USER_DATA_ADDR (MEM_USER_LEN_ADDR + 1) +#define MEM_USER_MAXLEN (512 - (MEM_USER_DATA_ADDR - MEM_DELTA_ADDR) * 4) + +// singleton RTC object +STATIC const pyb_rtc_obj_t pyb_rtc_obj = {{&pyb_rtc_type}}; + +// ALARM0 state +uint32_t pyb_rtc_alarm0_wake; // see MACHINE_WAKE_xxx constants +uint64_t pyb_rtc_alarm0_expiry; // in microseconds + +// RTC overflow checking +STATIC uint32_t rtc_last_ticks; + +void mp_hal_rtc_init(void) { + uint32_t magic; + + system_rtc_mem_read(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic)); + if (magic != MEM_MAGIC) { + magic = MEM_MAGIC; + system_rtc_mem_write(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic)); + uint32_t cal = system_rtc_clock_cali_proc(); + int64_t delta = 0; + system_rtc_mem_write(MEM_CAL_ADDR, &cal, sizeof(cal)); + system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); + uint32_t len = 0; + system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len)); + } + // system_get_rtc_time() is always 0 after reset/deepsleep + rtc_last_ticks = system_get_rtc_time(); + + // reset ALARM0 state + pyb_rtc_alarm0_wake = 0; + pyb_rtc_alarm0_expiry = 0; +} + +STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + // return constant object + return (mp_obj_t)&pyb_rtc_obj; +} + +void pyb_rtc_set_us_since_2000(uint64_t nowus) { + uint32_t cal = system_rtc_clock_cali_proc(); + // Save RTC ticks for overflow detection. + rtc_last_ticks = system_get_rtc_time(); + int64_t delta = nowus - (((uint64_t)rtc_last_ticks * cal) >> 12); + + // As the calibration value jitters quite a bit, to make the + // clock at least somewhat practially usable, we need to store it + system_rtc_mem_write(MEM_CAL_ADDR, &cal, sizeof(cal)); + system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); +}; + +uint64_t pyb_rtc_get_us_since_2000() { + uint32_t cal; + int64_t delta; + uint32_t rtc_ticks; + + system_rtc_mem_read(MEM_CAL_ADDR, &cal, sizeof(cal)); + system_rtc_mem_read(MEM_DELTA_ADDR, &delta, sizeof(delta)); + + // ESP-SDK system_get_rtc_time() only returns uint32 and therefore + // overflow about every 7:45h. Thus, we have to check for + // overflow and handle it. + rtc_ticks = system_get_rtc_time(); + if (rtc_ticks < rtc_last_ticks) { + // Adjust delta because of RTC overflow. + delta += (uint64_t)cal << 20; + system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); + } + rtc_last_ticks = rtc_ticks; + + return (((uint64_t)rtc_ticks * cal) >> 12) + delta; +}; + +void rtc_prepare_deepsleep(uint64_t sleep_us) { + // RTC time will reset at wake up. Let's be preared for this. + int64_t delta = pyb_rtc_get_us_since_2000() + sleep_us; + system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); +} + +STATIC mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) { + if (n_args == 1) { + // Get time + uint64_t msecs = pyb_rtc_get_us_since_2000() / 1000; + + timeutils_struct_time_t tm; + timeutils_seconds_since_2000_to_struct_time(msecs / 1000, &tm); + + mp_obj_t tuple[8] = { + mp_obj_new_int(tm.tm_year), + mp_obj_new_int(tm.tm_mon), + mp_obj_new_int(tm.tm_mday), + mp_obj_new_int(tm.tm_wday), + mp_obj_new_int(tm.tm_hour), + mp_obj_new_int(tm.tm_min), + mp_obj_new_int(tm.tm_sec), + mp_obj_new_int(msecs % 1000) + }; + + return mp_obj_new_tuple(8, tuple); + } else { + // Set time + mp_obj_t *items; + mp_obj_get_array_fixed_n(args[1], 8, &items); + + pyb_rtc_set_us_since_2000( + ((uint64_t)timeutils_seconds_since_2000( + mp_obj_get_int(items[0]), + mp_obj_get_int(items[1]), + mp_obj_get_int(items[2]), + mp_obj_get_int(items[4]), + mp_obj_get_int(items[5]), + mp_obj_get_int(items[6])) * 1000 + mp_obj_get_int(items[7])) * 1000); + + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime); + +STATIC mp_obj_t pyb_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) { + uint8_t rtcram[MEM_USER_MAXLEN]; + uint32_t len; + + if (n_args == 1) { + // read RTC memory + + system_rtc_mem_read(MEM_USER_LEN_ADDR, &len, sizeof(len)); + system_rtc_mem_read(MEM_USER_DATA_ADDR, rtcram, len + (4 - len % 4)); + + return mp_obj_new_bytes(rtcram, len); + } else { + // write RTC memory + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); + + if (bufinfo.len > MEM_USER_MAXLEN) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, + "buffer too long")); + } + + len = bufinfo.len; + system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len)); + + int i = 0; + for (; i < bufinfo.len; i++) { + rtcram[i] = ((uint8_t *)bufinfo.buf)[i]; + } + + system_rtc_mem_write(MEM_USER_DATA_ADDR, rtcram, len + (4 - len % 4)); + + return mp_const_none; + } + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_memory_obj, 1, 2, pyb_rtc_memory); + +STATIC mp_obj_t pyb_rtc_alarm(mp_obj_t self_in, mp_obj_t alarm_id, mp_obj_t time_in) { + (void)self_in; // unused + + // check we want alarm0 + if (mp_obj_get_int(alarm_id) != 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid alarm")); + } + + // set expiry time (in microseconds) + pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_2000() + (uint64_t)mp_obj_get_int(time_in) * 1000; + + return mp_const_none; + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_rtc_alarm_obj, pyb_rtc_alarm); + +STATIC mp_obj_t pyb_rtc_alarm_left(size_t n_args, const mp_obj_t *args) { + // check we want alarm0 + if (n_args > 1 && mp_obj_get_int(args[1]) != 0) { + mp_raise_ValueError("invalid alarm"); + } + + uint64_t now = pyb_rtc_get_us_since_2000(); + if (pyb_rtc_alarm0_expiry <= now) { + return MP_OBJ_NEW_SMALL_INT(0); + } else { + return mp_obj_new_int((pyb_rtc_alarm0_expiry - now) / 1000); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_left_obj, 1, 2, pyb_rtc_alarm_left); + +STATIC mp_obj_t pyb_rtc_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_trigger, ARG_wake }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_wake, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // check we want alarm0 + if (args[ARG_trigger].u_int != 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid alarm")); + } + + // set the wake value + pyb_rtc_alarm0_wake = args[ARG_wake].u_int; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_irq_obj, 1, pyb_rtc_irq); + +STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_datetime), (mp_obj_t)&pyb_rtc_datetime_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_memory), (mp_obj_t)&pyb_rtc_memory_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_alarm), (mp_obj_t)&pyb_rtc_alarm_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_alarm_left), (mp_obj_t)&pyb_rtc_alarm_left_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_rtc_irq_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ALARM0), MP_OBJ_NEW_SMALL_INT(0) }, +}; +STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table); + +const mp_obj_type_t pyb_rtc_type = { + { &mp_type_type }, + .name = MP_QSTR_RTC, + .make_new = pyb_rtc_make_new, + .locals_dict = (mp_obj_t)&pyb_rtc_locals_dict, +}; diff --git a/esp8266/machine_spi.c b/esp8266/machine_spi.c new file mode 100644 index 000000000..e97454711 --- /dev/null +++ b/esp8266/machine_spi.c @@ -0,0 +1,142 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mphal.h" +#include "extmod/machine_spi.h" + +/******************************************************************************/ +// MicroPython bindings for SPI + +STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) { + return 500000 / delay_half; +} + +STATIC uint32_t baudrate_to_delay_half(uint32_t baudrate) { + uint32_t delay_half = 500000 / baudrate; + // round delay_half up so that: actual_baudrate <= requested_baudrate + if (500000 % baudrate != 0) { + delay_half += 1; + } + return delay_half; +} + +STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "SPI(baudrate=%u, polarity=%u, phase=%u, sck=%u, mosi=%u, miso=%u)", + baudrate_from_delay_half(self->delay_half), + self->polarity, self->phase, self->sck, self->mosi, self->miso); +} + +STATIC void pyb_spi_init_helper(mp_machine_soft_spi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_sck, ARG_mosi, ARG_miso }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (args[ARG_baudrate].u_int != -1) { + self->delay_half = baudrate_to_delay_half(args[ARG_baudrate].u_int); + } + if (args[ARG_polarity].u_int != -1) { + self->polarity = args[ARG_polarity].u_int; + } + if (args[ARG_phase].u_int != -1) { + self->phase = args[ARG_phase].u_int; + } + if (args[ARG_sck].u_obj != MP_OBJ_NULL) { + self->sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj); + } + if (args[ARG_mosi].u_obj != MP_OBJ_NULL) { + self->mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj); + } + if (args[ARG_miso].u_obj != MP_OBJ_NULL) { + self->miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj); + } + + // configure pins + mp_hal_pin_write(self->sck, self->polarity); + mp_hal_pin_output(self->sck); + mp_hal_pin_output(self->mosi); + mp_hal_pin_input(self->miso); +} + +mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + mp_machine_soft_spi_obj_t *self = m_new_obj(mp_machine_soft_spi_obj_t); + self->base.type = &pyb_spi_type; + // set defaults + self->delay_half = baudrate_to_delay_half(500000); + self->polarity = 0; + self->phase = 0; + self->sck = 14; + self->mosi = 13; + self->miso = 12; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + pyb_spi_init_helper(self, n_args, args, &kw_args); + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t pyb_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + pyb_spi_init_helper(args[0], n_args - 1, args + 1, kw_args); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init); + +STATIC const mp_rom_map_elem_t pyb_spi_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_spi_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table); + +STATIC const mp_machine_spi_p_t pyb_spi_p = { + .transfer = mp_machine_soft_spi_transfer, +}; + +const mp_obj_type_t pyb_spi_type = { + { &mp_type_type }, + .name = MP_QSTR_SoftSPI, + .print = pyb_spi_print, + .make_new = pyb_spi_make_new, + .protocol = &pyb_spi_p, + .locals_dict = (mp_obj_dict_t*)&pyb_spi_locals_dict, +}; diff --git a/esp8266/machine_uart.c b/esp8266/machine_uart.c new file mode 100644 index 000000000..80e10d131 --- /dev/null +++ b/esp8266/machine_uart.c @@ -0,0 +1,279 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "ets_sys.h" +#include "uart.h" + +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mperrno.h" +#include "modmachine.h" + +// UartDev is defined and initialized in rom code. +extern UartDevice UartDev; + +typedef struct _pyb_uart_obj_t { + mp_obj_base_t base; + uint8_t uart_id; + uint8_t bits; + uint8_t parity; + uint8_t stop; + uint32_t baudrate; + uint16_t timeout; // timeout waiting for first char (in ms) + uint16_t timeout_char; // timeout waiting between chars (in ms) +} pyb_uart_obj_t; + +STATIC const char *_parity_name[] = {"None", "1", "0"}; + +/******************************************************************************/ +// MicroPython bindings for UART + +STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, timeout=%u, timeout_char=%u)", + self->uart_id, self->baudrate, self->bits, _parity_name[self->parity], + self->stop, self->timeout, self->timeout_char); +} + +STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_timeout, ARG_timeout_char }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_stop, MP_ARG_INT, {.u_int = 0} }, + //{ MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + //{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // set baudrate + if (args[ARG_baudrate].u_int > 0) { + self->baudrate = args[ARG_baudrate].u_int; + UartDev.baut_rate = self->baudrate; // Sic! + } + + // set data bits + switch (args[ARG_bits].u_int) { + case 0: + break; + case 5: + UartDev.data_bits = UART_FIVE_BITS; + self->bits = 5; + break; + case 6: + UartDev.data_bits = UART_SIX_BITS; + self->bits = 6; + break; + case 7: + UartDev.data_bits = UART_SEVEN_BITS; + self->bits = 7; + break; + case 8: + UartDev.data_bits = UART_EIGHT_BITS; + self->bits = 8; + break; + default: + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid data bits")); + break; + } + + // set parity + if (args[ARG_parity].u_obj != MP_OBJ_NULL) { + if (args[ARG_parity].u_obj == mp_const_none) { + UartDev.parity = UART_NONE_BITS; + UartDev.exist_parity = UART_STICK_PARITY_DIS; + self->parity = 0; + } else { + mp_int_t parity = mp_obj_get_int(args[ARG_parity].u_obj); + UartDev.exist_parity = UART_STICK_PARITY_EN; + if (parity & 1) { + UartDev.parity = UART_ODD_BITS; + self->parity = 1; + } else { + UartDev.parity = UART_EVEN_BITS; + self->parity = 2; + } + } + } + + // set stop bits + switch (args[ARG_stop].u_int) { + case 0: + break; + case 1: + UartDev.stop_bits = UART_ONE_STOP_BIT; + self->stop = 1; + break; + case 2: + UartDev.stop_bits = UART_TWO_STOP_BIT; + self->stop = 2; + break; + default: + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid stop bits")); + break; + } + + // set timeout + self->timeout = args[ARG_timeout].u_int; + + // set timeout_char + // make sure it is at least as long as a whole character (13 bits to be safe) + self->timeout_char = args[ARG_timeout_char].u_int; + uint32_t min_timeout_char = 13000 / self->baudrate + 1; + if (self->timeout_char < min_timeout_char) { + self->timeout_char = min_timeout_char; + } + + // setup + uart_setup(self->uart_id); +} + +STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + // get uart id + mp_int_t uart_id = mp_obj_get_int(args[0]); + if (uart_id != 0 && uart_id != 1) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) does not exist", uart_id)); + } + + // create instance + pyb_uart_obj_t *self = m_new_obj(pyb_uart_obj_t); + self->base.type = &pyb_uart_type; + self->uart_id = uart_id; + self->baudrate = 115200; + self->bits = 8; + self->parity = 0; + self->stop = 1; + self->timeout = 0; + self->timeout_char = 0; + + // init the peripheral + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + pyb_uart_init_helper(self, n_args - 1, args + 1, &kw_args); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t pyb_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + pyb_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init); + +STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) }, + + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table); + +STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { + pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->uart_id == 1) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "UART(1) can't read")); + } + + // make sure we want at least 1 char + if (size == 0) { + return 0; + } + + // wait for first char to become available + if (!uart_rx_wait(self->timeout * 1000)) { + *errcode = MP_EAGAIN; + return MP_STREAM_ERROR; + } + + // read the data + uint8_t *buf = buf_in; + for (;;) { + *buf++ = uart_rx_char(); + if (--size == 0 || !uart_rx_wait(self->timeout_char * 1000)) { + // return number of bytes read + return buf - (uint8_t*)buf_in; + } + } +} + +STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { + pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + const byte *buf = buf_in; + + /* TODO implement non-blocking + // wait to be able to write the first character + if (!uart_tx_wait(self, timeout)) { + *errcode = EAGAIN; + return MP_STREAM_ERROR; + } + */ + + // write the data + for (size_t i = 0; i < size; ++i) { + uart_tx_one_char(self->uart_id, *buf++); + } + + // return number of bytes written + return size; +} + +STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; +} + +STATIC const mp_stream_p_t uart_stream_p = { + .read = pyb_uart_read, + .write = pyb_uart_write, + .ioctl = pyb_uart_ioctl, + .is_text = false, +}; + +const mp_obj_type_t pyb_uart_type = { + { &mp_type_type }, + .name = MP_QSTR_UART, + .print = pyb_uart_print, + .make_new = pyb_uart_make_new, + .getiter = mp_identity, + .iternext = mp_stream_unbuffered_iter, + .protocol = &uart_stream_p, + .locals_dict = (mp_obj_dict_t*)&pyb_uart_locals_dict, +}; diff --git a/esp8266/machine_wdt.c b/esp8266/machine_wdt.c new file mode 100644 index 000000000..6dc4c0d18 --- /dev/null +++ b/esp8266/machine_wdt.c @@ -0,0 +1,85 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Paul Sokolovsky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +//#include +#include + +#include "py/nlr.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "user_interface.h" +#include "etshal.h" + +const mp_obj_type_t esp_wdt_type; + +typedef struct _machine_wdt_obj_t { + mp_obj_base_t base; +} machine_wdt_obj_t; + +STATIC machine_wdt_obj_t wdt_default = {{&esp_wdt_type}}; + +STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + + mp_int_t id = 0; + if (n_args > 0) { + id = mp_obj_get_int(args[0]); + } + + switch (id) { + case 0: + return &wdt_default; + default: + mp_raise_ValueError(""); + } +} + +STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) { + (void)self_in; + system_soft_wdt_feed(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed); + +STATIC mp_obj_t machine_wdt_deinit(mp_obj_t self_in) { + (void)self_in; + ets_wdt_disable(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_deinit_obj, machine_wdt_deinit); + +STATIC const mp_map_elem_t machine_wdt_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_feed), (mp_obj_t)&machine_wdt_feed_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&machine_wdt_deinit_obj }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); + +const mp_obj_type_t esp_wdt_type = { + { &mp_type_type }, + .name = MP_QSTR_WDT, + .make_new = machine_wdt_make_new, + .locals_dict = (mp_obj_t)&machine_wdt_locals_dict, +}; diff --git a/esp8266/modesp.c b/esp8266/modesp.c index 827907d42..207422b67 100644 --- a/esp8266/modesp.c +++ b/esp8266/modesp.c @@ -45,8 +45,7 @@ #include "mem.h" #include "espneopixel.h" #include "espapa102.h" -#include "modpyb.h" -#include "modpybrtc.h" +#include "modmachine.h" #define MODESP_ESPCONN (0) diff --git a/esp8266/modmachine.c b/esp8266/modmachine.c index 0ab3c122b..29a72f7e4 100644 --- a/esp8266/modmachine.c +++ b/esp8266/modmachine.c @@ -33,8 +33,7 @@ #include "extmod/machine_mem.h" #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" -#include "modpyb.h" -#include "modpybrtc.h" +#include "modmachine.h" #include "xtirq.h" #include "os_type.h" diff --git a/esp8266/modmachine.h b/esp8266/modmachine.h new file mode 100644 index 000000000..df7953ecb --- /dev/null +++ b/esp8266/modmachine.h @@ -0,0 +1,43 @@ +#ifndef __MICROPY_INCLUDED_ESP8266_MODPYB_H__ +#define __MICROPY_INCLUDED_ESP8266_MODPYB_H__ + +#include "py/obj.h" + +extern const mp_obj_type_t pyb_pin_type; +extern const mp_obj_type_t pyb_pwm_type; +extern const mp_obj_type_t pyb_adc_type; +extern const mp_obj_type_t pyb_rtc_type; +extern const mp_obj_type_t pyb_uart_type; +extern const mp_obj_type_t pyb_i2c_type; +extern const mp_obj_type_t pyb_spi_type; +extern const mp_obj_type_t pyb_hspi_type; +extern const mp_obj_type_t machine_spi_type; + +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj); + +typedef struct _pyb_pin_obj_t { + mp_obj_base_t base; + uint16_t phys_port; + uint16_t func; + uint32_t periph; +} pyb_pin_obj_t; + +const pyb_pin_obj_t pyb_pin_obj[16 + 1]; + +void pin_init0(void); +void pin_intr_handler_iram(void *arg); +void pin_intr_handler(uint32_t); + +uint mp_obj_get_pin(mp_obj_t pin_in); +pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in); +int pin_get(uint pin); +void pin_set(uint pin, int value); + +extern uint32_t pyb_rtc_alarm0_wake; +extern uint64_t pyb_rtc_alarm0_expiry; + +void pyb_rtc_set_us_since_2000(uint64_t nowus); +uint64_t pyb_rtc_get_us_since_2000(); +void rtc_prepare_deepsleep(uint64_t sleep_us); + +#endif // __MICROPY_INCLUDED_ESP8266_MODPYB_H__ diff --git a/esp8266/modmachinewdt.c b/esp8266/modmachinewdt.c deleted file mode 100644 index 6dc4c0d18..000000000 --- a/esp8266/modmachinewdt.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Paul Sokolovsky - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -//#include -#include - -#include "py/nlr.h" -#include "py/obj.h" -#include "py/runtime.h" -#include "user_interface.h" -#include "etshal.h" - -const mp_obj_type_t esp_wdt_type; - -typedef struct _machine_wdt_obj_t { - mp_obj_base_t base; -} machine_wdt_obj_t; - -STATIC machine_wdt_obj_t wdt_default = {{&esp_wdt_type}}; - -STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - - mp_int_t id = 0; - if (n_args > 0) { - id = mp_obj_get_int(args[0]); - } - - switch (id) { - case 0: - return &wdt_default; - default: - mp_raise_ValueError(""); - } -} - -STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) { - (void)self_in; - system_soft_wdt_feed(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed); - -STATIC mp_obj_t machine_wdt_deinit(mp_obj_t self_in) { - (void)self_in; - ets_wdt_disable(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_deinit_obj, machine_wdt_deinit); - -STATIC const mp_map_elem_t machine_wdt_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR_feed), (mp_obj_t)&machine_wdt_feed_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&machine_wdt_deinit_obj }, -}; -STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); - -const mp_obj_type_t esp_wdt_type = { - { &mp_type_type }, - .name = MP_QSTR_WDT, - .make_new = machine_wdt_make_new, - .locals_dict = (mp_obj_t)&machine_wdt_locals_dict, -}; diff --git a/esp8266/modonewire.c b/esp8266/modonewire.c index 0d8958cee..1bf772240 100644 --- a/esp8266/modonewire.c +++ b/esp8266/modonewire.c @@ -29,7 +29,7 @@ #include "py/obj.h" #include "py/mphal.h" -#include "modpyb.h" +#include "modmachine.h" #include "esponewire.h" STATIC mp_obj_t onewire_timings(mp_obj_t timings_in) { diff --git a/esp8266/modpyb.c b/esp8266/modpyb.c index ba53e71b3..9fe8039bc 100644 --- a/esp8266/modpyb.c +++ b/esp8266/modpyb.c @@ -28,12 +28,12 @@ #include "py/gc.h" #include "gccollect.h" -#include "modpyb.h" +#include "modmachine.h" // The pyb module no longer exists since all functionality now appears // elsewhere, in more standard places (eg time, machine modules). The // only remaining function is pyb.info() which has been moved to the -// esp module, pending deletion/renaming/moving elsewher. +// esp module, pending deletion/renaming/moving elsewhere. STATIC mp_obj_t pyb_info(mp_uint_t n_args, const mp_obj_t *args) { // print info about memory diff --git a/esp8266/modpyb.h b/esp8266/modpyb.h deleted file mode 100644 index c23a119e8..000000000 --- a/esp8266/modpyb.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __MICROPY_INCLUDED_ESP8266_MODPYB_H__ -#define __MICROPY_INCLUDED_ESP8266_MODPYB_H__ - -#include "py/obj.h" - -extern const mp_obj_type_t pyb_pin_type; -extern const mp_obj_type_t pyb_pwm_type; -extern const mp_obj_type_t pyb_adc_type; -extern const mp_obj_type_t pyb_rtc_type; -extern const mp_obj_type_t pyb_uart_type; -extern const mp_obj_type_t pyb_i2c_type; -extern const mp_obj_type_t pyb_spi_type; -extern const mp_obj_type_t pyb_hspi_type; -extern const mp_obj_type_t machine_spi_type; - -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj); - -typedef struct _pyb_pin_obj_t { - mp_obj_base_t base; - uint16_t phys_port; - uint16_t func; - uint32_t periph; -} pyb_pin_obj_t; - -const pyb_pin_obj_t pyb_pin_obj[16 + 1]; - -void pin_init0(void); -void pin_intr_handler_iram(void *arg); -void pin_intr_handler(uint32_t); - -uint mp_obj_get_pin(mp_obj_t pin_in); -pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in); -int pin_get(uint pin); -void pin_set(uint pin, int value); - -#endif // __MICROPY_INCLUDED_ESP8266_MODPYB_H__ diff --git a/esp8266/modpybadc.c b/esp8266/modpybadc.c deleted file mode 100644 index 26b28c50b..000000000 --- a/esp8266/modpybadc.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Josef Gajdusek - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "py/nlr.h" -#include "py/obj.h" -#include "py/runtime.h" -#include "user_interface.h" - -const mp_obj_type_t pyb_adc_type; - -typedef struct _pyb_adc_obj_t { - mp_obj_base_t base; - bool isvdd; -} pyb_adc_obj_t; - -STATIC pyb_adc_obj_t pyb_adc_vdd3 = {{&pyb_adc_type}, true}; -STATIC pyb_adc_obj_t pyb_adc_adc = {{&pyb_adc_type}, false}; - -STATIC mp_obj_t pyb_adc_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, - const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 1, 1, false); - - mp_int_t chn = mp_obj_get_int(args[0]); - - switch (chn) { - case 0: - return &pyb_adc_adc; - case 1: - return &pyb_adc_vdd3; - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - "not a valid ADC Channel: %d", chn)); - } -} - -STATIC mp_obj_t pyb_adc_read(mp_obj_t self_in) { - pyb_adc_obj_t *adc = self_in; - - if (adc->isvdd) { - return mp_obj_new_int(system_get_vdd33()); - } else { - return mp_obj_new_int(system_adc_read()); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_adc_read_obj, pyb_adc_read); - -STATIC const mp_map_elem_t pyb_adc_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&pyb_adc_read_obj } -}; -STATIC MP_DEFINE_CONST_DICT(pyb_adc_locals_dict, pyb_adc_locals_dict_table); - -const mp_obj_type_t pyb_adc_type = { - { &mp_type_type }, - .name = MP_QSTR_ADC, - .make_new = pyb_adc_make_new, - .locals_dict = (mp_obj_t)&pyb_adc_locals_dict, -}; diff --git a/esp8266/modpybhspi.c b/esp8266/modpybhspi.c deleted file mode 100644 index 10a090269..000000000 --- a/esp8266/modpybhspi.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "ets_sys.h" -#include "etshal.h" -#include "ets_alt_task.h" - -#include "py/runtime.h" -#include "py/stream.h" -#include "py/mphal.h" -#include "extmod/machine_spi.h" - -#include "hspi.h" - -mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, - size_t n_kw, const mp_obj_t *args); - -typedef struct _pyb_hspi_obj_t { - mp_obj_base_t base; - uint32_t baudrate; - uint8_t polarity; - uint8_t phase; -} pyb_hspi_obj_t; - - -STATIC void hspi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { - (void)self_in; - - if (dest == NULL) { - // fast case when we only need to write data - size_t chunk_size = 1024; - size_t count = len / chunk_size; - size_t i = 0; - for (size_t j = 0; j < count; ++j) { - for (size_t k = 0; k < chunk_size; ++k) { - spi_tx8fast(HSPI, src[i]); - ++i; - } - ets_loop_iter(); - } - while (i < len) { - spi_tx8fast(HSPI, src[i]); - ++i; - } - } else { - // we need to read and write data - - // Process data in chunks, let the pending tasks run in between - size_t chunk_size = 1024; // TODO this should depend on baudrate - size_t count = len / chunk_size; - size_t i = 0; - for (size_t j = 0; j < count; ++j) { - for (size_t k = 0; k < chunk_size; ++k) { - dest[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, src[i], 8, 0); - ++i; - } - ets_loop_iter(); - } - while (i < len) { - dest[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, src[i], 8, 0); - ++i; - } - } -} - -/******************************************************************************/ -// MicroPython bindings for HSPI - -STATIC void pyb_hspi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - pyb_hspi_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "HSPI(id=1, baudrate=%u, polarity=%u, phase=%u)", - self->baudrate, self->polarity, self->phase); -} - -STATIC void pyb_hspi_init_helper(pyb_hspi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_id, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), - allowed_args, args); - - if (args[ARG_baudrate].u_int != -1) { - self->baudrate = args[ARG_baudrate].u_int; - } - if (args[ARG_polarity].u_int != -1) { - self->polarity = args[ARG_polarity].u_int; - } - if (args[ARG_phase].u_int != -1) { - self->phase = args[ARG_phase].u_int; - } - if (self->baudrate == 80000000L) { - // Special case for full speed. - spi_init_gpio(HSPI, SPI_CLK_80MHZ_NODIV); - spi_clock(HSPI, 0, 0); - } else if (self->baudrate > 40000000L) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "impossible baudrate")); - } else { - uint32_t divider = 40000000L / self->baudrate; - uint16_t prediv = MIN(divider, SPI_CLKDIV_PRE + 1); - uint16_t cntdiv = (divider / prediv) * 2; // cntdiv has to be even - if (cntdiv > SPI_CLKCNT_N + 1 || cntdiv == 0 || prediv == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "impossible baudrate")); - } - self->baudrate = 80000000L / (prediv * cntdiv); - spi_init_gpio(HSPI, SPI_CLK_USE_DIV); - spi_clock(HSPI, prediv, cntdiv); - } - // TODO: Make the byte order configurable too (discuss param names) - spi_tx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW); - spi_rx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW); - CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE | SPI_USR_MISO | - SPI_USR_ADDR | SPI_USR_COMMAND | SPI_USR_DUMMY); - // Clear Dual or Quad lines transmission mode - CLEAR_PERI_REG_MASK(SPI_CTRL(HSPI), SPI_QIO_MODE | SPI_DIO_MODE | - SPI_DOUT_MODE | SPI_QOUT_MODE); - spi_mode(HSPI, self->phase, self->polarity); -} - -mp_obj_t pyb_hspi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, true); - mp_int_t id = -1; - if (n_args > 0) { - id = mp_obj_get_int(args[0]); - } - - if (id == -1) { - // Multiplex to bitbanging SPI - if (n_args > 0) { - args++; - } - return pyb_spi_make_new(type, 0, n_kw, args); - } - - if (id != 1) { - // FlashROM is on SPI0, so far we don't support its usage - mp_raise_ValueError(""); - } - - pyb_hspi_obj_t *self = m_new_obj(pyb_hspi_obj_t); - self->base.type = &pyb_hspi_type; - // set defaults - self->baudrate = 80000000L; - self->polarity = 0; - self->phase = 0; - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - pyb_hspi_init_helper(self, n_args, args, &kw_args); - return MP_OBJ_FROM_PTR(self); -} - -STATIC mp_obj_t pyb_hspi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - pyb_hspi_init_helper(args[0], n_args - 1, args + 1, kw_args); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(pyb_hspi_init_obj, 1, pyb_hspi_init); - -STATIC const mp_rom_map_elem_t pyb_hspi_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_hspi_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(pyb_hspi_locals_dict, pyb_hspi_locals_dict_table); - -STATIC const mp_machine_spi_p_t pyb_hspi_p = { - .transfer = hspi_transfer, -}; - -const mp_obj_type_t pyb_hspi_type = { - { &mp_type_type }, - .name = MP_QSTR_HSPI, - .print = pyb_hspi_print, - .make_new = pyb_hspi_make_new, - .protocol = &pyb_hspi_p, - .locals_dict = (mp_obj_dict_t*)&pyb_hspi_locals_dict, -}; diff --git a/esp8266/modpybpin.c b/esp8266/modpybpin.c deleted file mode 100644 index 8916da64f..000000000 --- a/esp8266/modpybpin.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014, 2015 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "etshal.h" -#include "c_types.h" -#include "user_interface.h" -#include "gpio.h" - -#include "py/nlr.h" -#include "py/runtime.h" -#include "py/gc.h" -#include "py/mphal.h" -#include "modpyb.h" - -#define GET_TRIGGER(phys_port) \ - GPIO_PIN_INT_TYPE_GET(GPIO_REG_READ(GPIO_PIN_ADDR(phys_port))) -#define SET_TRIGGER(phys_port, trig) \ - (GPIO_REG_WRITE(GPIO_PIN_ADDR(phys_port), \ - (GPIO_REG_READ(GPIO_PIN_ADDR(phys_port)) & ~GPIO_PIN_INT_TYPE_MASK) \ - | GPIO_PIN_INT_TYPE_SET(trig))) \ - -#define GPIO_MODE_INPUT (0) -#define GPIO_MODE_OUTPUT (1) -#define GPIO_MODE_OPEN_DRAIN (2) // synthesised -#define GPIO_PULL_NONE (0) -#define GPIO_PULL_UP (1) -// Removed in SDK 1.1.0 -//#define GPIO_PULL_DOWN (2) - -typedef struct _pin_irq_obj_t { - mp_obj_base_t base; - uint16_t phys_port; -} pin_irq_obj_t; - -const pyb_pin_obj_t pyb_pin_obj[16 + 1] = { - {{&pyb_pin_type}, 0, FUNC_GPIO0, PERIPHS_IO_MUX_GPIO0_U}, - {{&pyb_pin_type}, 1, FUNC_GPIO1, PERIPHS_IO_MUX_U0TXD_U}, - {{&pyb_pin_type}, 2, FUNC_GPIO2, PERIPHS_IO_MUX_GPIO2_U}, - {{&pyb_pin_type}, 3, FUNC_GPIO3, PERIPHS_IO_MUX_U0RXD_U}, - {{&pyb_pin_type}, 4, FUNC_GPIO4, PERIPHS_IO_MUX_GPIO4_U}, - {{&pyb_pin_type}, 5, FUNC_GPIO5, PERIPHS_IO_MUX_GPIO5_U}, - {{NULL}, 0, 0, 0}, - {{NULL}, 0, 0, 0}, - {{NULL}, 0, 0, 0}, - {{&pyb_pin_type}, 9, FUNC_GPIO9, PERIPHS_IO_MUX_SD_DATA2_U}, - {{&pyb_pin_type}, 10, FUNC_GPIO10, PERIPHS_IO_MUX_SD_DATA3_U}, - {{NULL}, 0, 0, 0}, - {{&pyb_pin_type}, 12, FUNC_GPIO12, PERIPHS_IO_MUX_MTDI_U}, - {{&pyb_pin_type}, 13, FUNC_GPIO13, PERIPHS_IO_MUX_MTCK_U}, - {{&pyb_pin_type}, 14, FUNC_GPIO14, PERIPHS_IO_MUX_MTMS_U}, - {{&pyb_pin_type}, 15, FUNC_GPIO15, PERIPHS_IO_MUX_MTDO_U}, - // GPIO16 is special, belongs to different register set, and - // otherwise handled specially. - {{&pyb_pin_type}, 16, -1, -1}, -}; - -STATIC uint8_t pin_mode[16 + 1]; - -// forward declaration -STATIC const pin_irq_obj_t pin_irq_obj[16]; - -void pin_init0(void) { - ETS_GPIO_INTR_DISABLE(); - ETS_GPIO_INTR_ATTACH(pin_intr_handler_iram, NULL); - // disable all interrupts - memset(&MP_STATE_PORT(pin_irq_handler)[0], 0, 16 * sizeof(mp_obj_t)); - for (int p = 0; p < 16; ++p) { - GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << p); - SET_TRIGGER(p, 0); - } - ETS_GPIO_INTR_ENABLE(); -} - -void pin_intr_handler(uint32_t status) { - gc_lock(); - status &= 0xffff; - for (int p = 0; status; ++p, status >>= 1) { - if (status & 1) { - mp_obj_t handler = MP_STATE_PORT(pin_irq_handler)[p]; - if (handler != MP_OBJ_NULL) { - mp_call_function_1_protected(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p])); - } - } - } - gc_unlock(); -} - -pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in) { - if (mp_obj_get_type(pin_in) != &pyb_pin_type) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "expecting a pin")); - } - pyb_pin_obj_t *self = pin_in; - return self; -} - -uint mp_obj_get_pin(mp_obj_t pin_in) { - return mp_obj_get_pin_obj(pin_in)->phys_port; -} - -void mp_hal_pin_input(mp_hal_pin_obj_t pin_id) { - pin_mode[pin_id] = GPIO_MODE_INPUT; - if (pin_id == 16) { - WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); - WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); - WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); // input - } else { - const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id]; - PIN_FUNC_SELECT(self->periph, self->func); - PIN_PULLUP_DIS(self->periph); - gpio_output_set(0, 0, 0, 1 << self->phys_port); - } -} - -void mp_hal_pin_output(mp_hal_pin_obj_t pin_id) { - pin_mode[pin_id] = GPIO_MODE_OUTPUT; - if (pin_id == 16) { - WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); - WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); - WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); // output - } else { - const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id]; - PIN_FUNC_SELECT(self->periph, self->func); - PIN_PULLUP_DIS(self->periph); - gpio_output_set(0, 0, 1 << self->phys_port, 0); - } -} - -int pin_get(uint pin) { - if (pin == 16) { - return READ_PERI_REG(RTC_GPIO_IN_DATA) & 1; - } - return GPIO_INPUT_GET(pin); -} - -void pin_set(uint pin, int value) { - if (pin == 16) { - int out_en = (pin_mode[pin] == GPIO_MODE_OUTPUT); - WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); - WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); - WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | out_en); - WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & ~1) | value); - return; - } - - uint32_t enable = 0; - uint32_t disable = 0; - switch (pin_mode[pin]) { - case GPIO_MODE_INPUT: - value = -1; - disable = 1; - break; - - case GPIO_MODE_OUTPUT: - enable = 1; - break; - - case GPIO_MODE_OPEN_DRAIN: - if (value == -1) { - return; - } else if (value == 0) { - enable = 1; - } else { - value = -1; - disable = 1; - } - break; - } - - enable <<= pin; - disable <<= pin; - if (value == -1) { - gpio_output_set(0, 0, enable, disable); - } else { - gpio_output_set(value << pin, (1 - value) << pin, enable, disable); - } -} - -STATIC void pyb_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - pyb_pin_obj_t *self = self_in; - - // pin name - mp_printf(print, "Pin(%u)", self->phys_port); -} - -// pin.init(mode, pull=None, *, value) -STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_pull, ARG_value }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}}, - { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - }; - - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - // get io mode - uint mode = args[ARG_mode].u_int; - - // get pull mode - uint pull = GPIO_PULL_NONE; - if (args[ARG_pull].u_obj != mp_const_none) { - pull = mp_obj_get_int(args[ARG_pull].u_obj); - } - - // get initial value - int value; - if (args[ARG_value].u_obj == MP_OBJ_NULL) { - value = -1; - } else { - value = mp_obj_is_true(args[ARG_value].u_obj); - } - - // save the mode - pin_mode[self->phys_port] = mode; - - // configure the GPIO as requested - if (self->phys_port == 16) { - // only pull-down seems to be supported by the hardware, and - // we only expose pull-up behaviour in software - if (pull != GPIO_PULL_NONE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin(16) doesn't support pull")); - } - } else { - PIN_FUNC_SELECT(self->periph, self->func); - #if 0 - // Removed in SDK 1.1.0 - if ((pull & GPIO_PULL_DOWN) == 0) { - PIN_PULLDWN_DIS(self->periph); - } - #endif - if ((pull & GPIO_PULL_UP) == 0) { - PIN_PULLUP_DIS(self->periph); - } - #if 0 - if ((pull & GPIO_PULL_DOWN) != 0) { - PIN_PULLDWN_EN(self->periph); - } - #endif - if ((pull & GPIO_PULL_UP) != 0) { - PIN_PULLUP_EN(self->periph); - } - } - - pin_set(self->phys_port, value); - - return mp_const_none; -} - -// constructor(id, ...) -STATIC mp_obj_t pyb_pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - - // get the wanted pin object - int wanted_pin = mp_obj_get_int(args[0]); - pyb_pin_obj_t *pin = NULL; - if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(pyb_pin_obj)) { - pin = (pyb_pin_obj_t*)&pyb_pin_obj[wanted_pin]; - } - if (pin == NULL || pin->base.type == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin")); - } - - if (n_args > 1 || n_kw > 0) { - // pin mode given, so configure this GPIO - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - pyb_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args); - } - - return (mp_obj_t)pin; -} - -// fast method for getting/setting pin value -STATIC mp_obj_t pyb_pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - pyb_pin_obj_t *self = self_in; - if (n_args == 0) { - // get pin - return MP_OBJ_NEW_SMALL_INT(pin_get(self->phys_port)); - } else { - // set pin - pin_set(self->phys_port, mp_obj_is_true(args[0])); - return mp_const_none; - } -} - -// pin.init(mode, pull) -STATIC mp_obj_t pyb_pin_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - return pyb_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); -} -MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pin_init_obj, 1, pyb_pin_obj_init); - -// pin.value([value]) -STATIC mp_obj_t pyb_pin_value(mp_uint_t n_args, const mp_obj_t *args) { - return pyb_pin_call(args[0], n_args - 1, 0, args + 1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pin_value_obj, 1, 2, pyb_pin_value); - -// pin.low() -STATIC mp_obj_t pyb_pin_low(mp_obj_t self_in) { - pyb_pin_obj_t *self = self_in; - pin_set(self->phys_port, 0); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_low_obj, pyb_pin_low); - -// pin.high() -STATIC mp_obj_t pyb_pin_high(mp_obj_t self_in) { - pyb_pin_obj_t *self = self_in; - pin_set(self->phys_port, 1); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_high_obj, pyb_pin_high); - -// pin.irq(*, trigger, handler=None) -STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_trigger, ARG_handler }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - pyb_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - if (self->phys_port >= 16) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "pin does not have IRQ capabilities")); - } - - if (args[ARG_trigger].u_int != 0) { - // configure irq - mp_obj_t handler = args[ARG_handler].u_obj; - if (handler == mp_const_none) { - handler = MP_OBJ_NULL; - } - ETS_GPIO_INTR_DISABLE(); - MP_STATE_PORT(pin_irq_handler)[self->phys_port] = handler; - SET_TRIGGER(self->phys_port, args[ARG_trigger].u_int); - GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << self->phys_port); - ETS_GPIO_INTR_ENABLE(); - } - - // return the irq object - return MP_OBJ_FROM_PTR(&pin_irq_obj[self->phys_port]); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pin_irq_obj, 1, pyb_pin_irq); - -STATIC const mp_map_elem_t pyb_pin_locals_dict_table[] = { - // instance methods - { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_pin_init_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&pyb_pin_value_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pyb_pin_low_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pyb_pin_high_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_pin_irq_obj }, - - // class constants - { MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_INPUT) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OPEN_DRAIN) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_UP) }, - //{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_DOWN) }, - - // IRG triggers, can be or'd together - { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING), MP_OBJ_NEW_SMALL_INT(GPIO_PIN_INTR_POSEDGE) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_PIN_INTR_NEGEDGE) }, -}; - -STATIC MP_DEFINE_CONST_DICT(pyb_pin_locals_dict, pyb_pin_locals_dict_table); - -const mp_obj_type_t pyb_pin_type = { - { &mp_type_type }, - .name = MP_QSTR_Pin, - .print = pyb_pin_print, - .make_new = pyb_pin_make_new, - .call = pyb_pin_call, - .locals_dict = (mp_obj_t)&pyb_pin_locals_dict, -}; - -/******************************************************************************/ -// Pin IRQ object - -STATIC const mp_obj_type_t pin_irq_type; - -STATIC const pin_irq_obj_t pin_irq_obj[16] = { - {{&pin_irq_type}, 0}, - {{&pin_irq_type}, 1}, - {{&pin_irq_type}, 2}, - {{&pin_irq_type}, 3}, - {{&pin_irq_type}, 4}, - {{&pin_irq_type}, 5}, - {{&pin_irq_type}, 6}, - {{&pin_irq_type}, 7}, - {{&pin_irq_type}, 8}, - {{&pin_irq_type}, 9}, - {{&pin_irq_type}, 10}, - {{&pin_irq_type}, 11}, - {{&pin_irq_type}, 12}, - {{&pin_irq_type}, 13}, - {{&pin_irq_type}, 14}, - {{&pin_irq_type}, 15}, -}; - -STATIC mp_obj_t pin_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - pin_irq_obj_t *self = self_in; - mp_arg_check_num(n_args, n_kw, 0, 0, false); - pin_intr_handler(1 << self->phys_port); - return mp_const_none; -} - -STATIC mp_obj_t pin_irq_trigger(size_t n_args, const mp_obj_t *args) { - pin_irq_obj_t *self = args[0]; - uint32_t orig_trig = GET_TRIGGER(self->phys_port); - if (n_args == 2) { - // set trigger - SET_TRIGGER(self->phys_port, mp_obj_get_int(args[1])); - } - // return original trigger value - return MP_OBJ_NEW_SMALL_INT(orig_trig); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_irq_trigger_obj, 1, 2, pin_irq_trigger); - -STATIC const mp_rom_map_elem_t pin_irq_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&pin_irq_trigger_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(pin_irq_locals_dict, pin_irq_locals_dict_table); - -STATIC const mp_obj_type_t pin_irq_type = { - { &mp_type_type }, - .name = MP_QSTR_IRQ, - .call = pin_irq_call, - .locals_dict = (mp_obj_dict_t*)&pin_irq_locals_dict, -}; diff --git a/esp8266/modpybpwm.c b/esp8266/modpybpwm.c deleted file mode 100644 index 871e4c3dd..000000000 --- a/esp8266/modpybpwm.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "esppwm.h" - -#include "py/nlr.h" -#include "py/runtime.h" -#include "modpyb.h" - -typedef struct _pyb_pwm_obj_t { - mp_obj_base_t base; - pyb_pin_obj_t *pin; - uint8_t active; - uint8_t channel; -} pyb_pwm_obj_t; - -STATIC bool pwm_inited = false; - -/******************************************************************************/ -// MicroPython bindings for PWM - -STATIC void pyb_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "PWM(%u", self->pin->phys_port); - if (self->active) { - mp_printf(print, ", freq=%u, duty=%u", - pwm_get_freq(self->channel), pwm_get_duty(self->channel)); - } - mp_printf(print, ")"); -} - -STATIC void pyb_pwm_init_helper(pyb_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_freq, ARG_duty }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_duty, MP_ARG_INT, {.u_int = -1} }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - int channel = pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func); - if (channel == -1) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - "PWM not supported on pin %d", self->pin->phys_port)); - } - - self->channel = channel; - self->active = 1; - if (args[ARG_freq].u_int != -1) { - pwm_set_freq(args[ARG_freq].u_int, self->channel); - } - if (args[ARG_duty].u_int != -1) { - pwm_set_duty(args[ARG_duty].u_int, self->channel); - } - - pwm_start(); -} - -STATIC mp_obj_t pyb_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - pyb_pin_obj_t *pin = mp_obj_get_pin_obj(args[0]); - - // create PWM object from the given pin - pyb_pwm_obj_t *self = m_new_obj(pyb_pwm_obj_t); - self->base.type = &pyb_pwm_type; - self->pin = pin; - self->active = 0; - self->channel = -1; - - // start the PWM subsystem if it's not already running - if (!pwm_inited) { - pwm_init(); - pwm_inited = true; - } - - // start the PWM running for this channel - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - pyb_pwm_init_helper(self, n_args - 1, args + 1, &kw_args); - - return MP_OBJ_FROM_PTR(self); -} - -STATIC mp_obj_t pyb_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - pyb_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pwm_init_obj, 1, pyb_pwm_init); - -STATIC mp_obj_t pyb_pwm_deinit(mp_obj_t self_in) { - pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); - pwm_delete(self->channel); - self->active = 0; - pwm_start(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pwm_deinit_obj, pyb_pwm_deinit); - -STATIC mp_obj_t pyb_pwm_freq(size_t n_args, const mp_obj_t *args) { - //pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (n_args == 1) { - // get - return MP_OBJ_NEW_SMALL_INT(pwm_get_freq(0)); - } else { - // set - pwm_set_freq(mp_obj_get_int(args[1]), 0); - pwm_start(); - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pwm_freq_obj, 1, 2, pyb_pwm_freq); - -STATIC mp_obj_t pyb_pwm_duty(size_t n_args, const mp_obj_t *args) { - pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (!self->active) { - pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func); - self->active = 1; - } - if (n_args == 1) { - // get - return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel)); - } else { - // set - pwm_set_duty(mp_obj_get_int(args[1]), self->channel); - pwm_start(); - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pwm_duty_obj, 1, 2, pyb_pwm_duty); - -STATIC const mp_rom_map_elem_t pyb_pwm_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_pwm_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_pwm_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_pwm_freq_obj) }, - { MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&pyb_pwm_duty_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(pyb_pwm_locals_dict, pyb_pwm_locals_dict_table); - -const mp_obj_type_t pyb_pwm_type = { - { &mp_type_type }, - .name = MP_QSTR_PWM, - .print = pyb_pwm_print, - .make_new = pyb_pwm_make_new, - .locals_dict = (mp_obj_dict_t*)&pyb_pwm_locals_dict, -}; diff --git a/esp8266/modpybrtc.c b/esp8266/modpybrtc.c deleted file mode 100644 index d69fc47a8..000000000 --- a/esp8266/modpybrtc.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Josef Gajdusek - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "py/nlr.h" -#include "py/obj.h" -#include "py/runtime.h" -#include "timeutils.h" -#include "user_interface.h" -#include "modpyb.h" - -typedef struct _pyb_rtc_obj_t { - mp_obj_base_t base; -} pyb_rtc_obj_t; - -#define MEM_MAGIC 0x75507921 -#define MEM_DELTA_ADDR 64 -#define MEM_CAL_ADDR (MEM_DELTA_ADDR + 2) -#define MEM_USER_MAGIC_ADDR (MEM_CAL_ADDR + 1) -#define MEM_USER_LEN_ADDR (MEM_USER_MAGIC_ADDR + 1) -#define MEM_USER_DATA_ADDR (MEM_USER_LEN_ADDR + 1) -#define MEM_USER_MAXLEN (512 - (MEM_USER_DATA_ADDR - MEM_DELTA_ADDR) * 4) - -// singleton RTC object -STATIC const pyb_rtc_obj_t pyb_rtc_obj = {{&pyb_rtc_type}}; - -// ALARM0 state -uint32_t pyb_rtc_alarm0_wake; // see MACHINE_WAKE_xxx constants -uint64_t pyb_rtc_alarm0_expiry; // in microseconds - -// RTC overflow checking -STATIC uint32_t rtc_last_ticks; - -void mp_hal_rtc_init(void) { - uint32_t magic; - - system_rtc_mem_read(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic)); - if (magic != MEM_MAGIC) { - magic = MEM_MAGIC; - system_rtc_mem_write(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic)); - uint32_t cal = system_rtc_clock_cali_proc(); - int64_t delta = 0; - system_rtc_mem_write(MEM_CAL_ADDR, &cal, sizeof(cal)); - system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); - uint32_t len = 0; - system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len)); - } - // system_get_rtc_time() is always 0 after reset/deepsleep - rtc_last_ticks = system_get_rtc_time(); - - // reset ALARM0 state - pyb_rtc_alarm0_wake = 0; - pyb_rtc_alarm0_expiry = 0; -} - -STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); - - // return constant object - return (mp_obj_t)&pyb_rtc_obj; -} - -void pyb_rtc_set_us_since_2000(uint64_t nowus) { - uint32_t cal = system_rtc_clock_cali_proc(); - // Save RTC ticks for overflow detection. - rtc_last_ticks = system_get_rtc_time(); - int64_t delta = nowus - (((uint64_t)rtc_last_ticks * cal) >> 12); - - // As the calibration value jitters quite a bit, to make the - // clock at least somewhat practially usable, we need to store it - system_rtc_mem_write(MEM_CAL_ADDR, &cal, sizeof(cal)); - system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); -}; - -uint64_t pyb_rtc_get_us_since_2000() { - uint32_t cal; - int64_t delta; - uint32_t rtc_ticks; - - system_rtc_mem_read(MEM_CAL_ADDR, &cal, sizeof(cal)); - system_rtc_mem_read(MEM_DELTA_ADDR, &delta, sizeof(delta)); - - // ESP-SDK system_get_rtc_time() only returns uint32 and therefore - // overflow about every 7:45h. Thus, we have to check for - // overflow and handle it. - rtc_ticks = system_get_rtc_time(); - if (rtc_ticks < rtc_last_ticks) { - // Adjust delta because of RTC overflow. - delta += (uint64_t)cal << 20; - system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); - } - rtc_last_ticks = rtc_ticks; - - return (((uint64_t)rtc_ticks * cal) >> 12) + delta; -}; - -void rtc_prepare_deepsleep(uint64_t sleep_us) { - // RTC time will reset at wake up. Let's be preared for this. - int64_t delta = pyb_rtc_get_us_since_2000() + sleep_us; - system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); -} - -STATIC mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) { - if (n_args == 1) { - // Get time - uint64_t msecs = pyb_rtc_get_us_since_2000() / 1000; - - timeutils_struct_time_t tm; - timeutils_seconds_since_2000_to_struct_time(msecs / 1000, &tm); - - mp_obj_t tuple[8] = { - mp_obj_new_int(tm.tm_year), - mp_obj_new_int(tm.tm_mon), - mp_obj_new_int(tm.tm_mday), - mp_obj_new_int(tm.tm_wday), - mp_obj_new_int(tm.tm_hour), - mp_obj_new_int(tm.tm_min), - mp_obj_new_int(tm.tm_sec), - mp_obj_new_int(msecs % 1000) - }; - - return mp_obj_new_tuple(8, tuple); - } else { - // Set time - mp_obj_t *items; - mp_obj_get_array_fixed_n(args[1], 8, &items); - - pyb_rtc_set_us_since_2000( - ((uint64_t)timeutils_seconds_since_2000( - mp_obj_get_int(items[0]), - mp_obj_get_int(items[1]), - mp_obj_get_int(items[2]), - mp_obj_get_int(items[4]), - mp_obj_get_int(items[5]), - mp_obj_get_int(items[6])) * 1000 + mp_obj_get_int(items[7])) * 1000); - - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime); - -STATIC mp_obj_t pyb_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) { - uint8_t rtcram[MEM_USER_MAXLEN]; - uint32_t len; - - if (n_args == 1) { - // read RTC memory - - system_rtc_mem_read(MEM_USER_LEN_ADDR, &len, sizeof(len)); - system_rtc_mem_read(MEM_USER_DATA_ADDR, rtcram, len + (4 - len % 4)); - - return mp_obj_new_bytes(rtcram, len); - } else { - // write RTC memory - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); - - if (bufinfo.len > MEM_USER_MAXLEN) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "buffer too long")); - } - - len = bufinfo.len; - system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len)); - - int i = 0; - for (; i < bufinfo.len; i++) { - rtcram[i] = ((uint8_t *)bufinfo.buf)[i]; - } - - system_rtc_mem_write(MEM_USER_DATA_ADDR, rtcram, len + (4 - len % 4)); - - return mp_const_none; - } - -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_memory_obj, 1, 2, pyb_rtc_memory); - -STATIC mp_obj_t pyb_rtc_alarm(mp_obj_t self_in, mp_obj_t alarm_id, mp_obj_t time_in) { - (void)self_in; // unused - - // check we want alarm0 - if (mp_obj_get_int(alarm_id) != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid alarm")); - } - - // set expiry time (in microseconds) - pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_2000() + (uint64_t)mp_obj_get_int(time_in) * 1000; - - return mp_const_none; - -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_rtc_alarm_obj, pyb_rtc_alarm); - -STATIC mp_obj_t pyb_rtc_alarm_left(size_t n_args, const mp_obj_t *args) { - // check we want alarm0 - if (n_args > 1 && mp_obj_get_int(args[1]) != 0) { - mp_raise_ValueError("invalid alarm"); - } - - uint64_t now = pyb_rtc_get_us_since_2000(); - if (pyb_rtc_alarm0_expiry <= now) { - return MP_OBJ_NEW_SMALL_INT(0); - } else { - return mp_obj_new_int((pyb_rtc_alarm0_expiry - now) / 1000); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_left_obj, 1, 2, pyb_rtc_alarm_left); - -STATIC mp_obj_t pyb_rtc_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_trigger, ARG_wake }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_wake, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - // check we want alarm0 - if (args[ARG_trigger].u_int != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid alarm")); - } - - // set the wake value - pyb_rtc_alarm0_wake = args[ARG_wake].u_int; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_irq_obj, 1, pyb_rtc_irq); - -STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR_datetime), (mp_obj_t)&pyb_rtc_datetime_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_memory), (mp_obj_t)&pyb_rtc_memory_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_alarm), (mp_obj_t)&pyb_rtc_alarm_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_alarm_left), (mp_obj_t)&pyb_rtc_alarm_left_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_rtc_irq_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ALARM0), MP_OBJ_NEW_SMALL_INT(0) }, -}; -STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table); - -const mp_obj_type_t pyb_rtc_type = { - { &mp_type_type }, - .name = MP_QSTR_RTC, - .make_new = pyb_rtc_make_new, - .locals_dict = (mp_obj_t)&pyb_rtc_locals_dict, -}; diff --git a/esp8266/modpybrtc.h b/esp8266/modpybrtc.h deleted file mode 100644 index 5b9d9fc76..000000000 --- a/esp8266/modpybrtc.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Josef Gajdusek - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -extern uint32_t pyb_rtc_alarm0_wake; -extern uint64_t pyb_rtc_alarm0_expiry; - -void pyb_rtc_set_us_since_2000(uint64_t nowus); - -uint64_t pyb_rtc_get_us_since_2000(); - -void rtc_prepare_deepsleep(uint64_t sleep_us); diff --git a/esp8266/modpybspi.c b/esp8266/modpybspi.c deleted file mode 100644 index e97454711..000000000 --- a/esp8266/modpybspi.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "py/runtime.h" -#include "py/stream.h" -#include "py/mphal.h" -#include "extmod/machine_spi.h" - -/******************************************************************************/ -// MicroPython bindings for SPI - -STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) { - return 500000 / delay_half; -} - -STATIC uint32_t baudrate_to_delay_half(uint32_t baudrate) { - uint32_t delay_half = 500000 / baudrate; - // round delay_half up so that: actual_baudrate <= requested_baudrate - if (500000 % baudrate != 0) { - delay_half += 1; - } - return delay_half; -} - -STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "SPI(baudrate=%u, polarity=%u, phase=%u, sck=%u, mosi=%u, miso=%u)", - baudrate_from_delay_half(self->delay_half), - self->polarity, self->phase, self->sck, self->mosi, self->miso); -} - -STATIC void pyb_spi_init_helper(mp_machine_soft_spi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_sck, ARG_mosi, ARG_miso }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - if (args[ARG_baudrate].u_int != -1) { - self->delay_half = baudrate_to_delay_half(args[ARG_baudrate].u_int); - } - if (args[ARG_polarity].u_int != -1) { - self->polarity = args[ARG_polarity].u_int; - } - if (args[ARG_phase].u_int != -1) { - self->phase = args[ARG_phase].u_int; - } - if (args[ARG_sck].u_obj != MP_OBJ_NULL) { - self->sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj); - } - if (args[ARG_mosi].u_obj != MP_OBJ_NULL) { - self->mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj); - } - if (args[ARG_miso].u_obj != MP_OBJ_NULL) { - self->miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj); - } - - // configure pins - mp_hal_pin_write(self->sck, self->polarity); - mp_hal_pin_output(self->sck); - mp_hal_pin_output(self->mosi); - mp_hal_pin_input(self->miso); -} - -mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); - mp_machine_soft_spi_obj_t *self = m_new_obj(mp_machine_soft_spi_obj_t); - self->base.type = &pyb_spi_type; - // set defaults - self->delay_half = baudrate_to_delay_half(500000); - self->polarity = 0; - self->phase = 0; - self->sck = 14; - self->mosi = 13; - self->miso = 12; - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - pyb_spi_init_helper(self, n_args, args, &kw_args); - return MP_OBJ_FROM_PTR(self); -} - -STATIC mp_obj_t pyb_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - pyb_spi_init_helper(args[0], n_args - 1, args + 1, kw_args); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init); - -STATIC const mp_rom_map_elem_t pyb_spi_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_spi_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table); - -STATIC const mp_machine_spi_p_t pyb_spi_p = { - .transfer = mp_machine_soft_spi_transfer, -}; - -const mp_obj_type_t pyb_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SoftSPI, - .print = pyb_spi_print, - .make_new = pyb_spi_make_new, - .protocol = &pyb_spi_p, - .locals_dict = (mp_obj_dict_t*)&pyb_spi_locals_dict, -}; diff --git a/esp8266/modpybuart.c b/esp8266/modpybuart.c deleted file mode 100644 index 25320fa1e..000000000 --- a/esp8266/modpybuart.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "ets_sys.h" -#include "uart.h" - -#include "py/runtime.h" -#include "py/stream.h" -#include "py/mperrno.h" -#include "modpyb.h" - -// UartDev is defined and initialized in rom code. -extern UartDevice UartDev; - -typedef struct _pyb_uart_obj_t { - mp_obj_base_t base; - uint8_t uart_id; - uint8_t bits; - uint8_t parity; - uint8_t stop; - uint32_t baudrate; - uint16_t timeout; // timeout waiting for first char (in ms) - uint16_t timeout_char; // timeout waiting between chars (in ms) -} pyb_uart_obj_t; - -STATIC const char *_parity_name[] = {"None", "1", "0"}; - -/******************************************************************************/ -// MicroPython bindings for UART - -STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, timeout=%u, timeout_char=%u)", - self->uart_id, self->baudrate, self->bits, _parity_name[self->parity], - self->stop, self->timeout, self->timeout_char); -} - -STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_timeout, ARG_timeout_char }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_stop, MP_ARG_INT, {.u_int = 0} }, - //{ MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - //{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - // set baudrate - if (args[ARG_baudrate].u_int > 0) { - self->baudrate = args[ARG_baudrate].u_int; - UartDev.baut_rate = self->baudrate; // Sic! - } - - // set data bits - switch (args[ARG_bits].u_int) { - case 0: - break; - case 5: - UartDev.data_bits = UART_FIVE_BITS; - self->bits = 5; - break; - case 6: - UartDev.data_bits = UART_SIX_BITS; - self->bits = 6; - break; - case 7: - UartDev.data_bits = UART_SEVEN_BITS; - self->bits = 7; - break; - case 8: - UartDev.data_bits = UART_EIGHT_BITS; - self->bits = 8; - break; - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid data bits")); - break; - } - - // set parity - if (args[ARG_parity].u_obj != MP_OBJ_NULL) { - if (args[ARG_parity].u_obj == mp_const_none) { - UartDev.parity = UART_NONE_BITS; - UartDev.exist_parity = UART_STICK_PARITY_DIS; - self->parity = 0; - } else { - mp_int_t parity = mp_obj_get_int(args[ARG_parity].u_obj); - UartDev.exist_parity = UART_STICK_PARITY_EN; - if (parity & 1) { - UartDev.parity = UART_ODD_BITS; - self->parity = 1; - } else { - UartDev.parity = UART_EVEN_BITS; - self->parity = 2; - } - } - } - - // set stop bits - switch (args[ARG_stop].u_int) { - case 0: - break; - case 1: - UartDev.stop_bits = UART_ONE_STOP_BIT; - self->stop = 1; - break; - case 2: - UartDev.stop_bits = UART_TWO_STOP_BIT; - self->stop = 2; - break; - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid stop bits")); - break; - } - - // set timeout - self->timeout = args[ARG_timeout].u_int; - - // set timeout_char - // make sure it is at least as long as a whole character (13 bits to be safe) - self->timeout_char = args[ARG_timeout_char].u_int; - uint32_t min_timeout_char = 13000 / self->baudrate + 1; - if (self->timeout_char < min_timeout_char) { - self->timeout_char = min_timeout_char; - } - - // setup - uart_setup(self->uart_id); -} - -STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - - // get uart id - mp_int_t uart_id = mp_obj_get_int(args[0]); - if (uart_id != 0 && uart_id != 1) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) does not exist", uart_id)); - } - - // create instance - pyb_uart_obj_t *self = m_new_obj(pyb_uart_obj_t); - self->base.type = &pyb_uart_type; - self->uart_id = uart_id; - self->baudrate = 115200; - self->bits = 8; - self->parity = 0; - self->stop = 1; - self->timeout = 0; - self->timeout_char = 0; - - // init the peripheral - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - pyb_uart_init_helper(self, n_args - 1, args + 1, &kw_args); - - return MP_OBJ_FROM_PTR(self); -} - -STATIC mp_obj_t pyb_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - pyb_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init); - -STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) }, - - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) }, - { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table); - -STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (self->uart_id == 1) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "UART(1) can't read")); - } - - // make sure we want at least 1 char - if (size == 0) { - return 0; - } - - // wait for first char to become available - if (!uart_rx_wait(self->timeout * 1000)) { - *errcode = MP_EAGAIN; - return MP_STREAM_ERROR; - } - - // read the data - uint8_t *buf = buf_in; - for (;;) { - *buf++ = uart_rx_char(); - if (--size == 0 || !uart_rx_wait(self->timeout_char * 1000)) { - // return number of bytes read - return buf - (uint8_t*)buf_in; - } - } -} - -STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { - pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - const byte *buf = buf_in; - - /* TODO implement non-blocking - // wait to be able to write the first character - if (!uart_tx_wait(self, timeout)) { - *errcode = EAGAIN; - return MP_STREAM_ERROR; - } - */ - - // write the data - for (size_t i = 0; i < size; ++i) { - uart_tx_one_char(self->uart_id, *buf++); - } - - // return number of bytes written - return size; -} - -STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { - *errcode = MP_EINVAL; - return MP_STREAM_ERROR; -} - -STATIC const mp_stream_p_t uart_stream_p = { - .read = pyb_uart_read, - .write = pyb_uart_write, - .ioctl = pyb_uart_ioctl, - .is_text = false, -}; - -const mp_obj_type_t pyb_uart_type = { - { &mp_type_type }, - .name = MP_QSTR_UART, - .print = pyb_uart_print, - .make_new = pyb_uart_make_new, - .getiter = mp_identity, - .iternext = mp_stream_unbuffered_iter, - .protocol = &uart_stream_p, - .locals_dict = (mp_obj_dict_t*)&pyb_uart_locals_dict, -}; diff --git a/esp8266/modutime.c b/esp8266/modutime.c index 1bd1c489d..2adb6c563 100644 --- a/esp8266/modutime.c +++ b/esp8266/modutime.c @@ -34,8 +34,7 @@ #include "py/runtime.h" #include "py/mphal.h" #include "py/smallint.h" -#include "modpyb.h" -#include "modpybrtc.h" +#include "modmachine.h" #include "timeutils.h" #include "user_interface.h" #include "extmod/utime_mphal.h" -- cgit v1.2.3