Commit 38efa482 authored by Robert Foss's avatar Robert Foss
Browse files

Merge remote-tracking branch 'upstream/dev' into dev

parents d2fc8782 340edbbe
......@@ -61,6 +61,14 @@
#define ROM_MODULES_U8G
#endif
#if defined(LUA_USE_MODULES_UCG)
#define MODULES_UCG "ucg"
#define ROM_MODULES_UCG \
_ROM(MODULES_UCG, luaopen_ucg, lucg_map)
#else
#define ROM_MODULES_UCG
#endif
#if defined(LUA_USE_MODULES_I2C)
#define MODULES_I2C "i2c"
#define ROM_MODULES_I2C \
......@@ -149,6 +157,14 @@
#define ROM_MODULES_WS2812
#endif
#if defined(LUA_USE_MODULES_ENDUSER_SETUP)
#define MODULES_ENDUSER_SETUP "enduser_setup"
#define ROM_MODULES_ENDUSER_SETUP \
_ROM(MODULES_ENDUSER_SETUP, luaopen_enduser_setup, enduser_setup_map)
#else
#define ROM_MODULES_ENDUSER_SETUP
#endif
#if defined(LUA_USE_MODULES_CJSON)
#define MODULES_CJSON "cjson"
#define ROM_MODULES_CJSON \
......@@ -213,6 +229,30 @@
#define ROM_MODULES_SNTP
#endif
#if defined(LUA_USE_MODULES_BMP085)
#define MODULES_BMP085 "bmp085"
#define ROM_MODULES_BMP085 \
_ROM(MODULES_BMP085, luaopen_bmp085, bmp085_map)
#else
#define ROM_MODULES_BMP085
#endif
#if defined(LUA_USE_MODULES_TSL2561)
#define MODULES_TSL2561 "tsl2561"
#define ROM_MODULES_TSL2561 \
_ROM(MODULES_TSL2561, luaopen_tsl2561, tsl2561_map)
#else
#define ROM_MODULES_TSL2561
#endif
#if defined(LUA_USE_MODULES_HX711)
#define MODULES_HX711 "hx711"
#define ROM_MODULES_HX711 \
_ROM(MODULES_HX711, luaopen_hx711, hx711_map)
#else
#define ROM_MODULES_HX711
#endif
#define LUA_MODULES_ROM \
ROM_MODULES_GPIO \
ROM_MODULES_PWM \
......@@ -220,6 +260,7 @@
ROM_MODULES_COAP \
ROM_MODULES_MQTT \
ROM_MODULES_U8G \
ROM_MODULES_UCG \
ROM_MODULES_I2C \
ROM_MODULES_SPI \
ROM_MODULES_TMR \
......@@ -230,6 +271,7 @@
ROM_MODULES_UART \
ROM_MODULES_OW \
ROM_MODULES_BIT \
ROM_MODULES_ENDUSER_SETUP \
ROM_MODULES_WS2801 \
ROM_MODULES_WS2812 \
ROM_MODULES_CJSON \
......@@ -240,5 +282,8 @@
ROM_MODULES_RTCTIME \
ROM_MODULES_RTCFIFO \
ROM_MODULES_SNTP \
ROM_MODULES_BMP085 \
ROM_MODULES_TSL2561 \
ROM_MODULES_HX711
#endif
......@@ -12,6 +12,7 @@
#include "c_types.h"
#include "mem.h"
#include "lwip/ip_addr.h"
#include "espconn.h"
#include "mqtt_msg.h"
......@@ -65,9 +66,11 @@ typedef struct lmqtt_userdata
int cb_puback_ref;
mqtt_state_t mqtt_state;
mqtt_connect_info_t connect_info;
uint32_t keep_alive_tick;
uint16_t keep_alive_tick;
uint32_t event_timeout;
#ifdef CLIENT_SSL_ENABLE
uint8_t secure;
#endif
bool connected; // indicate socket connected, not mqtt prot connected.
ETSTimer mqttTimer;
tConnState connState;
......@@ -228,10 +231,16 @@ READPACKET:
if(mqtt_get_type(in_buffer) != MQTT_MSG_TYPE_CONNACK){
NODE_DBG("MQTT: Invalid packet\r\n");
mud->connState = MQTT_INIT;
#ifdef CLIENT_SSL_ENABLE
if(mud->secure)
{
espconn_secure_disconnect(pesp_conn);
}
else
#endif
{
espconn_disconnect(pesp_conn);
}
} else {
mud->connState = MQTT_DATA;
NODE_DBG("MQTT: Connected\r\n");
......@@ -386,12 +395,17 @@ READPACKET:
if(node && (1==msg_size(&(mud->mqtt_state.pending_msg_q))) && mud->event_timeout == 0){
mud->event_timeout = MQTT_SEND_TIMEOUT;
NODE_DBG("Sent: %d\n", node->msg.length);
#ifdef CLIENT_SSL_ENABLE
if( mud->secure )
{
espconn_secure_sent( pesp_conn, node->msg.data, node->msg.length );
}
else
#endif
{
espconn_sent( pesp_conn, node->msg.data, node->msg.length );
}
mud->keep_alive_tick = 0;
}
NODE_DBG("receive, queue size: %d\n", msg_size(&(mud->mqtt_state.pending_msg_q)));
NODE_DBG("leave mqtt_socket_received.\n");
return;
......@@ -431,7 +445,7 @@ static void mqtt_socket_sent(void *arg)
lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->cb_puback_ref);
lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->self_ref); // pass the userdata to callback func in lua
lua_call(mud->L, 1, 0);
} else if(node && node->msg_type == MQTT_MSG_TYPE_PUBACK && node->publish_qos == 1) {
} else if(node && node->msg_type == MQTT_MSG_TYPE_PUBACK) {
msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q)));
} else if(node && node->msg_type == MQTT_MSG_TYPE_PUBCOMP) {
msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q)));
......@@ -463,10 +477,16 @@ static void mqtt_socket_connected(void *arg)
NODE_DBG("Send MQTT connection infomation, data len: %d, d[0]=%d \r\n", temp_msg->length, temp_msg->data[0]);
mud->event_timeout = MQTT_SEND_TIMEOUT;
// not queue this message. should send right now. or should enqueue this before head.
#ifdef CLIENT_SSL_ENABLE
if(mud->secure)
{
espconn_secure_sent(pesp_conn, temp_msg->data, temp_msg->length);
}
else
#endif
{
espconn_sent(pesp_conn, temp_msg->data, temp_msg->length);
}
mud->keep_alive_tick = 0;
mud->connState = MQTT_CONNECT_SENDING;
......@@ -508,10 +528,16 @@ void mqtt_socket_timer(void *arg)
} else if(mud->connState == MQTT_CONNECT_SENDING){ // MQTT_CONNECT send time out.
NODE_DBG("sSend MQTT_CONNECT failed.\n");
mud->connState = MQTT_INIT;
#ifdef CLIENT_SSL_ENABLE
if(mud->secure)
{
espconn_secure_disconnect(mud->pesp_conn);
}
else
#endif
{
espconn_disconnect(mud->pesp_conn);
}
mud->keep_alive_tick = 0; // not need count anymore
} else if(mud->connState == MQTT_CONNECT_SENT){ // wait for CONACK time out.
NODE_DBG("MQTT_CONNECT failed.\n");
......@@ -519,10 +545,16 @@ void mqtt_socket_timer(void *arg)
msg_queue_t *pending_msg = msg_peek(&(mud->mqtt_state.pending_msg_q));
if(pending_msg){
mud->event_timeout = MQTT_SEND_TIMEOUT;
#ifdef CLIENT_SSL_ENABLE
if(mud->secure)
{
espconn_secure_sent(mud->pesp_conn, pending_msg->msg.data, pending_msg->msg.length);
}
else
#endif
{
espconn_sent(mud->pesp_conn, pending_msg->msg.data, pending_msg->msg.length);
}
mud->keep_alive_tick = 0;
NODE_DBG("id: %d - qos: %d, length: %d\n", pending_msg->msg_id, pending_msg->publish_qos, pending_msg->msg.length);
} else {
......@@ -537,18 +569,25 @@ void mqtt_socket_timer(void *arg)
msg_queue_t *node = msg_enqueue( &(mud->mqtt_state.pending_msg_q), temp_msg,
0, MQTT_MSG_TYPE_PINGREQ, (int)mqtt_get_qos(temp_msg->data) );
// only one message in queue, send immediately.
#ifdef CLIENT_SSL_ENABLE
if(mud->secure)
{
espconn_secure_sent(mud->pesp_conn, temp_msg->data, temp_msg->length);
}
else
#endif
{
espconn_sent(mud->pesp_conn, temp_msg->data, temp_msg->length);
}
mud->keep_alive_tick = 0;
}
}
}
NODE_DBG("keep_alive_tick: %d\n", mud->keep_alive_tick);
NODE_DBG("leave mqtt_socket_timer.\n");
}
// Lua: mqtt.Client(clientid, keepalive, user, pass)
// Lua: mqtt.Client(clientid, keepalive, user, pass, clean_session)
static int mqtt_socket_client( lua_State* L )
{
NODE_DBG("enter mqtt_socket_client.\n");
......@@ -564,7 +603,7 @@ static int mqtt_socket_client( lua_State* L )
size_t unl = 0, pwl = 0;
int keepalive = 0;
int stack = 1;
unsigned secure = 0;
int clean_session = 1;
int top = lua_gettop(L);
// create a object
......@@ -579,7 +618,9 @@ static int mqtt_socket_client( lua_State* L )
mud->cb_suback_ref = LUA_NOREF;
mud->cb_puback_ref = LUA_NOREF;
mud->pesp_conn = NULL;
#ifdef CLIENT_SSL_ENABLE
mud->secure = 0;
#endif
mud->keep_alive_tick = 0;
mud->event_timeout = 0;
......@@ -627,6 +668,16 @@ static int mqtt_socket_client( lua_State* L )
pwl = 0;
NODE_DBG("lengh password: %d\r\n", pwl);
if(lua_isnumber( L, stack ))
{
clean_session = luaL_checkinteger( L, stack);
stack++;
}
if(clean_session > 1){
clean_session = 1;
}
// TODO: check the zalloc result.
mud->connect_info.client_id = (uint8_t *)c_zalloc(idl+1);
mud->connect_info.username = (uint8_t *)c_zalloc(unl + 1);
......@@ -656,7 +707,7 @@ static int mqtt_socket_client( lua_State* L )
NODE_DBG("MQTT: Init info: %s, %s, %s\r\n", mud->connect_info.client_id, mud->connect_info.username, mud->connect_info.password);
mud->connect_info.clean_session = 1;
mud->connect_info.clean_session = clean_session;
mud->connect_info.will_qos = 0;
mud->connect_info.will_retain = 0;
mud->connect_info.keepalive = keepalive;
......@@ -766,10 +817,16 @@ static void socket_connect(struct espconn *pesp_conn)
mud->event_timeout = MQTT_CONNECT_TIMEOUT;
mud->connState = MQTT_INIT;
#ifdef CLIENT_SSL_ENABLE
if(mud->secure)
{
espconn_secure_connect(pesp_conn);
}
else
#endif
{
espconn_connect(pesp_conn);
}
os_timer_arm(&mud->mqttTimer, 1000, 1);
......@@ -902,7 +959,14 @@ static int mqtt_socket_connect( lua_State* L )
} else {
secure = 0; // default to 0
}
#ifdef CLIENT_SSL_ENABLE
mud->secure = secure; // save
#else
if ( secure )
{
return luaL_error(L, "ssl not available");
}
#endif
if ( (stack<=top) && lua_isnumber(L, stack) )
{
......@@ -970,14 +1034,25 @@ static int mqtt_socket_close( lua_State* L )
if(mud->pesp_conn == NULL)
return 0;
// call mqtt_disconnect()
// Send disconnect message
mqtt_message_t* temp_msg = mqtt_msg_disconnect(&mud->mqtt_state.mqtt_connection);
NODE_DBG("Send MQTT disconnect infomation, data len: %d, d[0]=%d \r\n", temp_msg->length, temp_msg->data[0]);
#ifdef CLIENT_SSL_ENABLE
if(mud->secure)
espconn_secure_sent(mud->pesp_conn, temp_msg->data, temp_msg->length);
else
#endif
espconn_sent(mud->pesp_conn, temp_msg->data, temp_msg->length);
mud->mqtt_state.auto_reconnect = 0; // stop auto reconnect.
#ifdef CLIENT_SSL_ENABLE
if(mud->secure){
if(mud->pesp_conn->proto.tcp->remote_port || mud->pesp_conn->proto.tcp->local_port)
espconn_secure_disconnect(mud->pesp_conn);
}
else
#endif
{
if(mud->pesp_conn->proto.tcp->remote_port || mud->pesp_conn->proto.tcp->local_port)
espconn_disconnect(mud->pesp_conn);
......@@ -1126,10 +1201,16 @@ static int mqtt_socket_subscribe( lua_State* L ) {
if(node && (1==msg_size(&(mud->mqtt_state.pending_msg_q))) && mud->event_timeout == 0){
mud->event_timeout = MQTT_SEND_TIMEOUT;
NODE_DBG("Sent: %d\n", node->msg.length);
#ifdef CLIENT_SSL_ENABLE
if( mud->secure )
{
espconn_secure_sent( mud->pesp_conn, node->msg.data, node->msg.length );
}
else
#endif
{
espconn_sent( mud->pesp_conn, node->msg.data, node->msg.length );
}
mud->keep_alive_tick = 0;
}
......@@ -1208,10 +1289,16 @@ static int mqtt_socket_publish( lua_State* L )
if(node && (1==msg_size(&(mud->mqtt_state.pending_msg_q))) && mud->event_timeout == 0){
mud->event_timeout = MQTT_SEND_TIMEOUT;
NODE_DBG("Sent: %d\n", node->msg.length);
#ifdef CLIENT_SSL_ENABLE
if( mud->secure )
{
espconn_secure_sent( mud->pesp_conn, node->msg.data, node->msg.length );
}
else
#endif
{
espconn_sent( mud->pesp_conn, node->msg.data, node->msg.length );
}
mud->keep_alive_tick = 0;
}
......@@ -1256,7 +1343,7 @@ static int mqtt_socket_lwt( lua_State* L )
{
return luaL_error( L, "need lwt message");
}
stack++;
if(mud->connect_info.will_topic){ // free the previous one if there is any
c_free(mud->connect_info.will_topic);
mud->connect_info.will_topic = NULL;
......
......@@ -12,6 +12,7 @@
#include "c_types.h"
#include "mem.h"
#include "lwip/ip_addr.h"
#include "espconn.h"
#include "lwip/dns.h"
......@@ -1076,6 +1077,16 @@ static int net_send( lua_State* L, const char* mt )
luaL_unref(L, LUA_REGISTRYINDEX, nud->cb_send_ref);
nud->cb_send_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
// SDK 1.4.0 changed behaviour, for UDP server need to look up remote ip/port
if (isserver && pesp_conn->type == ESPCONN_UDP)
{
remot_info *pr = 0;
if (espconn_get_connection_info (pesp_conn, &pr, 0) != ESPCONN_OK)
return luaL_error (L, "remote ip/port unavailable");
pesp_conn->proto.udp->remote_port = pr->remote_port;
os_memmove (pesp_conn->proto.udp->remote_ip, pr->remote_ip, 4);
// The remot_info apparently should *not* be os_free()d, fyi
}
#ifdef CLIENT_SSL_ENABLE
if(nud->secure)
espconn_secure_sent(pesp_conn, (unsigned char *)payload, l);
......
......@@ -3,10 +3,13 @@
#include "lua.h"
#include "lauxlib.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lopcodes.h"
#include "lstring.h"
#include "lundump.h"
......@@ -145,39 +148,17 @@ static int node_heap( lua_State* L )
static lua_State *gL = NULL;
#ifdef DEVKIT_VERSION_0_9
extern int led_high_count; // this is defined in lua.c
extern int led_low_count;
// Lua: led(low, high)
static int node_led( lua_State* L )
{
int low, high;
if ( lua_isnumber(L, 1) )
{
low = lua_tointeger(L, 1);
if ( low < 0 ) {
return luaL_error( L, "wrong arg type" );
}
} else {
low = LED_LOW_COUNT_DEFAULT; // default to LED_LOW_COUNT_DEFAULT
}
if ( lua_isnumber(L, 2) )
{
high = lua_tointeger(L, 2);
if ( high < 0 ) {
return luaL_error( L, "wrong arg type" );
}
} else {
high = LED_HIGH_COUNT_DEFAULT; // default to LED_HIGH_COUNT_DEFAULT
}
led_high_count = (uint32_t)high / READLINE_INTERVAL;
led_low_count = (uint32_t)low / READLINE_INTERVAL;
return 0;
}
static int led_high_count = LED_HIGH_COUNT_DEFAULT;
static int led_low_count = LED_LOW_COUNT_DEFAULT;
static int led_count = 0;
static int key_press_count = 0;
static bool key_short_pressed = false;
static bool key_long_pressed = false;
static os_timer_t keyled_timer;
static int long_key_ref = LUA_NOREF;
static int short_key_ref = LUA_NOREF;
void default_long_press(void *arg) {
static void default_long_press(void *arg) {
if (led_high_count == 12 && led_low_count == 12) {
led_low_count = led_high_count = 6;
} else {
......@@ -188,11 +169,11 @@ void default_long_press(void *arg) {
// NODE_DBG("default_long_press is called. hc: %d, lc: %d\n", led_high_count, led_low_count);
}
void default_short_press(void *arg) {
static void default_short_press(void *arg) {
system_restart();
}
void key_long_press(void *arg) {
static void key_long_press(void *arg) {
NODE_DBG("key_long_press is called.\n");
if (long_key_ref == LUA_NOREF) {
default_long_press(arg);
......@@ -204,7 +185,7 @@ void key_long_press(void *arg) {
lua_call(gL, 0, 0);
}
void key_short_press(void *arg) {
static void key_short_press(void *arg) {
NODE_DBG("key_short_press is called.\n");
if (short_key_ref == LUA_NOREF) {
default_short_press(arg);
......@@ -216,6 +197,78 @@ void key_short_press(void *arg) {
lua_call(gL, 0, 0);
}
static void update_key_led (void *p)
{
(void)p;
uint8_t temp = 1, level = 1;
led_count++;
if(led_count>led_low_count+led_high_count){
led_count = 0; // reset led_count, the level still high
} else if(led_count>led_low_count && led_count <=led_high_count+led_low_count){
level = 1; // output high level
} else if(led_count<=led_low_count){
level = 0; // output low level
}
temp = platform_key_led(level);
if(temp == 0){ // key is pressed
key_press_count++;
if(key_press_count>=KEY_LONG_COUNT){
// key_long_press(NULL);
key_long_pressed = true;
key_short_pressed = false;
// key_press_count = 0;
} else if(key_press_count>=KEY_SHORT_COUNT){ // < KEY_LONG_COUNT
// key_short_press(NULL);
key_short_pressed = true;
}
}else{ // key is released
key_press_count = 0;
if(key_long_pressed){
key_long_press(NULL);
key_long_pressed = false;
}
if(key_short_pressed){
key_short_press(NULL);
key_short_pressed = false;
}
}
}
static void prime_keyled_timer (void)
{
os_timer_disarm (&keyled_timer);
os_timer_setfn (&keyled_timer, update_key_led, 0);
os_timer_arm (&keyled_timer, KEYLED_INTERVAL, 1);
}
// Lua: led(low, high)
static int node_led( lua_State* L )
{
int low, high;
if ( lua_isnumber(L, 1) )
{
low = lua_tointeger(L, 1);
if ( low < 0 ) {
return luaL_error( L, "wrong arg type" );
}
} else {
low = LED_LOW_COUNT_DEFAULT; // default to LED_LOW_COUNT_DEFAULT
}
if ( lua_isnumber(L, 2) )
{
high = lua_tointeger(L, 2);
if ( high < 0 ) {
return luaL_error( L, "wrong arg type" );
}
} else {
high = LED_HIGH_COUNT_DEFAULT; // default to LED_HIGH_COUNT_DEFAULT
}
led_high_count = (uint32_t)high / READLINE_INTERVAL;
led_low_count = (uint32_t)low / READLINE_INTERVAL;
prime_keyled_timer();
return 0;
}
// Lua: key(type, function)
static int node_key( lua_State* L )
{
......@@ -246,13 +299,12 @@ static int node_key( lua_State* L )
*ref = LUA_NOREF;
}
prime_keyled_timer();
return 0;
}
#endif
extern lua_Load gLoad;
extern os_timer_t lua_timer;
extern void dojob(lua_Load *load);
// Lua: input("string")
static int node_input( lua_State* L )
{
......@@ -269,9 +321,7 @@ static int node_input( lua_State* L )
NODE_DBG("Get command:\n");
NODE_DBG(load->line); // buggy here
NODE_DBG("\nResult(if any):\n");
os_timer_disarm(&lua_timer);
os_timer_setfn(&lua_timer, (os_timer_func_t *)dojob, load);
os_timer_arm(&lua_timer, READLINE_INTERVAL, 0); // no repeat
system_os_post (LUA_TASK_PRIO, LUA_PROCESS_LINE_SIG, 0);
}
}
return 0;
......@@ -382,7 +432,10 @@ static int node_compile( lua_State* L )
int result = luaU_dump(L, f, writer, &file_fd, stripping);
lua_unlock(L);
fs_flush(file_fd);
if (fs_flush(file_fd) < 0) { // result codes aren't propagated by flash_fs.h
// overwrite Lua error, like writer() does in case of a file io error
result = 1;
}
fs_close(file_fd);
file_fd = FS_OPEN_OK - 1;
......@@ -392,6 +445,9 @@ static int node_compile( lua_State* L )
if (result == LUA_ERR_CC_NOTINTEGER) {
return luaL_error(L, "target lua_Number is integral but fractional value found");
}
if (result == 1) { // result status generated by writer() or fs_flush() fail
return luaL_error(L, "writing to file failed");
}
return 0;
}
......@@ -404,10 +460,10 @@ static int node_setcpufreq(lua_State* L)
uint32_t new_freq = luaL_checkinteger(L, 1);
if (new_freq == CPU160MHZ){
REG_SET_BIT(0x3ff00014, BIT(0));
os_update_cpu_frequency(CPU160MHZ);
ets_update_cpu_frequency(CPU160MHZ);
} else {
REG_CLR_BIT(0x3ff00014, BIT(0));
os_update_cpu_frequency(CPU80MHZ);
ets_update_cpu_frequency(CPU80MHZ);
}
new_freq = ets_get_cpu_frequency();
lua_pushinteger(L, new_freq);
......@@ -430,6 +486,69 @@ static int node_restore (lua_State *L)
return 0;
}
#ifdef LUA_OPTIMIZE_DEBUG
/* node.stripdebug([level[, function]]). 
* level: 1 don't discard debug
* 2 discard Local and Upvalue debug info
* 3 discard Local, Upvalue and lineno debug info.
* function: Function to be stripped as per setfenv except 0 not permitted.
* If no arguments then the current default setting is returned.
* If function is omitted, this is the default setting for future compiles
* The function returns an estimated integer count of the bytes stripped.
*/
static int node_stripdebug (lua_State *L) {
int level;
if (L->top == L->base) {
lua_pushlightuserdata(L, &luaG_stripdebug );
lua_gettable(L, LUA_REGISTRYINDEX);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
lua_pushinteger(L, LUA_OPTIMIZE_DEBUG);
}
return 1;
}
level = luaL_checkint(L, 1);
if ((level <= 0) || (level > 3)) luaL_argerror(L, 1, "must in range 1-3");
if (L->top == L->base + 1) {
/* Store the default level in the registry if no function parameter */
lua_pushlightuserdata(L, &luaG_stripdebug);
lua_pushinteger(L, level);
lua_settable(L, LUA_REGISTRYINDEX);
lua_settop(L,0);
return 0;
}
if (level == 1) {
lua_settop(L,0);
lua_pushinteger(L, 0);
return 1;
}
if (!lua_isfunction(L, 2)) {
int scope = luaL_checkint(L, 2);
if (scope > 0) {
/* if the function parameter is a +ve integer then climb to find function */
lua_Debug ar;
lua_pop(L, 1); /* pop level as getinfo will replace it by the function */
if (lua_getstack(L, scope, &ar)) {
lua_getinfo(L, "f", &ar);
}
}
}
if(!lua_isfunction(L, 2) || lua_iscfunction(L, -1)) luaL_argerror(L, 2, "must be a Lua Function");
// lua_lock(L);
Proto *f = clvalue(L->base + 1)->l.p;
// lua_unlock(L);
lua_settop(L,0);
lua_pushinteger(L, luaG_stripdebug(L, f, level, 1));
return 1;
}
#endif
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
......@@ -456,6 +575,10 @@ const LUA_REG_TYPE node_map[] =
{ LSTRKEY( "setcpufreq" ), LFUNCVAL( node_setcpufreq) },
{ LSTRKEY( "bootreason" ), LFUNCVAL( node_bootreason) },
{ LSTRKEY( "restore" ), LFUNCVAL( node_restore) },
#ifdef LUA_OPTIMIZE_DEBUG
{ LSTRKEY( "stripdebug" ), LFUNCVAL( node_stripdebug ) },
#endif
// Combined to dsleep(us, option)
// { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) },
#if LUA_OPTIMIZE_MEMORY > 0
......
......@@ -7,15 +7,22 @@
#include "auxmods.h"
#include "lrotable.h"
// Lua: = spi.setup( id, mode, cpol, cpha, databits, clock )
#define SPI_HALFDUPLEX 0
#define SPI_FULLDUPLEX 1
static u8 spi_databits[NUM_SPI] = {0, 0};
static u8 spi_duplex[NUM_SPI] = {SPI_HALFDUPLEX, SPI_HALFDUPLEX};
// Lua: = spi.setup( id, mode, cpol, cpha, databits, clock_div, [duplex_mode] )
static int spi_setup( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
unsigned mode = luaL_checkinteger( L, 2 );
unsigned cpol = luaL_checkinteger( L, 3 );
unsigned cpha = luaL_checkinteger( L, 4 );
unsigned databits = luaL_checkinteger( L, 5 );
uint32_t clock = luaL_checkinteger( L, 6 );
int id = luaL_checkinteger( L, 1 );
int mode = luaL_checkinteger( L, 2 );
int cpol = luaL_checkinteger( L, 3 );
int cpha = luaL_checkinteger( L, 4 );
int databits = luaL_checkinteger( L, 5 );
u32 clock_div = luaL_checkinteger( L, 6 );
int duplex_mode = luaL_optinteger( L, 7, SPI_HALFDUPLEX );
MOD_CHECK_ID( spi, id );
......@@ -31,81 +38,150 @@ static int spi_setup( lua_State *L )
return luaL_error( L, "wrong arg type" );
}
if (databits != PLATFORM_SPI_DATABITS_8 && databits != PLATFORM_SPI_DATABITS_16) {
return luaL_error( L, "wrong arg type" );
if (databits < 0 || databits > 32) {
return luaL_error( L, "out of range" );
}
u32 res = platform_spi_setup(id, mode, cpol, cpha, databits, clock);
if (clock_div < 4) {
// defaulting to 8
clock_div = 8;
}
if (duplex_mode == SPI_HALFDUPLEX || duplex_mode == SPI_FULLDUPLEX)
{
spi_duplex[id] = duplex_mode;
}
else
{
return luaL_error( L, "out of range" );
}
spi_databits[id] = databits;
u32 res = platform_spi_setup(id, mode, cpol, cpha, clock_div);
lua_pushinteger( L, res );
return 1;
}
// Half-duplex mode:
// Lua: wrote = spi.send( id, data1, [data2], ..., [datan] )
// Full-duplex mode:
// Lua: wrote, [data1], ..., [datan] = spi.send_recv( id, data1, [data2], ..., [datan] )
// data can be either a string, a table or an 8-bit number
static int spi_send( lua_State *L )
static int spi_send_recv( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
const char *pdata;
size_t datalen, i;
int numdata;
u32 numdata;
u32 wrote = 0;
unsigned argn;
int pushed = 1;
unsigned argn, tos;
u8 recv = spi_duplex[id] == SPI_FULLDUPLEX ? 1 : 0;
MOD_CHECK_ID( spi, id );
if( lua_gettop( L ) < 2 )
if( (tos = lua_gettop( L )) < 2 )
return luaL_error( L, "wrong arg type" );
for( argn = 2; argn <= lua_gettop( L ); argn ++ )
// prepare first returned item 'wrote' - value is yet unknown
// position on stack is tos+1
lua_pushinteger( L, 0 );
for( argn = 2; argn <= tos; argn ++ )
{
// *** Send integer value and return received data as integer ***
// lua_isnumber() would silently convert a string of digits to an integer
// whereas here strings are handled separately.
if( lua_type( L, argn ) == LUA_TNUMBER )
{
numdata = ( int )luaL_checkinteger( L, argn );
if( numdata < 0 || numdata > 255 )
return luaL_error( L, "wrong arg range" );
platform_spi_send_recv( id, numdata );
numdata = luaL_checkinteger( L, argn );
if (recv > 0)
{
lua_pushinteger( L, platform_spi_send_recv( id, spi_databits[id], numdata ) );
pushed ++;
}
else
{
platform_spi_send( id, spi_databits[id], numdata );
}
wrote ++;
}
// *** Send table elements and return received data items as a table ***
else if( lua_istable( L, argn ) )
{
datalen = lua_objlen( L, argn );
if (recv > 0 && datalen > 0) {
// create a table for the received data
lua_createtable( L, datalen, 0 );
pushed ++;
}
for( i = 0; i < datalen; i ++ )
{
lua_rawgeti( L, argn, i + 1 );
numdata = ( int )luaL_checkinteger( L, -1 );
numdata = luaL_checkinteger( L, -1 );
lua_pop( L, 1 );
if( numdata < 0 || numdata > 255 )
return luaL_error( L, "wrong arg range" );
platform_spi_send_recv( id, numdata );
if (recv > 0) {
lua_pushinteger( L, platform_spi_send_recv( id, spi_databits[id], numdata ) );
lua_rawseti( L, -2, i + 1 );
}
else
{
platform_spi_send( id, spi_databits[id], numdata );
}
}
wrote += i;
if( i < datalen )
break;
}
// *** Send characters of a string and return received data items as string ***
else
{
luaL_Buffer b;
pdata = luaL_checklstring( L, argn, &datalen );
if (recv > 0) {
luaL_buffinit( L, &b );
}
for( i = 0; i < datalen; i ++ )
platform_spi_send_recv( id, pdata[ i ] );
{
if (recv > 0)
{
luaL_addchar( &b, (char)platform_spi_send_recv( id, spi_databits[id], pdata[ i ] ) );
}
else
{
platform_spi_send( id, spi_databits[id], pdata[ i ] );
}
}
if (recv > 0 && datalen > 0) {
luaL_pushresult( &b );
pushed ++;
}
wrote += i;
if( i < datalen )
break;
}
}
// update item 'wrote' on stack
lua_pushinteger( L, wrote );
return 1;
lua_replace( L, tos+1 );
return pushed;
}
// Lua: read = spi.recv( id, size )
// Lua: read = spi.recv( id, size, [default data] )
static int spi_recv( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
u32 size = ( u32 )luaL_checkinteger( L, 2 ), i;
int id = luaL_checkinteger( L, 1 );
int size = luaL_checkinteger( L, 2 ), i;
int def = luaL_optinteger( L, 3, 0xffffffff );
luaL_Buffer b;
spi_data_type data;
MOD_CHECK_ID( spi, id );
if (size == 0) {
......@@ -113,23 +189,136 @@ static int spi_recv( lua_State *L )
}
luaL_buffinit( L, &b );
for (i=0; i<size; i++) {
data = platform_spi_send_recv(id, 0xFF);
luaL_addchar( &b, ( char )data);
for (i=0; i<size; i++)
{
luaL_addchar( &b, ( char )platform_spi_send_recv( id, spi_databits[id], def ) );
}
luaL_pushresult( &b );
return 1;
}
// Lua: spi.set_mosi( id, offset, bitlen, data1, [data2], ..., [datan] )
static int spi_set_mosi( lua_State *L )
{
int id = luaL_checkinteger( L, 1 );
int offset = luaL_checkinteger( L, 2 );
int bitlen = luaL_checkinteger( L, 3 );
int argn;
MOD_CHECK_ID( spi, id );
if (offset < 0 || offset > 511) {
return luaL_error( L, "offset out of range" );
}
if (bitlen < 1 || bitlen > 32) {
return luaL_error( L, "bitlen out of range" );
}
if (lua_gettop( L ) < 4) {
return luaL_error( L, "too few args" );
}
for (argn = 4; argn <= lua_gettop( L ); argn++, offset += bitlen )
{
u32 data = ( u32 )luaL_checkinteger(L, argn );
if (offset + bitlen > 512) {
return luaL_error( L, "data range exceeded > 512 bits" );
}
if (PLATFORM_OK != platform_spi_set_mosi( id, offset, bitlen, data )) {
return luaL_error( L, "failed" );
}
}
return 0;
}
// Lua: data = spi.get_miso( id, offset, bitlen, num )
static int spi_get_miso( lua_State *L )
{
int id = luaL_checkinteger( L, 1 );
int offset = luaL_checkinteger( L, 2 );
int bitlen = luaL_checkinteger( L, 3 );
int num = luaL_checkinteger( L, 4 ), i;
MOD_CHECK_ID( spi, id );
if (offset < 0 || offset > 511) {
return luaL_error( L, "out of range" );
}
if (bitlen < 1 || bitlen > 32) {
return luaL_error( L, "bitlen out of range" );
}
if (offset + bitlen * num > 512) {
return luaL_error( L, "out of range" );
}
for (i = 0; i < num; i++)
{
lua_pushinteger( L, platform_spi_get_miso( id, offset + (bitlen * i), bitlen ) );
}
return num;
}
// Lua: spi.transaction( id, cmd_bitlen, cmd_data, addr_bitlen, addr_data, mosi_bitlen, dummy_bitlen, miso_bitlen )
static int spi_transaction( lua_State *L )
{
int id = luaL_checkinteger( L, 1 );
int cmd_bitlen = luaL_checkinteger( L, 2 );
u16 cmd_data = ( u16 )luaL_checkinteger( L, 3 );
int addr_bitlen = luaL_checkinteger( L, 4 );
u32 addr_data = ( u32 )luaL_checkinteger( L, 5 );
int mosi_bitlen = luaL_checkinteger( L, 6 );
int dummy_bitlen = luaL_checkinteger( L, 7 );
int miso_bitlen = luaL_checkinteger( L, 8 );
MOD_CHECK_ID( spi, id );
if (cmd_bitlen < 0 || cmd_bitlen > 16) {
return luaL_error( L, "cmd_bitlen out of range" );
}
if (addr_bitlen < 0 || addr_bitlen > 32) {
return luaL_error( L, "addr_bitlen out of range" );
}
if (mosi_bitlen < 0 || mosi_bitlen > 512) {
return luaL_error( L, "mosi_bitlen out of range" );
}
if (dummy_bitlen < 0 || dummy_bitlen > 256) {
return luaL_error( L, "dummy_bitlen out of range" );
}
if (miso_bitlen < -512 || miso_bitlen > 511) {
return luaL_error( L, "miso_bitlen out of range" );
}
if (PLATFORM_OK != platform_spi_transaction( id, cmd_bitlen, cmd_data, addr_bitlen, addr_data,
mosi_bitlen, dummy_bitlen, miso_bitlen) ) {
return luaL_error( L, "failed" );
}
return 0;
}
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const LUA_REG_TYPE spi_map[] =
{
{ LSTRKEY( "setup" ), LFUNCVAL( spi_setup ) },
{ LSTRKEY( "send" ), LFUNCVAL( spi_send ) },
{ LSTRKEY( "send" ), LFUNCVAL( spi_send_recv ) },
{ LSTRKEY( "recv" ), LFUNCVAL( spi_recv ) },
{ LSTRKEY( "set_mosi" ), LFUNCVAL( spi_set_mosi ) },
{ LSTRKEY( "get_miso" ), LFUNCVAL( spi_get_miso ) },
{ LSTRKEY( "transaction" ), LFUNCVAL( spi_transaction ) },
#if LUA_OPTIMIZE_MEMORY > 0
{ LSTRKEY( "MASTER" ), LNUMVAL( PLATFORM_SPI_MASTER ) },
{ LSTRKEY( "SLAVE" ), LNUMVAL( PLATFORM_SPI_SLAVE) },
......@@ -137,8 +326,9 @@ const LUA_REG_TYPE spi_map[] =
{ LSTRKEY( "CPHA_HIGH" ), LNUMVAL( PLATFORM_SPI_CPHA_HIGH) },
{ LSTRKEY( "CPOL_LOW" ), LNUMVAL( PLATFORM_SPI_CPOL_LOW) },
{ LSTRKEY( "CPOL_HIGH" ), LNUMVAL( PLATFORM_SPI_CPOL_HIGH) },
{ LSTRKEY( "DATABITS_8" ), LNUMVAL( PLATFORM_SPI_DATABITS_8) },
{ LSTRKEY( "DATABITS_16" ), LNUMVAL( PLATFORM_SPI_DATABITS_16) },
{ LSTRKEY( "DATABITS_8" ), LNUMVAL( 8 ) },
{ LSTRKEY( "HALFDUPLEX" ), LNUMVAL( SPI_HALFDUPLEX ) },
{ LSTRKEY( "FULLDUPLEX" ), LNUMVAL( SPI_FULLDUPLEX ) },
#endif // #if LUA_OPTIMIZE_MEMORY > 0
{ LNILKEY, LNILVAL }
};
......@@ -157,10 +347,10 @@ LUALIB_API int luaopen_spi( lua_State *L )
MOD_REG_NUMBER( L, "CPHA_HIGH", PLATFORM_SPI_CPHA_HIGH);
MOD_REG_NUMBER( L, "CPOL_LOW" , PLATFORM_SPI_CPOL_LOW);
MOD_REG_NUMBER( L, "CPOL_HIGH", PLATFORM_SPI_CPOL_HIGH);
MOD_REG_NUMBER( L, "DATABITS_8" , PLATFORM_SPI_DATABITS_8);
MOD_REG_NUMBER( L, "DATABITS_16" , PLATFORM_SPI_DATABITS_16);
MOD_REG_NUMBER( L, "DATABITS_8", 8 );
MOD_REG_NUMBER( L, "HALFDUPLEX", SPI_HALFDUPLEX );
MOD_REG_NUMBER( L, "FULLDUPLEX", SPI_FULLDUPLEX );
return 1;
#endif // #if LUA_OPTIMIZE_MEMORY > 0
}
......@@ -76,6 +76,7 @@ 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();
//in fact lua_State is constant, it's pointless to pass it around
//but hey, whatever, I'll just pass it, still we waste 28B here
......@@ -121,11 +122,11 @@ static int tmr_delay( lua_State* L ){
while(us >= 1000000){
us -= 1000000;
os_delay_us(1000000);
WRITE_PERI_REG(0x60000914, 0x73);
system_soft_wdt_feed ();
}
if(us>0){
os_delay_us(us);
WRITE_PERI_REG(0x60000914, 0x73);
system_soft_wdt_feed ();
}
return 0;
}
......@@ -256,7 +257,7 @@ why they are here*/
// extern void update_key_led();
// Lua: tmr.wdclr()
static int tmr_wdclr( lua_State* L ){
WRITE_PERI_REG(0x60000914, 0x73);
system_soft_wdt_feed ();
// update_key_led();
return 0;
}
......
/*
* tsl2561.c
*
* Created on: Aug 21, 2015
* Author: Michael Lucas (Aeprox @github)
*/
#include "lualib.h"
#include "lauxlib.h"
#include "platform.h"
#include "auxmods.h"
#include "lrotable.h"
#include "../tsl2561/tsl2561.h"
static uint16_t ch0;
static uint16_t ch1;
/* Initialises the device on pins sdapin and sclpin
* Lua: status = tsl2561.init(sdapin, sclpin, address(optional), package(optional))
*/
static int ICACHE_FLASH_ATTR tsl2561_init(lua_State* L) {
uint32_t sda;
uint32_t scl;
// check parameters
if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2)) {
return luaL_error(L, "wrong arg range");
}
sda = luaL_checkinteger(L, 1);
scl = luaL_checkinteger(L, 2);
if (scl == 0 || sda == 0) {
return luaL_error(L, "no i2c for D0");
}
// init I2C
uint8_t error = tsl2561Init(sda, scl);
// Parse optional parameters
if (lua_isnumber(L, 3)) {
uint8_t address = luaL_checkinteger(L, 3);
if (!((address == TSL2561_ADDRESS_GND) || (address == TSL2561_ADDRESS_FLOAT) || (address == TSL2561_ADDRESS_VDD))) {
return luaL_error(L, "Invalid argument: address");
}
else{
tsl2561SetAddress(address);
}
}
if (lua_isnumber(L, 4)) {
uint8_t package = luaL_checkinteger(L, 4);
if (!((package == TSL2561_PACKAGE_T_FN_CL) || (package == TSL2561_PACKAGE_CS))) {
return luaL_error(L, "Invalid argument: package");
}
else{
tsl2561SetPackage(package);
}
}
lua_pushnumber(L, error);
return 1;
}
/* Sets the integration time and gain settings of the device
* Lua: status = tsl2561.settiming(integration, gain)
*/
static int ICACHE_FLASH_ATTR tsl2561_lua_settiming(lua_State* L) {
// check variables
if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2)) {
return luaL_error(L, "wrong arg range");
}
uint8_t integration = luaL_checkinteger(L, 1);
if (!((integration == TSL2561_INTEGRATIONTIME_13MS) || (integration == TSL2561_INTEGRATIONTIME_101MS) || (integration == TSL2561_INTEGRATIONTIME_402MS))) {
return luaL_error(L, "Invalid argument: integration");
}
uint8_t gain = luaL_checkinteger(L, 2);
if (!((gain == TSL2561_GAIN_16X) || (gain == TSL2561_GAIN_1X))) {
return luaL_error(L, "Invalid argument: gain");
}
lua_pushnumber(L, tsl2561SetTiming(integration, gain));
return 1;
}
/* Reads sensor values from device and return calculated lux
* Lua: lux, status = tsl2561.getlux()
*/
static int ICACHE_FLASH_ATTR tsl2561_lua_calclux(lua_State* L) {
uint8_t error = tsl2561GetLuminosity(&ch0, &ch1);
if (error) {
lua_pushnumber(L, 0);
lua_pushnumber(L, error);
} else {
lua_pushnumber(L, tsl2561CalculateLux(ch0, ch1));
lua_pushnumber(L, error);
}
return 2;
}
/* Reads sensor values from device and returns them
* Lua: ch0, ch1, status = tsl2561.getrawchannels()
*/
static int ICACHE_FLASH_ATTR tsl2561_lua_getchannels(lua_State* L) {
uint8_t error = tsl2561GetLuminosity(&ch0, &ch1);
lua_pushnumber(L, ch0);
lua_pushnumber(L, ch1);
lua_pushnumber(L, error);
return 3;
}
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const LUA_REG_TYPE tsl2561_map[] =
{
{ LSTRKEY( "settiming" ), LFUNCVAL( tsl2561_lua_settiming)},
{ LSTRKEY( "getlux" ), LFUNCVAL( tsl2561_lua_calclux )},
{ LSTRKEY( "getrawchannels" ), LFUNCVAL( tsl2561_lua_getchannels )},
{ LSTRKEY( "init" ), LFUNCVAL( tsl2561_init )},
{ LSTRKEY( "TSL2561_OK" ), LNUMVAL( TSL2561_ERROR_OK )},
{ LSTRKEY( "TSL2561_ERROR_I2CINIT" ), LNUMVAL( TSL2561_ERROR_I2CINIT )},
{ LSTRKEY( "TSL2561_ERROR_I2CBUSY" ), LNUMVAL( TSL2561_ERROR_I2CBUSY )},
{ LSTRKEY( "TSL2561_ERROR_NOINIT" ), LNUMVAL( TSL2561_ERROR_NOINIT )},
{ LSTRKEY( "TSL2561_ERROR_LAST" ), LNUMVAL( TSL2561_ERROR_LAST )},
{ LSTRKEY( "INTEGRATIONTIME_13MS" ), LNUMVAL( TSL2561_INTEGRATIONTIME_13MS )},
{ LSTRKEY( "INTEGRATIONTIME_101MS" ), LNUMVAL( TSL2561_INTEGRATIONTIME_101MS )},
{ LSTRKEY( "INTEGRATIONTIME_402MS" ), LNUMVAL( TSL2561_INTEGRATIONTIME_402MS )},
{ LSTRKEY( "GAIN_1X" ), LNUMVAL( TSL2561_GAIN_1X )},
{ LSTRKEY( "GAIN_16X" ), LNUMVAL( TSL2561_GAIN_16X )},
{ LSTRKEY( "PACKAGE_CS" ), LNUMVAL( TSL2561_PACKAGE_CS )},
{ LSTRKEY( "PACKAGE_T_FN_CL" ), LNUMVAL( TSL2561_PACKAGE_T_FN_CL )},
{ LSTRKEY( "ADDRESS_GND" ), LNUMVAL( TSL2561_ADDRESS_GND )},
{ LSTRKEY( "ADDRESS_FLOAT" ), LNUMVAL( TSL2561_ADDRESS_FLOAT )},
{ LSTRKEY( "ADDRESS_VDD" ), LNUMVAL( TSL2561_ADDRESS_VDD )},
{ LNILKEY, LNILVAL}
};
LUALIB_API int luaopen_tsl2561(lua_State *L) {
LREGISTER(L, "tsl2561", tsl2561_map);
return 1;
}
......@@ -6,7 +6,6 @@
#include "auxmods.h"
#include "lrotable.h"
//#include "c_string.h"
#include "c_stdlib.h"
#include "u8g.h"
......@@ -16,8 +15,6 @@
struct _lu8g_userdata_t
{
u8g_t u8g;
u8g_pb_t pb;
u8g_dev_t dev;
};
typedef struct _lu8g_userdata_t lu8g_userdata_t;
......@@ -68,6 +65,8 @@ static int lu8g_setFont( lua_State *L )
u8g_fntpgm_uint8_t *font = (u8g_fntpgm_uint8_t *)lua_touserdata( L, 2 );
if (font != NULL)
u8g_SetFont( LU8G, font );
else
luaL_argerror(L, 2, "font data expected");
return 0;
}
......@@ -304,32 +303,24 @@ static int lu8g_generic_drawStr( lua_State *L, uint8_t rot )
// Lua: pix_len = u8g.drawStr( self, x, y, string )
static int lu8g_drawStr( lua_State *L )
{
lu8g_userdata_t *lud;
return lu8g_generic_drawStr( L, 0 );
}
// Lua: pix_len = u8g.drawStr90( self, x, y, string )
static int lu8g_drawStr90( lua_State *L )
{
lu8g_userdata_t *lud;
return lu8g_generic_drawStr( L, 1 );
}
// Lua: pix_len = u8g.drawStr180( self, x, y, string )
static int lu8g_drawStr180( lua_State *L )
{
lu8g_userdata_t *lud;
return lu8g_generic_drawStr( L, 2 );
}
// Lua: pix_len = u8g.drawStr270( self, x, y, string )
static int lu8g_drawStr270( lua_State *L )
{
lu8g_userdata_t *lud;
return lu8g_generic_drawStr( L, 3 );
}
......@@ -870,7 +861,7 @@ uint8_t u8g_com_esp8266_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
break;
case U8G_COM_MSG_WRITE_BYTE:
platform_spi_send_recv( 1, arg_val );
platform_spi_send( 1, 8, arg_val );
break;
case U8G_COM_MSG_WRITE_SEQ:
......@@ -879,7 +870,7 @@ uint8_t u8g_com_esp8266_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
register uint8_t *ptr = arg_ptr;
while( arg_val > 0 )
{
platform_spi_send_recv( 1, *ptr++ );
platform_spi_send( 1, 8, *ptr++ );
arg_val--;
}
}
......@@ -969,13 +960,6 @@ static int lu8g_close_display( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
// free up allocated page buffer
if (lud->pb.buf != NULL)
{
c_free( lud->pb.buf );
lud->pb.buf = NULL;
}
return 0;
}
......@@ -1157,13 +1141,14 @@ LUALIB_API int luaopen_u8g( lua_State *L )
// Options for circle/ ellipse drawing
MOD_REG_NUMBER( L, "DRAW_UPPER_RIGHT", U8G_DRAW_UPPER_RIGHT );
MOD_REG_NUMBER( L, "DRAW_UPPER_LEFT", U8G_DRAW_UPPER_RIGHT );
MOD_REG_NUMBER( L, "DRAW_LOWER_RIGHT", U8G_DRAW_UPPER_RIGHT );
MOD_REG_NUMBER( L, "DRAW_LOWER_LEFT", U8G_DRAW_UPPER_RIGHT );
MOD_REG_NUMBER( L, "DRAW_UPPER_LEFT", U8G_DRAW_UPPER_LEFT );
MOD_REG_NUMBER( L, "DRAW_LOWER_RIGHT", U8G_DRAW_LOWER_RIGHT );
MOD_REG_NUMBER( L, "DRAW_LOWER_LEFT", U8G_DRAW_LOWER_LEFT );
MOD_REG_NUMBER( L, "DRAW_ALL", U8G_DRAW_ALL );
// Display modes
MOD_REG_NUMBER( L, "MODE_BW", U8G_MODE_BW );
MOD_REG_NUMBER( L, "MODE_GRAY2BIT", U8G_MODE_BW );
MOD_REG_NUMBER( L, "MODE_GRAY2BIT", U8G_MODE_GRAY2BIT );
// create metatable
luaL_newmetatable(L, "u8g.display");
......
// Module for Ucglib
#include "lualib.h"
#include "lauxlib.h"
#include "platform.h"
#include "auxmods.h"
#include "lrotable.h"
#include "c_stdlib.h"
#include "ucg.h"
#include "ucg_config.h"
struct _lucg_userdata_t
{
ucg_t ucg;
ucg_dev_fnptr dev_cb;
ucg_dev_fnptr ext_cb;
// For Print() function
ucg_int_t tx, ty;
uint8_t tdir;
};
typedef struct _lucg_userdata_t lucg_userdata_t;
#define delayMicroseconds os_delay_us
static int16_t ucg_com_esp8266_hw_spi(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *data);
// shorthand macro for the ucg structure inside the userdata
#define LUCG (&(lud->ucg))
// helper function: retrieve and check userdata argument
static lucg_userdata_t *get_lud( lua_State *L )
{
lucg_userdata_t *lud = (lucg_userdata_t *)luaL_checkudata(L, 1, "ucg.display");
luaL_argcheck(L, lud, 1, "ucg.display expected");
return lud;
}
// helper function: retrieve given number of integer arguments
static void lucg_get_int_args( lua_State *L, uint8_t stack, uint8_t num, ucg_int_t *args)
{
while (num-- > 0)
{
*args++ = luaL_checkinteger( L, stack++ );
}
}
// Lua: ucg.begin( self, fontmode )
static int lucg_begin( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_Init( LUCG, lud->dev_cb, lud->ext_cb, ucg_com_esp8266_hw_spi );
ucg_int_t fontmode = luaL_checkinteger( L, 2 );
ucg_SetFontMode( LUCG, fontmode );
return 0;
}
// Lua: ucg.clearScreen( self )
static int lucg_clearScreen( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_ClearScreen( LUCG );
return 0;
}
// Lua: ucg.draw90Line( self, x, y, len, dir, col_idx )
static int lucg_draw90Line( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[5];
lucg_get_int_args( L, 2, 5, args );
ucg_Draw90Line( LUCG, args[0], args[1], args[2], args[3], args[4] );
return 0;
}
// Lua: ucg.drawBox( self, x, y, w, h )
static int lucg_drawBox( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawBox( LUCG, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawCircle( self, x0, y0, rad, option )
static int lucg_drawCircle( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawCircle( LUCG, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawDisc( self, x0, y0, rad, option )
static int lucg_drawDisc( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawDisc( LUCG, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawFrame( self, x, y, w, h )
static int lucg_drawFrame( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawFrame( LUCG, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawGradientBox( self, x, y, w, h )
static int lucg_drawGradientBox( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawGradientBox( LUCG, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: width = ucg.drawGlyph( self, x, y, dir, encoding )
static int lucg_drawGlyph( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[3];
lucg_get_int_args( L, 2, 3, args );
const char *c = luaL_checkstring( L, (1+3) + 1 );
if (c == NULL)
return 0;
lua_pushinteger( L, ucg_DrawGlyph( LUCG, args[0], args[1], args[2], *c ) );
return 1;
}
// Lua: ucg.drawGradientLine( self, x, y, len, dir )
static int lucg_drawGradientLine( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawGradientLine( LUCG, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawHLine( self, x, y, len )
static int lucg_drawHLine( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[3];
lucg_get_int_args( L, 2, 3, args );
ucg_DrawHLine( LUCG, args[0], args[1], args[2] );
return 0;
}
// Lua: ucg.drawLine( self, x1, y1, x2, y2 )
static int lucg_drawLine( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawLine( LUCG, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawPixel( self, x, y )
static int lucg_drawPixel( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[2];
lucg_get_int_args( L, 2, 2, args );
ucg_DrawPixel( LUCG, args[0], args[1] );
return 0;
}
// Lua: ucg.drawRBox( self, x, y, w, h, r )
static int lucg_drawRBox( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[5];
lucg_get_int_args( L, 2, 5, args );
ucg_DrawRBox( LUCG, args[0], args[1], args[2], args[3], args[4] );
return 0;
}
// Lua: ucg.drawRFrame( self, x, y, w, h, r )
static int lucg_drawRFrame( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[5];
lucg_get_int_args( L, 2, 5, args );
ucg_DrawRFrame( LUCG, args[0], args[1], args[2], args[3], args[4] );
return 0;
}
// Lua: width = ucg.drawString( self, x, y, dir, str )
static int lucg_drawString( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[3];
lucg_get_int_args( L, 2, 3, args );
const char *s = luaL_checkstring( L, (1+3) + 1 );
if (s == NULL)
return 0;
lua_pushinteger( L, ucg_DrawString( LUCG, args[0], args[1], args[2], s ) );
return 1;
}
// Lua: ucg.drawTetragon( self, x0, y0, x1, y1, x2, y2, x3, y3 )
static int lucg_drawTetragon( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[8];
lucg_get_int_args( L, 2, 8, args );
ucg_DrawTetragon( LUCG, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7] );
return 0;
}
// Lua: ucg.drawTriangle( self, x0, y0, x1, y1, x2, y2 )
static int lucg_drawTriangle( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[6];
lucg_get_int_args( L, 2, 6, args );
ucg_DrawTriangle( LUCG, args[0], args[1], args[2], args[3], args[4], args[5] );
return 0;
}
// Lua: ucg.drawVLine( self, x, y, len )
static int lucg_drawVLine( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[3];
lucg_get_int_args( L, 2, 3, args );
ucg_DrawVLine( LUCG, args[0], args[1], args[2] );
return 0;
}
// Lua: height = ucg.getFontAscent( self )
static int lucg_getFontAscent( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushinteger( L, ucg_GetFontAscent( LUCG ) );
return 1;
}
// Lua: height = ucg.getFontDescent( self )
static int lucg_getFontDescent( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushinteger( L, ucg_GetFontDescent( LUCG ) );
return 1;
}
// Lua: height = ucg.getHeight( self )
static int lucg_getHeight( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushinteger( L, ucg_GetHeight( LUCG ) );
return 1;
}
// Lua: width = ucg.getStrWidth( self )
static int lucg_getStrWidth( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
const char *s = luaL_checkstring( L, (1+3) + 1 );
if (s == NULL)
return 0;
lua_pushinteger( L, ucg_GetStrWidth( LUCG, s ) );
return 1;
}
// Lua: width = ucg.getWidth( self )
static int lucg_getWidth( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushinteger( L, ucg_GetWidth( LUCG ) );
return 1;
}
// Lua: ucg.setClipRange( self, x, y, w, h )
static int lucg_setClipRange( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_SetClipRange( LUCG, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.setColor( self, [idx], r, g, b )
static int lucg_setColor( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[3];
lucg_get_int_args( L, 2, 3, args );
ucg_int_t opt = luaL_optint( L, (1+3) + 1, -1 );
if (opt < 0)
ucg_SetColor( LUCG, 0, args[0], args[1], args[2] );
else
ucg_SetColor( LUCG, args[0], args[1], args[2], opt );
return 0;
}
// Lua: ucg.setFont( self, font )
static int lucg_setFont( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_fntpgm_uint8_t *font = (ucg_fntpgm_uint8_t *)lua_touserdata( L, 2 );
if (font != NULL)
ucg_SetFont( LUCG, font );
else
luaL_argerror(L, 2, "font data expected");
return 0;
}
// Lua: ucg.print( self, str )
static int lucg_print( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
const char *s = luaL_checkstring( L, 2 );
if (s == NULL)
return 0;
while (*s)
{
ucg_int_t delta;
delta = ucg_DrawGlyph(LUCG, lud->tx, lud->ty, lud->tdir, *(s++));
switch(lud->tdir)
{
case 0: lud->tx += delta; break;
case 1: lud->ty += delta; break;
case 2: lud->tx -= delta; break;
default: case 3: lud->ty -= delta; break;
}
}
return 0;
}
// Lua: ucg.setFontMode( self, fontmode )
static int lucg_setFontMode( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t fontmode = luaL_checkinteger( L, 2 );
ucg_SetFontMode( LUCG, fontmode );
return 0;
}
// Lua: ucg.setFontPosBaseline( self )
static int lucg_setFontPosBaseline( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_SetFontPosBaseline( LUCG );
return 0;
}
// Lua: ucg.setFontPosBottom( self )
static int lucg_setFontPosBottom( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_SetFontPosBottom( LUCG );
return 0;
}
// Lua: ucg.setFontPosCenter( self )
static int lucg_setFontPosCenter( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_SetFontPosCenter( LUCG );
return 0;
}
// Lua: ucg.setFontPosTop( self )
static int lucg_setFontPosTop( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_SetFontPosTop( LUCG );
return 0;
}
// Lua: ucg.setMaxClipRange( self )
static int lucg_setMaxClipRange( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_SetMaxClipRange( LUCG );
return 0;
}
// Lua: ucg.setPrintPos( self, x, y )
static int lucg_setPrintPos( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_int_t args[2];
lucg_get_int_args( L, 2, 2, args );
lud->tx = args[0];
lud->ty = args[1];
return 0;
}
// Lua: ucg.setPrintDir( self, dir )
static int lucg_setPrintDir( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
lud->tdir = luaL_checkinteger( L, 2 );
return 0;
}
// Lua: ucg.setRotate90( self )
static int lucg_setRotate90( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_SetRotate90( LUCG );
return 0;
}
// Lua: ucg.setRotate180( self )
static int lucg_setRotate180( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_SetRotate180( LUCG );
return 0;
}
// Lua: ucg.setRotate270( self )
static int lucg_setRotate270( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_SetRotate270( LUCG );
return 0;
}
// Lua: ucg.setScale2x2( self )
static int lucg_setScale2x2( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_SetScale2x2( LUCG );
return 0;
}
// Lua: ucg.undoRotate( self )
static int lucg_undoRotate( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_UndoRotate( LUCG );
return 0;
}
// Lua: ucg.undoScale( self )
static int lucg_undoScale( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
ucg_UndoScale( LUCG );
return 0;
}
static int16_t ucg_com_esp8266_hw_spi(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *data)
{
switch(msg)
{
case UCG_COM_MSG_POWER_UP:
/* "data" is a pointer to ucg_com_info_t structure with the following information: */
/* ((ucg_com_info_t *)data)->serial_clk_speed value in nanoseconds */
/* ((ucg_com_info_t *)data)->parallel_clk_speed value in nanoseconds */
/* setup pins */
// we assume that the SPI interface was already initialized
// just care for the /CS and D/C pins
//platform_gpio_write( ucg->pin_list[0], value );
if ( ucg->pin_list[UCG_PIN_RST] != UCG_PIN_VAL_NONE )
platform_gpio_mode( ucg->pin_list[UCG_PIN_RST], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
platform_gpio_mode( ucg->pin_list[UCG_PIN_CD], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
if ( ucg->pin_list[UCG_PIN_CS] != UCG_PIN_VAL_NONE )
platform_gpio_mode( ucg->pin_list[UCG_PIN_CS], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
break;
case UCG_COM_MSG_POWER_DOWN:
break;
case UCG_COM_MSG_DELAY:
delayMicroseconds(arg);
break;
case UCG_COM_MSG_CHANGE_RESET_LINE:
if ( ucg->pin_list[UCG_PIN_RST] != UCG_PIN_VAL_NONE )
platform_gpio_write( ucg->pin_list[UCG_PIN_RST], arg );
break;
case UCG_COM_MSG_CHANGE_CS_LINE:
if ( ucg->pin_list[UCG_PIN_CS] != UCG_PIN_VAL_NONE )
platform_gpio_write( ucg->pin_list[UCG_PIN_CS], arg );
break;
case UCG_COM_MSG_CHANGE_CD_LINE:
platform_gpio_write( ucg->pin_list[UCG_PIN_CD], arg );
break;
case UCG_COM_MSG_SEND_BYTE:
platform_spi_send( 1, 8, arg );
break;
case UCG_COM_MSG_REPEAT_1_BYTE:
while( arg > 0 ) {
platform_spi_send( 1, 8, data[0] );
arg--;
}
break;
case UCG_COM_MSG_REPEAT_2_BYTES:
while( arg > 0 ) {
platform_spi_send( 1, 8, data[0] );
platform_spi_send( 1, 8, data[1] );
arg--;
}
break;
case UCG_COM_MSG_REPEAT_3_BYTES:
while( arg > 0 ) {
platform_spi_send( 1, 8, data[0] );
platform_spi_send( 1, 8, data[1] );
platform_spi_send( 1, 8, data[2] );
arg--;
}
break;
case UCG_COM_MSG_SEND_STR:
while( arg > 0 ) {
platform_spi_send( 1, 8, *data++ );
arg--;
}
break;
case UCG_COM_MSG_SEND_CD_DATA_SEQUENCE:
while(arg > 0)
{
if ( *data != 0 )
{
/* set the data line directly, ignore the setting from UCG_CFG_CD */
if ( *data == 1 )
{
platform_gpio_write( ucg->pin_list[UCG_PIN_CD], 0 );
}
else
{
platform_gpio_write( ucg->pin_list[UCG_PIN_CD], 1 );
}
}
data++;
platform_spi_send( 1, 8, *data );
data++;
arg--;
}
break;
}
return 1;
}
// device destructor
static int lucg_close_display( lua_State *L )
{
lucg_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
return 0;
}
// ***************************************************************************
// Device constructors
//
//
#undef UCG_DISPLAY_TABLE_ENTRY
#define UCG_DISPLAY_TABLE_ENTRY(binding, device, extension) \
static int lucg_ ## binding( lua_State *L ) \
{ \
unsigned cs = luaL_checkinteger( L, 1 ); \
if (cs == 0) \
return luaL_error( L, "CS pin required" ); \
unsigned dc = luaL_checkinteger( L, 2 ); \
if (dc == 0) \
return luaL_error( L, "D/C pin required" ); \
unsigned res = luaL_optinteger( L, 3, UCG_PIN_VAL_NONE ); \
\
lucg_userdata_t *lud = (lucg_userdata_t *) lua_newuserdata( L, sizeof( lucg_userdata_t ) ); \
\
/* do a dummy init so that something usefull is part of the ucg structure */ \
ucg_Init( LUCG, ucg_dev_default_cb, ucg_ext_none, (ucg_com_fnptr)0 ); \
\
/* reset cursor position */ \
lud->tx = 0; \
lud->ty = 0; \
lud->tdir = 0; /* default direction */ \
\
uint8_t i; \
for( i = 0; i < UCG_PIN_COUNT; i++ ) \
lud->ucg.pin_list[i] = UCG_PIN_VAL_NONE; \
\
lud->dev_cb = device; \
lud->ext_cb = extension; \
lud->ucg.pin_list[UCG_PIN_RST] = res; \
lud->ucg.pin_list[UCG_PIN_CD] = dc; \
lud->ucg.pin_list[UCG_PIN_CS] = cs; \
\
/* set its metatable */ \
luaL_getmetatable(L, "ucg.display"); \
lua_setmetatable(L, -2); \
\
return 1; \
}
//
// Unroll the display table and insert binding functions.
UCG_DISPLAY_TABLE
//
// ***************************************************************************
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
static const LUA_REG_TYPE lucg_display_map[] =
{
{ LSTRKEY( "begin" ), LFUNCVAL( lucg_begin ) },
{ LSTRKEY( "clearScreen" ), LFUNCVAL( lucg_clearScreen ) },
{ LSTRKEY( "draw90Line" ), LFUNCVAL( lucg_draw90Line ) },
{ LSTRKEY( "drawBox" ), LFUNCVAL( lucg_drawBox ) },
{ LSTRKEY( "drawCircle" ), LFUNCVAL( lucg_drawCircle ) },
{ LSTRKEY( "drawDisc" ), LFUNCVAL( lucg_drawDisc ) },
{ LSTRKEY( "drawFrame" ), LFUNCVAL( lucg_drawFrame ) },
{ LSTRKEY( "drawGlyph" ), LFUNCVAL( lucg_drawGlyph ) },
{ LSTRKEY( "drawGradientBox" ), LFUNCVAL( lucg_drawGradientBox ) },
{ LSTRKEY( "drawGradientLine" ), LFUNCVAL( lucg_drawGradientLine ) },
{ LSTRKEY( "drawHLine" ), LFUNCVAL( lucg_drawHLine ) },
{ LSTRKEY( "drawLine" ), LFUNCVAL( lucg_drawLine ) },
{ LSTRKEY( "drawPixel" ), LFUNCVAL( lucg_drawPixel ) },
{ LSTRKEY( "drawRBox" ), LFUNCVAL( lucg_drawRBox ) },
{ LSTRKEY( "drawRFrame" ), LFUNCVAL( lucg_drawRFrame ) },
{ LSTRKEY( "drawString" ), LFUNCVAL( lucg_drawString ) },
{ LSTRKEY( "drawTetragon" ), LFUNCVAL( lucg_drawTetragon ) },
{ LSTRKEY( "drawTriangle" ), LFUNCVAL( lucg_drawTriangle ) },
{ LSTRKEY( "drawVLine" ), LFUNCVAL( lucg_drawVLine ) },
{ LSTRKEY( "getFontAscent" ), LFUNCVAL( lucg_getFontAscent ) },
{ LSTRKEY( "getFontDescent" ), LFUNCVAL( lucg_getFontDescent ) },
{ LSTRKEY( "getHeight" ), LFUNCVAL( lucg_getHeight ) },
{ LSTRKEY( "getStrWidth" ), LFUNCVAL( lucg_getStrWidth ) },
{ LSTRKEY( "getWidth" ), LFUNCVAL( lucg_getWidth ) },
{ LSTRKEY( "print" ), LFUNCVAL( lucg_print ) },
{ LSTRKEY( "setClipRange" ), LFUNCVAL( lucg_setClipRange ) },
{ LSTRKEY( "setColor" ), LFUNCVAL( lucg_setColor ) },
{ LSTRKEY( "setFont" ), LFUNCVAL( lucg_setFont ) },
{ LSTRKEY( "setFontMode" ), LFUNCVAL( lucg_setFontMode ) },
{ LSTRKEY( "setFontPosBaseline" ), LFUNCVAL( lucg_setFontPosBaseline ) },
{ LSTRKEY( "setFontPosBottom" ), LFUNCVAL( lucg_setFontPosBottom ) },
{ LSTRKEY( "setFontPosCenter" ), LFUNCVAL( lucg_setFontPosCenter ) },
{ LSTRKEY( "setFontPosTop" ), LFUNCVAL( lucg_setFontPosTop ) },
{ LSTRKEY( "setMaxClipRange" ), LFUNCVAL( lucg_setMaxClipRange ) },
{ LSTRKEY( "setPrintDir" ), LFUNCVAL( lucg_setPrintDir ) },
{ LSTRKEY( "setPrintPos" ), LFUNCVAL( lucg_setPrintPos ) },
{ LSTRKEY( "setRotate90" ), LFUNCVAL( lucg_setRotate90 ) },
{ LSTRKEY( "setRotate180" ), LFUNCVAL( lucg_setRotate180 ) },
{ LSTRKEY( "setRotate270" ), LFUNCVAL( lucg_setRotate270 ) },
{ LSTRKEY( "setScale2x2" ), LFUNCVAL( lucg_setScale2x2 ) },
{ LSTRKEY( "undoClipRange" ), LFUNCVAL( lucg_setMaxClipRange ) },
{ LSTRKEY( "undoRotate" ), LFUNCVAL( lucg_undoRotate ) },
{ LSTRKEY( "undoScale" ), LFUNCVAL( lucg_undoScale ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( lucg_close_display ) },
#if LUA_OPTIMIZE_MEMORY > 0
{ LSTRKEY( "__index" ), LROVAL ( lucg_display_map ) },
#endif
{ LNILKEY, LNILVAL }
};
const LUA_REG_TYPE lucg_map[] =
{
#undef UCG_DISPLAY_TABLE_ENTRY
#define UCG_DISPLAY_TABLE_ENTRY(binding, device, extension) { LSTRKEY( #binding ), LFUNCVAL ( lucg_ ##binding ) },
UCG_DISPLAY_TABLE
#if LUA_OPTIMIZE_MEMORY > 0
// Register fonts
#undef UCG_FONT_TABLE_ENTRY
#define UCG_FONT_TABLE_ENTRY(font) { LSTRKEY( #font ), LUDATA( (void *)(ucg_ ## font) ) },
UCG_FONT_TABLE
// Font modes
{ LSTRKEY( "FONT_MODE_TRANSPARENT" ), LNUMVAL( UCG_FONT_MODE_TRANSPARENT ) },
{ LSTRKEY( "FONT_MODE_SOLID" ), LNUMVAL( UCG_FONT_MODE_SOLID ) },
// Options for circle/ disc drawing
{ LSTRKEY( "DRAW_UPPER_RIGHT" ), LNUMVAL( UCG_DRAW_UPPER_RIGHT ) },
{ LSTRKEY( "DRAW_UPPER_LEFT" ), LNUMVAL( UCG_DRAW_UPPER_LEFT ) },
{ LSTRKEY( "DRAW_LOWER_RIGHT" ), LNUMVAL( UCG_DRAW_LOWER_RIGHT ) },
{ LSTRKEY( "DRAW_LOWER_LEFT" ), LNUMVAL( UCG_DRAW_LOWER_LEFT ) },
{ LSTRKEY( "DRAW_ALL" ), LNUMVAL( UCG_DRAW_ALL ) },
{ LSTRKEY( "__metatable" ), LROVAL( lucg_map ) },
#endif
{ LNILKEY, LNILVAL }
};
LUALIB_API int luaopen_ucg( lua_State *L )
{
#if LUA_OPTIMIZE_MEMORY > 0
luaL_rometatable(L, "ucg.display", (void *)lucg_display_map); // create metatable
return 0;
#else // #if LUA_OPTIMIZE_MEMORY > 0
int n;
luaL_register( L, AUXLIB_UCG, lucg_map );
// Set it as its own metatable
lua_pushvalue( L, -1 );
lua_setmetatable( L, -2 );
// Module constants
// Register fonts
#undef UCG_FONT_TABLE_ENTRY
#define UCG_FONT_TABLE_ENTRY(font) MOD_REG_LUDATA( L, #font, (void *)(ucg_ ## font) );
UCG_FONT_TABLE
// Font modes
MOD_REG_NUMBER( L, "FONT_MODE_TRANSPARENT", UCG_FONT_MODE_TRANSPARENT );
MOD_REG_NUMBER( L, "FONT_MODE_SOLID", UCG_FONT_MODE_SOLID );
// Options for circle/ disc drawing
MOD_REG_NUMBER( L, "DRAW_UPPER_RIGHT", UCG_DRAW_UPPER_RIGHT );
MOD_REG_NUMBER( L, "DRAW_UPPER_LEFT", UCG_DRAW_UPPER_LEFT );
MOD_REG_NUMBER( L, "DRAW_LOWER_RIGHT", UCG_DRAW_LOWER_RIGHT );
MOD_REG_NUMBER( L, "DRAW_LOWER_LEFT", UCG_DRAW_LOWER_LEFT );
MOD_REG_NUMBER( L, "DRAW_ALL", UCG_DRAW_ALL );
// create metatable
luaL_newmetatable(L, "ucg.display");
// metatable.__index = metatable
lua_pushliteral(L, "__index");
lua_pushvalue(L,-2);
lua_rawset(L,-3);
// Setup the methods inside metatable
luaL_register( L, NULL, lucg_display_map );
return 1;
#endif // #if LUA_OPTIMIZE_MEMORY > 0
}
......@@ -18,6 +18,11 @@
static int wifi_smart_succeed = LUA_NOREF;
static uint8 getap_output_format=0;
//wifi.sleep variables
#define FPM_SLEEP_MAX_TIME 0xFFFFFFF
static bool FLAG_wifi_force_sleep_enabled=0;
//variables for wifi event monitor
static sint32_t wifi_status_cb_ref[6] = {LUA_NOREF,LUA_NOREF,LUA_NOREF,LUA_NOREF,LUA_NOREF,LUA_NOREF};
static volatile os_timer_t wifi_sta_status_timer;
......@@ -28,12 +33,18 @@ static uint8 prev_wifi_status=0;
#else
static lua_State* smart_L = NULL;
#endif
static void wifi_smart_succeed_cb(void *arg){
static void wifi_smart_succeed_cb(sc_status status, void *pdata){
NODE_DBG("wifi_smart_succeed_cb is called.\n");
if (status == SC_STATUS_LINK_OVER)
{
smartconfig_stop();
return;
}
#if defined( NODE_SMART_OLDSTYLE )
if( !arg )
if (status != SC_STATUS_LINK || !pdata)
return;
if(wifi_smart_succeed == LUA_NOREF)
return;
......@@ -44,10 +55,10 @@ static void wifi_smart_succeed_cb(void *arg){
#else
if( !arg )
if (status != SC_STATUS_LINK || !pdata)
return;
struct station_config *sta_conf = arg;
struct station_config *sta_conf = pdata;
wifi_station_set_config(sta_conf);
wifi_station_disconnect();
wifi_station_connect();
......@@ -63,7 +74,6 @@ static void wifi_smart_succeed_cb(void *arg){
luaL_unref(smart_L, LUA_REGISTRYINDEX, wifi_smart_succeed);
wifi_smart_succeed = LUA_NOREF;
}
smartconfig_stop();
#endif // defined( NODE_SMART_OLDSTYLE )
}
......@@ -195,7 +205,8 @@ static int wifi_start_smart( lua_State* L )
if ( smart_type > 1 )
return luaL_error( L, "wrong arg range" );
smartconfig_start(smart_type, wifi_smart_succeed_cb);
smartconfig_set_type(smart_type);
smartconfig_start(wifi_smart_succeed_cb);
#endif // defined( NODE_SMART_OLDSTYLE )
......@@ -313,6 +324,67 @@ static int wifi_getphymode( lua_State* L )
return 1;
}
//wifi.sleep()
static int wifi_sleep(lua_State* L)
{
uint8 desired_sleep_state = 2;
sint8 wifi_fpm_do_sleep_return_value = 1;
if(lua_isnumber(L, 1))
{
if(luaL_checknumber(L, 1) == 0)
{
desired_sleep_state = 0;
}
else if(luaL_checknumber(L, 1) == 1)
{
desired_sleep_state = 1;
}
}
if (!FLAG_wifi_force_sleep_enabled && desired_sleep_state == 1 )
{
uint8 wifi_current_opmode = wifi_get_opmode();
if (wifi_current_opmode == 1 || wifi_current_opmode == 3 )
{
wifi_station_disconnect();
}
// set WiFi mode to null mode
wifi_set_opmode(NULL_MODE);
// set force sleep type
wifi_fpm_set_sleep_type(MODEM_SLEEP_T);
wifi_fpm_open();
wifi_fpm_do_sleep_return_value = wifi_fpm_do_sleep(FPM_SLEEP_MAX_TIME);
if (wifi_fpm_do_sleep_return_value == 0)
{
FLAG_wifi_force_sleep_enabled = TRUE;
}
else
{
wifi_fpm_close();
FLAG_wifi_force_sleep_enabled = FALSE;
}
}
else if(FLAG_wifi_force_sleep_enabled && desired_sleep_state == 0)
{
FLAG_wifi_force_sleep_enabled = FALSE;
// wake up to use WiFi again
wifi_fpm_do_wakeup();
wifi_fpm_close();
}
if (desired_sleep_state == 1 && FLAG_wifi_force_sleep_enabled == FALSE)
{
lua_pushnil(L);
lua_pushnumber(L, wifi_fpm_do_sleep_return_value);
}
else
{
lua_pushnumber(L, FLAG_wifi_force_sleep_enabled);
lua_pushnil(L);
}
return 2;
}
// Lua: mac = wifi.xx.getmac()
static int wifi_getmac( lua_State* L, uint8_t mode )
{
......@@ -333,7 +405,7 @@ static int wifi_setmac( lua_State* L, uint8_t mode )
if(len!=17)
return luaL_error( L, "wrong arg type" );
os_str2macaddr(mac, macaddr);
ets_str2macaddr(mac, macaddr);
lua_pushboolean(L,wifi_set_macaddr(mode, (uint8 *)mac));
return 1;
}
......@@ -591,7 +663,7 @@ static int wifi_station_config( lua_State* L )
if (ml!=17)
return luaL_error( L, "MAC:FF:FF:FF:FF:FF:FF" );
c_memset(sta_conf.bssid, 0, 6);
os_str2macaddr(sta_conf.bssid, macaddr);
ets_str2macaddr(sta_conf.bssid, macaddr);
sta_conf.bssid_set = 1;
}
else
......@@ -743,7 +815,7 @@ static int wifi_station_listap( lua_State* L )
if(len!=17)
return luaL_error( L, "bssid: FF:FF:FF:FF:FF:FF" );
c_memset(bssid, 0, 6);
os_str2macaddr(bssid, macaddr);
ets_str2macaddr(bssid, macaddr);
scan_cfg.bssid=bssid;
NODE_DBG(MACSTR, MAC2STR(scan_cfg.bssid));
NODE_DBG("\n");
......@@ -1055,7 +1127,7 @@ static int wifi_ap_getconfig( lua_State* L )
struct softap_config config;
wifi_softap_get_config(&config);
lua_pushstring( L, config.ssid );
if(config.authmode = AUTH_OPEN)
if(config.authmode == AUTH_OPEN)
lua_pushnil(L);
else
lua_pushstring( L, config.password );
......@@ -1229,7 +1301,7 @@ static int wifi_ap_dhcp_config( lua_State* L )
if (ip == 0)
return luaL_error( L, "wrong arg type" );
lease.start_ip = ip;
lease.start_ip.addr = ip;
NODE_DBG(IPSTR, IP2STR(&lease.start_ip));
NODE_DBG("\n");
......@@ -1323,6 +1395,7 @@ const LUA_REG_TYPE wifi_map[] =
{ LSTRKEY( "getchannel" ), LFUNCVAL( wifi_getchannel ) },
{ LSTRKEY( "setphymode" ), LFUNCVAL( wifi_setphymode ) },
{ LSTRKEY( "getphymode" ), LFUNCVAL( wifi_getphymode ) },
{ LSTRKEY( "sleep" ), LFUNCVAL( wifi_sleep ) },
{ LSTRKEY( "startsmart" ), LFUNCVAL( wifi_start_smart ) },
{ LSTRKEY( "stopsmart" ), LFUNCVAL( wifi_exit_smart ) },
{ LSTRKEY( "sleeptype" ), LFUNCVAL( wifi_sleeptype ) },
......@@ -1330,14 +1403,14 @@ const LUA_REG_TYPE wifi_map[] =
{ LSTRKEY( "sta" ), LROVAL( wifi_station_map ) },
{ LSTRKEY( "ap" ), LROVAL( wifi_ap_map ) },
// { LSTRKEY( "NULLMODE" ), LNUMVAL( NULL_MODE ) },
{ LSTRKEY( "NULLMODE" ), LNUMVAL( NULL_MODE ) },
{ LSTRKEY( "STATION" ), LNUMVAL( STATION_MODE ) },
{ LSTRKEY( "SOFTAP" ), LNUMVAL( SOFTAP_MODE ) },
{ LSTRKEY( "STATIONAP" ), LNUMVAL( STATIONAP_MODE ) },
{ LSTRKEY( "PHYMODE_B" ), LNUMVAL( PHY_MODE_B ) },
{ LSTRKEY( "PHYMODE_G" ), LNUMVAL( PHY_MODE_G ) },
{ LSTRKEY( "PHYMODE_N" ), LNUMVAL( PHY_MODE_N ) },
{ LSTRKEY( "PHYMODE_B" ), LNUMVAL( PHY_MODE_11B ) },
{ LSTRKEY( "PHYMODE_G" ), LNUMVAL( PHY_MODE_11G ) },
{ LSTRKEY( "PHYMODE_N" ), LNUMVAL( PHY_MODE_11N ) },
{ LSTRKEY( "NONE_SLEEP" ), LNUMVAL( NONE_SLEEP_T ) },
{ LSTRKEY( "LIGHT_SLEEP" ), LNUMVAL( LIGHT_SLEEP_T ) },
......
......@@ -115,11 +115,11 @@ static int ICACHE_FLASH_ATTR ws2801_writergb(lua_State* L) {
os_delay_us(10);
os_intr_lock();
ets_intr_lock();
ws2801_strip(buffer, length);
os_intr_unlock();
ets_intr_unlock();
return 0;
}
......
......@@ -31,8 +31,8 @@ static void ICACHE_RAM_ATTR ws2812_write(uint8_t pin, uint8_t *pixels, uint32_t
pixel = *p++;
mask = 0x80;
start_time = 0;
t0h = (1000 * system_get_cpu_freq()) / 3333; // 0.30us (spec=0.35 +- 0.15)
t1h = (1000 * system_get_cpu_freq()) / 1666; // 0.60us (spec=0.70 +- 0.15)
t0h = (1000 * system_get_cpu_freq()) / 3022; // 0.35us (spec=0.35 +- 0.15)
t1h = (1000 * system_get_cpu_freq()) / 1477; // 0.70us (spec=0.70 +- 0.15)
ttot = (1000 * system_get_cpu_freq()) / 800; // 1.25us (MUST be >= 1.25)
while (true) {
......@@ -94,9 +94,9 @@ static int ICACHE_FLASH_ATTR ws2812_writergb(lua_State* L)
platform_gpio_write(pin, 0);
// Send the buffer
os_intr_lock();
ets_intr_lock();
ws2812_write(pin_num[pin], (uint8_t*) buffer, length);
os_intr_unlock();
ets_intr_unlock();
c_free(buffer);
......@@ -120,9 +120,9 @@ static int ICACHE_FLASH_ATTR ws2812_writegrb(lua_State* L) {
platform_gpio_write(pin, 0);
// Send the buffer
os_intr_lock();
ets_intr_lock();
ws2812_write(pin_num[pin], (uint8_t*) buffer, length);
os_intr_unlock();
ets_intr_unlock();
return 0;
}
......
......@@ -220,7 +220,7 @@ uint32_t platform_flash_read( void *to, uint32_t fromaddr, uint32_t size )
#else // #ifindef INTERNAL_FLASH_READ_UNIT_SIZE
uint32_t temp, rest, ssize = size;
unsigned i;
char tmpdata[ INTERNAL_FLASH_READ_UNIT_SIZE ];
char tmpdata[ INTERNAL_FLASH_READ_UNIT_SIZE ] __attribute__ ((aligned(INTERNAL_FLASH_READ_UNIT_SIZE)));
uint8_t *pto = ( uint8_t* )to;
const uint32_t blksize = INTERNAL_FLASH_READ_UNIT_SIZE;
const uint32_t blkmask = INTERNAL_FLASH_READ_UNIT_SIZE - 1;
......
......@@ -55,20 +55,13 @@ int platform_gpio_mode( unsigned pin, unsigned mode, unsigned pull )
switch(pull){
case PLATFORM_GPIO_PULLUP:
PIN_PULLDWN_DIS(pin_mux[pin]);
PIN_PULLUP_EN(pin_mux[pin]);
break;
case PLATFORM_GPIO_PULLDOWN:
PIN_PULLUP_DIS(pin_mux[pin]);
PIN_PULLDWN_EN(pin_mux[pin]);
break;
case PLATFORM_GPIO_FLOAT:
PIN_PULLUP_DIS(pin_mux[pin]);
PIN_PULLDWN_DIS(pin_mux[pin]);
break;
default:
PIN_PULLUP_DIS(pin_mux[pin]);
PIN_PULLDWN_DIS(pin_mux[pin]);
break;
}
......@@ -197,7 +190,6 @@ uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int pari
case BIT_RATE_74880:
case BIT_RATE_115200:
case BIT_RATE_230400:
case BIT_RATE_256000:
case BIT_RATE_460800:
case BIT_RATE_921600:
case BIT_RATE_1843200:
......@@ -445,34 +437,87 @@ int platform_i2c_recv_byte( unsigned id, int ack ){
// *****************************************************************************
// SPI platform interface
uint32_t platform_spi_setup( unsigned id, int mode, unsigned cpol, unsigned cpha, unsigned databits, uint32_t clock)
uint32_t platform_spi_setup( uint8_t id, int mode, unsigned cpol, unsigned cpha, uint32_t clock_div)
{
spi_master_init(id, cpol, cpha, databits, clock);
spi_master_init( id, cpol, cpha, clock_div );
return 1;
}
spi_data_type platform_spi_send_recv( unsigned id, spi_data_type data )
int platform_spi_send( uint8_t id, uint8_t bitlen, spi_data_type data )
{
if (bitlen > 32)
return PLATFORM_ERR;
spi_mast_transaction( id, 0, 0, bitlen, data, 0, 0, 0 );
return PLATFORM_OK;
}
spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type data )
{
if (bitlen > 32)
return 0;
spi_mast_set_mosi( id, 0, bitlen, data );
spi_mast_transaction( id, 0, 0, 0, 0, bitlen, 0, -1 );
return spi_mast_get_miso( id, 0, bitlen );
}
int platform_spi_set_mosi( uint8_t id, uint8_t offset, uint8_t bitlen, spi_data_type data )
{
if (offset + bitlen > 512)
return PLATFORM_ERR;
spi_mast_set_mosi( id, offset, bitlen, data );
return PLATFORM_OK;
}
spi_data_type platform_spi_get_miso( uint8_t id, uint8_t offset, uint8_t bitlen )
{
spi_mast_byte_write(id, &data);
return data;
if (offset + bitlen > 512)
return 0;
return spi_mast_get_miso( id, offset, bitlen );
}
int platform_spi_transaction( uint8_t id, uint8_t cmd_bitlen, spi_data_type cmd_data,
uint8_t addr_bitlen, spi_data_type addr_data,
uint16_t mosi_bitlen, uint8_t dummy_bitlen, int16_t miso_bitlen )
{
if ((cmd_bitlen > 16) ||
(addr_bitlen > 32) ||
(mosi_bitlen > 512) ||
(dummy_bitlen > 256) ||
(miso_bitlen > 512))
return PLATFORM_ERR;
spi_mast_transaction( id, cmd_bitlen, cmd_data, addr_bitlen, addr_data, mosi_bitlen, dummy_bitlen, miso_bitlen );
return PLATFORM_OK;
}
// ****************************************************************************
// Flash access functions
/*
* Assumptions:
* > toaddr is INTERNAL_FLASH_WRITE_UNIT_SIZE aligned
* > size is a multiple of INTERNAL_FLASH_WRITE_UNIT_SIZE
*/
uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t size )
{
toaddr -= INTERNAL_FLASH_START_ADDRESS;
SpiFlashOpResult r;
const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
uint32_t *apbuf = NULL;
if( ((uint32_t)from) & blkmask ){
uint32_t fromaddr = (uint32_t)from;
if( (fromaddr & blkmask ) || (fromaddr >= INTERNAL_FLASH_START_ADDRESS)) {
apbuf = (uint32_t *)c_malloc(size);
if(!apbuf)
return 0;
c_memcpy(apbuf, from, size);
}
WRITE_PERI_REG(0x60000914, 0x73);
system_soft_wdt_feed ();
r = flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size);
if(apbuf)
c_free(apbuf);
......@@ -484,12 +529,37 @@ uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t siz
}
}
/*
* Assumptions:
* > fromaddr is INTERNAL_FLASH_READ_UNIT_SIZE aligned
* > size is a multiple of INTERNAL_FLASH_READ_UNIT_SIZE
*/
uint32_t platform_s_flash_read( void *to, uint32_t fromaddr, uint32_t size )
{
if (size==0)
return 0;
fromaddr -= INTERNAL_FLASH_START_ADDRESS;
SpiFlashOpResult r;
WRITE_PERI_REG(0x60000914, 0x73);
system_soft_wdt_feed ();
const uint32_t blkmask = (INTERNAL_FLASH_READ_UNIT_SIZE - 1);
if( ((uint32_t)to) & blkmask )
{
uint32_t size2=size-INTERNAL_FLASH_READ_UNIT_SIZE;
uint32* to2=(uint32*)((((uint32_t)to)&(~blkmask))+INTERNAL_FLASH_READ_UNIT_SIZE);
r = flash_read(fromaddr, to2, size2);
if(SPI_FLASH_RESULT_OK == r)
{
os_memmove(to,to2,size2);
char back[ INTERNAL_FLASH_READ_UNIT_SIZE ] __attribute__ ((aligned(INTERNAL_FLASH_READ_UNIT_SIZE)));
r=flash_read(fromaddr+size2,(uint32*)back,INTERNAL_FLASH_READ_UNIT_SIZE);
os_memcpy((uint8_t*)to+size2,back,INTERNAL_FLASH_READ_UNIT_SIZE);
}
}
else
r = flash_read(fromaddr, (uint32 *)to, size);
if(SPI_FLASH_RESULT_OK == r)
return size;
else{
......@@ -500,6 +570,6 @@ uint32_t platform_s_flash_read( void *to, uint32_t fromaddr, uint32_t size )
int platform_flash_erase_sector( uint32_t sector_id )
{
WRITE_PERI_REG(0x60000914, 0x73);
system_soft_wdt_feed ();
return flash_erase( sector_id ) == SPI_FLASH_RESULT_OK ? PLATFORM_OK : PLATFORM_ERR;
}
......@@ -27,7 +27,6 @@ uint8_t platform_key_led( uint8_t level);
// GPIO subsection
#define PLATFORM_GPIO_FLOAT 0
#define PLATFORM_GPIO_PULLUP 1
#define PLATFORM_GPIO_PULLDOWN 2
#define PLATFORM_GPIO_INT 2
#define PLATFORM_GPIO_OUTPUT 1
......@@ -90,9 +89,6 @@ int platform_can_recv( unsigned id, uint32_t *canid, uint8_t *idtype, uint8_t *l
// SPI clock polarity
#define PLATFORM_SPI_CPOL_LOW 0
#define PLATFORM_SPI_CPOL_HIGH 1
// SPI databits
#define PLATFORM_SPI_DATABITS_8 8
#define PLATFORM_SPI_DATABITS_16 16
// Data types
......@@ -100,10 +96,18 @@ typedef uint32_t spi_data_type;
// The platform SPI functions
int platform_spi_exists( unsigned id );
uint32_t platform_spi_setup( unsigned id, int mode, unsigned cpol, unsigned cpha, unsigned databits, uint32_t clock);
spi_data_type platform_spi_send_recv( unsigned id, spi_data_type data );
uint32_t platform_spi_setup( uint8_t id, int mode, unsigned cpol, unsigned cpha, uint32_t clock_div);
int platform_spi_send( uint8_t id, uint8_t bitlen, spi_data_type data );
spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type data );
void platform_spi_select( unsigned id, int is_select );
int platform_spi_set_mosi( uint8_t id, uint8_t offset, uint8_t bitlen, spi_data_type data );
spi_data_type platform_spi_get_miso( uint8_t id, uint8_t offset, uint8_t bitlen );
int platform_spi_transaction( uint8_t id, uint8_t cmd_bitlen, spi_data_type cmd_data,
uint8_t addr_bitlen, spi_data_type addr_data,
uint16_t mosi_bitlen, uint8_t dummy_bitlen, int16_t miso_bitlen );
// *****************************************************************************
// UART subsection
......
......@@ -8,7 +8,9 @@ spiffs fs;
static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2];
static u8_t spiffs_fds[32*4];
static u8_t spiffs_cache[(LOG_PAGE_SIZE+32)*4];
#if SPIFFS_CACHE
static u8_t spiffs_cache[(LOG_PAGE_SIZE+32)*2];
#endif
static s32_t my_spiffs_read(u32_t addr, u32_t size, u8_t *dst) {
platform_flash_read(dst, addr, size);
......@@ -44,7 +46,11 @@ The small 4KB sectors allow for greater flexibility in applications th
void myspiffs_mount() {
spiffs_config cfg;
#ifdef SPIFFS_FIXED_LOCATION
cfg.phys_addr = SPIFFS_FIXED_LOCATION;
#else
cfg.phys_addr = ( u32_t )platform_flash_get_first_free_block_address( NULL );
#endif
cfg.phys_addr += 0x3000;
cfg.phys_addr &= 0xFFFFC000; // align to 4 sector.
cfg.phys_size = INTERNAL_FLASH_SIZE - ( ( u32_t )cfg.phys_addr - INTERNAL_FLASH_START_ADDRESS );
......@@ -62,8 +68,12 @@ void myspiffs_mount() {
spiffs_work_buf,
spiffs_fds,
sizeof(spiffs_fds),
#if SPIFFS_CACHE
spiffs_cache,
sizeof(spiffs_cache),
#else
0, 0,
#endif
// myspiffs_check_callback);
0);
NODE_DBG("mount res: %i\n", res);
......@@ -79,7 +89,11 @@ int myspiffs_format( void )
{
SPIFFS_unmount(&fs);
u32_t sect_first, sect_last;
#ifdef SPIFFS_FIXED_LOCATION
sect_first = SPIFFS_FIXED_LOCATION;
#else
sect_first = ( u32_t )platform_flash_get_first_free_block_address( NULL );
#endif
sect_first += 0x3000;
sect_first &= 0xFFFFC000; // align to 4 sector.
sect_first = platform_flash_get_sector_of_address(sect_first);
......
......@@ -8,16 +8,10 @@
#ifndef SPIFFS_CONFIG_H_
#define SPIFFS_CONFIG_H_
// ----------- 8< ------------
// Following includes are for the linux test build of spiffs
// These may/should/must be removed/altered/replaced in your target
// #include "params_test.h"
#include "user_config.h"
#include "c_stdio.h"
#include "c_stdlib.h"
#include "c_stdint.h"
#include "c_string.h"
#include "c_stddef.h"
#include "c_types.h"
// ----------- >8 ------------
typedef sint32_t s32_t;
typedef uint32_t u32_t;
......@@ -67,6 +61,8 @@ typedef uint8_t u8_t;
#ifndef SPIFFS_CACHE_STATS
#define SPIFFS_CACHE_STATS 0
#endif
#else
#define SPIFFS_CACHE_WR 0
#endif
// Always check header of each accessed page to ensure consistent state.
......
......@@ -415,7 +415,7 @@ typedef struct __attribute(( packed )) {
} spiffs_page_header;
// object index header page header
typedef struct __attribute(( packed, aligned(4) ))
typedef struct __attribute(( packed ))
{
// common page header
spiffs_page_header p_hdr;
......@@ -428,7 +428,7 @@ typedef struct __attribute(( packed, aligned(4) ))
} spiffs_page_object_ix_header;
// object index page header
typedef struct __attribute(( packed, aligned(4) )) {
typedef struct __attribute(( packed )) {
spiffs_page_header p_hdr;
} spiffs_page_object_ix;
......
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: espconn_encry.c
*
* Description: data encrypt interface
*
* Modification history:
* 2014/3/31, v1.0 create this file.
*******************************************************************************/
#include "lwip/netif.h"
#include "lwip/inet.h"
#include "netif/etharp.h"
#include "lwip/tcp.h"
#include "lwip/ip.h"
#include "lwip/init.h"
#include "ets_sys.h"
#include "os_type.h"
//#include "os.h"
#include "ssl/app/espconn_ssl.h"
/******************************************************************************
* FunctionName : espconn_encry_connect
* Description : The function given as the connect
* Parameters : espconn -- the espconn used to listen the connection
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_secure_connect(struct espconn *espconn)
{
if (espconn == NULL)
return ESPCONN_ARG;
return espconn_ssl_client(espconn);
}
/******************************************************************************
* FunctionName : espconn_encry_disconnect
* Description : The function given as the disconnect
* Parameters : espconn -- the espconn used to listen the connection
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_secure_disconnect(struct espconn *espconn)
{
espconn_msg *pnode = NULL;
bool value = false;
if (espconn == NULL)
return ESPCONN_ARG;
value = espconn_find_connection(espconn, &pnode);
if (value){
espconn_ssl_disconnect(pnode);
return ESPCONN_OK;
}
else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_encry_sent
* Description : sent data for client or server
* Parameters : espconn -- espconn to set for client or server
* psent -- data to send
* length -- length of data to send
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_secure_sent(struct espconn *espconn, uint8 *psent, uint16 length)
{
espconn_msg *pnode = NULL;
bool value = false;
if (espconn == NULL)
return ESPCONN_ARG;
espconn ->state = ESPCONN_WRITE;
value = espconn_find_connection(espconn, &pnode);
if (value){
espconn_ssl_sent(pnode, psent, length);
return ESPCONN_OK;
}
else
return ESPCONN_ARG;
}
sint8 ICACHE_FLASH_ATTR
espconn_secure_accept(struct espconn *espconn)
{
if (espconn == NULL)
return ESPCONN_ARG;
return espconn_ssl_server(espconn);
}
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: espconn_ssl.c
*
* Description: ssl encrypt interface
*
* Modification history:
* 2014/3/31, v1.0 create this file.
*******************************************************************************/
#include "lwip/netif.h"
#include "netif/etharp.h"
#include "lwip/tcp.h"
#include "lwip/ip.h"
#include "lwip/init.h"
#include "lwip/tcp_impl.h"
#include "ssl/ssl_os_port.h"
#include "ssl/app/espconn_ssl.h"
#include "ets_sys.h"
#include "os_type.h"
//#include "os.h"
#include "lwip/app/espconn.h"
struct pbuf *psslpbuf = NULL;
extern espconn_msg *plink_active;
static err_t espconn_ssl_crecv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
static err_t espconn_ssl_srecv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
static void espconn_ssl_sclose(void *arg, struct tcp_pcb *pcb);
static void espconn_ssl_cclose(void *arg, struct tcp_pcb *pcb);
/////////////////////////////common function///////////////////////////////////
/******************************************************************************
* FunctionName : display_session_id
* Description : Display what session id we have.
* Parameters :
* Returns :
*******************************************************************************/
static void ICACHE_FLASH_ATTR display_session_id(SSL *ssl)
{
int i;
const uint8_t *session_id = ssl_get_session_id(ssl);
int sess_id_size = ssl_get_session_id_size(ssl);
if (sess_id_size > 0) {
ssl_printf("-----BEGIN SSL SESSION PARAMETERS-----\n");
for (i = 0; i < sess_id_size; i++) {
ssl_printf("%02x", session_id[i]);
}
ssl_printf("\n-----END SSL SESSION PARAMETERS-----\n");
//TTY_FLUSH();
}
}
/******************************************************************************
* FunctionName : display_cipher
* Description : Display what cipher we are using
* Parameters :
* Returns :
*******************************************************************************/
static void ICACHE_FLASH_ATTR display_cipher(SSL *ssl)
{
ssl_printf("CIPHER is ");
switch (ssl_get_cipher_id(ssl)) {
case SSL_AES128_SHA:
ssl_printf("AES128-SHA");
break;
case SSL_AES256_SHA:
ssl_printf("AES256-SHA");
break;
case SSL_RC4_128_SHA:
ssl_printf("RC4-SHA");
break;
case SSL_RC4_128_MD5:
ssl_printf("RC4-MD5");
break;
default:
ssl_printf("Unknown - %d", ssl_get_cipher_id(ssl));
break;
}
ssl_printf("\n");
//TTY_FLUSH();
}
/******************************************************************************
* FunctionName : espconn_ssl_reconnect
* Description : reconnect with host
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_ssl_reconnect(void *arg)
{
espconn_msg *pssl_recon = arg;
struct espconn *espconn = NULL;
ssl_msg *pssl = NULL;
sint8 ssl_reerr = 0;
if (pssl_recon != NULL) {
espconn = pssl_recon->preverse;
if (pssl_recon->pespconn != NULL){
if (espconn != NULL){
/*espconn_copy_partial(espconn, pssl_recon->pespconn);
if (pssl_recon->pespconn->proto.tcp != NULL){
os_free(pssl_recon->pespconn->proto.tcp);
pssl_recon->pespconn->proto.tcp = NULL;
}
os_free(pssl_recon->pespconn);
pssl_recon->pespconn = NULL;*/
espconn = pssl_recon->preverse;
} else {
espconn = pssl_recon->pespconn;
}
}
pssl = pssl_recon->pssl;
ssl_reerr = pssl_recon->pcommon.err;
if (pssl != NULL) {
if (pssl->ssl) {
ssl_free(pssl->ssl);
}
if (pssl->ssl_ctx) {
ssl_ctx_free(pssl->ssl_ctx);
}
os_free(pssl);
pssl = NULL;
pssl_recon->pssl = pssl;
}
os_free(pssl_recon);
pssl_recon = NULL;
if (espconn ->proto.tcp->reconnect_callback != NULL) {
espconn ->proto.tcp->reconnect_callback(espconn, ssl_reerr);
}
} else {
ssl_printf("espconn_ssl_reconnect err\n");
}
}
/******************************************************************************
* FunctionName : espconn_ssl_dissuccessful
* Description : as
* Parameters :
* Returns :
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_ssl_dissuccessful(void *arg)
{
espconn_msg *pdiscon = arg;
struct espconn *espconn = NULL;
struct tcp_pcb *pcb = NULL;
ssl_msg *pssl = NULL;
if (pdiscon != NULL) {
espconn = pdiscon->preverse;
if (pdiscon->pespconn != NULL){
if (espconn != NULL){
/*espconn_copy_partial(espconn, pdiscon->pespconn);
if (pdiscon->pespconn->proto.tcp != NULL){
os_free(pdiscon->pespconn->proto.tcp);
pdiscon->pespconn->proto.tcp = NULL;
}
os_free(pdiscon->pespconn);
pdiscon->pespconn = NULL;*/
espconn = pdiscon->preverse;
} else{
espconn = pdiscon->pespconn;
}
pcb = pdiscon->pcommon.pcb;
tcp_arg(pcb, NULL);
tcp_err(pcb, NULL);
}
pssl = pdiscon->pssl;
if (pssl != NULL) {
if (pssl->ssl) {
ssl_free(pssl->ssl);
}
if (pssl->ssl_ctx) {
ssl_ctx_free(pssl->ssl_ctx);
}
os_free(pssl);
pssl = NULL;
pdiscon->pssl = pssl;
}
os_free(pdiscon);
pdiscon = NULL;
if (espconn ->proto.tcp->disconnect_callback != NULL) {
espconn ->proto.tcp->disconnect_callback(espconn);
}
} else {
espconn_printf("espconn_ssl_dissuccessful err\n");
}
}
/******************************************************************************
* FunctionName : espconn_ssl_write
* Description : sent data for client or server
* Parameters : void *arg -- client or server to send
* uint8* psent -- Data to send
* uint16 length -- Length of data to send
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_ssl_sent(void *arg, uint8 *psent, uint16 length)
{
espconn_msg *pssl_sent = arg;
struct tcp_pcb *pcb = NULL;
ssl_msg *pssl = NULL;
u16_t len = 0;
int res = 0;
ssl_printf("espconn_ssl_sent pcb %p psent %p length %d\n", arg, psent, length);
if (pssl_sent == NULL || psent == NULL || length == 0) {
return;
}
pcb = pssl_sent->pcommon.pcb;
pssl = pssl_sent->pssl;
if (RT_MAX_PLAIN_LENGTH < length) {
len = RT_MAX_PLAIN_LENGTH;
} else {
len = length;
}
if (pssl != NULL) {
if (pssl->ssl != NULL) {
pssl->ssl->SslClient_pcb = pcb;
res = ssl_write(pssl->ssl, psent, len);
pssl_sent->pcommon.ptrbuf = psent + len;
pssl_sent->pcommon.cntr = length - len;
}
}
}
/******************************************************************************
* FunctionName : espconn_sent_packet
* Description : sent data for client or server
* Parameters : void *arg -- client or server to send
* uint8* psent -- Data to send
* uint16 length -- Length of data to send
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_sent_packet(struct tcp_pcb *pcb, uint8 *psent, uint16 length)
{
err_t err = 0;
u16_t len = 0;
if (pcb == NULL || psent == NULL || length == 0) {
return;
}
if (tcp_sndbuf(pcb) < length) {
len = tcp_sndbuf(pcb);
} else {
len = length;
}
if (len > (2 * pcb->mss)) {
len = 2 * pcb->mss;
}
do {
err = tcp_write(pcb, psent, len, 0);
if (err == ERR_MEM) {
len /= 2;
}
} while (err == ERR_MEM && len > 1);
if (err == ERR_OK) {
err = tcp_output(pcb);
}
}
////////////////////////////////client function////////////////////////////////
/******************************************************************************
* FunctionName : espconn_ssl_cclose_cb
* Description : as
* Parameters :
* Returns :
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_ssl_cclose_cb(void *arg)
{
static uint16 timecount = 0;
espconn_msg *pcclose_cb = arg;
if (pcclose_cb == NULL) {
return;
}
struct tcp_pcb *pcb = pcclose_cb->pcommon.pcb;
ssl_printf("espconn_ssl_cclose_cb %d %d\n", pcb->state, pcb->nrtx);
if (pcb->state == TIME_WAIT || pcb->state == CLOSED) {
pcclose_cb->pespconn ->state = ESPCONN_CLOSE;
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, pcclose_cb);
espconn_ssl_dissuccessful((void *)pcclose_cb);
} else {
os_timer_arm(&pcclose_cb->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
}
}
/******************************************************************************
* FunctionName : espconn_sslclient_close
* Description : The connection shall be actively closed.
* Parameters : pcb -- Additional argument to pass to the callback function
* pcb -- the pcb to close
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_ssl_cclose(void *arg, struct tcp_pcb *pcb)
{
espconn_msg *pcclose = arg;
os_timer_disarm(&pcclose->pcommon.ptimer);
os_timer_setfn(&pcclose->pcommon.ptimer, espconn_ssl_cclose_cb, pcclose);
os_timer_arm(&pcclose->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
tcp_recv(pcb, NULL);
pcclose->pcommon.err = tcp_close(pcb);
ssl_printf("espconn_ssl_cclose %d\n", pcclose->pcommon.err);
if (pcclose->pcommon.err != ERR_OK) {
/* closing failed, try again later */
tcp_recv(pcb, espconn_ssl_crecv);
} else {
tcp_sent(pcb, NULL);
tcp_poll(pcb, NULL, 0);
}
}
/******************************************************************************
* FunctionName : espconn_sslclient_sent
* Description : Data has been sent and acknowledged by the remote host.
* This means that more data can be sent.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb for which data has been acknowledged
* len -- The amount of bytes acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_ssl_csent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
espconn_msg *psent = arg;
ssl_msg *pssl = psent->pssl;
psent->pcommon.pcb = pcb;
if (pssl->quiet == true) {
int pkt_size = pssl->ssl->bm_index + SSL_RECORD_SIZE;
u16_t max_len = 2 * pcb->mss;
pssl->pkt_length += len;
ssl_printf("espconn_ssl_csent %d %d %d\n", len, pssl->pkt_length, pkt_size);
if (pssl->pkt_length == pkt_size){
pssl->ssl->bm_index = 0;
pssl->pkt_length = 0;
if (psent->pcommon.cntr == 0) {
psent->pespconn->state = ESPCONN_CONNECT;
if (psent->pespconn->sent_callback != NULL) {
psent->pespconn->sent_callback(psent->pespconn);
}
} else {
espconn_ssl_sent(psent, psent->pcommon.ptrbuf, psent->pcommon.cntr);
}
} else {
if (len == max_len){
espconn_sent_packet(pcb, &pssl->ssl->bm_all_data[pssl->pkt_length], pkt_size - pssl->pkt_length);
}
}
} else {
ssl_printf("espconn_ssl_csent %p %p %d\n", pcb, pssl->ssl->bm_all_data, len);
}
return ERR_OK;
}
/******************************************************************************
* FunctionName : espconn_sslclient_recv
* Description : Data has been received on this pcb.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb which received data
* p -- The received data (or NULL when the connection has been closed!)
* err -- An error code if there has been an error receiving
* Returns : ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_ssl_crecv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
u16_t ret = 0;
espconn_msg *precv = arg;
ssl_msg *pssl = precv->pssl;
ssl_printf("espconn_ssl_crecv %d %p %p\n", __LINE__, pssl->ssl, p);
if (p != NULL) {
tcp_recved(pcb, p ->tot_len);
if (pssl->ssl == NULL) {
pbuf_free(p);
} else {
pssl->ssl->ssl_pbuf = p;
if (ssl_handshake_status(pssl->ssl) != SSL_OK) {
ret = ssl_read(pssl->ssl, NULL);
pbuf_free(p);
if (ret != SSL_OK){
os_printf("client handshake failed\n");
espconn_ssl_cclose(arg, pcb);
}
}
if (ssl_handshake_status(pssl->ssl) == SSL_OK) {
if (!pssl->quiet) {
ssl_printf("client handshake need size %d\n", system_get_free_heap_size());
const char *common_name = ssl_get_cert_dn(pssl->ssl,
SSL_X509_CERT_COMMON_NAME);
if (common_name) {
ssl_printf("Common Name:\t\t\t%s\n", common_name);
}
display_session_id(pssl->ssl);
display_cipher(pssl->ssl);
pssl->quiet = true;
os_printf("client handshake ok!\n");
REG_CLR_BIT(0x3ff00014, BIT(0));
os_update_cpu_frequency(80);
precv->pespconn->state = ESPCONN_CONNECT;
precv->pcommon.pcb = pcb;
pbuf_free(p);
if (precv->pespconn->proto.tcp->connect_callback != NULL) {
precv->pespconn->proto.tcp->connect_callback(precv->pespconn);
}
} else {
uint8_t *read_buf = NULL;
ret = ssl_read(pssl->ssl, &read_buf);
precv->pespconn->state = ESPCONN_READ;
precv->pcommon.pcb = pcb;
pbuf_free(p);
if (precv->pespconn->recv_callback != NULL && read_buf != NULL) {
precv->pespconn->recv_callback(precv->pespconn, read_buf, ret);
}
precv->pespconn->state = ESPCONN_CONNECT;
}
}
}
}
if (err == ERR_OK && p == NULL) {
espconn_ssl_cclose(precv, pcb);
}
return ERR_OK;
}
/******************************************************************************
* FunctionName : espconn_client_err
* Description : The pcb had an error and is already deallocated.
* The argument might still be valid (if != NULL).
* Parameters : arg -- Additional argument to pass to the callback function
* err -- Error code to indicate why the pcb has been closed
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_ssl_cerr(void *arg, err_t err)
{
espconn_msg *pssl_cerr = arg;
struct tcp_pcb *pcb = NULL;
LWIP_UNUSED_ARG(err);
if (pssl_cerr != NULL) {
os_timer_disarm(&pssl_cerr->pcommon.ptimer);
pcb = pssl_cerr->pcommon.pcb;
pssl_cerr->pespconn->state = ESPCONN_CLOSE;
espconn_printf("espconn_ssl_cerr %d %d %d\n", pcb->state, pcb->nrtx, err);
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, pssl_cerr);
if (err == ERR_ABRT) {
switch (pcb->state) {
case SYN_SENT:
if (pcb->nrtx == TCP_SYNMAXRTX) {
pssl_cerr->pcommon.err = ESPCONN_CONN;
} else {
pssl_cerr->pcommon.err = err;
}
break;
case ESTABLISHED:
if (pcb->nrtx == TCP_MAXRTX) {
pssl_cerr->pcommon.err = ESPCONN_TIMEOUT;
} else {
pssl_cerr->pcommon.err = err;
}
break;
case FIN_WAIT_1:
if (pcb->nrtx == TCP_MAXRTX) {
pssl_cerr->pcommon.err = ESPCONN_CLSD;
} else {
pssl_cerr->pcommon.err = err;
}
break;
case FIN_WAIT_2:
pssl_cerr->pcommon.err = ESPCONN_CLSD;
break;
case CLOSED:
pssl_cerr->pcommon.err = ESPCONN_CONN;
break;
default :
break;
}
} else {
pssl_cerr->pcommon.err = err;
}
os_timer_setfn(&pssl_cerr->pcommon.ptimer, espconn_ssl_reconnect, pssl_cerr);
os_timer_arm(&pssl_cerr->pcommon.ptimer, 10, 0);
}
}
#if 0
/******************************************************************************
* FunctionName : espconn_ssl_cpoll
* Description : The poll function is called every 3nd second.
* If there has been no data sent (which resets the retries) in 3 seconds, close.
* If the last portion of a file has not been sent in 3 seconds, close.
*
* This could be increased, but we don't want to waste resources for bad connections.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb for which data has been acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_ssl_cpoll(void *arg, struct tcp_pcb *pcb)
{
ssl_printf("espconn_ssl_cpoll %p %d\n", pcb, pcb->state);
struct espconn *espconn = arg;
if (arg == NULL) {
tcp_abandon(pcb, 0);
tcp_poll(pcb, NULL, 0);
return ERR_ABRT;
}
if (pcb ->state == ESTABLISHED) {
espconn->recv_check ++;
if (espconn ->recv_check == 0x05){
//tcp_poll(pcb, espconn_ssl_cpoll, 0);
espconn->recv_check = 0;
espconn_ssl_cclose(arg, pcb);
}
} else {
//tcp_poll(pcb, espconn_ssl_cpoll, 0);
espconn_ssl_cclose(arg, pcb);
}
return ERR_OK;
}
#endif
/******************************************************************************
* FunctionName : espconn_sslclient_connect
* Description : A new incoming connection has been connected.
* Parameters : arg -- Additional argument to pass to the callback function
* tpcb -- The connection pcb which is connected
* err -- An unused error code, always ERR_OK currently
* Returns : connection result
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_ssl_connect(void *arg, struct tcp_pcb *tpcb, err_t err)
{
espconn_msg *pconnect = arg;
ssl_msg *pssl = NULL;
uint32_t options;
options = SSL_SERVER_VERIFY_LATER | SSL_DISPLAY_CERTS | SSL_NO_DEFAULT_KEY;
ssl_printf("espconn_ssl_connect %p %p %p %d\n", tpcb, arg, pespconn->psecure, system_get_free_heap_size());
//if (pespconn->psecure != NULL){
// return ERR_ISCONN;
//}
pconnect->pcommon.pcb = tpcb;
pssl = (ssl_msg *)os_zalloc(sizeof(ssl_msg));
pconnect->pssl = pssl;
if (pssl == NULL) {
return ERR_MEM;
}
REG_SET_BIT(0x3ff00014, BIT(0));
os_update_cpu_frequency(160);
os_printf("client handshake start.\n");
pssl->quiet = false;
pssl->ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS);
if (pssl->ssl_ctx == NULL) {
return ERR_MEM;
}
ssl_printf("espconn_ssl_client ssl_ctx %p\n", pssl->ssl_ctx);
pssl->ssl = SSLClient_new(pssl->ssl_ctx, tpcb, NULL, 0);
if (pssl->ssl == NULL) {
return ERR_MEM;
}
tcp_arg(tpcb, arg);
tcp_sent(tpcb, espconn_ssl_csent);
tcp_recv(tpcb, espconn_ssl_crecv);
//tcp_poll(tpcb, espconn_ssl_cpoll, 6);
return ERR_OK;
}
/******************************************************************************
* FunctionName : espconn_ssl_disconnect
* Description : A new incoming connection has been disconnected.
* Parameters : espconn -- the espconn used to disconnect with host
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_ssl_disconnect(espconn_msg *pdis)
{
if (pdis != NULL) {
if (pdis->preverse == NULL)
espconn_ssl_cclose(pdis, pdis->pcommon.pcb);
else
espconn_ssl_sclose(pdis, pdis->pcommon.pcb);
} else {
ssl_printf("espconn_ssl_disconnect err.\n");
}
}
/******************************************************************************
* FunctionName : espconn_ssl_client
* Description : Initialize the client: set up a connect PCB and bind it to
* the defined port
* Parameters : espconn -- the espconn used to build client
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_ssl_client(struct espconn *espconn)
{
struct tcp_pcb *pcb;
struct ip_addr ipaddr;
espconn_msg *pclient = NULL;
pclient = plink_active;
while(pclient != NULL){
if (pclient->pssl != NULL)
return ESPCONN_ISCONN;
pclient = pclient->pnext;
}
pclient = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
if (pclient == NULL){
return ESPCONN_MEM;
}
IP4_ADDR(&ipaddr, espconn->proto.tcp->remote_ip[0],
espconn->proto.tcp->remote_ip[1],
espconn->proto.tcp->remote_ip[2],
espconn->proto.tcp->remote_ip[3]);
pcb = tcp_new();
if (pcb == NULL) {
espconn ->state = ESPCONN_NONE;
os_free(pclient);
pclient = NULL;
return ESPCONN_MEM;
} else {
/*insert the node to the active connection list*/
espconn_list_creat(&plink_active, pclient);
tcp_arg(pcb, (void *)pclient);
tcp_err(pcb, espconn_ssl_cerr);
pclient->preverse = NULL;
pclient->pespconn = espconn;
pclient->pespconn->state = ESPCONN_WAIT;
pclient->pcommon.pcb = pcb;
tcp_bind(pcb, IP_ADDR_ANY, pclient->pespconn->proto.tcp->local_port);
pclient->pcommon.err = tcp_connect(pcb, &ipaddr, pclient->pespconn->proto.tcp->remote_port, espconn_ssl_connect);
return ESPCONN_OK;
}
}
/////////////////////////////server's function/////////////////////////////////
/******************************************************************************
* FunctionName : espconn_ssl_sclose_cb
* Description : as
* Parameters :
* Returns :
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_ssl_sclose_cb(void *arg)
{
static uint16 timecount = 0;
espconn_msg *psclose_cb = arg;
if (psclose_cb == NULL) {
return;
}
struct tcp_pcb *pcb = psclose_cb->pcommon.pcb;
ssl_printf("espconn_ssl_sclose_cb %d %d\n", pcb->state, pcb->nrtx);
if (pcb->state == CLOSED || pcb->state == TIME_WAIT) {
psclose_cb ->pespconn ->state = ESPCONN_CLOSE;
psclose_cb->pespconn->link_cnt --;
/*remove the node from the server's active connection list*/
espconn_list_delete(&plink_active, psclose_cb);
espconn_ssl_dissuccessful((void *)psclose_cb);
} else {
os_timer_arm(&psclose_cb->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
}
}
/******************************************************************************
* FunctionName : espconn_sslclient_close
* Description : The connection shall be actively closed.
* Parameters : pcb -- Additional argument to pass to the callback function
* pcb -- the pcb to close
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_ssl_sclose(void *arg, struct tcp_pcb *pcb)
{
espconn_msg *psclose = arg;
os_timer_disarm(&psclose->pcommon.ptimer);
os_timer_setfn(&psclose->pcommon.ptimer, espconn_ssl_sclose_cb, psclose);
os_timer_arm(&psclose->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
tcp_recv(pcb, NULL);
psclose->pcommon.err = tcp_close(pcb);
if (psclose->pcommon.err != ERR_OK) {
/* closing failed, try again later */
tcp_recv(pcb, espconn_ssl_srecv);
} else {
tcp_sent(pcb, NULL);
tcp_poll(pcb, NULL, 0);
}
}
/******************************************************************************
* FunctionName : espconn_sslclient_sent
* Description : Data has been sent and acknowledged by the remote host.
* This means that more data can be sent.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb for which data has been acknowledged
* len -- The amount of bytes acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_ssl_ssent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
espconn_msg *psent = arg;
ssl_msg *pssl = psent->pssl;
psent->pcommon.pcb = pcb;
psent->pcommon.recv_check = 0;
if (ssl_handshake_status(pssl->ssl) == SSL_OK) {
if (!pssl->quiet) {
ssl_printf("espconn_ssl_ssent %p %d\n",pcb, system_get_free_heap_size());
const char *common_name = ssl_get_cert_dn(pssl->ssl, SSL_X509_CERT_COMMON_NAME);
if (common_name) {
ssl_printf("Common Name:\t\t\t%s\n", common_name);
}
display_session_id(pssl->ssl);
display_cipher(pssl->ssl);
pssl->quiet = true;
os_printf("server handshake ok!\n");
REG_CLR_BIT(0x3ff00014, BIT(0));
os_update_cpu_frequency(80);
psent->pespconn->state = ESPCONN_CONNECT;
if (psent->pespconn->proto.tcp->connect_callback != NULL) {
psent->pespconn->proto.tcp->connect_callback(psent->pespconn);
}
} else {
int pkt_size = pssl->ssl->bm_index + SSL_RECORD_SIZE;
u16_t max_len = 2 * pcb->mss;
pssl->pkt_length += len;
ssl_printf("espconn_ssl_ssent %d %d %d\n", len, pssl->pkt_length, pkt_size);
if (pssl->pkt_length == pkt_size){
pssl->ssl->bm_index = 0;
pssl->pkt_length = 0;
if (psent->pcommon.cntr == 0) {
psent->pespconn->state = ESPCONN_CONNECT;
if (psent->pespconn->sent_callback != NULL) {
psent->pespconn->sent_callback(psent->pespconn);
}
} else {
espconn_ssl_sent(psent, psent->pcommon.ptrbuf, psent->pcommon.cntr);
}
} else {
if (len == max_len){
espconn_sent_packet(pcb, &pssl->ssl->bm_all_data[pssl->pkt_length], pkt_size - pssl->pkt_length);
}
}
}
} else {
ssl_printf("espconn_ssl_ssent %p %p %d\n",pcb, pssl->ssl->bm_all_data, len);
}
return ERR_OK;
}
/******************************************************************************
* FunctionName : espconn_sslclient_recv
* Description : Data has been received on this pcb.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb which received data
* p -- The received data (or NULL when the connection has been closed!)
* err -- An error code if there has been an error receiving
* Returns : ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_ssl_srecv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
u16_t ret = 0;
espconn_msg *precv = arg;
ssl_msg *pssl = precv->pssl;
ssl_printf("espconn_ssl_srecv %d %p %p\n", __LINE__, pcb, p);
if (p != NULL) {
tcp_recved(pcb, p ->tot_len);
precv->pcommon.recv_check = 0;
if (pssl->ssl == NULL) {
pbuf_free(p);
} else {
pssl->ssl->ssl_pbuf = p;
if (ssl_handshake_status(pssl->ssl) != SSL_OK) {
ret = ssl_read(pssl->ssl, NULL);
pbuf_free(p);
if (ret != SSL_OK){
os_printf("server handshake failed.\n");
espconn_ssl_sclose(arg, pcb);
}
} else {
uint8_t *read_buf = NULL;
ret = ssl_read(pssl->ssl, &read_buf);
precv->pespconn->state = ESPCONN_READ;
precv->pcommon.pcb = pcb;
pbuf_free(p);
if (precv->pespconn->recv_callback != NULL && read_buf != NULL) {
precv->pespconn->recv_callback(precv->pespconn, read_buf, ret);
}
precv->pespconn->state = ESPCONN_CONNECT;
}
}
}
if (err == ERR_OK && p == NULL) {
espconn_ssl_sclose(precv, pcb);
}
return ERR_OK;
}
/******************************************************************************
* FunctionName : espconn_server_poll
* Description : The poll function is called every 3nd second.
* If there has been no data sent (which resets the retries) in 3 seconds, close.
* If the last portion of a file has not been sent in 3 seconds, close.
*
* This could be increased, but we don't want to waste resources for bad connections.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb for which data has been acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_ssl_spoll(void *arg, struct tcp_pcb *pcb)
{
ssl_printf("espconn_ssl_spoll %p %d\n", pcb, pcb->state);
espconn_msg *pspoll = arg;
if (arg == NULL) {
tcp_abandon(pcb, 0);
tcp_poll(pcb, NULL, 0);
return ERR_ABRT;
}
if (pcb ->state == ESTABLISHED) {
pspoll ->pcommon.recv_check ++;
if (pspoll ->pcommon.recv_check == pspoll ->pcommon.timeout){
tcp_poll(pcb, NULL, 0);
pspoll ->pcommon.recv_check = 0;
espconn_ssl_sclose(arg, pcb);
}
} else {
tcp_poll(pcb, NULL, 0);
espconn_ssl_sclose(arg, pcb);
}
return ERR_OK;
}
/******************************************************************************
* FunctionName : esponn_server_err
* Description : The pcb had an error and is already deallocated.
* The argument might still be valid (if != NULL).
* Parameters : arg -- Additional argument to pass to the callback function
* err -- Error code to indicate why the pcb has been closed
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_ssl_serr(void *arg, err_t err)
{
espconn_msg *pserr = arg;
struct tcp_pcb *pcb = NULL;
LWIP_UNUSED_ARG(err);
if (pserr != NULL) {
os_timer_disarm(&pserr->pcommon.ptimer);
pcb = pserr->pcommon.pcb;
pserr->pespconn->state = ESPCONN_CLOSE;
/*remove the node from the server's active connection list*/
espconn_list_delete(&plink_active, pserr);
if (err == ERR_ABRT) {
switch (pcb->state) {
case SYN_RCVD:
if (pcb->nrtx == TCP_SYNMAXRTX) {
pserr->pcommon.err = ESPCONN_CONN;
} else {
pserr->pcommon.err = err;
}
break;
case ESTABLISHED:
if (pcb->nrtx == TCP_MAXRTX) {
pserr->pcommon.err = ESPCONN_TIMEOUT;
} else {
pserr->pcommon.err = err;
}
break;
case CLOSE_WAIT:
if (pcb->nrtx == TCP_MAXRTX) {
pserr->pcommon.err = ESPCONN_CLSD;
} else {
pserr->pcommon.err = err;
}
break;
case LAST_ACK:
pserr->pcommon.err = ESPCONN_CLSD;
break;
case CLOSED:
pserr->pcommon.err = ESPCONN_CONN;
break;
default :
break;
}
} else {
pserr->pcommon.err = err;
}
os_timer_setfn(&pserr->pcommon.ptimer, espconn_ssl_reconnect, pserr);
os_timer_arm(&pserr->pcommon.ptimer, 10, 0);
}
}
/******************************************************************************
* FunctionName : espconn_tcp_accept
* Description : A new incoming connection has been accepted.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb which is accepted
* err -- An unused error code, always ERR_OK currently
* Returns : acception result
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_ssl_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct espconn *espconn = arg;
ssl_msg *pssl = NULL;
espconn_msg *paccept = NULL;
remot_info *pinfo = NULL;
ssl_printf("espconn_ssl_accept %p %p %p %d\n", pcb, arg, espconn->psecure, system_get_free_heap_size());
LWIP_UNUSED_ARG(err);
paccept = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
tcp_arg(pcb, paccept);
tcp_err(pcb, espconn_ssl_serr);
if (paccept == NULL)
return ERR_MEM;
/*insert the node to the active connection list*/
espconn_list_creat(&plink_active, paccept);
paccept->preverse = espconn;
paccept->pespconn = espconn;
paccept->pcommon.timeout = 0x0a;
paccept->pcommon.pcb = pcb;
paccept->pcommon.remote_port = pcb->remote_port;
paccept->pcommon.remote_ip[0] = ip4_addr1_16(&pcb->remote_ip);
paccept->pcommon.remote_ip[1] = ip4_addr2_16(&pcb->remote_ip);
paccept->pcommon.remote_ip[2] = ip4_addr3_16(&pcb->remote_ip);
paccept->pcommon.remote_ip[3] = ip4_addr4_16(&pcb->remote_ip);
os_memcpy(espconn->proto.tcp->remote_ip, paccept->pcommon.remote_ip, 4);
espconn->proto.tcp->remote_port = pcb->remote_port;
espconn_get_connection_info(espconn, &pinfo , ESPCONN_SSL);
if (espconn->link_cnt == 0x01)
return ERR_ISCONN;
pssl = (ssl_msg *)os_zalloc(sizeof(ssl_msg));
paccept->pssl = pssl;
if (pssl == NULL) {
return ERR_MEM;
}
REG_SET_BIT(0x3ff00014, BIT(0));
os_update_cpu_frequency(160);
os_printf("server handshake start.\n");
pssl->quiet = false;
pssl->ssl_ctx = ssl_ctx_new(SSL_DISPLAY_CERTS, SSL_DEFAULT_SVR_SESS);
if (pssl->ssl_ctx == NULL) {
ssl_printf("Error: Server context is invalid\n");
return ERR_MEM;
}
ssl_printf("Server context %p\n", pssl->ssl_ctx);
pssl->ssl = sslserver_new(pssl->ssl_ctx, pcb);
if (pssl->ssl == NULL) {
ssl_printf("Error: Server ssl connection is invalid\n");
return ERR_MEM;
}
tcp_sent(pcb, espconn_ssl_ssent);
tcp_recv(pcb, espconn_ssl_srecv);
tcp_poll(pcb, espconn_ssl_spoll, 2);
return ERR_OK;
}
/******************************************************************************
* FunctionName : espconn_ssl_server
* Description : as
* Parameters :
* Returns :
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_ssl_server(struct espconn *espconn)
{
struct tcp_pcb *pcb;
pcb = tcp_new();
if (pcb == NULL) {
espconn ->state = ESPCONN_NONE;
return ESPCONN_MEM;
} else {
tcp_bind(pcb, IP_ADDR_ANY, espconn->proto.tcp->local_port);
pcb = tcp_listen(pcb);
if (pcb != NULL) {
espconn ->state = ESPCONN_LISTEN;
tcp_arg(pcb, (void *)espconn);
tcp_accept(pcb, espconn_ssl_accept);
return ESPCONN_OK;
} else {
espconn ->state = ESPCONN_NONE;
return ESPCONN_MEM;
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment