Repository: micropython/micropython-unicorn Branch: master Commit: 8286116877bc Files: 39 Total size: 246.9 KB Directory structure: gitextract_1e21aora/ ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── unicorn/ │ ├── Makefile │ ├── help.c │ ├── machine_i2c.c │ ├── machine_pin.c │ ├── main.c │ ├── modmachine.c │ ├── modmachine.h │ ├── modpyb.c │ ├── modpyb.h │ ├── modutime.c │ ├── mpconfigport.h │ ├── mpconfigport_features.h │ ├── mpconfigport_minimal.h │ ├── mpconfigport_pyboard.h │ ├── mphalport.c │ ├── mphalport.h │ ├── pyb_adc.c │ ├── pyb_led.c │ ├── pyb_servo.c │ ├── pyb_switch.c │ ├── qstrdefsport.h │ ├── uart.c │ ├── unicorn.ld │ └── unicorn_mcu.h └── www-emu/ ├── Makefile ├── codemirror.css ├── codemirror.js ├── demo_gen.py ├── features_demos.py ├── fit.js ├── index.html ├── minimal_demos.py ├── mp_unicorn.css ├── mp_unicorn.js └── pyboard_demos.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Build directories ###################### www-emu/build unicorn/build_* ================================================ FILE: .gitmodules ================================================ [submodule "micropython"] path = micropython url = https://github.com/micropython/micropython ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2017 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. ================================================ FILE: README.md ================================================ MicroPython on Unicorn ====================== This repository contains an implementation of a virtual microcontroller based on the Unicorn emulator, which is in turn based on QEMU. It also contains a port of MicroPython to that virtual microcontroller. Unicorn has a JavaScript version, unicorn.js, which is obtained by running Emscripten on the C version of Unicorn, and allows the virtual microcontroller to run in the browser. This then gives a full MicroPython port running simulated-bare-metal in a web browser. For a running demo please visit https://micropython.org/unicorn Build Instructions ------------------ ``` $ git submodule update --init ``` Firmware binaries can be customized in the unicorn directory. ``` $ cd unicorn $ make CONFIG=pyboard ``` The web page may be built using ``` $ cd www-emu $ make ``` In order to build without using gzip (For example when testing with `$ python -m http.server`) ``` $ cd www-emu $ make nogzip ``` There is a critical bug in unicorn-engine which is addressed [here](https://github.com/unicorn-engine/unicorn/pull/880). In order for full functionality apply the patch to a unicorn submodule within a unicorn.js repository and build normally. ================================================ FILE: unicorn/Makefile ================================================ # Select the configuration to build with, defaulting to "minimal" CONFIG ?= minimal ifeq ($(wildcard mpconfigport_$(CONFIG).h),) $(error Invalid CONFIG specified) endif BUILD = build_$(CONFIG) FIRMWARE = $(BUILD)/firmware_$(CONFIG) include ../micropython/py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h # include py core make definitions include $(TOP)/py/py.mk CROSS_COMPILE = arm-none-eabi- INC += -I. INC += -I$(TOP) INC += -I$(BUILD) CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) CFLAGS += -DMP_CONFIGFILE="" #Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -O0 -ggdb else CFLAGS += -Os -DNDEBUG endif LDFLAGS = -nostdlib -T unicorn.ld -Map=$@.map --cref LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) # Remove uncalled code from the final image. CFLAGS += -fdata-sections -ffunction-sections LDFLAGS += --gc-sections SRC_C = \ main.c \ uart.c \ help.c \ mphalport.c \ modutime.c \ modmachine.c \ machine_pin.c \ machine_i2c.c \ modpyb.c \ pyb_led.c \ pyb_switch.c \ pyb_servo.c \ pyb_adc.c \ shared/libc/string0.c \ shared/readline/readline.c \ shared/runtime/interrupt_char.c \ shared/runtime/pyexec.c \ shared/runtime/stdout_helpers.c \ SRC_C += \ lib/libm/math.c \ lib/libm/fmodf.c \ lib/libm/nearbyintf.c \ lib/libm/ef_sqrt.c \ lib/libm/log1pf.c \ lib/libm/acoshf.c \ lib/libm/asinhf.c \ lib/libm/atanhf.c \ lib/libm/kf_rem_pio2.c \ lib/libm/kf_sin.c \ lib/libm/kf_cos.c \ lib/libm/kf_tan.c \ lib/libm/ef_rem_pio2.c \ lib/libm/erf_lgamma.c \ lib/libm/sf_sin.c \ lib/libm/sf_cos.c \ lib/libm/sf_tan.c \ lib/libm/sf_frexp.c \ lib/libm/sf_modf.c \ lib/libm/sf_ldexp.c \ lib/libm/sf_erf.c \ lib/libm/wf_lgamma.c \ lib/libm/wf_tgamma.c \ lib/libm/asinfacosf.c \ lib/libm/atanf.c \ lib/libm/atan2f.c \ # List of sources for qstr extraction SRC_QSTR += $(SRC_C) OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) all: $(FIRMWARE).bin $(FIRMWARE).elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ $(FIRMWARE).bin: $(FIRMWARE).elf $(Q)$(OBJCOPY) -O binary -j .isr_vector -j .text -j .data $^ $@ include $(TOP)/py/mkrules.mk ================================================ FILE: unicorn/help.c ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 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 "py/builtin.h" const char unicorn_help_text[] = "Welcome to MicroPython running under Unicorn!\n" "\n" "Control commands:\n" " CTRL-A -- on a blank line, enter raw REPL mode\n" " CTRL-B -- on a blank line, enter normal REPL mode\n" " CTRL-C -- interrupt a running program\n" " CTRL-D -- on a blank line, do a soft reset of the board\n" " CTRL-E -- on a blank line, enter paste mode\n" "\n" "For further help on a specific object, type help(obj)\n" #if MICROPY_PY_BUILTINS_HELP_MODULES "For a list of available modules, type help('modules')\n" #endif ; ================================================ FILE: unicorn/machine_i2c.c ================================================ #include #include #include "py/runtime.h" #include "py/mphal.h" #include "py/mperrno.h" #include "extmod/machine_i2c.h" #include "unicorn_mcu.h" typedef struct _machine_i2c_obj_t { mp_obj_base_t base; } machine_i2c_obj_t; STATIC const machine_i2c_obj_t machine_i2c_obj[] = { {{&machine_i2c_type}}, }; STATIC void machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_printf(print, "I2C(1, freq=unicorn, timeout=unicorn)"); } STATIC mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_scl, ARG_sda, ARG_freq, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // work out i2c bus int i2c_id = 0; if (MP_OBJ_IS_STR(args[ARG_id].u_obj)) { const char *port = mp_obj_str_get_str(args[ARG_id].u_obj); if (0) { #ifdef MICROPY_HW_I2C1_NAME } else if (strcmp(port, "X") == 0) { i2c_id = 1; #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C(%s) doesn't exist", port)); } } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C(%d) doesn't exist", i2c_id)); } // get static peripheral object machine_i2c_obj_t *self = (machine_i2c_obj_t*)&machine_i2c_obj[i2c_id - 1]; // here we would check the scl/sda pins and configure them, but it's not implemented if (args[ARG_scl].u_obj != MP_OBJ_NULL || args[ARG_sda].u_obj != MP_OBJ_NULL) { mp_raise_ValueError("explicit choice of scl/sda is not implemented"); } // initialise the I2C peripheral //machine_i2c_init(self, args[ARG_freq].u_int, args[ARG_timeout].u_int); return MP_OBJ_FROM_PTR(self); } STATIC int machine_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) { printf("READFROM\n"); return 0; } STATIC int machine_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) { I2C->COMMAND = 0; I2C->DATA = addr << 1; int ret = I2C->DATA; if (ret < 0) { return ret; } else if (ret != 0) { return -MP_ENODEV; } int num_acks = 0; while (len > 0U) { I2C->DATA = *src++; len--; ret = I2C->DATA; if (ret < 0) { return ret; } else if (ret != 0) { break; } ++num_acks; } if (stop) { I2C->COMMAND = 1; } return num_acks; } STATIC int machine_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags) { if (flags & MP_MACHINE_I2C_FLAG_READ) { return machine_i2c_readfrom(self_in, addr, buf, len, flags & MP_MACHINE_I2C_FLAG_STOP); } else { return machine_i2c_writeto(self_in, addr, buf, len, flags & MP_MACHINE_I2C_FLAG_STOP); } } STATIC const mp_machine_i2c_p_t machine_i2c_p = { .transfer = mp_machine_i2c_transfer_adaptor, .transfer_single = machine_i2c_transfer_single, }; const mp_obj_type_t machine_i2c_type = { { &mp_type_type }, .name = MP_QSTR_I2C, .print = machine_i2c_print, .make_new = machine_i2c_make_new, .protocol = &machine_i2c_p, .locals_dict = (mp_obj_dict_t*)&mp_machine_i2c_locals_dict, }; ================================================ FILE: unicorn/machine_pin.c ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 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 "py/runtime.h" #include "modmachine.h" STATIC const machine_pin_obj_t machine_pin_obj[] = { {{&machine_pin_type}, MP_QSTR_X1, GPIO_X, 1}, {{&machine_pin_type}, MP_QSTR_X2, GPIO_X, 2}, {{&machine_pin_type}, MP_QSTR_X3, GPIO_X, 3}, {{&machine_pin_type}, MP_QSTR_X4, GPIO_X, 4}, {{&machine_pin_type}, MP_QSTR_X5, GPIO_X, 5}, {{&machine_pin_type}, MP_QSTR_X6, GPIO_X, 6}, {{&machine_pin_type}, MP_QSTR_X7, GPIO_X, 7}, {{&machine_pin_type}, MP_QSTR_X8, GPIO_X, 8}, {{&machine_pin_type}, MP_QSTR_X9, GPIO_X, 9}, {{&machine_pin_type}, MP_QSTR_X10, GPIO_X, 10}, {{&machine_pin_type}, MP_QSTR_X11, GPIO_X, 11}, {{&machine_pin_type}, MP_QSTR_X12, GPIO_X, 12}, {{&machine_pin_type}, MP_QSTR_X13, GPIO_X, 13}, {{&machine_pin_type}, MP_QSTR_X14, GPIO_X, 14}, {{&machine_pin_type}, MP_QSTR_X15, GPIO_X, 15}, {{&machine_pin_type}, MP_QSTR_X16, GPIO_X, 16}, {{&machine_pin_type}, MP_QSTR_X17, GPIO_X, 17}, {{&machine_pin_type}, MP_QSTR_X18, GPIO_X, 18}, {{&machine_pin_type}, MP_QSTR_X19, GPIO_X, 19}, {{&machine_pin_type}, MP_QSTR_X20, GPIO_X, 20}, {{&machine_pin_type}, MP_QSTR_X21, GPIO_X, 21}, {{&machine_pin_type}, MP_QSTR_X22, GPIO_X, 22}, {{&machine_pin_type}, MP_QSTR_X23, GPIO_X, 23}, {{&machine_pin_type}, MP_QSTR_X24, GPIO_X, 24}, {{&machine_pin_type}, MP_QSTR_Y1, GPIO_Y, 1}, {{&machine_pin_type}, MP_QSTR_Y2, GPIO_Y, 2}, {{&machine_pin_type}, MP_QSTR_Y3, GPIO_Y, 3}, {{&machine_pin_type}, MP_QSTR_Y4, GPIO_Y, 4}, {{&machine_pin_type}, MP_QSTR_Y5, GPIO_Y, 5}, {{&machine_pin_type}, MP_QSTR_Y6, GPIO_Y, 6}, {{&machine_pin_type}, MP_QSTR_Y7, GPIO_Y, 7}, {{&machine_pin_type}, MP_QSTR_Y8, GPIO_Y, 8}, {{&machine_pin_type}, MP_QSTR_Y9, GPIO_Y, 9}, {{&machine_pin_type}, MP_QSTR_Y10, GPIO_Y, 10}, {{&machine_pin_type}, MP_QSTR_Y11, GPIO_Y, 11}, {{&machine_pin_type}, MP_QSTR_Y12, GPIO_Y, 12}, }; machine_pin_obj_t *machine_pin_get(mp_obj_t *obj_in) { if (MP_OBJ_IS_TYPE(obj_in, &machine_pin_type)) { return (machine_pin_obj_t*)obj_in; } mp_raise_TypeError("expecting a Pin"); } void pin_set(mp_obj_t self_in, int value) { machine_pin_obj_t *self = self_in; if (value) { self->port->ODR |= (1 << self->pin); } else { self->port->ODR &= ~(1 << self->pin); } } void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_pin_obj_t *self = self_in; mp_printf(print, "Pin(%q)", self->name); } STATIC mp_obj_t machine_pin_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); qstr args0 = mp_obj_str_get_qstr(args[0]); for (int i = 0; i < MP_ARRAY_SIZE(machine_pin_obj); i++) { if (machine_pin_obj[i].name == args0) { return (mp_obj_t)&machine_pin_obj[i]; } } return mp_const_none; } STATIC mp_obj_t machine_pin_off(mp_obj_t self_in) { pin_set(self_in, 0); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_off_obj, machine_pin_off); STATIC mp_obj_t machine_pin_on(mp_obj_t self_in) { pin_set(self_in, 1); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_on_obj, machine_pin_on); mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); machine_pin_obj_t *self = self_in; if (n_args <= 0) { return MP_OBJ_NEW_SMALL_INT((self->port->IDR & (1 << self->pin)) ? 1 : 0); } else { if (mp_obj_get_int(args[0]) == 0) { self->port->ODR &= ~(1 << self->pin); } else { self->port->ODR |= (1 << self->pin); } return mp_const_none; } } STATIC mp_obj_t machine_pin_value(mp_uint_t n_args, const mp_obj_t *args) { return machine_pin_call(args[0], n_args - 1, 0, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value); STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_on_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_off_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(0) }, { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(1) }, { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(0) }, { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(1) }, { MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(0) }, }; STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); const mp_obj_type_t machine_pin_type = { { &mp_type_type }, .name = MP_QSTR_Pin, .print = machine_pin_print, .make_new = machine_pin_make_new, .call = machine_pin_call, .locals_dict = (mp_obj_dict_t*)&machine_pin_locals_dict, }; ================================================ FILE: unicorn/main.c ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 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/builtin.h" #include "py/compile.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/repl.h" #include "py/gc.h" #include "py/mperrno.h" #include "shared/runtime/interrupt_char.h" #include "shared/runtime/pyexec.h" #include "unicorn_mcu.h" void do_str(const char *src, mp_parse_input_kind_t input_kind) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); mp_obj_t module_fun = mp_compile(&parse_tree, MP_QSTR__lt_stdin_gt_, false); mp_call_function_0(module_fun); nlr_pop(); } else { // uncaught exception mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); } } int main(int argc, char **argv) { extern uint32_t _ebss; extern uint32_t _sdata; // Stack limit should be less than real stack size, so we have a chance // to recover from limit hit. (Limit is measured in bytes.) mp_stack_set_top((uint8_t*)&_sdata + UNICORN_CONTROLLER->RAM_SIZE); mp_stack_set_limit(UNICORN_CONTROLLER->STACK_SIZE - 1024); while (true) { gc_init(&_ebss, (uint8_t*)&_sdata + UNICORN_CONTROLLER->RAM_SIZE - UNICORN_CONTROLLER->STACK_SIZE); mp_init(); do_str("for i in range(1):pass", MP_PARSE_FILE_INPUT); for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { break; } } else { if (pyexec_friendly_repl() != 0) { break; } } } mp_deinit(); printf("PYB: soft reboot\n"); } return 0; } void gc_collect(void) { // WARNING: This gc_collect implementation doesn't try to get root // pointers from CPU registers, and thus may function incorrectly. void *dummy; gc_collect_start(); gc_collect_root(&dummy, ((mp_uint_t)MP_STATE_THREAD(stack_top) - (mp_uint_t)&dummy) / sizeof(mp_uint_t)); gc_collect_end(); } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); void nlr_jump_fail(void *val) { while (1); } void NORETURN __fatal_error(const char *msg) { while (1); } #ifndef NDEBUG void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); __fatal_error("Assertion failed"); } #endif // this is a minimal IRQ and reset framework for any Cortex-M CPU extern uint32_t _sidata, _sdata, _edata, _sbss, _ebss; void Reset_Handler(void) __attribute__((naked)); void Reset_Handler(void) { // set stack pointer __asm volatile ("ldr r0, =0x08000000"); __asm volatile ("ldr sp, [r0]"); // copy .data section from flash to RAM for (uint32_t *src = &_sidata, *dest = &_sdata; dest < &_edata;) { *dest++ = *src++; } // zero out .bss section for (uint32_t *dest = &_sbss; dest < &_ebss;) { *dest++ = 0; } UNICORN_CONTROLLER->PENDING = (uint32_t) &MP_STATE_MAIN_THREAD(mp_pending_exception); UNICORN_CONTROLLER->EXCEPTION = (uint32_t) &MP_STATE_VM(mp_kbd_exception); UNICORN_CONTROLLER->INTR_CHAR = (uint32_t) &mp_interrupt_char; // jump to board initialisation void _start(void); _start(); } void Default_Handler(void) { for (;;) { } } const uint32_t isr_vector[] __attribute__((section(".isr_vector"))) = { 0, // will be set dynamically (uint32_t)&Reset_Handler, (uint32_t)&Default_Handler, // NMI_Handler (uint32_t)&Default_Handler, // HardFault_Handler (uint32_t)&Default_Handler, // MemManage_Handler (uint32_t)&Default_Handler, // BusFault_Handler (uint32_t)&Default_Handler, // UsageFault_Handler 0, 0, 0, 0, (uint32_t)&Default_Handler, // SVC_Handler (uint32_t)&Default_Handler, // DebugMon_Handler 0, (uint32_t)&Default_Handler, // PendSV_Handler (uint32_t)&Default_Handler, // SysTick_Handler }; void _start(void) { // when we get here: stack is initialised, bss is clear, data is copied // SCB->CCR: enable 8-byte stack alignment for IRQ handlers, in accord with EABI //*((volatile uint32_t*)0xe000ed14) |= 1 << 9; // initialise the cpu and peripherals // now that we have a basic system up and running we can call main main(0, NULL); // we must not return for (;;) { } } ================================================ FILE: unicorn/modmachine.c ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 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 "py/obj.h" #include "modmachine.h" #include "extmod/machine_mem.h" #include "extmod/machine_i2c.h" #if MICROPY_PY_MACHINE STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) }, { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, #if MICROPY_PY_MACHINE_I2C { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, #endif }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); const mp_obj_module_t mp_module_machine = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&machine_module_globals, }; MP_REGISTER_MODULE(MP_QSTR_machine, mp_module_machine); #endif // MICROPY_PY_MACHINE ================================================ FILE: unicorn/modmachine.h ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 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_MODMACHINE_H #define MICROPY_INCLUDED_MODMACHINE_H #include "unicorn_mcu.h" typedef struct _machine_pin_obj_t { mp_obj_base_t base; qstr name; gpio_t *port; mp_uint_t pin; } machine_pin_obj_t; extern const mp_obj_type_t machine_pin_type; machine_pin_obj_t *machine_pin_get(mp_obj_t *obj_in); void pin_set(mp_obj_t self_in, int value); extern const mp_obj_type_t machine_i2c_type; #endif ================================================ FILE: unicorn/modpyb.c ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 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 "py/obj.h" #include "modpyb.h" STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pyb) }, { MP_ROM_QSTR(MP_QSTR_Switch), MP_ROM_PTR(&pyb_switch_type) }, { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pyb_led_type) }, { MP_ROM_QSTR(MP_QSTR_Servo), MP_ROM_PTR(&pyb_servo_type) }, { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_module_globals, pyb_module_globals_table); const mp_obj_module_t pyb_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&pyb_module_globals, }; MP_REGISTER_MODULE(MP_QSTR_pyb, pyb_module); ================================================ FILE: unicorn/modpyb.h ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 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. */ typedef enum { PYB_LED_RED = 1, PYB_LED_GREEN = 2, PYB_LED_YELLOW = 3, PYB_LED_BLUE = 4, } pyb_led_t; void led_state(pyb_led_t led, int state); void led_toggle(pyb_led_t led); extern const mp_obj_type_t pyb_led_type; void switch_init0(void); int switch_get(void); extern const mp_obj_type_t pyb_switch_type; void servo_init(void); extern const mp_obj_type_t pyb_servo_type; extern const mp_obj_type_t pyb_adc_type; ================================================ FILE: unicorn/modutime.c ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 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 "py/nlr.h" #include "py/smallint.h" #include "py/obj.h" #include "shared/timeutils/timeutils.h" #include "extmod/utime_mphal.h" #include "unicorn_mcu.h" #if MICROPY_PY_UTIME_MP_HAL STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); const mp_obj_module_t mp_module_utime = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&time_module_globals, }; MP_REGISTER_MODULE(MP_QSTR_utime, mp_module_utime); #endif // MICROPY_PY_UTIME_MP_HAL ================================================ FILE: unicorn/mpconfigport.h ================================================ #include // options to control how Micro Python is built #define MICROPY_QSTR_BYTES_IN_HASH (1) #define MICROPY_ALLOC_PATH_MAX (256) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (16) #define MICROPY_COMP_MODULE_CONST (0) #define MICROPY_STACK_CHECK (1) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTERS (0) #define MICROPY_ENABLE_GC (1) #define MICROPY_GC_ALLOC_THRESHOLD (0) #define MICROPY_REPL_EVENT_DRIVEN (0) #define MICROPY_HELPER_REPL (1) #define MICROPY_HELPER_LEXER_UNIX (0) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_ENABLE_DOC_STRING (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY___FILE__ (1) #define MICROPY_PY_IO (1) #define MICROPY_PY_STRUCT (1) #define MICROPY_PY_SYS (1) #define MICROPY_MODULE_FROZEN_MPY (0) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_KBD_EXCEPTION (1) // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) // This port is intended to be 32-bit, but unfortunately, int32_t for // different targets may be defined in different ways - either as int // or as long. This requires different printf formatting specifiers // to print such value. So, we avoid int32_t and use int directly. #define UINT_FMT "%u" #define INT_FMT "%d" typedef int mp_int_t; // must be pointer size typedef unsigned mp_uint_t; // must be pointer size typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, // We need an implementation of the log2 function which is not a macro #define MP_NEED_LOG2 (1) // We need to provide a declaration/definition of alloca() #include #define MICROPY_HW_BOARD_NAME "unicorn" #define MICROPY_HW_MCU_NAME "Cortex-M3" #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; ================================================ FILE: unicorn/mpconfigport_features.h ================================================ #define MICROPY_EMIT_THUMB (1) #define MICROPY_EMIT_INLINE_THUMB (1) #define MICROPY_COMP_CONST (1) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1) #define MICROPY_PY_ASYNC_AWAIT (1) #define MICROPY_PY_BUILTINS_BYTEARRAY (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_ENUMERATE (1) #define MICROPY_PY_BUILTINS_FILTER (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_REVERSED (1) #define MICROPY_PY_BUILTINS_SET (1) #define MICROPY_PY_BUILTINS_SLICE (1) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY_BUILTINS_MIN_MAX (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT unicorn_help_text #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY_GC (1) #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ATTRTUPLE (1) #define MICROPY_PY_COLLECTIONS (1) #define MICROPY_PY_MATH (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #include "mpconfigport.h" ================================================ FILE: unicorn/mpconfigport_minimal.h ================================================ #define MICROPY_COMP_CONST (0) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_BUILTINS_BYTEARRAY (0) #define MICROPY_PY_BUILTINS_ENUMERATE (0) #define MICROPY_PY_BUILTINS_FILTER (0) #define MICROPY_PY_BUILTINS_REVERSED (0) #define MICROPY_PY_BUILTINS_SET (0) #define MICROPY_PY_BUILTINS_SLICE (0) #define MICROPY_PY_BUILTINS_PROPERTY (0) #define MICROPY_PY_BUILTINS_MIN_MAX (0) #define MICROPY_PY_GC (0) #define MICROPY_PY_ARRAY (0) #define MICROPY_PY_ATTRTUPLE (0) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_MATH (0) #include "mpconfigport.h" ================================================ FILE: unicorn/mpconfigport_pyboard.h ================================================ #define MICROPY_EMIT_THUMB (1) #define MICROPY_EMIT_INLINE_THUMB (1) #define MICROPY_COMP_CONST (1) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1) #define MICROPY_PY_ASYNC_AWAIT (1) #define MICROPY_PY_BUILTINS_BYTEARRAY (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_ENUMERATE (1) #define MICROPY_PY_BUILTINS_FILTER (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_REVERSED (1) #define MICROPY_PY_BUILTINS_SET (1) #define MICROPY_PY_BUILTINS_SLICE (1) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY_BUILTINS_MIN_MAX (1) #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_POW3 (1) #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (1) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT unicorn_help_text #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY_BUILTINS_COMPILE (1) #define MICROPY_PY_BUILTINS_EXECFILE (1) #define MICROPY_PY_GC (1) #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ATTRTUPLE (1) #define MICROPY_PY_COLLECTIONS (1) #define MICROPY_PY_MATH (1) #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_SOFTI2C (1) #define MICROPY_HW_I2C1_NAME "X" #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #include "mpconfigport.h" ================================================ FILE: unicorn/mphalport.c ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 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 "py/runtime.h" #include "unicorn_mcu.h" #include "mphalport.h" void mp_hal_delay_ms(mp_uint_t ms) { uint32_t start = mp_hal_ticks_ms(); while (mp_hal_ticks_ms() - start < ms) { mp_handle_pending(true); UNICORN_CONTROLLER->IDLE = 1; } } void mp_hal_delay_us(mp_uint_t us) { uint32_t start = mp_hal_ticks_us(); while (mp_hal_ticks_us() - start < us) { mp_handle_pending(true); } } mp_uint_t mp_hal_ticks_us(void) { return RTC->TICKS_US; } mp_uint_t mp_hal_ticks_ms(void) { return RTC->TICKS_MS; } mp_uint_t mp_hal_ticks_cpu(void) { return UNICORN_CONTROLLER->INSNS; } ================================================ FILE: unicorn/mphalport.h ================================================ #include "py/obj.h" #include "modmachine.h" void mp_hal_delay_ms(mp_uint_t ms); void mp_hal_delay_us(mp_uint_t us); mp_uint_t mp_hal_ticks_ms(void); mp_uint_t mp_hal_ticks_us(void); mp_uint_t mp_hal_ticks_cpu(void); void mp_hal_set_interrupt_char(int c); #define MP_HAL_PIN_FMT "%q" #define mp_hal_pin_obj_t const machine_pin_obj_t* #define mp_hal_pin_name(p) ((p)->name) #define mp_hal_pin_od_low(p) pin_set((mp_obj_t)p, 0) #define mp_hal_pin_od_high(p) pin_set((mp_obj_t)p, 1) #define mp_hal_get_pin_obj(o) machine_pin_get(o) #define mp_hal_pin_read(p) (((p)->port->IDR & (1 << (p)->pin)) ? 1 : 0) #define mp_hal_pin_open_drain(p) mp_hal_pin_config((p), 0, 0, 0) static inline void mp_hal_pin_config(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint32_t alt) { } static inline void mp_hal_delay_us_fast(uint32_t us) { return; } ================================================ FILE: unicorn/pyb_adc.c ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 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 "py/runtime.h" #include "modpyb.h" #include "modmachine.h" #include "unicorn_mcu.h" typedef struct _pyb_adc_obj_t { mp_obj_base_t base; qstr pin_name; adc_t *port; mp_uint_t number; } pyb_adc_obj_t; STATIC const pyb_adc_obj_t pyb_adc_obj[] = { {{&pyb_adc_type}, MP_QSTR_X1, ADC_X, 1}, {{&pyb_adc_type}, MP_QSTR_X2, ADC_X, 2}, {{&pyb_adc_type}, MP_QSTR_X3, ADC_X, 3}, {{&pyb_adc_type}, MP_QSTR_X4, ADC_X, 4}, {{&pyb_adc_type}, MP_QSTR_X5, ADC_X, 5}, {{&pyb_adc_type}, MP_QSTR_X6, ADC_X, 6}, {{&pyb_adc_type}, MP_QSTR_X7, ADC_X, 7}, {{&pyb_adc_type}, MP_QSTR_X8, ADC_X, 8}, {{&pyb_adc_type}, MP_QSTR_X9, ADC_X, 9}, {{&pyb_adc_type}, MP_QSTR_X10, ADC_X, 10}, {{&pyb_adc_type}, MP_QSTR_X11, ADC_X, 11}, {{&pyb_adc_type}, MP_QSTR_X12, ADC_X, 12}, {{&pyb_adc_type}, MP_QSTR_Y1, ADC_Y, 1}, {{&pyb_adc_type}, MP_QSTR_Y2, ADC_Y, 2}, {{&pyb_adc_type}, MP_QSTR_Y3, ADC_Y, 3}, {{&pyb_adc_type}, MP_QSTR_Y4, ADC_Y, 4}, {{&pyb_adc_type}, MP_QSTR_Y5, ADC_Y, 5}, {{&pyb_adc_type}, MP_QSTR_Y6, ADC_Y, 6}, {{&pyb_adc_type}, MP_QSTR_Y7, ADC_Y, 7}, {{&pyb_adc_type}, MP_QSTR_Y8, ADC_Y, 8}, {{&pyb_adc_type}, MP_QSTR_Y9, ADC_Y, 9}, {{&pyb_adc_type}, MP_QSTR_Y10, ADC_Y, 10}, {{&pyb_adc_type}, MP_QSTR_Y11, ADC_Y, 11}, {{&pyb_adc_type}, MP_QSTR_Y12, ADC_Y, 12}, }; void pyb_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_printf(print, ""); } STATIC mp_obj_t pyb_adc_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, 1, false); machine_pin_obj_t *pin = machine_pin_get(args[0]); for (int i = 0; i < MP_ARRAY_SIZE(pyb_adc_obj); i++) { if (pyb_adc_obj[i].pin_name == pin->name) { return (mp_obj_t)&pyb_adc_obj[i]; } } return mp_const_none; } STATIC mp_obj_t pyb_adc_read(mp_obj_t self_in) { pyb_adc_obj_t *self = self_in; return mp_obj_new_int(self->port->IDR[self->number - 1]); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_adc_read_obj, pyb_adc_read); STATIC const mp_rom_map_elem_t pyb_adc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&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, .print = pyb_adc_print, .make_new = pyb_adc_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_adc_locals_dict, }; ================================================ FILE: unicorn/pyb_led.c ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-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 "py/nlr.h" #include "py/runtime.h" #include "modpyb.h" #include "unicorn_mcu.h" typedef struct _pyb_led_obj_t { mp_obj_base_t base; mp_uint_t led_id; } pyb_led_obj_t; STATIC const pyb_led_obj_t pyb_led_obj[] = { {{&pyb_led_type}, 1}, {{&pyb_led_type}, 2}, {{&pyb_led_type}, 3}, {{&pyb_led_type}, 4}, }; #define NUM_LEDS MP_ARRAY_SIZE(pyb_led_obj) void led_state(pyb_led_t led, int state) { if (led < 1 || led > NUM_LEDS) { return; } if (state == 0) { GPIO->ODR &= ~(1 << (led - 1)); } else { GPIO->ODR |= (1 << (led - 1)); } } void led_toggle(pyb_led_t led) { if (led < 1 || led > NUM_LEDS) { return; } GPIO->ODR ^= 1 << (led - 1); } void led_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_led_obj_t *self = self_in; mp_printf(print, "LED(%lu)", self->led_id); } STATIC mp_obj_t led_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, 1, false); // get led number mp_int_t led_id = mp_obj_get_int(args[0]); // check led number if (!(1 <= led_id && led_id <= NUM_LEDS)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "LED(%d) does not exist", led_id)); } return (mp_obj_t)&pyb_led_obj[led_id - 1]; } /// \method on() /// Turn the LED on. mp_obj_t led_obj_on(mp_obj_t self_in) { pyb_led_obj_t *self = self_in; led_state(self->led_id, 1); return mp_const_none; } /// \method off() /// Turn the LED off. mp_obj_t led_obj_off(mp_obj_t self_in) { pyb_led_obj_t *self = self_in; led_state(self->led_id, 0); return mp_const_none; } /// \method toggle() /// Toggle the LED between on and off. mp_obj_t led_obj_toggle(mp_obj_t self_in) { pyb_led_obj_t *self = self_in; led_toggle(self->led_id); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_on_obj, led_obj_on); STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_off_obj, led_obj_off); STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_toggle_obj, led_obj_toggle); STATIC const mp_rom_map_elem_t led_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&led_obj_on_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&led_obj_off_obj) }, { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&led_obj_toggle_obj) }, }; STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table); const mp_obj_type_t pyb_led_type = { { &mp_type_type }, .name = MP_QSTR_LED, .print = led_obj_print, .make_new = led_obj_make_new, .locals_dict = (mp_obj_dict_t*)&led_locals_dict, }; ================================================ FILE: unicorn/pyb_servo.c ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 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 "py/runtime.h" #include "modpyb.h" #include "unicorn_mcu.h" #define PYB_SERVO_NUM (1) typedef struct _pyb_servo_obj_t { mp_obj_base_t base; servo_t *pins; mp_uint_t servo_id; } pyb_servo_obj_t; STATIC const pyb_servo_obj_t pyb_servo_obj[] = { {{&pyb_servo_type}, SERVO_1, 1}, }; STATIC void pyb_servo_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_servo_obj_t *self = self_in; mp_printf(print, "", self->servo_id); } STATIC mp_obj_t pyb_servo_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, 1, false); mp_int_t servo_id = mp_obj_get_int(args[0]) - 1; if (!(0 <= servo_id && servo_id < PYB_SERVO_NUM)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Servo %d does not exist", servo_id + 1)); } return (mp_obj_t)&pyb_servo_obj[servo_id]; } STATIC mp_obj_t pyb_servo_angle(mp_uint_t n_args, const mp_obj_t *args) { pyb_servo_obj_t *self = args[0]; if (n_args == 1) { return mp_obj_new_int(self->pins->ANGLE); } else { self->pins->ANGLE = mp_obj_get_int(args[1]); if (n_args == 3) { self->pins->TIME = mp_obj_get_int(args[2]); } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_servo_angle_obj, 1, 3, pyb_servo_angle); STATIC const mp_rom_map_elem_t pyb_servo_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_angle), MP_ROM_PTR(&pyb_servo_angle_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_servo_locals_dict, pyb_servo_locals_dict_table); const mp_obj_type_t pyb_servo_type = { { &mp_type_type }, .name = MP_QSTR_Servo, .print = pyb_servo_print, .make_new = pyb_servo_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_servo_locals_dict, }; ================================================ FILE: unicorn/pyb_switch.c ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 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 "py/runtime.h" #include "modpyb.h" #include "unicorn_mcu.h" void switch_init0(void) { return; } int switch_get(void) { return GPIO->IDR; } typedef struct _pyb_switch_obj_t { mp_obj_base_t base; } pyb_switch_obj_t; STATIC const pyb_switch_obj_t pyb_switch_obj = {{&pyb_switch_type}}; void pyb_switch_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_print_str(print, "Switch()"); } STATIC mp_obj_t pyb_switch_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, 0, false); return (mp_obj_t)&pyb_switch_obj; } mp_obj_t pyb_switch_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 0, false); return switch_get() ? mp_const_true : mp_const_false; } STATIC mp_obj_t switch_value(mp_obj_t self_in) { return switch_get() ? mp_const_true : mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_switch_value_obj, switch_value); STATIC const mp_rom_map_elem_t pyb_switch_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&pyb_switch_value_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_switch_locals_dict, pyb_switch_locals_dict_table); const mp_obj_type_t pyb_switch_type = { { &mp_type_type }, .name = MP_QSTR_Switch, .print = pyb_switch_print, .make_new = pyb_switch_make_new, .call = pyb_switch_call, .locals_dict = (mp_obj_dict_t*)&pyb_switch_locals_dict, }; ================================================ FILE: unicorn/qstrdefsport.h ================================================ // qstrs specific to this port ================================================ FILE: unicorn/uart.c ================================================ #include #include "py/mpconfig.h" typedef struct _ucp_uart_t { volatile uint32_t TXR; volatile uint32_t RXR; } ucp_uart_t; #define UART0 ((ucp_uart_t*)0x40000000) // Receive single character int mp_hal_stdin_rx_chr(void) { unsigned char c = 0; c = UART0->RXR; return c; } // Send string of given length void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { while (len--) { UART0->TXR = *str++; } } ================================================ FILE: unicorn/unicorn.ld ================================================ /* GNU linker script for unicorn */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1M RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K /* the length is dynamically configured */ } /* top end of the stack */ /* this is dynamically configured and the correct value is at 0x08000000 */ /* _estack = ORIGIN(RAM) + LENGTH(RAM); */ /* define output sections */ SECTIONS { /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); KEEP(*(.isr_vector)) /* isr vector table */ *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); _etext = .; /* define a global symbol at end of code */ _sidata = _etext; /* This is used by the startup in order to initialize the .data secion */ } >FLASH /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). It is one task of the startup to copy the initial values from FLASH to RAM. */ .data : AT ( _sidata ) { . = ALIGN(4); _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ } >RAM /* Uninitialized data section */ .bss : { . = ALIGN(4); _sbss = .; /* define a global symbol at bss start; used by startup code */ *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end; used by startup code */ } >RAM .ARM.attributes 0 : { *(.ARM.attributes) } } ================================================ FILE: unicorn/unicorn_mcu.h ================================================ /* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 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 UNICORN_MCU #define UNICORN_MCU typedef struct _unicorn_controller_t { volatile uint32_t PENDING; volatile uint32_t EXCEPTION; volatile uint32_t INTR_CHAR; volatile uint32_t RAM_SIZE; volatile uint32_t STACK_SIZE; volatile uint32_t IDLE; volatile uint32_t INSNS; } unicorn_controller_t; #define UNICORN_CONTROLLER ((unicorn_controller_t*)0x40000100) typedef struct _gpio_t { volatile uint32_t ODR; volatile uint32_t IDR; } gpio_t; #define GPIO ((gpio_t*)0x40000200) #define GPIO_X ((gpio_t*)0x40000208) #define GPIO_Y ((gpio_t*)0x40000210) typedef struct _servo_t { volatile uint32_t ANGLE; volatile uint32_t TIME; } servo_t; #define SERVO_1 ((servo_t*)0x40000218) typedef struct _adc_t { volatile uint32_t IDR[12]; } adc_t; #define ADC_X ((adc_t*)0x40000220) #define ADC_Y ((adc_t*)0x40000250) typedef struct _rtc_t { volatile uint32_t TICKS_MS; volatile uint32_t TICKS_US; } rtc_t; #define RTC ((rtc_t*)0x40000300) typedef struct _i2c_t { volatile uint32_t DATA; volatile uint32_t COMMAND; // (0) Start bit, (1) Stop bit } i2c_t; #define I2C ((i2c_t*)0x40000400) #endif ================================================ FILE: www-emu/Makefile ================================================ BUILD = build UNICORN_BUILDS = ../unicorn/build_ IMAGES = images DEMO_GEN = demo_gen.py INDEX = index.html MP_UNICORN_JS = mp_unicorn.js MP_UNICORN_CSS = mp_unicorn.css FIRMWARE = firmware_ UNICORN_JS = unicorn-arm.min.js XTERM_JS = xterm.js XTERM_CSS = xterm.css FIT_JS = fit.js CODEMIRROR_JS = codemirror.js CODEMIRROR_CSS = codemirror.css BOOTSTRAP_CSS = bootstrap.min.css JQUERY_JS = jquery-3.2.1.min.js IMAGEMAPSTER_JS = jquery.imagemapster.min.js DEMO_SCRIPTS = demo_scripts.js # Using xterm.js release 2.6.0 and latest unicorn.js as no current release is functional XTERM_HASH = 2221f70ff05ba2af42ee0d26bed2f75dafe2d116 UNICORN_JS_LINK = https://raw.githubusercontent.com/AlexAltea/unicorn.js/master/dist/$(UNICORN_JS) XTERM_JS_LINK = https://raw.githubusercontent.com/sourcelair/xterm.js/$(XTERM_HASH)/dist/$(XTERM_JS) XTERM_CSS_LINK = https://raw.githubusercontent.com/sourcelair/xterm.js/$(XTERM_HASH)/dist/$(XTERM_CSS) FIT_JS_LINK = https://raw.githubusercontent.com/sourcelair/xterm.js/$(XTERM_HASH)/dist/addons/fit/$(FIT_JS) all: gzip gzip: $(BUILD) $(BUILD)/$(UNICORN_JS).gz $(BUILD)/$(XTERM_JS).gz $(BUILD)/$(XTERM_CSS).gz $(BUILD)/$(FIT_JS).gz $(BUILD)/$(CODEMIRROR_JS).gz $(BUILD)/$(CODEMIRROR_CSS).gz $(BUILD)/$(BOOTSTRAP_CSS).gz $(BUILD)/$(JQUERY_JS).gz $(BUILD)/$(IMAGEMAPSTER_JS).gz copy rm -f $(BUILD)/$(MP_UNICORN_JS).gz gzip $(BUILD)/$(MP_UNICORN_JS) # Make clean before switching between gzip and nogzip builds nogzip: $(BUILD) $(BUILD)/$(UNICORN_JS) $(BUILD)/$(XTERM_JS) $(BUILD)/$(XTERM_CSS) $(BUILD)/$(FIT_JS) $(BUILD)/$(CODEMIRROR_JS) $(BUILD)/$(CODEMIRROR_CSS) $(BUILD)/$(BOOTSTRAP_CSS) $(BUILD)/$(JQUERY_JS) $(BUILD)/$(IMAGEMAPSTER_JS) copy copy: cp $(INDEX) $(BUILD) cp $(MP_UNICORN_JS) $(BUILD) cp $(MP_UNICORN_CSS) $(BUILD) cp -r $(IMAGES) $(BUILD) -cp $(UNICORN_BUILDS)*/$(FIRMWARE)*.bin $(BUILD) python $(DEMO_GEN) mv $(DEMO_SCRIPTS) $(BUILD) $(BUILD): mkdir $(BUILD) $(BUILD)/$(UNICORN_JS): wget -P $(BUILD) $(UNICORN_JS_LINK) $(BUILD)/$(UNICORN_JS).gz: wget -P $(BUILD) $(UNICORN_JS_LINK) gzip $(BUILD)/$(UNICORN_JS) $(BUILD)/$(XTERM_JS): wget -P $(BUILD) $(XTERM_JS_LINK) $(BUILD)/$(XTERM_JS).gz: wget -P $(BUILD) $(XTERM_JS_LINK) gzip $(BUILD)/$(XTERM_JS) $(BUILD)/$(XTERM_CSS): wget -P $(BUILD) $(XTERM_CSS_LINK) $(BUILD)/$(XTERM_CSS).gz: wget -P $(BUILD) $(XTERM_CSS_LINK) gzip $(BUILD)/$(XTERM_CSS) $(BUILD)/$(FIT_JS): wget -P $(BUILD) $(FIT_JS_LINK) $(BUILD)/$(FIT_JS).gz: wget -P $(BUILD) $(FIT_JS_LINK) gzip $(BUILD)/$(FIT_JS) $(BUILD)/$(CODEMIRROR_JS): cp $(CODEMIRROR_JS) $(BUILD) $(BUILD)/$(CODEMIRROR_JS).gz: cp $(CODEMIRROR_JS) $(BUILD) gzip $(BUILD)/$(CODEMIRROR_JS) $(BUILD)/$(CODEMIRROR_CSS): cp $(CODEMIRROR_CSS) $(BUILD) $(BUILD)/$(CODEMIRROR_CSS).gz: cp $(CODEMIRROR_CSS) $(BUILD) gzip $(BUILD)/$(CODEMIRROR_CSS) $(BUILD)/$(BOOTSTRAP_CSS): cp $(BOOTSTRAP_CSS) $(BUILD) $(BUILD)/$(BOOTSTRAP_CSS).gz: cp $(BOOTSTRAP_CSS) $(BUILD) gzip $(BUILD)/$(BOOTSTRAP_CSS) $(BUILD)/$(JQUERY_JS): cp $(JQUERY_JS) $(BUILD) $(BUILD)/$(JQUERY_JS).gz: cp $(JQUERY_JS) $(BUILD) gzip $(BUILD)/$(JQUERY_JS) $(BUILD)/$(IMAGEMAPSTER_JS): cp $(IMAGEMAPSTER_JS) $(BUILD) $(BUILD)/$(IMAGEMAPSTER_JS).gz: cp $(IMAGEMAPSTER_JS) $(BUILD) gzip $(BUILD)/$(IMAGEMAPSTER_JS) .PHONY: clean clean: rm -rf $(BUILD) ================================================ FILE: www-emu/codemirror.css ================================================ /* BASICS */ .CodeMirror { /* Set height, width, borders, and global font properties here */ font-family: monospace; height: 300px; } /* PADDING */ .CodeMirror-lines { padding: 4px 0; /* Vertical padding around content */ } .CodeMirror pre { padding: 0 4px; /* Horizontal padding of content */ } .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { background-color: white; /* The little square between H and V scrollbars */ } /* GUTTER */ .CodeMirror-gutters { border-right: 1px solid #ddd; background-color: #f7f7f7; white-space: nowrap; } .CodeMirror-linenumbers {} .CodeMirror-linenumber { padding: 0 3px 0 5px; min-width: 20px; text-align: right; color: #999; -moz-box-sizing: content-box; box-sizing: content-box; } .CodeMirror-guttermarker { color: black; } .CodeMirror-guttermarker-subtle { color: #999; } /* CURSOR */ .CodeMirror div.CodeMirror-cursor { border-left: 1px solid black; } /* Shown when moving in bi-directional text */ .CodeMirror div.CodeMirror-secondarycursor { border-left: 1px solid silver; } .CodeMirror.cm-fat-cursor div.CodeMirror-cursor { width: auto; border: 0; background: #7e7; } .CodeMirror.cm-fat-cursor div.CodeMirror-cursors { z-index: 1; } .cm-animate-fat-cursor { width: auto; border: 0; -webkit-animation: blink 1.06s steps(1) infinite; -moz-animation: blink 1.06s steps(1) infinite; animation: blink 1.06s steps(1) infinite; } @-moz-keyframes blink { 0% { background: #7e7; } 50% { background: none; } 100% { background: #7e7; } } @-webkit-keyframes blink { 0% { background: #7e7; } 50% { background: none; } 100% { background: #7e7; } } @keyframes blink { 0% { background: #7e7; } 50% { background: none; } 100% { background: #7e7; } } /* Can style cursor different in overwrite (non-insert) mode */ div.CodeMirror-overwrite div.CodeMirror-cursor {} .cm-tab { display: inline-block; text-decoration: inherit; } .CodeMirror-ruler { border-left: 1px solid #ccc; position: absolute; } /* DEFAULT THEME */ .cm-s-default .cm-keyword {color: #708;} .cm-s-default .cm-atom {color: #219;} .cm-s-default .cm-number {color: #164;} .cm-s-default .cm-def {color: #00f;} .cm-s-default .cm-variable, .cm-s-default .cm-punctuation, .cm-s-default .cm-property, .cm-s-default .cm-operator {} .cm-s-default .cm-variable-2 {color: #05a;} .cm-s-default .cm-variable-3 {color: #085;} .cm-s-default .cm-comment {color: #a50;} .cm-s-default .cm-string {color: #a11;} .cm-s-default .cm-string-2 {color: #f50;} .cm-s-default .cm-meta {color: #555;} .cm-s-default .cm-qualifier {color: #555;} .cm-s-default .cm-builtin {color: #30a;} .cm-s-default .cm-bracket {color: #997;} .cm-s-default .cm-tag {color: #170;} .cm-s-default .cm-attribute {color: #00c;} .cm-s-default .cm-header {color: blue;} .cm-s-default .cm-quote {color: #090;} .cm-s-default .cm-hr {color: #999;} .cm-s-default .cm-link {color: #00c;} .cm-negative {color: #d44;} .cm-positive {color: #292;} .cm-header, .cm-strong {font-weight: bold;} .cm-em {font-style: italic;} .cm-link {text-decoration: underline;} .cm-strikethrough {text-decoration: line-through;} .cm-s-default .cm-error {color: #f00;} .cm-invalidchar {color: #f00;} /* Default styles for common addons */ div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } .CodeMirror-activeline-background {background: #e8f2ff;} /* STOP */ /* The rest of this file contains styles related to the mechanics of the editor. You probably shouldn't touch them. */ .CodeMirror { line-height: 1; position: relative; overflow: hidden; background: white; color: black; } .CodeMirror-scroll { overflow: scroll !important; /* Things will break if this is overridden */ /* 30px is the magic margin used to hide the element's real scrollbars */ /* See overflow: hidden in .CodeMirror */ margin-bottom: -30px; margin-right: -30px; padding-bottom: 30px; height: 100%; outline: none; /* Prevent dragging from highlighting the element */ position: relative; -moz-box-sizing: content-box; box-sizing: content-box; } .CodeMirror-sizer { position: relative; border-right: 30px solid transparent; -moz-box-sizing: content-box; box-sizing: content-box; } /* The fake, visible scrollbars. Used to force redraw during scrolling before actuall scrolling happens, thus preventing shaking and flickering artifacts. */ .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { position: absolute; z-index: 6; display: none; } .CodeMirror-vscrollbar { right: 0; top: 0; overflow-x: hidden; overflow-y: scroll; } .CodeMirror-hscrollbar { bottom: 0; left: 0; overflow-y: hidden; overflow-x: scroll; } .CodeMirror-scrollbar-filler { right: 0; bottom: 0; } .CodeMirror-gutter-filler { left: 0; bottom: 0; } .CodeMirror-gutters { position: absolute; left: 0; top: 0; z-index: 3; } .CodeMirror-gutter { white-space: normal; height: 100%; -moz-box-sizing: content-box; box-sizing: content-box; display: inline-block; margin-bottom: -30px; /* Hack to make IE7 behave */ *zoom:1; *display:inline; } .CodeMirror-gutter-wrapper { position: absolute; z-index: 4; height: 100%; } .CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4; } .CodeMirror-lines { cursor: text; min-height: 1px; /* prevents collapsing before first draw */ } .CodeMirror pre { /* Reset some styles that the rest of the page might have set */ -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; border-width: 0; background: transparent; font-family: inherit; font-size: inherit; margin: 0; white-space: pre; word-wrap: normal; line-height: inherit; color: inherit; z-index: 2; position: relative; overflow: visible; } .CodeMirror-wrap pre { word-wrap: break-word; white-space: pre-wrap; word-break: normal; } .CodeMirror-linebackground { position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 0; } .CodeMirror-linewidget { position: relative; z-index: 2; overflow: auto; } .CodeMirror-widget {} .CodeMirror-measure { position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden; } .CodeMirror-measure pre { position: static; } .CodeMirror div.CodeMirror-cursor { position: absolute; border-right: none; width: 0; } div.CodeMirror-cursors { visibility: hidden; position: relative; z-index: 3; } .CodeMirror-focused div.CodeMirror-cursors { visibility: visible; } .CodeMirror-selected { background: #d9d9d9; } .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } .CodeMirror-crosshair { cursor: crosshair; } .cm-searching { background: #ffa; background: rgba(255, 255, 0, .4); } /* IE7 hack to prevent it from returning funny offsetTops on the spans */ .CodeMirror span { *vertical-align: text-bottom; } /* Used to force a border model for a node */ .cm-force-border { padding-right: .1px; } @media print { /* Hide the cursor when printing */ .CodeMirror div.CodeMirror-cursors { visibility: hidden; } } /* See issue #2901 */ .cm-tab-wrap-hack:after { content: ''; } /* Help users use markselection to safely style text background */ span.CodeMirror-selectedtext { background: none; } ================================================ FILE: www-emu/codemirror.js ================================================ /* CodeMirror - Minified & Bundled Generated on 27/12/2014 with http://codemirror.net/doc/compress.html Version: HEAD CodeMirror Library: - codemirror.js Modes: - python.js */ !function(a){if("object"==typeof exports&&"object"==typeof module)module.exports=a();else{if("function"==typeof define&&define.amd)return define([],a);this.CodeMirror=a()}}(function(){"use strict";function w(a,b){if(!(this instanceof w))return new w(a,b);this.options=b=b?Xg(b):{},Xg(pe,b,!1),J(b);var c=b.value;"string"==typeof c&&(c=new Sf(c,b.mode)),this.doc=c;var f=this.display=new x(a,c);f.wrapper.CodeMirror=this,F(this),D(this),b.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),b.autofocus&&!o&&fd(this),N(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,draggingText:!1,highlight:new Ng,keySeq:null},d&&11>e&&setTimeout(Yg(ed,this,!0),20),id(this),ph(),Gc(this),this.curOp.forceUpdate=!0,Wf(this,c),b.autofocus&&!o||ih()==f.input?setTimeout(Yg(Od,this),20):Pd(this);for(var g in qe)qe.hasOwnProperty(g)&&qe[g](this,b[g],se);S(this);for(var h=0;he&&(c.gutters.style.zIndex=-1,c.scroller.style.paddingRight=0),n&&(g.style.width="0px"),f||(c.scroller.draggable=!0),k&&(c.inputDiv.style.height="1px",c.inputDiv.style.position="absolute"),a&&(a.appendChild?a.appendChild(c.wrapper):a(c.wrapper)),c.viewFrom=c.viewTo=b.first,c.reportedViewFrom=c.reportedViewTo=b.first,c.view=[],c.renderedView=null,c.externalMeasured=null,c.viewOffset=0,c.lastWrapHeight=c.lastWrapWidth=0,c.updateLineNumbers=null,c.nativeBarWidth=c.barHeight=c.barWidth=0,c.scrollbarsClipped=!1,c.lineNumWidth=c.lineNumInnerWidth=c.lineNumChars=null,c.prevInput="",c.alignWidgets=!1,c.pollingFast=!1,c.poll=new Ng,c.cachedCharWidth=c.cachedTextHeight=c.cachedPaddingH=null,c.inaccurateSelection=!1,c.maxLine=null,c.maxLineLength=0,c.maxLineChanged=!1,c.wheelDX=c.wheelDY=c.wheelStartX=c.wheelStartY=null,c.shift=!1,c.selForContextMenu=null}function y(a){a.doc.mode=w.getMode(a.options,a.doc.modeOption),z(a)}function z(a){a.doc.iter(function(a){a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null)}),a.doc.frontier=a.doc.first,Wb(a,100),a.state.modeGen++,a.curOp&&Vc(a)}function A(a){a.options.lineWrapping?(lh(a.display.wrapper,"CodeMirror-wrap"),a.display.sizer.style.minWidth="",a.display.sizerWidth=null):(kh(a.display.wrapper,"CodeMirror-wrap"),I(a)),C(a),Vc(a),qc(a),setTimeout(function(){O(a)},100)}function B(a){var b=Cc(a.display),c=a.options.lineWrapping,d=c&&Math.max(5,a.display.scroller.clientWidth/Dc(a.display)-3);return function(e){if(mf(a.doc,e))return 0;var f=0;if(e.widgets)for(var g=0;gb.maxLineLength&&(b.maxLineLength=c,b.maxLine=a)})}function J(a){var b=Ug(a.gutters,"CodeMirror-linenumbers");-1==b&&a.lineNumbers?a.gutters=a.gutters.concat(["CodeMirror-linenumbers"]):b>-1&&!a.lineNumbers&&(a.gutters=a.gutters.slice(0),a.gutters.splice(b,1))}function K(a){var b=a.display,c=b.gutters.offsetWidth,d=Math.round(a.doc.height+_b(a.display));return{clientHeight:b.scroller.clientHeight,viewHeight:b.wrapper.clientHeight,scrollWidth:b.scroller.scrollWidth,clientWidth:b.scroller.clientWidth,viewWidth:b.wrapper.clientWidth,barLeft:a.options.fixedGutter?c:0,docHeight:d,scrollHeight:d+bc(a)+b.barHeight,nativeBarWidth:b.nativeBarWidth,gutterWidth:c}}function L(a,b,c){this.cm=c;var f=this.vert=dh("div",[dh("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),g=this.horiz=dh("div",[dh("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");a(f),a(g),yg(f,"scroll",function(){f.clientHeight&&b(f.scrollTop,"vertical")}),yg(g,"scroll",function(){g.clientWidth&&b(g.scrollLeft,"horizontal")}),this.checkedOverlay=!1,d&&8>e&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")}function M(){}function N(a){a.display.scrollbars&&(a.display.scrollbars.clear(),a.display.scrollbars.addClass&&kh(a.display.wrapper,a.display.scrollbars.addClass)),a.display.scrollbars=new w.scrollbarModel[a.options.scrollbarStyle](function(b){a.display.wrapper.insertBefore(b,a.display.scrollbarFiller),yg(b,"mousedown",function(){a.state.focused&&setTimeout(Yg(fd,a),0)}),b.setAttribute("not-content","true")},function(b,c){"horizontal"==c?yd(a,b):xd(a,b)},a),a.display.scrollbars.addClass&&lh(a.display.wrapper,a.display.scrollbars.addClass)}function O(a,b){b||(b=K(a));var c=a.display.barWidth,d=a.display.barHeight;P(a,b);for(var e=0;4>e&&c!=a.display.barWidth||d!=a.display.barHeight;e++)c!=a.display.barWidth&&a.options.lineWrapping&&_(a),P(a,K(a)),c=a.display.barWidth,d=a.display.barHeight}function P(a,b){var c=a.display,d=c.scrollbars.update(b);c.sizer.style.paddingRight=(c.barWidth=d.right)+"px",c.sizer.style.paddingBottom=(c.barHeight=d.bottom)+"px",d.right&&d.bottom?(c.scrollbarFiller.style.display="block",c.scrollbarFiller.style.height=d.bottom+"px",c.scrollbarFiller.style.width=d.right+"px"):c.scrollbarFiller.style.display="",d.bottom&&a.options.coverGutterNextToScrollbar&&a.options.fixedGutter?(c.gutterFiller.style.display="block",c.gutterFiller.style.height=d.bottom+"px",c.gutterFiller.style.width=b.gutterWidth+"px"):c.gutterFiller.style.display=""}function Q(a,b,c){var d=c&&null!=c.top?Math.max(0,c.top):a.scroller.scrollTop;d=Math.floor(d-$b(a));var e=c&&null!=c.bottom?c.bottom:d+a.wrapper.clientHeight,f=ag(b,d),g=ag(b,e);if(c&&c.ensure){var h=c.ensure.from.line,i=c.ensure.to.line;f>h?(f=h,g=ag(b,bg(Xf(b,h))+a.wrapper.clientHeight)):Math.min(i,b.lastLine())>=g&&(f=ag(b,bg(Xf(b,i))-a.wrapper.clientHeight),g=i)}return{from:f,to:Math.max(g,f+1)}}function R(a){var b=a.display,c=b.view;if(b.alignWidgets||b.gutters.firstChild&&a.options.fixedGutter){for(var d=U(b)-b.scroller.scrollLeft+a.doc.scrollLeft,e=b.gutters.offsetWidth,f=d+"px",g=0;g=c.viewFrom&&b.visible.to<=c.viewTo&&(null==c.updateLineNumbers||c.updateLineNumbers>=c.viewTo)&&c.renderedView==c.view&&0==_c(a))return!1;S(a)&&(Xc(a),b.dims=bb(a));var e=d.first+d.size,f=Math.max(b.visible.from-a.options.viewportMargin,d.first),g=Math.min(e,b.visible.to+a.options.viewportMargin);c.viewFromg&&c.viewTo-g<20&&(g=Math.min(e,c.viewTo)),v&&(f=kf(a.doc,f),g=lf(a.doc,g));var h=f!=c.viewFrom||g!=c.viewTo||c.lastWrapHeight!=b.wrapperHeight||c.lastWrapWidth!=b.wrapperWidth;$c(a,f,g),c.viewOffset=bg(Xf(a.doc,c.viewFrom)),a.display.mover.style.top=c.viewOffset+"px";var i=_c(a);if(!h&&0==i&&!b.force&&c.renderedView==c.view&&(null==c.updateLineNumbers||c.updateLineNumbers>=c.viewTo))return!1;var j=ih();return i>4&&(c.lineDiv.style.display="none"),cb(a,c.updateLineNumbers,b.dims),i>4&&(c.lineDiv.style.display=""),c.renderedView=c.view,j&&ih()!=j&&j.offsetHeight&&j.focus(),fh(c.cursorDiv),fh(c.selectionDiv),c.heightForcer.style.top=c.gutters.style.height=0,h&&(c.lastWrapHeight=b.wrapperHeight,c.lastWrapWidth=b.wrapperWidth,Wb(a,400)),c.updateLineNumbers=null,!0}function Y(a,b){for(var c=b.force,d=b.viewport,e=!0;;e=!1){if(e&&a.options.lineWrapping&&b.oldDisplayWidth!=cc(a))c=!0;else if(c=!1,d&&null!=d.top&&(d={top:Math.min(a.doc.height+_b(a.display)-dc(a),d.top)}),b.visible=Q(a.display,a.doc,d),b.visible.from>=a.display.viewFrom&&b.visible.to<=a.display.viewTo)break;if(!X(a,b))break;_(a);var f=K(a);Sb(a),$(a,f),O(a,f)}Cg(a,"update",a),(a.display.viewFrom!=a.display.reportedViewFrom||a.display.viewTo!=a.display.reportedViewTo)&&(Cg(a,"viewportChange",a,a.display.viewFrom,a.display.viewTo),a.display.reportedViewFrom=a.display.viewFrom,a.display.reportedViewTo=a.display.viewTo)}function Z(a,b){var c=new V(a,b);if(X(a,c)){_(a),Y(a,c);var d=K(a);Sb(a),$(a,d),O(a,d)}}function $(a,b){a.display.sizer.style.minHeight=a.display.heightForcer.style.top=b.docHeight+"px",a.display.gutters.style.height=Math.max(b.docHeight+bc(a),b.clientHeight)+"px"}function _(a){for(var b=a.display,c=b.lineDiv.offsetTop,f=0;fe){var i=g.node.offsetTop+g.node.offsetHeight;h=i-c,c=i}else{var j=g.node.getBoundingClientRect();h=j.bottom-j.top}var k=g.line.height-h;if(2>h&&(h=Cc(b)),(k>.001||-.001>k)&&($f(g.line,h),ab(g.line),g.rest))for(var l=0;l=b&&m.lineNumber;m.changes&&(Ug(m.changes,"gutter")>-1&&(o=!1),db(a,m,k,c)),o&&(fh(m.lineNumber),m.lineNumber.appendChild(document.createTextNode(T(a.options,k)))),h=m.node.nextSibling}else{var n=lb(a,m,k,c);g.insertBefore(n,h)}k+=m.size}for(;h;)h=i(h)}function db(a,b,c,d){for(var e=0;ee&&(a.node.style.zIndex=2)),a.node}function fb(a){var b=a.bgClass?a.bgClass+" "+(a.line.bgClass||""):a.line.bgClass;if(b&&(b+=" CodeMirror-linebackground"),a.background)b?a.background.className=b:(a.background.parentNode.removeChild(a.background),a.background=null);else if(b){var c=eb(a);a.background=c.insertBefore(dh("div",null,b),c.firstChild)}}function gb(a,b){var c=a.display.externalMeasured;return c&&c.line==b.line?(a.display.externalMeasured=null,b.measure=c.measure,c.built):Gf(a,b)}function hb(a,b){var c=b.text.className,d=gb(a,b);b.text==b.node&&(b.node=d.pre),b.text.parentNode.replaceChild(d.pre,b.text),b.text=d.pre,d.bgClass!=b.bgClass||d.textClass!=b.textClass?(b.bgClass=d.bgClass,b.textClass=d.textClass,ib(b)):c&&(b.text.className=c)}function ib(a){fb(a),a.line.wrapClass?eb(a).className=a.line.wrapClass:a.node!=a.text&&(a.node.className="");var b=a.textClass?a.textClass+" "+(a.line.textClass||""):a.line.textClass;a.text.className=b||""}function jb(a,b,c,d){b.gutter&&(b.node.removeChild(b.gutter),b.gutter=null);var e=b.line.gutterMarkers;if(a.options.lineNumbers||e){var f=eb(b),g=b.gutter=f.insertBefore(dh("div",null,"CodeMirror-gutter-wrapper","left: "+(a.options.fixedGutter?d.fixedPos:-d.gutterTotalWidth)+"px; width: "+d.gutterTotalWidth+"px"),b.text);if(b.line.gutterClass&&(g.className+=" "+b.line.gutterClass),!a.options.lineNumbers||e&&e["CodeMirror-linenumbers"]||(b.lineNumber=g.appendChild(dh("div",T(a.options,c),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+d.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+a.display.lineNumInnerWidth+"px"))),e)for(var h=0;h=0){var g=tb(f.from(),e.from()),h=sb(f.to(),e.to()),i=f.empty()?e.from()==e.head:f.from()==f.head;b>=d&&--b,a.splice(--d,2,new vb(i?h:g,i?g:h))}}return new ub(a,b)}function xb(a,b){return new ub([new vb(a,b||a)],0)}function yb(a,b){return Math.max(a.first,Math.min(b,a.first+a.size-1))}function zb(a,b){if(b.linec?pb(c,Xf(a,c).text.length):Ab(b,Xf(a,b.line).text.length)}function Ab(a,b){var c=a.ch;return null==c||c>b?pb(a.line,b):0>c?pb(a.line,0):a}function Bb(a,b){return b>=a.first&&b=f.ch:j.to>f.ch))){if(d&&(Ag(k,"beforeCursorEnter"),k.explicitlyCleared)){if(h.markedSpans){--i;continue}break}if(!k.atomic)continue;var l=k.find(0>g?-1:1);if(0==qb(l,f)&&(l.ch+=g,l.ch<0?l=l.line>a.first?zb(a,pb(l.line-1)):null:l.ch>h.text.length&&(l=l.lineb&&(b=0),b=Math.round(b),d=Math.round(d),f.appendChild(dh("div",null,"CodeMirror-selected","position: absolute; left: "+a+"px; top: "+b+"px; width: "+(null==c?i-a:c)+"px; height: "+(d-b)+"px"))}function k(b,c,d){function m(c,d){return vc(a,pb(b,c),"div",f,d)}var k,l,f=Xf(e,b),g=f.text.length;return Ch(cg(f),c||0,null==d?g:d,function(a,b,e){var n,o,p,f=m(a,"left");if(a==b)n=f,o=p=f.left;else{if(n=m(b-1,"right"),"rtl"==e){var q=f;f=n,n=q}o=f.left,p=n.right}null==c&&0==a&&(o=h),n.top-f.top>3&&(j(o,f.top,null,f.bottom),o=h,f.bottoml.bottom||n.bottom==l.bottom&&n.right>l.right)&&(l=n),h+1>o&&(o=h),j(o,n.top,p-o,n.bottom)}),{start:k,end:l}}var d=a.display,e=a.doc,f=document.createDocumentFragment(),g=ac(a.display),h=g.left,i=Math.max(d.sizerWidth,cc(a)-d.sizer.offsetLeft)-g.right,l=b.from(),m=b.to();if(l.line==m.line)k(l.line,l.ch,m.ch);else{var n=Xf(e,l.line),o=Xf(e,m.line),p=hf(n)==hf(o),q=k(l.line,l.ch,p?n.text.length+1:null).end,r=k(m.line,p?0:null,m.ch).start;p&&(q.top0?b.blinker=setInterval(function(){b.cursorDiv.style.visibility=(c=!c)?"":"hidden"},a.options.cursorBlinkRate):a.options.cursorBlinkRate<0&&(b.cursorDiv.style.visibility="hidden")}}function Wb(a,b){a.doc.mode.startState&&a.doc.frontier=a.display.viewTo)){var c=+new Date+a.options.workTime,d=ye(b.mode,Zb(a,b.frontier)),e=[];b.iter(b.frontier,Math.min(b.first+b.size,a.display.viewTo+500),function(f){if(b.frontier>=a.display.viewFrom){var g=f.styles,h=Af(a,f,d,!0);f.styles=h.styles;var i=f.styleClasses,j=h.classes;j?f.styleClasses=j:i&&(f.styleClasses=null);for(var k=!g||g.length!=f.styles.length||i!=j&&(!i||!j||i.bgClass!=j.bgClass||i.textClass!=j.textClass),l=0;!k&&lc?(Wb(a,a.options.workDelay),!0):void 0}),e.length&&Pc(a,function(){for(var b=0;bg;--h){if(h<=f.first)return f.first;var i=Xf(f,h-1);if(i.stateAfter&&(!c||h<=f.frontier))return h;var j=Og(i.text,null,a.options.tabSize);(null==e||d>j)&&(e=h-1,d=j)}return e}function Zb(a,b,c){var d=a.doc,e=a.display;if(!d.mode.startState)return!0;var f=Yb(a,b,c),g=f>d.first&&Xf(d,f-1).stateAfter;return g=g?ye(d.mode,g):ze(d.mode),d.iter(f,b,function(c){Cf(a,c.text,g);var h=f==b-1||0==f%5||f>=e.viewFrom&&f2&&f.push((i.bottom+j.top)/2-c.top)}}f.push(c.bottom-c.top)}}function fc(a,b,c){if(a.line==b)return{map:a.measure.map,cache:a.measure.cache};for(var d=0;dc)return{map:a.measure.maps[d],cache:a.measure.caches[d],before:!0}}function gc(a,b){b=hf(b);var c=_f(b),d=a.display.externalMeasured=new Tc(a.doc,b,c);d.lineN=c;var e=d.built=Gf(a,d);return d.text=e.pre,gh(a.display.lineMeasure,e.pre),d}function hc(a,b,c,d){return kc(a,jc(a,b),c,d)}function ic(a,b){if(b>=a.display.viewFrom&&b=c.lineN&&bc?(i=0,j=1,k="left"):n>c?(i=c-m,j=i+1):(l==g.length-3||c==n&&g[l+3]>c)&&(j=n-m,i=j-1,c>=n&&(k="right")),null!=i){if(h=g[l+2],m==n&&f==(h.insertLeft?"left":"right")&&(k=f),"left"==f&&0==i)for(;l&&g[l-2]==g[l-3]&&g[l-1].insertLeft;)h=g[(l-=3)+2],k="left";if("right"==f&&i==n-m)for(;ll;l++){for(;i&&ch(b.line.text.charAt(m+i));)--i;for(;n>m+j&&ch(b.line.text.charAt(m+j));)++j;if(d&&9>e&&0==i&&j==n-m)o=h.parentNode.getBoundingClientRect();else if(d&&a.options.lineWrapping){var p=eh(h,i,j).getClientRects();o=p.length?p["right"==f?p.length-1:0]:lc}else o=eh(h,i,j).getBoundingClientRect()||lc;if(o.left||o.right||0==i)break;j=i,i-=1,k="right"}d&&11>e&&(o=nc(a.display.measure,o))}else{i>0&&(k=f="right");var p;o=a.options.lineWrapping&&(p=h.getClientRects()).length>1?p["right"==f?p.length-1:0]:h.getBoundingClientRect()}if(d&&9>e&&!i&&(!o||!o.left&&!o.right)){var q=h.parentNode.getClientRects()[0];o=q?{left:q.left,right:q.left+Dc(a.display),top:q.top,bottom:q.bottom}:lc}for(var r=o.top-b.rect.top,s=o.bottom-b.rect.top,t=(r+s)/2,u=b.view.measure.heights,l=0;lc.from?g(a-1):g(a,d)}d=d||Xf(a.doc,b.line),e||(e=jc(a,d));var i=cg(d),j=b.ch;if(!i)return g(j);var k=Mh(i,j),l=h(j,k);return null!=Lh&&(l.other=h(j,Lh)),l}function xc(a,b){var c=0,b=zb(a.doc,b);a.options.lineWrapping||(c=Dc(a.display)*b.ch);var d=Xf(a.doc,b.line),e=bg(d)+$b(a.display);return{left:c,right:c,top:e,bottom:e+d.height}}function yc(a,b,c,d){var e=pb(a,b);return e.xRel=d,c&&(e.outside=!0),e}function zc(a,b,c){var d=a.doc;if(c+=a.display.viewOffset,0>c)return yc(d.first,0,!0,-1);var e=ag(d,c),f=d.first+d.size-1;if(e>f)return yc(d.first+d.size-1,Xf(d,f).text.length,!0,1);0>b&&(b=0);for(var g=Xf(d,e);;){var h=Ac(a,g,e,b,c),i=ff(g),j=i&&i.find(0,!0);if(!i||!(h.ch>j.from.ch||h.ch==j.from.ch&&h.xRel>0))return h;e=_f(g=j.to.line)}}function Ac(a,b,c,d,e){function j(d){var e=wc(a,pb(c,d),"line",b,i);return g=!0,f>e.bottom?e.left-h:fq)return yc(c,n,r,1);for(;;){if(k?n==m||n==Oh(b,m,1):1>=n-m){for(var s=o>d||q-d>=d-o?m:n,t=d-(s==m?o:q);ch(b.text.charAt(s));)++s;var u=yc(c,s,s==m?p:r,-1>t?-1:t>1?1:0);return u}var v=Math.ceil(l/2),w=m+v;if(k){w=m;for(var x=0;v>x;++x)w=Oh(b,w,1)}var y=j(w);y>d?(n=w,q=y,(r=g)&&(q+=1e3),l=v):(m=w,o=y,p=g,l-=v)}}function Cc(a){if(null!=a.cachedTextHeight)return a.cachedTextHeight;if(null==Bc){Bc=dh("pre");for(var b=0;49>b;++b)Bc.appendChild(document.createTextNode("x")),Bc.appendChild(dh("br"));Bc.appendChild(document.createTextNode("x"))}gh(a.measure,Bc);var c=Bc.offsetHeight/50;return c>3&&(a.cachedTextHeight=c),fh(a.measure),c||1}function Dc(a){if(null!=a.cachedCharWidth)return a.cachedCharWidth;var b=dh("span","xxxxxxxxxx"),c=dh("pre",[b]);gh(a.measure,c);var d=b.getBoundingClientRect(),e=(d.right-d.left)/10;return e>2&&(a.cachedCharWidth=e),e||10}function Gc(a){a.curOp={cm:a,viewChanged:!1,startHeight:a.doc.height,forceUpdate:!1,updateInput:null,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,id:++Fc},Ec?Ec.ops.push(a.curOp):a.curOp.ownsGroup=Ec={ops:[a.curOp],delayedCallbacks:[]} }function Hc(a){var b=a.delayedCallbacks,c=0;do{for(;c=c.viewTo)||c.maxLineChanged&&b.options.lineWrapping,a.update=a.mustUpdate&&new V(b,a.mustUpdate&&{top:a.scrollTop,ensure:a.scrollToPos},a.forceUpdate)}function Lc(a){a.updatedDisplay=a.mustUpdate&&X(a.cm,a.update)}function Mc(a){var b=a.cm,c=b.display;a.updatedDisplay&&_(b),a.barMeasure=K(b),c.maxLineChanged&&!b.options.lineWrapping&&(a.adjustWidthTo=hc(b,c.maxLine,c.maxLine.text.length).left+3,b.display.sizerWidth=a.adjustWidthTo,a.barMeasure.scrollWidth=Math.max(c.scroller.clientWidth,c.sizer.offsetLeft+a.adjustWidthTo+bc(b)+b.display.barWidth),a.maxScrollLeft=Math.max(0,c.sizer.offsetLeft+a.adjustWidthTo-cc(b))),(a.updatedDisplay||a.selectionChanged)&&(a.newSelectionNodes=Qb(b))}function Nc(a){var b=a.cm;null!=a.adjustWidthTo&&(b.display.sizer.style.minWidth=a.adjustWidthTo+"px",a.maxScrollLeftf;f=e){var g=new Tc(a.doc,Xf(a.doc,f),f);e=f+g.size,d.push(g)}return d}function Vc(a,b,c,d){null==b&&(b=a.doc.first),null==c&&(c=a.doc.first+a.doc.size),d||(d=0);var e=a.display;if(d&&cb)&&(e.updateLineNumbers=b),a.curOp.viewChanged=!0,b>=e.viewTo)v&&kf(a.doc,b)e.viewFrom?Xc(a):(e.viewFrom+=d,e.viewTo+=d);else if(b<=e.viewFrom&&c>=e.viewTo)Xc(a);else if(b<=e.viewFrom){var f=Zc(a,c,c+d,1);f?(e.view=e.view.slice(f.index),e.viewFrom=f.lineN,e.viewTo+=d):Xc(a)}else if(c>=e.viewTo){var f=Zc(a,b,b,-1);f?(e.view=e.view.slice(0,f.index),e.viewTo=f.lineN):Xc(a)}else{var g=Zc(a,b,b,-1),h=Zc(a,c,c+d,1);g&&h?(e.view=e.view.slice(0,g.index).concat(Uc(a,g.lineN,h.lineN)).concat(e.view.slice(h.index)),e.viewTo+=d):Xc(a)}var i=e.externalMeasured;i&&(c=e.lineN&&b=d.viewTo)){var f=d.view[Yc(a,b)];if(null!=f.node){var g=f.changes||(f.changes=[]);-1==Ug(g,c)&&g.push(c)}}}function Xc(a){a.display.viewFrom=a.display.viewTo=a.doc.first,a.display.view=[],a.display.viewOffset=0}function Yc(a,b){if(b>=a.display.viewTo)return null;if(b-=a.display.viewFrom,0>b)return null;for(var c=a.display.view,d=0;db)return d}function Zc(a,b,c,d){var f,e=Yc(a,b),g=a.display.view;if(!v||c==a.doc.first+a.doc.size)return{index:e,lineN:c};for(var h=0,i=a.display.viewFrom;e>h;h++)i+=g[h].size;if(i!=b){if(d>0){if(e==g.length-1)return null;f=i+g[e].size-b,e++}else f=i-b;b+=f,c+=f}for(;kf(a.doc,c)!=c;){if(e==(0>d?0:g.length-1))return null;c+=d*g[e-(0>d?1:0)].size,e+=d}return{index:e,lineN:c}}function $c(a,b,c){var d=a.display,e=d.view;0==e.length||b>=d.viewTo||c<=d.viewFrom?(d.view=Uc(a,b,c),d.viewFrom=b):(d.viewFrom>b?d.view=Uc(a,b,d.viewFrom).concat(d.view):d.viewFromc&&(d.view=d.view.slice(0,Yc(a,c)))),d.viewTo=c}function _c(a){for(var b=a.display.view,c=0,d=0;d=9&&a.display.inputHasSelection===g||p&&/[\uf700-\uf7ff]/.test(g))return ed(a),!1;var h=!a.curOp;h&&Gc(a),a.display.shift=!1,8203!=g.charCodeAt(0)||f.sel!=a.display.selForContextMenu||c||(c="\u200b");for(var i=0,j=Math.min(c.length,g.length);j>i&&c.charCodeAt(i)==g.charCodeAt(i);)++i;var k=g.slice(i),l=wh(k),m=null;a.state.pasteIncoming&&f.sel.ranges.length>1&&(cd&&cd.join("\n")==k?m=0==f.sel.ranges.length%cd.length&&Vg(cd,wh):l.length==f.sel.ranges.length&&(m=Vg(l,function(a){return[a]})));for(var n=f.sel.ranges.length-1;n>=0;n--){var o=f.sel.ranges[n],q=o.from(),r=o.to();i-1){ke(a,v.line,"smart");break}}else u.electricInput&&u.electricInput.test(Xf(f,v.line).text.slice(0,v.ch))&&ke(a,v.line,"smart")}}return ie(a),a.curOp.updateInput=s,a.curOp.typing=!0,g.length>1e3||g.indexOf("\n")>-1?b.value=a.display.prevInput="":a.display.prevInput=g,h&&Ic(a),a.state.pasteIncoming=a.state.cutIncoming=!1,!0}function ed(a,b){if(!a.display.contextMenuPending){var c,f,g=a.doc;if(a.somethingSelected()){a.display.prevInput="";var h=g.sel.primary();c=yh&&(h.to().line-h.from().line>100||(f=a.getSelection()).length>1e3);var i=c?"-":f||a.getSelection();a.display.input.value=i,a.state.focused&&Tg(a.display.input),d&&e>=9&&(a.display.inputHasSelection=i)}else b||(a.display.prevInput=a.display.input.value="",d&&e>=9&&(a.display.inputHasSelection=null));a.display.inaccurateSelection=c}}function fd(a){"nocursor"==a.options.readOnly||o&&ih()==a.display.input||a.display.input.focus()}function gd(a){a.state.focused||(fd(a),Od(a))}function hd(a){return a.options.readOnly||a.doc.cantEdit}function id(a){function c(b){Eg(a,b)||vg(b)}function g(c){if(a.somethingSelected())cd=a.getSelections(),b.inaccurateSelection&&(b.prevInput="",b.inaccurateSelection=!1,b.input.value=cd.join("\n"),Tg(b.input));else{for(var d=[],e=[],f=0;fe?yg(b.scroller,"dblclick",Qc(a,function(b){if(!Eg(a,b)){var c=ld(a,b);if(c&&!td(a,b)&&!kd(a.display,b)){sg(b);var d=a.findWordAt(c);Eb(a.doc,d.anchor,d.head)}}})):yg(b.scroller,"dblclick",function(b){Eg(a,b)||sg(b)}),yg(b.lineSpace,"selectstart",function(a){kd(b,a)||sg(a)}),t||yg(b.scroller,"contextmenu",function(b){Qd(a,b)}),yg(b.scroller,"scroll",function(){b.scroller.clientHeight&&(xd(a,b.scroller.scrollTop),yd(a,b.scroller.scrollLeft,!0),Ag(a,"scroll",a))}),yg(b.scroller,"mousewheel",function(b){Cd(a,b)}),yg(b.scroller,"DOMMouseScroll",function(b){Cd(a,b)}),yg(b.wrapper,"scroll",function(){b.wrapper.scrollTop=b.wrapper.scrollLeft=0}),yg(b.input,"keyup",function(b){Md.call(a,b)}),yg(b.input,"input",function(){d&&e>=9&&a.display.inputHasSelection&&(a.display.inputHasSelection=null),dd(a)}),yg(b.input,"keydown",Qc(a,Kd)),yg(b.input,"keypress",Qc(a,Nd)),yg(b.input,"focus",Yg(Od,a)),yg(b.input,"blur",Yg(Pd,a)),a.options.dragDrop&&(yg(b.scroller,"dragstart",function(b){wd(a,b)}),yg(b.scroller,"dragenter",c),yg(b.scroller,"dragover",c),yg(b.scroller,"drop",Qc(a,vd))),yg(b.scroller,"paste",function(c){kd(b,c)||(a.state.pasteIncoming=!0,fd(a),bd(a))}),yg(b.input,"paste",function(){if(f&&!a.state.fakedLastChar&&!(new Date-a.state.lastMiddleDown<200)){var c=b.input.selectionStart,d=b.input.selectionEnd;b.input.value+="$",b.input.selectionEnd=d,b.input.selectionStart=c,a.state.fakedLastChar=!0}a.state.pasteIncoming=!0,bd(a)}),yg(b.input,"cut",g),yg(b.input,"copy",g),k&&yg(b.sizer,"mouseup",function(){ih()==b.input&&b.input.blur(),fd(a)})}function jd(a){var b=a.display;(b.lastWrapHeight!=b.wrapper.clientHeight||b.lastWrapWidth!=b.wrapper.clientWidth)&&(b.cachedCharWidth=b.cachedTextHeight=b.cachedPaddingH=null,b.scrollbarsClipped=!1,a.setSize())}function kd(a,b){for(var c=wg(b);c!=a.wrapper;c=c.parentNode)if(!c||"true"==c.getAttribute("cm-ignore-events")||c.parentNode==a.sizer&&c!=a.mover)return!0}function ld(a,b,c,d){var e=a.display;if(!c&&"true"==wg(b).getAttribute("not-content"))return null;var f,g,h=e.lineSpace.getBoundingClientRect();try{f=b.clientX-h.left,g=b.clientY-h.top}catch(b){return null}var j,i=zc(a,f,g);if(d&&1==i.xRel&&(j=Xf(a.doc,i.line).text).length==i.ch){var k=Og(j,j.length,a.options.tabSize)-j.length;i=pb(i.line,Math.max(0,Math.round((f-ac(a.display).left)/Dc(a.display))-k))}return i}function md(a){if(!Eg(this,a)){var b=this,c=b.display;if(c.shift=a.shiftKey,kd(c,a))return f||(c.scroller.draggable=!1,setTimeout(function(){c.scroller.draggable=!0},100)),void 0;if(!td(b,a)){var d=ld(b,a);switch(window.focus(),xg(a)){case 1:d?pd(b,a,d):wg(a)==c.scroller&&sg(a);break;case 2:f&&(b.state.lastMiddleDown=+new Date),d&&Eb(b.doc,d),setTimeout(Yg(fd,b),20),sg(a);break;case 3:t&&Qd(b,a)}}}}function pd(a,b,c){setTimeout(Yg(gd,a),0);var e,d=+new Date;od&&od.time>d-400&&0==qb(od.pos,c)?e="triple":nd&&nd.time>d-400&&0==qb(nd.pos,c)?(e="double",od={time:d,pos:c}):(e="single",nd={time:d,pos:c});var h,f=a.doc.sel,g=p?b.metaKey:b.ctrlKey;a.options.dragDrop&&rh&&!hd(a)&&"single"==e&&(h=f.contains(c))>-1&&!f.ranges[h].empty()?qd(a,b,c,g):rd(a,b,c,e,g)}function qd(a,b,c,g){var h=a.display,i=Qc(a,function(j){f&&(h.scroller.draggable=!1),a.state.draggingText=!1,zg(document,"mouseup",i),zg(h.scroller,"drop",i),Math.abs(b.clientX-j.clientX)+Math.abs(b.clientY-j.clientY)<10&&(sg(j),g||Eb(a.doc,c),fd(a),d&&9==e&&setTimeout(function(){document.body.focus(),fd(a)},20))});f&&(h.scroller.draggable=!0),a.state.draggingText=i,h.scroller.dragDrop&&h.scroller.dragDrop(),yg(document,"mouseup",i),yg(h.scroller,"drop",i)}function rd(a,b,c,d,e){function o(b){if(0!=qb(n,b))if(n=b,"rect"==d){for(var e=[],f=a.options.tabSize,k=Og(Xf(g,c.line).text,c.ch,f),l=Og(Xf(g,b.line).text,b.ch,f),m=Math.min(k,l),o=Math.max(k,l),p=Math.min(c.line,b.line),q=Math.min(a.lastLine(),Math.max(c.line,b.line));q>=p;p++){var r=Xf(g,p).text,s=Pg(r,m,f);m==o?e.push(new vb(pb(p,s),pb(p,s))):r.length>s&&e.push(new vb(pb(p,s),pb(p,Pg(r,o,f))))}e.length||e.push(new vb(c,c)),Kb(g,wb(j.ranges.slice(0,i).concat(e),i),{origin:"*mouse",scroll:!1}),a.scrollIntoView(b)}else{var t=h,u=t.anchor,v=b;if("single"!=d){if("double"==d)var w=a.findWordAt(b);else var w=new vb(pb(b.line,0),zb(g,pb(b.line+1,0)));qb(w.anchor,u)>0?(v=w.head,u=tb(t.from(),w.anchor)):(v=w.anchor,u=sb(t.to(),w.head))}var e=j.ranges.slice(0);e[i]=new vb(zb(g,u),v),Kb(g,wb(e,i),Lg)}}function r(b){var c=++q,e=ld(a,b,!0,"rect"==d);if(e)if(0!=qb(e,n)){gd(a),o(e);var h=Q(f,g);(e.line>=h.to||e.linep.bottom?20:0;i&&setTimeout(Qc(a,function(){q==c&&(f.scroller.scrollTop+=i,r(b))}),50)}}function s(b){q=1/0,sg(b),fd(a),zg(document,"mousemove",t),zg(document,"mouseup",u),g.history.lastSelOrigin=null}var f=a.display,g=a.doc;sg(b);var h,i,j=g.sel,k=j.ranges;if(e&&!b.shiftKey?(i=g.sel.contains(c),h=i>-1?k[i]:new vb(c,c)):h=g.sel.primary(),b.altKey)d="rect",e||(h=new vb(c,c)),c=ld(a,b,!0,!0),i=-1;else if("double"==d){var l=a.findWordAt(c);h=a.display.shift||g.extend?Db(g,h,l.anchor,l.head):l}else if("triple"==d){var m=new vb(pb(c.line,0),zb(g,pb(c.line+1,0)));h=a.display.shift||g.extend?Db(g,h,m.anchor,m.head):m}else h=Db(g,h,c);e?-1==i?(i=k.length,Kb(g,wb(k.concat([h]),i),{scroll:!1,origin:"*mouse"})):k.length>1&&k[i].empty()&&"single"==d?(Kb(g,wb(k.slice(0,i).concat(k.slice(i+1)),0)),j=g.sel):Gb(g,i,h,Lg):(i=0,Kb(g,new ub([h],0),Lg),j=g.sel);var n=c,p=f.wrapper.getBoundingClientRect(),q=0,t=Qc(a,function(a){xg(a)?r(a):s(a)}),u=Qc(a,s);yg(document,"mousemove",t),yg(document,"mouseup",u)}function sd(a,b,c,d,e){try{var f=b.clientX,g=b.clientY}catch(b){return!1}if(f>=Math.floor(a.display.gutters.getBoundingClientRect().right))return!1;d&&sg(b);var h=a.display,i=h.lineDiv.getBoundingClientRect();if(g>i.bottom||!Gg(a,c))return ug(b);g-=i.top-h.viewOffset;for(var j=0;j=f){var l=ag(a.doc,g),m=a.options.gutters[j];return e(a,c,a,l,m,b),ug(b)}}}function td(a,b){return sd(a,b,"gutterClick",!0,Cg)}function vd(a){var b=this;if(!Eg(b,a)&&!kd(b.display,a)){sg(a),d&&(ud=+new Date);var c=ld(b,a,!0),e=a.dataTransfer.files;if(c&&!hd(b))if(e&&e.length&&window.FileReader&&window.File)for(var f=e.length,g=Array(f),h=0,i=function(a,d){var e=new FileReader;e.onload=Qc(b,function(){if(g[d]=e.result,++h==f){c=zb(b.doc,c);var a={from:c,to:c,text:wh(g.join("\n")),origin:"paste"};Yd(b.doc,a),Jb(b.doc,xb(c,Sd(a)))}}),e.readAsText(a)},j=0;f>j;++j)i(e[j],j);else{if(b.state.draggingText&&b.doc.sel.contains(c)>-1)return b.state.draggingText(a),setTimeout(Yg(fd,b),20),void 0;try{var g=a.dataTransfer.getData("Text");if(g){if(b.state.draggingText&&!(p?a.metaKey:a.ctrlKey))var k=b.listSelections();if(Lb(b.doc,xb(c,c)),k)for(var j=0;jj.clientWidth||g&&j.scrollHeight>j.clientHeight){if(g&&p&&f)a:for(var k=c.target,l=h.view;k!=j;k=k.parentNode)for(var m=0;mn?o=Math.max(0,o+n-50):q=Math.min(b.doc.height,q+n+50),Z(b,{top:o,bottom:q})}20>zd&&(null==h.wheelStartX?(h.wheelStartX=j.scrollLeft,h.wheelStartY=j.scrollTop,h.wheelDX=e,h.wheelDY=g,setTimeout(function(){if(null!=h.wheelStartX){var a=j.scrollLeft-h.wheelStartX,b=j.scrollTop-h.wheelStartY,c=b&&h.wheelDY&&b/h.wheelDY||a&&h.wheelDX&&a/h.wheelDX;h.wheelStartX=h.wheelStartY=null,c&&(Ad=(Ad*zd+c)/(zd+1),++zd)}},200)):(h.wheelDX+=e,h.wheelDY+=g))}}function Dd(a,b,c){if("string"==typeof b&&(b=Ae[b],!b))return!1;a.display.pollingFast&&dd(a)&&(a.display.pollingFast=!1);var d=a.display.shift,e=!1;try{hd(a)&&(a.state.suppressEdits=!0),c&&(a.display.shift=!1),e=b(a)!=Jg}finally{a.display.shift=d,a.state.suppressEdits=!1}return e}function Ed(a,b,c){for(var d=0;de&&27==a.keyCode&&(a.returnValue=!1);var c=a.keyCode;b.display.shift=16==c||a.shiftKey;var f=Hd(b,a);i&&(Jd=f?c:null,!f&&88==c&&!yh&&(p?a.metaKey:a.ctrlKey)&&b.replaceSelection("",null,"cut")),18!=c||/\bCodeMirror-crosshair\b/.test(b.display.lineDiv.className)||Ld(b)}}function Ld(a){function c(a){18!=a.keyCode&&a.altKey||(kh(b,"CodeMirror-crosshair"),zg(document,"keyup",c),zg(document,"mouseover",c))}var b=a.display.lineDiv;lh(b,"CodeMirror-crosshair"),yg(document,"keyup",c),yg(document,"mouseover",c)}function Md(a){16==a.keyCode&&(this.doc.sel.shift=!1),Eg(this,a)}function Nd(a){var b=this;if(!(Eg(b,a)||a.ctrlKey&&!a.altKey||p&&a.metaKey)){var c=a.keyCode,f=a.charCode;if(i&&c==Jd)return Jd=null,sg(a),void 0;if(!(i&&(!a.which||a.which<10)||k)||!Hd(b,a)){var g=String.fromCharCode(null==f?c:f);Id(b,a,g)||(d&&e>=9&&(b.display.inputHasSelection=null),bd(b))}}}function Od(a){"nocursor"!=a.options.readOnly&&(a.state.focused||(Ag(a,"focus",a),a.state.focused=!0,lh(a.display.wrapper,"CodeMirror-focused"),a.curOp||a.display.selForContextMenu==a.doc.sel||(ed(a),f&&setTimeout(Yg(ed,a,!0),0))),ad(a),Vb(a))}function Pd(a){a.state.focused&&(Ag(a,"blur",a),a.state.focused=!1,kh(a.display.wrapper,"CodeMirror-focused")),clearInterval(a.display.blinker),setTimeout(function(){a.state.focused||(a.display.shift=!1)},150)}function Qd(a,b){function m(){if(null!=c.input.selectionStart){var b=a.somethingSelected(),d=c.input.value="\u200b"+(b?c.input.value:"");c.prevInput=b?"":"\u200b",c.input.selectionStart=1,c.input.selectionEnd=d.length,c.selForContextMenu=a.doc.sel}}function n(){if(c.contextMenuPending=!1,c.inputDiv.style.position="relative",c.input.style.cssText=k,d&&9>e&&c.scrollbars.setScrollTop(c.scroller.scrollTop=h),ad(a),null!=c.input.selectionStart){(!d||d&&9>e)&&m();var b=0,f=function(){c.selForContextMenu==a.doc.sel&&0==c.input.selectionStart?Qc(a,Ae.selectAll)(a):b++<10?c.detectingSelectAll=setTimeout(f,500):ed(a)};c.detectingSelectAll=setTimeout(f,200)}}if(!Eg(a,b,"contextmenu")){var c=a.display;if(!kd(c,b)&&!Rd(a,b)){var g=ld(a,b),h=c.scroller.scrollTop;if(g&&!i){var j=a.options.resetSelectionOnContextMenu;j&&-1==a.doc.sel.contains(g)&&Qc(a,Kb)(a.doc,xb(g),Kg);var k=c.input.style.cssText;if(c.inputDiv.style.position="absolute",c.input.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(b.clientY-5)+"px; left: "+(b.clientX-5)+"px; z-index: 1000; background: "+(d?"rgba(255, 255, 255, .05)":"transparent")+"; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",f)var l=window.scrollY;if(fd(a),f&&window.scrollTo(null,l),ed(a),a.somethingSelected()||(c.input.value=c.prevInput=" "),c.contextMenuPending=!0,c.selForContextMenu=a.doc.sel,clearTimeout(c.detectingSelectAll),d&&e>=9&&m(),t){vg(b);var o=function(){zg(window,"mouseup",o),setTimeout(n,20)};yg(window,"mouseup",o)}else setTimeout(n,50)}}}}function Rd(a,b){return Gg(a,"gutterContextMenu")?sd(a,b,"gutterContextMenu",!1,Ag):!1}function Td(a,b){if(qb(a,b.from)<0)return a;if(qb(a,b.to)<=0)return Sd(b);var c=a.line+b.text.length-(b.to.line-b.from.line)-1,d=a.ch;return a.line==b.to.line&&(d+=Sd(b).ch-b.to.ch),pb(c,d)}function Ud(a,b){for(var c=[],d=0;d=0;--e)Zd(a,{from:d[e].from,to:d[e].to,text:e?[""]:b.text});else Zd(a,b)}}function Zd(a,b){if(1!=b.text.length||""!=b.text[0]||0!=qb(b.from,b.to)){var c=Ud(a,b);hg(a,b,c,a.cm?a.cm.curOp.id:0/0),ae(a,b,c,We(a,b));var d=[];Vf(a,function(a,c){c||-1!=Ug(d,a.history)||(rg(a.history,b),d.push(a.history)),ae(a,b,null,We(a,b))})}}function $d(a,b,c){if(!a.cm||!a.cm.state.suppressEdits){for(var e,d=a.history,f=a.sel,g="undo"==b?d.done:d.undone,h="undo"==b?d.undone:d.done,i=0;i=0;--i){var l=e.changes[i];if(l.origin=b,k&&!Xd(a,l,!1))return g.length=0,void 0;j.push(eg(a,l));var m=i?Ud(a,l):Sg(g);ae(a,l,m,Ye(a,l)),!i&&a.cm&&a.cm.scrollIntoView({from:l.from,to:Sd(l)});var n=[];Vf(a,function(a,b){b||-1!=Ug(n,a.history)||(rg(a.history,l),n.push(a.history)),ae(a,l,null,Ye(a,l))})}}}}function _d(a,b){if(0!=b&&(a.first+=b,a.sel=new ub(Vg(a.sel.ranges,function(a){return new vb(pb(a.anchor.line+b,a.anchor.ch),pb(a.head.line+b,a.head.ch))}),a.sel.primIndex),a.cm)){Vc(a.cm,a.first,a.first-b,b);for(var c=a.cm.display,d=c.viewFrom;da.lastLine())){if(b.from.linef&&(b={from:b.from,to:pb(f,Xf(a,f).text.length),text:[b.text[0]],origin:b.origin}),b.removed=Yf(a,b.from,b.to),c||(c=Ud(a,b)),a.cm?be(a.cm,b,d):Of(a,b,d),Lb(a,c,Kg)}}function be(a,b,c){var d=a.doc,e=a.display,f=b.from,g=b.to,h=!1,i=f.line;a.options.lineWrapping||(i=_f(hf(Xf(d,f.line))),d.iter(i,g.line+1,function(a){return a==e.maxLine?(h=!0,!0):void 0})),d.sel.contains(b.from,b.to)>-1&&Fg(a),Of(d,b,c,B(a)),a.options.lineWrapping||(d.iter(i,f.line+b.text.length,function(a){var b=H(a);b>e.maxLineLength&&(e.maxLine=a,e.maxLineLength=b,e.maxLineChanged=!0,h=!1)}),h&&(a.curOp.updateMaxLine=!0)),d.frontier=Math.min(d.frontier,f.line),Wb(a,400);var j=b.text.length-(g.line-f.line)-1;f.line!=g.line||1!=b.text.length||Nf(a.doc,b)?Vc(a,f.line,g.line+1,j):Wc(a,f.line,"text");var k=Gg(a,"changes"),l=Gg(a,"change");if(l||k){var m={from:f,to:g,text:b.text,removed:b.removed,origin:b.origin};l&&Cg(a,"change",a,m),k&&(a.curOp.changeObjs||(a.curOp.changeObjs=[])).push(m)}a.display.selForContextMenu=null}function ce(a,b,c,d,e){if(d||(d=c),qb(d,c)<0){var f=d;d=c,c=f}"string"==typeof b&&(b=wh(b)),Yd(a,{from:c,to:d,text:b,origin:e})}function de(a,b){if(!Eg(a,"scrollCursorIntoView")){var c=a.display,d=c.sizer.getBoundingClientRect(),e=null;if(b.top+d.top<0?e=!0:b.bottom+d.top>(window.innerHeight||document.documentElement.clientHeight)&&(e=!1),null!=e&&!m){var f=dh("div","\u200b",null,"position: absolute; top: "+(b.top-c.viewOffset-$b(a.display))+"px; height: "+(b.bottom-b.top+bc(a)+c.barHeight)+"px; left: "+b.left+"px; width: 2px;");a.display.lineSpace.appendChild(f),f.scrollIntoView(e),a.display.lineSpace.removeChild(f)}}}function ee(a,b,c,d){null==d&&(d=0);for(var e=0;5>e;e++){var f=!1,g=wc(a,b),h=c&&c!=b?wc(a,c):g,i=ge(a,Math.min(g.left,h.left),Math.min(g.top,h.top)-d,Math.max(g.left,h.left),Math.max(g.bottom,h.bottom)+d),j=a.doc.scrollTop,k=a.doc.scrollLeft;if(null!=i.scrollTop&&(xd(a,i.scrollTop),Math.abs(a.doc.scrollTop-j)>1&&(f=!0)),null!=i.scrollLeft&&(yd(a,i.scrollLeft),Math.abs(a.doc.scrollLeft-k)>1&&(f=!0)),!f)break}return g}function fe(a,b,c,d,e){var f=ge(a,b,c,d,e);null!=f.scrollTop&&xd(a,f.scrollTop),null!=f.scrollLeft&&yd(a,f.scrollLeft)}function ge(a,b,c,d,e){var f=a.display,g=Cc(a.display);0>c&&(c=0);var h=a.curOp&&null!=a.curOp.scrollTop?a.curOp.scrollTop:f.scroller.scrollTop,i=dc(a),j={};e-c>i&&(e=c+i);var k=a.doc.height+_b(f),l=g>c,m=e>k-g;if(h>c)j.scrollTop=l?0:c;else if(e>h+i){var n=Math.min(c,(m?k:e)-i);n!=h&&(j.scrollTop=n)}var o=a.curOp&&null!=a.curOp.scrollLeft?a.curOp.scrollLeft:f.scroller.scrollLeft,p=cc(a)-(a.options.fixedGutter?f.gutters.offsetWidth:0),q=d-b>p;return q&&(d=b+p),10>b?j.scrollLeft=0:o>b?j.scrollLeft=Math.max(0,b-(q?0:10)):d>p+o-3&&(j.scrollLeft=d+(q?0:10)-p),j}function he(a,b,c){(null!=b||null!=c)&&je(a),null!=b&&(a.curOp.scrollLeft=(null==a.curOp.scrollLeft?a.doc.scrollLeft:a.curOp.scrollLeft)+b),null!=c&&(a.curOp.scrollTop=(null==a.curOp.scrollTop?a.doc.scrollTop:a.curOp.scrollTop)+c)}function ie(a){je(a);var b=a.getCursor(),c=b,d=b;a.options.lineWrapping||(c=b.ch?pb(b.line,b.ch-1):b,d=pb(b.line,b.ch+1)),a.curOp.scrollToPos={from:c,to:d,margin:a.options.cursorScrollMargin,isCursor:!0}}function je(a){var b=a.curOp.scrollToPos;if(b){a.curOp.scrollToPos=null;var c=xc(a,b.from),d=xc(a,b.to),e=ge(a,Math.min(c.left,d.left),Math.min(c.top,d.top)-b.margin,Math.max(c.right,d.right),Math.max(c.bottom,d.bottom)+b.margin);a.scrollTo(e.scrollLeft,e.scrollTop)}}function ke(a,b,c,d){var f,e=a.doc;null==c&&(c="add"),"smart"==c&&(e.mode.indent?f=Zb(a,b):c="prev");var g=a.options.tabSize,h=Xf(e,b),i=Og(h.text,null,g);h.stateAfter&&(h.stateAfter=null);var k,j=h.text.match(/^\s*/)[0];if(d||/\S/.test(h.text)){if("smart"==c&&(k=e.mode.indent(f,h.text.slice(j.length),h.text),k==Jg||k>150)){if(!d)return;c="prev"}}else k=0,c="not";"prev"==c?k=b>e.first?Og(Xf(e,b-1).text,null,g):0:"add"==c?k=i+a.options.indentUnit:"subtract"==c?k=i-a.options.indentUnit:"number"==typeof c&&(k=i+c),k=Math.max(0,k);var l="",m=0;if(a.options.indentWithTabs)for(var n=Math.floor(k/g);n;--n)m+=g,l+=" ";if(k>m&&(l+=Rg(k-m)),l!=j)ce(e,l,pb(b,0),pb(b,j.length),"+input");else for(var n=0;n=0;b--)ce(a.doc,"",d[b].from,d[b].to,"+delete");ie(a)})}function ne(a,b,c,d,e){function k(){var b=f+c;return b=a.first+a.size?j=!1:(f=b,i=Xf(a,b))}function l(a){var b=(e?Oh:Ph)(i,g,c,!0);if(null==b){if(a||!k())return j=!1;g=e?(0>c?Gh:Fh)(i):0>c?i.text.length:0}else g=b;return!0}var f=b.line,g=b.ch,h=c,i=Xf(a,f),j=!0;if("char"==d)l();else if("column"==d)l(!0);else if("word"==d||"group"==d)for(var m=null,n="group"==d,o=a.cm&&a.cm.getHelper(b,"wordChars"),p=!0;!(0>c)||l(!p);p=!1){var q=i.text.charAt(g)||"\n",r=_g(q,o)?"w":n&&"\n"==q?"n":!n||/\s/.test(q)?null:"p";if(!n||p||r||(r="s"),m&&m!=r){0>c&&(c=1,l());break}if(r&&(m=r),c>0&&!l(!p))break}var s=Pb(a,pb(f,g),h,!0);return j||(s.hitSide=!0),s}function oe(a,b,c,d){var g,e=a.doc,f=b.left;if("page"==d){var h=Math.min(a.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);g=b.top+c*(h-(0>c?1.5:.5)*Cc(a.display))}else"line"==d&&(g=c>0?b.bottom+3:b.top-3);for(;;){var i=zc(a,f,g);if(!i.outside)break;if(0>c?0>=g:g>=e.height){i.hitSide=!0;break}g+=5*c}return i}function re(a,b,c,d){w.defaults[a]=b,c&&(qe[a]=d?function(a,b,d){d!=se&&c(a,b,d)}:c)}function Ce(a){for(var c,d,e,f,b=a.split(/-(?!$)/),a=b[b.length-1],g=0;g0||0==g&&f.clearWhenEmpty!==!1)return f;if(f.replacedWith&&(f.collapsed=!0,f.widgetNode=dh("span",[f.replacedWith],"CodeMirror-widget"),d.handleMouseEvents||f.widgetNode.setAttribute("cm-ignore-events","true"),d.insertLeft&&(f.widgetNode.insertLeft=!0)),f.collapsed){if(gf(a,b.line,b,c,f)||b.line!=c.line&&gf(a,c.line,b,c,f))throw new Error("Inserting collapsed marker partially overlapping an existing one");v=!0}f.addToHistory&&hg(a,{from:b,to:c,origin:"markText"},a.sel,0/0);var j,h=b.line,i=a.cm;if(a.iter(h,c.line+1,function(a){i&&f.collapsed&&!i.options.lineWrapping&&hf(a)==i.display.maxLine&&(j=!0),f.collapsed&&h!=b.line&&$f(a,0),Te(a,new Qe(f,h==b.line?b.ch:null,h==c.line?c.ch:null)),++h}),f.collapsed&&a.iter(b.line,c.line+1,function(b){mf(a,b)&&$f(b,0)}),f.clearOnEnter&&yg(f,"beforeCursorEnter",function(){f.clear()}),f.readOnly&&(u=!0,(a.history.done.length||a.history.undone.length)&&a.clearHistory()),f.collapsed&&(f.id=++Je,f.atomic=!0),i){if(j&&(i.curOp.updateMaxLine=!0),f.collapsed)Vc(i,b.line,c.line+1);else if(f.className||f.title||f.startStyle||f.endStyle||f.css)for(var k=b.line;k<=c.line;k++)Wc(i,k,"text");f.atomic&&Nb(i.doc),Cg(i,"markerAdded",i,f)}return f}function Me(a,b,c,d,e){d=Xg(d),d.shared=!1;var f=[Ke(a,b,c,d,e)],g=f[0],h=d.widgetNode;return Vf(a,function(a){h&&(d.widgetNode=h.cloneNode(!0)),f.push(Ke(a,zb(a,b),zb(a,c),d,e));for(var i=0;i=b:f.to>b);(e||(e=[])).push(new Qe(g,f.from,i?null:f.to))}}return e}function Ve(a,b,c){if(a)for(var e,d=0;d=b:f.to>b);if(h||f.from==b&&"bookmark"==g.type&&(!c||f.marker.insertLeft)){var i=null==f.from||(g.inclusiveLeft?f.from<=b:f.from0&&h)for(var l=0;ll;++l)o.push(q);o.push(i)}return o}function Xe(a){for(var b=0;b0)){var k=[i,1],l=qb(j.from,h.from),m=qb(j.to,h.to);(0>l||!g.inclusiveLeft&&!l)&&k.push({from:j.from,to:h.from}),(m>0||!g.inclusiveRight&&!m)&&k.push({from:h.to,to:j.to}),e.splice.apply(e,k),i+=k.length-1}}return e}function $e(a){var b=a.markedSpans;if(b){for(var c=0;c=0&&0>=l||0>=k&&l>=0)&&(0>=k&&(qb(j.to,c)>0||i.marker.inclusiveRight&&e.inclusiveLeft)||k>=0&&(qb(j.from,d)<0||i.marker.inclusiveLeft&&e.inclusiveRight)))return!0}}}function hf(a){for(var b;b=ef(a);)a=b.find(-1,!0).line;return a}function jf(a){for(var b,c;b=ff(a);)a=b.find(1,!0).line,(c||(c=[])).push(a);return c}function kf(a,b){var c=Xf(a,b),d=hf(c);return c==d?b:_f(d)}function lf(a,b){if(b>a.lastLine())return b;var d,c=Xf(a,b);if(!mf(a,c))return b;for(;d=ff(c);)c=d.find(1,!0).line;return _f(c)+1}function mf(a,b){var c=v&&b.markedSpans;if(c)for(var d,e=0;ee;e++){d&&(d[0]=w.innerMode(a,c).mode);var f=a.token(b,c);if(b.pos>b.start)return f}throw new Error("Mode "+a.name+" failed to advance stream.")}function yf(a,b,c,d){function e(a){return{start:k.start,end:k.pos,string:k.current(),type:h||null,state:a?ye(f.mode,j):j}}var h,f=a.doc,g=f.mode;b=zb(f,b);var l,i=Xf(f,b.line),j=Zb(a,b.line,c),k=new He(i.text,a.options.tabSize);for(d&&(l=[]);(d||k.posa.options.maxHighlightLength?(h=!1,g&&Cf(a,b,d,k.pos),k.pos=b.length,l=null):l=vf(xf(c,k,d,m),f),m){var n=m[0].name;n&&(l="m-"+(l?n+" "+l:n))}if(!h||j!=l){for(;ij;){var d=e[i];d>a&&e.splice(i,1,a,e[i+1],d),i+=2,j=Math.min(a,d)}if(b)if(h.opaque)e.splice(c,i-c,a,"cm-overlay "+b),i=c+2;else for(;i>c;c+=2){var f=e[c+1];e[c+1]=(f?f+" ":"")+"cm-overlay "+b}},f)}return{styles:e,classes:f.bgClass||f.textClass?f:null}}function Bf(a,b,c){if(!b.styles||b.styles[0]!=a.state.modeGen){var d=Af(a,b,b.stateAfter=Zb(a,_f(b)));b.styles=d.styles,d.classes?b.styleClasses=d.classes:b.styleClasses&&(b.styleClasses=null),c===a.doc.frontier&&a.doc.frontier++}return b.styles}function Cf(a,b,c,d){var e=a.doc.mode,f=new He(b,a.options.tabSize);for(f.start=f.pos=d||0,""==b&&wf(e,c);!f.eol()&&f.pos<=a.options.maxHighlightLength;)xf(e,f,c),f.start=f.pos}function Ff(a,b){if(!a||/^\s*$/.test(a))return null;var c=b.addModeClass?Ef:Df;return c[a]||(c[a]=a.replace(/\S+/g,"cm-$&"))}function Gf(a,b){var c=dh("span",null,null,f?"padding-right: .1px":null),e={pre:dh("pre",[c]),content:c,col:0,pos:0,cm:a};b.measure={};for(var g=0;g<=(b.rest?b.rest.length:0);g++){var i,h=g?b.rest[g-1]:b.line;e.pos=0,e.addToken=If,(d||f)&&a.getOption("lineWrapping")&&(e.addToken=Jf(e.addToken)),vh(a.display.measure)&&(i=cg(h))&&(e.addToken=Kf(e.addToken,i)),e.map=[];var j=b!=a.display.externalMeasured&&_f(h);Mf(h,e,Bf(a,h,j)),h.styleClasses&&(h.styleClasses.bgClass&&(e.bgClass=mh(h.styleClasses.bgClass,e.bgClass||"")),h.styleClasses.textClass&&(e.textClass=mh(h.styleClasses.textClass,e.textClass||""))),0==e.map.length&&e.map.push(0,0,e.content.appendChild(th(a.display.measure))),0==g?(b.measure.map=e.map,b.measure.cache={}):((b.measure.maps||(b.measure.maps=[])).push(e.map),(b.measure.caches||(b.measure.caches=[])).push({}))}return f&&/\bcm-tab\b/.test(e.content.lastChild.className)&&(e.content.className="cm-tab-wrap-hack"),Ag(a,"renderLine",a,b.line,e.pre),e.pre.className&&(e.textClass=mh(e.pre.className,e.textClass||"")),e}function Hf(a){var b=dh("span","\u2022","cm-invalidchar");return b.title="\\u"+a.charCodeAt(0).toString(16),b}function If(a,b,c,f,g,h,i){if(b){var j=a.cm.options.specialChars,k=!1;if(j.test(b))for(var l=document.createDocumentFragment(),m=0;;){j.lastIndex=m;var n=j.exec(b),o=n?n.index-m:b.length-m;if(o){var p=document.createTextNode(b.slice(m,m+o));d&&9>e?l.appendChild(dh("span",[p])):l.appendChild(p),a.map.push(a.pos,a.pos+o,p),a.col+=o,a.pos+=o}if(!n)break;if(m+=o+1," "==n[0]){var q=a.cm.options.tabSize,r=q-a.col%q,p=l.appendChild(dh("span",Rg(r),"cm-tab"));a.col+=r}else{var p=a.cm.options.specialCharPlaceholder(n[0]);d&&9>e?l.appendChild(dh("span",[p])):l.appendChild(p),a.col+=1}a.map.push(a.pos,a.pos+1,p),a.pos++}else{a.col+=b.length;var l=document.createTextNode(b);a.map.push(a.pos,a.pos+b.length,l),d&&9>e&&(k=!0),a.pos+=b.length}if(c||f||g||k||i){var s=c||"";f&&(s+=f),g&&(s+=g);var t=dh("span",[l],s,i);return h&&(t.title=h),a.content.appendChild(t)}a.content.appendChild(l)}}function Jf(a){function b(a){for(var b=" ",c=0;ci&&l.from<=i)break}if(l.to>=j)return a(c,d,e,f,g,h);a(c,d.slice(0,l.to-i),e,f,null,h),f=null,d=d.slice(l.to-i),i=l.to}}}function Lf(a,b,c,d){var e=!d&&c.widgetNode;e&&(a.map.push(a.pos,a.pos+b,e),a.content.appendChild(e)),a.pos+=b}function Mf(a,b,c){var d=a.markedSpans,e=a.text,f=0;if(d)for(var k,l,n,o,p,q,r,h=e.length,i=0,g=1,j="",m=0;;){if(m==i){n=o=p=q=l="",r=null,m=1/0;for(var s=[],t=0;ti)?(null!=u.to&&m>u.to&&(m=u.to,o=""),v.className&&(n+=" "+v.className),v.css&&(l=v.css),v.startStyle&&u.from==i&&(p+=" "+v.startStyle),v.endStyle&&u.to==m&&(o+=" "+v.endStyle),v.title&&!q&&(q=v.title),v.collapsed&&(!r||cf(r.marker,v)<0)&&(r=u)):u.from>i&&m>u.from&&(m=u.from),"bookmark"==v.type&&u.from==i&&v.widgetNode&&s.push(v)}if(r&&(r.from||0)==i&&(Lf(b,(null==r.to?h+1:r.to)-i,r.marker,null==r.from),null==r.to))return;if(!r&&s.length)for(var t=0;t=h)break;for(var w=Math.min(h,m);;){if(j){var x=i+j.length;if(!r){var y=x>w?j.slice(0,w-i):j;b.addToken(b,y,k?k+n:n,p,i+y.length==m?o:"",q,l)}if(x>=w){j=j.slice(w-i),i=w;break}i=x,p=""}j=e.slice(f,f=c[g++]),k=Ff(c[g++],b.cm.options)}}else for(var g=1;g1&&a.remove(g.line+1,n-1),a.insert(g.line+1,p)}Cg(a,"change",a,b)}function Pf(a){this.lines=a,this.parent=null;for(var b=0,c=0;bb||b>=a.size)throw new Error("There is no line "+(b+a.first)+" in the document.");for(var c=a;!c.lines;)for(var d=0;;++d){var e=c.children[d],f=e.chunkSize();if(f>b){c=e;break}b-=f}return c.lines[b]}function Yf(a,b,c){var d=[],e=b.line;return a.iter(b.line,c.line+1,function(a){var f=a.text;e==c.line&&(f=f.slice(0,c.ch)),e==b.line&&(f=f.slice(b.ch)),d.push(f),++e}),d}function Zf(a,b,c){var d=[];return a.iter(b,c,function(a){d.push(a.text)}),d}function $f(a,b){var c=b-a.height;if(c)for(var d=a;d;d=d.parent)d.height+=c}function _f(a){if(null==a.parent)return null;for(var b=a.parent,c=Ug(b.lines,a),d=b.parent;d;b=d,d=d.parent)for(var e=0;d.children[e]!=b;++e)c+=d.children[e].chunkSize();return c+b.first}function ag(a,b){var c=a.first;a:do{for(var d=0;db){a=e;continue a}b-=f,c+=e.chunkSize()}return c}while(!a.lines);for(var d=0;db)break;b-=h}return c+d}function bg(a){a=hf(a);for(var b=0,c=a.parent,d=0;d1&&!a.done[a.done.length-2].ranges?(a.done.pop(),Sg(a.done)):void 0}function hg(a,b,c,d){var e=a.history;e.undone.length=0;var g,f=+new Date;if((e.lastOp==d||e.lastOrigin==b.origin&&b.origin&&("+"==b.origin.charAt(0)&&a.cm&&e.lastModTime>f-a.cm.options.historyEventDelay||"*"==b.origin.charAt(0)))&&(g=gg(e,e.lastOp==d))){var h=Sg(g.changes);0==qb(b.from,b.to)&&0==qb(b.from,h.to)?h.to=Sd(b):g.changes.push(eg(a,b))}else{var i=Sg(e.done);for(i&&i.ranges||kg(a.sel,e.done),g={changes:[eg(a,b)],generation:e.generation},e.done.push(g);e.done.length>e.undoDepth;)e.done.shift(),e.done[0].ranges||e.done.shift()}e.done.push(c),e.generation=++e.maxGeneration,e.lastModTime=e.lastSelTime=f,e.lastOp=e.lastSelOp=d,e.lastOrigin=e.lastSelOrigin=b.origin,h||Ag(a,"historyAdded")}function ig(a,b,c,d){var e=b.charAt(0);return"*"==e||"+"==e&&c.ranges.length==d.ranges.length&&c.somethingSelected()==d.somethingSelected()&&new Date-a.history.lastSelTime<=(a.cm?a.cm.options.historyEventDelay:500)}function jg(a,b,c,d){var e=a.history,f=d&&d.origin;c==e.lastSelOp||f&&e.lastSelOrigin==f&&(e.lastModTime==e.lastSelTime&&e.lastOrigin==f||ig(a,f,Sg(e.done),b))?e.done[e.done.length-1]=b:kg(b,e.done),e.lastSelTime=+new Date,e.lastSelOrigin=f,e.lastSelOp=c,d&&d.clearRedo!==!1&&fg(e.undone)}function kg(a,b){var c=Sg(b);c&&c.ranges&&c.equals(a)||b.push(a)}function lg(a,b,c,d){var e=b["spans_"+a.id],f=0;a.iter(Math.max(a.first,c),Math.min(a.first+a.size,d),function(c){c.markedSpans&&((e||(e=b["spans_"+a.id]={}))[f]=c.markedSpans),++f})}function mg(a){if(!a)return null;for(var c,b=0;b-1&&(Sg(h)[l]=j[l],delete j[l])}}}return e}function pg(a,b,c,d){c0}function Hg(a){a.prototype.on=function(a,b){yg(this,a,b)},a.prototype.off=function(a,b){zg(this,a,b)}}function Ng(){this.id=null}function Pg(a,b,c){for(var d=0,e=0;;){var f=a.indexOf(" ",d);-1==f&&(f=a.length);var g=f-d;if(f==a.length||e+g>=b)return d+Math.min(g,b-e);if(e+=f-d,e+=c-e%c,d=f+1,e>=b)return d}}function Rg(a){for(;Qg.length<=a;)Qg.push(Sg(Qg)+" ");return Qg[a]}function Sg(a){return a[a.length-1]}function Ug(a,b){for(var c=0;c-1&&$g(a)?!0:b.test(a):$g(a)}function ah(a){for(var b in a)if(a.hasOwnProperty(b)&&a[b])return!1;return!0}function ch(a){return a.charCodeAt(0)>=768&&bh.test(a)}function dh(a,b,c,d){var e=document.createElement(a);if(c&&(e.className=c),d&&(e.style.cssText=d),"string"==typeof b)e.appendChild(document.createTextNode(b));else if(b)for(var f=0;f0;--b)a.removeChild(a.firstChild);return a}function gh(a,b){return fh(a).appendChild(b)}function hh(a,b){if(a.contains)return a.contains(b);for(;b=b.parentNode;)if(b==a)return!0}function ih(){return document.activeElement}function jh(a){return new RegExp("(^|\\s)"+a+"(?:$|\\s)\\s*")}function mh(a,b){for(var c=a.split(" "),d=0;d2&&!(d&&8>e))}return sh?dh("span","\u200b"):dh("span","\xa0",null,"display: inline-block; width: 1px; margin-right: -1px")}function vh(a){if(null!=uh)return uh;var b=gh(a,document.createTextNode("A\u062eA")),c=eh(b,0,1).getBoundingClientRect();if(!c||c.left==c.right)return!1;var d=eh(b,1,2).getBoundingClientRect();return uh=d.right-c.right<3}function Ah(a){if(null!=zh)return zh;var b=gh(a,dh("span","x")),c=b.getBoundingClientRect(),d=eh(b,0,1).getBoundingClientRect();return zh=Math.abs(c.left-d.left)>1}function Ch(a,b,c,d){if(!a)return d(b,c,"ltr");for(var e=!1,f=0;fb||b==c&&g.to==b)&&(d(Math.max(g.from,b),Math.min(g.to,c),1==g.level?"rtl":"ltr"),e=!0)}e||d(b,c,"ltr")}function Dh(a){return a.level%2?a.to:a.from}function Eh(a){return a.level%2?a.from:a.to}function Fh(a){var b=cg(a);return b?Dh(b[0]):0}function Gh(a){var b=cg(a);return b?Eh(Sg(b)):a.text.length}function Hh(a,b){var c=Xf(a.doc,b),d=hf(c);d!=c&&(b=_f(d));var e=cg(d),f=e?e[0].level%2?Gh(d):Fh(d):0;return pb(b,f)}function Ih(a,b){for(var c,d=Xf(a.doc,b);c=ff(d);)d=c.find(1,!0).line,b=null;var e=cg(d),f=e?e[0].level%2?Fh(d):Gh(d):d.text.length;return pb(null==b?_f(d):b,f)}function Jh(a,b){var c=Hh(a,b.line),d=Xf(a.doc,c.line),e=cg(d);if(!e||0==e[0].level){var f=Math.max(0,d.text.search(/\S/)),g=b.line==c.line&&b.ch<=f&&b.ch;return pb(c.line,g?0:f)}return c}function Kh(a,b,c){var d=a[0].level;return b==d?!0:c==d?!1:c>b}function Mh(a,b){Lh=null;for(var d,c=0;cb)return c;if(e.from==b||e.to==b){if(null!=d)return Kh(a,e.level,a[d].level)?(e.from!=e.to&&(Lh=d),c):(e.from!=e.to&&(Lh=c),d);d=c}}return d}function Nh(a,b,c,d){if(!d)return b+c;do b+=c;while(b>0&&ch(a.text.charAt(b)));return b}function Oh(a,b,c,d){var e=cg(a);if(!e)return Ph(a,b,c,d);for(var f=Mh(e,b),g=e[f],h=Nh(a,b,g.level%2?-c:c,d);;){if(h>g.from&&h0==g.level%2?g.to:g.from);if(g=e[f+=c],!g)return null;h=c>0==g.level%2?Nh(a,g.to,-1,d):Nh(a,g.from,1,d)}}function Ph(a,b,c,d){var e=b+c;if(d)for(;e>0&&ch(a.text.charAt(e));)e+=c;return 0>e||e>a.text.length?null:e}var a=/gecko\/\d/i.test(navigator.userAgent),b=/MSIE \d/.test(navigator.userAgent),c=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent),d=b||c,e=d&&(b?document.documentMode||6:c[1]),f=/WebKit\//.test(navigator.userAgent),g=f&&/Qt\/\d+\.\d+/.test(navigator.userAgent),h=/Chrome\//.test(navigator.userAgent),i=/Opera\//.test(navigator.userAgent),j=/Apple Computer/.test(navigator.vendor),k=/KHTML\//.test(navigator.userAgent),l=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent),m=/PhantomJS/.test(navigator.userAgent),n=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\/\w+/.test(navigator.userAgent),o=n||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent),p=n||/Mac/.test(navigator.platform),q=/win/i.test(navigator.platform),r=i&&navigator.userAgent.match(/Version\/(\d*\.\d*)/);r&&(r=Number(r[1])),r&&r>=15&&(i=!1,f=!0);var s=p&&(g||i&&(null==r||12.11>r)),t=a||d&&e>=9,u=!1,v=!1;L.prototype=Xg({update:function(a){var b=a.scrollWidth>a.clientWidth+1,c=a.scrollHeight>a.clientHeight+1,d=a.nativeBarWidth;if(c){this.vert.style.display="block",this.vert.style.bottom=b?d+"px":"0";var e=a.viewHeight-(b?d:0);this.vert.firstChild.style.height=Math.max(0,a.scrollHeight-a.clientHeight+e)+"px"}else this.vert.style.display="",this.vert.firstChild.style.height="0";if(b){this.horiz.style.display="block",this.horiz.style.right=c?d+"px":"0",this.horiz.style.left=a.barLeft+"px";var f=a.viewWidth-a.barLeft-(c?d:0);this.horiz.firstChild.style.width=a.scrollWidth-a.clientWidth+f+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedOverlay&&a.clientHeight>0&&(0==d&&this.overlayHack(),this.checkedOverlay=!0),{right:c?d:0,bottom:b?d:0}},setScrollLeft:function(a){this.horiz.scrollLeft!=a&&(this.horiz.scrollLeft=a)},setScrollTop:function(a){this.vert.scrollTop!=a&&(this.vert.scrollTop=a)},overlayHack:function(){var a=p&&!l?"12px":"18px";this.horiz.style.minHeight=this.vert.style.minWidth=a;var b=this,c=function(a){wg(a)!=b.vert&&wg(a)!=b.horiz&&Qc(b.cm,md)(a)};yg(this.vert,"mousedown",c),yg(this.horiz,"mousedown",c)},clear:function(){var a=this.horiz.parentNode;a.removeChild(this.horiz),a.removeChild(this.vert)}},L.prototype),M.prototype=Xg({update:function(){return{bottom:0,right:0}},setScrollLeft:function(){},setScrollTop:function(){},clear:function(){}},M.prototype),w.scrollbarModel={"native":L,"null":M};var pb=w.Pos=function(a,b){return this instanceof pb?(this.line=a,this.ch=b,void 0):new pb(a,b)},qb=w.cmpPos=function(a,b){return a.line-b.line||a.ch-b.ch};ub.prototype={primary:function(){return this.ranges[this.primIndex]},equals:function(a){if(a==this)return!0;if(a.primIndex!=this.primIndex||a.ranges.length!=this.ranges.length)return!1;for(var b=0;b=0&&qb(a,d.to())<=0)return c}return-1}},vb.prototype={from:function(){return tb(this.anchor,this.head)},to:function(){return sb(this.anchor,this.head)},empty:function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch}};var Bc,nd,od,lc={left:0,right:0,top:0,bottom:0},Ec=null,Fc=0,cd=null,ud=0,zd=0,Ad=null;d?Ad=-.53:a?Ad=15:h?Ad=-.7:j&&(Ad=-1/3);var Bd=function(a){var b=a.wheelDeltaX,c=a.wheelDeltaY;return null==b&&a.detail&&a.axis==a.HORIZONTAL_AXIS&&(b=a.detail),null==c&&a.detail&&a.axis==a.VERTICAL_AXIS?c=a.detail:null==c&&(c=a.wheelDelta),{x:b,y:c}};w.wheelEventPixels=function(a){var b=Bd(a);return b.x*=Ad,b.y*=Ad,b};var Fd=new Ng,Jd=null,Sd=w.changeEnd=function(a){return a.text?pb(a.from.line+a.text.length-1,Sg(a.text).length+(1==a.text.length?a.from.ch:0)):a.to};w.prototype={constructor:w,focus:function(){window.focus(),fd(this),bd(this)},setOption:function(a,b){var c=this.options,d=c[a];(c[a]!=b||"mode"==a)&&(c[a]=b,qe.hasOwnProperty(a)&&Qc(this,qe[a])(this,b,d))},getOption:function(a){return this.options[a]},getDoc:function(){return this.doc},addKeyMap:function(a,b){this.state.keyMaps[b?"push":"unshift"](Ge(a))},removeKeyMap:function(a){for(var b=this.state.keyMaps,c=0;cc&&(ke(this,e.head.line,a,!0),c=e.head.line,d==this.doc.sel.primIndex&&ie(this));else{var f=e.from(),g=e.to(),h=Math.max(c,f.line);c=Math.min(this.lastLine(),g.line-(g.ch?0:1))+1;for(var i=h;c>i;++i)ke(this,i,a);var j=this.doc.sel.ranges;0==f.ch&&b.length==j.length&&j[d].from().ch>0&&Gb(this.doc,d,new vb(f,j[d].to()),Kg)}}}),getTokenAt:function(a,b){return yf(this,a,b)},getLineTokens:function(a,b){return yf(this,pb(a),b,!0)},getTokenTypeAt:function(a){a=zb(this.doc,a);var f,b=Bf(this,Xf(this.doc,a.line)),c=0,d=(b.length-1)/2,e=a.ch;if(0==e)f=b[2];else for(;;){var g=c+d>>1;if((g?b[2*g-1]:0)>=e)d=g;else{if(!(b[2*g+1]h?f:0==h?null:f.slice(0,h-1)},getModeAt:function(a){var b=this.doc.mode;return b.innerMode?w.innerMode(b,this.getTokenAt(a).state).mode:b},getHelper:function(a,b){return this.getHelpers(a,b)[0]},getHelpers:function(a,b){var c=[];if(!xe.hasOwnProperty(b))return xe;var d=xe[b],e=this.getModeAt(a);if("string"==typeof e[b])d[e[b]]&&c.push(d[e[b]]);else if(e[b])for(var f=0;fd&&(a=d,c=!0);var e=Xf(this.doc,a);return tc(this,e,{top:0,left:0},b||"page").top+(c?this.doc.height-bg(e):0)},defaultTextHeight:function(){return Cc(this.display)},defaultCharWidth:function(){return Dc(this.display)},setGutterMarker:Rc(function(a,b,c){return le(this.doc,a,"gutter",function(a){var d=a.gutterMarkers||(a.gutterMarkers={});return d[b]=c,!c&&ah(d)&&(a.gutterMarkers=null),!0})}),clearGutter:Rc(function(a){var b=this,c=b.doc,d=c.first;c.iter(function(c){c.gutterMarkers&&c.gutterMarkers[a]&&(c.gutterMarkers[a]=null,Wc(b,d,"gutter"),ah(c.gutterMarkers)&&(c.gutterMarkers=null)),++d})}),addLineWidget:Rc(function(a,b,c){return rf(this,a,b,c)}),removeLineWidget:function(a){a.clear()},lineInfo:function(a){if("number"==typeof a){if(!Bb(this.doc,a))return null;var b=a;if(a=Xf(this.doc,a),!a)return null}else{var b=_f(a);if(null==b)return null}return{line:b,handle:a,text:a.text,gutterMarkers:a.gutterMarkers,textClass:a.textClass,bgClass:a.bgClass,wrapClass:a.wrapClass,widgets:a.widgets}},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(a,b,c,d,e){var f=this.display;a=wc(this,zb(this.doc,a));var g=a.bottom,h=a.left;if(b.style.position="absolute",b.setAttribute("cm-ignore-events","true"),f.sizer.appendChild(b),"over"==d)g=a.top;else if("above"==d||"near"==d){var i=Math.max(f.wrapper.clientHeight,this.doc.height),j=Math.max(f.sizer.clientWidth,f.lineSpace.clientWidth);("above"==d||a.bottom+b.offsetHeight>i)&&a.top>b.offsetHeight?g=a.top-b.offsetHeight:a.bottom+b.offsetHeight<=i&&(g=a.bottom),h+b.offsetWidth>j&&(h=j-b.offsetWidth)}b.style.top=g+"px",b.style.left=b.style.right="","right"==e?(h=f.sizer.clientWidth-b.offsetWidth,b.style.right="0px"):("left"==e?h=0:"middle"==e&&(h=(f.sizer.clientWidth-b.offsetWidth)/2),b.style.left=h+"px"),c&&fe(this,h,g,h+b.offsetWidth,g+b.offsetHeight)},triggerOnKeyDown:Rc(Kd),triggerOnKeyPress:Rc(Nd),triggerOnKeyUp:Md,execCommand:function(a){return Ae.hasOwnProperty(a)?Ae[a](this):void 0},findPosH:function(a,b,c,d){var e=1;0>b&&(e=-1,b=-b);for(var f=0,g=zb(this.doc,a);b>f&&(g=ne(this.doc,g,e,c,d),!g.hitSide);++f);return g},moveH:Rc(function(a,b){var c=this;c.extendSelectionsBy(function(d){return c.display.shift||c.doc.extend||d.empty()?ne(c.doc,d.head,a,b,c.options.rtlMoveVisually):0>a?d.from():d.to()},Mg)}),deleteH:Rc(function(a,b){var c=this.doc.sel,d=this.doc;c.somethingSelected()?d.replaceSelection("",null,"+delete"):me(this,function(c){var e=ne(d,c.head,a,b,!1);return 0>a?{from:e,to:c.head}:{from:c.head,to:e}})}),findPosV:function(a,b,c,d){var e=1,f=d;0>b&&(e=-1,b=-b);for(var g=0,h=zb(this.doc,a);b>g;++g){var i=wc(this,h,"div");if(null==f?f=i.left:i.left=f,h=oe(this,i,e,c),h.hitSide)break}return h},moveV:Rc(function(a,b){var c=this,d=this.doc,e=[],f=!c.display.shift&&!d.extend&&d.sel.somethingSelected();if(d.extendSelectionsBy(function(g){if(f)return 0>a?g.from():g.to();var h=wc(c,g.head,"div");null!=g.goalColumn&&(h.left=g.goalColumn),e.push(h.left);var i=oe(c,h,a,b);return"page"==b&&g==d.sel.primary()&&he(c,null,vc(c,i,"div").top-h.top),i},Mg),e.length)for(var g=0;g0&&h(c.charAt(d-1));)--d;for(;e.5)&&C(this),Ag(this,"refresh",this)}),swapDoc:Rc(function(a){var b=this.doc;return b.cm=null,Wf(this,a),qc(this),ed(this),this.scrollTo(a.scrollLeft,a.scrollTop),this.curOp.forceScroll=!0,Cg(this,"swapDoc",this,b),b}),getInputField:function(){return this.display.input},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},Hg(w);var pe=w.defaults={},qe=w.optionHandlers={},se=w.Init={toString:function(){return"CodeMirror.Init"}};re("value","",function(a,b){a.setValue(b)},!0),re("mode",null,function(a,b){a.doc.modeOption=b,y(a)},!0),re("indentUnit",2,y,!0),re("indentWithTabs",!1),re("smartIndent",!0),re("tabSize",4,function(a){z(a),qc(a),Vc(a)},!0),re("specialChars",/[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g,function(a,b){a.options.specialChars=new RegExp(b.source+(b.test(" ")?"":"| "),"g"),a.refresh()},!0),re("specialCharPlaceholder",Hf,function(a){a.refresh()},!0),re("electricChars",!0),re("rtlMoveVisually",!q),re("wholeLineUpdateBefore",!0),re("theme","default",function(a){D(a),E(a)},!0),re("keyMap","default",function(a,b,c){var d=Ge(b),e=c!=w.Init&&Ge(c);e&&e.detach&&e.detach(a,d),d.attach&&d.attach(a,e||null)}),re("extraKeys",null),re("lineWrapping",!1,A,!0),re("gutters",[],function(a){J(a.options),E(a)},!0),re("fixedGutter",!0,function(a,b){a.display.gutters.style.left=b?U(a.display)+"px":"0",a.refresh()},!0),re("coverGutterNextToScrollbar",!1,function(a){O(a)},!0),re("scrollbarStyle","native",function(a){N(a),O(a),a.display.scrollbars.setScrollTop(a.doc.scrollTop),a.display.scrollbars.setScrollLeft(a.doc.scrollLeft)},!0),re("lineNumbers",!1,function(a){J(a.options),E(a)},!0),re("firstLineNumber",1,E,!0),re("lineNumberFormatter",function(a){return a},E,!0),re("showCursorWhenSelecting",!1,Sb,!0),re("resetSelectionOnContextMenu",!0),re("readOnly",!1,function(a,b){"nocursor"==b?(Pd(a),a.display.input.blur(),a.display.disabled=!0):(a.display.disabled=!1,b||ed(a))}),re("disableInput",!1,function(a,b){b||ed(a)},!0),re("dragDrop",!0),re("cursorBlinkRate",530),re("cursorScrollMargin",0),re("cursorHeight",1,Sb,!0),re("singleCursorHeightPerLine",!0,Sb,!0),re("workTime",100),re("workDelay",100),re("flattenSpans",!0,z,!0),re("addModeClass",!1,z,!0),re("pollInterval",100),re("undoDepth",200,function(a,b){a.doc.history.undoDepth=b}),re("historyEventDelay",1250),re("viewportMargin",10,function(a){a.refresh()},!0),re("maxHighlightLength",1e4,z,!0),re("moveInputWithCursor",!0,function(a,b){b||(a.display.inputDiv.style.top=a.display.inputDiv.style.left=0)}),re("tabindex",null,function(a,b){a.display.input.tabIndex=b||""}),re("autofocus",null);var te=w.modes={},ue=w.mimeModes={};w.defineMode=function(a,b){w.defaults.mode||"null"==a||(w.defaults.mode=a),arguments.length>2&&(b.dependencies=Array.prototype.slice.call(arguments,2)),te[a]=b},w.defineMIME=function(a,b){ue[a]=b},w.resolveMode=function(a){if("string"==typeof a&&ue.hasOwnProperty(a))a=ue[a];else if(a&&"string"==typeof a.name&&ue.hasOwnProperty(a.name)){var b=ue[a.name];"string"==typeof b&&(b={name:b}),a=Wg(b,a),a.name=b.name}else if("string"==typeof a&&/^[\w\-]+\/[\w\-]+\+xml$/.test(a))return w.resolveMode("application/xml");return"string"==typeof a?{name:a}:a||{name:"null"}},w.getMode=function(a,b){var b=w.resolveMode(b),c=te[b.name];if(!c)return w.getMode(a,"text/plain");var d=c(a,b);if(ve.hasOwnProperty(b.name)){var e=ve[b.name];for(var f in e)e.hasOwnProperty(f)&&(d.hasOwnProperty(f)&&(d["_"+f]=d[f]),d[f]=e[f])}if(d.name=b.name,b.helperType&&(d.helperType=b.helperType),b.modeProps)for(var f in b.modeProps)d[f]=b.modeProps[f];return d},w.defineMode("null",function(){return{token:function(a){a.skipToEnd()}}}),w.defineMIME("text/plain","null");var ve=w.modeExtensions={};w.extendMode=function(a,b){var c=ve.hasOwnProperty(a)?ve[a]:ve[a]={};Xg(b,c)},w.defineExtension=function(a,b){w.prototype[a]=b},w.defineDocExtension=function(a,b){Sf.prototype[a]=b},w.defineOption=re;var we=[];w.defineInitHook=function(a){we.push(a)};var xe=w.helpers={};w.registerHelper=function(a,b,c){xe.hasOwnProperty(a)||(xe[a]=w[a]={_global:[]}),xe[a][b]=c},w.registerGlobalHelper=function(a,b,c,d){w.registerHelper(a,b,d),xe[a]._global.push({pred:c,val:d})};var ye=w.copyState=function(a,b){if(b===!0)return b;if(a.copyState)return a.copyState(b);var c={};for(var d in b){var e=b[d];e instanceof Array&&(e=e.concat([])),c[d]=e}return c},ze=w.startState=function(a,b,c){return a.startState?a.startState(b,c):!0};w.innerMode=function(a,b){for(;a.innerMode;){var c=a.innerMode(b);if(!c||c.mode==a)break;b=c.state,a=c.mode}return c||{mode:a,state:b}};var Ae=w.commands={selectAll:function(a){a.setSelection(pb(a.firstLine(),0),pb(a.lastLine()),Kg)},singleSelection:function(a){a.setSelection(a.getCursor("anchor"),a.getCursor("head"),Kg)},killLine:function(a){me(a,function(b){if(b.empty()){var c=Xf(a.doc,b.head.line).text.length;return b.head.ch==c&&b.head.line0)e=new pb(e.line,e.ch+1),a.replaceRange(f.charAt(e.ch-1)+f.charAt(e.ch-2),pb(e.line,e.ch-2),e,"+transpose");else if(e.line>a.doc.first){var g=Xf(a.doc,e.line-1).text;g&&a.replaceRange(f.charAt(0)+"\n"+g.charAt(g.length-1),pb(e.line-1,g.length-1),pb(e.line,1),"+transpose")}c.push(new vb(e,e))}a.setSelections(c)})},newlineAndIndent:function(a){Pc(a,function(){for(var b=a.listSelections().length,c=0;b>c;c++){var d=a.listSelections()[c];a.replaceRange("\n",d.anchor,d.head,"+input"),a.indentLine(d.from().line+1,null,!0),ie(a)}})},toggleOverwrite:function(a){a.toggleOverwrite()}},Be=w.keyMap={};Be.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Be.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Be.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars"},Be.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Be["default"]=p?Be.macDefault:Be.pcDefault,w.normalizeKeyMap=function(a){var b={};for(var c in a)if(a.hasOwnProperty(c)){var d=a[c];if(/^(name|fallthrough|(de|at)tach)$/.test(c))continue;if("..."==d){delete a[c];continue}for(var e=Vg(c.split(" "),Ce),f=0;f=this.string.length},sol:function(){return this.pos==this.lineStart},peek:function(){return this.string.charAt(this.pos)||void 0},next:function(){return this.posb},eatSpace:function(){for(var a=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>a},skipToEnd:function(){this.pos=this.string.length},skipTo:function(a){var b=this.string.indexOf(a,this.pos);return b>-1?(this.pos=b,!0):void 0},backUp:function(a){this.pos-=a},column:function(){return this.lastColumnPos0?null:(f&&b!==!1&&(this.pos+=f[0].length),f)}var d=function(a){return c?a.toLowerCase():a},e=this.string.substr(this.pos,a.length);return d(e)==d(a)?(b!==!1&&(this.pos+=a.length),!0):void 0},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(a,b){this.lineStart+=a;try{return b()}finally{this.lineStart-=a}}};var Ie=w.TextMarker=function(a,b){this.lines=[],this.type=b,this.doc=a};Hg(Ie),Ie.prototype.clear=function(){if(!this.explicitlyCleared){var a=this.doc.cm,b=a&&!a.curOp;if(b&&Gc(a),Gg(this,"clear")){var c=this.find();c&&Cg(this,"clear",c.from,c.to)}for(var d=null,e=null,f=0;fa.display.maxLineLength&&(a.display.maxLine=i,a.display.maxLineLength=j,a.display.maxLineChanged=!0)}null!=d&&a&&this.collapsed&&Vc(a,d,e+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,a&&Nb(a.doc)),a&&Cg(a,"markerCleared",a,this),b&&Ic(a),this.parent&&this.parent.clear()}},Ie.prototype.find=function(a,b){null==a&&"bookmark"==this.type&&(a=1);for(var c,d,e=0;ec;++c){var e=this.lines[c];this.height-=e.height,uf(e),Cg(e,"delete")}this.lines.splice(a,b)},collapse:function(a){a.push.apply(a,this.lines)},insertInner:function(a,b,c){this.height+=c,this.lines=this.lines.slice(0,a).concat(b).concat(this.lines.slice(a));for(var d=0;da;++a)if(c(this.lines[a]))return!0}},Qf.prototype={chunkSize:function(){return this.size},removeInner:function(a,b){this.size-=b;for(var c=0;ca){var f=Math.min(b,e-a),g=d.height;if(d.removeInner(a,f),this.height-=g-d.height,e==f&&(this.children.splice(c--,1),d.parent=null),0==(b-=f))break;a=0}else a-=e}if(this.size-b<25&&(this.children.length>1||!(this.children[0]instanceof Pf))){var h=[];this.collapse(h),this.children=[new Pf(h)],this.children[0].parent=this}},collapse:function(a){for(var b=0;b=a){if(e.insertInner(a,b,c),e.lines&&e.lines.length>50){for(;e.lines.length>50;){var g=e.lines.splice(e.lines.length-25,25),h=new Pf(g);e.height-=h.height,this.children.splice(d+1,0,h),h.parent=this}this.maybeSpill()}break}a-=f}},maybeSpill:function(){if(!(this.children.length<=10)){var a=this;do{var b=a.children.splice(a.children.length-5,5),c=new Qf(b);if(a.parent){a.size-=c.size,a.height-=c.height;var e=Ug(a.parent.children,a);a.parent.children.splice(e+1,0,c)}else{var d=new Qf(a.children);d.parent=a,a.children=[d,c],a=d}c.parent=a.parent}while(a.children.length>10);a.parent.maybeSpill()}},iterN:function(a,b,c){for(var d=0;da){var g=Math.min(b,f-a);if(e.iterN(a,g,c))return!0;if(0==(b-=g))break;a=0}else a-=f}}};var Rf=0,Sf=w.Doc=function(a,b,c){if(!(this instanceof Sf))return new Sf(a,b,c);null==c&&(c=0),Qf.call(this,[new Pf([new sf("",null)])]),this.first=c,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1,this.frontier=c;var d=pb(c,0);this.sel=xb(d),this.history=new dg(null),this.id=++Rf,this.modeOption=b,"string"==typeof a&&(a=wh(a)),Of(this,{from:d,to:d,text:a}),Kb(this,xb(d),Kg)};Sf.prototype=Wg(Qf.prototype,{constructor:Sf,iter:function(a,b,c){c?this.iterN(a-this.first,b-a,c):this.iterN(this.first,this.first+this.size,a)},insert:function(a,b){for(var c=0,d=0;d=0;f--)Yd(this,d[f]);h?Jb(this,h):this.cm&&ie(this.cm)}),undo:Sc(function(){$d(this,"undo")}),redo:Sc(function(){$d(this,"redo")}),undoSelection:Sc(function(){$d(this,"undo",!0)}),redoSelection:Sc(function(){$d(this,"redo",!0)}),setExtending:function(a){this.extend=a},getExtending:function(){return this.extend},historySize:function(){for(var a=this.history,b=0,c=0,d=0;d=a.ch)&&b.push(e.marker.parent||e.marker)}return b},findMarks:function(a,b,c){a=zb(this,a),b=zb(this,b);var d=[],e=a.line;return this.iter(a.line,b.line+1,function(f){var g=f.markedSpans;if(g)for(var h=0;hi.to||null==i.from&&e!=a.line||e==b.line&&i.from>b.ch||c&&!c(i.marker)||d.push(i.marker.parent||i.marker)}++e}),d},getAllMarks:function(){var a=[];return this.iter(function(b){var c=b.markedSpans;if(c)for(var d=0;da?(b=a,!0):(a-=e,++c,void 0)}),zb(this,pb(c,b))},indexFromPos:function(a){a=zb(this,a);var b=a.ch;return a.lineb&&(b=a.from),null!=a.to&&a.toh||h>=b)return g+(b-f);g+=h-f,g+=c-g%c,f=h+1}},Qg=[""],Tg=function(a){a.select()};n?Tg=function(a){a.selectionStart=0,a.selectionEnd=a.value.length}:d&&(Tg=function(a){try{a.select()}catch(b){}}),[].indexOf&&(Ug=function(a,b){return a.indexOf(b)}),[].map&&(Vg=function(a,b){return a.map(b)});var eh,Zg=/[\u00df\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/,$g=w.isWordChar=function(a){return/\w/.test(a)||a>"\x80"&&(a.toUpperCase()!=a.toLowerCase()||Zg.test(a))},bh=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;eh=document.createRange?function(a,b,c){var d=document.createRange();return d.setEnd(a,c),d.setStart(a,b),d}:function(a,b,c){var d=document.body.createTextRange();try{d.moveToElementText(a.parentNode)}catch(e){return d}return d.collapse(!0),d.moveEnd("character",c),d.moveStart("character",b),d},d&&11>e&&(ih=function(){try{return document.activeElement}catch(a){return document.body}});var sh,uh,kh=w.rmClass=function(a,b){var c=a.className,d=jh(b).exec(c);if(d){var e=c.slice(d.index+d[0].length);a.className=c.slice(0,d.index)+(e?d[1]+e:"")}},lh=w.addClass=function(a,b){var c=a.className;jh(b).test(c)||(a.className+=(c?" ":"")+b)},oh=!1,rh=function(){if(d&&9>e)return!1;var a=dh("div");return"draggable"in a||"dragDrop"in a}(),wh=w.splitLines=3!="\n\nb".split(/\n/).length?function(a){for(var b=0,c=[],d=a.length;d>=b;){var e=a.indexOf("\n",b);-1==e&&(e=a.length);var f=a.slice(b,"\r"==a.charAt(e-1)?e-1:e),g=f.indexOf("\r");-1!=g?(c.push(f.slice(0,g)),b+=g+1):(c.push(f),b=e+1)}return c}:function(a){return a.split(/\r\n?|\n/)},xh=window.getSelection?function(a){try{return a.selectionStart!=a.selectionEnd}catch(b){return!1}}:function(a){try{var b=a.ownerDocument.selection.createRange()}catch(c){}return b&&b.parentElement()==a?0!=b.compareEndPoints("StartToEnd",b):!1},yh=function(){var a=dh("div");return"oncopy"in a?!0:(a.setAttribute("oncopy","return;"),"function"==typeof a.oncopy)}(),zh=null,Bh={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",107:"=",109:"-",127:"Delete",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"};w.keyNames=Bh,function(){for(var a=0;10>a;a++)Bh[a+48]=Bh[a+96]=String(a);for(var a=65;90>=a;a++)Bh[a]=String.fromCharCode(a);for(var a=1;12>=a;a++)Bh[a+111]=Bh[a+63235]="F"+a}();var Lh,Qh=function(){function c(c){return 247>=c?a.charAt(c):c>=1424&&1524>=c?"R":c>=1536&&1773>=c?b.charAt(c-1536):c>=1774&&2220>=c?"r":c>=8192&&8203>=c?"w":8204==c?"b":"L"}function j(a,b,c){this.level=a,this.from=b,this.to=c}var a="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",b="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm",d=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,e=/[stwN]/,f=/[LRr]/,g=/[Lb1n]/,h=/[1n]/,i="L";return function(a){if(!d.test(a))return!1;for(var m,b=a.length,k=[],l=0;b>l;++l)k.push(m=c(a.charCodeAt(l)));for(var l=0,n=i;b>l;++l){var m=k[l];"m"==m?k[l]=n:n=m}for(var l=0,o=i;b>l;++l){var m=k[l];"1"==m&&"r"==o?k[l]="n":f.test(m)&&(o=m,"r"==m&&(k[l]="R"))}for(var l=1,n=k[0];b-1>l;++l){var m=k[l];"+"==m&&"1"==n&&"1"==k[l+1]?k[l]="1":","!=m||n!=k[l+1]||"1"!=n&&"n"!=n||(k[l]=n),n=m}for(var l=0;b>l;++l){var m=k[l];if(","==m)k[l]="N";else if("%"==m){for(var p=l+1;b>p&&"%"==k[p];++p);for(var q=l&&"!"==k[l-1]||b>p&&"1"==k[p]?"1":"N",r=l;p>r;++r)k[r]=q;l=p-1}}for(var l=0,o=i;b>l;++l){var m=k[l];"L"==o&&"1"==m?k[l]="L":f.test(m)&&(o=m)}for(var l=0;b>l;++l)if(e.test(k[l])){for(var p=l+1;b>p&&e.test(k[p]);++p);for(var s="L"==(l?k[l-1]:i),t="L"==(b>p?k[p]:i),q=s||t?"L":"R",r=l;p>r;++r)k[r]=q;l=p-1}for(var v,u=[],l=0;b>l;)if(g.test(k[l])){var w=l;for(++l;b>l&&g.test(k[l]);++l);u.push(new j(0,w,l))}else{var x=l,y=u.length;for(++l;b>l&&"L"!=k[l];++l);for(var r=x;l>r;)if(h.test(k[r])){r>x&&u.splice(y,0,new j(1,x,r));var z=r;for(++r;l>r&&h.test(k[r]);++r);u.splice(y,0,new j(2,z,r)),x=r}else++r;l>x&&u.splice(y,0,new j(1,x,l))}return 1==u[0].level&&(v=a.match(/^\s+/))&&(u[0].from=v[0].length,u.unshift(new j(0,0,v[0].length))),1==Sg(u).level&&(v=a.match(/\s+$/))&&(Sg(u).to-=v[0].length,u.push(new j(0,b-v[0].length,b))),u[0].level!=Sg(u).level&&u.push(new j(u[0].level,b,b)),u}}();return w.version="4.9.1",w}),function(a){"object"==typeof exports&&"object"==typeof module?a(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],a):a(CodeMirror)}(function(a){"use strict";function b(a){return new RegExp("^(("+a.join(")|(")+"))\\b")}function h(a){return a.scopes[a.scopes.length-1]}var c=b(["and","or","not","is"]),d=["as","assert","break","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","lambda","pass","raise","return","try","while","with","yield","in"],e=["abs","all","any","bin","bool","bytearray","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip","__import__","NotImplemented","Ellipsis","__debug__"],f={builtins:["apply","basestring","buffer","cmp","coerce","execfile","file","intern","long","raw_input","reduce","reload","unichr","unicode","xrange","False","True","None"],keywords:["exec","print"]},g={builtins:["ascii","bytes","exec","print"],keywords:["nonlocal","False","True","None"]};a.registerHelper("hintWords","python",d.concat(e)),a.defineMode("python",function(i,j){function x(a,b){if(a.sol()&&"py"==h(b).type){var c=h(b).offset;if(a.eatSpace()){var d=a.indentation();return d>c?A(a,b,"py"):c>d&&B(a,b)&&(b.errorToken=!0),null}var e=y(a,b);return c>0&&B(a,b)&&(e+=" "+k),e}return y(a,b)}function y(a,b){if(a.eatSpace())return null;var d=a.peek();if("#"==d)return a.skipToEnd(),"comment";if(a.match(/^[0-9\.]/,!1)){var e=!1;if(a.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)&&(e=!0),a.match(/^\d+\.\d*/)&&(e=!0),a.match(/^\.\d+/)&&(e=!0),e)return a.eat(/J/i),"number";var f=!1;if(a.match(/^0x[0-9a-f]+/i)&&(f=!0),a.match(/^0b[01]+/i)&&(f=!0),a.match(/^0o[0-7]+/i)&&(f=!0),a.match(/^[1-9]\d*(e[\+\-]?\d+)?/)&&(a.eat(/J/i),f=!0),a.match(/^0(?![\dx])/i)&&(f=!0),f)return a.eat(/L/i),"number"}return a.match(u)?(b.tokenize=z(a.current()),b.tokenize(a,b)):a.match(o)||a.match(n)?null:a.match(m)||a.match(p)||a.match(c)?"operator":a.match(l)?null:a.match(v)?"keyword":a.match(w)?"builtin":a.match(/^(self|cls)\b/)?"variable-2":a.match(q)?"def"==b.lastToken||"class"==b.lastToken?"def":"variable":(a.next(),k)}function z(a){function d(d,e){for(;!d.eol();)if(d.eatWhile(/[^'"\\]/),d.eat("\\")){if(d.next(),b&&d.eol())return c}else{if(d.match(a))return e.tokenize=x,c;d.eat(/['"]/)}if(b){if(j.singleLineStringErrors)return k;e.tokenize=x}return c}for(;"rub".indexOf(a.charAt(0).toLowerCase())>=0;)a=a.substr(1);var b=1==a.length,c="string";return d.isString=!0,d}function A(a,b,c){var d=0,e=null;if("py"==c)for(;"py"!=h(b).type;)b.scopes.pop();d=h(b).offset+("py"==c?i.indentUnit:r),"py"==c||a.match(/^(\s|#.*)*$/,!1)||(e=a.column()+1),b.scopes.push({offset:d,type:c,align:e})}function B(a,b){for(var c=a.indentation();h(b).offset>c;){if("py"!=h(b).type)return!0;b.scopes.pop()}return h(b).offset!=c}function C(a,b){var c=b.tokenize(a,b),d=a.current();if("."==d)return c=a.match(q,!1)?null:k,null==c&&"meta"==b.lastStyle&&(c="meta"),c;if("@"==d)return j.version&&3==parseInt(j.version,10)?a.match(q,!1)?"meta":"operator":a.match(q,!1)?"meta":k;"variable"!=c&&"builtin"!=c||"meta"!=b.lastStyle||(c="meta"),("pass"==d||"return"==d)&&(b.dedent+=1),"lambda"==d&&(b.lambda=!0),":"!=d||b.lambda||"py"!=h(b).type||A(a,b,"py");var e=1==d.length?"[({".indexOf(d):-1;if(-1!=e&&A(a,b,"])}".slice(e,e+1)),e="])}".indexOf(d),-1!=e){if(h(b).type!=d)return k;b.scopes.pop()}return b.dedent>0&&a.eol()&&"py"==h(b).type&&(b.scopes.length>1&&b.scopes.pop(),b.dedent-=1),c}var k="error",l=j.singleDelimiters||new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]"),m=j.doubleOperators||new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))"),n=j.doubleDelimiters||new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))"),o=j.tripleDelimiters||new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");if(j.version&&3==parseInt(j.version,10))var p=j.singleOperators||new RegExp("^[\\+\\-\\*/%&|\\^~<>!@]"),q=j.identifiers||new RegExp("^[_A-Za-z\xa1-\uffff][_A-Za-z0-9\xa1-\uffff]*");else var p=j.singleOperators||new RegExp("^[\\+\\-\\*/%&|\\^~<>!]"),q=j.identifiers||new RegExp("^[_A-Za-z][_A-Za-z0-9]*");var r=j.hangingIndent||i.indentUnit,s=d,t=e;if(void 0!=j.extra_keywords&&(s=s.concat(j.extra_keywords)),void 0!=j.extra_builtins&&(t=t.concat(j.extra_builtins)),j.version&&3==parseInt(j.version,10)){s=s.concat(g.keywords),t=t.concat(g.builtins);var u=new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))","i")}else{s=s.concat(f.keywords),t=t.concat(f.builtins);var u=new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))","i")}var v=b(s),w=b(t),D={startState:function(a){return{tokenize:x,scopes:[{offset:a||0,type:"py",align:null}],lastStyle:null,lastToken:null,lambda:!1,dedent:0}},token:function(a,b){var c=b.errorToken;c&&(b.errorToken=!1);var d=C(a,b);b.lastStyle=d;var e=a.current();return e&&d&&(b.lastToken=e),a.eol()&&b.lambda&&(b.lambda=!1),c?d+" "+k:d},indent:function(b,c){if(b.tokenize!=x)return b.tokenize.isString?a.Pass:0;var d=h(b),e=c&&c.charAt(0)==d.type;return null!=d.align?d.align-(e?1:0):e&&b.scopes.length>1?b.scopes[b.scopes.length-2].offset:d.offset},lineComment:"#",fold:"indent"};return D}),a.defineMIME("text/x-python","python");var i=function(a){return a.split(" ")};a.defineMIME("text/x-cython",{name:"python",extra_keywords:i("by cdef cimport cpdef ctypedef enum exceptextern gil include nogil property publicreadonly struct union DEF IF ELIF ELSE")})}); ================================================ FILE: www-emu/demo_gen.py ================================================ import sys import os outfile = open('demo_scripts.js', 'w') for filename in os.listdir(): if filename[-9:] == '_demos.py': infile = open(filename, 'r') outfile.write('var ' + filename[:-9] + '_demos = new Map([["CHOOSE A DEMO...", "# Welcome to MicroPython on Unicorn!\\n\\n# The terminal beside this is no ordinary REPL.\\n# It utilizes the Unicorn CPU emulator converted\\n# to Javascript by Unicorn.js in order to run MicroPython\\n# \\\"bare metal\\\" on an ARM CPU emulation.\\n\\n# MicroPython on Unicorn is completely open source so \\n# make sure to report bugs to the issue tracker!.\\n\\n# Source: https://github.com/micropython/micropython-unicorn\\n\\n# The user and reset buttons along with the LEDs and pins\\n# on the pyboard below are fully functional. Unfortunately\\n# that\'s not quite the case for the clock speed approximation\\n# when delayed.\\n\\n# Try to write a script, paste some code or run a demo!\\n"], ') for demo in infile.read().split('#####\n'): outfile.write('["' + demo.split('\n')[0][2:] + '", "') for line in demo.split('\n')[1:-1]: outfile.write(line + '\\n') outfile.write('"], ') outfile.write(']);\n'); ================================================ FILE: www-emu/features_demos.py ================================================ # HELLO WORLD! # hello world! print('hello world') ##### # BIG INTEGER # bignum print(1 << 1000) ##### # ASSEMBLY # inline assembler @micropython.asm_thumb def asm_add(r0, r1): add(r0, r0, r1) print(asm_add(1, 2)) ================================================ FILE: www-emu/fit.js ================================================ /** * Fit terminal columns and rows to the dimensions of its DOM element. * * ## Approach * - Rows: Truncate the division of the terminal parent element height by the terminal row height. * * - Columns: Truncate the division of the terminal parent element width by the terminal character * width (apply display: inline at the terminal row and truncate its width with the current * number of columns). * @module xterm/addons/fit/fit * @license MIT */ (function (fit) { if (typeof exports === 'object' && typeof module === 'object') { /* * CommonJS environment */ module.exports = fit(require('../../xterm')); } else if (typeof define == 'function') { /* * Require.js is available */ define(['../../xterm'], fit); } else { /* * Plain browser environment */ fit(window.Terminal); } })(function (Xterm) { var exports = {}; exports.proposeGeometry = function (term) { if (!term.element.parentElement) { return null; } var parentElementStyle = window.getComputedStyle(term.element.parentElement), parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')), parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17), elementStyle = window.getComputedStyle(term.element), elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')), elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')), availableHeight = parentElementHeight - elementPaddingVer, availableWidth = parentElementWidth - elementPaddingHor, container = term.rowContainer, subjectRow = term.rowContainer.firstElementChild, contentBuffer = subjectRow.innerHTML, characterHeight, rows, characterWidth, cols, geometry; subjectRow.style.display = 'inline'; subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace characterWidth = subjectRow.getBoundingClientRect().width; subjectRow.style.display = ''; // Revert style before calculating height, since they differ. characterHeight = subjectRow.getBoundingClientRect().height; subjectRow.innerHTML = contentBuffer; rows = parseInt(availableHeight / characterHeight); cols = parseInt(availableWidth / characterWidth); geometry = {cols: cols, rows: rows}; return geometry; }; exports.fit = function (term) { var geometry = exports.proposeGeometry(term); if (geometry) { term.resize(geometry.cols, geometry.rows); } }; Xterm.prototype.proposeGeometry = function () { return exports.proposeGeometry(this); }; Xterm.prototype.fit = function () { return exports.fit(this); }; return exports; }); ================================================ FILE: www-emu/index.html ================================================ MicroPython on Unicorn

