Skip to content
Snippets Groups Projects
Select Git revision
  • 9317fee5238f8261e05a19187da355baa9d017ab
  • wip-bootstrap default
  • dualcore
  • ch3/leds
  • ch3/time
  • master
6 results

unix_mphal.c

Blame
  • user avatar
    Paul Sokolovsky authored
    Similar to existing mp_hal_ticks_ms().
    b5809582
    History
    unix_mphal.c 5.86 KiB
    /*
     * This file is part of the Micro Python project, http://micropython.org/
     *
     * The MIT License (MIT)
     *
     * Copyright (c) 2015 Damien P. George
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy
     * of this software and associated documentation files (the "Software"), to deal
     * in the Software without restriction, including without limitation the rights
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     * copies of the Software, and to permit persons to whom the Software is
     * furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice shall be included in
     * all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     * THE SOFTWARE.
     */
    
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/time.h>
    
    #include "py/mpstate.h"
    #include "py/mphal.h"
    #include "py/runtime.h"
    #include "extmod/misc.h"
    
    #ifndef _WIN32
    #include <signal.h>
    
    STATIC void sighandler(int signum) {
        if (signum == SIGINT) {
            #if MICROPY_ASYNC_KBD_INTR
            mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
            sigset_t mask;
            sigemptyset(&mask);
            // On entry to handler, its signal is blocked, and unblocked on
            // normal exit. As we instead perform longjmp, unblock it manually.
            sigprocmask(SIG_SETMASK, &mask, NULL);
            nlr_raise(MP_STATE_VM(keyboard_interrupt_obj));
            #else
            if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
                // this is the second time we are called, so die straight away
                exit(1);
            }
            mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
            MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
            #endif
        }
    }
    #endif
    
    void mp_hal_set_interrupt_char(char c) {
        // configure terminal settings to (not) let ctrl-C through
        if (c == CHAR_CTRL_C) {
            #ifndef _WIN32
            // enable signal handler
            struct sigaction sa;
            sa.sa_flags = 0;
            sa.sa_handler = sighandler;
            sigemptyset(&sa.sa_mask);
            sigaction(SIGINT, &sa, NULL);
            #endif
        } else {
            #ifndef _WIN32
            // disable signal handler
            struct sigaction sa;
            sa.sa_flags = 0;
            sa.sa_handler = SIG_DFL;
            sigemptyset(&sa.sa_mask);
            sigaction(SIGINT, &sa, NULL);
            #endif
        }
    }
    
    #if MICROPY_USE_READLINE == 1
    
    #include <termios.h>
    
    static struct termios orig_termios;
    
    void mp_hal_stdio_mode_raw(void) {
        // save and set terminal settings
        tcgetattr(0, &orig_termios);
        static struct termios termios;
        termios = orig_termios;
        termios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        termios.c_cflag = (termios.c_cflag & ~(CSIZE | PARENB)) | CS8;
        termios.c_lflag = 0;
        termios.c_cc[VMIN] = 1;
        termios.c_cc[VTIME] = 0;
        tcsetattr(0, TCSAFLUSH, &termios);
    }
    
    void mp_hal_stdio_mode_orig(void) {
        // restore terminal settings
        tcsetattr(0, TCSAFLUSH, &orig_termios);
    }
    
    #endif
    
    #if MICROPY_PY_OS_DUPTERM
    static int call_dupterm_read(void) {
        nlr_buf_t nlr;
        if (nlr_push(&nlr) == 0) {
            mp_obj_t read_m[3];
            mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m);
            read_m[2] = MP_OBJ_NEW_SMALL_INT(1);
            mp_obj_t res = mp_call_method_n_kw(1, 0, read_m);
            if (res == mp_const_none) {
                return -2;
            }
            mp_buffer_info_t bufinfo;
            mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ);
            if (bufinfo.len == 0) {
                mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n");
                MP_STATE_PORT(term_obj) = NULL;
                return -1;
            }
            nlr_pop();
            return *(byte*)bufinfo.buf;
        } else {
            // Temporarily disable dupterm to avoid infinite recursion
            mp_obj_t save_term = MP_STATE_PORT(term_obj);
            MP_STATE_PORT(term_obj) = NULL;
            mp_printf(&mp_plat_print, "dupterm: ");
            mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
            MP_STATE_PORT(term_obj) = save_term;
        }
    
        return -1;
    }
    #endif
    
    int mp_hal_stdin_rx_chr(void) {
        unsigned char c;
    #if MICROPY_PY_OS_DUPTERM
        if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
            int c;
            do {
                 c = call_dupterm_read();
            } while (c == -2);
            if (c == -1) {
                goto main_term;
            }
            if (c == '\n') {
                c = '\r';
            }
            return c;
        } else {
            main_term:;
    #endif
            int ret = read(0, &c, 1);
            if (ret == 0) {
                c = 4; // EOF, ctrl-D
            } else if (c == '\n') {
                c = '\r';
            }
            return c;
    #if MICROPY_PY_OS_DUPTERM
        }
    #endif
    }
    
    void mp_hal_stdout_tx_strn(const char *str, size_t len) {
        int ret = write(1, str, len);
        mp_uos_dupterm_tx_strn(str, len);
        (void)ret; // to suppress compiler warning
    }
    
    // cooked is same as uncooked because the terminal does some postprocessing
    void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
        mp_hal_stdout_tx_strn(str, len);
    }
    
    void mp_hal_stdout_tx_str(const char *str) {
        mp_hal_stdout_tx_strn(str, strlen(str));
    }
    
    mp_uint_t mp_hal_ticks_ms(void) {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        return tv.tv_sec * 1000 + tv.tv_usec / 1000;
    }
    
    mp_uint_t mp_hal_ticks_us(void) {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        return tv.tv_sec * 1000000 + tv.tv_usec;
    }