summaryrefslogtreecommitdiffstatshomepage
path: root/esp8266
diff options
context:
space:
mode:
Diffstat (limited to 'esp8266')
-rw-r--r--esp8266/Makefile10
-rw-r--r--esp8266/README.md28
-rw-r--r--esp8266/esp_mphal.c15
-rw-r--r--esp8266/esp_mphal.h13
-rw-r--r--esp8266/espapa102.c110
-rw-r--r--esp8266/espapa102.h27
-rw-r--r--esp8266/ets_alt_task.c6
-rw-r--r--esp8266/ets_alt_task.h1
-rw-r--r--esp8266/help.c2
-rw-r--r--esp8266/main.c4
-rw-r--r--esp8266/modesp.c22
-rw-r--r--esp8266/modmachine.c26
-rw-r--r--esp8266/modnetwork.c47
-rw-r--r--esp8266/modpybpin.c29
-rw-r--r--esp8266/modpybrtc.c40
-rw-r--r--esp8266/modpybspi.c7
-rw-r--r--esp8266/modpybuart.c6
-rw-r--r--esp8266/moduos.c36
-rw-r--r--esp8266/mpconfigport.h14
-rw-r--r--esp8266/scripts/apa102.py28
-rw-r--r--esp8266/scripts/dht.py32
-rw-r--r--esp8266/scripts/inisetup.py4
-rw-r--r--esp8266/scripts/neopixel.py9
-rw-r--r--esp8266/scripts/ntptime.py4
-rw-r--r--esp8266/scripts/onewire.py2
-rw-r--r--esp8266/scripts/port_diag.py12
-rw-r--r--esp8266/scripts/webrepl.py33
-rw-r--r--esp8266/scripts/webrepl_setup.py5
-rw-r--r--esp8266/uart.c5
-rw-r--r--esp8266/xtirq.h60
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__