BINARY :   RAM :   STACK :  


CLOCK SPEED MHz



PERIPHERALS :


LED
I2C LCD
SERVO
ADC

================================================ FILE: www-emu/minimal_demos.py ================================================ # HELLO WORLD! # hello world! print('hello world') ================================================ FILE: www-emu/mp_unicorn.css ================================================ body { font-size: 11pt; font-family: 'Open Sans'; margin: 0 0 0 0; line-height: 200%; } p { display: inline-block; margin: 0; } a, ins{ text-decoration: none; } #wrap { width: 96vw; margin: 2vw auto; } #col1 { float: left; width: 48vw } #col2 { float: right; width: 48vw; } #editor_wrap { height: 50vh; } .CodeMirror { height: 100%; font-family: 'Droid Sans Mono', monospace; } #terminal { line-height: 100%; height: 50vh; padding: 0; } .terminal { font-family: 'Droid Sans Mono', monospace; } #checkboxes { float: left; } #checkbox_table { width: 120%; } #PYB { position: absolute; right: 0; bottom: 2%; float: right; } .PYB { position: absolute; height: 30vh; bottom: 0; right: 0; } #base { z-index: 0; } .LED { display: none; z-index: 1; } #button_layer { z-index: 2; } .component { display: none; } #pin_servo_blade { height: 15vh; right: 11.95vh; bottom: 0.89vh; } #adc_slider { position: absolute; bottom: 22.30vh; right: 62.15vh; width: 15vh; } #lcd_unicorn { position: absolute; right: 56.15vh; bottom: 2vh; width: 256px; height: 128px; background: #354359; border: 3px; border-color: #171d26; border-style: solid; } .nav { display: block; } .navbar-container { padding-bottom: 1px; background-color: #2b2728; } .navbar { background-color: #2b2728; font-family: 'Montserrat', sans-serif; margin-left: auto; margin-right: auto; margin-bottom: 10px; width: 820px; } .navbar a { color: white; } .navbar a:hover { color: #d43738; } .navbar .navbar-brand { padding-top: 10px; font-size: 18px; font-weight: bold; } .navbar .navbar-brand img { vertical-align: middle; } .navbar .navbar-nav { float: right; padding-top: 10px; font-size: 12px; font-weight: bold; } button, select { position: relative; z-index: 3; line-height: normal; height: 27px; -moz-appearance: none; -webkit-appearance: none; cursor: pointer; color: white; font-family: 'Montserrat', sans-serif; font-size: 12px; padding: 5px 10px; border: 0; border-radius: 0; outline: 0; margin: 10px 10px 0px 0px; } button:hover, select:hover { filter: brightness(150%); } .red-element { background-color: #ff6464; } .green-element { background-color: #61ed61; } .blue-element { background-color: #649fff; } input { position: relative; z-index: 3; cursor: pointer; } input[type=checkbox] { -moz-appearance: none; -webkit-appearance: none; background-color: #ffffff; padding: 4px; border-style: solid; border-width: 2px; border-color: #ffd064; outline: 0; margin-right: 4px; display: inline-block; position: relative; } input[type=checkbox]:checked { background-color: #ffd064; padding: 6px; border: 0; } input[type=range] { -webkit-appearance: none; -moz-appearance: none; background: transparent; outline: 0; border: 0; margin: 0; padding: 0; } input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; height: 3vh; width: 1vh; border-radius: 0; outline: 0; border: 0; background: #ff64ff; margin-top: -1.1vh; } input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 0.7vh; margin-top: -2.70vh; background: #ff64ff; } input[type=range]::-moz-range-thumb { -moz-appearance: none; height: 3vh; width: 1vh; border-radius: 0; outline: 0; border: 0; background: #ff64ff; } input[type=range]::-moz-range-track { -moz-appearance: none; width: 100%; height: 0.7vh; background: #ff64ff; } ================================================ FILE: www-emu/mp_unicorn.js ================================================ var FLASH_ADDRESS = 0x08000000; var FLASH_SIZE = 0x100000; var RAM_ADDRESS = 0x20000000; var MAX_RAM_SIZE = 0x40000; var PERIPHERAL_ADDRESS = 0x40000000; var PERIPHERAL_SIZE = 0x10000; var UART0_TXR = 0x40000000; var UART0_RXR = 0x40000004; var UNICORN_CONTROLLER_PENDING = 0x40000100; var UNICORN_CONTROLLER_EXCEPTION = 0x40000104; var UNICORN_CONTROLLER_INTR_CHAR = 0x40000108; var UNICORN_CONTROLLER_RAM_SIZE = 0x4000010c; var UNICORN_CONTROLLER_STACK_SIZE = 0x40000110; var UNICORN_CONTROLLER_IDLE = 0x40000114; var UNICORN_CONTROLLER_INSNS = 0x40000118; var GPIO_ODR = 0x40000200; var GPIO_IDR = 0x40000204; var GPIO_X_ODR = 0x40000208; var GPIO_X_IDR = 0x4000020c; var GPIO_Y_ODR = 0x40000210; var GPIO_Y_IDR = 0x40000214; var SERVO_1_ANGLE = 0x40000218; var SERVO_1_TIME = 0x4000021c; var ADC_X_IDR = 0x40000220; var ADC_Y_IDR = 0x40000250; var RTC_TICKS_MS = 0x40000300; var RTC_TICKS_US = 0x40000304; var I2C_DATA = 0x40000400; var I2C_COMMAND = 0x40000404; var CYCLE_LIMIT = 50000; var prev_binary = ""; var user_button_state = 0; var epoch; var servo_angle = 0; var servo_target = 0; var servo_speed = 1; var LCD_WIDTH = 64; var LCD_HEIGHT = 32; var EPSILON = 0.5; var TICK_INSN_RATIO = 2.5; // The approximate number of clock ticks per instruction found through experimentation var HARD_I2C_SCL_X = 9 var HARD_I2C_SDA_X = 10 var pins_x = 0; var pins_y = 0; class I2C { constructor(address, scl, sda) { this.address = address; this.scl_gpio = scl[0] this.scl_pin = scl[1] this.sda_gpio = sda[0] this.sda_pin = sda[1] this.active = true; this.selected = false; this.rw = 0; this.data = 0; this.recv = 0; this.send = -1; this.buffer = [] } write(val) { var scl = this.scl_gpio(this.scl_pin) var nscl = extract_pin(val, this.scl_pin); var sda = this.sda_gpio(this.sda_pin) var nsda = extract_pin(val, this.sda_pin); if (nsda != sda) { if (scl) { if (!nsda) { // Start bit this.active = true; this.selected = false; this.recv = 0; this.data = 0; this.buffer = []; } else { // Stop bit this.active = false; if (this.selected) { this.process(); this.selected = false; } } } } if (nscl != scl && this.active) { if (nscl) { if (this.recv < 8) { this.data = (this.data << 1) + sda; this.recv++; } else { if (this.selected) { // Receive data this.buffer.push(this.data); this.send = 0; this.data = 0; this.recv = 0; } else if ((this.data >> 1) == this.address) { this.selected = true; this.rw = this.data & 1; this.send = 0; this.data = 0; this.recv = 0; } else { this.active = false; } } } else if (!nscl) { this.send = -1; } } } read(GPIO, pins) { if (this.sda_gpio.name != GPIO || this.send == -1) { return pins; } pins = set_pin(pins, this.sda_pin, this.send); return pins; } process() { } } class LCD extends I2C { process() { var ctx = lcd_unicorn.getContext('2d'); ctx.fillStyle = 'rgb(255, 255, 255)'; for (var j = 0; j < LCD_HEIGHT; j++) { for (var i = 0; i < LCD_WIDTH / 8; i++) { if (this.buffer.length == 0) { return; } var bite = this.buffer.shift(); for (var k = 7; k >= 0; k--) { if (bite >> k & 1) { ctx.fillRect(i * 4 * 8 + ((7 - k) * 4), j * 4, 4, 4); } else { ctx.clearRect(i * 4 * 8 + ((7 - k) * 4), j * 4, 4, 4); } } } } } } var i2c_devices = new Map([[8, new LCD(8, [X, HARD_I2C_SCL_X], [X, HARD_I2C_SDA_X])]]) function write_to_i2c_devices(pins) { // No X Y split? for (var key of i2c_devices.keys()) { i2c_devices.get(key).write(pins); } } function set_pin(pins, pin_no, val) { if (val) { return pins | (1 << pin_no); } else { return pins & ~(1 << pin_no); } } function hard_i2c_write(scl, sda) { var pins = pins_x; pins = set_pin(pins, HARD_I2C_SCL_X, scl); pins = set_pin(pins, HARD_I2C_SDA_X, sda); write_to_i2c_devices(pins); pins_x = pins; } function extract_pin(pins, n) { return ((pins & (1 << n)) ? 1 : 0); } function X(n) { return extract_pin(pins_x, n); } function Y(n) { return extract_pin(pins_y, n); } function int_to_bytes(n) { return new Uint8Array([n, n >> 8, n >> 16, n >> 24]); } function hook_read(handle, type, addr_lo, addr_hi, size, value_lo, value_hi, user_data) { if (addr_lo == UART0_RXR) { if (next_char.length == 0) { try { emu.emu_stop(); waiting = true; } catch (e){ console.log(e, '\n'); } } else { n = next_char.pop(); emu.mem_write(UART0_RXR, int_to_bytes(n)); } } else if (addr_lo == UNICORN_CONTROLLER_RAM_SIZE) { emu.mem_write(UNICORN_CONTROLLER_RAM_SIZE, int_to_bytes(ram_size)); } else if (addr_lo == UNICORN_CONTROLLER_STACK_SIZE) { emu.mem_write(UNICORN_CONTROLLER_STACK_SIZE, int_to_bytes(stack_size)); } else if (addr_lo == UNICORN_CONTROLLER_INSNS) { emu.mem_write(UNICORN_CONTROLLER_INSNS, int_to_bytes(insns)); } else if (addr_lo == GPIO_IDR) { emu.mem_write(GPIO_IDR, int_to_bytes(user_button_state)); } else if (addr_lo == GPIO_X_IDR) { for (var key of i2c_devices.keys()) { pins_x = i2c_devices.get(key).read('X', pins_x); } emu.mem_write(GPIO_X_IDR, int_to_bytes(pins_x)); emu.mem_write(GPIO_X_ODR, int_to_bytes(pins_x)); } else if (addr_lo == GPIO_Y_IDR) { for (var key of i2c_devices.keys()) { pins_y = i2c_devices.get(key).read('Y', pins_y); } emu.mem_write(GPIO_Y_IDR, int_to_bytes(pins_y)); emu.mem_write(GPIO_Y_ODR, int_to_bytes(pins_y)); } else if (addr_lo == SERVO_1_ANGLE) { emu.mem_write(SERVO_1_ANGLE, int_to_bytes(servo_angle)); } else if (addr_lo >= ADC_X_IDR && addr_lo < ADC_X_IDR + 0x30) { } else if (addr_lo >= ADC_Y_IDR && addr_lo < ADC_Y_IDR + 0x30) { if (addr_lo == ADC_Y_IDR + (3 * 4)) { //Pin Y4 connected to ADC slider emu.mem_write(addr_lo, int_to_bytes((adc_slider.value * 255) / 100)); } } else if (addr_lo == RTC_TICKS_MS) { emu.mem_write(RTC_TICKS_MS, int_to_bytes(parseInt(window.performance.now() - epoch, 10))); } else if (addr_lo == RTC_TICKS_US) { emu.mem_write(RTC_TICKS_US, int_to_bytes(parseInt((window.performance.now() - epoch) * 1000, 10))); } else if (addr_lo == I2C_DATA) { for (var key of i2c_devices.keys()) { pins_x = i2c_devices.get(key).read('X', pins_x); } emu.mem_write(I2C_DATA, int_to_bytes(X(HARD_I2C_SDA_X))); hard_i2c_write(0, X(HARD_I2C_SDA_X)); } return; } function hook_write(handle, type, addr_lo, addr_hi, size, value_lo, value_hi, user_data) { if (addr_lo == UART0_TXR) { if (value_lo == 4 && in_script) { if (in_error == true) { block_output = 1; in_error = false; in_script = false; } else { in_error = true; } } else if (block_output > 0) { block_output--; } else { term.write(String.fromCharCode(value_lo)); } } else if (addr_lo == UNICORN_CONTROLLER_PENDING) { pending = value_lo; } else if (addr_lo == UNICORN_CONTROLLER_EXCEPTION) { exception = int_to_bytes(value_lo); } else if (addr_lo == UNICORN_CONTROLLER_INTR_CHAR) { ichr_addr = value_lo; } else if (addr_lo == UNICORN_CONTROLLER_IDLE) { if (idle) { idle = false; emu.emu_stop(); } else { idle = true; } } else if (addr_lo == GPIO_ODR) { document.getElementById("red_led").style.display = extract_pin(value_lo, 0) ? "inline" : "none"; document.getElementById("green_led").style.display = extract_pin(value_lo, 1) ? "inline" : "none"; document.getElementById("yellow_led").style.display = extract_pin(value_lo, 2) ? "inline" : "none"; document.getElementById("blue_led").style.display = extract_pin(value_lo, 3) ? "inline" : "none"; } else if (addr_lo == GPIO_X_ODR) { write_to_i2c_devices(value_lo); pins_x = value_lo; emu.mem_write(GPIO_X_IDR, int_to_bytes(pins_x)); } else if (addr_lo == GPIO_Y_ODR) { write_to_i2c_devices(value_lo); pins_y = value_lo; emu.mem_write(GPIO_X_IDR, int_to_bytes(pins_y)); document.getElementById("pin_led_on").style.display = extract_pin(value_lo, 12) ? "inline" : "none"; } else if (addr_lo == SERVO_1_ANGLE) { servo_target = value_lo; rotate_servo(); } else if (addr_lo == SERVO_1_TIME) { servo_speed = (Math.abs(servo_angle - servo_target) / (value_lo / 1000)) / 60; } else if (addr_lo == I2C_DATA) { for (var i = 7; i >= 0; i--) { var j = (value_lo >> i) & 1; for (var k = 0; k < 3; k++) { hard_i2c_write(k % 2, j); } } hard_i2c_write(0, 1); hard_i2c_write(1, 1); } else if (addr_lo == I2C_COMMAND) { if (value_lo == 0) { hard_i2c_write(1, 1); hard_i2c_write(1, 0); } else if (value_lo == 1) { hard_i2c_write(1, 0); hard_i2c_write(1, 1); } } prev_val = value_lo; return; } function start() { set_editor_height(); set_LEDs(); binary = document.getElementById("binary").value; if (binary != prev_binary) { prev_binary = binary; demo_scripts = window[binary + "_demos"]; set_demos(); if (binary == "pyboard") { PYB.style.display = "inline"; } else { PYB.style.display = "none"; } var xhr = new XMLHttpRequest(); xhr.open('GET', "firmware_" + binary + ".bin", true); xhr.responseType = 'arraybuffer'; xhr.onload = function (e) { firmware = new Uint8Array(this.response); continue_start(); } xhr.send(); } else { continue_start(); } } function continue_start() { emu = new uc.Unicorn(uc.ARCH_ARM, uc.MODE_THUMB); emu.mem_map(FLASH_ADDRESS, FLASH_SIZE, uc.PROT_ALL); emu.mem_map(RAM_ADDRESS, MAX_RAM_SIZE, uc.PROT_ALL); emu.mem_map(PERIPHERAL_ADDRESS, PERIPHERAL_SIZE, uc.PROT_ALL); addr = firmware[4] + (firmware[5] << 8) + (firmware[6] << 16) + (firmware[7] << 24); next_char = []; timestamp = new Date(); cycles = 0; insns = 0; idle = false; waiting = false; block_output = 0; in_script = false; in_error = false; ram_size = Number(document.getElementById("ram_size").value); stack_size = Number(document.getElementById("stack_size").value); sp = RAM_ADDRESS + ram_size; emu.mem_write(FLASH_ADDRESS, firmware); emu.mem_write(FLASH_ADDRESS, int_to_bytes(sp)); emu.hook_add(uc.HOOK_MEM_READ, hook_read, null, PERIPHERAL_ADDRESS, PERIPHERAL_ADDRESS + PERIPHERAL_SIZE); emu.hook_add(uc.HOOK_MEM_WRITE, hook_write, null, PERIPHERAL_ADDRESS, PERIPHERAL_ADDRESS + PERIPHERAL_SIZE); epoch = window.performance.now(); execute(); } function execute() { try { emu.emu_start(addr | 1, FLASH_ADDRESS + FLASH_SIZE, 0, CYCLE_LIMIT); } catch (er) { console.log(er, '\n'); return 1; } addr = emu.reg_read_i32(uc.ARM_REG_PC); if (!waiting) { cycles++; insns += CYCLE_LIMIT * TICK_INSN_RATIO; requestAnimationFrame(execute); } return 0; } function inject(data) { keypress = data.split("").reverse().map(function(i) { return i.charCodeAt() }); waiting = false; ichr = emu.mem_read(ichr_addr, 4); if (keypress[0] == ichr[0]) { emu.mem_write(pending, exception); } else { next_char = keypress.concat(next_char); } execute(); } term.on('data', function (data) { inject(data); }); reset_button.addEventListener("click", reset_emu); PYB_reset_button.addEventListener("click", reset_emu); PYB_user_button.addEventListener("mousedown", function() { user_button_state = 1; }); PYB_user_button.addEventListener("mouseup", function() { user_button_state = 0; }); function reset_emu() { term.reset(); term.focus(); start(); } var run_button = document.getElementById("run_button"); run_button.addEventListener("click", function() { if (editor.getValue() == "") return inject(String.fromCharCode(3)); inject(String.fromCharCode(1)); inject(String.fromCharCode(4)); while (!waiting) { if (execute()) { return; } } term.reset(); term.focus(); block_output = 2; in_script = true; inject(editor.getValue()); inject(String.fromCharCode(4)); inject(String.fromCharCode(2)); }); function set_demos() { for (var i = demos.options.length - 1; i >= 0; i--) { demos.remove(i); } for (var [key, value] of demo_scripts) { demos.add(new Option(key, value)); } editor.setValue(demos.value); } demos.addEventListener("change", function() { checkboxes = document.getElementsByClassName('components'); for (var i = 0; i < checkboxes.length; i++) { var check = new Event('change'); checkboxes[i].checked = (demos.value.search(checkboxes[i].value) != -1) ? true : false; checkboxes[i].dispatchEvent(check); } if (demos.value.search("# PERIPHERALS: ") != -1) { editor.setValue(demos.value.slice(demos.value.search("\n") + 1)); } else { editor.setValue(demos.value); } }); function set_LEDs() { for (var led of ['red_led', 'green_led', 'yellow_led', 'blue_led']) { var img = document.getElementById(led); img.style.display = "none"; } } function set_editor_height(){ var editor_div = document.getElementById("editor_div"); var viewport = document.querySelector('.xterm-viewport'); editor_div.style.height = (parseFloat(viewport.style.lineHeight) * term.rows).toString() + "px"; } window.addEventListener('resize', function() { term.fit(); set_editor_height(); }); window.onload = function() { checkboxes = document.getElementsByClassName('components'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].addEventListener('change', function() { component = document.getElementById(this.value); component.style.display = this.checked ? "inline" : "none"; }); } } function rotate_servo() { if (servo_angle != servo_target) { servo_angle += servo_angle < servo_target ? servo_speed : -servo_speed; if (servo_angle > 90) servo_angle = 90; if (servo_angle < -90) servo_angle = -90; if (Math.abs(servo_angle - servo_target) < EPSILON) servo_angle = servo_target; pin_servo_blade.style.transform = "rotate(" + servo_angle.toString(10) + "deg)"; requestAnimationFrame(rotate_servo); } else { servo_speed = 1; } } gauge = setInterval(function() { new_timestamp = new Date(); if (!window.cycles) { speed = 0; } else { speed = (cycles * CYCLE_LIMIT * TICK_INSN_RATIO / 1000000) / ((new_timestamp - timestamp) / 1000); } document.getElementById("clock_speed").innerHTML = speed.toFixed(2); timestamp = new_timestamp; cycles = 0; }, 1000); start(); ================================================ FILE: www-emu/pyboard_demos.py ================================================ # HELLO WORLD! # hello world! print('hello world') ##### # BIG INTEGER # bignum print(1 << 1000) ##### # ASSEMBLY # inline assembler @micropython.asm_thumb def asm_add(r0, r1): add(r0, r0, r1) print(asm_add(1, 2)) ##### # SWITCH # push the USR button on the pyboard to flash the LEDs! # try using the reset button on the pyboard to quit this script! # switch callback not yet supported. import time import pyb while True: if pyb.Switch().value(): pyb.LED(1).on() else: pyb.LED(1).off() time.sleep_ms(50) ##### # LEDS # four LEDS numbered 1 to 4 import time import pyb for i in range(1000): pyb.LED((i%4) + 1).toggle() time.sleep_ms(100) ##### # TIME # the time module is utime, a specialized MicroPython library # sleep will break the clock speed # dates not yet supported import time print(time.ticks_ms()) time.sleep_ms(1000) print(time.ticks_us()) time.sleep_us(1000000) ##### # MATH # a subset of the Python Math library import math import cmath print(math.sqrt(5)) print(math.log10(100)) print(math.sin(12345) ** 2 + math.cos(12345) ** 2) print(math.cosh(1) ** 2 - math.sinh(1) ** 2) print(cmath.polar(1 + 1j)) ##### # PIN LED # PERIPHERALS: pin_led # Using a Pin with micropython # Make sure you have the LED checkbox marked! import machine # The LED is connected to our virtual pin Y12 y12 = machine.Pin('Y12') y12(0 if y12() else 1) ##### # ADC # PERIPHERALS: pin_adc # Using the ADC (Analogue to Digital Converter) # Make sure you have the ADC checkbox marked! import machine import pyb # The slider is connected to pin Y4, try adjusting it y4 = machine.Pin('Y4') adc = pyb.ADC(y4) print(adc.read()) ##### # SERVO # PERIPHERALS: pin_servo # Using the Servo # Make sure you have the Servo checkbox marked! import machine import pyb # The pyboard has four simple servo connections servo = pyb.Servo(1) servo.angle(90, 5000) ##### # I2C LCD # PERIPHERALS: i2c_lcd # A fully simulated I2C bus and LCD Display # The framebuf class simplifies graphics in MicroPython # Use the hardware i2c in example Pong for faster performance # Make sure you have the I2C LCD checkbox marked! import machine import framebuf i2c = machine.I2C('X') fbuf = framebuf.FrameBuffer(bytearray(64 * 32 // 8), 64, 32, framebuf.MONO_HLSB) logo = framebuf.FrameBuffer(bytearray(17 * 17 // 8), 17, 17, framebuf.MONO_HLSB) logo.fill(0) logo.fill_rect(1, 1, 15, 15, 1) logo.vline(4, 4, 12, 0) logo.vline(8, 1, 12, 0) logo.vline(12, 4, 12, 0) logo.vline(14, 13, 2, 0) fbuf.fill(0) fbuf.blit(logo, 23, 7) i2c.writeto(8, fbuf) ##### # MANDELBROT SET # A python Mandelbrot set courtesy of # http://warp.povusers.org/MandScripts/python.html # Try your own Python3 scripts on MicroPython! minX = -2.0 maxX = 1.0 width = 60 height = 28 aspectRatio = 2 chars = ' .,-:;i+hHM$*#@ ' yScale = (maxX-minX)*(float(height)/width)*aspectRatio for y in range(height): line = '' for x in range(width): c = complex(minX+x*(maxX-minX)/width, y*yScale/height-yScale/2) z = c for char in chars: if abs(z) > 2: break z = z*z+c line += char print(line) ##### # Pong # PERIPHERALS: i2c_lcd pin_adc # Pong! # Using emulated hardware i2c, we can push enough frames for # rough animations. Performance for this project is reduced # using chromium. import machine import framebuf import time import pyb SCREEN_WIDTH = 64 SCREEN_HEIGHT = 32 game_over = False score = 0 class Entity: def __init__(self, x, y, w, h, vx, vy): self.x = x; self.y = y; self.w = w; self.h = h; self.vx = vx; self.vy = vy; def draw(self, fbuf): fbuf.fill_rect(int(self.x), int(self.y), self.w, self.h, 1) class Ball(Entity): def update(self, dt, player): self.x += self.vx * dt; if (self.x <= 0): self.x = 0 self.vx = -self.vx if (self.x >= SCREEN_WIDTH - self.w): self.x = SCREEN_WIDTH - self.w self.vx = -self.vx self.y += self.vy * dt; if (self.y <= 0): self.y = 0 self.vy = -self.vy if (self.y >= SCREEN_HEIGHT - self.h - player.h): if (self.x >= player.x and self.x <= player.x + player.w): self.y = SCREEN_HEIGHT - self.h - player.h self.vy = -self.vy global score score += 1 if score % 2 == 0: self.vx += (self.vx/abs(self.vx)) * 1 if score % 3 == 0: self.vy += (self.vy/abs(self.vy)) * 1 else: global game_over game_over = True class Player(Entity): pass ball = Ball(32, 16, 1, 1, 2, -2) player = Player(30, 31, 10, 1, 0, 0) y4 = machine.Pin('Y4') adc = pyb.ADC(y4) i2c = machine.I2C('X') fbuf = framebuf.FrameBuffer(bytearray(64 * 32 // 8), 64, 32, framebuf.MONO_HLSB) tick = time.ticks_ms() while not game_over: ntick = time.ticks_ms() ball.update(time.ticks_diff(ntick, tick) // 100, player) tick = ntick player.x = adc.read() * 58 / 255 fbuf.fill(0) ball.draw(fbuf) player.draw(fbuf) i2c.writeto(8, fbuf) time.sleep_ms(50) # Adjust this for performance boosts fbuf.fill(0) fbuf.text('GAME', 15, 8) fbuf.text('OVER', 15, 18) i2c.writeto(8, fbuf) print('Score: ', score)