improved a bunch of stuff, and should now have working bulk transfer (maybe)

master
Ondřej Hruška 8 years ago
parent ff1c09d9f8
commit 23883ef582
  1. 3
      Makefile
  2. 2
      esp_iot_sdk_v1.5.2/include/osapi.h
  3. 8
      esp_meas.pro
  4. 2
      esp_meas.pro.user
  5. 5
      libesphttpd/util/cgiwebsocket.c
  6. 2
      sbmp
  7. 73
      user/cgi.c
  8. 4
      user/cgi.h
  9. 18
      user/datalink.c
  10. 7
      user/datalink.h
  11. 72
      user/page_home.c
  12. 8
      user/page_home.h
  13. 180
      user/sampling.c
  14. 10
      user/sampling.h
  15. 36
      user/uart_driver.c
  16. 42
      user/user_main.c

@ -66,7 +66,8 @@ LIBS += esphttpd
# compiler flags using during compilation of source files
CFLAGS = -Os -ggdb -std=gnu99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \
-Wno-address -ffunction-sections -Wno-strict-aliasing
-Wno-address -ffunction-sections
#-Wno-strict-aliasing
# linker flags used to generate the main object file
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,--gc-sections

@ -27,7 +27,7 @@
#ifdef USE_US_TIMER
#define os_timer_arm_us(a, b, c) ets_timer_arm_new(a, b, c, 0)
#endif
#define os_timer_arm(a, b, c) ets_timer_arm_new(a, b, c, 1)
#define os_timer_arm(timer, time_ms, repeat) ets_timer_arm_new(timer, time_ms, repeat, 1)
#define os_timer_disarm ets_timer_disarm
#define os_timer_setfn ets_timer_setfn

@ -52,7 +52,9 @@ SOURCES += \
user/datalink.c \
user/serial.c \
user/uptime.c \
sbmp/library/payload_parser.c
sbmp/library/payload_parser.c \
user/sampling.c \
user/page_home.c
HEADERS += \
include/uart_hw.h \
@ -126,7 +128,9 @@ HEADERS += \
user/serial.h \
libesphttpd/include/logging.h \
user/uptime.h \
sbmp/library/payload_parser.h
sbmp/library/payload_parser.h \
user/sampling.h \
user/page_home.h
DISTFILES += \
style.astylerc \

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.6.0, 2016-03-22T22:44:16. -->
<!-- Written by QtCreator 3.6.0, 2016-03-24T21:40:55. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

