diff options
Diffstat (limited to 'esp8266')
-rw-r--r-- | esp8266/Makefile | 10 | ||||
-rw-r--r-- | esp8266/README.md | 28 | ||||
-rw-r--r-- | esp8266/esp_mphal.c | 15 | ||||
-rw-r--r-- | esp8266/esp_mphal.h | 13 | ||||
-rw-r--r-- | esp8266/espapa102.c | 110 | ||||
-rw-r--r-- | esp8266/espapa102.h | 27 | ||||
-rw-r--r-- | esp8266/ets_alt_task.c | 6 | ||||
-rw-r--r-- | esp8266/ets_alt_task.h | 1 | ||||
-rw-r--r-- | esp8266/help.c | 2 | ||||
-rw-r--r-- | esp8266/main.c | 4 | ||||
-rw-r--r-- | esp8266/modesp.c | 22 | ||||
-rw-r--r-- | esp8266/modmachine.c | 26 | ||||
-rw-r--r-- | esp8266/modnetwork.c | 47 | ||||
-rw-r--r-- | esp8266/modpybpin.c | 29 | ||||
-rw-r--r-- | esp8266/modpybrtc.c | 40 | ||||
-rw-r--r-- | esp8266/modpybspi.c | 7 | ||||
-rw-r--r-- | esp8266/modpybuart.c | 6 | ||||
-rw-r--r-- | esp8266/moduos.c | 36 | ||||
-rw-r--r-- | esp8266/mpconfigport.h | 14 | ||||
-rw-r--r-- | esp8266/scripts/apa102.py | 28 | ||||
-rw-r--r-- | esp8266/scripts/dht.py | 32 | ||||
-rw-r--r-- | esp8266/scripts/inisetup.py | 4 | ||||
-rw-r--r-- | esp8266/scripts/neopixel.py | 9 | ||||
-rw-r--r-- | esp8266/scripts/ntptime.py | 4 | ||||
-rw-r--r-- | esp8266/scripts/onewire.py | 2 | ||||
-rw-r--r-- | esp8266/scripts/port_diag.py | 12 | ||||
-rw-r--r-- | esp8266/scripts/webrepl.py | 33 | ||||
-rw-r--r-- | esp8266/scripts/webrepl_setup.py | 5 | ||||
-rw-r--r-- | esp8266/uart.c | 5 | ||||
-rw-r--r-- | esp8266/xtirq.h | 60 |
30 files changed, 568 insertions, 69 deletions
diff --git a/esp8266/Makefile b/esp8266/Makefile index d8786301a8..65093d819b 100644 --- a/esp8266/Makefile +++ b/esp8266/Makefile @@ -26,7 +26,7 @@ INC += -I$(BUILD) INC += -I$(ESP_SDK)/include # UART for "os" messages. 0 is normal UART as used by MicroPython REPL, -# 1 is debug UART (tx only). +# 1 is debug UART (tx only), -1 to disable. UART_OS = 0 CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \ @@ -65,6 +65,7 @@ SRC_C = \ esppwm.c \ esponewire.c \ espneopixel.c \ + espapa102.c \ intr.c \ modpyb.c \ modpybpin.c \ @@ -123,6 +124,10 @@ LIB_SRC_C = $(addprefix lib/,\ fatfs/option/ccsbcs.c \ ) +DRIVERS_SRC_C = $(addprefix drivers/,\ + dht/dht.c \ + ) + SRC_S = \ gchelper.s \ @@ -133,10 +138,11 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) #OBJ += $(BUILD)/pins_$(BOARD).o # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(EXTMOD_SRC_C) +SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(EXTMOD_SRC_C) $(DRIVERS_SRC_C) # Append any auto-generated sources that are needed by sources listed in SRC_QSTR SRC_QSTR_AUTO_DEPS += diff --git a/esp8266/README.md b/esp8266/README.md index e187d4da17..0509a3799b 100644 --- a/esp8266/README.md +++ b/esp8266/README.md @@ -69,6 +69,34 @@ $ make PORT=/dev/ttyUSB0 deploy The image produced is `firmware-combined.bin`, to be flashed at 0x00000. +First start +----------- + +__Serial prompt__ + +You can access the REPL (Python prompt) over UART (the same as used for +programming). +- Baudrate: 115200 + +__WiFi__ + +Initally, the device configures itself as a WiFi access point (AP). +- ESSID: MicroPython-xxxxxx (x’s are replaced with part of the MAC address). +- Password: micropythoN (note the upper-case N). +- IP address of the board: 192.168.4.1. +- DHCP-server is activated. + +__WebREPL__ + +Python prompt over WiFi, connecting through a browser. +- Hosted at http://micropython.org/webrepl. +- GitHub repository https://github.com/micropython/webrepl. + +Please follow the instructions there. + +More detailed instructions can be found at +http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/intro.html + Troubleshooting --------------- diff --git a/esp8266/esp_mphal.c b/esp8266/esp_mphal.c index 25f1a9322f..9f090a0973 100644 --- a/esp8266/esp_mphal.c +++ b/esp8266/esp_mphal.c @@ -166,21 +166,24 @@ static int call_dupterm_read(void) { read_m[2] = MP_OBJ_NEW_SMALL_INT(1); mp_obj_t res = mp_call_method_n_kw(1, 0, read_m); if (res == mp_const_none) { + nlr_pop(); return -2; } mp_buffer_info_t bufinfo; mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ); if (bufinfo.len == 0) { - MP_STATE_PORT(term_obj) = NULL; - mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n"); + mp_uos_deactivate("dupterm: EOF received, deactivating\n", MP_OBJ_NULL); + nlr_pop(); return -1; } nlr_pop(); + if (*(byte*)bufinfo.buf == interrupt_char) { + mp_keyboard_interrupt(); + return -2; + } return *(byte*)bufinfo.buf; } else { - MP_STATE_PORT(term_obj) = NULL; - mp_printf(&mp_plat_print, "dupterm: Exception in read() method, deactivating: "); - mp_obj_print_exception(&mp_plat_print, nlr.ret_val); + mp_uos_deactivate("dupterm: Exception in read() method, deactivating: ", nlr.ret_val); } return -1; @@ -213,7 +216,7 @@ void mp_hal_signal_dupterm_input(void) { system_os_post(DUPTERM_TASK_ID, 0, 0); } -void mp_hal_pin_config_od(mp_hal_pin_obj_t pin_id) { +void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin_id) { const pyb_pin_obj_t *pin = &pyb_pin_obj[pin_id]; if (pin->phys_port == 16) { diff --git a/esp8266/esp_mphal.h b/esp8266/esp_mphal.h index 13b1c8fdf0..91fee21198 100644 --- a/esp8266/esp_mphal.h +++ b/esp8266/esp_mphal.h @@ -28,6 +28,10 @@ #define _INCLUDED_MPHAL_H_ #include "py/ringbuf.h" +#include "xtirq.h" + +void mp_keyboard_interrupt(void); +extern int interrupt_char; struct _mp_print_t; // Structure for UART-only output via mp_printf() @@ -59,14 +63,19 @@ void ets_event_poll(void); #include "osapi.h" #define mp_hal_delay_us_fast(us) os_delay_us(us) +#define mp_hal_quiet_timing_enter() disable_irq() +#define mp_hal_quiet_timing_exit(irq_state) enable_irq(irq_state) + // C-level pin HAL #include "etshal.h" #include "gpio.h" #include "esp8266/modpyb.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_config_od(mp_hal_pin_obj_t pin); -#define mp_hal_pin_low(p) do { \ +void mp_hal_pin_input(mp_hal_pin_obj_t pin); +void mp_hal_pin_output(mp_hal_pin_obj_t pin); +void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin); +#define mp_hal_pin_od_low(p) do { \ if ((p) == 16) { WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); } \ else { gpio_output_set(0, 1 << (p), 1 << (p), 0); } \ } while (0) diff --git a/esp8266/espapa102.c b/esp8266/espapa102.c new file mode 100644 index 0000000000..e5f3024b10 --- /dev/null +++ b/esp8266/espapa102.c @@ -0,0 +1,110 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Robert Foss, Daniel Busch + * + * 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 <stdio.h> +#include "c_types.h" +#include "eagle_soc.h" +#include "user_interface.h" +#include "espapa102.h" + +#define NOP asm volatile(" nop \n\t") + +static inline void _esp_apa102_send_byte(uint32_t clockPinMask, uint32_t dataPinMask, uint8_t byte) { + for (uint32_t i = 0; i < 8; i++) { + if (byte & 0x80) { + // set data pin high + GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, dataPinMask); + } else { + // set data pin low + GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, dataPinMask); + } + + // set clock pin high + GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, clockPinMask); + byte <<= 1; + NOP; + NOP; + + // set clock pin low + GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clockPinMask); + NOP; + NOP; + } +} + +static inline void _esp_apa102_send_colors(uint32_t clockPinMask, uint32_t dataPinMask, uint8_t *pixels, uint32_t numBytes) { + for (uint32_t i = 0; i < numBytes / 4; i++) { + _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 3] | 0xE0); + _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 2]); + _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 1]); + _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4]); + } +} + +static inline void _esp_apa102_start_frame(uint32_t clockPinMask, uint32_t dataPinMask) { + for (uint32_t i = 0; i < 4; i++) { + _esp_apa102_send_byte(clockPinMask, dataPinMask, 0x00); + } +} + +static inline void _esp_apa102_append_additionial_cycles(uint32_t clockPinMask, uint32_t dataPinMask, uint32_t numBytes) { + GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, dataPinMask); + + // we need to write some more clock cycles, because each led + // delays the data by one edge after inverting the clock + for (uint32_t i = 0; i < numBytes / 8 + ((numBytes / 4) % 2); i++) { + GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, clockPinMask); + NOP; + NOP; + + GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clockPinMask); + NOP; + NOP; + } +} + +static inline void _esp_apa102_end_frame(uint32_t clockPinMask, uint32_t dataPinMask) { + for (uint32_t i = 0; i < 4; i++) { + _esp_apa102_send_byte(clockPinMask, dataPinMask, 0xFF); + } +} + +void esp_apa102_write(uint8_t clockPin, uint8_t dataPin, uint8_t *pixels, uint32_t numBytes) { + uint32_t clockPinMask, dataPinMask; + + clockPinMask = 1 << clockPin; + dataPinMask = 1 << dataPin; + + // start the frame + _esp_apa102_start_frame(clockPinMask, dataPinMask); + + // write pixels + _esp_apa102_send_colors(clockPinMask, dataPinMask, pixels, numBytes); + + // end the frame + _esp_apa102_append_additionial_cycles(clockPinMask, dataPinMask, numBytes); + _esp_apa102_end_frame(clockPinMask, dataPinMask); +} diff --git a/esp8266/espapa102.h b/esp8266/espapa102.h new file mode 100644 index 0000000000..82c92025d3 --- /dev/null +++ b/esp8266/espapa102.h @@ -0,0 +1,27 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Robert Foss, Daniel Busch + * + * 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. + */ + +void esp_apa102_write(uint8_t clockPin, uint8_t dataPin, uint8_t *pixels, uint32_t numBytes); diff --git a/esp8266/ets_alt_task.c b/esp8266/ets_alt_task.c index 91623f06df..62872affb9 100644 --- a/esp8266/ets_alt_task.c +++ b/esp8266/ets_alt_task.c @@ -5,6 +5,7 @@ #include <esp_sdk_ver.h> #include "etshal.h" #include "user_interface.h" +#include "ets_alt_task.h" // Use standard ets_task or alternative impl #define USE_ETS_TASK 0 @@ -107,7 +108,12 @@ bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) { #endif } +int ets_loop_iter_disable = 0; + bool ets_loop_iter(void) { + if (ets_loop_iter_disable) { + return false; + } //static unsigned cnt; bool progress = false; for (volatile struct task_entry *t = emu_tasks; t < &emu_tasks[MP_ARRAY_SIZE(emu_tasks)]; t++) { diff --git a/esp8266/ets_alt_task.h b/esp8266/ets_alt_task.h index c423995841..4b5ba26dbd 100644 --- a/esp8266/ets_alt_task.h +++ b/esp8266/ets_alt_task.h @@ -1 +1,2 @@ +extern int ets_loop_iter_disable; bool ets_loop_iter(void); diff --git a/esp8266/help.c b/esp8266/help.c index 3a4d6e83a2..5370ee71ea 100644 --- a/esp8266/help.c +++ b/esp8266/help.c @@ -37,7 +37,7 @@ STATIC const char *help_text = "Basic WiFi configuration:\n" "\n" "import network\n" -"sta_if = network.WLAN(network.STA_IF)\n" +"sta_if = network.WLAN(network.STA_IF); sta_if.active(True)\n" "sta_if.scan() # Scan for available access points\n" "sta_if.connect(\"<AP_name>\", \"<password>\") # Connect to an AP\n" "sta_if.isconnected() # Check for successful connection\n" diff --git a/esp8266/main.c b/esp8266/main.c index 45ee85ac88..9cc955e44c 100644 --- a/esp8266/main.c +++ b/esp8266/main.c @@ -38,7 +38,7 @@ #include "gccollect.h" #include "user_interface.h" -STATIC char heap[24 * 1024]; +STATIC char heap[28 * 1024]; STATIC void mp_reset(void) { mp_stack_set_top((void*)0x40000000); @@ -58,7 +58,7 @@ STATIC void mp_reset(void) { MP_STATE_PORT(term_obj) = MP_OBJ_NULL; pin_init0(); #if MICROPY_MODULE_FROZEN - pyexec_frozen_module("_boot"); + pyexec_frozen_module("_boot.py"); pyexec_file("boot.py"); pyexec_file("main.py"); #endif diff --git a/esp8266/modesp.c b/esp8266/modesp.c index 44401d3a61..0c6cc423e1 100644 --- a/esp8266/modesp.c +++ b/esp8266/modesp.c @@ -27,13 +27,14 @@ #include <stdio.h> #include <string.h> #include <stdbool.h> -#include <errno.h> #include "py/nlr.h" #include "py/obj.h" #include "py/gc.h" #include "py/runtime.h" +#include "py/mperrno.h" #include "py/mphal.h" +#include "drivers/dht/dht.h" #include "netutils.h" #include "queue.h" #include "ets_sys.h" @@ -43,6 +44,7 @@ #include "spi_flash.h" #include "mem.h" #include "espneopixel.h" +#include "espapa102.h" #include "modpyb.h" #define MODESP_ESPCONN (0) @@ -577,7 +579,7 @@ STATIC mp_obj_t esp_flash_read(mp_obj_t offset_in, mp_obj_t len_or_buf_in) { if (alloc_buf) { m_del(byte, buf, len); } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO))); + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO))); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read); @@ -594,7 +596,7 @@ STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, const mp_obj_t buf_in) { } nlr_raise(mp_obj_new_exception_arg1( &mp_type_OSError, - MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO))); + MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO))); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write); @@ -606,7 +608,7 @@ STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) { } nlr_raise(mp_obj_new_exception_arg1( &mp_type_OSError, - MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO))); + MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase); @@ -636,6 +638,16 @@ STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k) } STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_); +STATIC mp_obj_t esp_apa102_write_(mp_obj_t clockPin, mp_obj_t dataPin, mp_obj_t buf) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); + esp_apa102_write(mp_obj_get_pin_obj(clockPin)->phys_port, + mp_obj_get_pin_obj(dataPin)->phys_port, + (uint8_t*)bufinfo.buf, bufinfo.len); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_apa102_write_obj, esp_apa102_write_); + STATIC mp_obj_t esp_freemem() { return MP_OBJ_NEW_SMALL_INT(system_get_free_heap_size()); } @@ -679,6 +691,8 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj }, #endif { MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&esp_neopixel_write_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_apa102_write), (mp_obj_t)&esp_apa102_write_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_dht_readinto), (mp_obj_t)&dht_readinto_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_freemem), (mp_obj_t)&esp_freemem_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_meminfo), (mp_obj_t)&esp_meminfo_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj }, // TODO delete/rename/move elsewhere diff --git a/esp8266/modmachine.c b/esp8266/modmachine.c index c3c9494ac8..36872c9dff 100644 --- a/esp8266/modmachine.c +++ b/esp8266/modmachine.c @@ -30,10 +30,12 @@ #include "py/obj.h" #include "py/runtime.h" #include "extmod/machine_mem.h" +#include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" #include "modpyb.h" #include "modpybrtc.h" +#include "xtirq.h" #include "os_type.h" #include "osapi.h" #include "etshal.h" @@ -189,6 +191,25 @@ const mp_obj_type_t esp_timer_type = { .locals_dict = (mp_obj_t)&esp_timer_locals_dict, }; +// this bit is unused in the Xtensa PS register +#define ETS_LOOP_ITER_BIT (12) + +STATIC mp_obj_t machine_disable_irq(void) { + uint32_t state = disable_irq(); + state = (state & ~(1 << ETS_LOOP_ITER_BIT)) | (ets_loop_iter_disable << ETS_LOOP_ITER_BIT); + ets_loop_iter_disable = 1; + return mp_obj_new_int(state); +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq); + +STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) { + uint32_t state = mp_obj_get_int(state_in); + ets_loop_iter_disable = (state >> ETS_LOOP_ITER_BIT) & 1; + enable_irq(state & ~(1 << ETS_LOOP_ITER_BIT)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq); + STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, @@ -201,6 +222,11 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, + { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, + + { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, + { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&esp_timer_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pyb_pin_type) }, diff --git a/esp8266/modnetwork.c b/esp8266/modnetwork.c index 5e9273158c..c0763ce0eb 100644 --- a/esp8266/modnetwork.c +++ b/esp8266/modnetwork.c @@ -27,7 +27,6 @@ #include <stdio.h> #include <stdint.h> #include <string.h> -#include <errno.h> #include "py/nlr.h" #include "py/objlist.h" @@ -137,16 +136,25 @@ STATIC void esp_scan_cb(scaninfo *si, STATUS status) { return; } if (si->pbss && status == 0) { - struct bss_info *bs; - STAILQ_FOREACH(bs, si->pbss, next) { - mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL); - t->items[0] = mp_obj_new_bytes(bs->ssid, strlen((char*)bs->ssid)); - t->items[1] = mp_obj_new_bytes(bs->bssid, sizeof(bs->bssid)); - t->items[2] = MP_OBJ_NEW_SMALL_INT(bs->channel); - t->items[3] = MP_OBJ_NEW_SMALL_INT(bs->rssi); - t->items[4] = MP_OBJ_NEW_SMALL_INT(bs->authmode); - t->items[5] = MP_OBJ_NEW_SMALL_INT(bs->is_hidden); - mp_obj_list_append(*esp_scan_list, MP_OBJ_FROM_PTR(t)); + // we need to catch any memory errors + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + struct bss_info *bs; + STAILQ_FOREACH(bs, si->pbss, next) { + mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL); + t->items[0] = mp_obj_new_bytes(bs->ssid, strlen((char*)bs->ssid)); + t->items[1] = mp_obj_new_bytes(bs->bssid, sizeof(bs->bssid)); + t->items[2] = MP_OBJ_NEW_SMALL_INT(bs->channel); + t->items[3] = MP_OBJ_NEW_SMALL_INT(bs->rssi); + t->items[4] = MP_OBJ_NEW_SMALL_INT(bs->authmode); + t->items[5] = MP_OBJ_NEW_SMALL_INT(bs->is_hidden); + mp_obj_list_append(*esp_scan_list, MP_OBJ_FROM_PTR(t)); + } + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + // indicate error + *esp_scan_list = MP_OBJ_NULL; } } else { // indicate error @@ -156,14 +164,25 @@ STATIC void esp_scan_cb(scaninfo *si, STATUS status) { } STATIC mp_obj_t esp_scan(mp_obj_t self_in) { - if (wifi_get_opmode() == SOFTAP_MODE) { + require_if(self_in, STATION_IF); + if ((wifi_get_opmode() & STATION_MODE) == 0) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, - "scan unsupported in AP mode")); + "STA must be active")); } mp_obj_t list = mp_obj_new_list(0, NULL); esp_scan_list = &list; wifi_station_scan(NULL, (scan_done_cb_t)esp_scan_cb); - ETS_POLL_WHILE(esp_scan_list != NULL); + while (esp_scan_list != NULL) { + // our esp_scan_cb is called via ets_loop_iter so it's safe to set the + // esp_scan_list variable to NULL without disabling interrupts + if (MP_STATE_VM(mp_pending_exception) != NULL) { + esp_scan_list = NULL; + mp_obj_t obj = MP_STATE_VM(mp_pending_exception); + MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; + nlr_raise(obj); + } + ets_loop_iter(); + } if (list == MP_OBJ_NULL) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "scan failed")); } diff --git a/esp8266/modpybpin.c b/esp8266/modpybpin.c index 6b9e20268b..166d6f566f 100644 --- a/esp8266/modpybpin.c +++ b/esp8266/modpybpin.c @@ -36,6 +36,7 @@ #include "py/nlr.h" #include "py/runtime.h" #include "py/gc.h" +#include "py/mphal.h" #include "modpyb.h" #define GET_TRIGGER(phys_port) \ @@ -123,6 +124,34 @@ 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; diff --git a/esp8266/modpybrtc.c b/esp8266/modpybrtc.c index e62dc88175..484d0d82fd 100644 --- a/esp8266/modpybrtc.c +++ b/esp8266/modpybrtc.c @@ -53,6 +53,9 @@ STATIC const pyb_rtc_obj_t pyb_rtc_obj = {{&pyb_rtc_type}}; 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; @@ -64,7 +67,11 @@ void mp_hal_rtc_init(void) { 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; @@ -79,13 +86,11 @@ STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp return (mp_obj_t)&pyb_rtc_obj; } -STATIC uint64_t pyb_rtc_raw_us(uint64_t cal) { - return (system_get_rtc_time() * cal) >> 12; -}; - void pyb_rtc_set_us_since_2000(uint64_t nowus) { uint32_t cal = system_rtc_clock_cali_proc(); - int64_t delta = nowus - pyb_rtc_raw_us(cal); + // 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 @@ -96,11 +101,23 @@ void pyb_rtc_set_us_since_2000(uint64_t nowus) { 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)); - return pyb_rtc_raw_us(cal) + 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; }; STATIC mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) { @@ -145,20 +162,17 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_d 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; - uint32_t magic; if (n_args == 1) { - - system_rtc_mem_read(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic)); - if (magic != MEM_MAGIC) { - return mp_const_none; - } + // 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); @@ -167,8 +181,6 @@ STATIC mp_obj_t pyb_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) { "buffer too long")); } - magic = MEM_MAGIC; - system_rtc_mem_write(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic)); len = bufinfo.len; system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len)); diff --git a/esp8266/modpybspi.c b/esp8266/modpybspi.c index 1131e8ef6b..c2bcc33edc 100644 --- a/esp8266/modpybspi.c +++ b/esp8266/modpybspi.c @@ -27,7 +27,6 @@ #include <stdio.h> #include <stdint.h> #include <string.h> -#include <errno.h> #include "ets_sys.h" #include "etshal.h" @@ -124,6 +123,12 @@ STATIC void pyb_spi_init_helper(pyb_spi_obj_t *self, size_t n_args, const mp_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); } STATIC 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) { diff --git a/esp8266/modpybuart.c b/esp8266/modpybuart.c index eefb38d998..5971ffecec 100644 --- a/esp8266/modpybuart.c +++ b/esp8266/modpybuart.c @@ -27,13 +27,13 @@ #include <stdio.h> #include <stdint.h> #include <string.h> -#include <errno.h> #include "ets_sys.h" #include "uart.h" #include "py/runtime.h" #include "py/stream.h" +#include "py/mperrno.h" #include "modpyb.h" // baudrate is currently fixed to this value @@ -136,7 +136,7 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i // wait for first char to become available if (!uart_rx_wait(self->timeout * 1000)) { - *errcode = EAGAIN; + *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } @@ -173,7 +173,7 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t } STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { - *errcode = EINVAL; + *errcode = MP_EINVAL; return MP_STREAM_ERROR; } diff --git a/esp8266/moduos.c b/esp8266/moduos.c index d75062eaf7..74262d86b1 100644 --- a/esp8266/moduos.c +++ b/esp8266/moduos.c @@ -25,7 +25,6 @@ */ #include <string.h> -#include <errno.h> #include "py/mpconfig.h" #include "py/nlr.h" @@ -33,6 +32,7 @@ #include "py/objtuple.h" #include "py/objstr.h" #include "py/runtime.h" +#include "py/mperrno.h" #include "extmod/misc.h" #include "genhdr/mpversion.h" #include "esp_mphal.h" @@ -74,12 +74,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); #if MICROPY_VFS_FAT mp_obj_t vfs_proxy_call(qstr method_name, mp_uint_t n_args, const mp_obj_t *args) { if (MP_STATE_PORT(fs_user_mount)[0] == NULL) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENODEV))); + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENODEV))); } mp_obj_t meth[n_args + 2]; mp_load_method(MP_STATE_PORT(fs_user_mount)[0], method_name, meth); - memcpy(meth + 2, args, n_args * sizeof(*args)); + if (args != NULL) { + memcpy(meth + 2, args, n_args * sizeof(*args)); + } return mp_call_method_n_kw(n_args, 0, meth); } @@ -93,10 +95,29 @@ STATIC mp_obj_t os_mkdir(mp_obj_t path_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir); +STATIC mp_obj_t os_chdir(mp_obj_t path_in) { + return vfs_proxy_call(MP_QSTR_chdir, 1, &path_in); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir); + +STATIC mp_obj_t os_getcwd(void) { + return vfs_proxy_call(MP_QSTR_getcwd, 0, NULL); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd); + STATIC mp_obj_t os_remove(mp_obj_t path_in) { return vfs_proxy_call(MP_QSTR_remove, 1, &path_in); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove); + +STATIC mp_obj_t os_rename(mp_obj_t path_old, mp_obj_t path_new) { + mp_obj_t args[2]; + args[0] = path_old; + args[1] = path_new; + return vfs_proxy_call(MP_QSTR_rename, 2, args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename); + #endif STATIC mp_obj_t os_urandom(mp_obj_t num) { @@ -117,6 +138,11 @@ STATIC mp_obj_t os_dupterm_notify(mp_obj_t obj_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_dupterm_notify_obj, os_dupterm_notify); +STATIC mp_obj_t os_stat(mp_obj_t path_in) { + return vfs_proxy_call(MP_QSTR_stat, 1, &path_in); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_stat_obj, os_stat); + STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, @@ -129,7 +155,11 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&os_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&os_mkdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&os_chdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&os_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&os_remove_obj) }, + { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&os_rename_obj) }, + { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&os_stat_obj) }, #endif }; diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h index e2c7f57e22..544edc408f 100644 --- a/esp8266/mpconfigport.h +++ b/esp8266/mpconfigport.h @@ -4,6 +4,11 @@ #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C) #define MICROPY_ALLOC_PATH_MAX (128) +#define MICROPY_ALLOC_LEXER_INDENT_INIT (8) +#define MICROPY_ALLOC_PARSE_RULE_INIT (48) +#define MICROPY_ALLOC_PARSE_RULE_INC (8) +#define MICROPY_ALLOC_PARSE_RESULT_INC (8) +#define MICROPY_ALLOC_PARSE_CHUNK_INIT (64) #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) @@ -19,6 +24,7 @@ #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) +#define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_BYTEARRAY (1) @@ -32,14 +38,17 @@ #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_COLLECTIONS (1) +#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH (1) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (1) +#define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_STRUCT (1) #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_STDFILES (1) +#define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_UCTYPES (1) #define MICROPY_PY_UHASHLIB (1) @@ -51,6 +60,7 @@ #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_LWIP (1) #define MICROPY_PY_MACHINE (1) +#define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_WEBSOCKET (1) #define MICROPY_PY_WEBREPL (1) @@ -105,6 +115,9 @@ typedef uint32_t sys_prot_t; // for modlwip #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) +#define mp_type_fileio fatfs_type_fileio +#define mp_type_textio fatfs_type_textio + // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_OBJ_NEW_QSTR(MP_QSTR_help), (mp_obj_t)&mp_builtin_help_obj }, \ @@ -135,6 +148,7 @@ extern const struct _mp_obj_module_t onewire_module; { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&utime_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&uos_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \ #define MP_STATE_PORT MP_STATE_VM diff --git a/esp8266/scripts/apa102.py b/esp8266/scripts/apa102.py new file mode 100644 index 0000000000..126448cc20 --- /dev/null +++ b/esp8266/scripts/apa102.py @@ -0,0 +1,28 @@ +# APA102 driver for MicroPython on ESP8266 +# MIT license; Copyright (c) 2016 Robert Foss, Daniel Busch + +from esp import apa102_write + +class APA102: + def __init__(self, clock_pin, data_pin, n): + self.clock_pin = clock_pin + self.data_pin = data_pin + self.n = n + self.buf = bytearray(n * 4) + + self.clock_pin.init(clock_pin.OUT) + self.data_pin.init(data_pin.OUT) + + def __setitem__(self, index, val): + r, g, b, brightness = val + self.buf[index * 4] = r + self.buf[index * 4 + 1] = g + self.buf[index * 4 + 2] = b + self.buf[index * 4 + 3] = brightness + + def __getitem__(self, index): + i = index * 4 + return self.buf[i], self.buf[i + 1], self.buf[i + 2], self.buf[i + 3] + + def write(self): + apa102_write(self.clock_pin, self.data_pin, self.buf) diff --git a/esp8266/scripts/dht.py b/esp8266/scripts/dht.py new file mode 100644 index 0000000000..9a69e7e07e --- /dev/null +++ b/esp8266/scripts/dht.py @@ -0,0 +1,32 @@ +# DHT11/DHT22 driver for MicroPython on ESP8266 +# MIT license; Copyright (c) 2016 Damien P. George + +import esp + +class DHTBase: + def __init__(self, pin): + self.pin = pin + self.buf = bytearray(5) + + def measure(self): + buf = self.buf + esp.dht_readinto(self.pin, buf) + if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xff != buf[4]: + raise Exception("checksum error") + +class DHT11(DHTBase): + def humidity(self): + return self.buf[0] + + def temperature(self): + return self.buf[2] + +class DHT22(DHTBase): + def humidity(self): + return (self.buf[0] << 8 | self.buf[1]) * 0.1 + + def temperature(self): + t = ((self.buf[2] & 0x7f) << 8 | self.buf[3]) * 0.1 + if self.buf[2] & 0x80: + t = -t + return t diff --git a/esp8266/scripts/inisetup.py b/esp8266/scripts/inisetup.py index 93a05bd8a7..461690b162 100644 --- a/esp8266/scripts/inisetup.py +++ b/esp8266/scripts/inisetup.py @@ -40,7 +40,7 @@ def setup(): with open("/boot.py", "w") as f: f.write("""\ # This file is executed on every boot (including wake-boot from deepsleep) -import webrepl -webrepl.start() +#import webrepl +#webrepl.start() """) return vfs diff --git a/esp8266/scripts/neopixel.py b/esp8266/scripts/neopixel.py index 4818c74a3b..8aa0348680 100644 --- a/esp8266/scripts/neopixel.py +++ b/esp8266/scripts/neopixel.py @@ -8,7 +8,7 @@ class NeoPixel: self.pin = pin self.n = n self.buf = bytearray(n * 3) - self.pin.init(pin.OUT, pin.PULL_NONE) + self.pin.init(pin.OUT) def __setitem__(self, index, val): r, g, b = val @@ -20,5 +20,12 @@ class NeoPixel: i = index * 3 return self.buf[i + 1], self.buf[i], self.buf[i + 2] + def fill(self, color): + r, g, b = color + for i in range(len(self.buf) / 3): + self.buf[i * 3] = g + self.buf[i * 3 + 1] = r + self.buf[i * 3 + 2] = b + def write(self): neopixel_write(self.pin, self.buf, True) diff --git a/esp8266/scripts/ntptime.py b/esp8266/scripts/ntptime.py index 650cc2e85b..a97e08e60d 100644 --- a/esp8266/scripts/ntptime.py +++ b/esp8266/scripts/ntptime.py @@ -10,10 +10,12 @@ except: # (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 NTP_DELTA = 3155673600 +host = "pool.ntp.org" + def time(): NTP_QUERY = bytearray(48) NTP_QUERY[0] = 0x1b - addr = socket.getaddrinfo('pool.ntp.org', 123)[0][-1] + addr = socket.getaddrinfo(host, 123)[0][-1] s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.settimeout(1) res = s.sendto(NTP_QUERY, addr) diff --git a/esp8266/scripts/onewire.py b/esp8266/scripts/onewire.py index 4980d0af5c..686616950a 100644 --- a/esp8266/scripts/onewire.py +++ b/esp8266/scripts/onewire.py @@ -13,7 +13,7 @@ class OneWire: def __init__(self, pin): self.pin = pin - self.pin.init(pin.OPEN_DRAIN, pin.PULL_NONE) + self.pin.init(pin.OPEN_DRAIN) def reset(self): return _ow.reset(self.pin) diff --git a/esp8266/scripts/port_diag.py b/esp8266/scripts/port_diag.py index fd7ee52d14..aa696b1abb 100644 --- a/esp8266/scripts/port_diag.py +++ b/esp8266/scripts/port_diag.py @@ -1,5 +1,7 @@ import esp import uctypes +import network +import lwip def main(): @@ -7,6 +9,7 @@ def main(): ROM = uctypes.bytearray_at(0x40200000, 16) fid = esp.flash_id() + print("FlashROM:") print("Flash ID: %x (Vendor: %x Device: %x)" % (fid, fid & 0xff, fid & 0xff00 | fid >> 16)) print("Flash bootloader data:") @@ -15,5 +18,14 @@ def main(): print("Byte @2: %02x" % ROM[2]) print("Byte @3: %02x (Flash size: %s Flash freq: %s)" % (ROM[3], SZ_MAP.get(ROM[3] >> 4, "?"), FREQ_MAP.get(ROM[3] & 0xf))) + print("\nNetworking:") + print("STA ifconfig:", network.WLAN(network.STA_IF).ifconfig()) + print("AP ifconfig:", network.WLAN(network.AP_IF).ifconfig()) + print("Free WiFi driver buffers of type:") + for i in range(5): + print("%d: %d" % (i, esp.esf_free_bufs(i))) + print("lwIP PCBs:") + lwip.print_pcbs() + main() diff --git a/esp8266/scripts/webrepl.py b/esp8266/scripts/webrepl.py index 1a2c82277e..da3e70c595 100644 --- a/esp8266/scripts/webrepl.py +++ b/esp8266/scripts/webrepl.py @@ -10,7 +10,7 @@ listen_s = None client_s = None def setup_conn(port, accept_handler): - global listen_s, client_s + global listen_s listen_s = socket.socket() listen_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) @@ -19,11 +19,13 @@ def setup_conn(port, accept_handler): listen_s.bind(addr) listen_s.listen(1) - listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler) + if accept_handler: + listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler) for i in (network.AP_IF, network.STA_IF): iface = network.WLAN(i) if iface.active(): print("WebREPL daemon started on ws://%s:%d" % (iface.ifconfig()[0], port)) + return listen_s def accept_conn(listen_sock): @@ -49,14 +51,25 @@ def stop(): listen_s.close() -def start(port=8266): +def start(port=8266, password=None): stop() - try: - import port_config - _webrepl.password(port_config.WEBREPL_PASS) + if password is None: + try: + import port_config + _webrepl.password(port_config.WEBREPL_PASS) + setup_conn(port, accept_conn) + print("Started webrepl in normal mode") + except: + import webrepl_setup + setup_conn(port, webrepl_setup.handle_conn) + print("Started webrepl in setup mode") + else: + _webrepl.password(password) setup_conn(port, accept_conn) print("Started webrepl in normal mode") - except: - import webrepl_setup - setup_conn(port, webrepl_setup.handle_conn) - print("Started webrepl in setup mode") + + +def start_foreground(port=8266): + stop() + s = setup_conn(port, None) + accept_conn(s) diff --git a/esp8266/scripts/webrepl_setup.py b/esp8266/scripts/webrepl_setup.py index 7c4068750c..d0bf8465d5 100644 --- a/esp8266/scripts/webrepl_setup.py +++ b/esp8266/scripts/webrepl_setup.py @@ -26,7 +26,7 @@ def getpass(stream, prompt): stream.write("\r\n") return passwd passwd += c -# stream.write("*") + stream.write("*") def handle_conn(listen_sock): cl, remote_addr = listen_sock.accept() @@ -60,6 +60,9 @@ some boards, you may need to press reset button or reconnect power.\r if len(passwd1) < 4: ws.write("Password too short\r\n") continue + elif len(passwd1) > 9: + ws.write("Password too long\r\n") + continue passwd2 = getpass(ws, "Confirm password: ") if passwd1 == passwd2: break diff --git a/esp8266/uart.c b/esp8266/uart.c index 573f0cb072..1c317a1cb6 100644 --- a/esp8266/uart.c +++ b/esp8266/uart.c @@ -19,6 +19,9 @@ #include "user_interface.h" #include "esp_mphal.h" +// seems that this is missing in the Espressif SDK +#define FUNC_U0RXD 0 + #define UART_REPL UART0 // UartDev is defined and initialized in rom code. @@ -53,7 +56,7 @@ static void ICACHE_FLASH_ATTR uart_config(uint8 uart_no) { ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, NULL); PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD); } uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate)); diff --git a/esp8266/xtirq.h b/esp8266/xtirq.h new file mode 100644 index 0000000000..856ff075ac --- /dev/null +++ b/esp8266/xtirq.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#ifndef __MICROPY_INCLUDED_ESP8266_XTIRQ_H__ +#define __MICROPY_INCLUDED_ESP8266_XTIRQ_H__ + +#include <stdint.h> + +// returns the value of "intlevel" from the PS register +static inline uint32_t query_irq(void) { + uint32_t ps; + __asm__ volatile("rsr %0, ps" : "=a" (ps)); + return ps & 0xf; +} + +// irqs with a priority value lower or equal to "intlevel" will be disabled +// "intlevel" should be between 0 and 15 inclusive, and should be an integer +static inline uint32_t raise_irq_pri(uint32_t intlevel) { + uint32_t old_ps; + __asm__ volatile ("rsil %0, %1" : "=a" (old_ps) : "I" (intlevel)); + return old_ps; +} + +// "ps" should be the value returned from raise_irq_pri +static inline void restore_irq_pri(uint32_t ps) { + __asm__ volatile ("wsr %0, ps; rsync" :: "a" (ps)); +} + +static inline uint32_t disable_irq(void) { + return raise_irq_pri(15); +} + +static inline void enable_irq(uint32_t irq_state) { + restore_irq_pri(irq_state); +} + +#endif // __MICROPY_INCLUDED_ESP8266_XTIRQ_H__ |