Newer
Older
Minitel-Dinos / Minitel.js
function Minitel(speed, tx, rx) {
    const DEBUG_INPUT = true;
    var term = {};
    var s = Serial1;
    var input = "";
    const keyCode = {
        ENVOI: 65,
        GUIDE: 68,
        CORRECTION: 71,
        RETOUR: 66,
        SUITE: 72,
        ANNULATION: 69,
        REPETITION: 67,
        SOMMAIRE: 70,
        FIN: 89,
    };

    /**
     * INPUT HANDLING
     */
    var callInput = ((ch, code) => {
        if (this.onInput)
            this.onInput(ch, code);
        else
            print("INPUT DISCONNECTED!!");
    }).bind(this);

    function inputHandler(data) {
        input += data;
        if (input.length == 0)
            return;
        if (input.charCodeAt(0) == 19) {
            if (input.length < 2)
                return;
            switch (input.charCodeAt(1)) {
                case keyCode.ENVOI:
                case keyCode.GUIDE:
                case keyCode.CORRECTION:
                case keyCode.RETOUR:
                case keyCode.SUITE:
                case keyCode.ANNULATION:
                case keyCode.REPETITION:
                case keyCode.SOMMAIRE:
                    callInput("", input.charCodeAt(1));
                    input = input.substr(2);
                    break;
                case keyCode.FIN:
                    if (input.length < 4)
                        return;
                    if (input.charCodeAt(2) == 19 && input.charCodeAt(3) == keyCode.FIN) {
                        callInput("", input.charCodeAt(1));
                        input = input.substr(4);
                        return;
                    } else
                        input = input.substr(2);
            }
        } else {
            callInput(input[0], 0);
            input = input.substr(1);
        }
    }

    /**
     * PROTOCOL
     */
    function defaults() {
        text();
        clear();
        bgColor(0);
        fgColor(7);
        return this;
    }
    function clear() {
        s.write(12);
        return this;
    }
    function graphics() {
        s.write(14);
        term.gm = true;
        return this;
    }
    function text() {
        s.write(15);
        term.gm = false;
        return this;
    }
    function home() { //CR / Line home
        s.write(13);
        return this;
    }
    function end() { //Line end
        s.write(24);
        return this;
    }

    //COLORS
    function bgColor(col) {
        if (col < 0 || col > 7)
            return;
        s.write([27, 80 + col]);
        term.bg = col;
        return this;
    }
    function fgColor(col) {
        if (col < 0 || col > 7)
            return;
        s.write([27, 64 + col]);
        term.fg = col;
        return this;
    }
    function blink(blink) {
        s.write([27, blink ? 72 : 73]);
        return this;
    }

    //CURSOR
    function locate(x, y) {
        s.write([31, 64 + y, 64 + x]);
        return this;
    }
    function showCursor(show) {
        term.cursor = show;
        s.write(show ? 17 : 20);
        return this;
    }

    //TEXT
    function mprint(str) {
        s.print(str);
        return this;
    }
    function println(str) {
        s.println(str === undefined ? "" : str);
        return this;
    }
    function write(data) {
        s.write(data);
        return this;
    }
    function font(mode) {
        s.write([27, mode]);
        return this;
    }
    function repeat(times) {
        s.write([18, times + 64]);
        return this;
    }

    /**
     * GRAPHICS
     */
    var start = ((x, y, opts) => {
        this.locate(x, y).graphics();
        if (opts && opts.fg)
            this.fgColor(opts.fg);
        if (opts && opts.bg)
            this.bgColor(opts.bg);
        return this;
    }).bind(this);

    function gCurStart() {
        if (term.cursor)
            this.write(20);
    }

    function gCurEnd() {
        if (term.cursor)
            this.write(17);
    }

    function graph(x, y, val, opts) {
        start(x, y, opts).write(val).text();
        return this;
    }

    function frame(x, y, w, h, opts) {
        gCurStart();
        var i;
        start(x, y, opts).write(118);
        if (opts && opts.title) {
            var s = String(opts.title);
            this.write(53).text();
            if (opts && opts.titleFg);
            this.fgColor(opts.titleFg);
            if (opts && opts.titleBg);
            this.fgColor(opts.titleBg);
            this.write(s);
            this.graphics().write(106);
            this.write(115).repeat(w - (s.length + 4));
        } else
            this.write(115).repeat(w - 2);
        this.write(121);
        if (opts && opts.fill) {
            for (i = 1; i < h; i++)
                start(x, y + i, opts).write([53, 32]).repeat(w - 2).write(106);
        } else
            for (i = 1; i < h; i++) {
                start(x, y + i, opts).write(53);
                start(x + w, y + i, opts).write(106);
            }
        start(x, y + h, opts).write([103, 115]).repeat(w - 2).write(59).text();
        gCurEnd();
        return this;
    }

    function fill(x, y, w, h, ch, opts) {
        if (w <= 0 || h <= 0)
            return;
        gCurStart();
        if (ch === undefined)
            ch = 32;
        for (var yy = y; yy < y + h; yy++)
            start(x, yy, opts).write(ch).repeat(w - 1);
        gCurEnd();
    }

    // *** PUBLISHING ***


    /**
     * CONSTRUCTOR
     */
    (() => {
        if (!speed)
            speed = 1200;
        if (!tx)
            tx = B6;
        if (!rx)
            rx = B7;
        print(`Configuring ESPruino in tx: ${tx}, rx: ${rx}, speed: ${speed}`);
        s.setup(speed, {
            tx: tx,
            rx: rx,
            bytesize: 7,
            parity: "e",
            errors: true
        });
        s.on('parity', function () {
            console.log("[!!] Parity error");
        });
        s.on('framing', function () {
            console.log("[!!] Framing error");
        });
        s.on('data', data => {
            if (DEBUG_INPUT) {
                var s = "<Minitel> (" + data.length + ") [";
                for (var i in data) {
                    if (i > 0)
                        s += ", ";
                    s += data.charCodeAt(i);
                }
                print(s + "]");
            }
            //***************
            inputHandler(data);
        });
    })();

    // *** PUBLSHING ***
    this.defaults = defaults;
    this.reset = reset;
    this.clear = clear;
    this.graphics = graphics;
    this.text = text;

    //COLORS
    this.bgColor = bgColor;
    this.fgColor = fgColor;
    this.blink = blink;
    this.color = {
        black: 0,
        red: 1,
        green: 2,
        yellow: 3,
        magenta: 4,
        blue: 5,
        cyan: 6,
        white: 7
    };

    //CURSOR
    this.locate = locate;
    this.showCursor = showCursor;

    //TEXT
    this.print = mprint;
    this.println = println;
    this.write = write;
    this.font = font;
    this.font.regular = 76;
    this.font.doubleHeight = 77;
    this.font.doubleWidth = 78;
    this.font.double = 79;
    this.font.double = 79;
    this.font.normal = 92;
    this.font.inverted = 93;
    this.font.transparent = 94;
    this.font.mask = 88;
    this.font.demask = 95;
    this.repeat = repeat;

    // INPUT
    this.keyCode = keyCode;

    // GRAPHICS
    this.graph = graph;
    this.frame = frame;
    this.fill = fill;
    //EVENTS
    this.onInput = undefined;
}

module.exports = Minitel;