diff --git a/README.md b/README.md
index 3f8e9ba..93dc8ef 100644
--- a/README.md
+++ b/README.md
@@ -1,96 +1,2 @@
-# esp-httpd README #
-
-This is the demonstration project for the small but powerful libesphttpd webserver
-for ESP8266(EX) chips. It is an example of how to make a module that can have
-the AP it connects to configured over a webbrowser. It also illustrates multiple
-flash layouts and some OTA update functionality.
-
-## ABOUT THE WEBSERVER ##
-
-The Good (aka: what's awesome)
- - Supports multiple connections, for eg simultaneous html/css/js/images downloading
- - Static files stored in flash, in an (optionally compressed) RO filesystem
- - Pluggable using external cgi routines
- - Simple template engine for mixed c and html things
- - Usable as an embedded library - should be easy to drop into your existing projects
- - Includes websocket support
-
-The Bad (aka: what can be improved)
- - Not built for speediness, although it's reasonable fast.
- - Built according to what I remember of the HTTP protocol, not according to the
- RFCs. Should work with most modern browsers, though.
- - No support for https.
-
-The Ugly (aka: bugs, misbehaviour)
-- Possible buffer overflows (usually not remotely exploitable) due to no os_snprintf
- This can be theoretically remedied by either Espressif including an os_snprintf in
- their libs or by using some alternate printf lib, like elm-chans xprintf
-
-## SOURCE OF THIS CODE ##
-The official esphttpd repo lives at http://git.spritesserver.nl/esphttpd.git/ and
-http://git.spritesserver.nl/libesphttpd.git/ . If you're a fan of Github, you can also
-peruse the official mirror at https://github.com/Spritetm/esphttpd and https://github.com/Spritetm/libesphttpd . If
-you want to discuss this code, there is a subforum at esp8266.com: http://www.esp8266.com/viewforum.php?f=34 .
-
-
-## ABOUT THE EXAMPLE ##
-
-When you flash the example into an ESP8266(EX) module, you get a small webserver with a few example
-pages. If you've already connected your module to your WLAN before, it'll keep those settings. When
-you haven't or the settings are wrong, keep GPIO0 for >5 seconds. The module will reboot into
-its STA+AP mode. Connect a computer to the newly formed access point and browse to
-http://192.168.4.1/wifi in order to connect the module to your WiFi network. The example also
-allows you to control a LED that's connected to GPIO2.
-
-## BUILDING EVERYTHING ##
-
-For this, you need an environment that can compile ESP8266 firmware. Environments for this still
-are in flux at the moment, but I'm using esp-open-sdk: https://github.com/pfalcon/esp-open-sdk .
-You probably also need an UNIX-like system; I'm working on Debian Linux myself.
-
-To manage the paths to all this, you can source a small shell fragment into your current session. For
-example, I source a file with these contents:
-
- export PATH=${PWD}/esp-open-sdk/xtensa-lx106-elf/bin:$PATH
- export SDK_BASE=${PWD}/esp-open-sdk/sdk
- export ESPTOOL=${PWD}/esptool/esptool.py
- export ESPPORT=/dev/ttyUSB0
- export ESPBAUD=460800
-
-Actual setup of the SDK and toolchain is out of the scope of this document, so I hope this helps you
-enough to set up your own if you haven't already.
-
-If you have that, you can clone out the source code:
-git clone http://git.spritesserver.nl/esphttpd.git/
-
-This project makes use of heatshrink, which is a git submodule. To fetch the code:
-
- cd esphttpd
- git submodule init
- git submodule update
-
-Now, build the code:
-
- make
-
-Depending on the way you built it, esp-open-sdk sometimes patches Espressifs SDK, needing a slightly different
-compiling process. If this is needed, you will get errors during compiling complaining about uint8_t being
-undeclared. If this happens, try building like this:
-
- make USE_OPENSDK=yes
-
-You can also edit the Makefile to change this more permanently.
-
-After the compile process, flash the code happens in 2 steps. First the code itself gets flashed. Reset the module into bootloader
-mode and enter 'make flash'.
-
-The 2nd step is to pack the static files the webserver will serve and flash that. Reset the module into
-bootloader mode again and enter `make htmlflash`.
-
-You should have a working webserver now.
-
-## WRITING CODE FOR THE WEBSERVER ##
-
-Please see the README.md of the libesphttpd project for the programming manual.
-
-
+# esp-vt100-firmware
+ESP8266 Remote Terminal project
diff --git a/compress_html.sh b/compress_html.sh
new file mode 100755
index 0000000..d71b43b
--- /dev/null
+++ b/compress_html.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+yuicompressor html_orig/style.css > html/style.css
+yuicompressor html_orig/script.js > html/script.js
+minify --type=html html_orig/index.html -o html/index.html
diff --git a/html/cats/cross-eyed-cat.jpg b/html/cats/cross-eyed-cat.jpg
deleted file mode 100644
index e166e87..0000000
Binary files a/html/cats/cross-eyed-cat.jpg and /dev/null differ
diff --git a/html/cats/junge-katze-iv.jpg b/html/cats/junge-katze-iv.jpg
deleted file mode 100644
index c3cf70b..0000000
Binary files a/html/cats/junge-katze-iv.jpg and /dev/null differ
diff --git a/html/cats/kitten-loves-toy.jpg b/html/cats/kitten-loves-toy.jpg
deleted file mode 100644
index 569ff56..0000000
Binary files a/html/cats/kitten-loves-toy.jpg and /dev/null differ
diff --git a/html/flash/140medley.min.js b/html/flash/140medley.min.js
deleted file mode 100644
index d1495d1..0000000
--- a/html/flash/140medley.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-var t=function(a,b){return function(c,d){return a.replace(/#{([^}]*)}/g,function(a,f){return Function("x","with(x)return "+f).call(c,d||b||{})})}},s=function(a,b){return b?{get:function(c){return a[c]&&b.parse(a[c])},set:function(c,d){a[c]=b.stringify(d)}}:{}}(this.localStorage||{},JSON),p=function(a,b,c,d){c=c||document;d=c[b="on"+b];a=c[b]=function(e){d=d&&d(e=e||c.event);return(a=a&&b(e))?b:d};c=this},m=function(a,b,c){b=document;c=b.createElement("p");c.innerHTML=a;for(a=b.createDocumentFragment();b=
-c.firstChild;)a.appendChild(b);return a},$=function(a,b){a=a.match(/^(\W)?(.*)/);return(b||document)["getElement"+(a[1]?a[1]=="#"?"ById":"sByClassName":"sByTagName")](a[2])},j=function(a){for(a=0;a<4;a++)try{return a?new ActiveXObject([,"Msxml2","Msxml3","Microsoft"][a]+".XMLHTTP"):new XMLHttpRequest}catch(b){}};
diff --git a/html/flash/index.html b/html/flash/index.html
deleted file mode 100644
index 117976b..0000000
--- a/html/flash/index.html
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
+
+
diff --git a/html_orig/script.js b/html_orig/script.js
new file mode 100644
index 0000000..2dcda4c
--- /dev/null
+++ b/html_orig/script.js
@@ -0,0 +1,271 @@
+//region Libs / utils
+
+/*
+ * DOM selector
+ *
+ * Usage:
+ * $('div');
+ * $('#name');
+ * $('.name');
+ *
+ *
+ * Copyright (C) 2011 Jed Schmidt - WTFPL
+ * More: https://gist.github.com/991057
+ *
+ */
+
+var $ = function(
+ a, // take a simple selector like "name", "#name", or ".name", and
+ b // an optional context, and
+){
+ a = a.match(/^(\W)?(.*)/); // split the selector into name and symbol.
+ return( // return an element or list, from within the scope of
+ b // the passed context
+ || document // or document,
+ )[
+ "getElement" + ( // obtained by the appropriate method calculated by
+ a[1]
+ ? a[1] == "#"
+ ? "ById" // the node by ID,
+ : "sByClassName" // the nodes by class name, or
+ : "sByTagName" // the nodes by tag name,
+ )
+ ](
+ a[2] // called with the name.
+ )
+};
+
+/*
+ * Create DOM element
+ *
+ * Usage:
+ * var el = m('
Hello
');
+ * document.body.appendChild(el);
+ *
+ *
+ * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ * Version 2, December 2004
+ *
+ * Copyright (C) 2011 Jed Schmidt - WTFPL
+ * More: https://gist.github.com/966233
+ *
+ */
+
+var m = function(
+ a, // an HTML string
+ b, // placeholder
+ c // placeholder
+){
+ b = document; // get the document,
+ c = b.createElement("p"); // create a container element,
+ c.innerHTML = a; // write the HTML to it, and
+ a = b.createDocumentFragment(); // create a fragment.
+
+ while ( // while
+ b = c.firstChild // the container element has a first child
+ ) a.appendChild(b); // append the child to the fragment,
+
+ return a // and then return the fragment.
+};
+
+//endregion
+
+
+//
+// Terminal class
+//
+(function () {
+ function make(e) {return document.createElement(e)}
+
+ var W = 26, H = 10; //26, 10
+ var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false};
+ var screen = [];
+
+ /** Colors table */
+ var CLR = [// dark gray #2E3436
+ // 0 black, 1 red, 2 green, 3 yellow
+ // 4 blue, 5 mag, 6 cyan, 7 white
+ '#111213','#CC0000','#4E9A06','#C4A000',
+ '#3465A4','#75507B','#06989A','#D3D7CF',
+ // BRIGHT
+ // 8 black, 9 red, 10 green, 11 yellow
+ // 12 blue, 13 mag, 14 cyan, 15 white
+ '#555753','#EF2929','#8AE234','#FCE94F',
+ '#729FCF','#AD7FA8','#34E2E2','#EEEEEC'
+ ];
+
+ /** Clear screen */
+ function cls() {
+ screen.forEach(function(cell, i) {
+ cell.t = ' ';
+ cell.fg = 7;
+ cell.bg = 0;
+ blit(cell);
+ });
+ }
+
+ /** Set text and color at XY */
+ function cellAt(y, x) {
+ return screen[y*W+x];
+ }
+
+ /** Get cell under cursor */
+ function cursorCell() {
+ return cellAt(cursor.y, cursor.x);
+ }
+
+ /** Enable or disable cursor visibility */
+ function cursorEnable(enable) {
+ cursor.hidden = !enable;
+ cursor.a &= enable;
+ blit(cursorCell(), cursor.a);
+ }
+
+ /** Safely move cursor */
+ function cursorSet(y, x) {
+ // Hide and prevent from showing up during the move
+ cursor.suppress = true;
+ blit(cursorCell(), false);
+
+ cursor.x = x;
+ cursor.y = y;
+
+ // Show again
+ cursor.suppress = false;
+ blit(cursorCell(), cursor.a);
+ }
+
+ /** Update cell on display. inv = invert (for cursor) */
+ function blit(cell, inv) {
+ var e = cell.e, fg, bg;
+ // Colors
+ fg = inv ? cell.bg : cell.fg;
+ bg = inv ? cell.fg : cell.bg;
+ // Update
+ e.innerText = (cell.t+' ')[0];
+ e.style.color = colorHex(fg);
+ e.style.backgroundColor = colorHex(bg);
+ e.style.fontWeight = fg > 7 ? 'bold' : 'normal';
+ }
+
+ /** Show entire screen */
+ function blitAll() {
+ screen.forEach(function(cell, i) {
+ /* Invert if under cursor & cursor active */
+ var inv = cursor.a && (i == cursor.y*W+cursor.x);
+ blit(cell, inv);
+ });
+ }
+
+ /** Load screen content from a 'binary' sequence */
+ function load(seq) {
+ if (seq.length != W*H*3) throw "Bad data format.";
+
+ // primitive format with 3 chars per cell: letter, fg [hex], bg [hex]
+ for (var i = 0; i < W * H; i++) {
+ var cell = screen[i];
+ cell.t = seq[i*3];
+ cell.fg = parseInt(seq[i*3+1], 16);
+ cell.bg = parseInt(seq[i*3+2], 16);
+ }
+
+ blitAll();
+ }
+
+ /** Parse color */
+ function colorHex(c) {
+ var c = parseInt(c);
+ if (c < 0 || c > 15) c = 0;
+ return CLR[c];
+ }
+
+ /** Init the terminal */
+ function init() {
+ /* Build screen & show */
+ var e, scr = $('#screen');
+ for(var i = 0; i < W*H; i++) {
+ e = make('span');
+
+ /* End of line */
+ if ((i > 0) && (i % W == 0)) {
+ scr.appendChild(make('br'));
+ }
+ /* The cell */
+ scr.appendChild(e);
+
+ var cell = {t: ' ', fg: 7, bg: 0, e: e};
+ screen.push(cell);
+ blit(cell);
+ }
+
+ /* Cursor blinking */
+ setInterval(function() {
+ cursor.a = !cursor.a;
+ if (cursor.hidden) {
+ cursor.a = false;
+ }
+
+ if (!cursor.suppress) {
+ blit(cursorCell(), cursor.a);
+ }
+ }, 500);
+ }
+
+ // publish
+ window.Term = {
+ init: init,
+ load: load,
+ setCursor: cursorSet,
+ enableCursor: cursorEnable,
+ clear: cls,
+ };
+})();
+
+//
+// Connection class
+//
+(function() {
+ var wsUri = "ws://"+window.location.host+"/ws/update.cgi";
+ var ws;
+
+ function onOpen(evt) {
+ console.log("CONNECTED");
+ }
+
+ function onClose(evt) {
+ console.error("SOCKET CLOSED");
+ }
+
+ function onMessage(evt) {
+ console.log("Message received!", evt.data);
+ // TODO process
+ }
+
+ function onError(evt) {
+ console.error(evt.data);
+ }
+
+ function doSend(message) {
+ ws.send(message);
+ }
+
+ function init() {
+ ws = new WebSocket(wsUri);
+ ws.onopen = onOpen;
+ ws.onclose = onClose
+ ws.onmessage = onMessage;
+ ws.onerror = onError;
+
+ console.log("Opening socket.");
+ }
+
+ window.Conn = {
+ ws: null,
+ init: init,
+ };
+})();
+
+function init() {
+ Term.init();
+ Conn.init();
+}
diff --git a/html_orig/style.css b/html_orig/style.css
new file mode 100644
index 0000000..06f1a5b
--- /dev/null
+++ b/html_orig/style.css
@@ -0,0 +1,40 @@
+html, body {
+ background: #48505F;
+ color: #eee;
+ font-family: monospace;
+ font-size: 16pt;
+ text-align: center;
+}
+
+header {
+ font-weight: bold;
+ font-size: 14pt;
+ padding: 6px;
+ display: block;
+}
+
+#screen {
+ display: block;
+ white-space: nowrap;
+ background: #111213;
+ border-radius: 3px;
+ padding: 6px;
+ box-shadow: inset 0 0 5px black;
+ display: inline-block;
+}
+
+#screen span {
+ white-space: pre;
+}
+
+#buttons {
+ margin-top: 10px;
+}
+
+button {
+ margin: 0 2px;
+ padding: 10px 0;
+ width: 22%;
+ max-width: 80px;
+ cursor: pointer;
+}
diff --git a/include/ets_sys_extra.h b/include/ets_sys_extra.h
new file mode 100755
index 0000000..a1a27e1
--- /dev/null
+++ b/include/ets_sys_extra.h
@@ -0,0 +1,17 @@
+#pragma once
+#include
+
+// copied from nodemcu source
+extern uint32_t system_get_time();
+extern uint32_t platform_tmr_exists(uint32_t t);
+extern uint32_t system_rtc_clock_cali_proc();
+extern uint32_t system_get_rtc_time();
+extern void system_restart();
+extern void system_soft_wdt_feed();
+
+// https://github.com/mziwisky/esp8266-dev/blob/master/esphttpd/include/espmissingincludes.h
+extern int ets_str2macaddr(void *, void *);
+extern void ets_update_cpu_frequency(int freqmhz);
+extern int os_printf_plus(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
+//extern uint8 wifi_get_opmode(void);
+extern void ets_bzero(void *s, size_t n);
diff --git a/user/cgi-test.c b/user/cgi-test.c
deleted file mode 100644
index 8817c7a..0000000
--- a/user/cgi-test.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-Cgi routines as used by the tests in the html/test subdirectory.
-*/
-
-/*
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Jeroen Domburg wrote this file. As long as you retain
- * this notice you can do whatever you want with this stuff. If we meet some day,
- * and you think this stuff is worth it, you can buy me a beer in return.
- * ----------------------------------------------------------------------------
- */
-
-
-#include
-#include "cgi-test.h"
-
-
-typedef struct {
- int len;
- int sendPos;
-} TestbedState;
-
-
-httpd_cgi_state ICACHE_FLASH_ATTR cgiTestbed(HttpdConnData *connData) {
- char buff[1024];
- int first=0;
- int l, x;
- TestbedState *state=(TestbedState*)connData->cgiData;
-
- if (connData->conn==NULL) {
- //Connection aborted. Clean up.
- if (state) free(state);
- return HTTPD_CGI_DONE;
- }
-
- if (state==NULL) {
- //First call
- state=malloc(sizeof(TestbedState));
- memset(state, 0, sizeof(state));
- connData->cgiData=state;
- first=1;
- }
-
- if (connData->requestType==HTTPD_METHOD_GET) {
- if (first) {
- httpdStartResponse(connData, 200);
- httpdHeader(connData, "content-type", "application/data");
- httpdEndHeaders(connData);
- l=httpdFindArg(connData->getArgs, "len", buff, sizeof(buff));
- state->len=1024;
- if (l!=-1) state->len=atoi(buff);
- state->sendPos=0;
- return HTTPD_CGI_MORE;
- } else {
- l=sizeof(buff);
- if (l>(state->len-state->sendPos)) l=(state->len-state->sendPos);
- //Fill with semi-random data
- for (x=0; xsendPos>>10))&0x1F)+'0';
- httpdSend(connData, buff, l);
- state->sendPos+=l;
- printf("Test: Uploaded %d/%d bytes\n", state->sendPos, state->len);
- if (state->len<=state->sendPos) {
- if (state) free(state);
- return HTTPD_CGI_DONE;
- } else {
- return HTTPD_CGI_MORE;
- }
- }
- }
- if (connData->requestType==HTTPD_METHOD_POST) {
- if (connData->post->len!=connData->post->received) {
- //Still receiving data. Ignore this.
- printf("Test: got %d/%d bytes\n", connData->post->received, connData->post->len);
- return HTTPD_CGI_MORE;
- } else {
- httpdStartResponse(connData, 200);
- httpdHeader(connData, "content-type", "text/plain");
- httpdEndHeaders(connData);
- l=sprintf(buff, "%d", connData->post->received);
- httpdSend(connData, buff, l);
- return HTTPD_CGI_DONE;
- }
- }
- return HTTPD_CGI_DONE;
-}
diff --git a/user/cgi-test.h b/user/cgi-test.h
deleted file mode 100644
index 501e6f3..0000000
--- a/user/cgi-test.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef CGI_TEST_H
-#define CGI_TEST_H
-
-#include "httpd.h"
-
-httpd_cgi_state cgiTestbed(HttpdConnData *connData);
-
-#endif
diff --git a/user/cgi.c b/user/cgi.c
deleted file mode 100644
index c73b3ff..0000000
--- a/user/cgi.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-Some random cgi routines. Used in the LED example and the page that returns the entire
-flash as a binary. Also handles the hit counter on the main page.
-*/
-
-/*
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Jeroen Domburg wrote this file. As long as you retain
- * this notice you can do whatever you want with this stuff. If we meet some day,
- * and you think this stuff is worth it, you can buy me a beer in return.
- * ----------------------------------------------------------------------------
- */
-
-
-#include
-#include "cgi.h"
-#include "io.h"
-
-
-//cause I can't be bothered to write an ioGetLed()
-static char currLedState=0;
-
-//Cgi that turns the LED on or off according to the 'led' param in the POST data
-httpd_cgi_state ICACHE_FLASH_ATTR cgiLed(HttpdConnData *connData) {
- int len;
- char buff[1024];
-
- if (connData->conn==NULL) {
- //Connection aborted. Clean up.
- return HTTPD_CGI_DONE;
- }
-
- len=httpdFindArg(connData->post->buff, "led", buff, sizeof(buff));
- if (len!=0) {
- currLedState=atoi(buff);
- ioLed(currLedState);
- }
-
- httpdRedirect(connData, "led.tpl");
- return HTTPD_CGI_DONE;
-}
-
-
-
-//Template code for the led page.
-httpd_cgi_state ICACHE_FLASH_ATTR tplLed(HttpdConnData *connData, char *token, void **arg) {
- char buff[128];
- if (token==NULL) return HTTPD_CGI_DONE;
-
- os_strcpy(buff, "Unknown");
- if (os_strcmp(token, "ledstate")==0) {
- if (currLedState) {
- os_strcpy(buff, "on");
- } else {
- os_strcpy(buff, "off");
- }
- }
- httpdSend(connData, buff, -1);
- return HTTPD_CGI_DONE;
-}
-
-static long hitCounter=0;
-
-//Template code for the counter on the index page.
-httpd_cgi_state ICACHE_FLASH_ATTR tplCounter(HttpdConnData *connData, char *token, void **arg) {
- char buff[128];
- if (token==NULL) return HTTPD_CGI_DONE;
-
- if (os_strcmp(token, "counter")==0) {
- hitCounter++;
- os_sprintf(buff, "%ld", hitCounter);
- }
- httpdSend(connData, buff, -1);
- return HTTPD_CGI_DONE;
-}
diff --git a/user/cgi.h b/user/cgi.h
deleted file mode 100644
index 7ba2a77..0000000
--- a/user/cgi.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef CGI_H
-#define CGI_H
-
-#include "httpd.h"
-
-httpd_cgi_state cgiLed(HttpdConnData *connData);
-httpd_cgi_state tplLed(HttpdConnData *connData, char *token, void **arg);
-httpd_cgi_state tplCounter(HttpdConnData *connData, char *token, void **arg);
-
-#endif
diff --git a/user/io.c b/user/io.c
index a342dbd..fa1ce2d 100644
--- a/user/io.c
+++ b/user/io.c
@@ -14,6 +14,8 @@
#define LEDGPIO 2
#define BTNGPIO 0
+static bool enable_ap_button = false;
+
static ETSTimer resetBtntimer;
void ICACHE_FLASH_ATTR ioLed(int ena) {
@@ -27,25 +29,34 @@ void ICACHE_FLASH_ATTR ioLed(int ena) {
static void ICACHE_FLASH_ATTR resetBtnTimerCb(void *arg) {
static int resetCnt=0;
- if (!GPIO_INPUT_GET(BTNGPIO)) {
+ if (enable_ap_button && !GPIO_INPUT_GET(BTNGPIO)) {
resetCnt++;
} else {
if (resetCnt>=6) { //3 sec pressed
wifi_station_disconnect();
- wifi_set_opmode(0x3); //reset to AP+STA mode
- os_printf("Reset to AP mode. Restarting system...\n");
+ wifi_set_opmode(STATIONAP_MODE); //reset to AP+STA mode
+ info("Reset to AP mode from GPIO0, Restarting system...");
system_restart();
}
resetCnt=0;
}
}
-void ioInit() {
+void ICACHE_FLASH_ATTR ioInit() {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
gpio_output_set(0, 0, (1<
+#include "uart_driver.h"
+#include "uart_handler.h"
+
+// Here the bitrates are defined
+#define UART0_BAUD BIT_RATE_115200
+#define UART1_BAUD BIT_RATE_115200
+
+/**
+ * Init the serial ports
+ */
+void ICACHE_FLASH_ATTR serialInit(void)
+{
+ UART_Init(UART0_BAUD, UART1_BAUD);
+ UART_SetPrintPort(UART0);
+ UART_SetupAsyncReceiver();
+}
+
+/**
+ * Handle a byte received from UART.
+ * Might do some buffering here maybe
+ *
+ * @param c
+ */
+void ICACHE_FLASH_ATTR UART_HandleRxByte(char c)
+{
+ printf("'%c',", c);
+}
\ No newline at end of file
diff --git a/user/serial.h b/user/serial.h
new file mode 100644
index 0000000..eda2e5b
--- /dev/null
+++ b/user/serial.h
@@ -0,0 +1,9 @@
+#ifndef SERIAL_H
+#define SERIAL_H
+
+/** Init the uarts */
+void serialInit(void);
+
+void UART_HandleRxByte(char c);
+
+#endif //SERIAL_H
diff --git a/user/stdout.c b/user/stdout.c
deleted file mode 100644
index bb4dddb..0000000
--- a/user/stdout.c
+++ /dev/null
@@ -1,47 +0,0 @@
-//Stupid bit of code that does the bare minimum to make os_printf work.
-
-/*
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Jeroen Domburg wrote this file. As long as you retain
- * this notice you can do whatever you want with this stuff. If we meet some day,
- * and you think this stuff is worth it, you can buy me a beer in return.
- * ----------------------------------------------------------------------------
- */
-
-#include
-#include
-
-static void ICACHE_FLASH_ATTR stdoutUartTxd(char c) {
- //Wait until there is room in the FIFO
- while (((READ_PERI_REG(UART_STATUS(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ;
- //Send the character
- WRITE_PERI_REG(UART_FIFO(0), c);
-}
-
-static void ICACHE_FLASH_ATTR stdoutPutchar(char c) {
- //convert \n -> \r\n
- if (c=='\n') stdoutUartTxd('\r');
- stdoutUartTxd(c);
-}
-
-
-void stdoutInit() {
- //Enable TxD pin
- PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
-
- //Set baud rate and other serial parameters to 115200,n,8,1
- uart_div_modify(0, UART_CLK_FREQ/BIT_RATE_115200);
- WRITE_PERI_REG(UART_CONF0(0), (STICK_PARITY_DIS)|(ONE_STOP_BIT << UART_STOP_BIT_NUM_S)| \
- (EIGHT_BITS << UART_BIT_NUM_S));
-
- //Reset tx & rx fifo
- SET_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
- CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
- //Clear pending interrupts
- WRITE_PERI_REG(UART_INT_CLR(0), 0xffff);
-
- //Install our own putchar handler
- os_install_putc1((void *)stdoutPutchar);
-}
diff --git a/user/stdout.h b/user/stdout.h
deleted file mode 100644
index a8d872d..0000000
--- a/user/stdout.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef STDOUT_H
-#define STDOUT_H
-
-void stdoutInit();
-
-#endif
\ No newline at end of file
diff --git a/user/uart_driver.c b/user/uart_driver.c
new file mode 100755
index 0000000..48f20f8
--- /dev/null
+++ b/user/uart_driver.c
@@ -0,0 +1,249 @@
+/*
+* Driver file for ESP8266 UART, works with the SDK.
+*/
+
+#include "uart_driver.h"
+
+#include
+
+#include "ets_sys.h"
+#include "osapi.h"
+#include "mem.h"
+#include "os_type.h"
+
+#include "ets_sys_extra.h"
+#include "uart_register.h"
+
+//========================================================
+
+
+void ICACHE_FLASH_ATTR UART_SetWordLength(UARTn uart_no, UartBitsNum4Char len)
+{
+ SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_BIT_NUM, len, UART_BIT_NUM_S);
+}
+
+
+void ICACHE_FLASH_ATTR UART_SetStopBits(UARTn uart_no, UartStopBitsNum bit_num)
+{
+ SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_STOP_BIT_NUM, bit_num, UART_STOP_BIT_NUM_S);
+}
+
+
+void ICACHE_FLASH_ATTR UART_SetLineInverse(UARTn uart_no, UART_LineLevelInverse inverse_mask)
+{
+ CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_LINE_INV_MASK);
+ SET_PERI_REG_MASK(UART_CONF0(uart_no), inverse_mask);
+}
+
+
+void ICACHE_FLASH_ATTR UART_SetParity(UARTn uart_no, UartParityMode Parity_mode)
+{
+ CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_PARITY | UART_PARITY_EN);
+ if (Parity_mode == PARITY_NONE) {
+ } else {
+ SET_PERI_REG_MASK(UART_CONF0(uart_no), Parity_mode | UART_PARITY_EN);
+ }
+}
+
+
+void ICACHE_FLASH_ATTR UART_SetBaudrate(UARTn uart_no, uint32 baud_rate)
+{
+ uart_div_modify(uart_no, UART_CLK_FREQ / baud_rate);
+}
+
+
+void ICACHE_FLASH_ATTR UART_SetFlowCtrl(UARTn uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh)
+{
+ if (flow_ctrl & USART_HWFlow_RTS) {
+ PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);
+ SET_PERI_REG_BITS(UART_CONF1(uart_no), UART_RX_FLOW_THRHD, rx_thresh, UART_RX_FLOW_THRHD_S);
+ SET_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN);
+ } else {
+ CLEAR_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN);
+ }
+
+ if (flow_ctrl & USART_HWFlow_CTS) {
+ PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS);
+ SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN);
+ } else {
+ CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN);
+ }
+}
+
+
+void ICACHE_FLASH_ATTR UART_WaitTxFifoEmpty(UARTn uart_no , uint32 time_out_us) //do not use if tx flow control enabled
+{
+ uint32 t_s = system_get_time();
+ while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)) {
+
+ if ((system_get_time() - t_s) > time_out_us) {
+ break;
+ }
+
+ system_soft_wdt_feed();
+ }
+}
+
+
+bool ICACHE_FLASH_ATTR UART_CheckOutputFinished(UARTn uart_no, uint32 time_out_us)
+{
+ uint32 t_start = system_get_time();
+ uint8 tx_fifo_len;
+
+ while (1) {
+ tx_fifo_len = UART_TxQueLen(uart_no);
+
+ // TODO If using output circbuf, check if empty
+
+ if (tx_fifo_len == 0) {
+ return TRUE;
+ }
+
+ if (system_get_time() - t_start > time_out_us) {
+ return FALSE;
+ }
+
+ system_soft_wdt_feed();
+ }
+}
+
+
+void ICACHE_FLASH_ATTR UART_ResetFifo(UARTn uart_no)
+{
+ SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
+ CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
+}
+
+
+void ICACHE_FLASH_ATTR UART_ClearIntrStatus(UARTn uart_no, uint32 clr_mask)
+{
+ WRITE_PERI_REG(UART_INT_CLR(uart_no), clr_mask);
+}
+
+
+void ICACHE_FLASH_ATTR UART_SetIntrEna(UARTn uart_no, uint32 ena_mask)
+{
+ SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask);
+}
+
+
+LOCAL void u0_putc_crlf(char c)
+{
+ UART_WriteCharCRLF(UART0, (u8)c, UART_TIMEOUT_US);
+}
+
+
+LOCAL void u1_putc_crlf(char c)
+{
+ UART_WriteCharCRLF(UART1, (u8)c, UART_TIMEOUT_US);
+}
+
+
+void ICACHE_FLASH_ATTR UART_SetPrintPort(UARTn uart_no)
+{
+ if (uart_no == UART0) {
+ os_install_putc1((void *)u0_putc_crlf);
+ } else {
+ os_install_putc1((void *)u1_putc_crlf);
+ }
+}
+
+
+// -------------- Custom UART functions -------------------------
+
+// !!! write handlers are not ICACHE_FLASH_ATTR -> can be used in IRQ !!!
+
+/**
+ * @brief Write a char to UART.
+ * @param uart_no
+ * @param c
+ * @param timeout_us - how long to max wait for space in FIFO.
+ * @return write success
+ */
+STATUS UART_WriteChar(UARTn uart_no, uint8 c, uint32 timeout_us)
+{
+ if (timeout_us == 0) {
+ timeout_us = UART_TIMEOUT_US;
+ }
+
+
+ uint32 t_s = system_get_time();
+
+ while ((system_get_time() - t_s) < timeout_us) {
+ uint8 fifo_cnt = UART_TxQueLen(uart_no);
+
+ if (fifo_cnt < UART_TX_FULL_THRESH_VAL) {
+ WRITE_PERI_REG(UART_FIFO(uart_no), c);
+ return OK;
+ }
+
+ system_soft_wdt_feed();
+ }
+
+ return FAIL;
+}
+
+
+/**
+ * @brief Write a char to UART, translating LF to CRLF and discarding CR.
+ * @param uart_no
+ * @param c
+ * @param timeout_us - how long to max wait for space in FIFO.
+ * @return write success
+ */
+STATUS UART_WriteCharCRLF(UARTn uart_no, uint8 c, uint32 timeout_us)
+{
+ STATUS st;
+
+ if (c == '\r') {
+ return OK;
+ } else if (c == '\n') {
+
+ st = UART_WriteChar(uart_no, '\r', timeout_us);
+ if (st != OK) return st;
+
+ st = UART_WriteChar(uart_no, '\n', timeout_us);
+ return st;
+
+ } else {
+ return UART_WriteChar(uart_no, c, timeout_us);
+ }
+}
+
+
+/**
+ * @brief Send a string to UART.
+ * @param uart_no
+ * @param str
+ * @param timeout_us - how long to max wait for space in FIFO.
+ * @return write success
+ */
+STATUS UART_WriteString(UARTn uart_no, const char *str, uint32 timeout_us)
+{
+ while (*str) {
+ STATUS suc = UART_WriteChar(uart_no, (u8) * str++, timeout_us);
+ if (suc != OK) return suc;
+ }
+
+ return OK;
+}
+
+
+
+/**
+ * @brief Send a buffer
+ * @param uart_no
+ * @param buffer - buffer to send
+ * @param len - buffer size
+ * @param timeout_us - how long to max wait for space in FIFO.
+ * @return write success
+ */
+STATUS UART_WriteBuffer(UARTn uart_no, const uint8 *buffer, size_t len, uint32 timeout_us)
+{
+ for (size_t i = 0; i < len; i++) {
+ STATUS suc = UART_WriteChar(uart_no, (u8) * buffer++, timeout_us);
+ if (suc != OK) return suc;
+ }
+
+ return OK;
+}
diff --git a/user/uart_driver.h b/user/uart_driver.h
new file mode 100755
index 0000000..8a95c0d
--- /dev/null
+++ b/user/uart_driver.h
@@ -0,0 +1,201 @@
+/**
+ * Low level UART peripheral support functions
+ */
+
+/*
+ * File : uart.h
+ * Copyright (C) 2013 - 2016, Espressif Systems
+ * Copyright (C) 2016, Ondřej Hruška (cleaning, modif.)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+
+#ifndef UART_APP_H
+#define UART_APP_H
+
+#include "uart_register.h"
+
+#include "eagle_soc.h"
+#include "c_types.h"
+
+
+// ===========
+
+// timeout for sending / receiving a char (default)
+#define UART_TIMEOUT_US 5000
+
+#define UART_TX_FULL_THRESH_VAL (UART_FIFO_LEN - 2) // if more than this many bytes in queue, don't write more
+#define UART_TX_EMPTY_THRESH_VAL 16
+
+// ===========
+
+
+typedef enum {
+ UART0 = 0,
+ UART1 = 1
+} UARTn;
+
+
+typedef enum {
+ FIVE_BITS = 0x0,
+ SIX_BITS = 0x1,
+ SEVEN_BITS = 0x2,
+ EIGHT_BITS = 0x3
+} UartBitsNum4Char;
+
+
+typedef enum {
+ ONE_STOP_BIT = 0x1,
+ ONE_HALF_STOP_BIT = 0x2,
+ TWO_STOP_BIT = 0x3
+} UartStopBitsNum;
+
+
+typedef enum {
+ PARITY_NONE = 0x2,
+ PARITY_ODD = 1,
+ PARITY_EVEN = 0
+} UartParityMode;
+
+
+typedef enum {
+ PARITY_DIS = 0,
+ PARITY_EN = 1
+} UartExistParity;
+
+
+typedef enum {
+ UART_None_Inverse = 0x0,
+ UART_Rxd_Inverse = UART_RXD_INV,
+ UART_CTS_Inverse = UART_CTS_INV,
+ UART_Txd_Inverse = UART_TXD_INV,
+ UART_RTS_Inverse = UART_RTS_INV,
+} UART_LineLevelInverse;
+
+
+typedef enum {
+ BIT_RATE_300 = 300,
+ BIT_RATE_600 = 600,
+ BIT_RATE_1200 = 1200,
+ BIT_RATE_2400 = 2400,
+ BIT_RATE_4800 = 4800,
+ BIT_RATE_9600 = 9600,
+ BIT_RATE_19200 = 19200,
+ BIT_RATE_38400 = 38400,
+ BIT_RATE_57600 = 57600,
+ BIT_RATE_74880 = 74880,
+ BIT_RATE_115200 = 115200,
+ BIT_RATE_230400 = 230400,
+ BIT_RATE_460800 = 460800,
+ BIT_RATE_921600 = 921600,
+ BIT_RATE_1843200 = 1843200,
+ BIT_RATE_3686400 = 3686400,
+} UartBautRate;
+
+
+typedef enum {
+ NONE_CTRL,
+ HARDWARE_CTRL,
+ XON_XOFF_CTRL
+} UartFlowCtrl;
+
+
+typedef enum {
+ USART_HWFlow_None = 0x0,
+ USART_HWFlow_RTS = 0x1,
+ USART_HWFlow_CTS = 0x2,
+ USART_HWFlow_CTS_RTS = 0x3
+} UART_HwFlowCtrl;
+
+
+typedef enum {
+ EMPTY,
+ UNDER_WRITE,
+ WRITE_OVER
+} RcvMsgBuffState;
+
+
+typedef struct {
+ uint32 RcvBuffSize;
+ uint8 *pRcvMsgBuff;
+ uint8 *pWritePos;
+ uint8 *pReadPos;
+ uint8 TrigLvl; //JLU: may need to pad
+ RcvMsgBuffState BuffState;
+} RcvMsgBuff;
+
+
+typedef struct {
+ uint32 TrxBuffSize;
+ uint8 *pTrxBuff;
+} TrxMsgBuff;
+
+
+typedef enum {
+ BAUD_RATE_DET,
+ WAIT_SYNC_FRM,
+ SRCH_MSG_HEAD,
+ RCV_MSG_BODY,
+ RCV_ESC_CHAR,
+} RcvMsgState;
+
+
+typedef struct {
+ UartBautRate baut_rate;
+ UartBitsNum4Char data_bits;
+ UartExistParity exist_parity;
+ UartParityMode parity;
+ UartStopBitsNum stop_bits;
+ UartFlowCtrl flow_ctrl;
+ RcvMsgBuff rcv_buff;
+ TrxMsgBuff trx_buff;
+ RcvMsgState rcv_state;
+ int received;
+ int buff_uart_no; //indicate which uart use tx/rx buffer
+} UartDevice;
+
+// UartDev is defined and initialized in rom code.
+extern UartDevice UartDev;
+
+
+//==============================================
+
+// FIFO used count
+#define UART_TxQueLen(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT)
+#define UART_RxQueLen(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT)
+
+STATUS UART_WriteCharCRLF(UARTn uart_no, uint8 c, uint32 timeout_us);
+STATUS UART_WriteChar(UARTn uart_no, uint8 c, uint32 timeout_us);
+STATUS UART_WriteString(UARTn uart_no, const char *str, uint32 timeout_us);
+STATUS UART_WriteBuffer(UARTn uart_no, const uint8 *buffer, size_t len, uint32 timeout_us);
+
+//==============================================
+
+void UART_SetWordLength(UARTn uart_no, UartBitsNum4Char len);
+void UART_SetStopBits(UARTn uart_no, UartStopBitsNum bit_num);
+void UART_SetLineInverse(UARTn uart_no, UART_LineLevelInverse inverse_mask);
+void UART_SetParity(UARTn uart_no, UartParityMode Parity_mode);
+void UART_SetBaudrate(UARTn uart_no, uint32 baud_rate);
+void UART_SetFlowCtrl(UARTn uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh);
+void UART_WaitTxFifoEmpty(UARTn uart_no , uint32 time_out_us); //do not use if tx flow control enabled
+void UART_ResetFifo(UARTn uart_no);
+void UART_ClearIntrStatus(UARTn uart_no, uint32 clr_mask);
+void UART_SetIntrEna(UARTn uart_no, uint32 ena_mask);
+void UART_SetPrintPort(UARTn uart_no);
+bool UART_CheckOutputFinished(UARTn uart_no, uint32 time_out_us);
+
+//==============================================
+
+#endif
+
diff --git a/user/uart_handler.c b/user/uart_handler.c
new file mode 100755
index 0000000..4c2625f
--- /dev/null
+++ b/user/uart_handler.c
@@ -0,0 +1,185 @@
+//Stupid bit of code that does the bare minimum to make os_printf work.
+
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * Jeroen Domburg wrote this file. As long as you retain
+ * this notice you can do whatever you want with this stuff. If we meet some day,
+ * and you think this stuff is worth it, you can buy me a beer in return.
+ * ----------------------------------------------------------------------------
+ */
+
+#include
+#include "uart_driver.h"
+#include "uart_handler.h"
+
+// messy irq/task based UART handling below
+
+static void uart0_rx_intr_handler(void *para);
+static void uart_recvTask(os_event_t *events);
+
+#define uart_recvTaskPrio 1
+#define uart_recvTaskQueueLen 10
+static os_event_t uart_recvTaskQueue[uart_recvTaskQueueLen];
+
+/** Clear the fifos */
+void ICACHE_FLASH_ATTR clear_rxtx(int uart_no)
+{
+ SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
+ CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
+}
+
+
+/**
+ * @brief Configure UART 115200-8-N-1
+ * @param uart_no
+ */
+static void ICACHE_FLASH_ATTR my_uart_init(UARTn uart_no, uint32 baud)
+{
+ UART_SetParity(uart_no, PARITY_NONE);
+ UART_SetStopBits(uart_no, ONE_STOP_BIT);
+ UART_SetWordLength(uart_no, EIGHT_BITS);
+ UART_SetBaudrate(uart_no, baud);
+ UART_ResetFifo(uart_no);
+}
+
+
+/** Configure basic UART func and pins */
+void ICACHE_FLASH_ATTR UART_Init(uint32_t baud0, uint32_t baud1)
+{
+ // U0TXD
+ PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
+ PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
+
+ // U0RXD
+ PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
+
+ // U1TXD (GPIO2)
+ PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
+
+ // Configure the UART peripherals
+ my_uart_init(UART0, baud0); // main
+ my_uart_init(UART1, baud1); // debug (output only)
+}
+
+/** Configure Rx on UART0 */
+void ICACHE_FLASH_ATTR UART_SetupAsyncReceiver(void)
+{
+ // Start the Rx reading task
+ system_os_task(uart_recvTask, uart_recvTaskPrio, uart_recvTaskQueue, uart_recvTaskQueueLen);
+ // set handler
+ ETS_UART_INTR_ATTACH((void *)uart0_rx_intr_handler, &(UartDev.rcv_buff)); // the buf will be used as an arg
+
+ // fifo threshold config
+ uint32_t conf = ((100 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S);
+ conf |= ((0x10 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S);
+ // timeout config
+ conf |= ((0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S); // timeout threshold
+ conf |= UART_RX_TOUT_EN; // enable timeout
+ WRITE_PERI_REG(UART_CONF1(UART0), conf);
+
+ // enable TOUT and ERR irqs
+ SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA);
+ /* clear interrupt flags */
+ WRITE_PERI_REG(UART_INT_CLR(UART0), 0xffff);
+ /* enable RX interrupts */
+ SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_OVF_INT_ENA);
+
+ // Enable IRQ in Extensa
+ ETS_UART_INTR_ENABLE();
+}
+
+
+// ---- async receive stuff ----
+
+
+void uart_rx_intr_disable(uint8 uart_no)
+{
+ CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
+}
+
+
+void uart_rx_intr_enable(uint8 uart_no)
+{
+ SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
+}
+
+
+/**
+ * @brief get number of bytes in UART tx fifo
+ * @param UART number
+ */
+#define UART_GetRxFifoCount(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT)
+
+
+void ICACHE_FLASH_ATTR UART_PollRx(void)
+{
+ uint8 fifo_len = UART_GetRxFifoCount(UART0);
+
+ for (uint8 idx = 0; idx < fifo_len; idx++) {
+ uint8 d_tmp = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
+ UART_HandleRxByte(d_tmp);
+ }
+}
+
+
+static void ICACHE_FLASH_ATTR uart_recvTask(os_event_t *events)
+{
+ if (events->sig == 0) {
+ UART_PollRx();
+
+ // clear irq flags
+ WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR | UART_RXFIFO_TOUT_INT_CLR);
+ // enable rx irq again
+ uart_rx_intr_enable(UART0);
+ } else if (events->sig == 1) {
+ // ???
+ }
+}
+
+
+/******************************************************************************
+ * FunctionName : uart0_rx_intr_handler
+ * Description : Internal used function
+ * UART0 interrupt handler, add self handle code inside
+ * Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg
+ * Returns : NONE
+*******************************************************************************/
+static void
+uart0_rx_intr_handler(void *para)
+{
+ (void)para;
+
+ uint32_t status_reg = READ_PERI_REG(UART_INT_ST(UART0));
+
+ if (status_reg & UART_FRM_ERR_INT_ST) {
+ // Framing Error
+ WRITE_PERI_REG(UART_INT_CLR(UART0), UART_FRM_ERR_INT_CLR);
+ }
+
+ if (status_reg & UART_RXFIFO_FULL_INT_ST) {
+ // RX fifo full
+ uart_rx_intr_disable(UART0);
+ WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
+
+ // run handler
+ system_os_post(uart_recvTaskPrio, 0, 0); /* -> notify the polling thread */
+ }
+
+ if (status_reg & UART_RXFIFO_TOUT_INT_ST) {
+ // Fifo timeout
+ uart_rx_intr_disable(UART0);
+ WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
+
+ // run handler
+ system_os_post(uart_recvTaskPrio, 0, 0); /* -> notify the polling thread */
+ }
+
+ if (status_reg & UART_TXFIFO_EMPTY_INT_ST) {
+ CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
+ }
+
+ if (status_reg & UART_RXFIFO_OVF_INT_ST) {
+ WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_OVF_INT_CLR);
+ }
+}
diff --git a/user/uart_handler.h b/user/uart_handler.h
new file mode 100755
index 0000000..de293d5
--- /dev/null
+++ b/user/uart_handler.h
@@ -0,0 +1,27 @@
+/**
+ * UART init & async rx module.
+ *
+ * Call UART_Init(), UART_SetupAsyncReceiver() and
+ * define UART_HandleRxByte() somewhere in application code.
+ *
+ * Call UART_PollRx() to allow rx in a blocking handler.
+ */
+
+#ifndef UART_HANDLER_H
+#define UART_HANDLER_H
+
+#include
+
+/** Configure basic UART func and pins */
+void UART_Init(uint32_t baud0, uint32_t baud1);
+
+/** Configure Rx on UART0 */
+void UART_SetupAsyncReceiver(void);
+
+/** User must provide this func for handling received bytes */
+extern void UART_HandleRxByte(char c);
+
+/** poll uart while waiting for something */
+void UART_PollRx(void);
+
+#endif
diff --git a/user/user_main.c b/user/user_main.c
index fb655c2..56c6022 100644
--- a/user/user_main.c
+++ b/user/user_main.c
@@ -7,84 +7,26 @@
* ----------------------------------------------------------------------------
*/
-/*
-This is example code for the esphttpd library. It's a small-ish demo showing off
-the server, including WiFi connection management capabilities, some IO and
-some pictures of cats.
-*/
+/**
+ * This is the ESP8266 Remote Terminal project main file.
+ */
#include
-#include "httpd.h"
+#include
+#include
+#include
+#include
+#include
+#include "serial.h"
#include "io.h"
-#include "httpdespfs.h"
-#include "cgi.h"
-#include "cgiwifi.h"
-#include "cgiflash.h"
-#include "stdout.h"
-#include "auth.h"
-#include "espfs.h"
-#include "captdns.h"
-#include "webpages-espfs.h"
-#include "cgiwebsocket.h"
-#include "cgi-test.h"
-
-//The example can print out the heap use every 3 seconds. You can use this to catch memory leaks.
-//#define SHOW_HEAP_USE
-
-//Function that tells the authentication system what users/passwords live on the system.
-//This is disabled in the default build; if you want to try it, enable the authBasic line in
-//the builtInUrls below.
-int myPassFn(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen) {
- if (no==0) {
- os_strcpy(user, "admin");
- os_strcpy(pass, "s3cr3t");
- return 1;
-//Add more users this way. Check against incrementing no for each user added.
-// } else if (no==1) {
-// os_strcpy(user, "user1");
-// os_strcpy(pass, "something");
-// return 1;
- }
- return 0;
-}
-static ETSTimer websockTimer;
+#define FIRMWARE_VERSION "0.1"
-//Broadcast the uptime in seconds every second over connected websockets
-static void ICACHE_FLASH_ATTR websockTimerCb(void *arg) {
- static int ctr=0;
- char buff[128];
- ctr++;
- os_sprintf(buff, "Up for %d minutes %d seconds!\n", ctr/60, ctr%60);
- cgiWebsockBroadcast("/websocket/ws.cgi", buff, os_strlen(buff), WEBSOCK_FLAG_NONE);
-}
+#define SHOW_HEAP_USE 1
-//On reception of a message, send "You sent: " plus whatever the other side sent
-void myWebsocketRecv(Websock *ws, char *data, int len, int flags) {
- int i;
- char buff[128];
- os_sprintf(buff, "You sent: ");
- for (i=0; irecvCb=myWebsocketRecv;
- cgiWebsocketSend(ws, "Hi, Websocket!", 14, WEBSOCK_FLAG_NONE);
-}
-
-//On reception of a message, echo it back verbatim
-void myEchoWebsocketRecv(Websock *ws, char *data, int len, int flags) {
- os_printf("EchoWs: echo, len=%d\n", len);
- cgiWebsocketSend(ws, data, len, flags);
-}
-
-//Echo websocket connected. Install reception handler.
-void myEchoWebsocketConnect(Websock *ws) {
- os_printf("EchoWs: connect\n");
- ws->recvCb=myEchoWebsocketRecv;
+ // NOOP
}
@@ -108,47 +50,14 @@ CgiUploadFlashDef uploadParams={
#define INCLUDE_FLASH_FNS
#endif
-/*
-This is the main url->function dispatching data struct.
-In short, it's a struct with various URLs plus their handlers. The handlers can
-be 'standard' CGI functions you wrote, or 'special' CGIs requiring an argument.
-They can also be auth-functions. An asterisk will match any url starting with
-everything before the asterisks; "*" matches everything. The list will be
-handled top-down, so make sure to put more specific rules above the more
-general ones. Authorization things (like authBasic) act as a 'barrier' and
-should be placed above the URLs they protect.
-*/
+/** Routes */
HttpdBuiltInUrl builtInUrls[]={
- ROUTE_CGI_ARG("*", cgiRedirectApClientToHostname, "esp8266.nonet"), // redirect func for the captive portal
- ROUTE_REDIRECT("/", "/index.tpl"),
- ROUTE_TPL("/led.tpl", tplLed),
- ROUTE_TPL("/index.tpl", tplCounter),
- ROUTE_CGI("/led.cgi", cgiLed),
-#ifdef INCLUDE_FLASH_FNS
- ROUTE_CGI_ARG("/flash/next", cgiGetFirmwareNext, &uploadParams),
- ROUTE_CGI_ARG("/flash/upload", cgiUploadFirmware, &uploadParams),
-#endif
- ROUTE_CGI("/flash/reboot", cgiRebootFirmware),
-
- //Routines to make the /wifi URL and everything beneath it work.
-
-//Enable the line below to protect the WiFi configuration with an username/password combo.
-// ROUTE_AUTH("/wifi/*", myPassFn),
-
- ROUTE_REDIRECT("/wifi", "/wifi/wifi.tpl"),
- ROUTE_REDIRECT("/wifi/", "/wifi/wifi.tpl"),
- ROUTE_CGI("/wifi/wifiscan.cgi", cgiWiFiScan),
- ROUTE_TPL("/wifi/wifi.tpl", tplWlan),
- ROUTE_CGI("/wifi/connect.cgi", cgiWiFiConnect),
- ROUTE_CGI("/wifi/connstatus.cgi", cgiWiFiConnStatus),
- ROUTE_CGI("/wifi/setmode.cgi", cgiWiFiSetMode),
+ // redirect func for the captive portal
+ ROUTE_CGI_ARG("*", cgiRedirectApClientToHostname, "esp8266.nonet"),
- ROUTE_WS("/websocket/ws.cgi", myWebsocketConnect),
- ROUTE_WS("/websocket/echo.cgi", myEchoWebsocketConnect),
+ ROUTE_WS("/ws/update.cgi", myWebsocketConnect),
- ROUTE_REDIRECT("/test", "/test/index.html"),
- ROUTE_REDIRECT("/test/", "/test/index.html"),
- ROUTE_CGI("/test/test.cgi", cgiTestbed),
+ // TODO add funcs for WiFi management (when web UI is added)
ROUTE_FILESYSTEM(),
ROUTE_END(),
@@ -159,15 +68,28 @@ HttpdBuiltInUrl builtInUrls[]={
static ETSTimer prHeapTimer;
static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg) {
+ static int led = 0;
os_printf("Heap: %ld\n", (unsigned long)system_get_free_heap_size());
+
+ cgiWebsockBroadcast("/ws/update.cgi", "HELLO", 5, WEBSOCK_FLAG_NONE);
+
+ ioLed(led);
+ led = !led;
}
#endif
//Main routine. Initialize stdout, the I/O, filesystem and the webserver and we're done.
void user_init(void) {
- stdoutInit();
- ioInit();
+ serialInit();
+
+ banner("ESP8266 Remote Terminal");
+ banner_info("Version "FIRMWARE_VERSION", built "__DATE__" at "__TIME__);
+ dbg("!!! TODO (c) and GitHub link here !!!");
+
+ //stdoutInit();
+
captdnsInit();
+ ioInit();
// 0x40200000 is the base address for spi flash memory mapping, ESPFS_POS is the position
// where image is written in flash that is defined in Makefile.
@@ -176,18 +98,30 @@ void user_init(void) {
#else
espFsInit((void*)(webpages_espfs_start));
#endif
+
httpdInit(builtInUrls, 80);
+
#ifdef SHOW_HEAP_USE
os_timer_disarm(&prHeapTimer);
os_timer_setfn(&prHeapTimer, prHeapTimerCb, NULL);
os_timer_arm(&prHeapTimer, 3000, 1);
#endif
- os_timer_disarm(&websockTimer);
- os_timer_setfn(&websockTimer, websockTimerCb, NULL);
- os_timer_arm(&websockTimer, 1000, 1);
- os_printf("\nReady\n");
+
+ info("System ready!");
}
+// ---- unused funcs removed from sdk to save space ---
+
void user_rf_pre_init() {
//Not needed, but some SDK versions want this defined.
}
+
+// вызывается из phy_chip_v6.o
+void ICACHE_FLASH_ATTR chip_v6_set_sense(void) {
+ // ret.n
+}
+
+// вызывается из phy_chip_v6.o
+int ICACHE_FLASH_ATTR chip_v6_unset_chanfreq(void) {
+ return 0;
+}
\ No newline at end of file