diff --git a/html/cats/cross-eyed-cat.jpg b/html/cats/cross-eyed-cat.jpg new file mode 100644 index 0000000..72deba6 Binary files /dev/null and b/html/cats/cross-eyed-cat.jpg differ diff --git a/html/cats/junge-katze-iv.jpg b/html/cats/junge-katze-iv.jpg new file mode 100644 index 0000000..803bbb0 Binary files /dev/null and b/html/cats/junge-katze-iv.jpg differ diff --git a/html/cats/kitten-loves-toy.jpg b/html/cats/kitten-loves-toy.jpg new file mode 100644 index 0000000..8965447 Binary files /dev/null and b/html/cats/kitten-loves-toy.jpg differ diff --git a/html/index.html b/html/index.html new file mode 100644 index 0000000..dbfb47a --- /dev/null +++ b/html/index.html @@ -0,0 +1,19 @@ + +Esp8266 web server + +

it Works

+

+If you see this, it means the tiny li'l website in your ESP8266 does actually work. +

+ +

+ +

And because we're on the Internets now, here are the required pictures of some cats:
+
+
+
+

+ diff --git a/html/led.tpl b/html/led.tpl new file mode 100644 index 0000000..2290d60 --- /dev/null +++ b/html/led.tpl @@ -0,0 +1,12 @@ +Test + + +

+If there's a LED connected to GPIO2, it's now %ledstate%. You can change that using the buttons below. +

