working terminal
This commit is contained in:
@@ -182,9 +182,15 @@ $1/%.o: %.S
|
|||||||
$(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@
|
$(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@
|
||||||
endef
|
endef
|
||||||
|
|
||||||
.PHONY: all checkdirs clean libesphttpd default-tgt
|
.PHONY: all web parser checkdirs clean libesphttpd default-tgt
|
||||||
|
|
||||||
all: checkdirs $(TARGET_OUT) $(FW_BASE)
|
web:
|
||||||
|
$(Q) ./build_web.sh
|
||||||
|
|
||||||
|
parser:
|
||||||
|
$(Q) ./build_parser.sh
|
||||||
|
|
||||||
|
all: checkdirs web parser $(TARGET_OUT) $(FW_BASE)
|
||||||
|
|
||||||
libesphttpd/Makefile:
|
libesphttpd/Makefile:
|
||||||
$(Q) [[ -e "libesphttpd/Makefile" ]] || echo -e "\e[31mlibesphttpd submodule missing.\nIf build fails, run \"git submodule init\" and \"git submodule update\".\e[0m"
|
$(Q) [[ -e "libesphttpd/Makefile" ]] || echo -e "\e[31mlibesphttpd submodule missing.\nIf build fails, run \"git submodule init\" and \"git submodule update\".\e[0m"
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "-- Building parser from Ragel source --"
|
||||||
|
|
||||||
ragel -L -G0 user/ansi_parser.rl -o user/ansi_parser.c
|
ragel -L -G0 user/ansi_parser.rl -o user/ansi_parser.c
|
||||||
|
|||||||
+3
-1
@@ -1,6 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "-- Preparing WWW files --"
|
||||||
|
|
||||||
mkdir -p html
|
mkdir -p html
|
||||||
yuicompressor html_orig/style.css > html/style.css
|
yuicompressor html_orig/style.css > html/style.css
|
||||||
yuicompressor html_orig/script.js > html/script.js
|
yuicompressor html_orig/script.js > html/script.js
|
||||||
minify --type=html html_orig/index.html -o html/term.tpl
|
minify --type=html html_orig/term.html -o html/term.tpl
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
var $=function(d,c){d=d.match(/^(\W)?(.*)/);return(c||document)["getElement"+(d[1]?d[1]=="#"?"ById":"sByClassName":"sByTagName")](d[2])};var m=function(e,d,f){d=document;f=d.createElement("p");f.innerHTML=e;e=d.createDocumentFragment();while(d=f.firstChild){e.appendChild(d)}return e};(function(){function a(r){return document.createElement(r)}var b=26,k=10;var l={a:false,x:0,y:0,suppress:false,hidden:false};var o=[];var g=["#111213","#CC0000","#4E9A06","#C4A000","#3465A4","#75507B","#06989A","#D3D7CF","#555753","#EF2929","#8AE234","#FCE94F","#729FCF","#AD7FA8","#34E2E2","#EEEEEC"];function p(){o.forEach(function(r,s){r.t=" ";r.fg=7;r.bg=0;d(r)})}function c(s,r){return o[s*b+r]}function i(){return c(l.y,l.x)}function q(r){l.hidden=!r;l.a&=r;d(i(),l.a)}function f(s,r){l.suppress=true;d(i(),false);l.x=r;l.y=s;l.suppress=false;d(i(),l.a)}function d(s,r){var v=s.e,t,u;t=r?s.bg:s.fg;u=r?s.fg:s.bg;v.innerText=(s.t+" ")[0];v.style.color=e(t);v.style.backgroundColor=e(u);v.style.fontWeight=t>7?"bold":"normal"}function h(){o.forEach(function(s,t){var r=l.a&&(t==l.y*b+l.x);d(s,r)})}function j(u){l.x=u.x;l.y=u.y;var v=0,B=0,x=u.screen;var r,w,A,z,s,y;while(v<x.length&&B<b*k){z=o[B++];r=z.fg=parseInt(x[v++],16);w=z.bg=parseInt(x[v++],16);A=z.t=x[v++];switch(x[v]){case"r":s=1;break;case"s":s=2;break;case"t":s=3;break;case"u":s=4;break;default:s=0}if(s>0){y=parseInt(x.substr(v+1,s));v=v+s+1;for(;y>0&&B<b*k;y--){z=o[B++];z.fg=r;z.bg=w;z.t=A}}}h()}function e(r){r=parseInt(r);if(r<0||r>15){r=0}return g[r]}function n(v){var u,r,t=$("#screen");for(var s=0;s<b*k;s++){u=a("span");if((s>0)&&(s%b==0)){t.appendChild(a("br"))}t.appendChild(u);r={t:" ",fg:7,bg:0,e:u};o.push(r);d(r)}setInterval(function(){l.a=!l.a;if(l.hidden){l.a=false}if(!l.suppress){d(i(),l.a)}},500);j(v)}window.Term={init:n,load:j,setCursor:f,enableCursor:q,clear:p}})();(function(){var g="ws://"+window.location.host+"/ws/update.cgi";var d;function c(i){console.log("CONNECTED")}function b(i){console.error("SOCKET CLOSED")}function f(i){try{Term.load(JSON.parse(i.data))}catch(j){console.error(j)}}function e(i){console.error(i.data)}function a(i){if(typeof i!="string"){i=JSON.stringify(i)}d.send(i)}function h(){d=new WebSocket(g);d.onopen=c;d.onclose=b;d.onmessage=f;d.onerror=e;console.log("Opening socket.")}window.Conn={ws:null,init:h,send:a}})();function init(a){Term.init(a);Conn.init()};
|
var $=function(d,c){d=d.match(/^(\W)?(.*)/);return(c||document)["getElement"+(d[1]?d[1]=="#"?"ById":"sByClassName":"sByTagName")](d[2])};var m=function(e,d,f){d=document;f=d.createElement("p");f.innerHTML=e;e=d.createDocumentFragment();while(d=f.firstChild){e.appendChild(d)}return e};(function(){function a(r){return document.createElement(r)}var b=26,k=10;var l={a:false,x:0,y:0,suppress:false,hidden:false};var o=[];var g=["#111213","#CC0000","#4E9A06","#C4A000","#3465A4","#75507B","#06989A","#D3D7CF","#555753","#EF2929","#8AE234","#FCE94F","#729FCF","#AD7FA8","#34E2E2","#EEEEEC"];function p(){o.forEach(function(r,s){r.t=" ";r.fg=7;r.bg=0;d(r)})}function c(s,r){return o[s*b+r]}function i(){return c(l.y,l.x)}function q(r){l.hidden=!r;l.a&=r;d(i(),l.a)}function f(s,r){l.suppress=true;d(i(),false);l.x=r;l.y=s;l.suppress=false;d(i(),l.a)}function d(s,r){var v=s.e,t,u;t=r?s.bg:s.fg;u=r?s.fg:s.bg;v.innerText=(s.t+" ")[0];v.style.color=e(t);v.style.backgroundColor=e(u);v.style.fontWeight=t>7?"bold":"normal"}function h(){o.forEach(function(s,t){var r=l.a&&(t==l.y*b+l.x);d(s,r)})}function j(v){l.x=v.x;l.y=v.y;var w=0,C=0,y=v.screen;var r=7,x=0;while(w<y.length&&C<b*k){var A=o[C++];var u=y[w];if(u!=","){r=A.fg=parseInt(y[w++],16);x=A.bg=parseInt(y[w++],16)}else{w++;A.fg=r;A.bg=x}var B=A.t=y[w++];var s=0;switch(y[w]){case"r":s=1;break;case"s":s=2;break;case"t":s=3;break;case"u":s=4;break;default:s=0}if(s>0){var z=parseInt(y.substr(w+1,s));w=w+s+1;for(;z>0&&C<b*k;z--){A=o[C++];A.fg=r;A.bg=x;A.t=B}}}h()}function e(r){r=parseInt(r);if(r<0||r>15){r=0}return g[r]}function n(v){var u,r,t=$("#screen");for(var s=0;s<b*k;s++){u=a("span");if((s>0)&&(s%b==0)){t.appendChild(a("br"))}t.appendChild(u);r={t:" ",fg:7,bg:0,e:u};o.push(r);d(r)}setInterval(function(){l.a=!l.a;if(l.hidden){l.a=false}if(!l.suppress){d(i(),l.a)}},500);j(v)}window.Term={init:n,load:j,setCursor:f,enableCursor:q,clear:p}})();(function(){var g="ws://"+window.location.host+"/ws/update.cgi";var d;function c(i){console.log("CONNECTED")}function b(i){console.error("SOCKET CLOSED")}function f(i){try{console.log("RX: ",i.data);Term.load(JSON.parse(i.data))}catch(j){console.error(j)}}function e(i){console.error(i.data)}function a(i){if(typeof i!="string"){i=JSON.stringify(i)}d.send(i)}function h(){d=new WebSocket(g);d.onopen=c;d.onclose=b;d.onmessage=f;d.onerror=e;console.log("Opening socket.")}window.Conn={ws:null,init:h,send:a}})();function init(a){Term.init(a);Conn.init()};
|
||||||
+18
-6
@@ -163,15 +163,26 @@ var m = function(
|
|||||||
cursor.y = obj.y;
|
cursor.y = obj.y;
|
||||||
|
|
||||||
// Simple compression - hexFG hexBG 'ASCII' (r/s/t/u NUM{1,2,3,4})?
|
// Simple compression - hexFG hexBG 'ASCII' (r/s/t/u NUM{1,2,3,4})?
|
||||||
|
// comma instead of both colors = same as before
|
||||||
|
|
||||||
var i = 0, ci = 0, str = obj.screen;
|
var i = 0, ci = 0, str = obj.screen;
|
||||||
var fg, bg, t, cell, repchars, rep;
|
var fg = 7, bg = 0;
|
||||||
while(i < str.length && ci<W*H) {
|
while(i < str.length && ci<W*H) {
|
||||||
cell = screen[ci++];
|
var cell = screen[ci++];
|
||||||
fg = cell.fg = parseInt(str[i++], 16);
|
|
||||||
bg = cell.bg = parseInt(str[i++], 16);
|
|
||||||
t = cell.t = str[i++];
|
|
||||||
|
|
||||||
|
var j = str[i];
|
||||||
|
if (j != ',') { // comma = repeat last colors
|
||||||
|
fg = cell.fg = parseInt(str[i++], 16);
|
||||||
|
bg = cell.bg = parseInt(str[i++], 16);
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
cell.fg = fg;
|
||||||
|
cell.bg = bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
var t = cell.t = str[i++];
|
||||||
|
|
||||||
|
var repchars = 0;
|
||||||
switch(str[i]) {
|
switch(str[i]) {
|
||||||
case 'r': repchars = 1; break;
|
case 'r': repchars = 1; break;
|
||||||
case 's': repchars = 2; break;
|
case 's': repchars = 2; break;
|
||||||
@@ -181,7 +192,7 @@ var m = function(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (repchars > 0) {
|
if (repchars > 0) {
|
||||||
rep = parseInt(str.substr(i+1,repchars));
|
var rep = parseInt(str.substr(i+1,repchars));
|
||||||
i = i + repchars + 1;
|
i = i + repchars + 1;
|
||||||
for (; rep>0 && ci<W*H; rep--) {
|
for (; rep>0 && ci<W*H; rep--) {
|
||||||
cell = screen[ci++];
|
cell = screen[ci++];
|
||||||
@@ -263,6 +274,7 @@ var m = function(
|
|||||||
|
|
||||||
function onMessage(evt) {
|
function onMessage(evt) {
|
||||||
try {
|
try {
|
||||||
|
console.log("RX: ", evt.data);
|
||||||
// Assume all our messages are screen updates
|
// Assume all our messages are screen updates
|
||||||
Term.load(JSON.parse(evt.data));
|
Term.load(JSON.parse(evt.data));
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
|||||||
+41
-28
@@ -188,11 +188,11 @@ handle_plainchar(char c)
|
|||||||
static const char _ansi_actions[] = {
|
static const char _ansi_actions[] = {
|
||||||
0, 1, 0, 1, 1, 1, 2, 1,
|
0, 1, 0, 1, 1, 1, 2, 1,
|
||||||
3, 1, 4, 1, 5, 1, 6, 1,
|
3, 1, 4, 1, 5, 1, 6, 1,
|
||||||
7, 1, 8
|
7, 1, 8, 1, 9
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char _ansi_eof_actions[] = {
|
static const char _ansi_eof_actions[] = {
|
||||||
0, 0, 0, 13, 13, 0, 0
|
0, 15, 15, 13, 13, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int ansi_start = 1;
|
static const int ansi_start = 1;
|
||||||
@@ -267,11 +267,11 @@ case 1:
|
|||||||
goto tr0;
|
goto tr0;
|
||||||
case 2:
|
case 2:
|
||||||
switch( (*p) ) {
|
switch( (*p) ) {
|
||||||
case 91: goto tr2;
|
case 91: goto tr3;
|
||||||
case 93: goto tr4;
|
case 93: goto tr4;
|
||||||
case 99: goto tr5;
|
case 99: goto tr5;
|
||||||
}
|
}
|
||||||
goto tr3;
|
goto tr2;
|
||||||
case 0:
|
case 0:
|
||||||
goto _out;
|
goto _out;
|
||||||
case 5:
|
case 5:
|
||||||
@@ -312,27 +312,28 @@ case 6:
|
|||||||
goto tr6;
|
goto tr6;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr3: cs = 0; goto _again;
|
tr2: cs = 0; goto f0;
|
||||||
tr6: cs = 0; goto f4;
|
tr6: cs = 0; goto f5;
|
||||||
tr0: cs = 1; goto f0;
|
tr0: cs = 1; goto f1;
|
||||||
tr1: cs = 2; goto _again;
|
tr1: cs = 2; goto _again;
|
||||||
tr7: cs = 4; goto f5;
|
tr7: cs = 4; goto f6;
|
||||||
tr8: cs = 4; goto f6;
|
tr8: cs = 4; goto f7;
|
||||||
tr9: cs = 4; goto f7;
|
tr9: cs = 4; goto f8;
|
||||||
tr2: cs = 5; goto f1;
|
tr3: cs = 5; goto f2;
|
||||||
tr4: cs = 5; goto f2;
|
tr4: cs = 5; goto f3;
|
||||||
tr5: cs = 5; goto f3;
|
tr5: cs = 5; goto f4;
|
||||||
tr10: cs = 6; goto f8;
|
tr10: cs = 6; goto f9;
|
||||||
|
|
||||||
f0: _acts = _ansi_actions + 1; goto execFuncs;
|
f1: _acts = _ansi_actions + 1; goto execFuncs;
|
||||||
f1: _acts = _ansi_actions + 3; goto execFuncs;
|
f2: _acts = _ansi_actions + 3; goto execFuncs;
|
||||||
f5: _acts = _ansi_actions + 5; goto execFuncs;
|
f6: _acts = _ansi_actions + 5; goto execFuncs;
|
||||||
f6: _acts = _ansi_actions + 7; goto execFuncs;
|
f7: _acts = _ansi_actions + 7; goto execFuncs;
|
||||||
f7: _acts = _ansi_actions + 9; goto execFuncs;
|
f8: _acts = _ansi_actions + 9; goto execFuncs;
|
||||||
f8: _acts = _ansi_actions + 11; goto execFuncs;
|
f9: _acts = _ansi_actions + 11; goto execFuncs;
|
||||||
f4: _acts = _ansi_actions + 13; goto execFuncs;
|
f5: _acts = _ansi_actions + 13; goto execFuncs;
|
||||||
f2: _acts = _ansi_actions + 15; goto execFuncs;
|
f0: _acts = _ansi_actions + 15; goto execFuncs;
|
||||||
f3: _acts = _ansi_actions + 17; goto execFuncs;
|
f3: _acts = _ansi_actions + 17; goto execFuncs;
|
||||||
|
f4: _acts = _ansi_actions + 19; goto execFuncs;
|
||||||
|
|
||||||
execFuncs:
|
execFuncs:
|
||||||
_nacts = *_acts++;
|
_nacts = *_acts++;
|
||||||
@@ -397,21 +398,27 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
/* #line 288 "user/ansi_parser.rl" */
|
/* #line 280 "user/ansi_parser.rl" */
|
||||||
|
{
|
||||||
|
{cs = 1; goto _again;}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
/* #line 292 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
// TODO implement OS control code parsing
|
// TODO implement OS control code parsing
|
||||||
{cs = 1; goto _again;}
|
{cs = 1; goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 9:
|
||||||
/* #line 293 "user/ansi_parser.rl" */
|
/* #line 297 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
// Reset screen
|
// Reset screen
|
||||||
handle_RESET_cmd();
|
handle_RESET_cmd();
|
||||||
{cs = 1; goto _again;}
|
{cs = 1; goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* #line 415 "user/ansi_parser.c" */
|
/* #line 422 "user/ansi_parser.c" */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
goto _again;
|
goto _again;
|
||||||
@@ -434,7 +441,13 @@ _again:
|
|||||||
{cs = 1; goto _again;}
|
{cs = 1; goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* #line 438 "user/ansi_parser.c" */
|
case 7:
|
||||||
|
/* #line 280 "user/ansi_parser.rl" */
|
||||||
|
{
|
||||||
|
{cs = 1; goto _again;}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
/* #line 451 "user/ansi_parser.c" */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -442,6 +455,6 @@ _again:
|
|||||||
_out: {}
|
_out: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #line 311 "user/ansi_parser.rl" */
|
/* #line 315 "user/ansi_parser.rl" */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -277,6 +277,10 @@ ansi_parser(const char *newdata, size_t len)
|
|||||||
fgoto main;
|
fgoto main;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action main_fail {
|
||||||
|
fgoto main;
|
||||||
|
}
|
||||||
|
|
||||||
CSI_body := ((32..47|60..64) @CSI_leading)?
|
CSI_body := ((32..47|60..64) @CSI_leading)?
|
||||||
((digit @CSI_digit)* ';' @CSI_semi)*
|
((digit @CSI_digit)* ';' @CSI_semi)*
|
||||||
(digit @CSI_digit)* alpha @CSI_end $!CSI_fail;
|
(digit @CSI_digit)* alpha @CSI_end $!CSI_fail;
|
||||||
@@ -305,7 +309,7 @@ ansi_parser(const char *newdata, size_t len)
|
|||||||
']' @OSC_start |
|
']' @OSC_start |
|
||||||
'c' @RESET_cmd
|
'c' @RESET_cmd
|
||||||
)
|
)
|
||||||
)+;
|
)+ $!main_fail;
|
||||||
|
|
||||||
write exec;
|
write exec;
|
||||||
}%%
|
}%%
|
||||||
|
|||||||
+106
-22
@@ -53,10 +53,22 @@ static Coordinate W = SCREEN_DEF_W;
|
|||||||
*/
|
*/
|
||||||
static Coordinate H = SCREEN_DEF_H;
|
static Coordinate H = SCREEN_DEF_H;
|
||||||
|
|
||||||
|
// XXX volatile is probably not needed
|
||||||
|
static volatile int notifyLock = 0;
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region Helpers
|
//region Helpers
|
||||||
|
|
||||||
|
#define NOTIFY_LOCK() do { \
|
||||||
|
notifyLock++; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define NOTIFY_DONE() do { \
|
||||||
|
if (notifyLock > 0) notifyLock--; \
|
||||||
|
if (notifyLock == 0) screen_notifyChange(); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset a cell
|
* Reset a cell
|
||||||
*/
|
*/
|
||||||
@@ -103,12 +115,13 @@ cursor_reset(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_init(void)
|
screen_init(void)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
for (unsigned int i = 0; i < MAX_SCREEN_SIZE; i++) {
|
for (unsigned int i = 0; i < MAX_SCREEN_SIZE; i++) {
|
||||||
cell_init(&screen[i]);
|
cell_init(&screen[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor_reset();
|
cursor_reset();
|
||||||
screen_notifyChange();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,9 +130,10 @@ screen_init(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_reset(void)
|
screen_reset(void)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
screen_clear(CLEAR_ALL);
|
screen_clear(CLEAR_ALL);
|
||||||
cursor_reset();
|
cursor_reset();
|
||||||
screen_notifyChange();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,6 +142,7 @@ screen_reset(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_clear(ClearMode mode)
|
screen_clear(ClearMode mode)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case CLEAR_ALL:
|
case CLEAR_ALL:
|
||||||
clear_range(0, W * H - 1);
|
clear_range(0, W * H - 1);
|
||||||
@@ -141,7 +156,7 @@ screen_clear(ClearMode mode)
|
|||||||
clear_range(0, (cursor.y * W) + cursor.x);
|
clear_range(0, (cursor.y * W) + cursor.x);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
screen_notifyChange();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,6 +165,7 @@ screen_clear(ClearMode mode)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_clear_line(ClearMode mode)
|
screen_clear_line(ClearMode mode)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case CLEAR_ALL:
|
case CLEAR_ALL:
|
||||||
clear_range(cursor.y * W, (cursor.y + 1) * W - 1);
|
clear_range(cursor.y * W, (cursor.y + 1) * W - 1);
|
||||||
@@ -163,7 +179,7 @@ screen_clear_line(ClearMode mode)
|
|||||||
clear_range(cursor.y * W, cursor.y * W + cursor.x);
|
clear_range(cursor.y * W, cursor.y * W + cursor.x);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
screen_notifyChange();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -179,6 +195,7 @@ screen_clear_line(ClearMode mode)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_resize(Coordinate w, Coordinate h)
|
screen_resize(Coordinate w, Coordinate h)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
// sanitize
|
// sanitize
|
||||||
if (w < 1) w = 1;
|
if (w < 1) w = 1;
|
||||||
if (h < 1) h = 1;
|
if (h < 1) h = 1;
|
||||||
@@ -186,7 +203,7 @@ screen_resize(Coordinate w, Coordinate h)
|
|||||||
W = w;
|
W = w;
|
||||||
H = h;
|
H = h;
|
||||||
screen_reset();
|
screen_reset();
|
||||||
screen_notifyChange();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -195,13 +212,15 @@ screen_resize(Coordinate w, Coordinate h)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_scroll_up(unsigned int lines)
|
screen_scroll_up(unsigned int lines)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
if (lines >= H - 1) {
|
if (lines >= H - 1) {
|
||||||
screen_clear(CLEAR_ALL);
|
screen_clear(CLEAR_ALL);
|
||||||
return;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bad cmd
|
||||||
if (lines == 0) {
|
if (lines == 0) {
|
||||||
return;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
int y;
|
int y;
|
||||||
@@ -210,7 +229,9 @@ screen_scroll_up(unsigned int lines)
|
|||||||
}
|
}
|
||||||
|
|
||||||
clear_range(y * W, W * H - 1);
|
clear_range(y * W, W * H - 1);
|
||||||
screen_notifyChange();
|
|
||||||
|
done:
|
||||||
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -219,13 +240,15 @@ screen_scroll_up(unsigned int lines)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_scroll_down(unsigned int lines)
|
screen_scroll_down(unsigned int lines)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
if (lines >= H - 1) {
|
if (lines >= H - 1) {
|
||||||
screen_clear(CLEAR_ALL);
|
screen_clear(CLEAR_ALL);
|
||||||
return;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bad cmd
|
||||||
if (lines == 0) {
|
if (lines == 0) {
|
||||||
return;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
int y;
|
int y;
|
||||||
@@ -234,7 +257,8 @@ screen_scroll_down(unsigned int lines)
|
|||||||
}
|
}
|
||||||
|
|
||||||
clear_range(0, lines * W-1);
|
clear_range(0, lines * W-1);
|
||||||
screen_notifyChange();
|
done:
|
||||||
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -247,11 +271,12 @@ screen_scroll_down(unsigned int lines)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_cursor_set(Coordinate x, Coordinate y)
|
screen_cursor_set(Coordinate x, Coordinate y)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
if (x >= W) x = W - 1;
|
if (x >= W) x = W - 1;
|
||||||
if (y >= H) y = H - 1;
|
if (y >= H) y = H - 1;
|
||||||
cursor.x = x;
|
cursor.x = x;
|
||||||
cursor.y = y;
|
cursor.y = y;
|
||||||
screen_notifyChange();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -260,9 +285,10 @@ screen_cursor_set(Coordinate x, Coordinate y)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_cursor_set_x(Coordinate x)
|
screen_cursor_set_x(Coordinate x)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
if (x >= W) x = W - 1;
|
if (x >= W) x = W - 1;
|
||||||
cursor.x = x;
|
cursor.x = x;
|
||||||
screen_notifyChange();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -271,9 +297,10 @@ screen_cursor_set_x(Coordinate x)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_cursor_set_y(Coordinate y)
|
screen_cursor_set_y(Coordinate y)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
if (y >= H) y = H - 1;
|
if (y >= H) y = H - 1;
|
||||||
cursor.y = y;
|
cursor.y = y;
|
||||||
screen_notifyChange();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -282,10 +309,27 @@ screen_cursor_set_y(Coordinate y)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_cursor_move(int dx, int dy)
|
screen_cursor_move(int dx, int dy)
|
||||||
{
|
{
|
||||||
if (dx < 0 && -dx > cursor.x) dx = -cursor.x;
|
NOTIFY_LOCK();
|
||||||
if (dy < 0 && -dy > cursor.y) dy = -cursor.y;
|
int move;
|
||||||
screen_cursor_set(cursor.x + dx, cursor.y + dy);
|
|
||||||
screen_notifyChange();
|
cursor.x += dx;
|
||||||
|
cursor.y += dy;
|
||||||
|
if (cursor.x >= W) cursor.x = W - 1;
|
||||||
|
if (cursor.x < 0) cursor.x = 0;
|
||||||
|
|
||||||
|
if (cursor.y < 0) {
|
||||||
|
move = -cursor.y;
|
||||||
|
cursor.y = 0;
|
||||||
|
screen_scroll_down((unsigned int)move);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor.y >= H) {
|
||||||
|
move = cursor.y - (H - 1);
|
||||||
|
cursor.y = H - 1;
|
||||||
|
screen_scroll_up((unsigned int)move);
|
||||||
|
}
|
||||||
|
|
||||||
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -304,9 +348,10 @@ screen_cursor_save(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_cursor_restore(void)
|
screen_cursor_restore(void)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
cursor.x = cursor_sav.x;
|
cursor.x = cursor_sav.x;
|
||||||
cursor.y = cursor_sav.y;
|
cursor.y = cursor_sav.y;
|
||||||
screen_notifyChange();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -315,8 +360,9 @@ screen_cursor_restore(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_cursor_enable(bool enable)
|
screen_cursor_enable(bool enable)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
cursor.visible = enable;
|
cursor.visible = enable;
|
||||||
screen_notifyChange();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -383,7 +429,44 @@ screen_set_bright_fg(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_putchar(char ch)
|
screen_putchar(char ch)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
|
|
||||||
Cell *c = &screen[cursor.x + cursor.y * W];
|
Cell *c = &screen[cursor.x + cursor.y * W];
|
||||||
|
|
||||||
|
// Special treatment for CRLF
|
||||||
|
switch (ch) {
|
||||||
|
case '\r':
|
||||||
|
screen_cursor_set_x(0);
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
screen_cursor_move(0, 1);
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
case 8: // BS
|
||||||
|
if (cursor.x > 0) cursor.x--;
|
||||||
|
// erase target cell
|
||||||
|
c = &screen[cursor.x + cursor.y * W];
|
||||||
|
c->c = ' ';
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
case 9: // TAB
|
||||||
|
c->c = ' ';
|
||||||
|
// nested recurs >:( but it's ok
|
||||||
|
screen_putchar(' ');
|
||||||
|
screen_putchar(' ');
|
||||||
|
screen_putchar(' ');
|
||||||
|
screen_putchar(' ');
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (ch < ' ') {
|
||||||
|
// Discard
|
||||||
|
warn("Ignoring control char %d", (int)c);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c->c = ch;
|
c->c = ch;
|
||||||
|
|
||||||
if (cursor.inverse) {
|
if (cursor.inverse) {
|
||||||
@@ -407,7 +490,8 @@ screen_putchar(char ch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
screen_notifyChange();
|
done:
|
||||||
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -495,7 +579,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
|||||||
ss->lastFg = 0;
|
ss->lastFg = 0;
|
||||||
ss->lastChar = '\0';
|
ss->lastChar = '\0';
|
||||||
|
|
||||||
bufprint("{x:%d,y:%d,screen:\"", cursor.x, cursor.y);
|
bufprint("{\"x\":%d,\"y\":%d,\"screen\":\"", cursor.x, cursor.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = ss->index;
|
int i = ss->index;
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ typedef enum {
|
|||||||
} ClearMode;
|
} ClearMode;
|
||||||
|
|
||||||
typedef uint8_t Color;
|
typedef uint8_t Color;
|
||||||
typedef unsigned int Coordinate;
|
typedef int Coordinate;
|
||||||
|
|
||||||
httpd_cgi_state ICACHE_FLASH_ATTR
|
httpd_cgi_state ICACHE_FLASH_ATTR
|
||||||
screenSerializeToBuffer(char *buffer, size_t buf_len, void **data);
|
screenSerializeToBuffer(char *buffer, size_t buf_len, void **data);
|
||||||
|
|||||||
+6
-3
@@ -25,7 +25,10 @@ void ICACHE_FLASH_ATTR serialInit(void)
|
|||||||
*/
|
*/
|
||||||
void ICACHE_FLASH_ATTR UART_HandleRxByte(char c)
|
void ICACHE_FLASH_ATTR UART_HandleRxByte(char c)
|
||||||
{
|
{
|
||||||
// TODO buffering, do not run parser after just 1 char
|
if (c > 0 && c < 127) {
|
||||||
printf("(%c)", c);
|
// TODO buffering, do not run parser after just 1 char
|
||||||
ansi_parser(&c, 1);
|
ansi_parser(&c, 1);
|
||||||
|
} else {
|
||||||
|
warn("Bad char %d ('%c')", (unsigned char)c, c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+5
-4
@@ -55,8 +55,7 @@ void ICACHE_FLASH_ATTR myWebsocketConnect(Websock *ws) {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
httpd_cgi_state ICACHE_FLASH_ATTR tplScreen(HttpdConnData *connData, char *token, void **arg) {
|
httpd_cgi_state ICACHE_FLASH_ATTR tplScreen(HttpdConnData *connData, char *token, void **arg) {
|
||||||
// cleanup
|
if (token==NULL) {
|
||||||
if (!connData) {
|
|
||||||
// Release data object
|
// Release data object
|
||||||
screenSerializeToBuffer(NULL, 0, arg);
|
screenSerializeToBuffer(NULL, 0, arg);
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
@@ -67,6 +66,9 @@ httpd_cgi_state ICACHE_FLASH_ATTR tplScreen(HttpdConnData *connData, char *token
|
|||||||
|
|
||||||
if (streq(token, "screenData")) {
|
if (streq(token, "screenData")) {
|
||||||
httpd_cgi_state cont = screenSerializeToBuffer(buff, bufsiz, arg);
|
httpd_cgi_state cont = screenSerializeToBuffer(buff, bufsiz, arg);
|
||||||
|
|
||||||
|
dbg("Sending buf: %s", buff);
|
||||||
|
|
||||||
httpdSend(connData, buff, -1);
|
httpdSend(connData, buff, -1);
|
||||||
return cont;
|
return cont;
|
||||||
}
|
}
|
||||||
@@ -104,8 +106,7 @@ HttpdBuiltInUrl builtInUrls[]={ //ICACHE_RODATA_ATTR
|
|||||||
|
|
||||||
// TODO add funcs for WiFi management (when web UI is added)
|
// TODO add funcs for WiFi management (when web UI is added)
|
||||||
|
|
||||||
// ROUTE_TPL_FILE("/", tplScreen, "term.tpl"),
|
ROUTE_TPL_FILE("/", tplScreen, "term.tpl"),
|
||||||
ROUTE_TPL("/term.tpl", tplScreen),
|
|
||||||
ROUTE_FILESYSTEM(),
|
ROUTE_FILESYSTEM(),
|
||||||
ROUTE_END(),
|
ROUTE_END(),
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user