refactor pin config, add support for rx pull-up

v2.1
Thorsten von Eicken 9 years ago
parent f0997b13ea
commit e0040e74bc
  1. 23
      esp-link/cgi.c
  2. 4
      esp-link/cgi.h
  3. 112
      esp-link/cgipins.c
  4. 3
      esp-link/config.c
  5. 5
      esp-link/config.h
  6. 5
      esp-link/main.c
  7. 133
      html/home.html
  8. 79
      html/style.css
  9. 123
      html/ui.js
  10. 8
      html/wifi/wifi.html
  11. 6
      serial/serbridge.c
  12. 4
      serial/uart.c

@ -59,6 +59,23 @@ getStringArg(HttpdConnData *connData, char *name, char *config, int max_len) {
return 1; return 1;
} }
// look for the HTTP arg 'name' and store it at 'config' as an 8-bit integer
// returns -1 on error, 0 if not found, 1 if found and OK
int8_t ICACHE_FLASH_ATTR
getInt8Arg(HttpdConnData *connData, char *name, int8_t *config) {
char buff[16];
int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff));
if (len < 0) return 0; // not found, skip
int m = atoi(buff);
if (len >= 6 || m < -128 || m > 255) {
os_sprintf(buff, "Value for %s out of range", name);
errorResponse(connData, 400, buff);
return -1;
}
*config = m;
return 1;
}
int8_t ICACHE_FLASH_ATTR int8_t ICACHE_FLASH_ATTR
getBoolArg(HttpdConnData *connData, char *name, bool*config) { getBoolArg(HttpdConnData *connData, char *name, bool*config) {
char buff[64]; char buff[64];
@ -150,6 +167,10 @@ int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) {
httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate"); httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate");
httpdHeader(connData, "Content-Type", "application/json"); httpdHeader(connData, "Content-Type", "application/json");
httpdEndHeaders(connData); httpdEndHeaders(connData);
// limit hostname to 12 chars
char name[13];
os_strncpy(name, flashConfig.hostname, 12);
name[12] = 0;
// construct json response // construct json response
os_sprintf(buff, os_sprintf(buff,
"{\"menu\": [\"Home\", \"/home.html\", " "{\"menu\": [\"Home\", \"/home.html\", "
@ -160,7 +181,7 @@ int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) {
#endif #endif
"\"Debug log\", \"/log.html\" ],\n" "\"Debug log\", \"/log.html\" ],\n"
" \"version\": \"%s\"," " \"version\": \"%s\","
"\"name\":\"%s\"}", esp_link_version, flashConfig.sys_name); "\"name\":\"%s\"}", esp_link_version, name);
httpdSend(connData, buff, -1); httpdSend(connData, buff, -1);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }

@ -12,6 +12,10 @@ void errorResponse(HttpdConnData *connData, int code, char *message);
// 'max_len' (incl terminating zero), returns -1 on error, 0 if not found, 1 if found // 'max_len' (incl terminating zero), returns -1 on error, 0 if not found, 1 if found
int8_t getStringArg(HttpdConnData *connData, char *name, char *config, int max_len); int8_t getStringArg(HttpdConnData *connData, char *name, char *config, int max_len);
// Get the HTTP query-string param 'name' and store it as a int8 value at 'config',
// supports signed and unsigned, returns -1 on error, 0 if not found, 1 if found
int8_t getInt8Arg(HttpdConnData *connData, char *name, int8_t *config);
// Get the HTTP query-string param 'name' and store it boolean value at 'config', // Get the HTTP query-string param 'name' and store it boolean value at 'config',
// supports 1/true and 0/false, returns -1 on error, 0 if not found, 1 if found // supports 1/true and 0/false, returns -1 on error, 0 if not found, 1 if found
int8_t getBoolArg(HttpdConnData *connData, char *name, bool*config); int8_t getBoolArg(HttpdConnData *connData, char *name, bool*config);