+
+ + +
+ + diff --git a/include/uart_hw.h b/include/uart_hw.h new file mode 100644 index 0000000..183e694 --- /dev/null +++ b/include/uart_hw.h @@ -0,0 +1,195 @@ +//Generated at 2012-07-03 18:44:06 +/* + * Copyright (c) 2010 - 2011 Espressif System + * + */ + +#ifndef UART_REGISTER_H_INCLUDED +#define UART_REGISTER_H_INCLUDED +#define REG_UART_BASE( i ) (0x60000000+(i)*0xf00) +//version value:32'h062000 + +#define UART_FIFO( i ) (REG_UART_BASE( i ) + 0x0) +#define UART_RXFIFO_RD_BYTE 0x000000FF +#define UART_RXFIFO_RD_BYTE_S 0 + +#define UART_INT_RAW( i ) (REG_UART_BASE( i ) + 0x4) +#define UART_RXFIFO_TOUT_INT_RAW (BIT(8)) +#define UART_BRK_DET_INT_RAW (BIT(7)) +#define UART_CTS_CHG_INT_RAW (BIT(6)) +#define UART_DSR_CHG_INT_RAW (BIT(5)) +#define UART_RXFIFO_OVF_INT_RAW (BIT(4)) +#define UART_FRM_ERR_INT_RAW (BIT(3)) +#define UART_PARITY_ERR_INT_RAW (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_RAW (BIT(1)) +#define UART_RXFIFO_FULL_INT_RAW (BIT(0)) + +#define UART_INT_ST( i ) (REG_UART_BASE( i ) + 0x8) +#define UART_RXFIFO_TOUT_INT_ST (BIT(8)) +#define UART_BRK_DET_INT_ST (BIT(7)) +#define UART_CTS_CHG_INT_ST (BIT(6)) +#define UART_DSR_CHG_INT_ST (BIT(5)) +#define UART_RXFIFO_OVF_INT_ST (BIT(4)) +#define UART_FRM_ERR_INT_ST (BIT(3)) +#define UART_PARITY_ERR_INT_ST (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_ST (BIT(1)) +#define UART_RXFIFO_FULL_INT_ST (BIT(0)) + +#define UART_INT_ENA( i ) (REG_UART_BASE( i ) + 0xC) +#define UART_RXFIFO_TOUT_INT_ENA (BIT(8)) +#define UART_BRK_DET_INT_ENA (BIT(7)) +#define UART_CTS_CHG_INT_ENA (BIT(6)) +#define UART_DSR_CHG_INT_ENA (BIT(5)) +#define UART_RXFIFO_OVF_INT_ENA (BIT(4)) +#define UART_FRM_ERR_INT_ENA (BIT(3)) +#define UART_PARITY_ERR_INT_ENA (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_ENA (BIT(1)) +#define UART_RXFIFO_FULL_INT_ENA (BIT(0)) + +#define UART_INT_CLR( i ) (REG_UART_BASE( i ) + 0x10) +#define UART_RXFIFO_TOUT_INT_CLR (BIT(8)) +#define UART_BRK_DET_INT_CLR (BIT(7)) +#define UART_CTS_CHG_INT_CLR (BIT(6)) +#define UART_DSR_CHG_INT_CLR (BIT(5)) +#define UART_RXFIFO_OVF_INT_CLR (BIT(4)) +#define UART_FRM_ERR_INT_CLR (BIT(3)) +#define UART_PARITY_ERR_INT_CLR (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_CLR (BIT(1)) +#define UART_RXFIFO_FULL_INT_CLR (BIT(0)) + +#define UART_CLKDIV( i ) (REG_UART_BASE( i ) + 0x14) +#define UART_CLKDIV_CNT 0x000FFFFF +#define UART_CLKDIV_S 0 + +#define UART_AUTOBAUD( i ) (REG_UART_BASE( i ) + 0x18) +#define UART_GLITCH_FILT 0x000000FF +#define UART_GLITCH_FILT_S 8 +#define UART_AUTOBAUD_EN (BIT(0)) + +#define UART_STATUS( i ) (REG_UART_BASE( i ) + 0x1C) +#define UART_TXD (BIT(31)) +#define UART_RTSN (BIT(30)) +#define UART_DTRN (BIT(29)) +#define UART_TXFIFO_CNT 0x000000FF +#define UART_TXFIFO_CNT_S 16 +#define UART_RXD (BIT(15)) +#define UART_CTSN (BIT(14)) +#define UART_DSRN (BIT(13)) +#define UART_RXFIFO_CNT 0x000000FF +#define UART_RXFIFO_CNT_S 0 + +#define UART_CONF0( i ) (REG_UART_BASE( i ) + 0x20) +#define UART_TXFIFO_RST (BIT(18)) +#define UART_RXFIFO_RST (BIT(17)) +#define UART_IRDA_EN (BIT(16)) +#define UART_TX_FLOW_EN (BIT(15)) +#define UART_LOOPBACK (BIT(14)) +#define UART_IRDA_RX_INV (BIT(13)) +#define UART_IRDA_TX_INV (BIT(12)) +#define UART_IRDA_WCTL (BIT(11)) +#define UART_IRDA_TX_EN (BIT(10)) +#define UART_IRDA_DPLX (BIT(9)) +#define UART_TXD_BRK (BIT(8)) +#define UART_SW_DTR (BIT(7)) +#define UART_SW_RTS (BIT(6)) +#define UART_STOP_BIT_NUM 0x00000003 +#define UART_STOP_BIT_NUM_S 4 +#define UART_BIT_NUM 0x00000003 +#define UART_BIT_NUM_S 2 +#define UART_PARITY_EN (BIT(1)) +#define UART_PARITY (BIT(0)) + +#define UART_CONF1( i ) (REG_UART_BASE( i ) + 0x24) +#define UART_RX_TOUT_EN (BIT(31)) +#define UART_RX_TOUT_THRHD 0x0000007F +#define UART_RX_TOUT_THRHD_S 24 +#define UART_RX_FLOW_EN (BIT(23)) +#define UART_RX_FLOW_THRHD 0x0000007F +#define UART_RX_FLOW_THRHD_S 16 +#define UART_TXFIFO_EMPTY_THRHD 0x0000007F +#define UART_TXFIFO_EMPTY_THRHD_S 8 +#define UART_RXFIFO_FULL_THRHD 0x0000007F +#define UART_RXFIFO_FULL_THRHD_S 0 + +#define UART_LOWPULSE( i ) (REG_UART_BASE( i ) + 0x28) +#define UART_LOWPULSE_MIN_CNT 0x000FFFFF +#define UART_LOWPULSE_MIN_CNT_S 0 + +#define UART_HIGHPULSE( i ) (REG_UART_BASE( i ) + 0x2C) +#define UART_HIGHPULSE_MIN_CNT 0x000FFFFF +#define UART_HIGHPULSE_MIN_CNT_S 0 + +#define UART_PULSE_NUM( i ) (REG_UART_BASE( i ) + 0x30) +#define UART_PULSE_NUM_CNT 0x0003FF +#define UART_PULSE_NUM_CNT_S 0 + +#define UART_DATE( i ) (REG_UART_BASE( i ) + 0x78) +#define UART_ID( i ) (REG_UART_BASE( i ) + 0x7C) +#endif // UART_REGISTER_H_INCLUDED + +#define RX_BUFF_SIZE 256 +#define TX_BUFF_SIZE 100 +#define UART0 0 +#define UART1 1 + +typedef enum { + FIVE_BITS = 0x0, + SIX_BITS = 0x1, + SEVEN_BITS = 0x2, + EIGHT_BITS = 0x3 +} UartBitsNum4Char; + +typedef enum { + ONE_STOP_BIT = 0, + ONE_HALF_STOP_BIT = BIT2, + TWO_STOP_BIT = BIT2 +} UartStopBitsNum; + +typedef enum { + NONE_BITS = 0, + ODD_BITS = 0, + EVEN_BITS = BIT4 +} UartParityMode; + +typedef enum { + STICK_PARITY_DIS = 0, + STICK_PARITY_EN = BIT3 | BIT5 +} UartExistParity; + +typedef enum { + 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 +} UartBautRate; + +typedef enum { + NONE_CTRL, + HARDWARE_CTRL, + XON_XOFF_CTRL +} UartFlowCtrl; + +typedef enum { + EMPTY, + UNDER_WRITE, + WRITE_OVER +} RcvMsgBuffState; + +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; + diff --git a/user/cgiwifi.c b/user/cgiwifi.c new file mode 100644 index 0000000..36529b6 --- /dev/null +++ b/user/cgiwifi.c @@ -0,0 +1,216 @@ +/* +Cgi/template routines for the /wifi url. +*/ + +/* + * ---------------------------------------------------------------------------- + * "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 +#include "user_interface.h" +#include "mem.h" +#include "httpd.h" +#include "cgi.h" +#include "io.h" +#include "espmissingincludes.h" + +//WiFi access point data +typedef struct { + char ssid[32]; + char rssi; + char enc; +} ApData; + +//Scan resolt +typedef struct { + char scanInProgress; + ApData **apData; + int noAps; +} ScanResultData; + +//Static scan status storage. +ScanResultData cgiWifiAps; + +//Callback the code calls when a wlan ap scan is done. Basically stores the result in +//the cgiWifiAps struct. +void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) { + int n; + struct bss_info *bss_link = (struct bss_info *)arg; + os_printf("wifiScanDoneCb %d\n", status); + if (status!=OK) { + cgiWifiAps.scanInProgress=0; + wifi_station_disconnect(); //test HACK + return; + } + + //Clear prev ap data if needed. + if (cgiWifiAps.apData!=NULL) { + for (n=0; nnext.stqe_next; + n++; + } + //Allocate memory for access point data + cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); + cgiWifiAps.noAps=n; + + //Copy access point data to the static struct + n=0; + bss_link = (struct bss_info *)arg; + while (bss_link != NULL) { + cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData)); + cgiWifiAps.apData[n]->rssi=bss_link->rssi; + cgiWifiAps.apData[n]->enc=bss_link->authmode; + strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); + + bss_link = bss_link->next.stqe_next; + n++; + } + os_printf("Scan done: found %d APs\n", n); + //We're done. + cgiWifiAps.scanInProgress=0; +} + + +//Routine to start a WiFi access point scan. +static void ICACHE_FLASH_ATTR wifiStartScan() { + int x; + cgiWifiAps.scanInProgress=1; + x=wifi_station_get_connect_status(); + if (x!=STATION_GOT_IP) { + //Unit probably is trying to connect to a bogus AP. This messes up scanning. Stop that. + os_printf("STA status = %d. Disconnecting STA...\n", x); + wifi_station_disconnect(); + } + wifi_station_scan(NULL, wifiScanDoneCb); +} + +//This CGI is called from the bit of AJAX-code in wifi.tpl. It will initiate a +//scan for access points and if available will return the result of an earlier scan. +//The result is embedded in a bit of JSON parsed by the javascript in wifi.tpl. +int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { + int len; + int i; + char buff[1024]; + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Type", "text/json"); + httpdEndHeaders(connData); + + if (cgiWifiAps.scanInProgress==1) { + len=os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); + espconn_sent(connData->conn, (uint8 *)buff, len); + } else { + len=os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"0\", \n\"APs\": [\n"); + espconn_sent(connData->conn, (uint8 *)buff, len); + if (cgiWifiAps.apData==NULL) cgiWifiAps.noAps=0; + for (i=0; issid, cgiWifiAps.apData[i]->rssi, + cgiWifiAps.apData[i]->enc, (i==cgiWifiAps.noAps-1)?"":","); + espconn_sent(connData->conn, (uint8 *)buff, len); + } + len=os_sprintf(buff, "]\n}\n}\n"); + espconn_sent(connData->conn, (uint8 *)buff, len); + wifiStartScan(); + } + return HTTPD_CGI_DONE; +} + +//Temp store for new ap info. +static struct station_config stconf; + +//This routine is ran some time after a connection attempt to an access point. If +//the connect succeeds, this gets the module in STA-only mode. +static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { + int x=wifi_station_get_connect_status(); + if (x==STATION_GOT_IP) { + //Go to STA mode. This needs a reset, so do that. + wifi_set_opmode(1); + system_restart(); + } else { + os_printf("Connect fail. Not going into STA-only mode.\n"); + } +} + +//Actually connect to a station. This routine is timed because I had problems +//with immediate connections earlier. It probably was something else that caused it, +//but I can't be arsed to put the code back :P +static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) { + int x; + static ETSTimer resetTimer; + wifi_station_disconnect(); + wifi_station_set_config(&stconf); + wifi_station_connect(); + x=wifi_get_opmode(); + if (x!=1) { + //Schedule disconnect/connect + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 4000, 0); + } +} + + +//This cgi uses the routines above to connect to a specific access point with the +//given ESSID using the given password. +int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { + char essid[128]; + char passwd[128]; + static ETSTimer reassTimer; + + if (connData->conn==NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + + httpdFindArg(connData->postBuff, "essid", essid, sizeof(essid)); + httpdFindArg(connData->postBuff, "passwd", passwd, sizeof(passwd)); + + os_strncpy((char*)stconf.ssid, essid, 32); + os_strncpy((char*)stconf.password, passwd, 64); + + //Schedule disconnect/connect + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, reassTimerCb, NULL); + os_timer_arm(&reassTimer, 1000, 0); + + httpdRedirect(connData, "connecting.html"); + + return HTTPD_CGI_DONE; +} + +//Template code for the WLAN page. +void ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg) { + char buff[1024]; + int x; + static struct station_config stconf; + if (token==NULL) return; + wifi_station_get_config(&stconf); + + os_strcpy(buff, "Unknown"); + if (os_strcmp(token, "WiFiMode")==0) { + x=wifi_get_opmode(); + if (x==1) os_strcpy(buff, "Client"); + if (x==2) os_strcpy(buff, "SoftAP"); + if (x==3) os_strcpy(buff, "STA+AP"); + } else if (os_strcmp(token, "currSsid")==0) { + os_strcpy(buff, (char*)stconf.ssid); + } else if (os_strcmp(token, "WiFiPasswd")==0) { + os_strcpy(buff, (char*)stconf.password); + } + espconn_sent(connData->conn, (uint8 *)buff, os_strlen(buff)); +} + + diff --git a/user/cgiwifi.h b/user/cgiwifi.h new file mode 100644 index 0000000..91c1992 --- /dev/null +++ b/user/cgiwifi.h @@ -0,0 +1,11 @@ +#ifndef CGIWIFI_H +#define CGIWIFI_H + +#include "httpd.h" + +int cgiWiFiScan(HttpdConnData *connData); +void tplWlan(HttpdConnData *connData, char *token, void **arg); +int cgiWiFi(HttpdConnData *connData); +int cgiWiFiConnect(HttpdConnData *connData); + +#endif \ No newline at end of file diff --git a/user/stdout.c b/user/stdout.c new file mode 100644 index 0000000..68efd54 --- /dev/null +++ b/user/stdout.c @@ -0,0 +1,50 @@ +//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 "espmissingincludes.h" +#include "ets_sys.h" +#include "osapi.h" +#include "uart_hw.h" + +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); +} \ No newline at end of file diff --git a/user/stdout.h b/user/stdout.h new file mode 100644 index 0000000..589da44 --- /dev/null +++ b/user/stdout.h @@ -0,0 +1 @@ +void stdoutInit();