188 lines
4.8 KiB
C
188 lines
4.8 KiB
C
// Module for interfacing with serial
|
|
|
|
#include "module.h"
|
|
#include "lauxlib.h"
|
|
#include "platform.h"
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include "rom.h"
|
|
#include "driver/input.h"
|
|
|
|
static int uart_receive_rf = LUA_NOREF;
|
|
|
|
void uart_on_data_cb(const char *buf, size_t len){
|
|
lua_State *L = lua_getstate();
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, uart_receive_rf);
|
|
lua_pushlstring(L, buf, len);
|
|
luaL_pcallx(L, 1, 0);
|
|
}
|
|
|
|
// Lua: uart.on("method", [number/char], function, [run_input])
|
|
static int l_uart_on( lua_State* L )
|
|
{
|
|
size_t el;
|
|
int stack = 2, data_len = -1;
|
|
char end_char = 0;
|
|
const char *method = lua_tostring( L, 1);
|
|
bool run_input = true;
|
|
luaL_argcheck(L, method && !strcmp(method, "data"), 1, "method not supported");
|
|
|
|
if (lua_type( L, stack ) == LUA_TNUMBER) {
|
|
data_len = luaL_checkinteger( L, stack );
|
|
luaL_argcheck(L, data_len >= 0 && data_len < LUA_MAXINPUT, stack, "wrong arg range");
|
|
stack++;
|
|
} else if (lua_isstring(L, stack)) {
|
|
const char *end = luaL_checklstring( L, stack, &el );
|
|
end_char = end[0];
|
|
stack++;
|
|
if(el!=1) {
|
|
return luaL_error( L, "wrong arg range" );
|
|
}
|
|
}
|
|
|
|
if (lua_isfunction(L, stack)) {
|
|
if (lua_isnumber(L, stack+1) && lua_tointeger(L, stack+1) == 0) {
|
|
run_input = false;
|
|
}
|
|
lua_pushvalue(L, stack);
|
|
luaL_unref(L, LUA_REGISTRYINDEX, uart_receive_rf);
|
|
uart_receive_rf = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else {
|
|
luaL_unref(L, LUA_REGISTRYINDEX, uart_receive_rf);
|
|
uart_receive_rf = LUA_NOREF;
|
|
}
|
|
|
|
if (uart_receive_rf == LUA_NOREF) {
|
|
input_setup_receive(NULL, 0, 0, 1);
|
|
} else
|
|
input_setup_receive(uart_on_data_cb, data_len, end_char, run_input);
|
|
return 0;
|
|
}
|
|
|
|
bool uart0_echo = true;
|
|
// Lua: actualbaud = setup( id, baud, databits, parity, stopbits, echo )
|
|
static int l_uart_setup( lua_State* L )
|
|
{
|
|
uint32_t id, databits, parity, stopbits;
|
|
uint32_t baud, res;
|
|
|
|
id = luaL_checkinteger( L, 1 );
|
|
MOD_CHECK_ID( uart, id );
|
|
|
|
baud = luaL_checkinteger( L, 2 );
|
|
databits = luaL_checkinteger( L, 3 );
|
|
parity = luaL_checkinteger( L, 4 );
|
|
stopbits = luaL_checkinteger( L, 5 );
|
|
if (lua_isnumber(L,6)) {
|
|
input_setecho(lua_tointeger(L,6) ? true : false);
|
|
}
|
|
|
|
res = platform_uart_setup( id, baud, databits, parity, stopbits );
|
|
lua_pushinteger( L, res );
|
|
return 1;
|
|
}
|
|
|
|
// uart.getconfig(id)
|
|
static int l_uart_getconfig( lua_State* L )
|
|
{
|
|
uint32_t id, databits, parity, stopbits;
|
|
uint32_t baud;
|
|
|
|
id = luaL_checkinteger( L, 1 );
|
|
MOD_CHECK_ID( uart, id );
|
|
|
|
platform_uart_get_config(id, &baud, &databits, &parity, &stopbits);
|
|
|
|
lua_pushinteger(L, baud);
|
|
lua_pushinteger(L, databits);
|
|
lua_pushinteger(L, parity);
|
|
lua_pushinteger(L, stopbits);
|
|
return 4;
|
|
}
|
|
|
|
// Lua: alt( set )
|
|
static int l_uart_alt( lua_State* L )
|
|
{
|
|
unsigned set;
|
|
|
|
set = luaL_checkinteger( L, 1 );
|
|
|
|
platform_uart_alt( set );
|
|
return 0;
|
|
}
|
|
|
|
// Lua: write( id, string1, [string2], ..., [stringn] )
|
|
static int l_uart_write( lua_State* L )
|
|
{
|
|
int id;
|
|
const char* buf;
|
|
size_t len, i;
|
|
int total = lua_gettop( L ), s;
|
|
|
|
id = luaL_checkinteger( L, 1 );
|
|
MOD_CHECK_ID( uart, id );
|
|
for( s = 2; s <= total; s ++ )
|
|
{
|
|
if( lua_type( L, s ) == LUA_TNUMBER )
|
|
{
|
|
len = lua_tointeger( L, s );
|
|
if( len > 255 )
|
|
return luaL_error( L, "invalid number" );
|
|
platform_uart_send( id, ( u8 )len );
|
|
}
|
|
else
|
|
{
|
|
luaL_checktype( L, s, LUA_TSTRING );
|
|
buf = lua_tolstring( L, s, &len );
|
|
for( i = 0; i < len; i ++ )
|
|
platform_uart_send( id, buf[ i ] );
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#define DIR_RX 0
|
|
#define DIR_TX 1
|
|
|
|
static int l_uart_fifodepth( lua_State* L )
|
|
{
|
|
int id = luaL_optinteger( L, 1, 0 );
|
|
if ((id != 0) && (id != 1))
|
|
return luaL_argerror(L, 1, "Bad UART id; must be 0 or 1");
|
|
|
|
int dir = luaL_optinteger( L, 2, 0 );
|
|
if ((dir != DIR_RX) && (dir != DIR_TX))
|
|
return luaL_argerror(L, 2, "Bad direction; must be DIR_RX or DIR_TX");
|
|
|
|
int reg = READ_PERI_REG(UART_STATUS(id));
|
|
int rsh = reg >> ((dir == DIR_RX) ? UART_RXFIFO_CNT_S : UART_TXFIFO_CNT_S);
|
|
int rm = rsh & ((dir == DIR_RX) ? UART_RXFIFO_CNT : UART_TXFIFO_CNT );
|
|
|
|
lua_pushinteger(L, rm);
|
|
return 1;
|
|
}
|
|
|
|
// Module function map
|
|
LROT_BEGIN(uart, NULL, 0)
|
|
LROT_FUNCENTRY( setup, l_uart_setup )
|
|
LROT_FUNCENTRY( getconfig, l_uart_getconfig )
|
|
LROT_FUNCENTRY( write, l_uart_write )
|
|
LROT_FUNCENTRY( on, l_uart_on )
|
|
LROT_FUNCENTRY( alt, l_uart_alt )
|
|
LROT_FUNCENTRY( fifodepth, l_uart_fifodepth )
|
|
|
|
LROT_NUMENTRY( STOPBITS_1, PLATFORM_UART_STOPBITS_1 )
|
|
LROT_NUMENTRY( STOPBITS_1_5, PLATFORM_UART_STOPBITS_1_5 )
|
|
LROT_NUMENTRY( STOPBITS_2, PLATFORM_UART_STOPBITS_2 )
|
|
LROT_NUMENTRY( PARITY_NONE, PLATFORM_UART_PARITY_NONE )
|
|
LROT_NUMENTRY( PARITY_EVEN, PLATFORM_UART_PARITY_EVEN )
|
|
LROT_NUMENTRY( PARITY_ODD, PLATFORM_UART_PARITY_ODD )
|
|
|
|
LROT_NUMENTRY( DIR_RX, DIR_RX )
|
|
LROT_NUMENTRY( DIR_TX, DIR_TX )
|
|
LROT_END(uart, NULL, 0)
|
|
|
|
|
|
NODEMCU_MODULE(UART, "uart", uart, NULL);
|