@ -136,8 +136,7 @@ int ICACHE_FLASH_ATTR cgiWebsockBroadcast(char *resource, char *data, int len, i
}
lw=lw->priv->next;
}
return ret;
*/
return ret;*/
return 0;
}
@ -217,7 +216,7 @@ int ICACHE_FLASH_ATTR cgiWebSocketRecv(HttpdConnData *connData, char *data, int
//received here at the same time; no more byte iterations till the end of this frame.
//First, unmask the data
sl=len-i;
dbg("[WS] Frame payload. wasHeaderByte %d fr.len %d sl %d cmd 0x%x\n", wasHeaderByte, (int)ws->priv->fr.len, (int)sl, ws->priv->fr.flags);
dbg("[WS] Frame payload. wasHeaderByte %d fr.len %d sl %d cmd 0x%x", wasHeaderByte, (int)ws->priv->fr.len, (int)sl, ws->priv->fr.flags);
if (sl > ws->priv->fr.len) sl=ws->priv->fr.len;
for (j=0; j<sl; j++) data[i+j]^=(ws->priv->fr.mask[(ws->priv->maskCtr++)&3]);

@ -1 +1 @@
Subproject commit 7c43fd3e1a147d24cde05a7ecd3d155e293caa89
Subproject commit 6df0fcacd8bc23d2af86df4d5c5c2c624938eeb4

@ -16,73 +16,9 @@ flash as a binary. Also handles the hit counter on the main page.
#include <esp8266.h>
#include "cgi.h"
#include "uptime.h"
#include "datalink.h"
//Template code for the counter on the index page.
int ICACHE_FLASH_ATTR tplHome(HttpdConnData *connData, char *token, void **arg)
{
struct station_config stconf;
char buff[128];
u8 mac[6];
// empty string if no token matches
buff[0] = 0;
if (token == NULL) return HTTPD_CGI_DONE;
if (strcmp(token, "uptime") == 0) {
// Uptime
uptime_str(buff);
} else if (strcmp(token, "heap") == 0) {
// Free heap
sprintf(buff, "%u", system_get_free_heap_size());
} else if (strcmp(token, "wifiMode") == 0) {
// WiFi mode
switch (wifi_get_opmode()) {
case STATION_MODE: strcpy(buff, "Client"); break;
case SOFTAP_MODE: strcpy(buff, "SoftAP"); break;
case STATIONAP_MODE: strcpy(buff, "STA+AP"); break;
default: strcpy(buff, "Unknown");
}
} else if (strcmp(token, "staSSID") == 0) {
// Station SSID (if in station mode)
int opmode = wifi_get_opmode();
if (opmode != STATION_MODE && opmode != STATIONAP_MODE) {
strcpy(buff, "N/A"); // no SSID in AP-only mode
} else {
wifi_station_get_config(&stconf);
strcpy(buff, (char*)stconf.ssid);
}
} else if (strcmp(token, "staRSSI") == 0) {
// Signal strength if in Station mode
int rssi = wifi_station_get_rssi();
sprintf(buff, "%d", rssi);
} else if (strcmp(token, "staMAC") == 0) {
// Station MAC addr
wifi_get_macaddr(STATION_IF, mac);
sprintf(buff, MACSTR, MAC2STR(mac));
} else if (strcmp(token, "apMAC") == 0) {
// SoftAP MAC addr
wifi_get_macaddr(SOFTAP_IF, mac);
sprintf(buff, MACSTR, MAC2STR(mac));
} else if (strcmp(token, "chipID") == 0) {
// Chip serial number
sprintf(buff, "%08x", system_get_chip_id());
}
httpdSend(connData, buff, -1);
return HTTPD_CGI_DONE;
}
// ----
// ---- demonstration of a multi-part substituion in a template ----
typedef struct {
uint32_t count_remain;
@ -90,7 +26,7 @@ typedef struct {
//Template code for the counter on the index page.
int ICACHE_FLASH_ATTR tplMultipart(HttpdConnData *connData, char *token, void **arg)
int FLASH_FN tplMultipart(HttpdConnData *connData, char *token, void **arg)
{
if (token == NULL) {
if (*arg != NULL) {
@ -104,6 +40,7 @@ int ICACHE_FLASH_ATTR tplMultipart(HttpdConnData *connData, char *token, void **
RandomNumberState *rns = *arg;
char buff[20];
// first call in this substitution
if (rns == NULL) {
//First call to this cgi. Open the file so we can read it.
rns=(RandomNumberState *)malloc(sizeof(RandomNumberState));
@ -122,6 +59,7 @@ int ICACHE_FLASH_ATTR tplMultipart(HttpdConnData *connData, char *token, void **
info("User wants %d numbers.", count);
}
// print the numbers
for (int i = 0; i < 100; i++) {
os_sprintf(buff, "<li>%lu\n", os_random());
httpdSend(connData, buff, -1);
@ -131,6 +69,7 @@ int ICACHE_FLASH_ATTR tplMultipart(HttpdConnData *connData, char *token, void **
}
}
// We are done.
if (rns->count_remain == 0) {
free(rns);
*arg = NULL; // mark as already freed

@ -4,10 +4,6 @@
#include <esp8266.h>
#include "httpd.h"
int tplHome(HttpdConnData *connData, char *token, void **arg);
//int cgiRandomNumbers(HttpdConnData *connData);
int tplMultipart(HttpdConnData *connData, char *token, void **arg);
#endif

@ -1,11 +1,11 @@
#include "esp8266.h"
#include "uart_driver.h"
#include "sbmp.h"
#include "datalink.h"
// payload rx buffer
#define PAYLOAD_BUFFER_LEN (256+3)
static SBMP_Endpoint *ep;
SBMP_Endpoint *dlnk_ep;
/** func used for sending bytes by SBMP */
@ -17,21 +17,21 @@ static void FLASH_FN u0_putc(uint8_t c)
static void FLASH_FN dg_handler(SBMP_Datagram *dg)
{
dbg("[SBMP] Datagram received.");
dbg("[SBMP] Datagram received, type %d", dg->type);
}
/** This is called by the UART rx handler */
void datalink_receive(uint8_t byte)
{
sbmp_ep_receive(ep, byte);
sbmp_ep_receive(dlnk_ep, byte);
}
/** Datalink */
void FLASH_FN datalinkInit(void)
{
ep = sbmp_ep_init(NULL, NULL, 256, dg_handler, u0_putc);
dlnk_ep = sbmp_ep_init(NULL, NULL, PAYLOAD_BUFFER_LEN, dg_handler, u0_putc);
sbmp_ep_enable(ep, true);
sbmp_ep_enable(dlnk_ep, true);
info("SBMP started on UART0");
}

@ -2,6 +2,13 @@
#define DATALINK_H
#include <esp8266.h>
#include <sbmp.h>
// request to capture data...
#define DG_REQUEST_CAPTURE 40
extern SBMP_Endpoint *dlnk_ep;
void datalinkInit(void);

@ -0,0 +1,72 @@
#include <esp8266.h>
#include <httpd.h>
#include "page_home.h"
#include "uptime.h"
/** System Status page */
int FLASH_FN tplHome(HttpdConnData *connData, char *token, void **arg)
{
// arg is unused
(void)arg;
struct station_config stconf;
char buff[128];
u8 mac[6];
// empty string if no token matches
buff[0] = 0;
if (token == NULL) return HTTPD_CGI_DONE;
if (strcmp(token, "uptime") == 0) {
// Uptime
uptime_str(buff);
} else if (strcmp(token, "heap") == 0) {
// Free heap
sprintf(buff, "%u", system_get_free_heap_size());
} else if (strcmp(token, "wifiMode") == 0) {
// WiFi mode
switch (wifi_get_opmode()) {
case STATION_MODE: strcpy(buff, "Client"); break;
case SOFTAP_MODE: strcpy(buff, "SoftAP"); break;
case STATIONAP_MODE: strcpy(buff, "STA+AP"); break;
default: strcpy(buff, "Unknown");
}
} else if (strcmp(token, "staSSID") == 0) {
// Station SSID (if in station mode)
int opmode = wifi_get_opmode();
if (opmode != STATION_MODE && opmode != STATIONAP_MODE) {
strcpy(buff, "N/A"); // no SSID in AP-only mode
} else {
wifi_station_get_config(&stconf);
strcpy(buff, (char*)stconf.ssid);
}
} else if (strcmp(token, "staRSSI") == 0) {
// Signal strength if in Station mode
int rssi = wifi_station_get_rssi();
sprintf(buff, "%d", rssi);
} else if (strcmp(token, "staMAC") == 0) {
// Station MAC addr
wifi_get_macaddr(STATION_IF, mac);
sprintf(buff, MACSTR, MAC2STR(mac));
} else if (strcmp(token, "apMAC") == 0) {
// SoftAP MAC addr
wifi_get_macaddr(SOFTAP_IF, mac);
sprintf(buff, MACSTR, MAC2STR(mac));
} else if (strcmp(token, "chipID") == 0) {
// Chip serial number
sprintf(buff, "%08x", system_get_chip_id());
}
httpdSend(connData, buff, -1);
return HTTPD_CGI_DONE;
}

@ -0,0 +1,8 @@
#ifndef PAGE_HOME_H
#define PAGE_HOME_H
#include <httpd.h>
int tplHome(HttpdConnData *connData, char *token, void **arg);
#endif // PAGE_HOME_H

@ -0,0 +1,180 @@
#include <esp8266.h>
#include <sbmp.h>
#include "datalink.h"
#include "sampling.h"
// The buffer is big enough for 256 data bytes - 4*64
// number of 32-bit vars in the chunk
#define CHUNK_LEN_32 64
// chunk size for bulk transfer - 64 floats
#define CHUNK_LEN (CHUNK_LEN_32*4)
static bool acquire_pending = false;
static uint16_t acquire_session;
static ETSTimer prSampleAbortTimer;
static void FLASH_FN prSampleAbortTimerCb(void *arg) {
warn("Sampling aborted due to timeout.");
acquire_pending = false;
// free the data obj if not NULL
sbmp_ep_free_listener_obj(dlnk_ep, acquire_session);
// release the slot
sbmp_ep_remove_listener(dlnk_ep, acquire_session);
}
typedef struct {
uint32_t pos;
uint32_t total;
} DataReadState;
static void FLASH_FN request_data_sesn_listener(SBMP_Endpoint *ep, SBMP_Datagram *dg, void **obj)
{
dbg("Received msg in session %d, dg type %d", dg->session, dg->type);
DataReadState *state = *obj;
// allocate the state struct
if (state == NULL) {
state = malloc(sizeof(DataReadState));
*obj = state;
}
PayloadParser pp;
switch (dg->type) {
case DG_BULK_OFFER:// Data ready notification
info("--- Data offered for bulk transfer ---");
// data is ready to be read
pp = pp_start(dg->payload, dg->length);
state->pos = 0;
state->total = pp_u32(&pp);
dbg("Total bytes: %d", state->total);
sbmp_bulk_request(ep, state->pos, CHUNK_LEN, dg->session); // 64 floats in one message
break;
case DG_BULK_DATA: // data received
info("--- Received a chunk ---");
// Process the received data
pp = pp_start(dg->payload, dg->length);
for (int i = 0; i < dg->length/4; i++) {
float f = pp_float(&pp);
dbg("Rx %.2f", f);
}
// and ask for more
state->pos += dg->length;
if (state->pos >= state->total) {
dbg("Transfer is complete.");
// transfer complete
// make sure the peer has freed the buffer
// (may be waiting for us if we wanted to re-read something)
sbmp_bulk_abort(ep, dg->session);
goto cleanup;
} else {
// read next part
sbmp_bulk_request(ep, state->pos, CHUNK_LEN, dg->session);
}
break;
case DG_BULK_ABORT: // Peer resets the readout
// this is unlikely
warn("Bulk transfer aborted by peer.");
goto cleanup;
}
return;
cleanup:
// free the obj
free(state);
// remove the listener
sbmp_ep_remove_listener(ep, dg->session);
}
static bool FLASH_FN meas_request_data(uint16_t count)
{
info("Requesting data capture - %d samples.", count);
if (acquire_pending) {
error("Acquire request already in progress.");
return false;
}
if (sbmp_ep_handshake_status(dlnk_ep) != SBMP_HSK_SUCCESS) {
error("Hsk status not SUCCESS, can't request data.");
return false;
}
// start the abort timer - timeout
os_timer_disarm(&prSampleAbortTimer);
os_timer_setfn(&prSampleAbortTimer, prSampleAbortTimerCb, NULL);
os_timer_arm(&prSampleAbortTimer, 5000, 0); // 5 seconds, no repeat
// start a message
uint16_t sesn;
bool suc = sbmp_ep_start_message(dlnk_ep, DG_REQUEST_CAPTURE, sizeof(uint16_t), &sesn);
if (!suc) return false;
// register the session listener
sbmp_ep_add_listener(dlnk_ep, sesn, request_data_sesn_listener, NULL);
// request N values
sbmp_ep_send_u16(dlnk_ep, count);
dbg("Request sent, session nr %d", sesn);
acquire_session = sesn;
return true;
}
// ------ C G I ---------
int FLASH_FN cgiReadSamples(HttpdConnData *connData)
{
char buff[128];
if (connData->conn == NULL) {
//Connection aborted. Clean up.
return HTTPD_CGI_DONE;
}
uint16_t count = 1;
int len = httpdFindArg(connData->getArgs, "n", buff, sizeof(buff));
if (len != -1) {
count = (uint16_t)atoi(buff);
}
dbg("User wants %d samples.", count);
meas_request_data(count);
httpdStartResponse(connData, 200);
httpdHeader(connData, "Content-Type", "text/plain");
httpdEndHeaders(connData);
// body
httpdSend(connData, "OK.", -1);
return HTTPD_CGI_DONE;
}

@ -0,0 +1,10 @@
#ifndef SAMPLING_H
#define SAMPLING_H
#include <esp8266.h>
#include <httpd.h>
// temporary func to nread samples
int cgiReadSamples(HttpdConnData *connData);
#endif // SAMPLING_H

@ -17,30 +17,26 @@
//========================================================
void ICACHE_FLASH_ATTR
UART_SetWordLength(UARTn uart_no, UartBitsNum4Char len)
void FLASH_FN 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)
void FLASH_FN 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)
void FLASH_FN 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)
void FLASH_FN 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) {
@ -50,15 +46,13 @@ UART_SetParity(UARTn uart_no, UartParityMode Parity_mode)
}
void ICACHE_FLASH_ATTR
UART_SetBaudrate(UARTn uart_no, uint32 baud_rate)
void FLASH_FN 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)
void FLASH_FN 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);
@ -77,8 +71,7 @@ UART_SetFlowCtrl(UARTn uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh)
}
void ICACHE_FLASH_ATTR
UART_WaitTxFifoEmpty(UARTn uart_no , uint32 time_out_us) //do not use if tx flow control enabled
void FLASH_FN 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)) {
@ -92,8 +85,7 @@ UART_WaitTxFifoEmpty(UARTn uart_no , uint32 time_out_us) //do not use if tx flow
}
bool ICACHE_FLASH_ATTR
UART_CheckOutputFinished(UARTn uart_no, uint32 time_out_us)
bool FLASH_FN UART_CheckOutputFinished(UARTn uart_no, uint32 time_out_us)
{
uint32 t_start = system_get_time();
uint8 tx_fifo_len;
@ -116,23 +108,20 @@ UART_CheckOutputFinished(UARTn uart_no, uint32 time_out_us)
}
void ICACHE_FLASH_ATTR
UART_ResetFifo(UARTn uart_no)
void FLASH_FN 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)
void FLASH_FN 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)
void FLASH_FN UART_SetIntrEna(UARTn uart_no, uint32 ena_mask)
{
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask);
}
@ -150,8 +139,7 @@ LOCAL void u1_putc_crlf(char c)
}
void ICACHE_FLASH_ATTR
UART_SetPrintPort(UARTn uart_no)
void FLASH_FN UART_SetPrintPort(UARTn uart_no)
{
if (uart_no == UART0) {
os_install_putc1((void *)u0_putc_crlf);

@ -27,20 +27,33 @@
#include "uart_driver.h"
#include "uptime.h"
#include "sbmp.h"
#include "page_home.h"
#include "sampling.h"
#define SHOW_HEAP_USE
#include "sbmp.h"
#ifdef SHOW_HEAP_USE
static ETSTimer prHeapTimer;
static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg) {
u32 heap = system_get_free_heap_size();
char upt[20];
uptime_str(upt);
os_printf("Uptime: %s, Heap: %u\n", upt, heap);
/** Timer called each second */
static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg)
{
static u8 cnt = 0;
static u32 last = 0;
if (++cnt == 3) {
cnt = 0;
u32 heap = system_get_free_heap_size();
char upt[20];
uptime_str(upt);
os_printf("%s, heap: %u (~ %d)\n", upt, heap, (heap-last));
last = heap;
}
// we will also try to set up a SBMP connection
if (sbmp_ep_handshake_status(dlnk_ep) != SBMP_HSK_SUCCESS) {
sbmp_ep_start_handshake(dlnk_ep);
}
}
#endif
/**
@ -118,6 +131,8 @@ static HttpdBuiltInUrl builtInUrls[] = {
ROUTE_TPL_FILE("/", tplHome, "/pages/home.tpl"),
ROUTE_CGI("/acquire.cgi", cgiReadSamples),
ROUTE_TPL_FILE("/multipart", tplMultipart, "/multipart.tpl"),
//Enable the line below to protect the WiFi configuration with an username/password combo.
@ -185,16 +200,9 @@ void user_init(void)
info("\nReady\n");
#ifdef SHOW_HEAP_USE
os_timer_disarm(&prHeapTimer);
os_timer_setfn(&prHeapTimer, prHeapTimerCb, NULL);
os_timer_arm(&prHeapTimer, 3000, 1);
#endif
// // print TEST on the command interface every 500 ms
// os_timer_disarm(&prTestTimer);
// os_timer_setfn(&prTestTimer, test_timer_task, NULL);
// os_timer_arm(&prTestTimer, 500, 1);
os_timer_arm(&prHeapTimer, 1000, 1);
}

Loading…
Cancel
Save