support for dynamically changing gpio pin assignments

pull/25/head
Thorsten von Eicken 10 years ago
parent 03819576cf
commit e412390d84
  1. 2
      Makefile
  2. 2
      html/140medley.min.js
  3. 13
      html/home.tpl
  4. 2
      html/style.css
  5. 21
      html/ui.js
  6. 15
      html/wifi/wifi.tpl
  7. 84
      serial/serbridge.c
  8. 3
      serial/serbridge.h
  9. 21
      serial/serled.c
  10. 2
      serial/serled.h
  11. 18
      user/cgipins.c
  12. 20
      user/status.c
  13. 2
      user/status.h
  14. 6
      user/user_main.c

@ -19,7 +19,7 @@ XTENSA_TOOLS_ROOT ?= $(abspath ../esp-open-sdk/xtensa-lx106-elf/bin)/
# Base directory of the ESP8266 SDK package, absolute # Base directory of the ESP8266 SDK package, absolute
# Typically you'll download from Espressif's BBS, http://bbs.espressif.com/viewforum.php?f=5 # Typically you'll download from Espressif's BBS, http://bbs.espressif.com/viewforum.php?f=5
SDK_BASE ?= $(abspath ../esp_iot_sdk_v1.1.0) SDK_BASE ?= $(abspath ../esp_iot_sdk_v1.1.2p)
# Esptool.py path and port, only used for 1-time serial flashing # Esptool.py path and port, only used for 1-time serial flashing
# Typically you'll use https://github.com/themadinventor/esptool # Typically you'll use https://github.com/themadinventor/esptool

@ -1,4 +1,4 @@
var b=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}, var 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= 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}, 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])}, $=function(a,b){a=a.match(/^(\W)?(.*)/);return(b||document)["getElement"+(a[1]?a[1]=="#"?"ById":"sByClassName":"sByTagName")](a[2])},