@ -7,6 +7,7 @@
#include "status.h" #include "status.h"
#include "serbridge.h" #include "serbridge.h"
#if 0
static char *map_names[] = { static char *map_names[] = {
"esp-bridge", "jn-esp-v2", "esp-01(AVR)", "esp-01(ARM)", "esp-br-rev", "wifi-link-12", "esp-bridge", "jn-esp-v2", "esp-01(AVR)", "esp-01(ARM)", "esp-br-rev", "wifi-link-12",
}; };
@ -21,46 +22,19 @@ static int8_t map_asn[][5] = {
}; };
static const int num_map_names = sizeof(map_names)/sizeof(char*); static const int num_map_names = sizeof(map_names)/sizeof(char*);
static const int num_map_func = sizeof(map_func)/sizeof(char*); static const int num_map_func = sizeof(map_func)/sizeof(char*);
#endif
// Cgi to return choice of pin assignments // Cgi to return choice of pin assignments
int ICACHE_FLASH_ATTR cgiPinsGet(HttpdConnData *connData) { int ICACHE_FLASH_ATTR cgiPinsGet(HttpdConnData *connData) {
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted
char buff[2048]; char buff[1024];
int len; int len;
// figure out current mapping len = os_sprintf(buff,
int curr = 0; "{ \"reset\":%d, \"isp\":%d, \"conn\":%d, \"ser\":%d, \"swap\":%d, \"rxpup\":%d }",
for (int i=0; i<num_map_names; i++) { flashConfig.reset_pin, flashConfig.isp_pin, flashConfig.conn_led_pin,
int8_t *map = map_asn[i]; flashConfig.ser_led_pin, !!flashConfig.swap_uart, 1);
if (map[0] == flashConfig.reset_pin && map[1] == flashConfig.isp_pin &&
map[2] == flashConfig.conn_led_pin && map[3] == flashConfig.ser_led_pin &&
map[4] == flashConfig.swap_uart) {
curr = i;
}
}
// print mapping
len = os_sprintf(buff, "{ \"curr\":\"%s\", \"map\": [ ", map_names[curr]);
for (int i=0; i<num_map_names; i++) {
if (i != 0) buff[len++] = ',';
len += os_sprintf(buff+len, "\n{ \"value\":%d, \"name\":\"%s\"", i, map_names[i]);
for (int f=0; f<num_map_func; f++) {
len += os_sprintf(buff+len, ", \"%s\":%d", map_func[f], map_asn[i][f]);
}
len += os_sprintf(buff+len, ", \"descr\":\"");
for (int f=0; f<num_map_func; f++) {
int8_t p = map_asn[i][f];
if (f == 4)
len += os_sprintf(buff+len, " %s:%s", map_func[f], p?"yes":"no");
else if (p >= 0)
len += os_sprintf(buff+len, " %s:gpio%d", map_func[f], p);
else
len += os_sprintf(buff+len, " %s:n/a", map_func[f]);
}
len += os_sprintf(buff+len, "\" }");
}
len += os_sprintf(buff+len, "\n] }");
jsonHeader(connData, 200); jsonHeader(connData, 200);
httpdSend(connData, buff, len); httpdSend(connData, buff, len);
@ -73,41 +47,73 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) {
return HTTPD_CGI_DONE; // Connection aborted return HTTPD_CGI_DONE; // Connection aborted
} }
char buff[128]; int8_t ok = 0;
int len = httpdFindArg(connData->getArgs, "map", buff, sizeof(buff)); int8_t reset, isp, conn, ser;
if (len <= 0) { bool swap, rxpup;
jsonHeader(connData, 400); ok |= getInt8Arg(connData, "reset", &reset);
return HTTPD_CGI_DONE; ok |= getInt8Arg(connData, "isp", &isp);
} ok |= getInt8Arg(connData, "conn", &conn);
ok |= getInt8Arg(connData, "ser", &ser);
ok |= getBoolArg(connData, "swap", &swap);
ok |= getBoolArg(connData, "rxpup", &rxpup);
if (ok < 0) return HTTPD_CGI_DONE;
int m = atoi(buff); char *coll;
if (m < 0 || m >= num_map_names) { if (ok > 0) {
jsonHeader(connData, 400); // check whether two pins collide
return HTTPD_CGI_DONE; uint16_t pins = 0;
if (reset >= 0) pins = 1 << reset;
if (isp >= 0) {
if (pins & (1<<isp)) { coll = "ISP/Flash"; goto collision; }
pins |= 1 << isp;
} }
#ifdef CGIPINS_DBG if (conn >= 0) {
os_printf("Switching pin map to %s (%d)\n", map_names[m], m); if (pins & (1<<conn)) { coll = "Conn LED"; goto collision; }
#endif pins |= 1 << conn;
int8_t *map = map_asn[m]; }
flashConfig.reset_pin = map[0]; if (ser >= 0) {
flashConfig.isp_pin = map[1]; if (pins & (1<<ser)) { coll = "Serial LED"; goto collision; }
flashConfig.conn_led_pin = map[2]; pins |= 1 << ser;
flashConfig.ser_led_pin = map[3]; }
flashConfig.swap_uart = map[4]; if (swap) {
if (pins & (1<<1)) { coll = "Uart TX"; goto collision; }
if (pins & (1<<3)) { coll = "Uart RX"; goto collision; }
} else {
if (pins & (1<<15)) { coll = "Uart TX"; goto collision; }
if (pins & (1<<13)) { coll = "Uart RX"; goto collision; }
}
// we're good, set flashconfig
flashConfig.reset_pin = reset;
flashConfig.isp_pin = isp;
flashConfig.conn_led_pin = conn;
flashConfig.ser_led_pin = ser;
flashConfig.swap_uart = swap;
flashConfig.rx_pullup = rxpup;
// apply the changes
serbridgeInitPins(); serbridgeInitPins();
serledInit(); serledInit();
statusInit(); statusInit();
// save to flash
if (configSave()) { if (configSave()) {
httpdStartResponse(connData, 200); httpdStartResponse(connData, 204);
httpdEndHeaders(connData); httpdEndHeaders(connData);
} else { } else {
httpdStartResponse(connData, 500); httpdStartResponse(connData, 500);
httpdEndHeaders(connData); httpdEndHeaders(connData);
httpdSend(connData, "Failed to save config", -1); httpdSend(connData, "Failed to save config", -1);
} }
}
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
collision: {
char buff[128];
os_sprintf(buff, "Pin assignment for %s collides with another assignment", coll);
errorResponse(connData, 400, buff);
return HTTPD_CGI_DONE;
}
} }
int ICACHE_FLASH_ATTR cgiPins(HttpdConnData *connData) { int ICACHE_FLASH_ATTR cgiPins(HttpdConnData *connData) {

@ -22,7 +22,8 @@ FlashConfig flashDefault = {
2, 1, // mqtt_timeout, mqtt_clean_session 2, 1, // mqtt_timeout, mqtt_clean_session
1883, 60, // mqtt port, mqtt_keepalive 1883, 60, // mqtt port, mqtt_keepalive
"\0", "\0", "\0", "\0", "\0", // mqtt host, client_id, user, password, status-topic "\0", "\0", "\0", "\0", "\0", // mqtt host, client_id, user, password, status-topic
"\0", "\0", // sys name, sys description "\0", // system description
1, // rx_pullup
}; };
typedef union { typedef union {

@ -13,7 +13,7 @@ typedef struct {
char hostname[32]; // if using DHCP char hostname[32]; // if using DHCP
uint32_t staticip, netmask, gateway; // using DHCP if staticip==0 uint32_t staticip, netmask, gateway; // using DHCP if staticip==0
uint8_t log_mode; // UART log debug mode uint8_t log_mode; // UART log debug mode
uint8_t swap_uart; // swap uart0 to gpio 13&15 int8_t swap_uart; // swap uart0 to gpio 13&15
uint8_t tcp_enable, rssi_enable; // TCP client settings uint8_t tcp_enable, rssi_enable; // TCP client settings
char api_key[48]; // RSSI submission API key (Grovestreams for now) char api_key[48]; // RSSI submission API key (Grovestreams for now)
uint8_t slip_enable, mqtt_enable, // SLIP protocol, MQTT client uint8_t slip_enable, mqtt_enable, // SLIP protocol, MQTT client
@ -23,7 +23,8 @@ typedef struct {
uint16_t mqtt_port, mqtt_keepalive; // MQTT Host port, MQTT Keepalive timer uint16_t mqtt_port, mqtt_keepalive; // MQTT Host port, MQTT Keepalive timer
char mqtt_host[32], mqtt_clientid[48], mqtt_username[32], mqtt_password[32]; char mqtt_host[32], mqtt_clientid[48], mqtt_username[32], mqtt_password[32];
char mqtt_status_topic[32]; char mqtt_status_topic[32];
char sys_name[13], sys_descr[129]; // informal system name and description char sys_descr[129]; // system description
int8_t rx_pullup; // internal pull-up on RX pin
} FlashConfig; } FlashConfig;
extern FlashConfig flashConfig; extern FlashConfig flashConfig;

@ -116,7 +116,7 @@ static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData) {
"\"size\": \"%s\"," "\"id\": \"0x%02lX 0x%04lX\"," "\"partition\": \"%s\"," "\"size\": \"%s\"," "\"id\": \"0x%02lX 0x%04lX\"," "\"partition\": \"%s\","
"\"slip\": \"%s\"," "\"mqtt\": \"%s/%s\"," "\"baud\": \"%ld\"," "\"slip\": \"%s\"," "\"mqtt\": \"%s/%s\"," "\"baud\": \"%ld\","
"\"description\": \"%s\"" "}", "\"description\": \"%s\"" "}",
flashConfig.sys_name, rst_info->reason, rst_codes[rst_info->reason], flashConfig.hostname, rst_info->reason, rst_codes[rst_info->reason],
flash_maps[system_get_flash_size_map()], fid & 0xff, (fid&0xff00)|((fid>>16)&0xff), flash_maps[system_get_flash_size_map()], fid & 0xff, (fid&0xff00)|((fid>>16)&0xff),
part_id ? "user2.bin" : "user1.bin", part_id ? "user2.bin" : "user1.bin",
flashConfig.slip_enable ? "enabled" : "disabled", flashConfig.slip_enable ? "enabled" : "disabled",
@ -134,7 +134,7 @@ static int ICACHE_FLASH_ATTR cgiSystemSet(HttpdConnData *connData) {
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
int8_t status = 0; int8_t status = 0;
status |= getStringArg(connData, "name", flashConfig.sys_name, sizeof(flashConfig.sys_name)); status |= getStringArg(connData, "name", flashConfig.hostname, sizeof(flashConfig.hostname));
status |= getStringArg(connData, "description", flashConfig.sys_descr, sizeof(flashConfig.sys_descr)); status |= getStringArg(connData, "description", flashConfig.sys_descr, sizeof(flashConfig.sys_descr));
if (status < 0) return HTTPD_CGI_DONE; // getStringArg has produced an error response if (status < 0) return HTTPD_CGI_DONE; // getStringArg has produced an error response
@ -172,7 +172,6 @@ void user_init(void) {
os_delay_us(10000L); os_delay_us(10000L);
os_printf("\n\n** %s\n", esp_link_version); os_printf("\n\n** %s\n", esp_link_version);
os_printf("Flash config restore %s\n", restoreOk ? "ok" : "*FAILED*"); os_printf("Flash config restore %s\n", restoreOk ? "ok" : "*FAILED*");
if (flashConfig.sys_name[0] == 0) os_strcpy(flashConfig.sys_name, "name-me");
#if defined(STA_SSID) && defined(STA_PASS) #if defined(STA_SSID) && defined(STA_PASS)
int x = wifi_get_opmode() & 0x3; int x = wifi_get_opmode() & 0x3;

@ -7,65 +7,132 @@
<div class="content"> <div class="content">
<div class="pure-g"> <div class="pure-g">
<div class="pure-u-1"><div class="card"> <!-- LEFT COLUMN -->
<div class="pure-u-1 pure-u-md-1-2">
<div class="card">
<h1>System overview</h1>
<div id="wifi-spinner" class="spinner spinner-small"></div>
<table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody>
<tr><td class="popup-target">Hostname</td><td>
<div class="click-to-edit system-name">
<span class="edit-off"></span>
<input class="edit-on" maxlength=31 hidden></input>
<div class="popup">Hostname displayed in menu bar
and used by DHCP and mDNS</div>
</div>
</td></tr>
<tr><td>Network SSID</td><td id="wifi-ssid"></td></tr>
<tr><td>Wifi status</td><td id="wifi-status"></td></tr>
<tr><td>Wifi address</td><td id="wifi-ip"></td></tr>
<tr><td>SLIP status</td><td class="system-slip"></td></tr>
<tr><td>MQTT status</td><td class="system-mqtt"></td></tr>
<tr><td>Serial baud</td><td class="system-baud"></td></tr>
</tbody></table>
</div>
<div class="card">
<h1>Info</h1>
<p style="margin-bottom:0;">The JeeLabs esp-link firmware bridges the ESP8266 <p style="margin-bottom:0;">The JeeLabs esp-link firmware bridges the ESP8266
serial port to Wifi and can serial port to Wifi and can
program microcontrollers over the serial port, in particular Arduinos, AVRs, and program microcontrollers over the serial port, in particular Arduinos, AVRs, and
NXP's LPC800 and other ARM processors. Typical avrdude command line to NXP's LPC800 and other ARM processors. Typical avrdude command line to
program an Arduino:</p> program an Arduino:</p>
<div class="tt">/home/arduino/hardware/tools/avrdude \<br> <div class="tt">/home/arduino/hardware/tools/avrdude&nbsp;\<br>
&nbsp;&nbsp;-DV -patmega328p -Pnet:esp-link.local:23 -carduino -b115200 -U \<br> &nbsp;&nbsp;-DV -patmega328p \<br>
&nbsp;&nbsp;-C /home/arduino/hardware/tools/avrdude.conf flash:w:my_sketch.hex:i &nbsp;&nbsp;-Pnet:esp-link.local:23 \<br>
&nbsp;&nbsp;-carduino -b115200 -U \<br>
&nbsp;&nbsp;-C /home/arduino/hardware/tools/avrdude.conf&nbsp;\<br>
&nbsp;&nbsp;flash:w:my_sketch.hex:i
</div> </div>
<p>where <tt>-Pnet:esp-link.local:23</tt> tells avrdude to connect to port 23 of esp-link. <p>where <tt>-Pnet:esp-link.local:23</tt> tells avrdude to connect to port 23 of esp-link.
You can substitute the IP address of your esp-link for esp-link.local if necessary. You can substitute the IP address of your esp-link for esp-link.local if necessary.
Please refer to Please refer to
<a href="https://github.com/jeelabs/esp-link/blob/master/README.md">the online README</a> <a href="https://github.com/jeelabs/esp-link/blob/master/README.md">the online README</a>
for up-to-date help.</p> for up-to-date help.</p>
</div></div>
</div> </div>
<div class="pure-g"> </div>
<!-- RIGHT COLUMN -->
<div class="pure-u-1 pure-u-md-1-2"> <div class="pure-u-1 pure-u-md-1-2">
<div class="card"> <div class="card">
<h1>Wifi summary</h1> <h1>Pin assignment</h1>
<div id="wifi-spinner" class="spinner spinner-small"></div> <div id="pin-spinner" class="spinner spinner-small"></div>
<table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody> <div id="pin-table" hidden>
<tr><td>WiFi mode</td><td id="wifi-mode"></td></tr> <form action="#" id="pinform" class="pure-form pure-form-aligned form-narrow">
<tr><td>Configured network</td><td id="wifi-ssid"></td></tr> <div class="pure-control-group">
<tr><td>Wifi channel</td><td id="wifi-chan"></td></tr> <label for="pin-preset">Presets</label><select id="pin-preset" class="pure-button">
<tr><td>Wifi status</td><td id="wifi-status"></td></tr> <option value="" selected disabled></option>
<tr><td>Wifi address</td><td id="wifi-ip"></td></tr> </select></label>
<tr><td>Configured hostname</td><td id="wifi-hostname"></td></tr> </div>
</tbody></table> <hr>
<div class="pure-control-group">
<label for="pin-reset">Reset</label>
<select id="pin-reset"></select>
<div class="popup">Connect to uC reset pin for programming and reset-uC function</div>
</div>
<div class="pure-control-group">
<label for="pin-isp">ISP/Flash</label>
<select id="pin-isp"></select>
<div class="popup">Second signal to program uC.
AVR:not used, esp8266:gpio2, ARM:ISP</div>
</div>
<div class="pure-control-group">
<label for="pin-conn">Conn LED</label>
<select id="pin-conn"></select>
<div class="popup">LED to show wifi connectivity</div>
</div>
<div class="pure-control-group">
<label for="pin-ser">Serial LED</label>
<select id="pin-ser"></select>
<div class="popup">LED to show serial activity</div>
</div>
<div class="pure-control-group">
<label for="pin-swap">UART pins</label>
<select id="pin-swap" class="pure-button">
<option value="0">normal</option>
<option value="1">swapped</option>
</select>
<div class="popup">Swap UART0 pins to avoid ROM boot message.<br>Normal is
TX on gpio1/TX0 and RX on gpio3/RX0, swapped is TX on gpio15 and RX on gpio13.
</div>
</div>
<div class="pure-control-group">
<label for="pin-rxpup" class="pure-checkbox">RX pull-up</label>
<input id="pin-rxpup" type="checkbox">
<div class="popup">Enable internal 40K pull-up on RX</div>
</div>
<button id="set-pins" type="submit" class="pure-button button-primary">Change!</button>
</form>
</div>
</div> </div>
<div class="card"> <div class="card">
<h1>Esp-link summary</h1> <h1>System details</h1>
<div id="system-spinner" class="spinner spinner-small"></div> <div id="system-spinner" class="spinner spinner-small"></div>
<table id="system-table" class="pure-table pure-table-horizontal" hidden><tbody> <table id="system-table" class="pure-table pure-table-horizontal" hidden><tbody>
<tr><td>Flash chip ID</td><td class="system-id"></td></tr> <tr><td>WiFi mode</td><td id="wifi-mode"></td></tr>
<tr><td>Flash size</td><td class="system-size"></td></tr> <tr><td>Wifi channel</td><td id="wifi-chan"></td></tr>
<tr><td>Flash chip ID</td><td>
<div>
<span class="system-id"></span>
<div class="popup pop-left">Common IDs: 4016=4MB, 4014=1MB, 4013=512KB</div>
</div>
</td></tr>
<tr><td>Flash size</td><td>
<div>
<span class="system-size"></span>
<div class="popup pop-left">Size configured into bootloader, must match chip size</div>
</div>
</td></tr>
<tr><td>Current partition</td><td class="system-partition"></td></tr> <tr><td>Current partition</td><td class="system-partition"></td></tr>
<tr><td>SLIP status</td><td class="system-slip"></td></tr> <tr><td colspan=2 class="popup-target">Description:<br>
<tr><td>MQTT status</td><td class="system-mqtt"></td></tr>
<tr><td>Serial baud</td><td class="system-baud"></td></tr>
<tr><td colspan=2 >Description:<br>
<div class="click-to-edit system-description"> <div class="click-to-edit system-description">
<span class="edit-off"></span> <div class="edit-off"></div>
<textarea class="edit-on" rows=3 maxlength=127 hidden></textarea> <textarea class="edit-on" rows=3 maxlength=127 hidden></textarea>
<div class="edit-on popup" hidden>A short description or memo for this esp-link <div class="popup">A short description or memo for this esp-link
module, 128 chars max</div> module, 128 chars max</div>
</div> </div>
</td></tr> </td></tr>
</tbody></table> </tbody></table>
</div> </div>
</div> </div>
<div class="pure-u-1 pure-u-md-1-2"><div class="card">
<h1>Pin assignment</h1>
<legend>Select one of the following signal/pin assignments to match your hardware</legend>
<fieldset class='radios' id='pin-mux'>
<div class="spinner spinner-small"></div>
</fieldset>
</div></div>
</div> </div>
<div class="pure-g"> <div class="pure-g">
</div> </div>
@ -76,9 +143,11 @@
<script type="text/javascript"> <script type="text/javascript">
onLoad(function() { onLoad(function() {
makeAjaxInput("system", "description"); makeAjaxInput("system", "description");
makeAjaxInput("system", "name");
fetchPins(); fetchPins();
getWifiInfo(); getWifiInfo();
getSystemInfo(); getSystemInfo();
bnd($("#pinform"), "submit", setPins);
}); });
</script> </script>
</body></html> </body></html>

@ -42,16 +42,71 @@ a:hover {
background-color: #eee; background-color: #eee;
width: 100%; width: 100%;
} }
div.edit-on.popup { .click-to-edit span, .click-to-edit div {
/*background-color: #e0e0e0;*/
/*color: #1c0099;*/
padding: 0.3em;
width: 100%;
color: #444; /* rgba not supported (IE 8) */
color: rgba(0, 0, 0, 0.80); /* rgba supported */
border: 1px solid #999; /*IE 6/7/8*/
border: none rgba(0, 0, 0, 0); /*IE9 + everything else*/
background-color: #E6E6E6;
text-decoration: none;
border-radius: 2px;
}
.click-to-edit span:hover, .click-to-edit div:hover,
.click-to-edit span:focus, .click-to-edit div:focus {
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#1a000000',GradientType=0);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(transparent), color-stop(40%, rgba(0,0,0, 0.05)), to(rgba(0,0,0, 0.10)));
background-image: -webkit-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
background-image: -moz-linear-gradient(top, rgba(0,0,0, 0.05) 0%, rgba(0,0,0, 0.10));
background-image: -o-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
}
.click-to-edit span:focus, .click-to-edit div:focus {
outline: 0;
}
.click-to-edit span:active, .click-to-edit div:active {
box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset;
border-color: #000\9;
}
/* Firefox: Get rid of the inner focus border */
.click-to-edit span::-moz-focus-inner,
.click-to-edit div::-moz-focus-inner {
padding: 0;
border: 0;
}
/* pop-ups */
.popup-hidden {
display: none;
}
.popup, div.popup {
position: absolute; position: absolute;
top: 100%; /*top: 100%;*/
left: 20px; bottom: 100%;
background-color: cornsilk; background-color: #fff0b3;
border-radius: 5px;
border: 0px solid #000;
color: #333; color: #333;
font-size: 80%; font-size: 80%;
line-height: 110%; line-height: 110%;
z-index: 100; z-index: 100;
padding: 3px; padding: 5px;
min-width: 20em;
}
.popup:not(.pop-left) {
left: 20px;
}
.popup.pop-left {
right: 20px;
}
.popup-target:hover .popup {
display: block;
}
.popup-target {
position: relative;
} }
/* wifi AP selection form */ /* wifi AP selection form */
@ -81,6 +136,16 @@ fieldset fields {
padding: 0.5em 0.5em; padding: 0.5em 0.5em;
} }
/* Narrow left-aligned Forms */
.pure-form-aligned.form-narrow .pure-control-group label {
text-align: left;
width: 6em;
}
.pure-form-aligned.form-narrow input[type=checkbox],
.pure-form-aligned.form-narrow input[type=radio] {
float: none;
}
/* make images size-up */ /* make images size-up */
.xx-pure-img-responsive { .xx-pure-img-responsive {
max-width: 100%; max-width: 100%;
@ -172,6 +237,10 @@ select.pure-button {
padding: 0.465em 1em; padding: 0.465em 1em;
color: #009; /* same as a:link */ color: #009; /* same as a:link */
} }
.button-small {
font-size: 75%;
background: #ccc;
}
input.inline { input.inline {
float:none; float:none;

@ -213,6 +213,11 @@ function ajaxJsonSpin(method, url, ok_cb, err_cb) {
//===== main menu, header spinner and notification boxes //===== main menu, header spinner and notification boxes
function hidePopup(el) {
addClass(el, "popup-hidden");
addClass(el.parentNode, "popup-target");
}
onLoad(function() { onLoad(function() {
var l = $("#layout"); var l = $("#layout");
var o = l.childNodes[0]; var o = l.childNodes[0];
@ -229,11 +234,7 @@ onLoad(function() {
<div class="pure-menu">\ <div class="pure-menu">\
<a class="pure-menu-heading" href="https://github.com/jeelabs/esp-link">\ <a class="pure-menu-heading" href="https://github.com/jeelabs/esp-link">\
<img src="/favicon.ico" height="32">&nbsp;esp-link</a>\ <img src="/favicon.ico" height="32">&nbsp;esp-link</a>\
<div class="pure-menu-heading click-to-edit system-name" style="padding: 0px 0.6em">\ <div class="pure-menu-heading system-name" style="padding: 0px 0.6em"></div>\
<span class="edit-off"></span>\
<input class="edit-on" maxlength=12 hidden>\
<div class="edit-on popup" hidden>Short name for this esp-link, 12 chars max</div>\
</div>\
<ul id="menu-list" class="pure-menu-list"></ul>\ <ul id="menu-list" class="pure-menu-list"></ul>\
</div>\ </div>\
</div>\ </div>\
@ -251,6 +252,11 @@ onLoad(function() {
toggleClass(ml, active); toggleClass(ml, active);
}); });
// hide pop-ups
domForEach($(".popup"), function(el) {
hidePopup(el);
});
// populate menu via ajax call // populate menu via ajax call
var getMenu = function() { var getMenu = function() {
ajaxJson("GET", "/menu", function(data) { ajaxJson("GET", "/menu", function(data) {
@ -267,8 +273,7 @@ onLoad(function() {
var v = $("#version"); var v = $("#version");
if (v != null) { v.innerHTML = data.version; } if (v != null) { v.innerHTML = data.version; }
setEditToClick("system-name", data.name); setEditToClick("system-name", data["name"]);
makeAjaxInput("system", "name");
}, function() { setTimeout(getMenu, 1000); }); }, function() { setTimeout(getMenu, 1000); });
}; };
getMenu(); getMenu();
@ -313,7 +318,7 @@ function setEditToClick(klass, value) {
function showSystemInfo(data) { function showSystemInfo(data) {
Object.keys(data).forEach(function(v) { Object.keys(data).forEach(function(v) {
setEditToClick("system-" + v, data[v]); setEditToClick("system-"+v, data[v]);
}); });
$("#system-spinner").setAttribute("hidden", ""); $("#system-spinner").setAttribute("hidden", "");
$("#system-table").removeAttribute("hidden"); $("#system-table").removeAttribute("hidden");
@ -331,6 +336,8 @@ function makeAjaxInput(klass, field) {
var eoff = $(".edit-off", div)[0]; var eoff = $(".edit-off", div)[0];
var url = "/"+klass+"/update?"+field; var url = "/"+klass+"/update?"+field;
if (eoff === undefined || eon == undefined) return;
var enableEditToClick = function() { var enableEditToClick = function() {
eoff.setAttribute('hidden',''); eoff.setAttribute('hidden','');
domForEach(eon, function(el){ el.removeAttribute('hidden'); }); domForEach(eon, function(el){ el.removeAttribute('hidden'); });
@ -366,6 +373,7 @@ function showWarning(text) {
var el = $("#warning"); var el = $("#warning");
el.innerHTML = text; el.innerHTML = text;
el.removeAttribute('hidden'); el.removeAttribute('hidden');
window.scrollTo(0, 0);
} }
function hideWarning() { function hideWarning() {
el = $("#warning").setAttribute('hidden', ''); el = $("#warning").setAttribute('hidden', '');
@ -384,36 +392,70 @@ function showNotification(text) {
//===== GPIO Pin mux card //===== GPIO Pin mux card
var currPin; var pinPresets = {
// pin={reset:12, isp:13, LED_conn:0, LED_ser:2} // array: reset, isp, conn, ser, swap, rxpup
function createInputForPin(pin) { "esp-01": [ 0, -1, 2, -1, 0, 1 ],
var input = document.createElement("input"); "esp-12": [ 12, 14, 0, 2, 0, 1 ],
input.type = "radio"; "esp-12 swap": [ 1, 3, 0, 2, 1, 1 ],
input.name = "pins"; "esp-bridge": [ 12, 13, 0, 14, 0, 0 ],
input.data = pin.name; "wifi-link-12": [ 1, 3, 0, 2, 1, 0 ],
input.className = "pin-input"; };
input.value= pin.value;
input.id = "opt-" + pin.value; function createPresets(sel) {
if (currPin == pin.name) input.checked = "1"; for (var p in pinPresets) {
var opt = m('<option value="' + p + '">' + p + '</option>');
var descr = m('<label for="opt-'+pin.value+'"><b>'+pin.name+":</b>"+pin.descr+"</label>"); sel.appendChild(opt);
var div = document.createElement("div"); }
div.appendChild(input);
div.appendChild(descr); function applyPreset(v) {
return div; var pp = pinPresets[v];
if (pp === undefined) return pp;
console.log("apply preset:", v, pp);
function setPP(k, v) { $("#pin-"+k).value = v; };
setPP("reset", pp[0]);
setPP("isp", pp[1]);
setPP("conn", pp[2]);
setPP("ser", pp[3]);
setPP("swap", pp[4]);
$("#pin-rxpup").checked = !!pp[5];
};
bnd(sel, "change", function(ev) {
console.log("preset change:", sel.value);
ev.preventDefault();
applyPreset(sel.value);
});
} }
function displayPins(resp) { function displayPins(resp) {
var po = $("#pin-mux"); function createSelectForPin(name, v) {
po.innerHTML = ""; var sel = $("#pin-"+name);
currPin = resp.curr; addClass(sel, "pure-button");
resp.map.forEach(function(v) { [-1,0,1,2,3,4,5,12,13,14,15].forEach(function(i) {
po.appendChild(createInputForPin(v)); var opt = document.createElement("option");
opt.value = i;
if (i >= 0) opt.innerHTML = "gpio"+i;
else opt.innerHTML = "disabled";
if (i===1) opt.innerHTML += "/TX0";
if (i===2) opt.innerHTML += "/TX1";
if (i===3) opt.innerHTML += "/RX0";
if (i==v) opt.selected = true;
sel.appendChild(opt);
}); });
var i, inputs = $(".pin-input"); var pup = $(".popup", sel.parentNode);
for (i=0; i<inputs.length; i++) { if (pup !== undefined) hidePopup(pup[0]);
inputs[i].onclick = function() { setPins(this.value, this.data) };
}; };
createSelectForPin("reset", resp["reset"]);
createSelectForPin("isp", resp["isp"]);
createSelectForPin("conn", resp["conn"]);
createSelectForPin("ser", resp["ser"]);
$("#pin-swap").value = resp["swap"];
$("#pin-rxpup").checked = !!resp["rxpup"];
createPresets($("#pin-preset"));
$("#pin-spinner").setAttribute("hidden", "");
$("#pin-table").removeAttribute("hidden");
} }
function fetchPins() { function fetchPins() {
@ -423,10 +465,17 @@ function fetchPins() {
} }
function setPins(v, name) { function setPins(v, name) {
ajaxSpin("POST", "/pins?map="+v, function() { var url = "/pins";
showNotification("Pin assignment changed to " + name); var sep = "?";
}, function() { ["reset", "isp", "conn", "ser", "swap"].forEach(function(p) {
showNotification("Pin assignment change failed"); url += sep + p + "=" + $("#pin-"+p).value;
sep = "&";
});
url += "&rxpup=" + ($("#pin-rxpup").selected ? "1" : "0");
ajaxSpin("POST", url, function() {
showNotification("Pin assignment changed");
}, function(status, errMsg) {
showWarning(errMsg);
window.setTimeout(fetchPins, 100); window.setTimeout(fetchPins, 100);
}); });
} }

@ -30,7 +30,8 @@
<div id="aps">Scanning... <div class="spinner spinner-small"></div></div> <div id="aps">Scanning... <div class="spinner spinner-small"></div></div>
<label for="opt-hiddenssid"> <label for="opt-hiddenssid">
<input type="radio" name="essid" value="_hidden_ssid_" id="opt-hiddenssid"> <input type="radio" name="essid" value="_hidden_ssid_" id="opt-hiddenssid">
<input type="text" id="hidden-ssid" value="" style="width:auto; display:inline-block;"> <input type="text" id="hidden-ssid" value=""
style="width:auto; display:inline-block; margin-left: 0.7em">
</label> </label>
<label>WiFi password, if applicable:</label> <label>WiFi password, if applicable:</label>
<input id="wifi-passwd" type="password" name="passwd" placeholder="password"> <input id="wifi-passwd" type="password" name="passwd" placeholder="password">
@ -51,10 +52,7 @@
<input type="radio" name="dhcp" value="off" id="dhcp-roff"/> <input type="radio" name="dhcp" value="off" id="dhcp-roff"/>
Static IP</label> Static IP</label>
</div> </div>
<div id="dhcp-on" class="pure-form-stacked"> <div id="dhcp-on" class="pure-form-stacked"></div>
<label>Hostname when requesting DHCP lease</label>
<input id="wifi-hostname" type="text" name="hostname"/>
</div>
<div id="dhcp-off" class="pure-form-stacked"> <div id="dhcp-off" class="pure-form-stacked">
<label>Static IP address</label> <label>Static IP address</label>
<input id="wifi-staticip" type="text" name="staticip"/> <input id="wifi-staticip" type="text" name="staticip"/>

@ -446,11 +446,15 @@ serbridgeInitPins()
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 4); PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 4);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 4); PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 4);
PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTCK_U); PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTCK_U);
PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTDO_U); if (flashConfig.rx_pullup) PIN_PULLUP_EN(PERIPHS_IO_MUX_MTDO_U);
else PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTDO_U);
system_uart_swap(); system_uart_swap();
} else { } else {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, 0); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, 0); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, 0);
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
if (flashConfig.rx_pullup) PIN_PULLUP_EN(PERIPHS_IO_MUX_U0RXD_U);
else PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0RXD_U);
system_uart_de_swap(); system_uart_de_swap();
} }

@ -56,10 +56,10 @@ uart_config(uint8 uart_no)
} else { } else {
/* rcv_buff size is 0x100 */ /* rcv_buff size is 0x100 */
ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff));
PIN_PULLUP_DIS (PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
PIN_PULLUP_DIS (PERIPHS_IO_MUX_U0RXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, 0); // FUNC_U0RXD==0 PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, 0); // FUNC_U0RXD==0
//PIN_PULLUP_DIS (PERIPHS_IO_MUX_U0TXD_U); now done in serbridgeInitPins
//PIN_PULLUP_DIS (PERIPHS_IO_MUX_U0RXD_U);
} }
uart_div_modify(uart_no, UART_CLK_FREQ / UartDev.baut_rate); uart_div_modify(uart_no, UART_CLK_FREQ / UartDev.baut_rate);

Loading…
Cancel
Save