Commit c8ac5cfb authored by Arnim Läuger's avatar Arnim Läuger Committed by GitHub
Browse files

Merge pull request #1980 from nodemcu/dev

2.1.0 master drop
parents 22e1adc4 787379f0
......@@ -43,7 +43,8 @@ static void gpio_intr_callback_task (task_param_t param, uint8 priority)
// Now must be >= then . Add the missing bits
if (then > (now & 0xffffff)) {
then += 0x1000000;
// Now must have rolled over since the interrupt -- back it down
now -= 0x1000000;
}
then = (then + (now & 0x7f000000)) & 0x7fffffff;
......
/*
* Driver for TI Texas Instruments HDC1080 Temperature/Humidity Sensor.
* Code By Metin KOC
* Sixfab Inc. metin@sixfab.com
* Code based on ADXL345 driver.
*/
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
#include "c_stdlib.h"
#include "c_string.h"
#include "c_math.h"
static const uint32_t hdc1080_i2c_id = 0;
static const uint8_t hdc1080_i2c_addr = 0x40;
#define HDC1080_TEMPERATURE_REGISTER 0X00
#define HDC1080_HUMIDITY_REGISTER 0X01
#define HDC1080_CONFIG_REGISTER 0X02
static int hdc1080_setup(lua_State* L) {
// Configure Sensor
platform_i2c_send_start(hdc1080_i2c_id);
platform_i2c_send_address(hdc1080_i2c_id, hdc1080_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
platform_i2c_send_byte(hdc1080_i2c_id, HDC1080_CONFIG_REGISTER);
platform_i2c_send_byte(hdc1080_i2c_id, 0x05); //Bit[10] to 1 for 11 bit resolution , Set Bit[9:8] to 01 for 11 bit resolution.
platform_i2c_send_byte(hdc1080_i2c_id, 0x00);
platform_i2c_send_stop(hdc1080_i2c_id);
return 0;
}
static int hdc1080_init(lua_State* L) {
uint32_t sda;
uint32_t scl;
platform_print_deprecation_note("hdc1080.init() is replaced by hdc1080.setup()", "in the next version");
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");
}
platform_i2c_setup(hdc1080_i2c_id, sda, scl, PLATFORM_I2C_SPEED_SLOW);
// remove sda and scl parameters from stack
lua_remove(L, 1);
lua_remove(L, 1);
return hdc1080_setup(L);
}
static int hdc1080_read(lua_State* L) {
uint8_t data[2];
#ifdef LUA_NUMBER_INTEGRAL
int temp;
int humidity;
#else
float temp;
float humidity;
#endif
int i;
platform_i2c_send_start(hdc1080_i2c_id);
platform_i2c_send_address(hdc1080_i2c_id, hdc1080_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
platform_i2c_send_byte(hdc1080_i2c_id, HDC1080_TEMPERATURE_REGISTER);
platform_i2c_send_stop(hdc1080_i2c_id);
os_delay_us(7000);
platform_i2c_send_start(hdc1080_i2c_id);
platform_i2c_send_address(hdc1080_i2c_id, hdc1080_i2c_addr, PLATFORM_I2C_DIRECTION_RECEIVER);
for (i=0; i<2; i++) {
data[i] = platform_i2c_recv_byte(hdc1080_i2c_id, 1);
}
platform_i2c_send_stop(hdc1080_i2c_id);
#ifdef LUA_NUMBER_INTEGRAL
temp = ((((data[0]<<8)|data[1])*165)>>16)-40;
lua_pushinteger(L, (int)temp);
#else
temp = ((float)((data[0]<<8)|data[1])/(float)pow(2,16))*165.0f-40.0f;
lua_pushnumber(L, temp);
#endif
platform_i2c_send_start(hdc1080_i2c_id);
platform_i2c_send_address(hdc1080_i2c_id, hdc1080_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
platform_i2c_send_byte(hdc1080_i2c_id, HDC1080_HUMIDITY_REGISTER);
platform_i2c_send_stop(hdc1080_i2c_id);
os_delay_us(7000);
platform_i2c_send_start(hdc1080_i2c_id);
platform_i2c_send_address(hdc1080_i2c_id, hdc1080_i2c_addr, PLATFORM_I2C_DIRECTION_RECEIVER);
for (i=0; i<2; i++) {
data[i] = platform_i2c_recv_byte(hdc1080_i2c_id, 1);
}
platform_i2c_send_stop(hdc1080_i2c_id);
#ifdef LUA_NUMBER_INTEGRAL
humidity = ((((data[0]<<8)|data[1]))*100)>>16;
lua_pushinteger(L, (int)humidity);
#else
humidity = ((float)((data[0]<<8)|data[1])/(float)pow(2,16))*100.0f;
lua_pushnumber(L, humidity);
#endif
return 2;
}
static const LUA_REG_TYPE hdc1080_map[] = {
{ LSTRKEY( "read" ), LFUNCVAL( hdc1080_read )},
{ LSTRKEY( "setup" ), LFUNCVAL( hdc1080_setup )},
{ LSTRKEY( "init" ), LFUNCVAL( hdc1080_init )},
{ LNILKEY, LNILVAL}
};
NODEMCU_MODULE(HDC1080, "hdc1080", hdc1080_map, NULL);
// Module for mqtt
//
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
......@@ -42,10 +42,14 @@ typedef struct mqtt_event_data_t
uint16_t data_offset;
} mqtt_event_data_t;
#define RECONNECT_OFF 0
#define RECONNECT_POSSIBLE 1
#define RECONNECT_ON 2
typedef struct mqtt_state_t
{
uint16_t port;
int auto_reconnect;
uint8_t auto_reconnect; // 0 is not auto_reconnect. 1 is auto reconnect, but never connected. 2 is auto reconnect, but once connected
mqtt_connect_info_t* connect_info;
uint16_t message_length;
uint16_t message_length_read;
......@@ -106,7 +110,7 @@ static void mqtt_socket_disconnected(void *arg) // tcp only
}
}
if(mud->mqtt_state.auto_reconnect){
if(mud->mqtt_state.auto_reconnect == RECONNECT_ON) {
mud->pesp_conn->reverse = mud;
mud->pesp_conn->type = ESPCONN_TCP;
mud->pesp_conn->state = ESPCONN_NONE;
......@@ -153,7 +157,7 @@ static void mqtt_socket_reconnected(void *arg, sint8_t err)
mud->event_timeout = 0; // no need to count anymore
if(mud->mqtt_state.auto_reconnect){
if(mud->mqtt_state.auto_reconnect == RECONNECT_ON) {
pesp_conn->proto.tcp->remote_port = mud->mqtt_state.port;
pesp_conn->proto.tcp->local_port = espconn_port();
socket_connect(pesp_conn);
......@@ -166,6 +170,9 @@ static void mqtt_socket_reconnected(void *arg, sint8_t err)
{
espconn_disconnect(pesp_conn);
}
mqtt_connack_fail(mud, MQTT_CONN_FAIL_SERVER_NOT_FOUND);
mqtt_socket_disconnected(arg);
}
NODE_DBG("leave mqtt_socket_reconnected.\n");
......@@ -287,7 +294,7 @@ READPACKET:
switch(mud->connState){
case MQTT_CONNECT_SENDING:
case MQTT_CONNECT_SENT:
mud->event_timeout = 0;
mud->event_timeout = 0;
if(mqtt_get_type(in_buffer) != MQTT_MSG_TYPE_CONNACK){
NODE_DBG("MQTT: Invalid packet\r\n");
......@@ -330,6 +337,9 @@ READPACKET:
} else {
mud->connState = MQTT_DATA;
NODE_DBG("MQTT: Connected\r\n");
if (mud->mqtt_state.auto_reconnect == RECONNECT_POSSIBLE) {
mud->mqtt_state.auto_reconnect = RECONNECT_ON;
}
if(mud->cb_connect_ref == LUA_NOREF)
break;
if(mud->self_ref == LUA_NOREF)
......@@ -603,6 +613,16 @@ void mqtt_socket_timer(void *arg)
NODE_DBG("Can not connect to broker.\n");
os_timer_disarm(&mud->mqttTimer);
mqtt_connack_fail(mud, MQTT_CONN_FAIL_SERVER_NOT_FOUND);
#ifdef CLIENT_SSL_ENABLE
if(mud->secure)
{
espconn_secure_disconnect(mud->pesp_conn);
}
else
#endif
{
espconn_disconnect(mud->pesp_conn);
}
} else if(mud->connState == MQTT_CONNECT_SENDING){ // MQTT_CONNECT send time out.
NODE_DBG("sSend MQTT_CONNECT failed.\n");
mud->connState = MQTT_INIT;
......@@ -779,7 +799,7 @@ static int mqtt_socket_client( lua_State* L )
mud->connect_info.keepalive = keepalive;
mud->mqtt_state.pending_msg_q = NULL;
mud->mqtt_state.auto_reconnect = 0;
mud->mqtt_state.auto_reconnect = RECONNECT_OFF;
mud->mqtt_state.port = 1883;
mud->mqtt_state.connect_info = &mud->connect_info;
......@@ -924,7 +944,7 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
{
dns_reconn_count++;
if( dns_reconn_count >= 5 ){
NODE_ERR( "DNS Fail!\n" );
NODE_DBG( "DNS Fail!\n" );
// Note: should delete the pesp_conn or unref self_ref here.
struct espconn *pesp_conn = arg;
......@@ -938,7 +958,7 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
mqtt_socket_disconnected(arg); // although not connected, but fire disconnect callback to release every thing.
return -1;
}
NODE_ERR( "DNS retry %d!\n", dns_reconn_count );
NODE_DBG( "DNS retry %d!\n", dns_reconn_count );
host_ip.addr = 0;
return espconn_gethostbyname(pesp_conn, name, &host_ip, socket_dns_foundcb);
}
......@@ -968,7 +988,7 @@ static int mqtt_socket_connect( lua_State* L )
ip_addr_t ipaddr;
const char *domain;
int stack = 1;
unsigned secure = 0, auto_reconnect = 0;
unsigned secure = 0, auto_reconnect = RECONNECT_OFF;
int top = lua_gettop(L);
sint8 espconn_status;
......@@ -1053,12 +1073,15 @@ static int mqtt_socket_connect( lua_State* L )
if ( (stack<=top) && lua_isnumber(L, stack) )
{
auto_reconnect = lua_tointeger(L, stack);
if ( auto_reconnect == RECONNECT_POSSIBLE ) {
platform_print_deprecation_note("autoreconnect == 1 is deprecated", "in the next version");
}
stack++;
if ( auto_reconnect != 0 && auto_reconnect != 1 ){
auto_reconnect = 0; // default to 0
if ( auto_reconnect != RECONNECT_OFF && auto_reconnect != RECONNECT_POSSIBLE ){
auto_reconnect = RECONNECT_OFF; // default to 0
}
} else {
auto_reconnect = 0; // default to 0
auto_reconnect = RECONNECT_OFF; // default to 0
}
mud->mqtt_state.auto_reconnect = auto_reconnect;
......@@ -1128,7 +1151,7 @@ static int mqtt_socket_close( lua_State* L )
return 1;
}
mud->mqtt_state.auto_reconnect = 0; // stop auto reconnect.
mud->mqtt_state.auto_reconnect = RECONNECT_OFF; // stop auto reconnect.
sint8 espconn_status = ESPCONN_CONN;
if (mud->connected) {
......
......@@ -297,7 +297,10 @@ int net_createServer( lua_State *L ) {
type = luaL_optlong(L, 1, TYPE_TCP);
timeout = luaL_optlong(L, 2, 30);
if (type == TYPE_UDP) return net_createUDPSocket( L );
if (type == TYPE_UDP) {
platform_print_deprecation_note("net.createServer with net.UDP type", "in next version");
return net_createUDPSocket( L );
}
if (type != TYPE_TCP) return luaL_error(L, "invalid type");
lnet_userdata *u = net_create(L, TYPE_TCP_SERVER);
......@@ -312,9 +315,13 @@ int net_createConnection( lua_State *L ) {
type = luaL_optlong(L, 1, TYPE_TCP);
secure = luaL_optlong(L, 2, 0);
if (type == TYPE_UDP) return net_createUDPSocket( L );
if (type == TYPE_UDP) {
platform_print_deprecation_note("net.createConnection with net.UDP type", "in next version");
return net_createUDPSocket( L );
}
if (type != TYPE_TCP) return luaL_error(L, "invalid type");
if (secure) {
platform_print_deprecation_note("net.createConnection with secure flag", "in next version");
#ifdef TLS_MODULE_PRESENT
return tls_socket_create( L );
#else
......@@ -379,6 +386,7 @@ int net_listen( lua_State *L ) {
ud->tcp_pcb = tcp_new();
if (!ud->tcp_pcb)
return luaL_error(L, "cannot allocate PCB");
ud->tcp_pcb->so_options |= SOF_REUSEADDR;
err = tcp_bind(ud->tcp_pcb, &addr, port);
if (err == ERR_OK) {
tcp_arg(ud->tcp_pcb, ud);
......@@ -638,6 +646,27 @@ int net_dns( lua_State *L ) {
return 0;
}
// Lua: client/socket:ttl([ttl])
int net_ttl( lua_State *L ) {
lnet_userdata *ud = net_get_udata(L);
if (!ud || ud->type == TYPE_TCP_SERVER)
return luaL_error(L, "invalid user data");
if (!ud->pcb)
return luaL_error(L, "socket is not open/bound yet");
int ttl = luaL_optinteger(L, 2, -1);
// Since `ttl` field is part of IP_PCB macro
// (which are at beginning of both udp_pcb/tcp_pcb)
// and PCBs declared as `union` there is safe to
// access ttl field without checking for type.
if (ttl == -1) {
ttl = ud->udp_pcb->ttl;
} else {
ud->udp_pcb->ttl = ttl;
}
lua_pushinteger(L, ttl);
return 1;
}
// Lua: client:getpeer()
int net_getpeer( lua_State *L ) {
lnet_userdata *ud = net_get_udata(L);
......@@ -951,6 +980,7 @@ static const LUA_REG_TYPE net_tcpsocket_map[] = {
{ LSTRKEY( "hold" ), LFUNCVAL( net_hold ) },
{ LSTRKEY( "unhold" ), LFUNCVAL( net_unhold ) },
{ LSTRKEY( "dns" ), LFUNCVAL( net_dns ) },
{ LSTRKEY( "ttl" ), LFUNCVAL( net_ttl ) },
{ LSTRKEY( "getpeer" ), LFUNCVAL( net_getpeer ) },
{ LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) },
......@@ -964,6 +994,7 @@ static const LUA_REG_TYPE net_udpsocket_map[] = {
{ LSTRKEY( "on" ), LFUNCVAL( net_on ) },
{ LSTRKEY( "send" ), LFUNCVAL( net_send ) },
{ LSTRKEY( "dns" ), LFUNCVAL( net_dns ) },
{ LSTRKEY( "ttl" ), LFUNCVAL( net_ttl ) },
{ LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) },
{ LSTRKEY( "__index" ), LROVAL( net_udpsocket_map ) },
......
......@@ -53,6 +53,9 @@ static int node_deepsleep( lua_State* L )
else
system_deep_sleep_set_option( option );
}
bool instant = false;
if (lua_isnumber(L, 3))
instant = lua_tointeger(L, 3);
// Set deleep time, skip if nil
if ( lua_isnumber(L, 1) )
{
......@@ -61,24 +64,46 @@ static int node_deepsleep( lua_State* L )
if ( us < 0 )
return luaL_error( L, "wrong arg range" );
else
system_deep_sleep( us );
{
if (instant)
system_deep_sleep_instant(us);
else
system_deep_sleep( us );
}
}
return 0;
}
// Lua: dsleep_set_options
// Combined to dsleep( us, option )
// static int node_deepsleep_setoption( lua_State* L )
// {
// s32 option;
// option = luaL_checkinteger( L, 1 );
// if ( option < 0 || option > 4)
// return luaL_error( L, "wrong arg range" );
// else
// deep_sleep_set_option( option );
// return 0;
// }
// Lua: info()
#ifdef PMSLEEP_ENABLE
#include "pmSleep.h"
int node_sleep_resume_cb_ref= LUA_NOREF;
void node_sleep_resume_cb(void)
{
PMSLEEP_DBG("START");
pmSleep_execute_lua_cb(&node_sleep_resume_cb_ref);
PMSLEEP_DBG("END");
}
// Lua: node.sleep(table)
static int node_sleep( lua_State* L )
{
pmSleep_INIT_CFG(cfg);
cfg.sleep_mode=LIGHT_SLEEP_T;
if(lua_istable(L, 1)){
pmSleep_parse_table_lua(L, 1, &cfg, NULL, &node_sleep_resume_cb_ref);
}
else{
return luaL_argerror(L, 1, "must be table");
}
cfg.resume_cb_ptr = &node_sleep_resume_cb;
pmSleep_suspend(&cfg);
return 0;
}
#endif //PMSLEEP_ENABLE
static int node_info( lua_State* L )
{
......@@ -87,11 +112,7 @@ static int node_info( lua_State* L )
lua_pushinteger(L, NODE_VERSION_REVISION);
lua_pushinteger(L, system_get_chip_id()); // chip id
lua_pushinteger(L, spi_flash_get_id()); // flash id
#if defined(FLASH_SAFE_API)
lua_pushinteger(L, flash_safe_get_size_byte() / 1024); // flash size in KB
#else
lua_pushinteger(L, flash_rom_get_size_byte() / 1024); // flash size in KB
#endif // defined(FLASH_SAFE_API)
lua_pushinteger(L, flash_rom_get_mode());
lua_pushinteger(L, flash_rom_get_speed());
return 8;
......@@ -129,11 +150,7 @@ static int node_flashsize( lua_State* L )
{
flash_rom_set_size_byte(luaL_checkinteger(L, 1));
}
#if defined(FLASH_SAFE_API)
uint32_t sz = flash_safe_get_size_byte();
#else
uint32_t sz = flash_rom_get_size_byte();
#endif // defined(FLASH_SAFE_API)
lua_pushinteger( L, sz );
return 1;
}
......@@ -562,6 +579,10 @@ static const LUA_REG_TYPE node_map[] =
{
{ LSTRKEY( "restart" ), LFUNCVAL( node_restart ) },
{ LSTRKEY( "dsleep" ), LFUNCVAL( node_deepsleep ) },
#ifdef PMSLEEP_ENABLE
{ LSTRKEY( "sleep" ), LFUNCVAL( node_sleep ) },
PMSLEEP_INT_MAP,
#endif
{ LSTRKEY( "info" ), LFUNCVAL( node_info ) },
{ LSTRKEY( "chipid" ), LFUNCVAL( node_chipid ) },
{ LSTRKEY( "flashid" ), LFUNCVAL( node_flashid ) },
......
//***************************************************************************
// Si7021 module for ESP8266 with nodeMCU
// fetchbot @github
// MIT license, http://opensource.org/licenses/MIT
//***************************************************************************
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
#include "osapi.h"
//***************************************************************************
// I2C ADDRESS DEFINITON
//***************************************************************************
#define SI7021_I2C_ADDRESS (0x40)
//***************************************************************************
// COMMAND DEFINITON
//***************************************************************************
#define SI7021_CMD_MEASURE_RH_HOLD (0xE5)
#define SI7021_CMD_MEASURE_RH_NOHOLD (0xF5)
#define SI7021_CMD_MEASURE_TEMP_HOLD (0xE3)
#define SI7021_CMD_MEASURE_TEMP_NOHOLD (0xF3)
#define SI7021_CMD_READ_PREV_TEMP (0xE0)
#define SI7021_CMD_RESET (0xFE)
#define SI7021_CMD_WRITE_RHT_REG (0xE6)
#define SI7021_CMD_READ_RHT_REG (0xE7)
#define SI7021_CMD_WRITE_HEATER_REG (0x51)
#define SI7021_CMD_READ_HEATER_REG (0x11)
#define SI7021_CMD_ID1 (0xFA0F)
#define SI7021_CMD_ID2 (0xFCC9)
#define SI7021_CMD_FIRM_REV (0x84B8)
//***************************************************************************
// REGISTER DEFINITON
//***************************************************************************
#define SI7021_RH12_TEMP14 (0x00)
#define SI7021_RH08_TEMP12 (0x01)
#define SI7021_RH10_TEMP13 (0x80)
#define SI7021_RH11_TEMP11 (0x81)
#define SI7021_HEATER_ENABLE (0x04)
#define SI7021_HEATER_DISABLE (0x00)
//***************************************************************************
static const uint32_t si7021_i2c_id = 0;
static uint8_t si7021_i2c_addr = SI7021_I2C_ADDRESS;
static uint8_t si7021_res = 0x00;
static uint8_t si7021_config = 0x3A;
static uint8_t si7021_heater = 0x00;
static uint8_t si7021_heater_setting = 0x00;
static uint8_t write_byte(uint8_t reg) {
platform_i2c_send_start(si7021_i2c_id);
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
platform_i2c_send_byte(si7021_i2c_id, reg);
platform_i2c_send_stop(si7021_i2c_id);
}
static uint8_t write_reg(uint8_t reg, uint8_t data) {
platform_i2c_send_start(si7021_i2c_id);
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
platform_i2c_send_byte(si7021_i2c_id, reg);
platform_i2c_send_byte(si7021_i2c_id, data);
platform_i2c_send_stop(si7021_i2c_id);
}
static uint8_t read_reg(uint8_t reg, uint8_t *buf, uint8_t size) {
platform_i2c_send_start(si7021_i2c_id);
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
platform_i2c_send_byte(si7021_i2c_id, reg);
platform_i2c_send_stop(si7021_i2c_id);
platform_i2c_send_start(si7021_i2c_id);
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_RECEIVER);
os_delay_us(25000);
while (size-- > 0)
*buf++ = platform_i2c_recv_byte(si7021_i2c_id, size > 0);
platform_i2c_send_stop(si7021_i2c_id);
return 1;
}
static uint8_t read_serial(uint16_t reg, uint8_t *buf, uint8_t size) {
platform_i2c_send_start(si7021_i2c_id);
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
platform_i2c_send_byte(si7021_i2c_id, (uint8_t)(reg >> 8));
platform_i2c_send_byte(si7021_i2c_id, (uint8_t)(reg & 0xFF));
// platform_i2c_send_stop(si7021_i2c_id);
platform_i2c_send_start(si7021_i2c_id);
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_RECEIVER);
while (size-- > 0)
*buf++ = platform_i2c_recv_byte(si7021_i2c_id, size > 0);
platform_i2c_send_stop(si7021_i2c_id);
return 1;
}
// CRC8
uint8_t si7021_crc8(uint8_t crc, uint8_t *buf, uint8_t size) {
while (size--) {
crc ^= *buf++;
for (uint8_t i = 0; i < 8; i++) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0x31;
} else crc <<= 1;
}
}
return crc;
}
static int si7021_lua_setup(lua_State* L) {
write_byte(SI7021_CMD_RESET);
os_delay_us(50000);
// check for device on i2c bus
uint8_t buf_r[1];
read_reg(SI7021_CMD_READ_RHT_REG, buf_r, 1);
if (buf_r[0] != 0x3A)
return luaL_error(L, "found no device");
return 0;
}
// Change sensor settings and returns them
// Lua: res, vdds, heater[, heater_set] = si7021.settings(RESOLUTION[,HEATER,HEATER_SETTING])
static int si7021_lua_setting(lua_State* L) {
// check variable
if (!lua_isnumber(L, 1)) {
return luaL_error(L, "wrong arg range");
}
si7021_res = luaL_checkinteger(L, 1);
if (!((si7021_res == SI7021_RH12_TEMP14) || (si7021_res == SI7021_RH08_TEMP12) || (si7021_res == SI7021_RH10_TEMP13) || (si7021_res == SI7021_RH11_TEMP11))) {
return luaL_error(L, "Invalid argument: resolution");
}
si7021_config = (si7021_res | 0x3A);
write_reg(SI7021_CMD_WRITE_RHT_REG,si7021_config);
// Parse optional parameters
if (lua_isnumber(L, 2)) {
if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3)) {
return luaL_error(L, "wrong arg range");
}
si7021_heater = luaL_checkinteger(L, 2);
if (!((si7021_heater == SI7021_HEATER_ENABLE) || (si7021_heater == SI7021_HEATER_DISABLE))) {
return luaL_error(L, "Invalid argument: heater");
}
si7021_heater_setting = luaL_checkinteger(L, 3);
if ((si7021_heater_setting < 0x00) || (si7021_heater_setting > 0x0F)) {
return luaL_error(L, "Invalid argument: heater_setting");
}
si7021_config = (si7021_res | si7021_heater | 0x3A);
write_reg(SI7021_CMD_WRITE_RHT_REG,si7021_config);
write_reg(SI7021_CMD_WRITE_HEATER_REG,(si7021_heater_setting & 0x0F));
}
uint8_t buf_c[1];
uint8_t buf_h[1];
read_reg(SI7021_CMD_READ_RHT_REG, buf_c, 1);
read_reg(SI7021_CMD_READ_HEATER_REG, buf_h, 1);
lua_pushinteger(L, ((buf_c[0] >> 6) + (buf_c[0] & 0x01)));
lua_pushinteger(L, ((buf_c[0] >> 6) & 0x01));
lua_pushinteger(L, ((buf_c[0] >> 2) & 0x01));
lua_pushinteger(L, (buf_h[0] & 0x0F));
return 4;
}
// Reads sensor values from device and returns them
// Lua: hum, temp, humdec, tempdec = si7021.read()
static int si7021_lua_read(lua_State* L) {
uint8_t buf_h[3]; // first two byte data, third byte crc
read_reg(SI7021_CMD_MEASURE_RH_HOLD, buf_h, 3);
if (buf_h[2] != si7021_crc8(0, buf_h, 2)) //crc check
return luaL_error(L, "crc error");
double hum = (uint16_t)((buf_h[0] << 8) | buf_h[1]);
hum = ((hum * 125) / 65536 - 6);
int humdec = (int)((hum - (int)hum) * 1000);
uint8_t buf_t[2]; // two byte data, no crc on combined temp measurement
read_reg(SI7021_CMD_READ_PREV_TEMP, buf_t, 2);
double temp = (uint16_t)((buf_t[0] << 8) | buf_t[1]);
temp = ((temp * 175.72) / 65536 - 46.85);
int tempdec = (int)((temp - (int)temp) * 1000);
lua_pushnumber(L, hum);
lua_pushnumber(L, temp);
lua_pushinteger(L, humdec);
lua_pushinteger(L, tempdec);
return 4;
}
// Reads electronic serial number from device and returns them
// Lua: serial = si7021.serial()
static int si7021_lua_serial(lua_State* L) {
uint32_t serial_a;
uint8_t crc = 0;
uint8_t buf_s_1[8]; // every second byte contains crc
read_serial(SI7021_CMD_ID1, buf_s_1, 8);
for(uint8_t i = 0; i <= 6; i+=2) {
crc = si7021_crc8(crc, buf_s_1+i, 1);
if (buf_s_1[i+1] != crc)
return luaL_error(L, "crc error");
serial_a = (serial_a << 8) + buf_s_1[i];
}
uint32_t serial_b;
crc = 0;
uint8_t buf_s_2[6]; // every third byte contains crc
read_serial(SI7021_CMD_ID2, buf_s_2, 6);
for(uint8_t i = 0; i <=3; i+=3) {
crc = si7021_crc8(crc, buf_s_2+i, 2);
if (buf_s_2[i+2] != crc)
return luaL_error(L, "crc error");
serial_b = (serial_b << 16) + (buf_s_2[i] << 8) + buf_s_2[i+1];
}
lua_pushinteger(L, serial_a);
lua_pushinteger(L, serial_b);
return 2;
}
// Reads electronic firmware revision from device and returns them
// Lua: firmware = si7021.firmware()
static int si7021_lua_firmware(lua_State* L) {
uint8_t firmware;
uint8_t buf_f[1];
read_serial(SI7021_CMD_FIRM_REV, buf_f, 1);
firmware = buf_f[0];
lua_pushinteger(L, firmware);
return 1;
}
static const LUA_REG_TYPE si7021_map[] = {
{ LSTRKEY( "setup" ), LFUNCVAL(si7021_lua_setup) },
{ LSTRKEY( "setting" ), LFUNCVAL(si7021_lua_setting) },
{ LSTRKEY( "read" ), LFUNCVAL(si7021_lua_read) },
{ LSTRKEY( "serial" ), LFUNCVAL(si7021_lua_serial) },
{ LSTRKEY( "firmware" ), LFUNCVAL(si7021_lua_firmware) },
{ LSTRKEY( "RH12_TEMP14" ), LNUMVAL(SI7021_RH12_TEMP14) },
{ LSTRKEY( "RH08_TEMP12" ), LNUMVAL(SI7021_RH08_TEMP12) },
{ LSTRKEY( "RH10_TEMP13" ), LNUMVAL(SI7021_RH10_TEMP13) },
{ LSTRKEY( "RH11_TEMP11" ), LNUMVAL(SI7021_RH11_TEMP11) },
{ LSTRKEY( "HEATER_ENABLE" ), LNUMVAL(SI7021_HEATER_ENABLE) },
{ LSTRKEY( "HEATER_DISABLE" ), LNUMVAL(SI7021_HEATER_DISABLE) },
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(SI7021, "si7021", si7021_map, NULL);
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include "lstring.h"
#ifndef LOCAL_LUA
#include "module.h"
#include "c_string.h"
#include "c_math.h"
#include "c_limits.h"
#endif
#define JSONSL_STATE_USER_FIELDS int lua_object_ref; int used_count;
#define JSONSL_NO_JPR
#include "jsonsl.c"
#define LUA_SJSONLIBNAME "sjson"
#define DEFAULT_DEPTH 20
#define DBG_PRINTF(...)
typedef struct {
jsonsl_t jsn;
int result_ref;
int hkey_ref;
int null_ref;
int metatable;
int pos_ref;
uint8_t complete;
const char *error;
lua_State *L;
size_t min_needed;
size_t min_available;
size_t buffer_len;
const char *buffer; // Points into buffer_ref
int buffer_ref;
} JSN_DATA;
#define get_parent_object_ref() ((state->level == 1) ? data->result_ref : state[-1].lua_object_ref)
#define get_parent_object_used_count_pre_inc() ((state->level == 1) ? 1 : ++state[-1].used_count)
static const char* get_state_buffer(JSN_DATA *ctx, struct jsonsl_state_st *state)
{
size_t offset = state->pos_begin - ctx->min_available;
return ctx->buffer + offset;
}
// The elem data is a ref
static int error_callback(jsonsl_t jsn,
jsonsl_error_t err,
struct jsonsl_state_st *state,
char *at)
{
JSN_DATA *data = (JSN_DATA *) jsn->data;
data->error = jsonsl_strerror(err);
//fprintf(stderr, "Got error at pos %lu: %s\n", jsn->pos, jsonsl_strerror(err));
return 0;
}
static void
create_table(JSN_DATA *data) {
lua_newtable(data->L);
if (data->metatable != LUA_NOREF) {
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->metatable);
lua_setmetatable(data->L, -2);
}
}
static void
create_new_element(jsonsl_t jsn,
jsonsl_action_t action,
struct jsonsl_state_st *state,
const char *buf)
{
JSN_DATA *data = jsn->data;
DBG_PRINTF("L%d: new action %d @ %d state->type %s\n", state->level, action, state->pos_begin, jsonsl_strtype(state->type));
DBG_PRINTF("buf: '%s' ('%.10s')\n", buf, get_state_buffer(data, state));
state->lua_object_ref = LUA_NOREF;
switch(state->type) {
case JSONSL_T_SPECIAL:
case JSONSL_T_STRING:
case JSONSL_T_HKEY:
break;
case JSONSL_T_LIST:
case JSONSL_T_OBJECT:
create_table(data);
state->lua_object_ref = lua_ref(data->L, 1);
state->used_count = 0;
lua_rawgeti(data->L, LUA_REGISTRYINDEX, get_parent_object_ref());
if (data->hkey_ref == LUA_NOREF) {
// list, so append
lua_pushnumber(data->L, get_parent_object_used_count_pre_inc());
DBG_PRINTF("Adding array element\n");
} else {
// object, so
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->hkey_ref);
lua_unref(data->L, data->hkey_ref);
data->hkey_ref = LUA_NOREF;
DBG_PRINTF("Adding hash element\n");
}
if (data->pos_ref != LUA_NOREF && state->level > 1) {
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->pos_ref);
lua_pushnumber(data->L, state->level - 1);
lua_pushvalue(data->L, -3); // get the key
lua_settable(data->L, -3);
lua_pop(data->L, 1);
}
// At this point, the stack:
// top: index/hash key
// : table
int want_value = 1;
// Invoke the checkpath method if possible
if (data->pos_ref != LUA_NOREF) {
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->metatable);
lua_getfield(data->L, -1, "checkpath");
if (lua_type(data->L, -1) != LUA_TNIL) {
// Call with the new table and the path as arguments
lua_rawgeti(data->L, LUA_REGISTRYINDEX, state->lua_object_ref);
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->pos_ref);
lua_call(data->L, 2, 1);
want_value = lua_toboolean(data->L, -1);
}
lua_pop(data->L, 2); // Discard the metatable and either the getfield result or retval
}
if (want_value) {
lua_rawgeti(data->L, LUA_REGISTRYINDEX, state->lua_object_ref);
lua_settable(data->L, -3);
lua_pop(data->L, 1); // the table
} else {
lua_pop(data->L, 2); // the index and table
}
break;
default:
DBG_PRINTF("Unhandled type %c\n", state->type);
luaL_error(data->L, "Unhandled type");
break;
}
data->min_needed = state->pos_begin;
}
static void push_number(JSN_DATA *data, struct jsonsl_state_st *state) {
lua_pushlstring(data->L, get_state_buffer(data, state), state->pos_cur - state->pos_begin);
LUA_NUMBER r = lua_tonumber(data->L, -1);
lua_pop(data->L, 1);
lua_pushnumber(data->L, r);
}
static int fromhex(char c) {
if (c <= '9') {
return c & 0xf;
}
return ((c - 'A' + 10) & 0xf);
}
static void output_utf8(luaL_Buffer *buf, int c) {
char space[4];
char *b = space;
if (c<0x80) *b++=c;
else if (c<0x800) *b++=192+c/64, *b++=128+c%64;
else if (c-0xd800u<0x800) *b++ = '?';
else if (c<0x10000) *b++=224+c/4096, *b++=128+c/64%64, *b++=128+c%64;
else if (c<0x110000) *b++=240+c/262144, *b++=128+c/4096%64, *b++=128+c/64%64, *b++=128+c%64;
else *b++ = '?';
luaL_addlstring(buf, space, b - space);
}
static void push_string(JSN_DATA *data, struct jsonsl_state_st *state) {
luaL_Buffer b;
luaL_buffinit(data->L, &b);
int i;
const char *c = get_state_buffer(data, state) + 1;
for (i = 0; i < state->pos_cur - state->pos_begin - 1; i++) {
int nc = c[i];
if (nc == '\\') {
i++;
nc = c[i] & 255;
switch (c[i]) {
case 'b':
nc = '\b';
break;
case 'f':
nc = '\f';
break;
case 'n':
nc = '\n';
break;
case 'r':
nc = '\r';
break;
case 't':
nc = '\t';
break;
case 'u':
nc = fromhex(c[++i]) << 12;
nc += fromhex(c[++i]) << 8;
nc += fromhex(c[++i]) << 4;
nc += fromhex(c[++i]) ;
output_utf8(&b, nc);
continue;
}
}
luaL_putchar(&b, nc);
}
luaL_pushresult(&b);
}
static void
cleanup_closing_element(jsonsl_t jsn,
jsonsl_action_t action,
struct jsonsl_state_st *state,
const char *at)
{
JSN_DATA *data = (JSN_DATA *) jsn->data;
DBG_PRINTF( "L%d: cc action %d state->type %s\n", state->level, action, jsonsl_strtype(state->type));
DBG_PRINTF( "buf (%d - %d): '%.*s'\n", state->pos_begin, state->pos_cur, state->pos_cur - state->pos_begin, get_state_buffer(data, state));
DBG_PRINTF( "at: '%s'\n", at);
switch (state->type) {
case JSONSL_T_HKEY:
push_string(data, state);
data->hkey_ref = lua_ref(data->L, 1);
break;
case JSONSL_T_STRING:
lua_rawgeti(data->L, LUA_REGISTRYINDEX, get_parent_object_ref());
if (data->hkey_ref == LUA_NOREF) {
// list, so append
lua_pushnumber(data->L, get_parent_object_used_count_pre_inc());
} else {
// object, so
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->hkey_ref);
lua_unref(data->L, data->hkey_ref);
data->hkey_ref = LUA_NOREF;
}
push_string(data, state);
lua_settable(data->L, -3);
lua_pop(data->L, 1);
break;
case JSONSL_T_SPECIAL:
DBG_PRINTF("Special flags = 0x%x\n", state->special_flags);
// need to deal with true/false/null
if (state->special_flags & (JSONSL_SPECIALf_TRUE|JSONSL_SPECIALf_FALSE|JSONSL_SPECIALf_NUMERIC|JSONSL_SPECIALf_NULL)) {
if (state->special_flags & JSONSL_SPECIALf_TRUE) {
lua_pushboolean(data->L, 1);
} else if (state->special_flags & JSONSL_SPECIALf_FALSE) {
lua_pushboolean(data->L, 0);
} else if (state->special_flags & JSONSL_SPECIALf_NULL) {
DBG_PRINTF("Outputting null\n");
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->null_ref);
} else if (state->special_flags & JSONSL_SPECIALf_NUMERIC) {
push_number(data, state);
}
lua_rawgeti(data->L, LUA_REGISTRYINDEX, get_parent_object_ref());
if (data->hkey_ref == LUA_NOREF) {
// list, so append
lua_pushnumber(data->L, get_parent_object_used_count_pre_inc());
} else {
// object, so
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->hkey_ref);
lua_unref(data->L, data->hkey_ref);
data->hkey_ref = LUA_NOREF;
}
lua_pushvalue(data->L, -3);
lua_remove(data->L, -4);
lua_settable(data->L, -3);
lua_pop(data->L, 1);
}
break;
case JSONSL_T_OBJECT:
case JSONSL_T_LIST:
lua_unref(data->L, state->lua_object_ref);
state->lua_object_ref = LUA_NOREF;
if (data->pos_ref != LUA_NOREF) {
lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->pos_ref);
lua_pushnumber(data->L, state->level);
lua_pushnil(data->L);
lua_settable(data->L, -3);
lua_pop(data->L, 1);
}
if (state->level == 1) {
data->complete = 1;
}
break;
}
}
static int sjson_decoder_int(lua_State *L, int argno) {
int nlevels = DEFAULT_DEPTH;
if (lua_type(L, argno) == LUA_TTABLE) {
lua_getfield(L, argno, "depth");
nlevels = lua_tointeger(L, argno);
if (nlevels == 0) {
nlevels = DEFAULT_DEPTH;
}
if (nlevels < 4) {
nlevels = 4;
}
if (nlevels > 1000) {
nlevels = 1000;
}
lua_pop(L, 1);
}
JSN_DATA *data = (JSN_DATA *) lua_newuserdata(L, sizeof(JSN_DATA) + jsonsl_get_size(nlevels));
//
// Associate its metatable
luaL_getmetatable(L, "sjson.decoder");
lua_setmetatable(L, -2);
jsonsl_t jsn = jsonsl_init((jsonsl_t) (data + 1), nlevels);
int i;
for (i = 0; i < jsn->levels_max; i++) {
jsn->stack[i].lua_object_ref = LUA_NOREF;
}
data->jsn = jsn;
data->result_ref = LUA_NOREF;
data->null_ref = LUA_REFNIL;
data->metatable = LUA_NOREF;
data->hkey_ref = LUA_NOREF;
data->pos_ref = LUA_NOREF;
data->buffer_ref = LUA_NOREF;
data->complete = 0;
data->error = NULL;
data->L = L;
data->buffer_len = 0;
data->min_needed = data->min_available = jsn->pos;
lua_pushlightuserdata(L, 0);
data->null_ref = lua_ref(L, 1);
// This may throw...
lua_newtable(L);
data->result_ref = luaL_ref(L, LUA_REGISTRYINDEX);
if (lua_type(L, argno) == LUA_TTABLE) {
luaL_unref(L, LUA_REGISTRYINDEX, data->null_ref);
data->null_ref = LUA_NOREF;
lua_getfield(L, argno, "null");
data->null_ref = lua_ref(L, 1);
lua_getfield(L, argno, "metatable");
lua_pushvalue(L, -1);
data->metatable = lua_ref(L, 1);
if (lua_type(L, -1) != LUA_TNIL) {
lua_getfield(L, -1, "checkpath");
if (lua_type(L, -1) != LUA_TNIL) {
lua_newtable(L);
data->pos_ref = lua_ref(L, 1);
}
lua_pop(L, 1); // Throw away the checkpath value
}
lua_pop(L, 1); // Throw away the metatable
}
jsonsl_enable_all_callbacks(data->jsn);
jsn->action_callback = NULL;
jsn->action_callback_PUSH = create_new_element;
jsn->action_callback_POP = cleanup_closing_element;
jsn->error_callback = error_callback;
jsn->data = data;
jsn->max_callback_level = nlevels;
return 1;
}
static int sjson_decoder(lua_State *L) {
return sjson_decoder_int(L, 1);
}
static int sjson_decoder_result_int(lua_State *L, JSN_DATA *data) {
if (!data->complete) {
luaL_error(L, "decode not complete");
}
lua_rawgeti(L, LUA_REGISTRYINDEX, data->result_ref);
lua_rawgeti(L, -1, 1);
lua_remove(L, -2);
return 1;
}
static int sjson_decoder_result(lua_State *L) {
JSN_DATA *data = (JSN_DATA *)luaL_checkudata(L, 1, "sjson.decoder");
return sjson_decoder_result_int(L, data);
}
static void sjson_free_working_data(lua_State *L, JSN_DATA *data) {
jsonsl_t jsn = data->jsn;
int i;
for (i = 0; i < jsn->levels_max; i++) {
luaL_unref(L, LUA_REGISTRYINDEX, jsn->stack[i].lua_object_ref);
jsn->stack[i].lua_object_ref = LUA_NOREF;
}
luaL_unref(L, LUA_REGISTRYINDEX, data->metatable);
data->metatable = LUA_NOREF;
luaL_unref(L, LUA_REGISTRYINDEX, data->hkey_ref);
data->hkey_ref = LUA_NOREF;
luaL_unref(L, LUA_REGISTRYINDEX, data->null_ref);
data->null_ref = LUA_NOREF;
luaL_unref(L, LUA_REGISTRYINDEX, data->pos_ref);
data->pos_ref = LUA_NOREF;
luaL_unref(L, LUA_REGISTRYINDEX, data->buffer_ref);
data->buffer_ref = LUA_NOREF;
}
static int sjson_decoder_write_int(lua_State *L, int udata_pos, int string_pos) {
JSN_DATA *data = (JSN_DATA *)luaL_checkudata(L, udata_pos, "sjson.decoder");
size_t len;
const char *str = luaL_checklstring(L, string_pos, &len);
if (data->error) {
luaL_error(L, "JSON parse error: previous call");
}
if (!data->complete) {
data->L = L;
// Merge into any existing buffer and deal with discard
if (data->buffer_ref != LUA_NOREF) {
luaL_Buffer b;
luaL_buffinit(L, &b);
lua_rawgeti(L, LUA_REGISTRYINDEX, data->buffer_ref);
size_t prev_len;
const char *prev_buffer = luaL_checklstring(L, -1, &prev_len);
lua_pop(L, 1); // But string still referenced so it cannot move
int discard = data->min_needed - data->min_available;
prev_buffer += discard;
prev_len -= discard;
if (prev_len > 0) {
luaL_addlstring(&b, prev_buffer, prev_len);
}
data->min_available += discard;
luaL_unref(L, LUA_REGISTRYINDEX, data->buffer_ref);
data->buffer_ref = LUA_NOREF;
lua_pushvalue(L, string_pos);
luaL_addvalue(&b);
luaL_pushresult(&b);
} else {
lua_pushvalue(L, string_pos);
}
size_t blen;
data->buffer = luaL_checklstring(L, -1, &blen);
data->buffer_len = blen;
data->buffer_ref = lua_ref(L, 1);
jsonsl_feed(data->jsn, str, len);
if (data->error) {
luaL_error(L, "JSON parse error: %s", data->error);
}
}
if (data->complete) {
// We no longer need the buffer
sjson_free_working_data(L, data);
return sjson_decoder_result_int(L, data);
}
return 0;
}
static int sjson_decoder_write(lua_State *L) {
return sjson_decoder_write_int(L, 1, 2);
}
static int sjson_decode(lua_State *L) {
int push_count = sjson_decoder_int(L, 2);
if (push_count != 1) {
luaL_error(L, "Internal error in sjson.deocder");
}
luaL_checkudata(L, -1, "sjson.decoder");
push_count = sjson_decoder_write_int(L, -1, 1);
if (push_count != 1) {
luaL_error(L, "Incomplete JSON object passed to sjson.decode");
}
// Now we have two items on the stack -- the udata and the result
lua_remove(L, -2);
return 1;
}
static int sjson_decoder_destructor(lua_State *L) {
JSN_DATA *data = (JSN_DATA *)luaL_checkudata(L, 1, "sjson.decoder");
sjson_free_working_data(L, data);
data->jsn = NULL;
luaL_unref(L, LUA_REGISTRYINDEX, data->result_ref);
data->result_ref = LUA_NOREF;
DBG_PRINTF("Destructor called\n");
return 0;
}
//
//--------------------------------- ENCODER BELOW
//
//
//
//#undef DBG_PRINTF
//#define DBG_PRINTF printf
typedef struct {
int lua_object_ref;
// for arrays
// 0 -> [
// 1 -> first element
// 2 -> ,
// 3 -> second element
// 4 -> ]
// for objects
// 0 -> { firstkey :
// 1 -> first value
// 2 -> , secondkey :
// 3 -> second value
// 4 -> }
short offset;
// -1 for objects
// 0 -> n maximum integer key = n
short size;
int lua_key_ref;
} ENC_DATA_STATE;
typedef struct {
ENC_DATA_STATE *stack;
int nlevels;
int level;
int current_str_ref;
int null_ref;
int offset;
} ENC_DATA;
static int sjson_encoder_get_table_size(lua_State *L, int argno) {
// Returns -1 for object, otherwise the maximum integer key value found.
lua_pushvalue(L, argno);
// stack now contains: -1 => table
lua_pushnil(L);
// stack now contains: -1 => nil; -2 => table
//
int maxkey = 0;
while (lua_next(L, -2)) {
lua_pop(L, 1);
// stack now contains: -1 => key; -2 => table
if (lua_type(L, -1) == LUA_TNUMBER) {
int val = lua_tointeger(L, -1);
if (val > maxkey) {
maxkey = val;
} else if (val <= 0) {
maxkey = -1;
lua_pop(L, 1);
break;
}
} else {
maxkey = -1;
lua_pop(L, 1);
break;
}
}
lua_pop(L, 1);
return maxkey;
}
static void enc_pop_stack(lua_State *L, ENC_DATA *data) {
if (data->level < 0) {
luaL_error(L, "encoder stack underflow");
}
ENC_DATA_STATE *state = &data->stack[data->level];
lua_unref(L, state->lua_object_ref);
state->lua_object_ref = LUA_NOREF;
lua_unref(L, state->lua_key_ref);
state->lua_key_ref = LUA_REFNIL;
data->level--;
}
static void enc_push_stack(lua_State *L, ENC_DATA *data, int argno) {
if (++data->level >= data->nlevels) {
luaL_error(L, "encoder stack overflow");
}
lua_pushvalue(L, argno);
ENC_DATA_STATE *state = &data->stack[data->level];
state->lua_object_ref = lua_ref(L, 1);
state->size = sjson_encoder_get_table_size(L, argno);
state->offset = 0; // We haven't started on this one yet
}
static int sjson_encoder(lua_State *L) {
int nlevels = DEFAULT_DEPTH;
int argno = 1;
// Validate first arg is a table
luaL_checktype(L, argno++, LUA_TTABLE);
if (lua_type(L, argno) == LUA_TTABLE) {
lua_getfield(L, argno, "depth");
nlevels = lua_tointeger(L, argno);
if (nlevels == 0) {
nlevels = DEFAULT_DEPTH;
}
if (nlevels < 4) {
nlevels = 4;
}
if (nlevels > 1000) {
nlevels = 1000;
}
lua_pop(L, 1);
}
ENC_DATA *data = (ENC_DATA *) lua_newuserdata(L, sizeof(ENC_DATA) + nlevels * sizeof(ENC_DATA_STATE));
// Associate its metatable
luaL_getmetatable(L, "sjson.encoder");
lua_setmetatable(L, -2);
data->nlevels = nlevels;
data->level = -1;
data->stack = (ENC_DATA_STATE *) (data + 1);
data->current_str_ref = LUA_NOREF;
int i;
for (i = 0; i < nlevels; i++) {
data->stack[i].lua_object_ref = LUA_NOREF;
data->stack[i].lua_key_ref = LUA_REFNIL;
}
enc_push_stack(L, data, 1);
data->null_ref = LUA_REFNIL;
if (lua_type(L, argno) == LUA_TTABLE) {
luaL_unref(L, LUA_REGISTRYINDEX, data->null_ref);
data->null_ref = LUA_NOREF;
lua_getfield(L, argno, "null");
data->null_ref = lua_ref(L, 1);
}
return 1;
}
static void encode_lua_object(lua_State *L, ENC_DATA *data, int argno, const char *prefix, const char *suffix) {
luaL_Buffer b;
luaL_buffinit(L, &b);
luaL_addstring(&b, prefix);
int type = lua_type(L, argno);
if (type == LUA_TSTRING) {
// Check to see if it is the NULL value
if (data->null_ref != LUA_REFNIL) {
lua_rawgeti(L, LUA_REGISTRYINDEX, data->null_ref);
if (lua_equal(L, -1, -2)) {
type = LUA_TNIL;
}
lua_pop(L, 1);
}
}
switch (type) {
default:
luaL_error(L, "Cannot encode type %d", type);
break;
case LUA_TLIGHTUSERDATA:
case LUA_TNIL:
luaL_addstring(&b, "null");
break;
case LUA_TBOOLEAN:
luaL_addstring(&b, lua_toboolean(L, argno) ? "true" : "false");
break;
case LUA_TNUMBER:
{
lua_pushvalue(L, argno);
size_t len;
const char *str = lua_tolstring(L, -1, &len);
char value[len + 1];
strcpy(value, str);
lua_pop(L, 1);
luaL_addstring(&b, value);
break;
}
case LUA_TSTRING:
{
luaL_addchar(&b, '"');
size_t len;
const char *str = lua_tolstring(L, argno, &len);
while (len > 0) {
if ((*str & 0xff) < 0x20) {
char value[8];
value[0] = '\\';
char *d = value + 1;
switch(*str) {
case '\f':
*d++ = 'f';
break;
case '\n':
*d++ = 'n';
break;
case '\t':
*d++ = 't';
break;
case '\r':
*d++ = 'r';
break;
case '\b':
*d++ = 'b';
break;
default:
*d++ = 'u';
*d++ = '0';
*d++ = '0';
*d++ = "0123456789abcdef"[(*str >> 4) & 0xf];
*d++ = "0123456789abcdef"[(*str ) & 0xf];
break;
}
*d = '\0';
luaL_addstring(&b, value);
} else {
luaL_addchar(&b, *str);
}
str++;
len--;
}
luaL_addchar(&b, '"');
break;
}
}
luaL_addstring(&b, suffix);
luaL_pushresult(&b);
}
static int sjson_encoder_next_value_is_table(lua_State *L) {
int count = 10;
while ((lua_type(L, -1) == LUA_TFUNCTION
#ifdef LUA_TLIGHTFUNCTION
|| lua_type(L, -1) == LUA_TLIGHTFUNCTION
#endif
) && count-- > 0) {
// call it and use the return value
lua_call(L, 0, 1); // Expecting replacement value
}
return (lua_type(L, -1) == LUA_TTABLE);
}
static void sjson_encoder_make_next_chunk(lua_State *L, ENC_DATA *data) {
if (data->level < 0) {
return;
}
luaL_Buffer b;
luaL_buffinit(L, &b);
// Ending condition
while (data->level >= 0 && !b.lvl) {
ENC_DATA_STATE *state = &data->stack[data->level];
int finished = 0;
if (state->size >= 0) {
if (state->offset == 0) {
// start of object or whatever
luaL_addchar(&b, '[');
}
if (state->offset == state->size << 1) {
luaL_addchar(&b, ']');
finished = 1;
} else if ((state->offset & 1) == 0) {
if (state->offset > 0) {
luaL_addchar(&b, ',');
}
} else {
// output the value
lua_rawgeti(L, LUA_REGISTRYINDEX, state->lua_object_ref);
lua_rawgeti(L, -1, (state->offset >> 1) + 1);
if (sjson_encoder_next_value_is_table(L)) {
enc_push_stack(L, data, -1);
lua_pop(L, 2);
state->offset++;
continue;
}
encode_lua_object(L, data, -1, "", "");
lua_remove(L, -2);
lua_remove(L, -2);
luaL_addvalue(&b);
}
state->offset++;
} else {
lua_rawgeti(L, LUA_REGISTRYINDEX, state->lua_object_ref);
// stack now contains: -1 => table
lua_rawgeti(L, LUA_REGISTRYINDEX, state->lua_key_ref);
// stack now contains: -1 => nil or key; -2 => table
if (lua_next(L, -2)) {
// save the key
if (state->offset & 1) {
lua_unref(L, state->lua_key_ref);
state->lua_key_ref = LUA_NOREF;
// Duplicate the key
lua_pushvalue(L, -2);
state->lua_key_ref = lua_ref(L, 1);
}
if ((state->offset & 1) == 0) {
// copy the key so that lua_tostring does not modify the original
lua_pushvalue(L, -2);
// stack now contains: -1 => key; -2 => value; -3 => key; -4 => table
// key
lua_tostring(L, -1);
encode_lua_object(L, data, -1, state->offset ? "," : "{", ":");
lua_remove(L, -2);
lua_remove(L, -2);
lua_remove(L, -2);
lua_remove(L, -2);
} else {
if (sjson_encoder_next_value_is_table(L)) {
enc_push_stack(L, data, -1);
lua_pop(L, 3);
state->offset++;
continue;
}
encode_lua_object(L, data, -1, "", "");
lua_remove(L, -2);
lua_remove(L, -2);
lua_remove(L, -2);
}
luaL_addvalue(&b);
} else {
lua_pop(L, 1);
// We have got to the end
luaL_addchar(&b, '}');
finished = 1;
}
state->offset++;
}
if (finished) {
enc_pop_stack(L, data);
}
}
luaL_pushresult(&b);
data->current_str_ref = lua_ref(L, 1);
data->offset = 0;
}
static int sjson_encoder_read_int(lua_State *L, ENC_DATA *data, int readsize) {
luaL_Buffer b;
luaL_buffinit(L, &b);
size_t len;
do {
// Fill the buffer with (up to) readsize characters
if (data->current_str_ref != LUA_NOREF) {
// this is not allowed
lua_rawgeti(L, LUA_REGISTRYINDEX, data->current_str_ref);
const char *str = lua_tolstring(L, -1, &len);
lua_pop(L, 1); // Note that we still have the string referenced so it can't go away
int amnt = len - data->offset;;
if (amnt > readsize) {
amnt = readsize;
}
luaL_addlstring(&b, str + data->offset, amnt);
data->offset += amnt;
readsize -= amnt;
if (data->offset == len) {
lua_unref(L, data->current_str_ref);
data->current_str_ref = LUA_NOREF;
}
}
if (readsize > 0) {
// Make the next chunk
sjson_encoder_make_next_chunk(L, data);
}
} while (readsize > 0 && data->current_str_ref != LUA_NOREF);
luaL_pushresult(&b);
lua_tolstring(L, -1, &len);
if (len == 0) {
// we have got to the end
lua_pop(L, 1);
return 0;
}
return 1;
}
static int sjson_encoder_read(lua_State *L) {
ENC_DATA *data = (ENC_DATA *)luaL_checkudata(L, 1, "sjson.encoder");
int readsize = 1024;
if (lua_type(L, 2) == LUA_TNUMBER) {
readsize = lua_tointeger(L, 2);
if (readsize < 1) {
readsize = 1;
}
}
return sjson_encoder_read_int(L, data, readsize);
}
static int sjson_encode(lua_State *L) {
sjson_encoder(L);
ENC_DATA *data = (ENC_DATA *)luaL_checkudata(L, -1, "sjson.encoder");
int rc = sjson_encoder_read_int(L, data, 1000000);
lua_remove(L, -(rc + 1));
return rc;
}
static int sjson_encoder_destructor(lua_State *L) {
ENC_DATA *data = (ENC_DATA *)luaL_checkudata(L, 1, "sjson.encoder");
int i;
for (i = 0; i < data->nlevels; i++) {
luaL_unref(L, LUA_REGISTRYINDEX, data->stack[i].lua_object_ref);
luaL_unref(L, LUA_REGISTRYINDEX, data->stack[i].lua_key_ref);
}
luaL_unref(L, LUA_REGISTRYINDEX, data->null_ref);
luaL_unref(L, LUA_REGISTRYINDEX, data->current_str_ref);
DBG_PRINTF("Destructor called\n");
return 0;
}
#ifdef LOCAL_LUA
static const luaL_Reg sjson_encoder_map[] = {
{ "read", sjson_encoder_read },
{ "__gc", sjson_encoder_destructor },
{ NULL, NULL }
};
static const luaL_Reg sjson_decoder_map[] = {
{ "write", sjson_decoder_write },
{ "result", sjson_decoder_result },
{ "__gc", sjson_decoder_destructor },
{ NULL, NULL }
};
static const luaL_Reg sjsonlib[] = {
{ "decode", sjson_decode },
{ "decoder", sjson_decoder },
{ "encode", sjson_encode },
{ "encoder", sjson_encoder },
{NULL, NULL}
};
#else
static const LUA_REG_TYPE sjson_encoder_map[] = {
{ LSTRKEY( "read" ), LFUNCVAL( sjson_encoder_read ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( sjson_encoder_destructor ) },
{ LSTRKEY( "__index" ), LROVAL( sjson_encoder_map ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE sjson_decoder_map[] = {
{ LSTRKEY( "write" ), LFUNCVAL( sjson_decoder_write ) },
{ LSTRKEY( "result" ), LFUNCVAL( sjson_decoder_result ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( sjson_decoder_destructor ) },
{ LSTRKEY( "__index" ), LROVAL( sjson_decoder_map ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE sjson_map[] = {
{ LSTRKEY( "encode" ), LFUNCVAL( sjson_encode ) },
{ LSTRKEY( "decode" ), LFUNCVAL( sjson_decode ) },
{ LSTRKEY( "encoder" ), LFUNCVAL( sjson_encoder ) },
{ LSTRKEY( "decoder" ), LFUNCVAL( sjson_decoder ) },
{ LSTRKEY( "NULL" ), LUDATA( 0 ) },
{ LNILKEY, LNILVAL }
};
#endif
LUALIB_API int luaopen_sjson (lua_State *L) {
#ifdef LOCAL_LUA
luaL_register(L, LUA_SJSONLIBNAME, sjsonlib);
lua_getglobal(L, LUA_SJSONLIBNAME);
lua_pushstring(L, "NULL");
lua_pushlightuserdata(L, 0);
lua_settable(L, -3);
lua_pop(L, 1);
luaL_newmetatable(L, "sjson.encoder");
luaL_register(L, NULL, sjson_encoder_map);
lua_setfield(L, -1, "__index");
luaL_newmetatable(L, "sjson.decoder");
luaL_register(L, NULL, sjson_decoder_map);
lua_setfield(L, -1, "__index");
#else
luaL_rometatable(L, "sjson.decoder", (void *)sjson_decoder_map);
luaL_rometatable(L, "sjson.encoder", (void *)sjson_encoder_map);
#endif
return 1;
}
#ifndef LOCAL_LUA
NODEMCU_MODULE(SJSON, "sjson", sjson_map, luaopen_sjson);
#endif
......@@ -4,6 +4,8 @@
#include "lauxlib.h"
#include "platform.h"
#include "driver/spi.h"
#define SPI_HALFDUPLEX 0
#define SPI_FULLDUPLEX 1
......@@ -196,37 +198,35 @@ static int spi_recv( lua_State *L )
}
// Lua: spi.set_mosi( id, offset, bitlen, data1, [data2], ..., [datan] )
// Lua: spi.set_mosi( id, string )
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;
int id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( spi, id );
if (offset < 0 || offset > 511) {
return luaL_error( L, "offset out of range" );
}
if (lua_type( L, 2 ) == LUA_TSTRING) {
size_t len;
const char *data = luaL_checklstring( L, 2, &len );
luaL_argcheck( L, 2, len <= 64, "out of range" );
if (bitlen < 1 || bitlen > 32) {
return luaL_error( L, "bitlen out of range" );
}
spi_mast_blkset( id, len * 8, data );
if (lua_gettop( L ) < 4) {
return luaL_error( L, "too few args" );
}
} else {
int offset = luaL_checkinteger( L, 2 );
int bitlen = luaL_checkinteger( L, 3 );
for (argn = 4; argn <= lua_gettop( L ); argn++, offset += bitlen )
{
u32 data = ( u32 )luaL_checkinteger(L, argn );
luaL_argcheck( L, 2, offset >= 0 && offset <= 511, "out of range" );
luaL_argcheck( L, 3, bitlen >= 1 && bitlen <= 32, "out of range" );
if (offset + bitlen > 512) {
return luaL_error( L, "data range exceeded > 512 bits" );
}
for (int 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" );
spi_mast_set_mosi( id, offset, bitlen, data );
}
}
......@@ -234,72 +234,69 @@ static int spi_set_mosi( lua_State *L )
}
// Lua: data = spi.get_miso( id, offset, bitlen, num )
// Lua: string = spi.get_miso( id, len )
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;
int id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( spi, id );
if (offset < 0 || offset > 511) {
return luaL_error( L, "out of range" );
}
if (lua_gettop( L ) == 2) {
uint8_t data[64];
int len = luaL_checkinteger( L, 2 );
if (bitlen < 1 || bitlen > 32) {
return luaL_error( L, "bitlen out of range" );
}
luaL_argcheck( L, 2, len >= 1 && len <= 64, "out of range" );
if (offset + bitlen * num > 512) {
return luaL_error( L, "out of range" );
}
spi_mast_blkget( id, len * 8, data );
for (i = 0; i < num; i++)
{
lua_pushinteger( L, platform_spi_get_miso( id, offset + (bitlen * i), bitlen ) );
lua_pushlstring( L, data, len );
return 1;
} else {
int offset = luaL_checkinteger( L, 2 );
int bitlen = luaL_checkinteger( L, 3 );
int num = luaL_checkinteger( L, 4 ), i;
luaL_argcheck( L, 2, offset >= 0 && offset <= 511, "out of range" );
luaL_argcheck( L, 3, bitlen >= 1 && bitlen <= 32, "out of range" );
if (offset + bitlen * num > 512) {
return luaL_error( L, "out of range" );
}
for (i = 0; i < num; i++) {
lua_pushinteger( L, spi_mast_get_miso( id, offset + (bitlen * i), bitlen ) );
}
return num;
}
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 );
int id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( spi, id );
if (cmd_bitlen < 0 || cmd_bitlen > 16) {
return luaL_error( L, "cmd_bitlen out of range" );
}
int cmd_bitlen = luaL_checkinteger( L, 2 );
u16 cmd_data = ( u16 )luaL_checkinteger( L, 3 );
luaL_argcheck( L, 2, cmd_bitlen >= 0 && cmd_bitlen <= 16, "out of range" );
if (addr_bitlen < 0 || addr_bitlen > 32) {
return luaL_error( L, "addr_bitlen out of range" );
}
int addr_bitlen = luaL_checkinteger( L, 4 );
u32 addr_data = ( u32 )luaL_checkinteger( L, 5 );
luaL_argcheck( L, 4, addr_bitlen >= 0 && addr_bitlen <= 32, "out of range" );
if (mosi_bitlen < 0 || mosi_bitlen > 512) {
return luaL_error( L, "mosi_bitlen out of range" );
}
int mosi_bitlen = luaL_checkinteger( L, 6 );
luaL_argcheck( L, 6, mosi_bitlen >= 0 && mosi_bitlen <= 512, "out of range" );
if (dummy_bitlen < 0 || dummy_bitlen > 256) {
return luaL_error( L, "dummy_bitlen out of range" );
}
int dummy_bitlen = luaL_checkinteger( L, 7 );
luaL_argcheck( L, 7, dummy_bitlen >= 0 && dummy_bitlen <= 256, "out of range" );
if (miso_bitlen < -512 || miso_bitlen > 512) {
return luaL_error( L, "miso_bitlen out of range" );
}
int miso_bitlen = luaL_checkinteger( L, 8 );
luaL_argcheck( L, 8, miso_bitlen >= -512 && miso_bitlen <= 512, "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" );
}
spi_mast_transaction( id, cmd_bitlen, cmd_data, addr_bitlen, addr_data,
mosi_bitlen, dummy_bitlen, miso_bitlen );
return 0;
}
......
// ***************************************************************************
// TCS34725 module for ESP8266 with nodeMCU
//
// Written by K. Townsend (microBuilder.eu), Adapted for nodeMCU by Travis Howse (tjhowse gmail.com)
//
// BSD (see license.txt)
// ***************************************************************************
// Original header:
/**************************************************************************/
/*!
@file tcs34725.c
@author K. Townsend (microBuilder.eu)
@ingroup Sensors
@brief Driver for the TAOS TCS34725 I2C digital RGB/color sensor
@license BSD (see license.txt)
*/
/**************************************************************************/
//#define NODE_DEBUG
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
#include "c_math.h"
// #define TCS34725_ADDRESS (0x29<<1)
#define TCS34725_ADDRESS (0x29)
#define TCS34725_BUS_ID (0x00) /* ?? Not sure what this is for . Nodemcu I2C bus ID? */
#define TCS34725_READBIT (0x01)
#define TCS34725_COMMAND_BIT (0x80)
#define TCS34725_ENABLE (0x00)
#define TCS34725_ENABLE_AIEN (0x10) /* RGBC Interrupt Enable */
#define TCS34725_ENABLE_WEN (0x08) /* Wait enable - Writing 1 activates the wait timer */
#define TCS34725_ENABLE_AEN (0x02) /* RGBC Enable - Writing 1 actives the ADC, 0 disables it */
#define TCS34725_ENABLE_PON (0x01) /* Power on - Writing 1 activates the internal oscillator, 0 disables it */
#define TCS34725_ATIME (0x01) /* Integration time */
#define TCS34725_WTIME (0x03) /* Wait time (if TCS34725_ENABLE_WEN is asserted) */
#define TCS34725_WTIME_2_4MS (0xFF) /* WLONG0 = 2.4ms WLONG1 = 0.029s */
#define TCS34725_WTIME_204MS (0xAB) /* WLONG0 = 204ms WLONG1 = 2.45s */
#define TCS34725_WTIME_614MS (0x00) /* WLONG0 = 614ms WLONG1 = 7.4s */
#define TCS34725_AILTL (0x04) /* Clear channel lower interrupt threshold */
#define TCS34725_AILTH (0x05)
#define TCS34725_AIHTL (0x06) /* Clear channel upper interrupt threshold */
#define TCS34725_AIHTH (0x07)
#define TCS34725_PERS (0x0C) /* Persistence register - basic SW filtering mechanism for interrupts */
#define TCS34725_PERS_NONE (0b0000) /* Every RGBC cycle generates an interrupt */
#define TCS34725_PERS_1_CYCLE (0b0001) /* 1 clean channel value outside threshold range generates an interrupt */
#define TCS34725_PERS_2_CYCLE (0b0010) /* 2 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_3_CYCLE (0b0011) /* 3 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_5_CYCLE (0b0100) /* 5 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_10_CYCLE (0b0101) /* 10 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_15_CYCLE (0b0110) /* 15 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_20_CYCLE (0b0111) /* 20 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_25_CYCLE (0b1000) /* 25 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_30_CYCLE (0b1001) /* 30 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_35_CYCLE (0b1010) /* 35 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_40_CYCLE (0b1011) /* 40 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_45_CYCLE (0b1100) /* 45 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_50_CYCLE (0b1101) /* 50 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_55_CYCLE (0b1110) /* 55 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_60_CYCLE (0b1111) /* 60 clean channel values outside threshold range generates an interrupt */
#define TCS34725_CONFIG (0x0D)
#define TCS34725_CONFIG_WLONG (0x02) /* Choose between short and long (12x) wait times via TCS34725_WTIME */
#define TCS34725_CONTROL (0x0F) /* Set the gain level for the sensor */
#define TCS34725_ID (0x12) /* 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727 */
#define TCS34725_STATUS (0x13)
#define TCS34725_STATUS_AINT (0x10) /* RGBC Clean channel interrupt */
#define TCS34725_STATUS_AVALID (0x01) /* Indicates that the RGBC channels have completed an integration cycle */
#define TCS34725_CDATAL (0x14) /* Clear channel data */
#define TCS34725_CDATAH (0x15)
#define TCS34725_RDATAL (0x16) /* Red channel data */
#define TCS34725_RDATAH (0x17)
#define TCS34725_GDATAL (0x18) /* Green channel data */
#define TCS34725_GDATAH (0x19)
#define TCS34725_BDATAL (0x1A) /* Blue channel data */
#define TCS34725_BDATAH (0x1B)
#define TCS34725_EN_DELAY 30
typedef enum
{
TCS34725_INTEGRATIONTIME_2_4MS = 0xFF, /**< 2.4ms - 1 cycle - Max Count: 1024 */
TCS34725_INTEGRATIONTIME_24MS = 0xF6, /**< 24ms - 10 cycles - Max Count: 10240 */
TCS34725_INTEGRATIONTIME_101MS = 0xD5, /**< 101ms - 42 cycles - Max Count: 43008 */
TCS34725_INTEGRATIONTIME_154MS = 0xC0, /**< 154ms - 64 cycles - Max Count: 65535 */
TCS34725_INTEGRATIONTIME_700MS = 0x00 /**< 700ms - 256 cycles - Max Count: 65535 */
}
tcs34725IntegrationTime_t;
typedef enum
{
TCS34725_GAIN_1X = 0x00, /**< No gain */
TCS34725_GAIN_4X = 0x01, /**< 2x gain */
TCS34725_GAIN_16X = 0x02, /**< 16x gain */
TCS34725_GAIN_60X = 0x03 /**< 60x gain */
}
tcs34725Gain_t;
static void temp_setup_debug(int line, const char *str);
uint8_t tcs34725Setup(lua_State* L);
uint8_t tcs34725Enable(lua_State* L);
uint8_t tcs34725Disable(lua_State* L);
uint8_t tcs34725GetRawData(lua_State* L);
uint8_t tcs34725LuaSetIntegrationTime(lua_State* L);
uint8_t tcs34725SetIntegrationTime(tcs34725IntegrationTime_t it, lua_State* L);
uint8_t tcs34725LuaSetGain(lua_State* L);
uint8_t tcs34725SetGain(tcs34725Gain_t gain, lua_State* L);
static bool _tcs34725Initialised = false;
static int32_t _tcs34725SensorID = 0;
static tcs34725Gain_t _tcs34725Gain = TCS34725_GAIN_1X;
static tcs34725IntegrationTime_t _tcs34725IntegrationTime = TCS34725_INTEGRATIONTIME_2_4MS;
os_timer_t tcs34725_timer; // timer for forced mode readout
sint32_t cb_tcs_en;
/**************************************************************************/
/*!
@brief Writes an 8 bit values over I2C
*/
/**************************************************************************/
uint8_t tcs34725Write8 (uint8_t reg, uint8_t value)
{
platform_i2c_send_start(TCS34725_BUS_ID);
platform_i2c_send_address(TCS34725_BUS_ID, TCS34725_ADDRESS, PLATFORM_I2C_DIRECTION_TRANSMITTER);
platform_i2c_send_byte(TCS34725_BUS_ID, TCS34725_COMMAND_BIT | reg );
platform_i2c_send_byte(TCS34725_BUS_ID, value);
platform_i2c_send_stop(TCS34725_BUS_ID);
return 0;
}
/**************************************************************************/
/*!
@brief Reads a 8 bit values over I2C
*/
/**************************************************************************/
uint8_t tcs34725Read8(uint8_t reg)
{
uint8_t value;
platform_i2c_send_start(TCS34725_BUS_ID);
platform_i2c_send_address(TCS34725_BUS_ID, TCS34725_ADDRESS, PLATFORM_I2C_DIRECTION_TRANSMITTER);
platform_i2c_send_byte(TCS34725_BUS_ID, TCS34725_COMMAND_BIT | reg);
platform_i2c_send_stop(TCS34725_BUS_ID);
platform_i2c_send_start(TCS34725_BUS_ID);
platform_i2c_send_address(TCS34725_BUS_ID, TCS34725_ADDRESS, PLATFORM_I2C_DIRECTION_RECEIVER);
value = platform_i2c_recv_byte(TCS34725_BUS_ID, 0);
platform_i2c_send_stop(TCS34725_BUS_ID);
return value;
}
/**************************************************************************/
/*!
@brief Reads a 16 bit values over I2C
*/
/**************************************************************************/
uint16_t tcs34725Read16(uint8_t reg)
{
uint8_t low = tcs34725Read8(reg);
uint8_t high = tcs34725Read8(++reg);
return (high << 8) | low;
}
/**************************************************************************/
/*!
@brief Finishes enabling the device
*/
/**************************************************************************/
uint8_t tcs34725EnableDone()
{
dbg_printf("Enable finished\n");
lua_State *L = lua_getstate();
os_timer_disarm (&tcs34725_timer);
tcs34725Write8(TCS34725_ENABLE, TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN);
/* Ready to go ... set the initialised flag */
_tcs34725Initialised = true;
/* This needs to take place after the initialisation flag! */
tcs34725SetIntegrationTime(TCS34725_INTEGRATIONTIME_2_4MS, L);
tcs34725SetGain(TCS34725_GAIN_60X, L);
lua_rawgeti(L, LUA_REGISTRYINDEX, cb_tcs_en); // Get the callback to call
luaL_unref(L, LUA_REGISTRYINDEX, cb_tcs_en); // Unregister the callback to avoid leak
cb_tcs_en = LUA_NOREF;
lua_call(L, 0, 0);
return 0;
}
/**************************************************************************/
/*!
@brief Enables the device
*/
/**************************************************************************/
uint8_t tcs34725Enable(lua_State* L)
{
dbg_printf("Enable begun\n");
if (lua_type(L, 1) == LUA_TFUNCTION || lua_type(L, 1) == LUA_TLIGHTFUNCTION) {
if (cb_tcs_en != LUA_NOREF) {
luaL_unref(L, LUA_REGISTRYINDEX, cb_tcs_en);
}
lua_pushvalue(L, 1);
cb_tcs_en = luaL_ref(L, LUA_REGISTRYINDEX);
} else {
return luaL_error(L, "Enable argument must be a function.");
}
tcs34725Write8(TCS34725_ENABLE, TCS34725_ENABLE_PON);
// Start a timer to wait TCS34725_EN_DELAY before calling tcs34725EnableDone
os_timer_disarm (&tcs34725_timer);
os_timer_setfn (&tcs34725_timer, (os_timer_func_t *)tcs34725EnableDone, NULL);
os_timer_arm (&tcs34725_timer, TCS34725_EN_DELAY, 0); // trigger callback when readout is ready
return 0;
}
/**************************************************************************/
/*!
@brief Disables the device (putting it in lower power sleep mode)
*/
/**************************************************************************/
uint8_t tcs34725Disable(lua_State* L)
{
/* Turn the device off to save power */
uint8_t reg = 0;
reg = tcs34725Read8(TCS34725_ENABLE);
tcs34725Write8(TCS34725_ENABLE, reg & ~(TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN));
_tcs34725Initialised = false;
return 0;
}
/**************************************************************************/
/*!
@brief Initialises the I2C block
*/
/**************************************************************************/
uint8_t tcs34725Setup(lua_State* L)
{
uint8_t id = 0;
/* Make sure we have the right IC (0x44 = TCS34725 and TCS34721) */
id = tcs34725Read8(TCS34725_ID);
dbg_printf("id: %x\n",id);
if (id != 0x44) {
return luaL_error(L, "No TCS34725 found.");
}
lua_pushinteger(L, 1);
return 1;
}
/**************************************************************************/
/*!
@brief Sets the integration time to the specified value
*/
/**************************************************************************/
uint8_t tcs34725LuaSetIntegrationTime(lua_State* L)
{
tcs34725IntegrationTime_t it = luaL_checkinteger(L, 1);
return tcs34725SetIntegrationTime(it,L);
}
/**************************************************************************/
/*!
@brief Sets the integration time to the specified value
*/
/**************************************************************************/
uint8_t tcs34725SetIntegrationTime(tcs34725IntegrationTime_t it, lua_State* L)
{
if (!_tcs34725Initialised)
{
tcs34725Setup(L);
}
tcs34725Write8(TCS34725_ATIME, it);
_tcs34725IntegrationTime = it;
return 0;
}
/**************************************************************************/
/*!
@brief Sets gain to the specified value from Lua
*/
/**************************************************************************/
uint8_t tcs34725LuaSetGain(lua_State* L)
{
tcs34725Gain_t gain = luaL_checkinteger(L, 1);
return tcs34725SetGain(gain,L);
}
/**************************************************************************/
/*!
@brief Sets gain to the specified value
*/
/**************************************************************************/
uint8_t tcs34725SetGain(tcs34725Gain_t gain, lua_State* L)
{
if (!_tcs34725Initialised)
{
return luaL_error(L, "TCS34725 not initialised.");
}
tcs34725Write8(TCS34725_CONTROL, gain);
_tcs34725Gain = gain;
return 0;
}
/**************************************************************************/
/*!
@brief Reads the raw red, green, blue and clear channel values
*/
/**************************************************************************/
uint8_t tcs34725GetRawData(lua_State* L)
{
uint16_t r;
uint16_t g;
uint16_t b;
uint16_t c;
if (!_tcs34725Initialised)
{
return luaL_error(L, "TCS34725 not initialised.");
}
c = tcs34725Read16(TCS34725_CDATAL);
r = tcs34725Read16(TCS34725_RDATAL);
g = tcs34725Read16(TCS34725_GDATAL);
b = tcs34725Read16(TCS34725_BDATAL);
lua_pushinteger(L, c);
lua_pushinteger(L, r);
lua_pushinteger(L, g);
lua_pushinteger(L, b);
return 4;
}
static const LUA_REG_TYPE tcs34725_map[] = {
{ LSTRKEY( "setup" ), LFUNCVAL(tcs34725Setup)},
{ LSTRKEY( "enable" ), LFUNCVAL(tcs34725Enable)},
{ LSTRKEY( "disable" ), LFUNCVAL(tcs34725Disable)},
{ LSTRKEY( "raw" ), LFUNCVAL(tcs34725GetRawData)},
{ LSTRKEY( "setGain" ), LFUNCVAL(tcs34725LuaSetGain)},
{ LSTRKEY( "setIntegrationTime" ), LFUNCVAL(tcs34725LuaSetIntegrationTime)},
{ LNILKEY, LNILVAL}
};
NODEMCU_MODULE(TCS34725, "tcs34725", tcs34725_map, NULL);
\ No newline at end of file
......@@ -53,12 +53,14 @@ tmr.softwd(int)
#include "platform.h"
#include "c_types.h"
#include "user_interface.h"
#include "swTimer/swTimer.h"
#define TIMER_MODE_OFF 3
#define TIMER_MODE_SINGLE 0
#define TIMER_MODE_SEMI 2
#define TIMER_MODE_AUTO 1
#define TIMER_IDLE_FLAG (1<<7)
#define TIMER_IDLE_FLAG (1<<7)
#define STRINGIFY_VAL(x) #x
#define STRINGIFY(x) STRINGIFY_VAL(x)
......@@ -126,9 +128,9 @@ static int tmr_delay( lua_State* L ){
sint32_t us = luaL_checkinteger(L, 1);
if(us <= 0)
return luaL_error(L, "wrong arg range");
while(us >= 1000000){
us -= 1000000;
os_delay_us(1000000);
while(us >= 10000){
us -= 10000;
os_delay_us(10000);
system_soft_wdt_feed ();
}
if(us>0){
......@@ -172,14 +174,14 @@ static int tmr_register(lua_State* L){
lua_pushvalue(L, 4);
sint32_t ref = luaL_ref(L, LUA_REGISTRYINDEX);
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF)
ets_timer_disarm(&tmr->os);
os_timer_disarm(&tmr->os);
//there was a bug in this part, the second part of the following condition was missing
if(tmr->lua_ref != LUA_NOREF && tmr->lua_ref != ref)
luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref);
tmr->lua_ref = ref;
tmr->mode = mode|TIMER_IDLE_FLAG;
tmr->interval = interval;
ets_timer_setfn(&tmr->os, alarm_timer_common, tmr);
os_timer_setfn(&tmr->os, alarm_timer_common, tmr);
return 0;
}
......@@ -197,7 +199,7 @@ static int tmr_start(lua_State* L){
lua_pushboolean(L, 0);
}else{
tmr->mode &= ~TIMER_IDLE_FLAG;
ets_timer_arm_new(&tmr->os, tmr->interval, tmr->mode==TIMER_MODE_AUTO, 1);
os_timer_arm(&tmr->os, tmr->interval, tmr->mode==TIMER_MODE_AUTO);
lua_pushboolean(L, 1);
}
return 1;
......@@ -221,7 +223,7 @@ static int tmr_stop(lua_State* L){
//we return false if the timer is idle (of not registered)
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF){
tmr->mode |= TIMER_IDLE_FLAG;
ets_timer_disarm(&tmr->os);
os_timer_disarm(&tmr->os);
lua_pushboolean(L, 1);
}else{
lua_pushboolean(L, 0);
......@@ -229,6 +231,73 @@ static int tmr_stop(lua_State* L){
return 1;
}
#ifdef ENABLE_TIMER_SUSPEND
static int tmr_suspend(lua_State* L){
timer_t tmr = tmr_get(L, 1);
if((tmr->mode & TIMER_IDLE_FLAG) == 1){
return luaL_error(L, "timer not armed");
}
int retval = swtmr_suspend(&tmr->os);
if(retval != SWTMR_OK){
return luaL_error(L, swtmr_errorcode2str(retval));
}
else{
lua_pushboolean(L, true);
}
return 1;
}
static int tmr_resume(lua_State* L){
timer_t tmr = tmr_get(L, 1);
if(swtmr_suspended_test(&tmr->os) == FALSE){
return luaL_error(L, "timer not suspended");
}
int retval = swtmr_resume(&tmr->os);
if(retval != SWTMR_OK){
return luaL_error(L, swtmr_errorcode2str(retval));
}
else{
lua_pushboolean(L, true);
}
return 1;
}
static int tmr_suspend_all (lua_State *L)
{
sint32 retval = swtmr_suspend(NULL);
// lua_pushnumber(L, swtmr_suspend(NULL));
if(retval!=SWTMR_OK){
return luaL_error(L, swtmr_errorcode2str(retval));
}
else{
lua_pushboolean(L, true);
}
return 1;
}
static int tmr_resume_all (lua_State *L)
{
sint32 retval = swtmr_resume(NULL);
if(retval!=SWTMR_OK){
return luaL_error(L, swtmr_errorcode2str(retval));
}
else{
lua_pushboolean(L, true);
}
return 1;
}
#endif
// Lua: tmr.unregister( id / ref )
static int tmr_unregister(lua_State* L){
timer_t tmr = tmr_get(L, 1);
......@@ -239,7 +308,7 @@ static int tmr_unregister(lua_State* L){
}
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF)
ets_timer_disarm(&tmr->os);
os_timer_disarm(&tmr->os);
if(tmr->lua_ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref);
tmr->lua_ref = LUA_NOREF;
......@@ -256,8 +325,8 @@ static int tmr_interval(lua_State* L){
if(tmr->mode != TIMER_MODE_OFF){
tmr->interval = interval;
if(!(tmr->mode&TIMER_IDLE_FLAG)){
ets_timer_disarm(&tmr->os);
ets_timer_arm_new(&tmr->os, tmr->interval, tmr->mode==TIMER_MODE_AUTO, 1);
os_timer_disarm(&tmr->os);
os_timer_arm(&tmr->os, tmr->interval, tmr->mode==TIMER_MODE_AUTO);
}
}
return 0;
......@@ -271,9 +340,15 @@ static int tmr_state(lua_State* L){
lua_pushnil(L);
return 1;
}
lua_pushboolean(L, (tmr->mode&TIMER_IDLE_FLAG)==0);
lua_pushinteger(L, tmr->mode&(~TIMER_IDLE_FLAG));
return 2;
lua_pushboolean(L, (tmr->mode & TIMER_IDLE_FLAG) == 0);
lua_pushinteger(L, tmr->mode & (~TIMER_IDLE_FLAG));
#ifdef ENABLE_TIMER_SUSPEND
lua_pushboolean(L, swtmr_suspended_test(&tmr->os));
#else
lua_pushnil(L);
#endif
return 3;
}
/*I left the led comments 'couse I don't know
......@@ -348,10 +423,27 @@ static int tmr_create( lua_State *L ) {
ud->lua_ref = LUA_NOREF;
ud->self_ref = LUA_NOREF;
ud->mode = TIMER_MODE_OFF;
ets_timer_disarm(&ud->os);
os_timer_disarm(&ud->os);
return 1;
}
#if defined(SWTMR_DEBUG)
static void tmr_printRegistry(lua_State* L){
swtmr_print_registry();
}
static void tmr_printSuspended(lua_State* L){
swtmr_print_suspended();
}
static void tmr_printTimerlist(lua_State* L){
swtmr_print_timer_list();
}
#endif
// Module function map
static const LUA_REG_TYPE tmr_dyn_map[] = {
......@@ -362,11 +454,24 @@ static const LUA_REG_TYPE tmr_dyn_map[] = {
{ LSTRKEY( "unregister" ), LFUNCVAL( tmr_unregister ) },
{ LSTRKEY( "state" ), LFUNCVAL( tmr_state ) },
{ LSTRKEY( "interval" ), LFUNCVAL( tmr_interval) },
#ifdef ENABLE_TIMER_SUSPEND
{ LSTRKEY( "suspend" ), LFUNCVAL( tmr_suspend ) },
{ LSTRKEY( "resume" ), LFUNCVAL( tmr_resume ) },
#endif
{ LSTRKEY( "__gc" ), LFUNCVAL( tmr_unregister ) },
{ LSTRKEY( "__index" ), LROVAL( tmr_dyn_map ) },
{ LNILKEY, LNILVAL }
};
#if defined(SWTMR_DEBUG)
static const LUA_REG_TYPE tmr_dbg_map[] = {
{ LSTRKEY( "printRegistry" ), LFUNCVAL( tmr_printRegistry ) },
{ LSTRKEY( "printSuspended" ), LFUNCVAL( tmr_printSuspended ) },
{ LSTRKEY( "printTimerlist" ), LFUNCVAL( tmr_printTimerlist ) },
{ LNILKEY, LNILVAL }
};
#endif
static const LUA_REG_TYPE tmr_map[] = {
{ LSTRKEY( "delay" ), LFUNCVAL( tmr_delay ) },
{ LSTRKEY( "now" ), LFUNCVAL( tmr_now ) },
......@@ -376,11 +481,20 @@ static const LUA_REG_TYPE tmr_map[] = {
{ LSTRKEY( "register" ), LFUNCVAL( tmr_register ) },
{ LSTRKEY( "alarm" ), LFUNCVAL( tmr_alarm ) },
{ LSTRKEY( "start" ), LFUNCVAL( tmr_start ) },
{ LSTRKEY( "stop" ), LFUNCVAL( tmr_stop ) },
{ LSTRKEY( "stop" ), LFUNCVAL( tmr_stop ) },
#ifdef ENABLE_TIMER_SUSPEND
{ LSTRKEY( "suspend" ), LFUNCVAL( tmr_suspend ) },
{ LSTRKEY( "suspend_all" ), LFUNCVAL( tmr_suspend_all ) },
{ LSTRKEY( "resume" ), LFUNCVAL( tmr_resume ) },
{ LSTRKEY( "resume_all" ), LFUNCVAL( tmr_resume_all ) },
#endif
{ LSTRKEY( "unregister" ), LFUNCVAL( tmr_unregister ) },
{ LSTRKEY( "state" ), LFUNCVAL( tmr_state ) },
{ LSTRKEY( "interval" ), LFUNCVAL( tmr_interval ) },
{ LSTRKEY( "create" ), LFUNCVAL( tmr_create ) },
#if defined(SWTMR_DEBUG)
{ LSTRKEY( "debug" ), LROVAL( tmr_dbg_map ) },
#endif
{ LSTRKEY( "ALARM_SINGLE" ), LNUMVAL( TIMER_MODE_SINGLE ) },
{ LSTRKEY( "ALARM_SEMI" ), LNUMVAL( TIMER_MODE_SEMI ) },
{ LSTRKEY( "ALARM_AUTO" ), LNUMVAL( TIMER_MODE_AUTO ) },
......@@ -396,14 +510,16 @@ int luaopen_tmr( lua_State *L ){
alarm_timers[i].lua_ref = LUA_NOREF;
alarm_timers[i].self_ref = LUA_REFNIL;
alarm_timers[i].mode = TIMER_MODE_OFF;
//improve boot speed by using ets_timer_disarm instead of os_timer_disarm to avoid timer registry maintenance call.
ets_timer_disarm(&alarm_timers[i].os);
}
last_rtc_time=system_get_rtc_time(); // Right now is time 0
last_rtc_time_us=0;
//improve boot speed by using ets_timer_disarm instead of os_timer_disarm to avoid timer registry maintenance call.
ets_timer_disarm(&rtc_timer);
ets_timer_setfn(&rtc_timer, rtc_callback, NULL);
ets_timer_arm_new(&rtc_timer, 1000, 1, 1);
os_timer_setfn(&rtc_timer, rtc_callback, NULL);
os_timer_arm(&rtc_timer, 1000, 1);
return 0;
}
......
......@@ -26,10 +26,6 @@ static uint8 getap_output_format=0;
#define INVALID_MAC_STR "MAC:FF:FF:FF:FF:FF:FF"
//wifi.sleep variables
#define FPM_SLEEP_MAX_TIME 0xFFFFFFF
static bool FLAG_wifi_force_sleep_enabled=0;
#ifdef WIFI_SMART_ENABLE
static void wifi_smart_succeed_cb(sc_status status, void *pdata){
NODE_DBG("wifi_smart_succeed_cb is called.\n");
......@@ -110,16 +106,16 @@ static void wifi_scan_done(void *arg, STATUS status)
}
if(getap_output_format==1) //use new format(BSSID : SSID, RSSI, Authmode, Channel)
{
c_sprintf(temp,MACSTR, MAC2STR(bss_link->bssid));
wifi_add_sprintf_field(L, temp, "%s,%d,%d,%d",
ssid, bss_link->rssi, bss_link->authmode, bss_link->channel);
c_sprintf(temp,MACSTR, MAC2STR(bss_link->bssid));
wifi_add_sprintf_field(L, temp, "%s,%d,%d,%d",
ssid, bss_link->rssi, bss_link->authmode, bss_link->channel);
NODE_DBG(MACSTR" : %s\n",MAC2STR(bss_link->bssid) , temp);//00 00 00 00 00 00
}
else//use old format(SSID : Authmode, RSSI, BSSID, Channel)
else //use old format(SSID : Authmode, RSSI, BSSID, Channel)
{
wifi_add_sprintf_field(L, ssid, "%d,%d,"MACSTR",%d",
bss_link->authmode, bss_link->rssi, MAC2STR(bss_link->bssid),bss_link->channel);
NODE_DBG("%s : %s\n", ssid, temp);
wifi_add_sprintf_field(L, ssid, "%d,%d,"MACSTR",%d",
bss_link->authmode, bss_link->rssi, MAC2STR(bss_link->bssid),bss_link->channel);
NODE_DBG("%s : %s\n", ssid, temp);
}
bss_link = bss_link->next.stqe_next;
......@@ -130,7 +126,7 @@ static void wifi_scan_done(void *arg, STATUS status)
lua_newtable( L );
}
lua_call(L, 1, 0);
unregister_lua_cb(L, &wifi_scan_succeed);
unregister_lua_cb(L, &wifi_scan_succeed);
}
#ifdef WIFI_SMART_ENABLE
......@@ -144,15 +140,19 @@ static int wifi_start_smart( lua_State* L )
unsigned channel;
int stack = 1;
if ( lua_isnumber(L, stack) ){
if ( lua_isnumber(L, stack) )
{
channel = lua_tointeger(L, stack);
stack++;
} else {
}
else
{
channel = 6;
}
// luaL_checkanyfunction(L, stack);
if (lua_type(L, stack) == LUA_TFUNCTION || lua_type(L, stack) == LUA_TLIGHTFUNCTION){
if (lua_type(L, stack) == LUA_TFUNCTION || lua_type(L, stack) == LUA_TLIGHTFUNCTION)
{
lua_pushvalue(L, stack); // copy argument (func) to the top of stack
if(wifi_smart_succeed != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, wifi_smart_succeed);
......@@ -164,7 +164,9 @@ static int wifi_start_smart( lua_State* L )
if(wifi_smart_succeed == LUA_NOREF){
smart_begin(channel, NULL, NULL);
}else{
}
else
{
smart_begin(channel, (smart_succeed )wifi_smart_succeed_cb, L);
}
......@@ -220,13 +222,25 @@ static int wifi_setmode( lua_State* L )
bool save_to_flash=true;
mode = luaL_checkinteger( L, 1 );
luaL_argcheck(L, mode == STATION_MODE || mode == SOFTAP_MODE || mode == STATIONAP_MODE || mode == NULL_MODE, 1, "Invalid mode");
if(!lua_isnoneornil(L, 2))
{
if(!lua_isboolean(L, 2)) luaL_typerror(L, 2, lua_typename(L, LUA_TBOOLEAN));
if(!lua_isboolean(L, 2))
{
luaL_typerror(L, 2, lua_typename(L, LUA_TBOOLEAN));
}
save_to_flash=lua_toboolean(L, 2);
}
if(save_to_flash) wifi_set_opmode( (uint8_t)mode);
else wifi_set_opmode_current( (uint8_t)mode);
if(save_to_flash)
{
wifi_set_opmode( (uint8_t)mode);
}
else
{
wifi_set_opmode_current( (uint8_t)mode);
}
mode = (unsigned)wifi_get_opmode();
lua_pushinteger( L, mode );
return 1;
......@@ -268,6 +282,7 @@ static int wifi_setphymode( lua_State* L )
if ( mode != PHY_MODE_11B && mode != PHY_MODE_11G && mode != PHY_MODE_11N )
return luaL_error( L, "wrong arg type" );
wifi_set_phy_mode( (uint8_t)mode);
mode = (unsigned)wifi_get_phy_mode();
lua_pushinteger( L, mode );
......@@ -283,67 +298,92 @@ static int wifi_getphymode( lua_State* L )
return 1;
}
// Lua: wifi.sleep()
static int wifi_sleep(lua_State* L)
#ifdef PMSLEEP_ENABLE
/* Begin WiFi suspend functions*/
#include "pmSleep.h"
static int wifi_resume_cb_ref = LUA_NOREF; // Holds resume callback reference
static int wifi_suspend_cb_ref = LUA_NOREF; // Holds suspend callback reference
void wifi_pmSleep_suspend_CB(void)
{
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);
PMSLEEP_DBG("\n\tDBG: %s start\n", __func__);
if (wifi_suspend_cb_ref != LUA_NOREF)
{
lua_State* L = lua_getstate(); // Get main Lua thread pointer
lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_suspend_cb_ref); // Push suspend callback onto stack
lua_unref(L, wifi_suspend_cb_ref); // remove suspend callback from LUA_REGISTRY
wifi_suspend_cb_ref = LUA_NOREF; // Update variable since reference is no longer valid
lua_call(L, 0, 0); // Execute suspend callback
}
else
{
lua_pushnumber(L, FLAG_wifi_force_sleep_enabled);
lua_pushnil(L);
PMSLEEP_DBG("\n\tDBG: lua cb unavailable\n");
}
return 2;
PMSLEEP_DBG("\n\tDBG: %s end\n", __func__);
return;
}
void wifi_pmSleep_resume_CB(void)
{
PMSLEEP_DBG("\n\tDBG: %s start\n", __func__);
// If resume callback was defined
pmSleep_execute_lua_cb(&wifi_resume_cb_ref);
PMSLEEP_DBG("\n\tDBG: %s end\n", __func__);
return;
}
// Lua: wifi.suspend({duration, suspend_cb, resume_cb, preserve_mode})
static int wifi_suspend(lua_State* L)
{
// If no parameters were provided
if (lua_isnone(L, 1))
{
// Return current WiFi suspension state
lua_pushnumber(L, pmSleep_get_state());
return 1; // Return WiFi suspension state
}
pmSleep_INIT_CFG(cfg);
cfg.sleep_mode = MODEM_SLEEP_T;
if(lua_istable(L, 1))
{
pmSleep_parse_table_lua(L, 1, &cfg, &wifi_suspend_cb_ref, &wifi_resume_cb_ref);
}
else
return luaL_argerror(L, 1, "must be table");
cfg.resume_cb_ptr = &wifi_pmSleep_resume_CB;
cfg.suspend_cb_ptr = &wifi_pmSleep_suspend_CB;
pmSleep_suspend(&cfg);
return 0;
}
// Lua: wifi.resume([Resume_CB])
static int wifi_resume(lua_State* L)
{
PMSLEEP_DBG("\n\tDBG: %s start\n", __func__);
uint8 fpm_state = pmSleep_get_state();
// If forced sleep api is not enabled, return error
if (fpm_state == 0)
{
return luaL_error(L, "WIFi not suspended");
}
// If a resume callback was provided
if (lua_isfunction(L, 1))
{
// If there is already a resume callback reference
lua_pushvalue(L, 1); //Push resume callback to the top of the stack
register_lua_cb(L, &wifi_resume_cb_ref);
PMSLEEP_DBG("\n\tDBG: Resume CB registered\n");
}
pmSleep_resume(NULL);
PMSLEEP_DBG("\n\tDBG: %s end\n", __func__);
return 0;
}
/* End WiFi suspend functions*/
#endif
// Lua: wifi.nullmodesleep()
static int wifi_null_mode_auto_sleep(lua_State* L)
{
......@@ -396,7 +436,9 @@ static int wifi_getip( lua_State* L, uint8_t mode )
if(pTempIp.ip.addr==0){
lua_pushnil(L);
return 1;
} else {
}
else
{
c_sprintf(temp, "%d.%d.%d.%d", IP2STR(&pTempIp.ip) );
lua_pushstring( L, temp );
c_sprintf(temp, "%d.%d.%d.%d", IP2STR(&pTempIp.netmask) );
......@@ -416,8 +458,9 @@ static int wifi_getbroadcast( lua_State* L, uint8_t mode )
if(pTempIp.ip.addr==0){
lua_pushnil(L);
return 1;
} else {
}
else
{
struct ip_addr broadcast_address;
uint32 subnet_mask32 = pTempIp.netmask.addr & pTempIp.ip.addr;
......@@ -478,7 +521,7 @@ static int wifi_setip( lua_State* L, uint8_t mode )
return 1;
}
// Lua: wifi.sta.getaplist
// Lua: wifi.sta.getapinfo
static int wifi_station_get_ap_info4lua( lua_State* L )
{
struct station_config config[5];
......@@ -506,8 +549,8 @@ static int wifi_station_get_ap_info4lua( lua_State* L )
c_sprintf(debug_temp, " %-6d %-32s ", i, temp);
#endif
memset(temp, 0, sizeof(temp));
if(strlen(config[i].password) >= 8)
memset(temp, 0, sizeof(temp));
if(strlen(config[i].password) > 0) /* WPA = min 8, WEP = min 5 ASCII characters for a 40-bit key */
{
memcpy(temp, config[i].password, sizeof(config[i].password));
lua_pushstring(L, temp);
......@@ -517,7 +560,7 @@ static int wifi_station_get_ap_info4lua( lua_State* L )
c_sprintf(debug_temp + strlen(debug_temp), "%-64s ", temp);
#endif
memset(temp, 0, sizeof(temp));
memset(temp, 0, sizeof(temp));
if (config[i].bssid_set)
{
c_sprintf(temp, MACSTR, MAC2STR(config[i].bssid));
......@@ -590,8 +633,16 @@ static int wifi_station_getconfig( lua_State* L, bool get_flash_cfg)
{
struct station_config sta_conf;
char temp[sizeof(sta_conf.password)+1]; //max password length + '\0'
if(get_flash_cfg) wifi_station_get_config_default(&sta_conf);
else wifi_station_get_config(&sta_conf);
if(get_flash_cfg)
{
wifi_station_get_config_default(&sta_conf);
}
else
{
wifi_station_get_config(&sta_conf);
}
if(sta_conf.ssid==0)
{
lua_pushnil(L);
......@@ -607,7 +658,7 @@ static int wifi_station_getconfig( lua_State* L, bool get_flash_cfg)
lua_pushstring(L, temp);
lua_setfield(L, -2, "ssid");
if(strlen(sta_conf.password) >= 8)
if(strlen(sta_conf.password) > 0) /* WPA = min 8, WEP = min 5 ASCII characters for a 40-bit key */
{
memset(temp, 0, sizeof(temp));
memcpy(temp, sta_conf.password, sizeof(sta_conf.password));
......@@ -652,6 +703,36 @@ static int wifi_station_getconfig_default(lua_State *L)
return wifi_station_getconfig(L, true);
}
// Lua: wifi.sta.clearconfig()
static int wifi_station_clear_config ( lua_State* L )
{
struct station_config sta_conf;
bool auto_connect=true;
bool save_to_flash=true;
memset(sta_conf.ssid, 0, sizeof(sta_conf.ssid));
memset(sta_conf.password, 0, sizeof(sta_conf.password));
memset(sta_conf.bssid, 0, sizeof(sta_conf.bssid));
sta_conf.bssid_set=0;
wifi_station_disconnect();
bool config_success;
if(save_to_flash)
{
config_success = wifi_station_set_config(&sta_conf);
}
else
{
config_success = wifi_station_set_config_current(&sta_conf);
}
wifi_station_set_auto_connect((uint8)0);
lua_pushboolean(L, config_success);
return 1;
}
// Lua: wifi.sta.config()
static int wifi_station_config( lua_State* L )
{
......@@ -673,12 +754,18 @@ static int wifi_station_config( lua_State* L )
if( lua_isstring(L, -1) )
{
const char *ssid = luaL_checklstring( L, -1, &sl );
luaL_argcheck(L, ((sl>=1 && sl<=sizeof(sta_conf.ssid)) ), 1, "ssid: length:1-32");
luaL_argcheck(L, ((sl>=0 && sl<=sizeof(sta_conf.ssid)) ), 1, "ssid: length:0-32"); /* Zero-length SSID is valid as a way to clear config */
memcpy(sta_conf.ssid, ssid, sl);
}
else return luaL_argerror( L, 1, "ssid:not string" );
else
{
return luaL_argerror( L, 1, "ssid:not string" );
}
}
else
{
return luaL_argerror( L, 1, "ssid required" );
}
else return luaL_argerror( L, 1, "ssid required" );
lua_pop(L, 1);
lua_getfield(L, 1, "pwd");
......@@ -687,10 +774,13 @@ static int wifi_station_config( lua_State* L )
if( lua_isstring(L, -1) )
{
const char *pwd = luaL_checklstring( L, -1, &pl );
luaL_argcheck(L, ((pl>=8 && pl<=sizeof(sta_conf.password)) ), 1, "pwd: length:8-64");
luaL_argcheck(L, ((pl>=0 && pl<=sizeof(sta_conf.password)) ), 1, "pwd: length:0-64"); /* WPA = min 8, WEP = min 5 ASCII characters for a 40-bit key */
memcpy(sta_conf.password, pwd, pl);
}
else return luaL_argerror( L, 1, "pwd:not string" );
else
{
return luaL_argerror( L, 1, "pwd:not string" );
}
}
lua_pop(L, 1);
......@@ -704,7 +794,10 @@ static int wifi_station_config( lua_State* L )
ets_str2macaddr(sta_conf.bssid, macaddr);
sta_conf.bssid_set = 1;
}
else return luaL_argerror(L, 1, "bssid:not string");
else
{
return luaL_argerror(L, 1, "bssid:not string");
}
}
lua_pop(L, 1);
......@@ -715,29 +808,43 @@ static int wifi_station_config( lua_State* L )
{
auto_connect=lua_toboolean(L, -1);
}
else return luaL_argerror(L, 1, "auto:not boolean");
else
{
return luaL_argerror(L, 1, "auto:not boolean");
}
}
lua_pop(L, 1);
lua_getfield(L, 1, "save");
if (!lua_isnil(L, -1))
{
if (lua_isboolean(L, -1)) save_to_flash=lua_toboolean(L, -1);
else return luaL_argerror(L, 1, "save:not boolean");
if (lua_isboolean(L, -1))
{
save_to_flash=lua_toboolean(L, -1);
}
else
{
return luaL_argerror(L, 1, "save:not boolean");
}
}
else
{
save_to_flash=false;
}
else save_to_flash=false;
lua_pop(L, 1);
}
else //to be depreciated
else //to be deprecated
{
platform_print_deprecation_note("Argument style station configuration is replaced by table style station configuration", "in the next version");
const char *ssid = luaL_checklstring( L, 1, &sl );
luaL_argcheck(L, ((sl>=1 && sl<sizeof(sta_conf.ssid)) ), 1, "length:1-32");
luaL_argcheck(L, (sl>=0 && sl<sizeof(sta_conf.ssid)), 1, "length:0-32"); /* Zero-length SSID is valid as a way to clear config */
memcpy(sta_conf.ssid, ssid, sl);
const char *password = luaL_checklstring( L, 2, &pl );
luaL_argcheck(L, (pl==0||(pl>=8 && pl<=sizeof(sta_conf.password)) ), 2, "length:0 or 8-64");
luaL_argcheck(L, (pl>=0 && pl<=sizeof(sta_conf.password)), 2, "length:0-64"); /* WPA = min 8, WEP = min 5 ASCII characters for a 40-bit key */
memcpy(sta_conf.password, password, pl);
......@@ -801,11 +908,20 @@ static int wifi_station_config( lua_State* L )
wifi_station_disconnect();
bool config_success;
if(save_to_flash) config_success = wifi_station_set_config(&sta_conf);
else config_success = wifi_station_set_config_current(&sta_conf);
if(save_to_flash)
{
config_success = wifi_station_set_config(&sta_conf);
}
else
{
config_success = wifi_station_set_config_current(&sta_conf);
}
wifi_station_set_auto_connect((uint8)auto_connect);
if(auto_connect) wifi_station_connect();
if(auto_connect)
{
wifi_station_connect();
}
lua_pushboolean(L, config_success);
return 1;
......@@ -848,122 +964,143 @@ static int wifi_station_listap( lua_State* L )
if (lua_type(L, 1)==LUA_TTABLE)
{
char ssid[32];
char bssid[6];
uint8 channel=0;
uint8 show_hidden=0;
size_t len;
lua_getfield(L, 1, "ssid");
if (!lua_isnil(L, -1)){ /* found? */
if( lua_isstring(L, -1) ) // deal with the ssid string
{
const char *ssidstr = luaL_checklstring( L, -1, &len );
if(len>32)
return luaL_error( L, "ssid:<32" );
c_memset(ssid, 0, 32);
c_memcpy(ssid, ssidstr, len);
scan_cfg.ssid=ssid;
NODE_DBG(scan_cfg.ssid);
NODE_DBG("\n");
}
else
return luaL_error( L, "wrong arg type" );
}
else
scan_cfg.ssid=NULL;
lua_getfield(L, 1, "bssid");
if (!lua_isnil(L, -1)){ /* found? */
if( lua_isstring(L, -1) ) // deal with the ssid string
{
const char *macaddr = luaL_checklstring( L, -1, &len );
luaL_argcheck(L, len==17, 1, INVALID_MAC_STR);
c_memset(bssid, 0, 6);
ets_str2macaddr(bssid, macaddr);
scan_cfg.bssid=bssid;
NODE_DBG(MACSTR, MAC2STR(scan_cfg.bssid));
NODE_DBG("\n");
}
else
return luaL_error( L, "wrong arg type" );
}
else
scan_cfg.bssid=NULL;
lua_getfield(L, 1, "channel");
if (!lua_isnil(L, -1)){ /* found? */
if( lua_isnumber(L, -1) ) // deal with the ssid string
{
channel = luaL_checknumber( L, -1);
if(!(channel>=0 && channel<=13))
return luaL_error( L, "channel: 0 or 1-13" );
scan_cfg.channel=channel;
NODE_DBG("%d\n", scan_cfg.channel);
}
else
return luaL_error( L, "wrong arg type" );
}
else
scan_cfg.channel=0;
lua_getfield(L, 1, "show_hidden");
if (!lua_isnil(L, -1)){ /* found? */
if( lua_isnumber(L, -1) ) // deal with the ssid string
{
show_hidden = luaL_checknumber( L, -1);
if(show_hidden!=0 && show_hidden!=1)
return luaL_error( L, "show_hidden: 0 or 1" );
scan_cfg.show_hidden=show_hidden;
NODE_DBG("%d\n", scan_cfg.show_hidden);
}
else
return luaL_error( L, "wrong arg type" );
}
else
scan_cfg.show_hidden=0;
if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION)
{
lua_pushnil(L);
lua_insert(L, 2);
}
lua_pop(L, -4);
}
else if (lua_type(L, 1) == LUA_TNUMBER)
{
lua_pushnil(L);
lua_insert(L, 1);
}
else if (lua_type(L, 1) == LUA_TFUNCTION || lua_type(L, 1) == LUA_TLIGHTFUNCTION)
{
lua_pushnil(L);
lua_insert(L, 1);
lua_pushnil(L);
lua_insert(L, 1);
char ssid[32];
char bssid[6];
uint8 channel=0;
uint8 show_hidden=0;
size_t len;
lua_getfield(L, 1, "ssid");
if (!lua_isnil(L, -1)) /* found? */
{
if( lua_isstring(L, -1) ) // deal with the ssid string
{
const char *ssidstr = luaL_checklstring( L, -1, &len );
if(len>32)
return luaL_error( L, "ssid:<32" );
c_memset(ssid, 0, 32);
c_memcpy(ssid, ssidstr, len);
scan_cfg.ssid=ssid;
NODE_DBG(scan_cfg.ssid);
NODE_DBG("\n");
}
else
{
return luaL_error( L, "wrong arg type" );
}
}
else
{
scan_cfg.ssid=NULL;
}
lua_getfield(L, 1, "bssid");
if (!lua_isnil(L, -1)) /* found? */
{
if( lua_isstring(L, -1) ) // deal with the ssid string
{
const char *macaddr = luaL_checklstring( L, -1, &len );
luaL_argcheck(L, len==17, 1, INVALID_MAC_STR);
c_memset(bssid, 0, 6);
ets_str2macaddr(bssid, macaddr);
scan_cfg.bssid=bssid;
NODE_DBG(MACSTR, MAC2STR(scan_cfg.bssid));
NODE_DBG("\n");
}
else
{
return luaL_error( L, "wrong arg type" );
}
}
else
{
scan_cfg.bssid=NULL;
}
lua_getfield(L, 1, "channel");
if (!lua_isnil(L, -1)) /* found? */
{
if( lua_isnumber(L, -1) ) // deal with the ssid string
{
channel = luaL_checknumber( L, -1);
if(!(channel>=0 && channel<=13))
return luaL_error( L, "channel: 0 or 1-13" );
scan_cfg.channel=channel;
NODE_DBG("%d\n", scan_cfg.channel);
}
else
{
return luaL_error( L, "wrong arg type" );
}
}
else
{
scan_cfg.channel=0;
}
lua_getfield(L, 1, "show_hidden");
if (!lua_isnil(L, -1)) /* found? */
{
if( lua_isnumber(L, -1) ) // deal with the ssid string
{
show_hidden = luaL_checknumber( L, -1);
if(show_hidden!=0 && show_hidden!=1)
return luaL_error( L, "show_hidden: 0 or 1" );
scan_cfg.show_hidden=show_hidden;
NODE_DBG("%d\n", scan_cfg.show_hidden);
}
else
{
return luaL_error( L, "wrong arg type" );
}
}
else
{
scan_cfg.show_hidden=0;
}
if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION)
{
lua_pushnil(L);
lua_insert(L, 2);
}
lua_pop(L, -4);
}
else if (lua_type(L, 1) == LUA_TNUMBER)
{
lua_pushnil(L);
lua_insert(L, 1);
}
else if (lua_type(L, 1) == LUA_TFUNCTION || lua_type(L, 1) == LUA_TLIGHTFUNCTION)
{
lua_pushnil(L);
lua_insert(L, 1);
lua_pushnil(L);
lua_insert(L, 1);
}
else if(lua_isnil(L, 1))
{
if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION)
{
lua_pushnil(L);
lua_insert(L, 2);
}
if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION)
{
lua_pushnil(L);
lua_insert(L, 2);
}
}
else
{
return luaL_error( L, "wrong arg type" );
return luaL_error( L, "wrong arg type" );
}
if (lua_type(L, 2) == LUA_TNUMBER) //this section changes the output format
{
getap_output_format=luaL_checkinteger( L, 2 );
if ( getap_output_format != 0 && getap_output_format != 1)
return luaL_error( L, "wrong arg type" );
}
{
getap_output_format=luaL_checkinteger( L, 2 );
if (getap_output_format != 0 && getap_output_format != 1)
return luaL_error( L, "wrong arg type" );
}
NODE_DBG("Use alternate output format: %d\n", getap_output_format);
if (lua_type(L, 3) == LUA_TFUNCTION || lua_type(L, 3) == LUA_TLIGHTFUNCTION)
{
......@@ -972,16 +1109,16 @@ static int wifi_station_listap( lua_State* L )
if (lua_type(L, 1)==LUA_TTABLE)
{
wifi_station_scan(&scan_cfg,wifi_scan_done);
wifi_station_scan(&scan_cfg,wifi_scan_done);
}
else
{
wifi_station_scan(NULL,wifi_scan_done);
wifi_station_scan(NULL,wifi_scan_done);
}
}
else
{
unregister_lua_cb(L, &wifi_scan_succeed);
unregister_lua_cb(L, &wifi_scan_succeed);
}
return 0;
}
......@@ -1007,9 +1144,9 @@ static bool wifi_sta_sethostname(const char *hostname, size_t len)
for (int i=1; i<len; i++)
{
//characters in the middle of the host name can be alphanumeric or a hyphen(-) only
if (!(isalnum(hostname[i]) || hostname[i]=='-'))
if (!(isalnum(hostname[i]) || hostname[i]=='-'))
{
return false;
return false;
}
}
return wifi_station_set_hostname((char*)hostname);
......@@ -1029,7 +1166,8 @@ static int wifi_station_sleeptype( lua_State* L )
{
unsigned type;
if ( lua_isnumber(L, 1) ){
if ( lua_isnumber(L, 1) )
{
type = lua_tointeger(L, 1);
luaL_argcheck(L, (type == NONE_SLEEP_T || type == LIGHT_SLEEP_T || type == MODEM_SLEEP_T), 1, "range:0-2");
if(!wifi_set_sleep_type(type)){
......@@ -1054,7 +1192,7 @@ static int wifi_station_status( lua_State* L )
// Lua: wifi.sta.getrssi()
static int wifi_station_getrssi( lua_State* L ){
sint8 rssival=wifi_station_get_rssi();
NODE_DBG("\n\tRSSI is %i\n", rssival);
NODE_DBG("\n\tRSSI is %d\n", rssival);
if (rssival<10)
{
lua_pushinteger(L, rssival);
......@@ -1063,7 +1201,7 @@ static int wifi_station_getrssi( lua_State* L ){
{
lua_pushnil(L);
}
return 1;
return 1;
}
//Lua: wifi.ap.deauth()
......@@ -1079,7 +1217,7 @@ static int wifi_ap_deauth( lua_State* L )
}
else
{
c_memset(&mac, 0xFF, sizeof(mac));
c_memset(&mac, 0xFF, sizeof(mac));
}
lua_pushboolean(L,wifi_softap_deauth(mac));
return 1;
......@@ -1115,8 +1253,15 @@ static int wifi_ap_getconfig( lua_State* L, bool get_flash_cfg)
{
struct softap_config config;
char temp[sizeof(config.password)+1]; //max password length + '\0'
if (get_flash_cfg) wifi_softap_get_config_default(&config);
else wifi_softap_get_config(&config);
if (get_flash_cfg)
{
wifi_softap_get_config_default(&config);
}
else
{
wifi_softap_get_config(&config);
}
if(lua_isboolean(L, 1) && lua_toboolean(L, 1)==true)
{
lua_newtable(L);
......@@ -1150,7 +1295,10 @@ static int wifi_ap_getconfig( lua_State* L, bool get_flash_cfg)
memcpy(temp, config.ssid, sizeof(config.ssid));
lua_pushstring(L, temp);
if(config.authmode == AUTH_OPEN) lua_pushnil(L);
if(config.authmode == AUTH_OPEN)
{
lua_pushnil(L);
}
else
{
memset(temp, 0, sizeof(temp));
......@@ -1177,7 +1325,9 @@ static int wifi_ap_getconfig_default(lua_State *L)
static int wifi_ap_config( lua_State* L )
{
if (!lua_istable(L, 1))
{
return luaL_typerror(L, 1, lua_typename(L, LUA_TTABLE));
}
struct softap_config config;
bool save_to_flash=true;
......@@ -1189,7 +1339,8 @@ static int wifi_ap_config( lua_State* L )
memset(config.password, 0, sizeof(config.password));
lua_getfield(L, 1, "ssid");
if (!lua_isnil(L, -1)){ /* found? */
if (!lua_isnil(L, -1)) /* found? */
{
if( lua_isstring(L, -1) ) // deal with the ssid string
{
const char *ssid = luaL_checklstring( L, -1, &sl );
......@@ -1198,14 +1349,21 @@ static int wifi_ap_config( lua_State* L )
config.ssid_len = sl;
config.ssid_hidden = 0;
}
else return luaL_argerror( L, 1, "ssid: not string" );
else
{
return luaL_argerror( L, 1, "ssid: not string" );
}
}
else
{
return luaL_argerror( L, 1, "ssid: required" );
}
else return luaL_argerror( L, 1, "ssid: required" );
lua_pop(L, 1);
lua_getfield(L, 1, "pwd");
if (!lua_isnil(L, -1)){ /* found? */
if (!lua_isnil(L, -1)) /* found? */
{
if( lua_isstring(L, -1) ) // deal with the password string
{
const char *pwd = luaL_checklstring( L, -1, &pl );
......@@ -1214,9 +1372,12 @@ static int wifi_ap_config( lua_State* L )
config.authmode = AUTH_WPA_WPA2_PSK;
}
else
{
return luaL_argerror( L, 1, "pwd: not string" );
}
}
else{
else
{
config.authmode = AUTH_OPEN;
}
lua_pop(L, 1);
......@@ -1230,7 +1391,10 @@ static int wifi_ap_config( lua_State* L )
luaL_argcheck(L, (lint >= 0 && lint < AUTH_MAX), 1, "auth: Range:0-4");
config.authmode = (uint8_t)luaL_checkinteger(L, -1);
}
else return luaL_argerror(L, 1, "auth: not number");
else
{
return luaL_argerror(L, 1, "auth: not number");
}
}
lua_pop(L, 1);
......@@ -1245,8 +1409,10 @@ static int wifi_ap_config( lua_State* L )
luaL_argcheck(L, (lint >= 1 && lint <= 13), 1, "channel: Range:1-13");
config.channel = (uint8_t)lint;
}
else luaL_argerror(L, 1, "channel: not number");
else
{
luaL_argerror(L, 1, "channel: not number");
}
}
else
{
......@@ -1261,13 +1427,23 @@ static int wifi_ap_config( lua_State* L )
Ltype_tmp=lua_type(L, -1);
if(Ltype_tmp==LUA_TNUMBER||Ltype_tmp==LUA_TBOOLEAN)
{
if(Ltype_tmp==LUA_TNUMBER)lint=luaL_checkinteger(L, -1);
if(Ltype_tmp==LUA_TBOOLEAN)lint=(lua_Number)lua_toboolean(L, -1);
if(Ltype_tmp==LUA_TNUMBER)
{
lint=luaL_checkinteger(L, -1);
}
if(Ltype_tmp==LUA_TBOOLEAN)
{
lint=(lua_Number)lua_toboolean(L, -1);
}
luaL_argcheck(L, (lint == 0 || lint==1), 1, "hidden: 0 or 1");
config.ssid_hidden = (uint8_t)lint;
}
else return luaL_argerror(L, 1, "hidden: not boolean");
else
{
return luaL_argerror(L, 1, "hidden: not boolean");
}
}
else
{
......@@ -1286,7 +1462,10 @@ static int wifi_ap_config( lua_State* L )
config.max_connection = (uint8_t)lint;
}
else return luaL_argerror(L, 1, "max: not number");
else
{
return luaL_argerror(L, 1, "max: not number");
}
}
else
{
......@@ -1304,7 +1483,10 @@ static int wifi_ap_config( lua_State* L )
luaL_argcheck(L, (lint >= 100 && lint <= 60000), 1, "beacon: 100-60000");
config.beacon_interval = (uint16_t)lint;
}
else return luaL_argerror(L, 1, "beacon: not number");
else
{
return luaL_argerror(L, 1, "beacon: not number");
}
}
else
{
......@@ -1320,7 +1502,10 @@ static int wifi_ap_config( lua_State* L )
{
save_to_flash=lua_toboolean(L, -1);
}
else return luaL_argerror(L, 1, "save: not boolean");
else
{
return luaL_argerror(L, 1, "save: not boolean");
}
}
lua_pop(L, 1);
......@@ -1342,8 +1527,15 @@ static int wifi_ap_config( lua_State* L )
#endif
bool config_success;
if(save_to_flash) config_success = wifi_softap_set_config(&config);
else config_success = wifi_softap_set_config_current(&config);
if(save_to_flash)
{
config_success = wifi_softap_set_config(&config);
}
else
{
config_success = wifi_softap_set_config_current(&config);
}
lua_pushboolean(L, config_success);
return 1;
}
......@@ -1433,6 +1625,7 @@ static int wifi_ap_dhcp_stop( lua_State* L )
static const LUA_REG_TYPE wifi_station_map[] = {
{ LSTRKEY( "autoconnect" ), LFUNCVAL( wifi_station_setauto ) },
{ LSTRKEY( "changeap" ), LFUNCVAL( wifi_station_change_ap ) },
{ LSTRKEY( "clearconfig"), LFUNCVAL( wifi_station_clear_config ) },
{ LSTRKEY( "config" ), LFUNCVAL( wifi_station_config ) },
{ LSTRKEY( "connect" ), LFUNCVAL( wifi_station_connect4lua ) },
{ LSTRKEY( "disconnect" ), LFUNCVAL( wifi_station_disconnect4lua ) },
......@@ -1490,7 +1683,10 @@ static 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 ) },
#ifdef PMSLEEP_ENABLE
{ LSTRKEY( "suspend" ), LFUNCVAL( wifi_suspend ) },
{ LSTRKEY( "resume" ), LFUNCVAL( wifi_resume ) },
#endif
{ LSTRKEY( "nullmodesleep" ), LFUNCVAL( wifi_null_mode_auto_sleep ) },
#ifdef WIFI_SMART_ENABLE
{ LSTRKEY( "startsmart" ), LFUNCVAL( wifi_start_smart ) },
......
......@@ -52,6 +52,15 @@ void wifi_change_default_host_name(void);
#define EVENT_DBG(...) //c_printf(__VA_ARGS__)
#endif
enum wifi_suspension_state
{
WIFI_AWAKE = 0,
WIFI_SUSPENSION_PENDING = 1,
WIFI_SUSPENDED = 2
};
#ifdef WIFI_SDK_EVENT_MONITOR_ENABLE
extern const LUA_REG_TYPE wifi_event_monitor_map[];
void wifi_eventmon_init();
......
......@@ -63,6 +63,8 @@ static void wifi_status_cb(int arg)
// wifi.sta.eventMonReg()
int wifi_station_event_mon_reg(lua_State* L)
{
platform_print_deprecation_note("wifi.sta.eventmonreg() is replaced by wifi.eventmon.register()", "in the next version");
uint8 id=(uint8)luaL_checknumber(L, 1);
if ((id > 5)) // verify user specified a valid wifi status
{
......@@ -152,9 +154,10 @@ static void wifi_event_monitor_handle_event_cb(System_Event_t *evt)
if((wifi_event_cb_ref[evt->event] != LUA_NOREF) || ((wifi_event_cb_ref[EVENT_MAX] != LUA_NOREF) &&
!(evt->event == EVENT_STAMODE_CONNECTED || evt->event == EVENT_STAMODE_DISCONNECTED ||
evt->event == EVENT_STAMODE_AUTHMODE_CHANGE||evt->event==EVENT_STAMODE_GOT_IP ||
evt->event == EVENT_STAMODE_DHCP_TIMEOUT||evt->event==EVENT_SOFTAPMODE_STACONNECTED ||
evt->event == EVENT_SOFTAPMODE_STADISCONNECTED||evt->event==EVENT_SOFTAPMODE_PROBEREQRECVED)))
evt->event == EVENT_STAMODE_AUTHMODE_CHANGE || evt->event == EVENT_STAMODE_GOT_IP ||
evt->event == EVENT_STAMODE_DHCP_TIMEOUT || evt->event == EVENT_SOFTAPMODE_STACONNECTED ||
evt->event == EVENT_SOFTAPMODE_STADISCONNECTED || evt->event == EVENT_SOFTAPMODE_PROBEREQRECVED ||
evt->event == EVENT_OPMODE_CHANGED)))
{
evt_queue_t *temp = (evt_queue_t*)c_malloc(sizeof(evt_queue_t)); //allocate memory for new queue item
temp->evt = (System_Event_t*)c_malloc(sizeof(System_Event_t)); //allocate memory to hold event structure
......@@ -277,7 +280,16 @@ static void wifi_event_monitor_process_event_queue(task_param_t param, uint8 pri
evt->event_info.ap_probereqrecved.rssi);
break;
default://if event is not implemented, push table with userdata containing event data
case EVENT_OPMODE_CHANGED:
EVENT_DBG("\n\tOPMODE_CHANGED\n");
wifi_add_int_field(L, "old_mode", evt->event_info.opmode_changed.old_opmode);
wifi_add_int_field(L, "new_mode", evt->event_info.opmode_changed.new_opmode);
EVENT_DBG("\topmode: %u -> %u\n",
evt->event_info.opmode_changed.old_opmode,
evt->event_info.opmode_changed.new_opmode);
break;
default://if event is not implemented, return event id
EVENT_DBG("\n\tswitch/case default\n");
wifi_add_sprintf_field(L, "info", "event %u not implemented", evt->event);
break;
......@@ -348,6 +360,7 @@ const LUA_REG_TYPE wifi_event_monitor_map[] =
{ LSTRKEY( "AP_STACONNECTED" ), LNUMVAL( EVENT_SOFTAPMODE_STACONNECTED ) },
{ LSTRKEY( "AP_STADISCONNECTED" ), LNUMVAL( EVENT_SOFTAPMODE_STADISCONNECTED ) },
{ LSTRKEY( "AP_PROBEREQRECVED" ), LNUMVAL( EVENT_SOFTAPMODE_PROBEREQRECVED ) },
{ LSTRKEY( "WIFI_MODE_CHANGED" ), LNUMVAL( EVENT_OPMODE_CHANGED ) },
{ LSTRKEY( "EVENT_MAX" ), LNUMVAL( EVENT_MAX ) },
#ifdef WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
{ LSTRKEY( "reason" ), LROVAL( wifi_event_monitor_reason_map ) },
......
......@@ -27,7 +27,7 @@ typedef struct {
// Init UART1 to be able to stream WS2812 data to GPIO2 pin
// If DUAL mode is selected, init UART0 to stream to TXD0 as well
// You HAVE to redirect LUA's output somewhere else
static void ws2812_init(lua_State* L) {
static int ws2812_init(lua_State* L) {
const int mode = luaL_optinteger(L, 1, MODE_SINGLE);
luaL_argcheck(L, mode == MODE_SINGLE || mode == MODE_DUAL, 1, "ws2812.SINGLE or ws2812.DUAL expected");
......@@ -57,6 +57,8 @@ static void ws2812_init(lua_State* L) {
GPIO_REG_WRITE(GPIO_ENABLE_W1TC_ADDRESS, BIT2);
// Enable Function 2 for GPIO2 (U1TXD)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
return 0;
}
// Stream data using UART1 routed to GPIO2
......
// Module for xpt2046
// by Starofall, F.J. Exoo
// used source code from:
// - https://github.com/spapadim/XPT2046/
// - https://github.com/PaulStoffregen/XPT2046_Touchscreen/
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
// Hardware specific values
static const uint16_t CAL_MARGIN = 0; // Set to 0: up to the application
static const uint8_t CTRL_LO_DFR = 0b0011;
static const uint8_t CTRL_LO_SER = 0b0100;
static const uint8_t CTRL_HI_X = 0b1001 << 4;
static const uint8_t CTRL_HI_Y = 0b1101 << 4;
static const uint16_t ADC_MAX = 0x0fff; // 12 bits
// Runtime variables
static uint16_t _width, _height;
static uint8_t _cs_pin, _irq_pin;
static int32_t _cal_dx, _cal_dy, _cal_dvi, _cal_dvj;
static uint16_t _cal_vi1, _cal_vj1;
// Average pair with least distance between each
static int16_t besttwoavg( int16_t x , int16_t y , int16_t z ) {
int16_t da, db, dc;
int16_t reta = 0;
if ( x > y ) da = x - y; else da = y - x;
if ( x > z ) db = x - z; else db = z - x;
if ( z > y ) dc = z - y; else dc = y - z;
if ( da <= db && da <= dc ) reta = (x + y) >> 1;
else if ( db <= da && db <= dc ) reta = (x + z) >> 1;
else reta = (y + z) >> 1;
return reta;
}
// Checks if the irq_pin is down
static int isTouching() {
return (platform_gpio_read(_irq_pin) == 0);
}
// transfer 16 bits from the touch display - returns the recived uint16_t
static uint16_t transfer16(uint16_t _data) {
union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } t;
t.val = _data;
t.msb = platform_spi_send_recv(1, 8, t.msb);
t.lsb = platform_spi_send_recv(1, 8, t.lsb);
return t.val;
}
// reads the value from the touch panel
static uint16_t _readLoop(uint8_t ctrl, uint8_t max_samples) {
uint16_t prev = 0xffff, cur = 0xffff;
uint8_t i = 0;
do {
prev = cur;
cur = platform_spi_send_recv(1, 8 , 0);
cur = (cur << 4) | (platform_spi_send_recv(1, 8 , ctrl) >> 4); // 16 clocks -> 12-bits (zero-padded at end)
} while ((prev != cur) && (++i < max_samples));
return cur;
}
// Returns the raw position information
static void getRaw(uint16_t *vi, uint16_t *vj) {
// Implementation based on TI Technical Note http://www.ti.com/lit/an/sbaa036/sbaa036.pdf
// Disable interrupt: reading position generates false interrupt
ETS_GPIO_INTR_DISABLE();
platform_gpio_write(_cs_pin, PLATFORM_GPIO_LOW);
platform_spi_send_recv(1, 8 , CTRL_HI_X | CTRL_LO_DFR); // Send first control int
*vi = _readLoop(CTRL_HI_X | CTRL_LO_DFR, 255);
*vj = _readLoop(CTRL_HI_Y | CTRL_LO_DFR, 255);
// Turn off ADC by issuing one more read (throwaway)
// This needs to be done, because PD=0b11 (needed for MODE_DFR) will disable PENIRQ
platform_spi_send_recv(1, 8 , 0); // Maintain 16-clocks/conversion; _readLoop always ends after issuing a control int
platform_spi_send_recv(1, 8 , CTRL_HI_Y | CTRL_LO_SER);
transfer16(0); // Flush last read, just to be sure
platform_gpio_write(_cs_pin, PLATFORM_GPIO_HIGH);
// Clear interrupt status
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(pin_num[_irq_pin]));
// Enable interrupt again
ETS_GPIO_INTR_ENABLE();
}
// sets the calibration of the display
static void setCalibration (uint16_t vi1, uint16_t vj1, uint16_t vi2, uint16_t vj2) {
_cal_dx = _width - 2*CAL_MARGIN;
_cal_dy = _height - 2*CAL_MARGIN;
_cal_vi1 = (int32_t)vi1;
_cal_vj1 = (int32_t)vj1;
_cal_dvi = (int32_t)vi2 - vi1;
_cal_dvj = (int32_t)vj2 - vj1;
}
// returns the position on the screen by also applying the calibration
static void getPosition (uint16_t *x, uint16_t *y) {
if (isTouching() == 0) {
*x = *y = 0xffff;
return;
}
uint16_t vi, vj;
getRaw(&vi, &vj);
// Map to (un-rotated) display coordinates
*x = (uint16_t)(_cal_dx * (vj - _cal_vj1) / _cal_dvj + CAL_MARGIN);
if (*x > 0x7fff) *x = 0;
*y = (uint16_t)(_cal_dy * (vi - _cal_vi1) / _cal_dvi + CAL_MARGIN);
if (*y > 0x7fff) *y = 0;
}
// Lua: xpt2046.init(cspin, irqpin, height, width)
static int xpt2046_init( lua_State* L ) {
_cs_pin = luaL_checkinteger( L, 1 );
_irq_pin = luaL_checkinteger( L, 2 );
_height = luaL_checkinteger( L, 3 );
_width = luaL_checkinteger( L, 4 );
// set pins correct
platform_gpio_mode(_cs_pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
setCalibration(
/*vi1=*/((int32_t)CAL_MARGIN) * ADC_MAX / _width,
/*vj1=*/((int32_t)CAL_MARGIN) * ADC_MAX / _height,
/*vi2=*/((int32_t)_width - CAL_MARGIN) * ADC_MAX / _width,
/*vj2=*/((int32_t)_height - CAL_MARGIN) * ADC_MAX / _height
);
// assume spi was inited before with a clockDiv of >=16
// as higher spi clock speed produced inaccurate results
// do first powerdown
platform_gpio_write(_cs_pin, PLATFORM_GPIO_LOW);
// Issue a throw-away read, with power-down enabled (PD{1,0} == 0b00)
// Otherwise, ADC is disabled
platform_spi_send_recv(1, 8, CTRL_HI_Y | CTRL_LO_SER);
transfer16(0); // Flush, just to be sure
platform_gpio_write(_cs_pin, PLATFORM_GPIO_HIGH);
return 0;
}
// Lua: xpt2046.isTouched()
static int xpt2046_isTouched( lua_State* L ) {
lua_pushboolean( L, isTouching());
return 1;
}
// Lua: xpt2046.setCalibration(a,b,c,d)
static int xpt2046_setCalibration( lua_State* L ) {
int32_t a = luaL_checkinteger( L, 1 );
int32_t b = luaL_checkinteger( L, 2 );
int32_t c = luaL_checkinteger( L, 3 );
int32_t d = luaL_checkinteger( L, 4 );
setCalibration(a,b,c,d);
return 0;
}
// Lua: xpt2046.xpt2046_getRaw()
static int xpt2046_getRaw( lua_State* L ) {
uint16_t x, y;
getRaw(&x, &y);
lua_pushinteger( L, x);
lua_pushinteger( L, y);
return 2;
}
// Lua: xpt2046.xpt2046_getPosition()
static int xpt2046_getPosition( lua_State* L ) {
uint16_t x, y;
getPosition(&x, &y);
lua_pushinteger( L, x);
lua_pushinteger( L, y);
return 2;
}
// Lua: xpt2046.xpt2046_getPositionAvg()
static int xpt2046_getPositionAvg( lua_State* L ) {
// Run three times
uint16_t x1, y1, x2, y2, x3, y3;
getPosition(&x1, &y1);
getPosition(&x2, &y2);
getPosition(&x3, &y3);
// Average the two best results
int16_t x = besttwoavg(x1,x2,x3);
int16_t y = besttwoavg(y1,y2,y3);
lua_pushinteger( L, x);
lua_pushinteger( L, y);
return 2;
}
// Module function map
static const LUA_REG_TYPE xpt2046_map[] = {
{ LSTRKEY( "isTouched"), LFUNCVAL(xpt2046_isTouched) },
{ LSTRKEY( "getRaw" ), LFUNCVAL(xpt2046_getRaw) },
{ LSTRKEY( "getPosition"), LFUNCVAL(xpt2046_getPosition)},
{ LSTRKEY( "getPositionAvg"), LFUNCVAL(xpt2046_getPositionAvg)},
{ LSTRKEY( "setCalibration"), LFUNCVAL(xpt2046_setCalibration)},
{ LSTRKEY( "init" ), LFUNCVAL(xpt2046_init) },
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(XPT2046, "xpt2046", xpt2046_map, NULL);
......@@ -162,7 +162,7 @@ const char* mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length)
}
totlen += i;
if(i + 2 >= *length)
if(i + 2 > *length)
return NULL;
topiclen = buffer[i++] << 8;
topiclen |= buffer[i++];
......@@ -191,12 +191,12 @@ const char* mqtt_get_publish_data(uint8_t* buffer, uint16_t* length)
}
totlen += i;
if(i + 2 >= *length)
if(i + 2 > *length)
return NULL;
topiclen = buffer[i++] << 8;
topiclen |= buffer[i++];
if(i + topiclen >= *length){
if(i + topiclen > *length){
*length = 0;
return NULL;
}
......@@ -204,7 +204,7 @@ const char* mqtt_get_publish_data(uint8_t* buffer, uint16_t* length)
if(mqtt_get_qos(buffer) > 0)
{
if(i + 2 >= *length)
if(i + 2 > *length)
return NULL;
i += 2;
}
......@@ -231,6 +231,9 @@ uint16_t mqtt_get_id(uint8_t* buffer, uint16_t length)
int i;
int topiclen;
if(mqtt_get_qos(buffer) <= 0)
return 0;
for(i = 1; i < length; ++i)
{
if((buffer[i] & 0x80) == 0)
......@@ -240,23 +243,17 @@ uint16_t mqtt_get_id(uint8_t* buffer, uint16_t length)
}
}
if(i + 2 >= length)
if(i + 2 > length)
return 0;
topiclen = buffer[i++] << 8;
topiclen |= buffer[i++];
if(i + topiclen >= length)
if(i + topiclen > length)
return 0;
i += topiclen;
if(mqtt_get_qos(buffer) > 0)
{
if(i + 2 >= length)
return 0;
//i += 2;
} else {
return 0;
}
if(i + 2 > length)
return 0;
return (buffer[i] << 8) | buffer[i + 1];
}
......
......@@ -11,7 +11,7 @@
// Number of resources (0 if not available/not implemented)
#define NUM_GPIO GPIO_PIN_NUM
#define NUM_SPI 2
#define NUM_UART 1
#define NUM_UART 2
#define NUM_PWM GPIO_PIN_NUM
#define NUM_ADC 1
#define NUM_CAN 0
......@@ -32,11 +32,7 @@
#elif defined(FLASH_16M)
#define FLASH_SEC_NUM 0x1000
#elif defined(FLASH_AUTOSIZE)
#if defined(FLASH_SAFE_API)
#define FLASH_SEC_NUM (flash_safe_get_sec_num())
#else
#define FLASH_SEC_NUM (flash_rom_get_sec_num())
#endif // defined(FLASH_SAFE_API)
#else
#define FLASH_SEC_NUM 0x80
#endif
......@@ -55,15 +51,9 @@
// SpiFlashOpResult spi_flash_erase_sector(uint16 sec);
// SpiFlashOpResult spi_flash_write(uint32 des_addr, uint32 *src_addr, uint32 size);
// SpiFlashOpResult spi_flash_read(uint32 src_addr, uint32 *des_addr, uint32 size);
#if defined(FLASH_SAFE_API)
#define flash_write flash_safe_write
#define flash_erase flash_safe_erase_sector
#define flash_read flash_safe_read
#else
#define flash_write spi_flash_write
#define flash_erase spi_flash_erase_sector
#define flash_read spi_flash_read
#endif // defined(FLASH_SAFE_API)
#define CACHE_FLASH_CTRL_REG 0x3ff0000c
#define CACHE_FLASH_ACTIVE 0x00000100
......
......@@ -10,71 +10,33 @@
uint32_t flash_detect_size_byte(void)
{
// enable operations on whole physical flash, SDK might have restricted
// the flash size already
extern SpiFlashChip * flashchip;
uint32 orig_chip_size = flashchip->chip_size;
flashchip->chip_size = FLASH_SIZE_16MBYTE;
#define FLASH_BUFFER_SIZE_DETECT 32
uint32_t dummy_size = FLASH_SIZE_256KBYTE;
uint8_t data_orig[FLASH_BUFFER_SIZE_DETECT] ICACHE_STORE_ATTR = {0};
uint8_t data_new[FLASH_BUFFER_SIZE_DETECT] ICACHE_STORE_ATTR = {0};
if (SPI_FLASH_RESULT_OK == flash_safe_read(0, (uint32 *)data_orig, FLASH_BUFFER_SIZE_DETECT))
if (SPI_FLASH_RESULT_OK == flash_read(0, (uint32 *)data_orig, FLASH_BUFFER_SIZE_DETECT))
{
dummy_size = FLASH_SIZE_256KBYTE;
while ((dummy_size < FLASH_SIZE_16MBYTE) &&
(SPI_FLASH_RESULT_OK == flash_safe_read(dummy_size, (uint32 *)data_new, FLASH_BUFFER_SIZE_DETECT)) &&
(SPI_FLASH_RESULT_OK == flash_read(dummy_size, (uint32 *)data_new, FLASH_BUFFER_SIZE_DETECT)) &&
(0 != os_memcmp(data_orig, data_new, FLASH_BUFFER_SIZE_DETECT))
)
{
dummy_size *= 2;
}
};
return dummy_size;
#undef FLASH_BUFFER_SIZE_DETECT
}
uint32_t flash_safe_get_size_byte(void)
{
static uint32_t flash_size = 0;
if (flash_size == 0)
{
flash_size = flash_detect_size_byte();
#if !defined(FLASH_SAFE_API)
// clip maximum flash size to 4MByte if "SAFE API" is not used
if (flash_size > FLASH_SIZE_4MBYTE) {
flash_size = FLASH_SIZE_4MBYTE;
}
#endif
}
return flash_size;
}
uint16_t flash_safe_get_sec_num(void)
{
return (flash_safe_get_size_byte() / (SPI_FLASH_SEC_SIZE));
}
SpiFlashOpResult flash_safe_read(uint32 src_addr, uint32 *des_addr, uint32 size)
{
SpiFlashOpResult result = SPI_FLASH_RESULT_ERR;
FLASH_SAFEMODE_ENTER();
result = spi_flash_read(src_addr, (uint32 *) des_addr, size);
FLASH_SAFEMODE_LEAVE();
return result;
}
// revert temporary setting
flashchip->chip_size = orig_chip_size;
SpiFlashOpResult flash_safe_write(uint32 des_addr, uint32 *src_addr, uint32 size)
{
SpiFlashOpResult result = SPI_FLASH_RESULT_ERR;
FLASH_SAFEMODE_ENTER();
result = spi_flash_write(des_addr, src_addr, size);
FLASH_SAFEMODE_LEAVE();
return result;
}
SpiFlashOpResult flash_safe_erase_sector(uint16 sec)
{
SpiFlashOpResult result = SPI_FLASH_RESULT_ERR;
FLASH_SAFEMODE_ENTER();
result = spi_flash_erase_sector(sec);
FLASH_SAFEMODE_LEAVE();
return result;
return dummy_size;
#undef FLASH_BUFFER_SIZE_DETECT
}
SPIFlashInfo flash_rom_getinfo(void)
......
......@@ -20,16 +20,6 @@
#define FLASH_SIZE_8MBYTE (FLASH_SIZE_64MBIT / 8)
#define FLASH_SIZE_16MBYTE (FLASH_SIZE_128MBIT/ 8)
#define FLASH_SAFEMODE_ENTER() \
do { \
extern SpiFlashChip * flashchip; \
flashchip->chip_size = FLASH_SIZE_16MBYTE
#define FLASH_SAFEMODE_LEAVE() \
flashchip->chip_size = flash_rom_get_size_byte(); \
} while(0)
/******************************************************************************
* ROM Function definition
* Note: It is unsafe to use ROM function, but it may efficient.
......@@ -89,15 +79,10 @@ typedef struct
uint32_t segment_size;
} ICACHE_STORE_TYPEDEF_ATTR SPIFlashInfo;
uint32_t flash_detect_size_byte(void);
uint32_t flash_safe_get_size_byte(void);
uint16_t flash_safe_get_sec_num(void);
SpiFlashOpResult flash_safe_read(uint32 src_addr, uint32 *des_addr, uint32 size);
SpiFlashOpResult flash_safe_write(uint32 des_addr, uint32 *src_addr, uint32 size);
SpiFlashOpResult flash_safe_erase_sector(uint16 sec);
SPIFlashInfo flash_rom_getinfo(void);
uint8_t flash_rom_get_size_type(void);
uint32_t flash_rom_get_size_byte(void);
uint32_t flash_detect_size_byte(void);
bool flash_rom_set_size_type(uint8_t);
bool flash_rom_set_size_byte(uint32_t);
uint16_t flash_rom_get_sec_num(void);
......
......@@ -755,6 +755,8 @@ int platform_i2c_recv_byte( unsigned id, int ack ){
uint32_t platform_spi_setup( uint8_t id, int mode, unsigned cpol, unsigned cpha, uint32_t clock_div )
{
spi_master_init( id, cpol, cpha, clock_div );
// all platform functions assume LSB order for MOSI & MISO buffer
spi_mast_byte_order( id, SPI_ORDER_LSB );
return 1;
}
......@@ -779,8 +781,6 @@ spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type
int platform_spi_blkwrite( uint8_t id, size_t len, const uint8_t *data )
{
spi_mast_byte_order( id, SPI_ORDER_LSB );
while (len > 0) {
size_t chunk_len = len > 64 ? 64 : len;
......@@ -791,8 +791,6 @@ int platform_spi_blkwrite( uint8_t id, size_t len, const uint8_t *data )
len -= chunk_len;
}
spi_mast_byte_order( id, SPI_ORDER_MSB );
return PLATFORM_OK;
}
......@@ -802,8 +800,6 @@ int platform_spi_blkread( uint8_t id, size_t len, uint8_t *data )
os_memset( (void *)mosi_idle, 0xff, len > 64 ? 64 : len );
spi_mast_byte_order( id, SPI_ORDER_LSB );
while (len > 0 ) {
size_t chunk_len = len > 64 ? 64 : len;
......@@ -815,29 +811,9 @@ int platform_spi_blkread( uint8_t id, size_t len, uint8_t *data )
len -= chunk_len;
}
spi_mast_byte_order( id, SPI_ORDER_MSB );
return PLATFORM_OK;
}
int platform_spi_set_mosi( uint8_t id, uint16_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, uint16_t offset, uint8_t bitlen )
{
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 )
......@@ -940,3 +916,8 @@ uint32_t platform_flash_mapped2phys (uint32_t mapped_addr)
uint32_t meg = (b1 << 1) | b0;
return mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS + meg * 0x100000;
}
void* platform_print_deprecation_note( const char *msg, const char *time_frame)
{
c_printf( "Warning, deprecated API! %s. It will be removed %s. See documentation for details.\n", msg, time_frame );
}
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