@ -44,10 +44,11 @@ function createInputForPin(pin) {
var input = document.createElement("input"); var input = document.createElement("input");
input.type = "radio"; input.type = "radio";
input.name = "pins"; input.name = "pins";
input.data = pin.name;
input.className = "pin-input";
input.value= pin.value; input.value= pin.value;
input.id = "opt-" + pin.value; input.id = "opt-" + pin.value;
input.onclick = "setPins("+pin.value+", '"+pin.name+"')"; if (currPin == pin.name) input.checked = "1";
if (currPin == pin.value) input.checked = "1";
var descr = m('<label for="opt-'+pin.value+'"><b>'+pin.name+":</b>"+pin.descr+"</label>"); var descr = m('<label for="opt-'+pin.value+'"><b>'+pin.name+":</b>"+pin.descr+"</label>");
descr.for = "opt-" + pin.value; descr.for = "opt-" + pin.value;
@ -64,6 +65,10 @@ function displayPins(resp) {
resp.map.forEach(function(v) { resp.map.forEach(function(v) {
po.appendChild(createInputForPin(v)); po.appendChild(createInputForPin(v));
}); });
var i, inputs = $(".pin-input");
for (i=0; i<inputs.length; i++) {
inputs[i].onclick = function() { setPins(this.value, this.data) };
};
} }
function fetchPins() { function fetchPins() {
@ -73,7 +78,7 @@ function fetchPins() {
} }
function setPins(v, name) { function setPins(v, name) {
ajaxJson("POST", "/pins?value="+v, function() { ajaxSpin("POST", "/pins?map="+v, function() {
showNotification("Pin assignment changed to " + name); showNotification("Pin assignment changed to " + name);
}, function() { }, function() {
showNotification("Pin assignment change failed"); showNotification("Pin assignment change failed");
@ -83,7 +88,7 @@ function setPins(v, name) {
window.onload=function(e) { window.onload=function(e) {
fetchPins(); fetchPins();
//$("#pinform").onsubmit = setPins; getWifiInfo();
}; };
</script> </script>
</body></html> </body></html>

@ -37,7 +37,7 @@ fieldset fields {
} }
#pin-mux label { #pin-mux label {
display: block; display: block;
margin: 0em 0.2em 0em 2em; margin: 0em 0.2em 0em 1em;
width: 90%; width: 90%;
} }

@ -46,6 +46,25 @@
}(this, this.document)); }(this, this.document));
//===== Wifi info
function showWifiInfo(data) {
Object.keys(data).forEach(function(v) {
el = $("#wifi-" + v);
if (el != null) el.innerHTML = data[v];
});
$("#wifi-spinner").setAttribute("hidden", "");
$("#wifi-table").removeAttribute("hidden");
currAp = data.ssid;
}
function getWifiInfo() {
ajaxJson('GET', "/wifi/info", showWifiInfo,
function(s, st) { window.setTimeout(getWifiInfo, 1000); });
}
//===== Notifications
function showWarning(text) { function showWarning(text) {
var el = $("#warning"); var el = $("#warning");
el.innerHTML = text; el.innerHTML = text;
@ -66,6 +85,8 @@ function showNotification(text) {
}, 4000); }, 4000);
} }
//===== AJAX
function ajaxReq(method, url, ok_cb, err_cb) { function ajaxReq(method, url, ok_cb, err_cb) {
var xhr = j(); var xhr = j();
xhr.open(method, url, true); xhr.open(method, url, true);

@ -135,21 +135,6 @@ function scanAPs() {
}); });
} }
function showWifiInfo(data) {
Object.keys(data).forEach(function(v) {
el = $("#wifi-" + v);
if (el != null) el.innerHTML = data[v];
});
$("#wifi-spinner").setAttribute("hidden", "");
$("#wifi-table").removeAttribute("hidden");
currAp = data.ssid;
}
function getWifiInfo() {
ajaxJson('GET', "info", showWifiInfo,
function(s, st) { window.setTimeout(getWifiInfo, 1000); });
}
function getStatus() { function getStatus() {
ajaxJsonSpin("GET", "connstatus", function(data) { ajaxJsonSpin("GET", "connstatus", function(data) {
if (data.status == "idle" || data.status == "connecting") { if (data.status == "idle" || data.status == "connecting") {

@ -9,12 +9,12 @@
#include "uart.h" #include "uart.h"
#include "serbridge.h" #include "serbridge.h"
#include "serled.h" #include "serled.h"
#include "config.h"
#include "console.h" #include "console.h"
static uint8_t mcu_reset_pin, mcu_isp_pin;
static struct espconn serbridgeConn; static struct espconn serbridgeConn;
static esp_tcp serbridgeTcp; static esp_tcp serbridgeTcp;
static int8_t mcu_reset_pin, mcu_isp_pin;
sint8 ICACHE_FLASH_ATTR espbuffsend(serbridgeConnData *conn, const char *data, uint16 len); sint8 ICACHE_FLASH_ATTR espbuffsend(serbridgeConnData *conn, const char *data, uint16 len);
@ -147,22 +147,30 @@ telnetUnwrap(uint8_t *inBuf, int len, uint8_t state)
case TN_setControl: // switch control line and delay a tad case TN_setControl: // switch control line and delay a tad
switch (c) { switch (c) {
case DTR_ON: case DTR_ON:
os_printf("MCU reset gpio%d\n", mcu_reset_pin); if (mcu_reset_pin >= 0) {
GPIO_OUTPUT_SET(mcu_reset_pin, 0); os_printf("MCU reset gpio%d\n", mcu_reset_pin);
os_delay_us(100L); GPIO_OUTPUT_SET(mcu_reset_pin, 0);
os_delay_us(100L);
} else os_printf("MCU reset: no pin\n");
break; break;
case DTR_OFF: case DTR_OFF:
GPIO_OUTPUT_SET(mcu_reset_pin, 1); if (mcu_reset_pin >= 0) {
os_delay_us(100L); GPIO_OUTPUT_SET(mcu_reset_pin, 1);
os_delay_us(100L);
}
break; break;
case RTS_ON: case RTS_ON:
os_printf("MCU ISP gpio%d\n", mcu_isp_pin); if (mcu_isp_pin >= 0) {
GPIO_OUTPUT_SET(mcu_isp_pin, 0); os_printf("MCU ISP gpio%d\n", mcu_isp_pin);
os_delay_us(100L); GPIO_OUTPUT_SET(mcu_isp_pin, 0);
os_delay_us(100L);
} else os_printf("MCU isp: no pin\n");
break; break;
case RTS_OFF: case RTS_OFF:
GPIO_OUTPUT_SET(mcu_isp_pin, 1); if (mcu_isp_pin >= 0) {
os_delay_us(100L); GPIO_OUTPUT_SET(mcu_isp_pin, 1);
os_delay_us(100L);
}
break; break;
} }
state = TN_end; state = TN_end;
@ -173,10 +181,12 @@ telnetUnwrap(uint8_t *inBuf, int len, uint8_t state)
} }
void ICACHE_FLASH_ATTR serbridgeReset() { void ICACHE_FLASH_ATTR serbridgeReset() {
os_printf("MCU reset gpio%d\n", mcu_reset_pin); if (mcu_reset_pin >= 0) {
GPIO_OUTPUT_SET(mcu_reset_pin, 0); os_printf("MCU reset gpio%d\n", mcu_reset_pin);
os_delay_us(100L); GPIO_OUTPUT_SET(mcu_reset_pin, 0);
GPIO_OUTPUT_SET(mcu_reset_pin, 1); os_delay_us(100L);
GPIO_OUTPUT_SET(mcu_reset_pin, 1);
} else os_printf("MCU reset: no pin\n");
} }
@ -201,13 +211,13 @@ static void ICACHE_FLASH_ATTR serbridgeRecvCb(void *arg, char *data, unsigned sh
os_printf("MCU Reset=%d ISP=%d\n", mcu_reset_pin, mcu_isp_pin); os_printf("MCU Reset=%d ISP=%d\n", mcu_reset_pin, mcu_isp_pin);
os_delay_us(2*1000L); // time for os_printf to happen os_delay_us(2*1000L); // time for os_printf to happen
// send reset to arduino/ARM // send reset to arduino/ARM
GPIO_OUTPUT_SET(mcu_reset_pin, 0); if (mcu_reset_pin >= 0) GPIO_OUTPUT_SET(mcu_reset_pin, 0);
os_delay_us(100L); os_delay_us(100L);
GPIO_OUTPUT_SET(mcu_isp_pin, 0); if (mcu_isp_pin >= 0) GPIO_OUTPUT_SET(mcu_isp_pin, 0);
os_delay_us(100L); os_delay_us(100L);
GPIO_OUTPUT_SET(mcu_reset_pin, 1); if (mcu_reset_pin >= 0) GPIO_OUTPUT_SET(mcu_reset_pin, 1);
os_delay_us(100L); os_delay_us(100L);
GPIO_OUTPUT_SET(mcu_isp_pin, 1); if (mcu_isp_pin >= 0) GPIO_OUTPUT_SET(mcu_isp_pin, 1);
os_delay_us(1000L); os_delay_us(1000L);
conn->conn_mode = cmAVR; conn->conn_mode = cmAVR;
@ -255,9 +265,11 @@ static void ICACHE_FLASH_ATTR serbridgeDisconCb(void *arg) {
{ {
if (connData[i].conn_mode == cmAVR) { if (connData[i].conn_mode == cmAVR) {
// send reset to arduino/ARM // send reset to arduino/ARM
GPIO_OUTPUT_SET(mcu_reset_pin, 0); if (mcu_reset_pin >= 0) {
os_delay_us(100L); GPIO_OUTPUT_SET(mcu_reset_pin, 0);
GPIO_OUTPUT_SET(mcu_reset_pin, 1); os_delay_us(100L);
GPIO_OUTPUT_SET(mcu_reset_pin, 1);
}
} }
connData[i].conn = NULL; connData[i].conn = NULL;
} }
@ -306,8 +318,23 @@ serbridgeUartCb(char *buf, int length) {
} }
} }
void ICACHE_FLASH_ATTR serbridgeInitPins() {
mcu_reset_pin = flashConfig.reset_pin;
mcu_isp_pin = flashConfig.isp_pin;
os_printf("Serbridge pins: reset=%d isp=%d\n", mcu_reset_pin, mcu_isp_pin);
// set both pins to 1 before turning them on so we don't cause a reset
if (mcu_isp_pin >= 0) GPIO_OUTPUT_SET(mcu_isp_pin, 1);
if (mcu_reset_pin >= 0) GPIO_OUTPUT_SET(mcu_reset_pin, 1);
// switch pin mux to make these pins GPIO pins
if (mcu_reset_pin >= 0) makeGpio(mcu_reset_pin);
if (mcu_isp_pin >= 0) makeGpio(mcu_isp_pin);
}
// Start transparent serial bridge TCP server on specified port (typ. 23) // Start transparent serial bridge TCP server on specified port (typ. 23)
void ICACHE_FLASH_ATTR serbridgeInit(int port, uint8_t reset_pin, uint8_t isp_pin) { void ICACHE_FLASH_ATTR serbridgeInit(int port) {
serbridgeInitPins();
int i; int i;
for (i = 0; i < MAX_CONN; i++) { for (i = 0; i < MAX_CONN; i++) {
connData[i].conn = NULL; connData[i].conn = NULL;
@ -318,15 +345,6 @@ void ICACHE_FLASH_ATTR serbridgeInit(int port, uint8_t reset_pin, uint8_t isp_pi
serbridgeTcp.local_port = port; serbridgeTcp.local_port = port;
serbridgeConn.proto.tcp = &serbridgeTcp; serbridgeConn.proto.tcp = &serbridgeTcp;
mcu_reset_pin = reset_pin;
mcu_isp_pin = isp_pin;
// set both pins to 1 so we don't cause a reset
GPIO_OUTPUT_SET(mcu_isp_pin, 1);
GPIO_OUTPUT_SET(mcu_reset_pin, 1);
// switch pin mux to make these pins GPIO pins
makeGpio(mcu_reset_pin);
makeGpio(mcu_isp_pin);
espconn_regist_connectcb(&serbridgeConn, serbridgeConnectCb); espconn_regist_connectcb(&serbridgeConn, serbridgeConnectCb);
espconn_accept(&serbridgeConn); espconn_accept(&serbridgeConn);
espconn_tcp_set_max_con_allow(&serbridgeConn, MAX_CONN); espconn_tcp_set_max_con_allow(&serbridgeConn, MAX_CONN);

@ -32,7 +32,8 @@ struct serbridgeConnData {
uint8_t telnet_state; uint8_t telnet_state;
}; };
void ICACHE_FLASH_ATTR serbridgeInit(int port, uint8_t reset_pin, uint8_t isp_pin); void ICACHE_FLASH_ATTR serbridgeInit(int port);
void ICACHE_FLASH_ATTR serbridgeInitPins(void);
void ICACHE_FLASH_ATTR serbridgeUartCb(char *buf, int len); void ICACHE_FLASH_ATTR serbridgeUartCb(char *buf, int len);
void ICACHE_FLASH_ATTR serbridgeReset(); void ICACHE_FLASH_ATTR serbridgeReset();

@ -1,15 +1,17 @@
#include <esp8266.h> #include <esp8266.h>
#include <config.h>
#include <serled.h> #include <serled.h>
static ETSTimer serledTimer; static ETSTimer serledTimer;
static uint8_t serledPin;
static void ICACHE_FLASH_ATTR setSerled(int on) { static void ICACHE_FLASH_ATTR setSerled(int on) {
int8_t pin = flashConfig.ser_led_pin;
if (pin < 0) return; // disabled
// LED is active-low // LED is active-low
if (on) { if (on) {
gpio_output_set(0, (1<<serledPin), (1<<serledPin), 0); gpio_output_set(0, (1<<pin), (1<<pin), 0);
} else { } else {
gpio_output_set((1<<serledPin), 0, (1<<serledPin), 0); gpio_output_set((1<<pin), 0, (1<<pin), 0);
} }
} }
@ -24,11 +26,14 @@ void ICACHE_FLASH_ATTR serledFlash(int duration) {
os_timer_arm(&serledTimer, duration, 0); os_timer_arm(&serledTimer, duration, 0);
} }
void ICACHE_FLASH_ATTR serledInit(uint8_t pin) { void ICACHE_FLASH_ATTR serledInit(void) {
serledPin = pin; int8_t pin = flashConfig.ser_led_pin;
makeGpio(pin); if (pin >= 0) {
gpio_output_set(0, 0, (1<<pin), 0); makeGpio(pin);
serledFlash(1000); // turn it on for 1 second gpio_output_set(0, 0, (1<<pin), 0);
serledFlash(1000); // turn it on for 1 second
}
os_printf("SER led=%d\n", pin);
} }
// Make a pin be GPIO, i.e. set the mux so the pin has the gpio function // Make a pin be GPIO, i.e. set the mux so the pin has the gpio function

@ -2,7 +2,7 @@
#define SERLED_H #define SERLED_H
void serledFlash(int duration); void serledFlash(int duration);
void serledInit(uint8_t pin); void serledInit(void);
void makeGpio(uint8_t pin); void makeGpio(uint8_t pin);
#endif #endif

@ -3,16 +3,20 @@
#include "cgi.h" #include "cgi.h"
#include "espfs.h" #include "espfs.h"
#include "config.h" #include "config.h"
#include "serled.h"
#include "status.h"
#include "serbridge.h"
static char *map_names[] = { static char *map_names[] = {
"esp-bridge", "jn-esp-v2", "esp-01(ARM)", "esp-01(AVR)", "esp-bridge", "jn-esp-v2", "esp-01(AVR)", "esp-01(ARM)", "esp-br-rev",
}; };
static char* map_func[] = { "reset", "isp", "conn_led", "ser_led" }; static char* map_func[] = { "reset", "isp", "conn_led", "ser_led" };
static int8_t map_asn[][4] = { static int8_t map_asn[][4] = {
{ 12, 13, 0, 14 }, // esp-bridge { 12, 13, 0, 14 }, // esp-bridge
{ 12, 13, 0, 2 }, // jn-esp-v2 { 12, 13, 0, 2 }, // jn-esp-v2
{ 0, 2, -1, -1 }, // esp-01(ARM)
{ 0, -1, 2, -1 }, // esp-01(AVR) { 0, -1, 2, -1 }, // esp-01(AVR)
{ 0, 2, -1, -1 }, // esp-01(ARM)
{ 13, 12, 14, 0 }, // esp-br-rev -- for test purposes
}; };
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*);
@ -45,7 +49,9 @@ int ICACHE_FLASH_ATTR cgiPinsGet(HttpdConnData *connData) {
} }
len += os_sprintf(buff+len, ", \"descr\":\""); len += os_sprintf(buff+len, ", \"descr\":\"");
for (int f=0; f<num_map_func; f++) { for (int f=0; f<num_map_func; f++) {
len += os_sprintf(buff+len, " %s:gpio%d", map_func[f], map_asn[i][f]); int8_t p = map_asn[i][f];
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, "\" }");
} }
@ -64,7 +70,7 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) {
char buff[128]; char buff[128];
int len = httpdFindArg(connData->getArgs, "map", buff, sizeof(buff)); int len = httpdFindArg(connData->getArgs, "map", buff, sizeof(buff));
if (len == 0) { if (len <= 0) {
jsonHeader(connData, 400); jsonHeader(connData, 400);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
@ -82,6 +88,10 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) {
flashConfig.conn_led_pin = map[2]; flashConfig.conn_led_pin = map[2];
flashConfig.ser_led_pin = map[3]; flashConfig.ser_led_pin = map[3];
serbridgeInitPins();
serledInit();
statusInit();
jsonHeader(connData, 200); jsonHeader(connData, 200);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }

@ -1,16 +1,18 @@
#include <esp8266.h> #include <esp8266.h>
#include "config.h"
#include "serled.h"
#include "cgiwifi.h" #include "cgiwifi.h"
#define LEDGPIO 0
static ETSTimer ledTimer; static ETSTimer ledTimer;
static void ICACHE_FLASH_ATTR setLed(int on) { static void ICACHE_FLASH_ATTR setLed(int on) {
int8_t pin = flashConfig.conn_led_pin;
if (pin < 0) return; // disabled
// LED is active-low // LED is active-low
if (on) { if (on) {
gpio_output_set(0, (1<<LEDGPIO), (1<<LEDGPIO), 0); gpio_output_set(0, (1<<pin), (1<<pin), 0);
} else { } else {
gpio_output_set((1<<LEDGPIO), 0, (1<<LEDGPIO), 0); gpio_output_set((1<<pin), 0, (1<<pin), 0);
} }
} }
@ -58,10 +60,12 @@ void ICACHE_FLASH_ATTR statusWifiUpdate(uint8_t state) {
os_timer_arm(&ledTimer, 500, 0); os_timer_arm(&ledTimer, 500, 0);
} }
void ICACHE_FLASH_ATTR statusInit() { void ICACHE_FLASH_ATTR statusInit(void) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0); if (flashConfig.conn_led_pin >= 0) {
gpio_output_set(0, 0, (1<<LEDGPIO), 0); makeGpio(flashConfig.conn_led_pin);
setLed(1); setLed(1);
}
os_printf("CONN led=%d\n", flashConfig.conn_led_pin);
os_timer_disarm(&ledTimer); os_timer_disarm(&ledTimer);
os_timer_setfn(&ledTimer, ledTimerCb, NULL); os_timer_setfn(&ledTimer, ledTimerCb, NULL);

@ -2,7 +2,7 @@
#define STATUS_H #define STATUS_H
void statusWifiUpdate(uint8_t state); void statusWifiUpdate(uint8_t state);
void statusInit(uint8_t pin); void statusInit(void);
#endif #endif

@ -122,8 +122,8 @@ void user_init(void) {
# define VERS_STR(V) VERS_STR_STR(V) # define VERS_STR(V) VERS_STR_STR(V)
os_printf("\n\nInitializing esp-link\n" VERS_STR(VERSION) "\n"); os_printf("\n\nInitializing esp-link\n" VERS_STR(VERSION) "\n");
// Status LEDs // Status LEDs
statusInit(LED_CONN_PIN); statusInit();
serledInit(LED_SERIAL_PIN); serledInit();
logInit(); logInit();
// Wifi // Wifi
wifiInit(); wifiInit();
@ -133,7 +133,7 @@ void user_init(void) {
// mount the http handlers // mount the http handlers
httpdInit(builtInUrls, 80); httpdInit(builtInUrls, 80);
// init the wifi-serial transparent bridge (port 23) // init the wifi-serial transparent bridge (port 23)
serbridgeInit(23, MCU_RESET_PIN, MCU_ISP_PIN); serbridgeInit(23);
uart_add_recv_cb(&serbridgeUartCb); uart_add_recv_cb(&serbridgeUartCb);
#ifdef SHOW_HEAP_USE #ifdef SHOW_HEAP_USE
os_timer_disarm(&prHeapTimer); os_timer_disarm(&prHeapTimer);

Loading…
Cancel
Save